用于整人用的,立刻掛斷時(shí)阿里通不收費(fèi)。
流程:寫(xiě)程序向客戶(hù)端發(fā)送消息,實(shí)現(xiàn)撥號(hào)功能;修改客戶(hù)端,方便我們的程序獲知對(duì)方正在響鈴,然后立刻掛斷。
一、文件脫殼 客戶(hù)端加了個(gè)ASPACK 2.12的殼
(1)先清除ASLR標(biāo)記(ASLR用于隨機(jī)程序載入基地址,最好先清除掉)
(2)直接使用脫殼機(jī)脫殼。
二、自動(dòng)撥號(hào)功能
原理:自動(dòng)撥號(hào),很自然的思路就是把子窗體控件找出來(lái),然后從外部發(fā)送消息過(guò)來(lái),實(shí)現(xiàn)按鈕點(diǎn)擊。
(1)原先的思路是使用spy++把子控件都找出來(lái),但是分析發(fā)現(xiàn)阿里通使用了第三方UI庫(kù)(SOUI),SPY++什么都找不到。
(2)那就直接調(diào)試——產(chǎn)生按鍵的消息找出來(lái)。
直接拉入OD,直接在A(yíng)PI DispatchMessage()中設(shè)置消息條件斷點(diǎn),攔截單擊釋放事件。
攔截條件為:[[esp+4]+4]==WM_LBUTTONUP,即左鍵單擊釋放事件。很快斷下來(lái)了。可以發(fā)現(xiàn)這個(gè)UI庫(kù)是通過(guò)事件
發(fā)生時(shí)的坐標(biāo)軸(即消息結(jié)構(gòu)體的LPARAM)來(lái)辨別是哪個(gè)按鍵被單擊的,所以找到所有的數(shù)字按鍵的lparam參數(shù),直接記錄
下來(lái),之后只要發(fā)送WM_LBUTTONUP消息給主窗口,填充下lparam參數(shù)就行了,宏定義如下:
- //找到的lparam參數(shù)如下
- #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 //播放頁(yè)面
三、瞬間掛斷實(shí)現(xiàn)
瞬間掛斷功能比較復(fù)雜。當(dāng)響鈴時(shí),可以看到的變化如下:(即中間的文字由"正在呼叫..." 變成 "正在響鈴...")
一個(gè)想法是抓包分析,找到告訴客戶(hù)端對(duì)面正在響鈴的包,但是很快放棄了。這么多包,可能還加密了,很難分析。
另一個(gè)想法就是,找到SOUI這個(gè)第三方UI設(shè)置TEXT文本的API,雖然對(duì)這個(gè)UI庫(kù)一點(diǎn)都不懂,但很容易猜到API的名
字應(yīng)該帶有text。其dll文件為soui.dll,于是在od查找此模塊所有api,找到以下7個(gè)候選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
全部設(shè)置斷點(diǎn),然后撥打號(hào)碼測(cè)試。很快就發(fā)現(xiàn)SWindow::SetWindowTextW 斷點(diǎn)下"正在響鈴..."參數(shù)。
定位到關(guān)鍵API。現(xiàn)在的問(wèn)題就是怎么告訴我們程序,已經(jīng)開(kāi)始響鈴了。 想法一:修改API,如果參數(shù)為"正在響鈴...",
就告訴我們程序開(kāi)始響鈴了。(但是不知道修改DLL怎么保存) 想法二:查看調(diào)用這個(gè)API的主模塊語(yǔ)句。很幸運(yùn)地發(fā)現(xiàn),
調(diào)用次API的那個(gè)語(yǔ)句只用來(lái)傳遞"正在響鈴...",也就是不和其他語(yǔ)句混用。所以直接修改這里就行了。 原先的匯編語(yǔ)句為:
(我這邊主模塊基地址為0x008c0000,以下語(yǔ)句地址為0x008d80e4)
- mov edx,dword ptr ds[ebx+0x30
- push eax //字符串"正在響鈴..."
- call edx //調(diào)用SWindow::SetWindowText
修改后為:
- 地址008d80e4:(6個(gè)字節(jié)替換 )
- jmp 0x00af2610
- nop
-
- 地址:00af2610(原先為0填充區(qū)域)
- pushad
- mov edx,dword ptr ds:[ebx+0x30
- push eax
- inc [0xaf260c //注意:此處我們?cè)O(shè)置一個(gè)疊加器表示是否已經(jīng)響鈴了,我們程序再通過(guò)ReadProcessMemory定時(shí)讀取這個(gè)值
- call edx
- popad
- jmp 008d80ea //繼續(xù)原來(lái)的流程
這樣程序就改好了.注意:上面我們使用0填充區(qū)域的4個(gè)字節(jié),設(shè)置累加器,用于判斷響鈴是否發(fā)生(初始值為4,期間API執(zhí)行兩次變成6,
為什么是不是一次我也不知道,但就是兩次,表示正在響鈴),我們程序讀取這個(gè)值(ReadProcessMemory)后,會(huì)再將其置4。
四、外部程序
登錄上述修改后的客戶(hù)端,執(zhí)行這個(gè)C++程序,傳入電話(huà)號(hào)碼,就會(huì)自動(dòng)撥號(hào)了,響鈴瞬間自動(dòng)掛斷)
(使用修改后的阿里通客戶(hù)端,才可以實(shí)現(xiàn)自動(dòng)掛斷功能。超過(guò)1MB好像沒(méi)辦法上傳)
- #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[12]={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){ //讀取阿里通客戶(hù)端,我們?cè)O(shè)置的累加器。其初值為4。當(dāng)其為6時(shí)(因?yàn)镾Window::SetWindowTest會(huì)執(zhí)行兩次,
- 我也不知道為什么兩次),表示正在響鈴
- 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("進(jìn)程讀取失敗...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){ //將累加器重置為0
- 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[4];data[0]=0x4;data[1]=0x0;data[2]=0;data[3]=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("進(jìn)程寫(xiě)入失敗...\n");exit(-1);}
- if (read_count(hwnd)!=4){
- printf("unknown error!\n");
- }
- CloseHandle(hProcess);
- return 0;
- }
- int waitForRing(HWND hwnd){ //等待"正在響鈴..."出現(xiàn)
- 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(){ //清空電話(huà)欄
- for (int i=0;i<30;i++) {
- if (click(BTN_BACKSPACE)==-1)return -1;
- }
- return 0;
- }
- int call(char *phone){ //發(fā)送消息自動(dòng)按鍵,并撥號(hào)
- 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[phone[i]-'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[1]);
- return 0;
- }
-
|