珊瑚虫外挂原理分析

珊瑚虫外挂原理分析【原创】
发送 MSN 消息给 runjin runjin 当前离线 添加 runjin 的声望 反映此帖
标 题: 珊瑚虫外挂原理分析【原创】
作 者: runjin
时 间: 2005-03-20,21:44
链 接: http://bbs.pediy.com/showthread.php?t=12240

珊瑚虫外挂原理分析

作者: RunJin
     [email protected]

分析工具: softice , OD
我的操作系统: win 2000 sp4 , win 98
分析对象: QQ2005贺岁版 珊瑚虫外挂

为了方便分析,我先把CoralQQ.dll和coralqq.exe先脱壳,这两个文件加的
都是超弱壳,脱壳过程不在这里多说.

    由于win nt 平台和win9x 的差异,珊瑚虫外挂因系统的不同而分开两种
工作原理.
    我们都知道,珊瑚外挂是给QQ的主程序QQ.exe外挂了一个Coralqq.dll,
而完成这个工作的就是coralqq.exe .要加载一个dll文件必须是qq.exe自己
的某个线程执行LoadLibraryA,并且以coralqq.dll为参数,但qq.exe本来根本
没有这样的一段代码,怎么办?答案很简单,既然它没有,那就让我们帮它加上去,
coralqq.exe就是利用WriteProcessMemory帮QQ.exe加上了这样一段代码,并且
改变程序流程,让qq.exe先加载coralqq.dll再跳到原来的oep执行.
    想了一下,比较合理的方法有:
1.在nt内核的系统上,利用远程线程的方法,首先用CreateProcess创建QQ.exe
的进程,同时创建了主线程,再用VirtualAllocEx在qq.exe中申请一块内存,然后把
我们的代码写进去,最后用CreateRemoteThread在qq的进程中创建另外一个
线程,其开始执行的地方正是我们自己加入的代码首地址.

2.先用CreateProcess创建QQ进程和主线程,在QQ的内存空间中找个合理
的地方写入我们的代码,然后修改某个地方(例如OEP)使QQ先跳去执行我们
写入的代码,加载coralqq.dll,修复原来改过的oep,然后跳回oep让程序正常执行.


下面就让我们分析一下珊瑚虫的外挂是怎样做到的,首先分析nt平台上的
运行过程.

用OD载入脱壳后的coralqq.exe,停在下面:
00418E2C >/$  55                          push  ebp
00418E2D  |.  8BEC                        mov  ebp, esp
00418E2F  |.  83C4 F0                     add  esp,-10
00418E32  |.  B8 648D4100                 mov  eax,CoralQQ.00418D64
00418E37  |.  E8 A4BAFEFF                 call CoralQQ.004048E0
00418E3C  |.  A1 F49D4100                 mov  eax, dword  ptr  ds:[419DF4]
00418E41  |.  33D2                        xor  edx, edx
00418E43  |.  E8 30F4FFFF                 call CoralQQ.00418278
00418E48  |.  A1 F49D4100                 mov  eax, dword  ptr  ds:[419DF4]
00418E4D  |.  8B00                        mov  eax, dword  ptr  ds:[ eax]
00418E4F  |.  83C0 18                     add  eax,18
00418E52  |.  E8 F9C6FEFF                 call CoralQQ.00405550
00418E57  |.  E8 08A9FEFF                 call CoralQQ.00403764

然后下断点:  bp CreateRemoteThread ,然后运行,结果发现,OD根本没有断下,
证明珊瑚虫的外挂没有使用远程线程的方法,难道它是用了第二种方法?我们再验证一下:
首先在OD中 bp CreateProcess,断下,反回后,用winhex打开QQ.exe的内存,把QQ.exe
的OEP处改为CC,接着在softice中 bpint 3 ,在OD中按F9运行,接着就是中断在softice
中,把oep(464b58)处还原,在再softice下 bpm 464b58 ,然后结束程序,再运行coralqq.exe
发现自始至终那个bpm断点还是没有断下,证明珊瑚虫外挂在2000下也没有修改QQ.exe
的oep来改变程序流程,晕.没办法,只好在OD中下WriteProcessMemory断点,看看它究竟
修改了哪里.

