Pwn学习随笔

Pwn题做题流程

  • 使用checksec检查ELF文件保护开启的状态
  • IDApro逆向分析程序漏洞(逻辑复杂的可以使用动态调试)
  • 编写python的exp脚本进行攻击
    • (若攻击不成功)进行GDB动态调试,查找原因
    • (若攻击成功)获取flag , 编写Writeup
一般都会在C代码开头设置setbuf(stdout, 0)表示设置printf缓冲区为0,有就输出而不是等到输出\n时一块输出
ebp + 0x4 存放函数中第一个局部变量,ebp - 0x4是返回地址ebp - 0x8 存放函数第一个参数
栈帧基本知识
Pwn学习随笔

文章插图
下面解释一下下面的汇编代码(AT&T格式) , 
首先push %ebp,保存调用者的调用者的ebp寄存器,move %esp, %ebp开始创建caller函数的栈帧,然后sub $0x10, %esp,在32位程序下是4字节对齐的,将esp指针向下移动16字节(参数占12字节 , 局部变量4字节),即四格,此时esp指向3上面的地址,
然后将callee函数的参数入栈(cdecl从右往左入栈),然后调用call calleecall指令其实是两条指令 , 先push esp + 0xc , 将返回地址压栈,然后jmp 00000000跳到callee函数的位置开始执行,然后同样的操作,先将caller函数的ebp寄存器压栈,然后mov esp. ebp开始创建callee函数的栈帧,之后开始callee函数的计算功能,取出之前入栈的参数进行加法操作 。执行完后将栈中保存的caller函数ebp寄存器的内容再popebp寄存器,此时ebp指向最上面的位置 。然后esp - 4,上移一格 。最后执行ret指令 , 其实也是两条指令 , pop eipcaller调用callee函数之前入栈的返回地址popeip , 下一步就执行该地址 。然后esp + 4,回到caller函数的栈帧 , 可以看到首先是add $0xc, %esp , 将栈顶指针提升到3上面的位置 , 然后mov %eax, -0x4(%ebp) , 意思就是将eax寄存器的值 (callee的返回值) 赋给ebp-4的位置,即caller函数的局部变量ret , 然后addl $0x4,-0x4(%ebp)将局部变量ret的值 + 4 , 最后再把局部变量赋给eax寄存区准备返回
Pwn学习随笔

文章插图
call指令执行完后 , 会在esp中存储返回地址0x401171 = 0x40116c + 4 , 
Pwn学习随笔

文章插图
进入函数内部后 , 需要首先执行push ebp,保存调用它的函数的栈帧 。然后ebp = esp,提升栈底,准备创建本函数的栈帧,
sub esp, 50,会将esp的位置往上提升0x40 / 4 = 0x10即16格,然后push ebx | esi | edi保存现场到堆栈中,lea edi, dword ptr ss:[ebp-40]取地址编号赋给ediedi = esp + 3*0x4,下面三条之路是一组,stos用于将eax的值存储到edi的地址编号中,ecx记录执行次数 。每执行一次,ecx - 1, edi + 4(df位为0)或者edi - 4(df位为1)ccccccccint 3的硬编码int 3是端点,这样做为了防止缓冲区溢出,未到的栈空间都被设置为cccccccc,CPU执行遇到这里就会将程序停下来了 。下一步mov eax, dword ptr ss:[ebp+8]是函数的第二个参数,ebp+c是函数的第一个参数,这两步执行了关键操作 2 + 1 = 3此时函数功能就完成了,下面就是恢复现场了,pop edi,可分为两步,mov edi, espadd esp,4,先push的后pop然后执行mov, esp, ebp,即将栈指针esp下降到之前sub执行前的位置,栈中的数据并没有清除
然后pop ebp,即将0x12ff30赋给ebp然后esp + 4,最后执行retn,相当于pop eipmov eip, 401171然后esp + 4,这个地址就很关键了,这就是我们在pwn中经常覆盖的返回地址 。然后返回到调用者中执行 , 但是需要注意此时

推荐阅读