32位程序调用64位代码

原理

x64系统下的进程是有32位和64位两种工作模式,这两种工作模式的区别在于CS寄存器。32位模式时,CS = 0x23;64位模式时,CS = 0x33。这两种工作模式是可以进行切换的,一般会通过retf指令,一条retf指令等效于以下2条汇编指令:pop ip; pop cs

如果此时栈中有0x33,则会将0x33弹出到CS寄存器中,实现32位程序切换到64位代码的过程。所以retf是识别32位程序调用64位代码的重要标志。

Linux

动态调试

1
gdbserver :23946 ./father

IDA64打开,选择Remote GDB debugger,配置好IP,设置断点,开始运行。

如果没有显示代码,打开Debugger菜单中的Manual memory regions菜单项,右键Insert新建一个内存区域,设置起始地址,注意选择64-bit segment。

如果不需要Manual memory regions中增加内存区域,可以通过IDA的Edit->Segments->Change Segment Attributes修改内存为64位代码。

静态调试

通过IDC或者python脚本,dump出64bit代码,选择64-bit mode分析代码,Edit->Segments->Rebase Segment重定义基地址,以保持和动态调试地址一致。

Windows

静态调试

010Editor打开,NtHeader->OptionalHeader->Magic,修改为PE64(20Bh)。保存后,用IDA64打开,Edit->Segments->Rebase program,Image base填0。

动态调试

Windbg64,File->Open Executable,View菜单打开Disassembly(汇编)、Registers(寄存器)、Memory(内存)和Command(命令)窗口,在Disassembly窗口输入GWoC+0x134c,确定也是retf,按F9设置断点。按F5执行到断点处,再按F8单步进入执行,此时CS寄存器可以看到已经变成0x33,进入64位代码块。