00231012    57                push  edi
00231013    8B4424 24         mov  eax, dword  ptr  ss:[ esp+24]
00231017    A3 70302300       mov  dword  ptr  ds:[233070], eax
0023101C    8305 70302300 04  add  dword  ptr  ds:[233070],4
00231023    E8 5C000000       call <jmp.&kernel32.CreateProcessA> ;创建QQ的进程
上面创建后的QQ主线程是暂停的,不会马上执行,在win9x下也是这样.

第一次中断时堆栈显示:
0012EBDC   0040C75C  / CALL 到 WriteProcessMemory 来自 CoralQQ.0040C756
0012EBE0   00000018  |hProcess = 00000018
0012EBE4   5F000000  |Address = 5F000000
0012EBE8   00CC0F44  |Buffer = 00CC0F44
0012EBEC   000000D2  |BytesToWrite = D2 (210.)
0012EBF0   0012EC68  \pBytesWritten = 0012EC68

第二次:
0012EC70   00416231  / CALL 到 WriteProcessMemory 来自 CoralQQ.0041622C
0012EC74   00000018  |hProcess = 00000018
0012EC78   5F010000  |Address = 5F010000
0012EC7C   0012EE9F  |Buffer = 0012EE9F
0012EC80   00000025  |BytesToWrite = 25 (37.)
0012EC84   0012EFD0  \pBytesWritten = 0012EFD0

第三次:
0012EC70   004162CB  / CALL 到 WriteProcessMemory 来自 CoralQQ.004162C6
0012EC74   00000018  |hProcess = 00000018
0012EC78   77F84BC0  |Address = 77F84BC0
0012EC7C   0012EFC3  |Buffer = 0012EFC3
0012EC80   00000005  |BytesToWrite = 5
0012EC84   0012EFD0  \pBytesWritten = 0012EFD0

第四次:
0012EC70   0041632B  / CALL 到 WriteProcessMemory 来自 CoralQQ.00416326
0012EC74   00000018  |hProcess = 00000018
0012EC78   5F010025  |Address = 5F010025
0012EC7C   0012EC96  |Buffer = 0012EC96
0012EC80   00000208  |BytesToWrite = 208 (520.)
0012EC84   0012EFD0  \pBytesWritten = 0012EFD0

第五次:
0012EC70   0041634B  / CALL 到 WriteProcessMemory 来自 CoralQQ.00416346
0012EC74   00000018  |hProcess = 00000018
0012EC78   5F010000  |Address = 5F010000
0012EC7C   0012EE9F  |Buffer = 0012EE9F
0012EC80   00000025  |BytesToWrite = 25 (37.)
0012EC84   0012EFD0  \pBytesWritten = 0012EFD0

留意第三次中断: 77F84BC0 对应着: NtTestAlert  所在库:ntdll.dll

程序每次执行前都要经过 ntdll.dll 的 NtTestAlert函数,它使函数首句跳到某个
地方,从而改变程序流程.
00417E7E    8B45 F4           mov  eax, dword  ptr  ss:[ ebp-C]
00417E81    50                push  eax
00417E82    E8 DDCDFEFF       call <jmp.&kernel32.ResumeThread> ;使得QQ的主线程继续执行


把 0012efc3 处的E9改为CC,再在softice中bpint 3 ,让其中断后跟踪:
001B:77F84BC0  E93BB408E7           JMP       5F010000

单步执行跟踪

001B:5F010000  B80000015F           MOV        EAX,5F010000
001B:5F010005  B90000005F           MOV        ECX,5F000000
001B:5F01000A  FFD1                 CALL       ECX

此时 ecx的值为5F000000


