Hi,大家好,我是编程小6,很荣幸遇见你,我把这些年在开发过程中遇到的问题或想法写出来,今天说一说
珊瑚虫外壳_网金游侠内挂使用教程,希望能够帮助你!!!。
作者: RunJin runjin000@yahoo.com.cn 分析工具: softice , OD 我的操作系统: win 2000 sp4 , win 98 分析对象: 2005贺岁版 珊瑚虫外挂 为了方便分析,我先把Coral.dll和coral.exe先脱壳,这两个文件加的 都是超弱壳,脱壳过程不在这里多说. 由于win nt 平台和win9x 的差异,珊瑚虫外挂因系统的不同而分开两种 工作原理. 我们都知道,珊瑚外挂是给的主程序.exe外挂了一个Coral.dll, 而完成这个工作的就是coral.exe .要加载一个dll文件必须是.exe自己 的某个线程执行LoadLibraryA,并且以coral.dll为参数,但.exe本来根本 没有这样的一段代码,怎么办?答案很简单,既然它没有,那就让我们帮它加上去, coral.exe就是利用WriteProcessMemory帮.exe加上了这样一段代码,并且 改变程序流程,让.exe先加载coral.dll再跳到原来的oep执行. 想了一下,比较合理的方法有: 1.在nt内核的系统上,利用远程线程的方法,首先用CreateProcess创建.exe 的进程,同时创建了主线程,再用VirtualAllocEx在.exe中申请一块内存,然后把 我们的代码写进去,最后用CreateRemoteThread在的进程中创建另外一个 线程,其开始执行的地方正是我们自己加入的代码首地址. 2.先用CreateProcess创建进程和主线程,在的内存空间中找个合理 的地方写入我们的代码,然后修改某个地方(例如OEP)使先跳去执行我们 写入的代码,加载coral.dll,修复原来改过的oep,然后跳回oep让程序正常执行. 下面就让我们分析一下珊瑚虫的外挂是怎样做到的,首先分析nt平台上的 运行过程. 用OD载入脱壳后的coral.exe,停在下面: 00418E2C >/$ 55 push ebp 00418E2D |. 8BEC mov ebp,esp 00418E2F |. 83C4 F0 add esp,-10 00418E32 |. B8 648D4100 mov eax,Coral.00418D64 00418E37 |. E8 A4BAFEFF call Coral.004048E0 00418E3C |. A1 F49D4100 mov eax,dword ptr ds:[419DF4] 00418E41 |. 33D2 xor edx,edx 00418E43 |. E8 30F4FFFF call Coral.00 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 Coral.00 00418E57 |. E8 08A9FEFF call Coral.00 然后下断点: bp CreateRemoteThread ,然后运行,结果发现,OD根本没有断下, 证明珊瑚虫的外挂没有使用远程线程的方法,难道它是用了第二种方法?我们再验证一下: 首先在OD中bp CreateProcess,断下,反回后,用winhex打开.exe的内存,把.exe 的OEP处改为CC,接着在softice中 bpint 3 ,在OD中按F9运行,接着就是中断在softice 中,把oep(464b58)处还原,在再softice下 bpm 464b58 ,然后结束程序,再运行coral.exe 发现自始至终那个bpm断点还是没有断下,证明珊瑚虫外挂在2000下也没有修改.exe 的oep来改变程序流程,晕.没办法,只好在OD中下WriteProcessMemory断点,看看它究竟 修改了哪里. 00 57 push edi 00 8B4424 24 mov eax,dword ptr ss:[esp+24] 00 A3 mov dword ptr ds:[],eax 0023101C 8305 04 add dword ptr ds:[],4 00 E8 5C000000 call ;创建的进程 上面创建后的主线程是暂停的,不会马上执行,在win9x下也是这样. 第一次中断时堆栈显示: 0012EBDC 0040C75C /CALL 到 WriteProcessMemory 来自 Coral.0040C756 0012EBE0 00000018 |hProcess = 00000018 0012EBE4 5F000000 |Address = 5F000000 0012EBE8 00CC0F44 |Buffer = 00CC0F44 0012EBEC 000000D2 |BytesToWrite = D2 (210.) 0012EBF0 0012EC68 /pBytesWritten = 0012EC68 第二次: 0012EC70 00 /CALL 到 WriteProcessMemory 来自 Coral.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 来自 Coral.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 来自 Coral.00 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 来自 Coral.00 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 ;使得的主线程继续执行 把 0012efc3 处的E9改为CC,再在softice中bpint 3 ,让其中断后跟踪: 001B:77F84BC0 E93BB408E7 JMP 5F010000 单步执行跟踪 001B:5F010000 BF MOV EAX,5F010000 001B:5F010005 BF 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 C745FC0 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 FF15CF 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 MOV [EAX+04],DL 001B:5F000049 C745FC0 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 CMP WORD PTR [EAX],00 001B:5F00007E 740C JZ 5F00008C 001B:5F000080 42 INC EDX 001B:5F000081 83C002 ADD EAX,02 001B:5F000084 81FA0 CMP EDX,00000103 001B:5F00008A 75EE JNZ 5F00007A 001B:5F00008C 8BC2 MOV EAX,EDX 001B:5F00008E 03C0 ADD EAX,EAX 001B:5F000090 F0 MOV [EBP-10],AX 001B:5F000094 6683C002 ADD AX,02 001B:5F000098 F2 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 81C 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载入Coral.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 ;判断操作系统 00415CAD test eax, 00415CB2 je short CORAL.00415CFE 00415CB4 xor edi,edi 00415CB6 xor esi,esi 00415CB8 jmp short CORAL.00415CE7 00415CBA /cmp esi,dword ptr ss:[ebp-24] 00415CBD |je short CORAL.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 CORAL.00415CDF 00415CD0 |push ebp ; /Arg1 00415CD1 |call CORAL.00415BD4 ; /Coral.00415BD4 00415CD6 |pop ecx 00415CD7 |test al,al 00415CD9 |je short CORAL.00415CDF 00415CDB |mov bl,1 00415CDD |jmp short CORAL.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 ; /VirtualQueryEx 获得内存业面信息 00415CF7 |cmp eax,1C 00415CFA /je short CORAL.00415CBA 00415CFC jmp short CORAL.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 ; /WriteProcessMemory 看一下此时的堆栈: 0067EA5C 0000000C |hProcess = 0000000C 0067EA60 83138AAC |Address = 83138AAC 0067EA64 0067EABC |Buffer = 0067EABC 0067EA68 00000292 |BytesToWrite = 292 (658.) 0067EA6C 0067EA7C /pBytesWritten = 0067EA7C 它把缓冲区 0067eabc的658的字节写进.exe的内存 83138aac处,在win98下,进程内存中的共享(M MF)分区是0x~0xbfffffff,所有的内存映射文件和系统共享DLL将加载在这个地址,而 那些映射文件和系统共享DLL往往都在比较高的地址,所以说,从地址对上的一大段地址空间 往往是比较"空闲"的,当然,并不是说这些地址就可以乱读乱写,至于这个83138aac的地址值具体是怎样计算出来的, 我还没有分析清楚,但我想到另外一种可行的方法,而且经过我自己编程证实,那就是以1000h大小为单位,从 开始用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 ; /VirtualProtectEx 上面的代码是改变.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就是.exe的OEP,很明显,它要改变oep来改变程序流程!! 好了,我们又用那套方法,把0067eea6的第一个字节改为cc,在softice中bpint 3,然后中断,再 跟踪. 在softice下中断后: 0167:00464B58 E91328CE82 JMP 0167: CBBEC6AMOV DWORD PTR [00464B58],6AEC8B55 ;马上恢复oep处的代码 0167:A C6055C4B4600FF MOV BYTE PTR [00464B5C],FF 0167: 68FA PUSH FA 0167: PUSH 00000038 0167:B 6A40 PUSH 40 0167:D FF15F CALL [KERNEL32!GlobalAlloc] ;再申请内存 0167: C700B85077F7 MOV DWORD PTR [EAX],F77750B8 ;从这里开始一直填入新数据 0167: C74004BFFFD068 MOV DWORD PTR [EAX+04],68D0FFBF 0167:A0 C83 MOV DWORD PTR [EAX+08], 0167:A7 C7400CB89348E9 MOV DWORD PTR [EAX+0C],E94893B8 0167:AE C74010BFFFD0B8 MOV DWORD PTR [EAX+10],B8D0FFBF 0167:B5 CB4600 MOV DWORD PTR [EAX+14],00464B58 0167:BC C74018FFE0C705 MOV DWORD PTR [EAX+18],05C7E0FF 0167:C3 C7401C584B4600 MOV DWORD PTR [EAX+1C],00464B58 0167:CA CBEC6A MOV DWORD PTR [EAX+20],6AEC8B55 0167:D1 C74024C6055C4B MOV DWORD PTR [EAX+24],4B5C05C6 0167:D8 CFF68 MOV DWORD PTR [EAX+28],68FF0046 0167:DF C7402CFA MOV DWORD PTR [EAX+2C],FA 0167:E6 C00 MOV DWORD PTR [EAX+30],00003868 0167:ED CA40FF MOV DWORD PTR [EAX+34],FF406A00 0167:F4 FFE0 JMP EAX ;此时eax为 0063059C 0167:0063059C B85077F7BF MOV EAX,KERNEL32!LoadLibraryA;加载Coral.dll 0167:006305A1 FFD0 CALL EAX 0167:006305A3 PUSH 0167:006305A8 B89348E9BF MOV EAX,COMCTL32!ORD_0049 0167:006305AD FFD0 CALL EAX 0167:006305AF B8584B4600 MOV EAX,00464B58 0167:006305B4 FFE0 JMP EAX ;跳回.exe的入口点 分析完毕. 到了这里,我们可以总结一下了,在win2000/xp下coral.exe先创建的进程,同时也就创建了 的暂停的主线程,接着往进程的内存写入代码,修改Ntdll.NtTestAlert的代码跳让程序跳到自己的 代码处执行,在执行的过程中恢复Ntdll.NtTestAlert处被改了的代码,同时加载Coral.dll. 在win9x下,coral.exe先创建的进程,同时也就创建了的暂停的主线程,接着往.exe的内存 写数据,改写.exe的oep从而达到改变程序流程的目的,让其先执行加入了的代码,加载Coral.dll, 加载完后再跳到原来的.exe的oep继续执行. 其实在win2000/xp下面完全可以用远程线程的方法来实现加载dll文件,我后来自己编程实现了外挂 这一步. 也许有读者读完这编文章后会问:"加载了coral.dll又有什么用?它是怎样显IP的?" 其实,要显IP当然要修改的内存中的代码,而修改内存代码这一步是在加载coral.dll的时候由 coral.dll完成的.也就是说,在执行LoadLibrary的过程中系统会执行corall.dll的 LibMain ,修改 的过程就在LibMain中完成了!而说到显IP的原理,抱歉,不在我们这编文章的讨论范围之内,我们只是讨论 外挂中"挂"这一步. 下面是我写的代码,可以做出一个顶替Coral.exe的程序,但原理上和Coral.exe有一点点不同 .586 .model flat, stdcall option casemap :none ; case sensitive include windows.inc include kernel32.inc includelib kernel32.lib .data db "./.exe",0 ikeyname db "",0 isecname db "main",0 szBuffer dw 50 dup(0) dllname db "./Coral.dll",0 szkernel32 db "Kernel32.dll",0 dllin dd 0 szloadlibrary db "LoadLibraryA",0 oaddr dd 0 wriaddr dd 0 ininame db "./Coral.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 ;从Coral.ini中获取程序的路径 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 ;创建进程 cmp eax,0 jz exit invoke GetVersion test eax,0h ;判断操作系统类型 jnz win9x invoke VirtualAllocEx,stProcInfo.hProcess,NULL,01000h,MEM_COMMIT,/ PAGE_EXECUTE_READWRITE ;在内存中分配空间 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 ;让继续运行 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,0h 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 ;改变.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 ;让继续执行 exit: invoke ExitProcess,0 ret main endp ;下面的都是要写入到.exe的内存的附加代码,但有些数值在写入前要实时修正 oepwrite: mov eax,0 chan0: jmp eax codewrite: mov eax,0464b58h push 6aec8b55h pop [eax] mov eax,0464b5ch push ffh pop [eax] push 0 chan1: push 464b58h mov eax,0 chan2: jmp eax codeend: end start
今天的分享到此就结束了,感谢您的阅读,如果确实帮到您,您可以动动手指转发给其他人。
上一篇
已是最后文章
下一篇
已是最新文章