汇编与反汇编之小技巧

来源:互联网 发布:marc dorcel 知乎 编辑:程序博客网 时间:2024/04/29 17:32

大家都知道,对于位于当前调试目标中的指令,可以使用WinDBGu命令进行反汇编。u命令的参数是要反汇编代码的地址值或者符号,如果不指定,那么WinDBG会使用当前程序指针寄存器所指向的代码,例如:

0:001> u

ntdll!DbgBreakPoint:

7c901230 cc              int     3

7c901231 c3              ret

如果要想将汇编指令翻译为机器码,那么应该使用a命令,a命令使用的参数格式与u命令相同,只不过参数的含义代表的是要产生的机器码要存放的起始地 址。例如执行a 0x400000命令后,WinDBG会启动交互式编辑提示符(Input>),而后便可以输入汇编指令,没输入一条后,按回车,然后可以继续输入 下一条,结束时直接按回车。

举个实际的例子,启动记事本程序,然后将WinDBG附加上去,此时执行u命令看到的就是上面的反汇编结果,也就是EIP指向的是ntdll中的 DbgBreakPoint函数,这个函数只有两条指令。接下来执行a命令,在Input提示符后输入nop然后按回车,而后再按回车结束汇编操作。

此时再执行u ntdll!DbgBreakPoint命令,可以看到:

0:001> u

ntdll!DbgBreakPoint: 7c901230 90              nop

7c901231 c3              ret

可见本来的INT 3指令被替换为nop指令(机器码为90)了。

输入g命令恢复记事本程序执行,然后再按Ctrl+Break试图将其中断到调试器,发现不立刻反应了,这是因为远程中断所依赖的ntdll!DbgBreakPoint函数的INT 3指令被我们替换为NOP(空指令)了。不过当WinDBG发现中断操作超时后会使用挂起的方式来中断(感兴趣的读者,可以参考《软件调试》的10.6.7节)。

上面是基本的反汇编和汇编用法。下面再说一种特殊的用法。

如果我们在日志文件或者其它环境中看到一段机器码,那么如何将其翻译为汇编指令呢?u命令是不支持后面直接跟随机器码的。

这时一种简单的方法就是找一段内存,然后将要反汇编的机器码输入到这段内存中,然后再使用u命令。哪里找这段内存呢?这段内存必须可以写。通常可以 选择栈。具体来说,先使用r命令观察目前的栈顶地址,即ESP寄存器的值。为了不破坏栈上的数据,应该使用比ESP小的空闲区域。

例如:

0:001> r

eax=7ffd7000 ebx=00000001 ecx=00000002 edx=00000003 esi=00000004 edi=00000005

eip=7c901230 esp=00beffcc ebp=00befff4 iopl=0         nv up ei pl zr na pe nc

cs=001b  ss=0023  ds=0023  es=0023  fs=0038  gs=0000             efl=00000246

ntdll!DbgBreakPoint:

7c901230 90              nop

上面的esp=00beffcc,如果我们要反汇编十几个字节的机器码,那么就可以使用00beff00开始的一段,即输入eb 00beff00,开始交互式编辑内存,输入要反汇编的机器码。

89.1E.83.C9.FF.F0.0F.C1.08.FF.75.08.E8.FD.0A.FD.FF.8B.45.08.5E.5B.5D.C2.08.00.CC.CC.CC.CC.CC.

输入结束后,再执行u 00beff00

0:001> u 00beff00 00beff00 891e            mov     dword ptr [esi],ebx

00beff02 83c9ff          or      ecx,0FFFFFFFFh

00beff05 f00fc108        lock xadd dword ptr [eax],ecx

00beff09 ff7508          push    dword ptr [ebp+8]

00beff0c e8fd0afdff      call    00bc0a0e

00beff11 8b4508          mov     eax,dword ptr [ebp+8]

00beff14 5e              pop     esi

00beff15 5b              pop     ebx

 

原创粉丝点击