001B:5F000000  55                   PUSH       EBP
001B:5F000001  8BEC                 MOV        EBP, ESP
001B:5F000003  83C4EC               ADD        ESP,-14
001B:5F000006  53                   PUSH       EBX
001B:5F000007  56                   PUSH       ESI
001B:5F000008  8BD8                 MOV        EBX, EAX
001B:5F00000A  896DFC               MOV       [ EBP-04], EBP
001B:5F00000D  8B431C               MOV        EAX,[ EBX+1C]
001B:5F000010  8B55FC               MOV        EDX,[ EBP-04]
001B:5F000013  83C204               ADD        EDX,04
001B:5F000016  8902                 MOV       [ EDX], EAX
001B:5F000018  8B431C               MOV        EAX,[ EBX+1C]
001B:5F00001B  8945EC               MOV       [ EBP-14], EAX
001B:5F00001E  C745FC05000000       MOV        DWORD  PTR [ EBP-04],00000005
001B:5F000025  8D45F8               LEA        EAX,[ EBP-08]
001B:5F000028  50                   PUSH       EAX
001B:5F000029  6A40                 PUSH      40
001B:5F00002B  8D45FC               LEA        EAX,[ EBP-04]
001B:5F00002E  50                   PUSH       EAX
001B:5F00002F  8D45EC               LEA        EAX,[ EBP-14]
001B:5F000032  50                   PUSH       EAX
001B:5F000033  6AFF                 PUSH      FF
001B:5F000035  FF15C600005F         CALL      [5F0000C6]
001B:5F00003B  8B431C               MOV        EAX,[ EBX+1C]
001B:5F00003E  8B5320               MOV        EDX,[ EBX+20]
001B:5F000041  8910                 MOV       [ EAX], EDX  ;恢复Ntdll.NtTestAlert入口处
001B:5F000043  8A5324               MOV        DL,[ EBX+24]
001B:5F000046  885004               MOV       [ EAX+04], DL
001B:5F000049  C745FC05000000       MOV        DWORD  PTR [ EBP-04],00000005
001B:5F000050  8D45F8               LEA        EAX,[ EBP-08]
001B:5F000053  50                   PUSH       EAX
001B:5F000054  8B45F8               MOV        EAX,[ EBP-08]
001B:5F000057  50                   PUSH       EAX
001B:5F000058  8D45FC               LEA        EAX,[ EBP-04]
001B:5F00005B  50                   PUSH       EAX
001B:5F00005C  8D45EC               LEA        EAX,[ EBP-14]
001B:5F00005F  50                   PUSH       EAX
001B:5F000060  6AFF                 PUSH      FF
001B:5F000062  FF15CA00005F         CALL      [5F0000CA]
001B:5F000068  8B7318               MOV        ESI,[ EBX+18]
001B:5F00006B  4E                   DEC        ESI
001B:5F00006C  85F6                 TEST       ESI, ESI
001B:5F00006E  7C4C                 JL        5F0000BC
001B:5F000070  46                   INC        ESI
001B:5F000071  8D4325               LEA        EAX,[ EBX+25]
001B:5F000074  8BD8                 MOV        EBX, EAX
001B:5F000076  33D2                 XOR        EDX, EDX
001B:5F000078  8BC3                 MOV        EAX, EBX
001B:5F00007A  66833800             CMP        WORD  PTR [ EAX],00
001B:5F00007E  740C                 JZ        5F00008C
001B:5F000080  42                   INC        EDX
001B:5F000081  83C002               ADD        EAX,02
001B:5F000084  81FA03010000         CMP        EDX,00000103
001B:5F00008A  75EE                 JNZ       5F00007A
001B:5F00008C  8BC2                 MOV        EAX, EDX
001B:5F00008E  03C0                 ADD        EAX, EAX
001B:5F000090  668945F0             MOV       [ EBP-10], AX
001B:5F000094  6683C002             ADD        AX,02
001B:5F000098  668945F2             MOV       [ EBP-0E], AX
001B:5F00009C  8BC3                 MOV        EAX, EBX
001B:5F00009E  8945F4               MOV       [ EBP-0C], EAX
001B:5F0000A1  8D45FC               LEA        EAX,[ EBP-04]
001B:5F0000A4  50                   PUSH       EAX
001B:5F0000A5  8D45F0               LEA        EAX,[ EBP-10]
001B:5F0000A8  50                   PUSH       EAX
001B:5F0000A9  6A00                 PUSH      00
001B:5F0000AB  6A00                 PUSH      00
001B:5F0000AD  FF15CE00005F         CALL      [5F0000CE]  ;call LoadLibraryA
001B:5F0000B3  81C308020000         ADD        EBX,00000208
001B:5F0000B9  4E                   DEC        ESI
001B:5F0000BA  75BA                 JNZ       5F000076
001B:5F0000BC  5E                   POP        ESI
001B:5F0000BD  5B                   POP        EBX
001B:5F0000BE  8BE5                 MOV        ESP, EBP
001B:5F0000C0  5D                   POP        EBP
001B:5F0000C1  C3                   RET
001B:5F0000C2  0000                 ADD       [ EAX], AL
001B:5F0000C4  0000                 ADD       [ EAX], AL
001B:5F0000C6  C4BFF877C4BF         LES        EDI,[ EDI+BFC477F8]
001B:5F0000CC  F8                   CLC
001B:5F0000CD  7761                 JA        5F000130
001B:5F0000CF  32F8                 XOR        BH, AL
001B:5F0000D1  7700                 JA        5F0000D3


