x86二进制ROP攻击栈未对齐问题:为何添加4字节padding才生效?
问题解释:ROP调用system时的栈结构问题
你遇到的核心问题是x86 cdecl调用约定下,直接跳转函数与call指令的栈结构差异,和栈对齐无关,具体拆解如下:
1. 直接跳转system时的栈要求
正常用call system调用函数时,CPU会自动把下一条指令的地址(返回地址)压入栈,再跳转到system。此时system内部的栈结构是:
[参数] [返回地址] <-- ESP指向这里(call执行后)
system函数执行第一步会做栈帧初始化:
push ebp mov ebp, esp
之后它会通过ebp+8获取第一个参数(ebp+4是返回地址,ebp是旧栈基址)。
但你是通过ROP直接覆盖EIP为system_addr,相当于直接跳转到system,没有经过call指令,CPU不会自动压入返回地址,此时栈的结构完全由你的payload决定。
2. 第一个payload的问题
第一个payload构造后,栈在EIP被覆盖后的结构是:
[44字节填充] system_addr <-- EIP指向这里 bincat_addr <-- ESP指向这里(CPU跳转到system时)
当system执行栈帧初始化后,ebp等于当前ESP(即bincat_addr的地址),此时:
ebp+4= bincat_addr(被system当成返回地址)ebp+8= 栈中bincat_addr之后的内容(超出payload范围,是无效内存)
system会尝试读取ebp+8作为第一个参数,访问无效地址导致程序崩溃。
3. 第二个payload为什么生效
添加4字节padding后,栈结构变成:
[44字节填充] system_addr <-- EIP指向这里 CCCC <-- ESP指向这里(跳转后) bincat_addr
system执行栈帧初始化后:
ebp+4= CCCC(被当成返回地址,虽然无效,但system执行完cat操作后才会跳转到这里,不影响我们要的核心操作)ebp+8= bincat_addr(正好是我们要传的参数)
此时system能正确拿到/bin/cat flag.txt的地址作为参数,执行后完成命令,即使最后跳转到CCCC崩溃也无关紧要。
为什么你之前的理解错误
你以为会执行system("CCCC"),是混淆了ESP指向的内容和函数参数的位置。system的第一个参数不是ESP指向的内容,而是ebp+8——也就是返回地址占位的4字节之后的内容,所以CCCC只是占了返回地址的位置,真正的参数是后面的bincat_addr。
内容的提问来源于stack exchange,提问作者IRP_HANDLER
相关产品推荐
相关产品推荐

