vcvycy 发表于 2017-5-11 22:33

XX通自动拨号、瞬间挂断实现

本帖最后由 ubuntu 于 2019-6-6 18:36 编辑

用于整人用的,立刻挂断时阿里通不收费。by cjf@xmu
流程:写程序向客户端发送消息,实现拨号功能;修改客户端,方便我们的程序获知对方正在响铃,然后立刻挂断。
一、文件脱壳      
       客户端加了个ASPACK 2.12的壳
      (1)先清除ASLR标记(ASLR用于随机程序载入基地址,最好先清除掉)
      (2)直接使用脱壳机脱壳。
二、自动拨号功能
      原理:自动拨号,很自然的思路就是把子窗体控件找出来,然后从外部发送消息过来,实现按钮点击。
      (1)原先的思路是使用spy++把子控件都找出来,但是分析发现阿里通使用了第三方UI库(SOUI),SPY++什么都找不到。

   (2)那就直接调试——产生按键的消息找出来。
             直接拉入OD,直接在API DispatchMessage()中设置消息条件断点,拦截单击释放事件。
             拦截条件为:[+4]==WM_LBUTTONUP,即左键单击释放事件。很快断下来了。可以发现这个UI库是通过事件发生时的坐标轴(即消息结构体的LPARAM)来辨别是哪个按键被单击的,所以找到所有的数字按键的lparam参数,直接记录下来,之后只要发送WM_LBUTTONUP消息给主窗口,填充下lparam参数就行了,宏定义如下:
[*]//找到的lparam参数如下
#define BTN_1 0x010d01d1
#define BTN_2 0x010d0221
#define BTN_3 0x010d0301
#define BTN_4 0x014d01d1
#define BTN_5 0x014d0221
#define BTN_6 0x014d0301
#define BTN_7 0x018d01d1
#define BTN_8 0x018d0267
#define BTN_9 0x018d0301
#define BTN_0 0x01bd0267
#define BTN_BACKSPACE 0x009c02f1             //回退按钮
#define BTN_CALL 0x02320260                     //拨打按钮
#define BTN_STOP 0x01db02c1                     //挂断按钮
#define BTN_DIAL_PAGE 0x00AB0024             //播放页面

三、瞬间挂断实现
      瞬间挂断功能比较复杂。当响铃时,可以看到的变化如下:(即中间的文字由"正在呼叫..." 变成 "正在响铃...")      
         
一个想法是抓包分析,找到告诉客户端对面正在响铃的包,但是很快放弃了。这么多包,可能还加密了,很难分析。
             另一个想法就是,找到SOUI这个第三方UI设置TEXT文本的API,虽然对这个UI库一点都不懂,但很容易猜到API的名字应该带有text。其dll文件为soui.dll,于是在od查找此模块所有api,找到以下7个候选API:
[*]5440161B   .text      输出         SOUI::CSimpleWnd::SetWindowTextW
[*]543CDC62   .text      输出         SOUI::SComboBase::SetWindowTextW
[*]543E6759   .text      输出         SOUI::SRichEdit::SetWindowTextW
[*]543FC984   .text      输出         SOUI::SWindow::SetWindowTextW
[*]
[*]543CB871   .text      输出         SOUI::SLink::DrawTextW
[*]543CB76A   .text      输出         SOUI::SStatic::DrawTextW
[*]543FA10F   .text      输出         SOUI::SWindow::DrawTextW

   全部设置断点,然后拨打号码测试。很快就发现SWindow::SetWindowTextW 断点下"正在响铃..."参数,成功定位到关键API。
   现在的问题就是怎么告诉我们程序,已经开始响铃了。   
   想法一:修改API,如果参数为"正在响铃...",就告诉我们程序开始响铃了。(但是不知道修改DLL怎么保存)   
   想法二:查看调用这个API的主模块语句。很幸运地发现,调用次API的那个语句只用来传递"正在响铃...",也就是不和其他语句混用。所以直接修改这里就行了。   
    原先的汇编语句为:(我这边主模块基地址为0x008c0000,以下语句地址为0x008d80e4)

