我假设你已经掌握Ollydbg的使用,并且希望用WinDbg进行内核级的调试。这篇教程将会以Ollydbg为线索,帮助你尽快掌握WinDbg的使用,并简单介绍它的一些特性。我把这篇文章定位为Ollydbg到WinDbg内核调试之间的过渡。
----------------------------------------------------------如果没有跳会怎么样?----------------------------------------------------
0040C7F0 8B4B 04 mov ecx,dword ptr ds:[ebx+4]
0040C7F3 68 74364400 push blbeta.00443674 ; UNICODE "/q"
0040C7F8 51 push ecx
0040C7F9 E8 B1290100 call blbeta.0041F1AF 从传入参数看,此CALL判断运行参数是否为/q
0040C7FE 83C4 08 add esp,8
0040C801 85C0 test eax,eax
0040C803 0F84 AF010000 je blbeta.0040C9B8 可能是参数/q对应的功能模块
Ollydbg的参考字符功能,基本可以猜到该程序能以参数启动,格式为“/ 参数”,长度不等于1
--------------------------------------------------------------回到正题------------------------------------------------------------
0040C809 33D2 xor edx,edx
0040C80B 55 push ebp 初始栈-60
0040C80C 57 push edi 初始栈-64
0040C80D 33C0 xor eax,eax
0040C80F 895424 10 mov dword ptr ss:[esp+10],edx
0040C813 B9 11000000 mov ecx,11
0040C818 8D7C24 20 lea edi,dword ptr ss:[esp+20]
0040C81C F3:AB rep stos dword ptr es:[edi]
0040C81E 397424 6C cmp dword ptr ss:[esp+6C],esi 仍然是跟初始栈+8比较
0040C822 895424 14 mov dword ptr ss:[esp+14],edx
0040C826 895424 18 mov dword ptr ss:[esp+18],edx
0040C82A C74424 20 44000>mov dword ptr ss:[esp+20],44
0040C832 895424 1C mov dword ptr ss:[esp+1C],edx
0040C836 76 70 jbe short blbeta.0040C8A8 ESI没有改变过,此处相当于JMP
-----------------------------------------------junk code如何引诱你改变EIP跟进去?------------------------------------------------
0040C838 8B43 04 mov eax,dword ptr ds:[ebx+4]
0040C83B 68 64364400 push blbeta.00443664 ; UNICODE "/expert"
0040C840 50 push eax
0040C841 E8 69290100 call blbeta.0041F1AF
0040C846 83C4 08 add esp,8
0040C849 85C0 test eax,eax
0040C84B 75 5B jnz short blbeta.0040C8A8
首先是一个非常引诱的字符参考“/expert”,跟进去仿佛能开启高级功能。然后是0040C8A8由于跟上面跳转一样,或者会让你觉得不跳转,继续跟下去便是开启高级功能的关键。攻城为下攻心为上,如果我在这里安排一些破坏性的代码。。。。。。
--------------------------------------------------------------回到正题------------------------------------------------------------
虽然跳过了一大堆junk code不过我猜肯定不止那么少。
0040C8A8 8B0B mov ecx,dword ptr ds:[ebx]
0040C8AA 51 push ecx
0040C8AB E8 21200100 call blbeta.0041E8D1
0040C8B0 68 74364400 push blbeta.00443674 ; UNICODE "/q"
0040C8B5 8BF0 mov esi,eax
0040C8B7 E8 15200100 call blbeta.0041E8D1 前面已经有处理/q的例程了,这里还处理?忽略
0040C8BC 83C4 08 add esp,8
0040C8BF 6A 04 push 4
0040C8C1 8D6C06 04 lea ebp,dword ptr ds:[esi+eax+4]
0040C8C5 68 00100000 push 1000
0040C8CA 8D7C2D 00 lea edi,dword ptr ss:[ebp+ebp]
0040C8CE 57 push edi
0040C8CF 6A 00 push 0
0040C8D1 FF15 B0A34300 call dword ptr ds:[<&KERNEL32.VirtualAlloc>] ; KERNEL32.VirtualAlloc
0040C8D7 8BCF mov ecx,edi 这条指令跟下一条指令相当于mov edx,edi
0040C8D9 8BD1 mov edx,ecx 到这里还有junk code
0040C8DB 8BF0 mov esi,eax 又是一个junk code
0040C8DD C1E9 02 shr ecx,2
0040C8E0 33C0 xor eax,eax
0040C8E2 8BFE mov edi,esi 相当于mov edi,eax
0040C8E4 F3:AB rep stos dword ptr es:[edi]
代码分析=体力活,本文重点介绍工具使用,而不是代码还原。现在忽略细节,直接看它用了什么API。
CALL KERNEL32.VirtualAlloc
Call KERNEL32.GetModuleFileNameW
call KERNEL32.CreateEventW
call KERNEL32.CreateProcessW 其中|CommandLine = ""D:lbeta.exe" /q"
call KERNEL32.WaitForSingleObject
call KERNEL32.CloseHandle
call KERNEL32.VirtualFree
call KERNEL32.ExitProcess
ExitProcess之后又来到一开始的地方了。
0040C7C0 8B4424 08 mov eax,dword ptr ss:[esp+8]
0040C7C4 83EC 54 sub esp,54
0040C7C7 56 push esi
0040C7C8 BE 01000000 mov esi,1
0040C7CD 3BC6 cmp eax,esi
0040C7CF 0F85 E4010000 jnz blbeta.0040C9B9 这次跳转成功了
0040C9B9 5E pop esi
0040C9BA 83C4 54 add esp,54
0040C9BD C2 0C00 retn 0C retn后ESP-0c
关于TLS:现在我们知道TLSCALLBACK通过初始栈+8的数据来判断是什么情况下被调用。当它的值为1时,代表TLS被首次运行。假如只是简单判断是否第一次被运行,只要判断是否为1就够了。为什么结束时是retn 0c?现在让我们单步进入系统区域看看:
77F86209 FF75 14 push dword ptr ss:[ebp+14]
77F8620C FF75 10 push dword ptr ss:[ebp+10]
77F8620F FF75 0C push dword ptr ss:[ebp+C]
77F86212 FF55 08 call dword ptr ss:[ebp+8]
77F86215 8BE6 mov esp,esi