珊瑚虫外挂原理分析

作者: RunJin
     runjin000@yahoo.com.cn

分析工具: 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 flatstdcall
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

目录: 本手册的功能 读者对象 本手册的组织结构 排版风格 如何使用本手册 其它相关文件 (外国人就是罗嗦,为了求全,只好随他了。) 第一章 欢迎使用SoftICE 产品概况 介绍SoftICE 介绍Symbol Loader 如何得到客户服务 联系NuMega公司的技术支持中心 第二章 安装SoftICE 介绍 硬件和软件要求 SoftICE显示选择 安装之前 安装 安装之后 配置BOOT。INI以便在多处理器系统中支持单CPU 配置SoftICE在Windows 95下正确载入 通过串行口连接第二台计算机 解决显卡问题 第三章 SoftICE教程 介绍 载入SoftICE 构造GDIDEMO样本程序 装入GDIDEMO样本程序 控制SoftICE屏幕 通过源码跟踪和逐步调试 读本地数据 设定断点和目标断点 设定一个断点 设定STICKY断点 (此处不知STICKY作何解释。待我读到此处时大概会明白) 使用SoftICE命令行信息 使用符号和符号表 设定条件断点 设置BPX断点 编辑断点 设定读写内存断点 第四章 将代码装入SoftICE 调试的概念 准备调试程序 准备调试设备驱动程序和VxDs(虚拟设备驱动程序) 手工装入SoftICE 装入SoftICE for Windows 95 装入SoftICE for Windows NT 构造带有调试信息的程序 使用Symbol Loader转换和载入文件 修改模块设定 修改通用设定 修改编译设定 修改调试设定 指定程序的源文件 删除符号表 在DOS命令行里使用Symbol Loader 使用Symbol Loader的命令行工具 NMSYM命令行的语法 使用NMSYM来转换符号信息 使用NMSYM来装入模块和符号信息 使用NMSYM来装入或导出符号表 使用NMSYM卸载符号信息 使用NMSYM来保存历史记录 关于NMSYM的信息 第五章 SoftICE导航 介绍 呼出SoftICE窗口 启动时禁用SoftICE 使用SoftICE窗口 调整窗口大小 控制窗口 拷贝和粘贴数据 用鼠标输入命令 得到帮助 使用命令窗口 滚动窗口 键入命令 重呼命令 使用运行时宏 将命令窗口的历史缓存保存到文件 相关命令 控制代码窗口 读信息 在代码窗口键入命令 使用本地窗口 控制本地窗口 扩展和分解堆栈 相关命令 使用观察窗口 控制观察窗口 设定观察表达式 读信息 扩展和分解类型表达式 相关命令 使用寄存器窗口 控制寄存器窗口 读信息 编辑寄存器和标志位 相关命令 使用数据窗口 控制数据窗口 读信息 改变内存地址和格式 编辑内存 辅助表达式 相关命令 第六章 使用SoftICE 在跟踪错误时调试多个程序 跟踪错误 Ring-3 32位保护模式(Win32程序) Ring-0 驱动代码(内核模式设备驱动程序) Ring-3 16位保护模式(16位Win程序) 地址内容 使用INT 0x41 .DOT命令 理解从R-3到R-0的转变 第七章 使用断点 第八章 ----------------------------------------------------------- (...很累人那!今天就这些了吧.因为我也是读一些翻译一些,所以有些"向前引用 "的名词术语不知道要如何解释其意义.应该读完再翻译比较好...不过那个时候我 又开学了...呜...一点时间也没有了!) 第七章 使用断点 介绍 SoftICE所支持的断点类型 断点选项 执行断点 内存断点 中断断点 I/O断点 窗口消息断点 理解断点的含义 虚断点 设置断点活动 条件断点 条件断点计数功能 在条件表达式中使用本地变量 在条件断点里引用堆栈 参考 多重断点 所用时间 断点统计 在表达式中引用断点 维护断点 使用内嵌断点 第八章 使用表达式 表达式 操作符 操作符优先级 形成表达式 表达式类型 定制类型 取得符号的数值 间接使用符号 第九章 装入系统组件符号 装入由DLL和EXE文件导出的符号表 使用未命名的入口点
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值