[*]mov edx,dword ptr ds[ebx+0x30
push eax                                     //字符串"正在响铃..."
call   edx                                     //调用SWindow::SetWindowText

   修改后为:
[*]//地址008d80e4:(6个字节替换 )
jmp 0x00af2610
nop
地址:00af2610(原先为0填充区域)
pushad
mov edx,dword ptr ds:
push eax
inc    //注意:此处我们设置一个叠加器表示是否已经响铃了,我们程序再通过ReadProcessMemory定时读取这个值
calledx
popad
jmp 008d80ea //继续原来的流程

这样程序就改好了.
   注意:上面我们使用0填充区域的4个字节,设置累加器,用于判断响铃是否发生(初始值我改为4,一次响铃时,此API执行两次,而变成6,至于为什么是不是一次我也没去分析,但就是两次,表示正在响铃),我们程序定时读取这个值(ReadProcessMemory)后,等到值为6时,则响铃成功,然后再将其置4。
四、外部程序
       登录上述修改后的客户端,执行这个C++程序,传入电话号码,就会自动拨号了,响铃瞬间自动挂断)
      (使用修改后的阿里通客户端,才可以实现自动挂断功能。超过1MB好像没办法上传)
[*]#include<windows.h>
#include<stdio.h>
#define CNT_ADDR 0x00af260c
#define BTN_1 0x010d01d1
#define BTN_2 0x010d0221
#define BTN_3 0x010d0301
#define BTN_4 0x014d01d1
#define BTN_5 0x014d0221
#define BTN_6 0x014d0301
#define BTN_7 0x018d01d1
#define BTN_8 0x018d0267
#define BTN_9 0x018d0301
#define BTN_0 0x01bd0267
#define BTN_BACKSPACE 0x009c02f1
#define BTN_CALL 0x02320260
#define BTN_STOP 0x01db02c1
#define BTN_DIAL_PAGE 0x00AB0024
static int btn_pos={BTN_0,BTN_1,BTN_2,BTN_3,BTN_4,BTN_5,BTN_6,BTN_7,BTN_8,BTN_9};
int read_count(HWND hwnd){ //读取阿里通客户端,我们设置的累加器。其初值为4。当其为6时(因为SWindow::SetWindowTest会执行两次,我也不知道为什么两次),表示正在响铃
int ret;
DWORD pid;
GetWindowThreadProcessId(hwnd,&pid);
HANDLE hProcess=OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_OPERATION | PROCESS_VM_READ | PROCESS_VM_WRITE, 0, pid);
if (hProcess==0){printf("OpenProcess失败...\n");exit(-1);}
DWORD bytes_read=0;
bool bIsOk=ReadProcessMemory(hProcess,(LPCVOID)CNT_ADDR,(LPVOID)&ret,4,&bytes_read);
if (!bIsOk || bytes_read!=4){
      printf("进程读取失败...ok=%d bytes_read=%d\n",bIsOk,bytes_read);
      exit(-1);
}
CloseHandle(hProcess);
//printf("ret=%d\n",ret);
return ret;
}
int reset_count(HWND hwnd){      //将累加器重置为4(随便设置的一个数字)
DWORD pid;
GetWindowThreadProcessId(hwnd,&pid);
HANDLE hProcess=OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_OPERATION | PROCESS_VM_READ | PROCESS_VM_WRITE, 0, pid);
if (hProcess==0){printf("OpenProcess失败...\n");exit(-1);}
char data;data=0x4;data=0x0;data=0;data=0;
//int *k=(int*)data;
//printf("k=%x\n",*k);
DWORD bytes_write;
bool bIsOk=WriteProcessMemory(hProcess,(LPVOID)CNT_ADDR,data,4,&bytes_write);
if (!bIsOk || bytes_write!=4){printf("进程写入失败...\n");exit(-1);}
if (read_count(hwnd)!=4){
    printf("unknown error!\n");
}
CloseHandle(hProcess);
return 0;
}
int waitForRing(HWND hwnd){   //等待"正在响铃..."出现
if (hwnd==0){printf("hwnd=0\n");exit(-1);}
    while (true){
      if (read_count(hwnd)==6){
      //printf("start ringing...!\n");
      reset_count(hwnd);
      break;
      }
      Sleep(100);
    }
return 0;
}
class ALI{
public:
HWND hwnd;
int click(int pos){
    if (hwnd)SendMessage(hwnd,WM_LBUTTONUP,0,pos);
    else exit(-1);
    return 0;
}
int clear(){                              //清空电话栏
    for (int i=0;i<30;i++) {
      if (click(BTN_BACKSPACE)==-1)return -1;
    }
    return 0;
}
int call(char *phone){                     //发送消息自动按键,并拨号
    hwnd=FindWindow(0,"阿里通");
    //printf("hwnd=%x\n",hwnd);
    click(BTN_DIAL_PAGE);
    //exit(-2);
    clear();
    int len=strlen(phone);
    if (len>11 || len<8)return -1;
    for (int i=0;i<len;i++){
      click(btn_pos-'0']);
    }
    click(BTN_CALL);
    //printf("waitForRing...\n");
    waitForRing(hwnd);
    click(BTN_STOP);
    Sleep(5000);
    return 0;
}
};
int main(int argc,char** argv){
ALI ali;
if (argc<2) return -1;
ali.call(argv);
return 0;
}