我们再分析一下win9x下珊瑚虫的外挂又是怎样运行的.
再次用OD载入Coralqq.exe

00415C9D   mov  dword  ptr  ss:[ ebp-C], ecx
00415CA0   mov  dword  ptr  ss:[ ebp-4], edx
00415CA3   mov  dword  ptr  ss:[ ebp-8], eax
00415CA6   xor  ebx, ebx
00415CA8   call <jmp.&kernel32.GetVersion>  ;判断操作系统
00415CAD   test  eax,80000000
00415CB2   je  short CORALQQ.00415CFE
00415CB4   xor  edi, edi
00415CB6   xor  esi, esi
00415CB8   jmp  short CORALQQ.00415CE7
00415CBA  / cmp  esi, dword  ptr  ss:[ ebp-24]
00415CBD  | je  short CORALQQ.00415CE2
00415CBF  | mov  eax, dword  ptr  ss:[ ebp-4]
00415CC2  | mov  edx, dword  ptr  ss:[ ebp-24]
00415CC5  | mov  dword  ptr  ds:[ eax], edx
00415CC7  | cmp  dword  ptr  ss:[ ebp-18],1000
00415CCE  | jnz  short CORALQQ.00415CDF
00415CD0  | push  ebp                               ; /Arg1
00415CD1  | call CORALQQ.00415BD4                  ; \CoralQQ.00415BD4
00415CD6  | pop  ecx
00415CD7  | test  al, al
00415CD9  | je  short CORALQQ.00415CDF
00415CDB  | mov  bl,1
00415CDD  | jmp  short CORALQQ.00415D29
00415CDF  | mov  esi, dword  ptr  ss:[ ebp-24]
00415CE2  | mov  eax, dword  ptr  ss:[ ebp-1C]
00415CE5  | add  edi, eax
00415CE7    push 1C                                ; /BufSize = 1C (28.)
00415CE9  | lea  eax, dword  ptr  ss:[ ebp-28]          ; |
00415CEC  | push  eax                               ; |Buffer
00415CED  | push  edi                               ; |Address
00415CEE  | mov  eax, dword  ptr  ss:[ ebp-8]           ; |
00415CF1  | push  eax                               ; |hProcess
00415CF2  | call <jmp.&kernel32.VirtualQueryEx>    ; \VirtualQueryEx 获得内存业面信息
00415CF7  | cmp  eax,1C
00415CFA  \ je  short CORALQQ.00415CBA
00415CFC   jmp  short CORALQQ.00415D29

上面的代码是判断操作系统的版本,如果是win9x的话就先跳到415ce7,

00415A4B  |> \8> lea  eax, dword  ptr  ss:[ ebp-8]
00415A4E  |.  5> push  eax                                  ; /pBytesWritten
00415A4F  |.  5> push  edi                                  ; |BytesToWrite
00415A50  |.  8> mov  eax, dword  ptr  ss:[ ebp-4]              ; |
00415A53  |.  5> push  eax                                  ; |Buffer
00415A54  |.  5> push  esi                                  ; |Address
00415A55  |.  5> push  ebx                                  ; |hProcess
00415A56  |.  E> call <jmp.&kernel32.WriteProcessMemory>   ; \WriteProcessMemory

