调教pwndbg

最近由于某些原因,更新了一下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
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
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
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
0x60: 0x7ffff7dd1bc8 (main_arena+168) ◂— 0x7ffff7dd1bc8
0x70: 0x7ffff7dd1bd8 (main_arena+184) ◂— 0x7ffff7dd1bd8
0x80: 0x7ffff7dd1be8 (main_arena+200) ◂— 0x7ffff7dd1be8
0x90: 0x7ffff7dd1bf8 (main_arena+216) ◂— 0x7ffff7dd1bf8
0xa0: 0x7ffff7dd1c08 (main_arena+232) ◂— 0x7ffff7dd1c08
0xb0: 0x7ffff7dd1c18 (main_arena+248) ◂— 0x7ffff7dd1c18
0xc0: 0x7ffff7dd1c28 (main_arena+264) ◂— 0x7ffff7dd1c28
0xd0: 0x7ffff7dd1c38 (main_arena+280) ◂— 0x7ffff7dd1c38
0xe0: 0x7ffff7dd1c48 (main_arena+296) ◂— 0x7ffff7dd1c48
0xf0: 0x7ffff7dd1c58 (main_arena+312) ◂— 0x7ffff7dd1c58
0x100: 0x7ffff7dd1c68 (main_arena+328) ◂— 0x7ffff7dd1c68
0x110: 0x7ffff7dd1c78 (main_arena+344) ◂— 0x7ffff7dd1c78
0x120: 0x7ffff7dd1c88 (main_arena+360) ◂— 0x7ffff7dd1c88
0x130: 0x7ffff7dd1c98 (main_arena+376) ◂— 0x7ffff7dd1c98
0x140: 0x7ffff7dd1ca8 (main_arena+392) ◂— 0x7ffff7dd1ca8
0x150: 0x7ffff7dd1cb8 (main_arena+408) ◂— 0x7ffff7dd1cb8
0x160: 0x7ffff7dd1cc8 (main_arena+424) ◂— 0x7ffff7dd1cc8
0x170: 0x7ffff7dd1cd8 (main_arena+440) ◂— 0x7ffff7dd1cd8
0x180: 0x7ffff7dd1ce8 (main_arena+456) ◂— 0x7ffff7dd1ce8
0x190: 0x7ffff7dd1cf8 (main_arena+472) ◂— 0x7ffff7dd1cf8
0x1a0: 0x7ffff7dd1d08 (main_arena+488) ◂— 0x7ffff7dd1d08
0x1b0: 0x7ffff7dd1d18 (main_arena+504) ◂— 0x7ffff7dd1d18
0x1c0: 0x7ffff7dd1d28 (main_arena+520) ◂— 0x7ffff7dd1d28
0x1d0: 0x7ffff7dd1d38 (main_arena+536) ◂— 0x7ffff7dd1d38
0x1e0: 0x7ffff7dd1d48 (main_arena+552) ◂— 0x7ffff7dd1d48
0x1f0: 0x7ffff7dd1d58 (main_arena+568) ◂— 0x7ffff7dd1d58
0x200: 0x7ffff7dd1d68 (main_arena+584) ◂— 0x7ffff7dd1d68
0x210: 0x7ffff7dd1d78 (main_arena+600) ◂— 0x7ffff7dd1d78
0x220: 0x7ffff7dd1d88 (main_arena+616) ◂— 0x7ffff7dd1d88
0x230: 0x7ffff7dd1d98 (main_arena+632) ◂— 0x7ffff7dd1d98
0x240: 0x7ffff7dd1da8 (main_arena+648) ◂— 0x7ffff7dd1da8
0x250: 0x7ffff7dd1db8 (main_arena+664) ◂— 0x7ffff7dd1db8
0x260: 0x7ffff7dd1dc8 (main_arena+680) ◂— 0x7ffff7dd1dc8
0x270: 0x7ffff7dd1dd8 (main_arena+696) ◂— 0x7ffff7dd1dd8
0x280: 0x7ffff7dd1de8 (main_arena+712) ◂— 0x7ffff7dd1de8
0x290: 0x7ffff7dd1df8 (main_arena+728) ◂— 0x7ffff7dd1df8
0x2a0: 0x7ffff7dd1e08 (main_arena+744) ◂— 0x7ffff7dd1e08
0x2b0: 0x7ffff7dd1e18 (main_arena+760) ◂— 0x7ffff7dd1e18
0x2c0: 0x7ffff7dd1e28 (main_arena+776) ◂— 0x7ffff7dd1e28
0x2d0: 0x7ffff7dd1e38 (main_arena+792) ◂— 0x7ffff7dd1e38
0x2e0: 0x7ffff7dd1e48 (main_arena+808) ◂— 0x7ffff7dd1e48
0x2f0: 0x7ffff7dd1e58 (main_arena+824) ◂— 0x7ffff7dd1e58
0x300: 0x7ffff7dd1e68 (main_arena+840) ◂— 0x7ffff7dd1e68
0x310: 0x7ffff7dd1e78 (main_arena+856) ◂— 0x7ffff7dd1e78
0x320: 0x7ffff7dd1e88 (main_arena+872) ◂— 0x7ffff7dd1e88
0x330: 0x7ffff7dd1e98 (main_arena+888) ◂— 0x7ffff7dd1e98
0x340: 0x7ffff7dd1ea8 (main_arena+904) ◂— 0x7ffff7dd1ea8
0x350: 0x7ffff7dd1eb8 (main_arena+920) ◂— 0x7ffff7dd1eb8
0x360: 0x7ffff7dd1ec8 (main_arena+936) ◂— 0x7ffff7dd1ec8
0x370: 0x7ffff7dd1ed8 (main_arena+952) ◂— 0x7ffff7dd1ed8
0x380: 0x7ffff7dd1ee8 (main_arena+968) ◂— 0x7ffff7dd1ee8
0x390: 0x7ffff7dd1ef8 (main_arena+984) ◂— 0x7ffff7dd1ef8
0x3a0: 0x7ffff7dd1f08 (main_arena+1000) ◂— 0x7ffff7dd1f08
0x3b0: 0x7ffff7dd1f18 (main_arena+1016) ◂— 0x7ffff7dd1f18
0x3c0: 0x7ffff7dd1f28 (main_arena+1032) ◂— 0x7ffff7dd1f28
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
0x540: 0x7ffff7dd1fb8 (main_arena+1176) ◂— 0x7ffff7dd1fb8
0x580: 0x7ffff7dd1fc8 (main_arena+1192) ◂— 0x7ffff7dd1fc8
0x5c0: 0x7ffff7dd1fd8 (main_arena+1208) ◂— 0x7ffff7dd1fd8
0x600: 0x7ffff7dd1fe8 (main_arena+1224) ◂— 0x7ffff7dd1fe8
0x640: 0x7ffff7dd1ff8 (main_arena+1240) ◂— 0x7ffff7dd1ff8
0x680: 0x7ffff7dd2008 (main_arena+1256) ◂— 0x7ffff7dd2008
0x6c0: 0x7ffff7dd2018 (main_arena+1272) ◂— 0x7ffff7dd2018
0x700: 0x7ffff7dd2028 (main_arena+1288) ◂— 0x7ffff7dd2028
0x740: 0x7ffff7dd2038 (main_arena+1304) ◂— 0x7ffff7dd2038
0x780: 0x7ffff7dd2048 (main_arena+1320) ◂— 0x7ffff7dd2048
0x7c0: 0x7ffff7dd2058 (main_arena+1336) ◂— 0x7ffff7dd2058
0x800: 0x7ffff7dd2068 (main_arena+1352) ◂— 0x7ffff7dd2068
0x840: 0x7ffff7dd2078 (main_arena+1368) ◂— 0x7ffff7dd2078
0x880: 0x7ffff7dd2088 (main_arena+1384) ◂— 0x7ffff7dd2088
0x8c0: 0x7ffff7dd2098 (main_arena+1400) ◂— 0x7ffff7dd2098
0x900: 0x7ffff7dd20a8 (main_arena+1416) ◂— 0x7ffff7dd20a8
0x940: 0x7ffff7dd20b8 (main_arena+1432) ◂— 0x7ffff7dd20b8
0x980: 0x7ffff7dd20c8 (main_arena+1448) ◂— 0x7ffff7dd20c8
0x9c0: 0x7ffff7dd20d8 (main_arena+1464) ◂— 0x7ffff7dd20d8
0xa00: 0x7ffff7dd20e8 (main_arena+1480) ◂— 0x7ffff7dd20e8
0xa40: 0x7ffff7dd20f8 (main_arena+1496) ◂— 0x7ffff7dd20f8
0xa80: 0x7ffff7dd2108 (main_arena+1512) ◂— 0x7ffff7dd2108
0xac0: 0x7ffff7dd2118 (main_arena+1528) ◂— 0x7ffff7dd2118
0xb00: 0x7ffff7dd2128 (main_arena+1544) ◂— 0x7ffff7dd2128
0xb40: 0x7ffff7dd2138 (main_arena+1560) ◂— 0x7ffff7dd2138
0xb80: 0x7ffff7dd2148 (main_arena+1576) ◂— 0x7ffff7dd2148
0xbc0: 0x7ffff7dd2158 (main_arena+1592) ◂— 0x7ffff7dd2158
0xc00: 0x7ffff7dd2168 (main_arena+1608) ◂— 0x7ffff7dd2168
0xc40: 0x7ffff7dd2178 (main_arena+1624) ◂— 0x7ffff7dd2178
0xe00: 0x7ffff7dd2188 (main_arena+1640) ◂— 0x7ffff7dd2188
0x1000: 0x7ffff7dd2198 (main_arena+1656) ◂— 0x7ffff7dd2198
0x1200: 0x7ffff7dd21a8 (main_arena+1672) ◂— 0x7ffff7dd21a8
0x1400: 0x7ffff7dd21b8 (main_arena+1688) ◂— 0x7ffff7dd21b8
0x1600: 0x7ffff7dd21c8 (main_arena+1704) ◂— 0x7ffff7dd21c8
0x1800: 0x7ffff7dd21d8 (main_arena+1720) ◂— 0x7ffff7dd21d8
0x1a00: 0x7ffff7dd21e8 (main_arena+1736) ◂— 0x7ffff7dd21e8
0x1c00: 0x7ffff7dd21f8 (main_arena+1752) ◂— 0x7ffff7dd21f8
0x1e00: 0x7ffff7dd2208 (main_arena+1768) ◂— 0x7ffff7dd2208
0x2000: 0x7ffff7dd2218 (main_arena+1784) ◂— 0x7ffff7dd2218
0x2200: 0x7ffff7dd2228 (main_arena+1800) ◂— 0x7ffff7dd2228
0x2400: 0x7ffff7dd2238 (main_arena+1816) ◂— 0x7ffff7dd2238
0x2600: 0x7ffff7dd2248 (main_arena+1832) ◂— 0x7ffff7dd2248
0x2800: 0x7ffff7dd2258 (main_arena+1848) ◂— 0x7ffff7dd2258
0x2a00: 0x7ffff7dd2268 (main_arena+1864) ◂— 0x7ffff7dd2268
0x3000: 0x7ffff7dd2278 (main_arena+1880) ◂— 0x7ffff7dd2278
0x4000: 0x7ffff7dd2288 (main_arena+1896) ◂— 0x7ffff7dd2288
0x5000: 0x7ffff7dd2298 (main_arena+1912) ◂— 0x7ffff7dd2298
0x6000: 0x7ffff7dd22a8 (main_arena+1928) ◂— 0x7ffff7dd22a8
0x7000: 0x7ffff7dd22b8 (main_arena+1944) ◂— 0x7ffff7dd22b8
0x8000: 0x7ffff7dd22c8 (main_arena+1960) ◂— 0x7ffff7dd22c8
0x9000: 0x7ffff7dd22d8 (main_arena+1976) ◂— 0x7ffff7dd22d8
0xa000: 0x7ffff7dd22e8 (main_arena+1992) ◂— 0x7ffff7dd22e8
0x10000: 0x7ffff7dd22f8 (main_arena+2008) ◂— 0x7ffff7dd22f8
0x18000: 0x7ffff7dd2308 (main_arena+2024) ◂— 0x7ffff7dd2308
0x20000: 0x7ffff7dd2318 (main_arena+2040) ◂— 0x7ffff7dd2318
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.pyget的代码

修改后代码如下

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 = [address]
result = [] ##patch 1
for i in range(limit):
# Don't follow cycles, except to stop at the second occurrence.
if result.count(address) >= 2:
break
if hard_stop is not None and address == hard_stop:
result.append(hard_end)
break
result.append(address) ##patch 2
try:
address = address + offset
# Avoid redundant dereferences in bare metal mode by checking
# if address is in any of vmmap pages
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
##result.append(address) ##patch 3
except gdb.MemoryError:
break
return result

世界终于正常了.
















































但这远远没有结束.既然魔改了,就把之前不爽的地方都魔改一遍好了233333333

首先是heap命令打印chunk的时候,prevsize和size是十进制打印的,实际比赛中你还得把他转换成hex才有意义…

不过这不是pwndbg的错,因为gdb print malloc_chunk的时候就是这样打印的(真的怪

通过修改pwndbg/chain.pymalloc_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')
## edit start
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)
## edit end
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 │....│....│....│....│