ret2xx
这两周做了很多栈溢出的题,这是很基础的东西,所以想写一下做一个归类。
基础知识
系统调用怎么写:首先,如果要在rop链中用系统调用,要知道32位和64位区别:
1.传参方式不同
2.系统调用号不同
3.调用方式不同
32位传参方式:
系统调用号存在eax,参数依次放在ebx,ecx,edx,esi,edi,ebp,返回值存到eax
调用号:sys_read的调用号为3,sys_write的调用号为4,sys_execve的调用号为11
调用方式:使用int 0x80软中端指令进行系统调用
64位传参方式:
系统调用号放在rax,参数依次放在rdi,rsi,rdx,r10,r8,r9,返回值存在rax
(和普通函数调用仅仅在第四个参数那不同,普通的函数是参数放入rcx)
调用号:sys_read的调用号为0,sys_write的调用号为1,sys_execve的调用号为59
调用方式:使用syscall函数进行系统调用
举例:32位:ret2syscall,如何调用以下函数:
1 | execve("/bin/sh",NULL,NULL) |
1 | payload = flat([b'a' * 112, pop_eax, 0xb, pop_edx_ecx_ebx, 0, 0, binsh, int_0x80]) |
先将系统调用号存到eax,再将参数传入ebx,ecx,edx,最后执行0x80软中断
64位:如何调用以下函数:
1 | fd = open("flag", O_RDONLY) |
1 | payload += b'a'*0x38 + p64(pop_rdi_ret) + p64(alarm_got) +p64(pop_rax_ret) + p64(syscall_offset) + p64(add_rdi_al_ret) |
首先rdi存某个系统调用的got地址,再用rax存syscall相对于alarm这个系统调用的偏移地址,接下来用add将got中alarm地址+偏移就是syscall地址覆盖alarm的got地址,所以该地址变成了syscall,rdi存的就是syscall地址,接下来rsi存入open的第一个参数,r15存入垃圾数据,然后rdi存flag字符串地址,rax存open的调用号,最后用syscall来调用这个rop(改alarm的got,调用函数需要用plt)
read函数本来就在程序中用过,所以不用执行系统调用。