看一下此时的堆栈:
0067EA5C   0000000C  |hProcess = 0000000C
0067EA60   83138AAC  |Address = 83138AAC
0067EA64   0067EABC  |Buffer = 0067EABC
0067EA68   00000292  |BytesToWrite = 292 (658.)
0067EA6C   0067EA7C  \pBytesWritten = 0067EA7C

它把缓冲区 0067eabc的658的字节写进QQ.exe的内存 83138aac处,在win98下,进程内存中的共享(M
MF)分区是0x80000000~0xbfffffff,所有的内存映射文件和系统共享DLL将加载在这个地址,而
那些映射文件和系统共享DLL往往都在比较高的地址,所以说,从80000000地址对上的一大段地址空间
往往是比较 "空闲"的,当然,并不是说这些地址就可以乱读乱写,至于这个83138aac的地址值具体是怎样计算出来的,
我还没有分析清楚,但我想到另外一种可行的方法,而且经过我自己编程证实,那就是以1000h大小为单位,从80000000
开始用WriteProcessMemory一直往上写数据,直到写入成功,证明那段1000h的地址可用,而且1000h
大小的内存空间已经够我们放代码的了,之所以用1000h为单位大小,是因为考虑到块对齐.

继续跟踪:
00415A39  |.  8D45 F8         lea  eax, dword  ptr  ss:[ ebp-8]
00415A3C  |.  50              push  eax                                  ; /pOldProtect
00415A3D  |.  6A 40           push 40                                   ; |NewProtect = PAGE_EXECUTE_READWRITE
00415A3F  |.  57              push  edi                                  ; |Size
00415A40  |.  56              push  esi                                  ; |Address
00415A41  |.  53              push  ebx                                  ; |hProcess
00415A42  |.  E8 85F2FEFF     call <jmp.&kernel32.VirtualProtectEx>     ; \VirtualProtectEx

上面的代码是改变QQ.exe的oep处的属性,使其可读可写可执行,为改写oep处的代码做准备

接着,又一次中断在WriteProcessMemory
看看堆栈:
0067EA5C   0000000C  |hProcess = 0000000C
0067EA60   00464B58  |Address = 464B58
0067EA64   0067EE46  |Buffer = 0067EE46
0067EA68   00000005  |BytesToWrite = 5
0067EA6C   0067EA7C  \pBytesWritten = 0067EA7C

464b58就是QQ.exe的OEP,很明显,它要改变oep来改变程序流程!!

    好了,我们又用那套方法,把0067eea6的第一个字节改为cc,在softice中bpint 3,然后中断,再
跟踪.
    在softice下中断后:
0167:00464B58  E91328CE82           JMP       83147370   


0167:83147370  C705584B4600558BEC6AMOV        DWORD  PTR [00464B58],6AEC8B55  ;马上恢复oep处的代码
0167:8314737A  C6055C4B4600FF       MOV        BYTE  PTR [00464B5C],FF
0167:83147381  68FA731483           PUSH      831473FA
0167:83147386  6838000000           PUSH      00000038
0167:8314738B  6A40                 PUSH      40
0167:8314738D  FF15F6731483         CALL      [KERNEL32!GlobalAlloc]  ;再申请内存
0167:83147393  C700B85077F7         MOV        DWORD  PTR [ EAX],F77750B8  ;从这里开始一直填入新数据
0167:83147399  C74004BFFFD068       MOV        DWORD  PTR [ EAX+04],68D0FFBF
0167:831473A0  C7400870731483       MOV        DWORD  PTR [ EAX+08],83147370
0167:831473A7  C7400CB89348E9       MOV        DWORD  PTR [ EAX+0C],E94893B8
0167:831473AE  C74010BFFFD0B8       MOV        DWORD  PTR [ EAX+10],B8D0FFBF
0167:831473B5  C74014584B4600       MOV        DWORD  PTR [ EAX+14],00464B58
0167:831473BC  C74018FFE0C705       MOV        DWORD  PTR [ EAX+18],05C7E0FF
0167:831473C3  C7401C584B4600       MOV        DWORD  PTR [ EAX+1C],00464B58
0167:831473CA  C74020558BEC6A       MOV        DWORD  PTR [ EAX+20],6AEC8B55
0167:831473D1  C74024C6055C4B       MOV        DWORD  PTR [ EAX+24],4B5C05C6
0167:831473D8  C740284600FF68       MOV        DWORD  PTR [ EAX+28],68FF0046
0167:831473DF  C7402CFA731483       MOV        DWORD  PTR [ EAX+2C],831473FA
0167:831473E6  C7403068380000       MOV        DWORD  PTR [ EAX+30],00003868
0167:831473ED  C74034006A40FF       MOV        DWORD  PTR [ EAX+34],FF406A00
0167:831473F4  FFE0                 JMP        EAX  ;此时eax为 0063059C


