这道题是hctf2016年“就是干”那道题。附件有下载地址及writeup。我就是分析一下:
首先IDA分析一下:
新建两个结构体
00000000 str_struct struc ; (sizeof=0x20)
00000000 str dq ?
00000008 str_padding dq ?
00000010 size dq ?
00000018 free_func dq ?
00000020 str_struct ends
00000020
00000000 ; ---------------------------------------------------------------------------
00000000
00000000 str_list struc ; (sizeof=0x10) ; XREF: .bss:string_listr
00000000 flag dq ?
00000008 str_ptr dq ?
00000010 str_list ends
这两个结构体非常重要了,涉及到后边堆的利用,首先介绍一下第一个结构体str_struct吧,大小是0x20,当要保存的字符串大小小于0xf 时,字符串就保存在0x0-0xf处,当保存的字符串大小大于0xf时,0x0-0x8保存一个指针,指向字符串的地址。 0x10-0x17表示字符串的大小,0x18-0x1f表示free函数的地址。
再介绍一下str_list结构体,当创建string时,置flag=1,当delete string,置flag=0,str-ptr指向str_struct结构体。
然后我把IDA的伪代码贴出来,方便以后分析:
__int64 create_string()
{
signed int i; // [sp+4h] [bp-102Ch]@12
str_struct *string_struct; // [sp+8h] [bp-1028h]@1
char *dest; // [sp+10h] [bp-1020h]@8
unsigned __int64 nbytes; // [sp+18h] [bp-1018h]@1
unsigned __int64 nbytesa; // [sp+18h] [bp-1018h]@6
char buf; // [sp+20h] [bp-1010h]@3
__int64 canary; // [sp+1028h] [bp-8h]@1
canary = *MK_FP(__FS__, 40LL);
string_struct = (str_struct *)malloc(0x20uLL);
printf("Pls give string size:");
nbytes = read_int();
if ( nbytes <= 0x1000 )
{
printf("str:");
if ( read(0, &buf, nbytes) == -1 )
{
puts("got elf!!");
exit(1);
}
nbytesa = strlen(&buf);
if ( nbytesa > 0xF )
{
dest = (char *)malloc(nbytesa);
if ( !dest )
{
puts("malloc faild!");
exit(1);
}
strncpy(dest, &buf, nbytesa);
string_struct->str = (__int64)dest;
string_struct->free_func = (__int64)free_2;
}
else
{
strncpy((char *)string_struct, &buf, nbytesa);
string_struct->free_func = (__int64)free_1;
}
LODWORD(string_struct->size) = nbytesa;
for ( i = 0; i <= 15; ++i )
{
if ( !LODWORD(string_list[i].flag) )
{
LODWORD(string_list[i].flag) = 1;
string_list[i].str_ptr = (__int64)string_struct;
printf("The string id is %d\n", (unsigned int)i);
break;
}
}
if ( i == 16 )
{
puts("The string list is full");
((void (__fastcall *)(str_struct *))string_struct->free_func)(string_struct);
}
}
else
{
puts("Invalid size");
free(string_struct);
}
return *MK_FP(__FS__, 40LL) ^ canary;
}
__int64 delete_string()
{
int sid; // [sp+Ch] [bp-114h]@1
char buf; // [sp+10h] [bp-110h]@5
__int64 v3; // [sp+118h] [bp-8h]@1
v3 = *MK_FP(__FS__, 40LL);
printf("Pls give me the string id you want to delete\nid:");
sid = read_int();
if ( sid < 0 || sid > 16 )
puts("Invalid id");
if ( string_list[sid].str_ptr )
{
printf("Are you sure?:");
read(0, &buf, 0x100uLL);
if ( !strncmp(&buf, "yes", 3uLL) )
{
(*(void (__fastcall **)(_