首页
社区
课程
招聘
[原创]Asis CTF 2016 b00ks WP
发表于: 2024-2-17 02:09 12492

[原创]Asis CTF 2016 b00ks WP

2024-2-17 02:09
12492

环境:ubuntu16.04 glibc版本:2.23

按照惯例用checksec查看下保护 image.png

可以看到除了canary保护,其余保护全开 再用IDA进行代码审计

main函数

为了后续的代码审计,我这里给函数名都自定义了一个名字。 前几行代码定义了几个变量,然后关闭了缓冲区。 后面调用各种函数,然后进入while循环。 整个main函数没什么好看的。

welcome函数

打印了一行字,也没啥好看的

author_name函数

主要功能是往off_202018写入大小不超过32的数据 这里注意off_202018是在bss段的

my_read(_BYTE *a1, int a2)函数

开始定义了一个变量i 然后进入if语句,判断a2(也可以理解为输入大小)是否合法,不合法即返回0 接着进入循环语句: 第一个if:每次往a1中写入一个字节,读取失败则返回1 第二个if:判断当前是否为换行符,10 == \x0a =='\n' 然后自增a1 最后判断是否读完,然后结束循环 循环结束后,将a1最后一个字节设为0,最后返回0

menu函数

普普通通的一个菜单

create函数

定义了几个变量: v1,存name和description的size *ptr,name所在chunk的指针 v5,description所在chunk的指针 v3,整个book所在chunk的指针 v2,可以理解为book数组的索引 整个函数流程就是:写入name_size -> 写入name -> 写入description_size -> 写入description -> 最后把id name指针 description指针 description大小写入到books结构体中 注意,这里存book数组的指针为off_202010,与off_202018(即author_name)刚好相距0x20 所以当author_name大小刚好为0x20时,会溢出到off_202010存在off-by-one漏洞,因为最后溢出了一个'\x00'

edit函数

先写入函数id 如果id大于0,循环book数组,找到id对应的书, 如果i == 20,就报错,说明整个book数组最多可以存20个book结构体,否则覆写之前的description

print函数

主要功能就是打印所有book数组中的book结构体的信息

到这里代码审计就先暂停一下,理一下思路 回顾create函数,其通过malloc来创建name和description和book结构体对应的chunk,因此他们的地址都是有一定关系的,而author_name又会把book结构体所在地址低两位用'\x00'给覆盖, 所以我们可以在写完author_name后,创建一个book结构体,然后通过print函数把结构体在堆中的地址给打印出来,达到泄露堆地址的目的 再接着调用author_name函数,再次把第一个book结构体的低两位给覆盖 因为name description book结构体之间的地址都是有关系的,因此我们可以控制malloc的大小,让description的后两位变成'\x00' 最重要的是这里又给了修改description的功能,所以我们就可以通过修改某一个book结构体的description,伪造一个book结构体,达到任意写地址的目的。

解题思路:通过_free_hook来获取shell __free_hook可以在free前或者free后执行一些我们想要执行的函数,比如system("/bin/sh") 既然是利用__free_hook,那就必须得先获取libc基地址,我们从第一步开始

先往author_name写入0x20个字符,然后创建一个book结构体,再print该结构体信息,达到泄露堆地址的目的

image.png 具体的malloc大小得自己测试,不一定是我这个数字,可能环境的原因吧

创建一个由mmap分配空间的堆,因为mmap创建的堆的地址和libc地址的偏移是固定的

mmap阈值,可以在glibc中的malloc.c中找到

修改s1的description,伪造一个结构体,使其name和description指向s2的name,然后打印泄露mmap地址

image.png

使用vmmap命令查看libc基地址,计算mmap与其偏移

image.png 偏移 = 0x7f2caba03010 - 0x00007f2cab451000 基地址 = mmap地址 - 偏移

获取system、/bin/sh和__free_hook地址

修改s1的description为"bin/sh"和"__free_hook"的地址,达到间接修改s2的name和description的目的。

修改s2的description为"system"的地址,使得在free之前,执行system("/bin/sh")

image.png


__int64 __fastcall main(int a1, char **a2, char **a3)
{
 struct _IO_FILE *v3; // rdi
 int v5; // [rsp+1Ch] [rbp-4h]

 setvbuf(stdout, 0LL, 2, 0LL);
 v3 = stdin;
 setvbuf(stdin, 0LL, 1, 0LL);
 welcome();
 author_name();
 while ( 1 )
 {
   v5 = menu();
   if ( v5 == 6 )
     break;
   switch ( v5 )
   {
     case 1:
       create();
       break;
     case 2:
       delete(v3);
       break;
     case 3:
       edit(v3);
       break;
     case 4:
       print();
       break;
     case 5:
       author_name();
       break;
     default:
       v3 = (struct _IO_FILE *)"Wrong option";
       puts("Wrong option");
       break;
   }
 }
 puts("Thanks to use our library software");
 return 0LL;
}
int welcome()
{
 return puts("Welcome to ASISCTF book library");
}
__int64 sub_B6D()
{
 printf("Enter author name: ");
 if ( !(unsigned int)my_read(off_202018, 32LL) )
   return 0LL;
 printf("fail to read author_name");
 return 1LL;
}
__int64 __fastcall my_read(_BYTE *a1, int a2)
{
 int i; // [rsp+14h] [rbp-Ch]

 if ( a2 <= 0 )
   return 0LL;
 for ( i = 0; ; ++i )
 {
   if ( (unsigned int)read(0, a1, 1uLL) != 1 )
     return 1LL;
   if ( *a1 == 10 )
     break;
   ++a1;
   if ( i == a2 )
     break;
 }
 *a1 = 0;
 return 0LL;
}
__int64 sub_A89()
{
 int v1; // [rsp+Ch] [rbp-4h] BYREF

 v1 = -1;
 puts("\n1. Create a book");
 puts("2. Delete a book");
 puts("3. Edit a book");
 puts("4. Print book detail");
 puts("5. Change current author name");
 puts("6. Exit");
 printf("> ");
 __isoc99_scanf("%d", &v1);
 if ( v1 <= 6 && v1 > 0 )
   return (unsigned int)v1;
 else
   return 0xFFFFFFFFLL;
}

[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

最后于 2024-11-24 10:21 被mick0960编辑 ,原因: 添加了代码语言
收藏
免费 2
支持
分享
最新回复 (1)
雪    币: 29187
活跃值: (63432)
能力值: (RANK:135 )
在线值:
发帖
回帖
粉丝
2
建议附件也上传一份
2024-2-20 18:19
0
游客
登录 | 注册 方可回帖
返回
//