0167:0063059C  B85077F7BF           MOV        EAX,KERNEL32!LoadLibraryA ;加载Coralqq.dll
0167:006305A1  FFD0                 CALL       EAX
0167:006305A3  6870731483           PUSH      83147370
0167:006305A8  B89348E9BF           MOV        EAX,COMCTL32!ORD_0049
0167:006305AD  FFD0                 CALL       EAX
0167:006305AF  B8584B4600           MOV        EAX,00464B58 
0167:006305B4  FFE0                 JMP        EAX  ;跳回QQ.exe的入口点

分析完毕.
到了这里,我们可以总结一下了,在win2000/xp下coralqq.exe先创建QQ的进程,同时也就创建了
QQ的暂停的主线程,接着往QQ进程的内存写入代码,修改Ntdll.NtTestAlert的代码跳让程序跳到自己的
代码处执行,在执行的过程中恢复Ntdll.NtTestAlert处被改了的代码,同时加载Coralqq.dll.

在win9x下,coralqq.exe先创建QQ的进程,同时也就创建了QQ的暂停的主线程,接着往QQ.exe的内存
写数据,改写QQ.exe的oep从而达到改变程序流程的目的,让其先执行加入了的代码,加载Coralqq.dll,
加载完后再跳到原来的QQ.exe的oep继续执行.
其实在win2000/xp下面完全可以用远程线程的方法来实现加载dll文件,我后来自己编程实现了外挂
这一步.
    也许有读者读完这编文章后会问: "加载了coralqq.dll又有什么用?它是怎样显IP的?"
其实,要显 IP当然要修改QQ的内存中的代码,而修改内存代码这一步是在加载coralqq.dll的时候由
coralqq.dll完成的.也就是说,在执行LoadLibrary的过程中系统会执行corall.dll的 LibMain ,修改
的过程就在LibMain中完成了!而说到显 IP的原理,抱歉,不在我们这编文章的讨论范围之内,我们只是讨论
外挂中 "挂"这一步.


下面是我写的代码,可以做出一个顶替Coralqq.exe的程序,但原理上和Coralqq.exe有一点点不同



.586
.model  flat,  stdcall
option  casemap : none    ; case sensitive

include        windows.inc
include        kernel32.inc
includelib    kernel32.lib



.data
qq  db  ".\QQ.exe",0
ikeyname  db  "qq",0
isecname  db  "main",0
szBuffer         dw  50 dup(0)

dllname  db  ".\CoralQQ.dll",0
szkernel32  db  "Kernel32.dll",0
dllin  dd 0
szloadlibrary  db  "LoadLibraryA",0
oaddr  dd 0
wriaddr  dd 0
ininame  db  ".\CoralQQ.ini",0






.data?
align  dword
con CONTEXT <>
align  dword
con2 CONTEXT <>    

stStartUp    STARTUPINFO <?>
stProcInfo    PROCESS_INFORMATION <?>