下载地址:http://pan.baidu.com/s/1dESFyVn
用法,ali_final.exe替换掉原来客户端。
然后打开cmd,命令call.exe 139xxxxxxxx ,就会自动打了。
注:想要循环的话,把c++ 中main函数ali.call(argv)改成循环的, 重新编译下就好了,一小时一个号码貌似最多打10次,否则被封。被封后,过一段时间又可以用了。

Valkyrie-Madoka 发表于 2017-5-12 21:48

本帖最后由 Valkyrie-Madoka 于 2017-5-12 22:43 编辑

确实可以用,使用方法我说的明确些吧。解压出来的ali_Final.exe重名命名成客户端里的Alicall.exe然后把2个文件都复制进客户端。命令提示符是要根据你的客户端路径来完成的比如我的是D盘正确的使用CMD命令就是E:\Alicall\call.exe 139XXXXXXXX,这样就可以使用了。发现个问题,就是对方秒接电话还是会扣费的......

vcvycy 发表于 2017-5-13 12:33

本帖最后由 vcvycy 于 2017-5-13 12:48 编辑

Valkyrie-Madoka 发表于 2017-5-12 21:48
确实可以用,使用方法我说的明确些吧。解压出来的ali_Final.exe重名命名成客户端里的Alicall.exe然后把2个 ...
确实会有秒接的情况,因为网络延迟,客户端告诉我们对面响铃的时候,对方可能已经在响铃1~2秒,这个应该是没办法处理的。

vcvycy 发表于 2017-5-11 22:34

格式全乱了,怎么重新编辑= =

wuaipojp9527 发表于 2017-5-11 22:36

........赞一下

万物皆为灰烬 发表于 2017-5-11 22:36

支持一下

JUNGLE_CN 发表于 2017-5-11 22:41

感觉这样的话就实现了电话骚扰的功能

扮演狠角色 发表于 2017-5-11 22:42

。。。良心发现!!!

iso9001 发表于 2017-5-11 22:50

真坏......

leiweihua 发表于 2017-5-11 22:52

没啥用,呼叫次数多了就封号了。同一个IP登录多了也封号

snowwolf198 发表于 2017-5-11 22:54

哈哈哈,这样以后就可以随便拨打骚扰电话了哈!!!这个软件有点{:1_925:}

www854542900 发表于 2017-5-11 22:59

楼主真强大
页: [1] 2 3 4 5 6 7 8 9 10
查看完整版本: XX通自动拨号、瞬间挂断实现