最近由于某些原因,更新了一下pwndbg,结果发现原本好好的bins
功能被改成了一坨屎!!
去github看了一下issues,果然也有人说到这个问题.
https://github.com/pwndbg/pwndbg/issues/424
原本是这样的
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 pwndbg> bins fastbins 0x20: 0x602000 ◂— 0x0 0x30: 0x0 0x40: 0x0 0x50: 0x0 0x60: 0x0 0x70: 0x0 0x80: 0x0 unsortedbin all: 0x0 smallbins empty largebins empty
后来变成了这样
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 pwndbg> bins fastbins 0x20: 0x602000 ◂— 0x0 0x30: 0x0 0x40: 0x0 0x50: 0x0 0x60: 0x0 0x70: 0x0 0x80: 0x0 unsortedbin all: 0x7ffff7dd1b78 (main_arena+88) ◂— 0x7ffff7dd1b78 smallbins 0x20: 0x7ffff7dd1b88 (main_arena+104) ◂— 0x7ffff7dd1b88 0x30: 0x7ffff7dd1b98 (main_arena+120) ◂— 0x7ffff7dd1b98 0x40: 0x7ffff7dd1ba8 (main_arena+136) ◂— 0x7ffff7dd1ba8 0x50: 0x7ffff7dd1bb8 (main_arena+152) ◂— 0x7ffff7dd1bb8 ...... 0x3d0: 0x7ffff7dd1f38 (main_arena+1048) ◂— 0x7ffff7dd1f38 0x3e0: 0x7ffff7dd1f48 (main_arena+1064) ◂— 0x7ffff7dd1f48 0x3f0: 0x7ffff7dd1f58 (main_arena+1080) ◂— 0x7ffff7dd1f58 largebins 0x400: 0x7ffff7dd1f68 (main_arena+1096) ◂— 0x7ffff7dd1f68 0x440: 0x7ffff7dd1f78 (main_arena+1112) ◂— 0x7ffff7dd1f78 0x480: 0x7ffff7dd1f88 (main_arena+1128) ◂— 0x7ffff7dd1f88 0x4c0: 0x7ffff7dd1f98 (main_arena+1144) ◂— 0x7ffff7dd1f98 0x500: 0x7ffff7dd1fa8 (main_arena+1160) ◂— 0x7ffff7dd1fa8 ...... 0x28000: 0x7ffff7dd2328 (main_arena+2056) ◂— 0x7ffff7dd2328 0x40000: 0x7ffff7dd2338 (main_arena+2072) ◂— 0x7ffff7dd2338 0x80000: 0x7ffff7dd2348 (main_arena+2088) ◂— 0x7ffff7dd2348
what a shit code !!!
这怎么能忍?
对照comment前的代码,我修改了pwndbg/chain.py
中get
的代码
修改后代码如下
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 def get (address, limit=LIMIT, offset=0 , hard_stop=None , hard_end=0 ): """ Recursively dereferences an address. For bare metal, it will stop when the address is not in any of vmmap pages to avoid redundant dereference. Arguments: address(int): the first address to begin dereferencing limit(int): number of valid pointers offset(int): offset into the address to get the next pointer hard_stop(int): address to stop at hard_end: value to append when hard_stop is reached Returns: A list representing pointers of each ```address``` and reference """ limit = int (limit) result = [] for i in range (limit): if result.count(address) >= 2 : break if hard_stop is not None and address == hard_stop: result.append(hard_end) break result.append(address) try : address = address + offset if not pwndbg.abi.linux and not pwndbg.vmmap.find(address): break address = int (pwndbg.memory.poi(pwndbg.typeinfo.ppvoid, address)) address &= pwndbg.arch.ptrmask except gdb.MemoryError: break return result
世界终于正常了.
但这远远没有结束.既然魔改了,就把之前不爽的地方都魔改一遍好了233333333
首先是heap
命令打印chunk的时候,prevsize和size是十进制打印的,实际比赛中你还得把他转换成hex才有意义…
不过这不是pwndbg的错,因为gdb print malloc_chunk的时候就是这样打印的(真的怪
通过修改pwndbg/chain.py
中malloc_chunk
实现.
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 @pwndbg.commands.ParsedCommand @pwndbg.commands.OnlyWhenRunning def malloc_chunk (addr ): """ Prints out the malloc_chunk at the specified address. """ main_heap = pwndbg.heap.current if not isinstance (addr, six.integer_types): addr = int (addr) chunk = read_chunk(addr) size = int (chunk['size' ]) actual_size = size & ~7 prev_inuse, is_mmapped, non_main_arena = main_heap.chunk_flags(size) arena = None if non_main_arena: arena = main_heap.get_heap(addr)['ar_ptr' ] fastbins = main_heap.fastbins(arena) header = M.get(addr) if prev_inuse: if actual_size in fastbins: header += message.hint(' FASTBIN' ) else : header += message.hint(' PREV_INUSE' ) if is_mmapped: header += message.hint(' IS_MMAPED' ) if non_main_arena: header += message.hint(' NON_MAIN_ARENA' ) chunk_str='{\n' for key in chunk["value" ].type .keys(): chunk_str+=' %s = %s,\n' %(str (key),hex (int (chunk["value" ][key]))) chunk_str+='}' print (header, chunk_str) return chunk
实际效果:
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 pwndbg> heap Top Chunk: 0x113c0c0 Last Remainder: 0 0x113c000 FASTBIN { prev_size = 0x0, size = 0x61, fd = 0x113c060, bk = 0x0, fd_nextsize = 0x0, bk_nextsize = 0x0, } 0x113c060 FASTBIN { prev_size = 0x0, size = 0x61, fd = 0x113c000, bk = 0x0, fd_nextsize = 0x0, bk_nextsize = 0x0, } 0x113c0c0 PREV_INUSE { prev_size = 0x0, size = 0x20f41, fd = 0x0, bk = 0x0, fd_nextsize = 0x0, bk_nextsize = 0x0, }
其次,我认为pwndbg自带的find_fake_fast
太鸡肋了,一是要输入你指定的大小,二是还经常无故爆炸,三是还有bug
为此我添加了这样一个commands
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 @pwndbg.commands.ParsedCommand @pwndbg.commands.OnlyWhenRunning def fake_fastbin_all (addr ): """ Finds candidate fake fast chunks that will overlap with the specified address. Used for fastbin dups and house of spirit """ main_heap = pwndbg.heap.current max_fast = main_heap.global_max_fast max_idx = main_heap.fastbin_index(max_fast) start = int (addr) - int (max_fast) mem = pwndbg.memory.read(start, max_fast, partial=True ) fmt = { 'little' : '<' , 'big' : '>' }[pwndbg.arch.endian] + { 4 : 'I' , 8 : 'Q' }[pwndbg.arch.ptrsize] print (C.banner("FAKE CHUNKS" )) for idx in range (max_idx +1 ): if pwndbg.arch.ptrsize == 8 : print (message.hint(hex ((idx+2 )<<4 ))+": " ) else : print (message.hint(hex ((idx+2 )<<3 ))+": " ) for offset in range (max_fast - pwndbg.arch.ptrsize): candidate = mem[offset:offset + pwndbg.arch.ptrsize] if len (candidate) == pwndbg.arch.ptrsize: value = struct.unpack(fmt, candidate)[0 ] if main_heap.fastbin_index(value&0xffffffff ) == idx: print ('[+]' ,hex (start+offset-pwndbg.arch.ptrsize),', padding len:' ,hex (int (addr)-start-offset-pwndbg.arch.ptrsize))
这个命令只要你提供地址,就能打印出所有可行的fake chunk
效果如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 pwndbg> p &__malloc_hook $1 = (void *(**)(size_t, const void *)) 0x7f690516ab10 <__malloc_hook> pwndbg> fake_fastbin_all 0x7f690516ab10 FAKE CHUNKS 0x20: 0x30: 0x40: 0x50: 0x60: 0x70: [+] 0x7f690516aaed , padding len: 0x13 [+] 0x7f690516aafd , padding len: 0x3 0x80: pwndbg> hex 0x7f690516aaed +0000 0x7f690516aaed 00 00 00 60 92 16 05 69 7f 00 00 00 00 00 00 00 │...`│...i│....│....│ +0010 0x7f690516aafd 00 00 00 20 be e2 04 69 7f 00 00 00 ba e2 04 69 │....│...i│....│...i│ +0020 0x7f690516ab0d 7f 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │....│....│....│....│ +0030 0x7f690516ab1d 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │....│....│....│....│