.code
 start:
 main  proc
     local wrisize: dword  ;用来存放要写入的代码的大小
     local num: dword
     local oldpro: dword
     local lastwri: dword
     local wribase: dword  ;用来存放写入代码的基址
     invoke GetPrivateProfileString, offset isecname, offset ikeyname,\
         offset szloadlibrary, offset szBuffer,\
        sizeof szBuffer, offset ininame     ;从Coralqq.ini中获取QQ程序的路径
      invoke GetModuleHandle, offset szkernel32
      invoke GetProcAddress, eax, offset szloadlibrary
      mov dllin, eax
     
    invoke GetStartupInfo, addr stStartUp
     invoke CreateProcess,NULL, offset szBuffer,NULL,NULL, FALSE,\
    CREATE_SUSPENDED,NULL,NULL, addr stStartUp, addr stProcInfo  ;创建QQ进程
     cmp  eax,0
     jz exit
     invoke GetVersion
      test  eax,080000000h  ;判断操作系统类型
      jnz win9x
     invoke VirtualAllocEx,stProcInfo.hProcess,NULL,01000h,MEM_COMMIT,\
    PAGE_EXECUTE_READWRITE  ;在QQ内存中分配空间
     mov oaddr, eax
     invoke WriteProcessMemory,stProcInfo.hProcess,oaddr, offset dllname,\
    sizeof dllname, addr num  ;写入数据
     invoke CreateRemoteThread,stProcInfo.hProcess,NULL,0,dllin,oaddr,0,\
     addr num  ;创建远程线程
     invoke    CloseHandle, eax
     invoke ResumeThread,stProcInfo.hThread  ;让QQ继续运行
     invoke ExitProcess,0
     ret

win9x:    
     mov wribase,oepwrite
     mov wrisize,codeend-oepwrite
     invoke VirtualProtect,wribase,wrisize,\
    PAGE_EXECUTE_READWRITE, addr oldpro  ;改变这个程序的要写入代码的地方的属性,其实可以在编译时加上开关
    
     mov wrisize,codeend-codewrite
     mov wriaddr,080000000h
     sub wriaddr,1000h
again:
     add wriaddr,1000h
     mov wribase,codewrite
     invoke WriteProcessMemory,stProcInfo.hProcess,wriaddr,\
    wribase,wrisize, addr num  ;写入代码
     mov  eax,wrisize
     cmp  eax,num
     jnz again
    
     mov  eax,wriaddr
     mov  ebx,chan0-4
     mov [ ebx], eax
     invoke VirtualProtectEx,stProcInfo.hProcess,0464b58h,7,\
    PAGE_EXECUTE_READWRITE, addr oldpro  ;改变QQ.exe的oep处的属性
     mov wribase,oepwrite
     invoke WriteProcessMemory,stProcInfo.hProcess,0464b58h, wribase,7,\
     addr num  ;写入数据
    
     mov  eax,dllin
     mov  ebx,chan2-4
     mov [ ebx], eax
     mov  eax,codeend-codewrite
     add  eax,wriaddr
     mov  ebx,chan1-4
     mov [ ebx], eax
     mov wribase,codewrite
     mov wrisize,codeend-codewrite
     invoke WriteProcessMemory,stProcInfo.hProcess,wriaddr,\
    wribase,wrisize, addr num
    
     mov  eax,codeend-codewrite
     add  eax,wriaddr
     mov lastwri, eax
     invoke WriteProcessMemory,stProcInfo.hProcess,lastwri, offset dllname,\
    sizeof dllname, addr num

     invoke ResumeThread,stProcInfo.hThread  ;让QQ继续执行
    exit:
     invoke ExitProcess,0
     ret



            
main  endp

;下面的都是要写入到QQ.exe的内存的附加代码,但有些数值在写入前要实时修正

oepwrite:
     mov  eax,0
chan0:     jmp  eax

codewrite: 
mov  eax,0464b58h
push  6aec8b55h
pop [ eax]
mov  eax,0464b5ch
push  101868ffh
pop [ eax]
push 080000000
chan1: 
push 464b58h
mov  eax,0
chan2: 
jmp  eax
codeend:

end start

你可能感兴趣的:(珊瑚虫外挂原理分析)