这个题是fsb+uaf
int __cdecl main(int argc, const char **argv, const char **envp)
{
unsigned int *v3; // rsi
_QWORD *v4; // rax
unsigned int v6; // [rsp+Ch] [rbp-24h]
__int64 v7; // [rsp+10h] [rbp-20h]
__int64 v8; // [rsp+18h] [rbp-18h]
__int64 v9; // [rsp+20h] [rbp-10h]
setvbuf(stdout, 0LL, 2, 0LL);
setvbuf(stdin, 0LL, 1, 0LL);
o = malloc(0x28uLL);
*((_QWORD *)o + 3) = greetings;
*((_QWORD *)o + 4) = byebye;
printf("hey, what's your name? : ", 0LL);
v3 = (unsigned int *)&v7;
__isoc99_scanf("%24s", &v7);
v4 = o;
*(_QWORD *)o = v7;
v4[1] = v8;
v4[2] = v9;
id = v7;
getchar();
func[0] = (__int64)echo1;
qword_602088 = (__int64)echo2;
qword_602090 = (__int64)echo3;
v6 = 0;
do
{
while ( 1 )
{
while ( 1 )
{
puts("\n- select echo type -");
puts("- 1. : BOF echo");
puts("- 2. : FSB echo");
puts("- 3. : UAF echo");
puts("- 4. : exit");
printf("> ", v3);
v3 = &v6;
__isoc99_scanf("%d", &v6);
getchar();
if ( v6 > 3 )
break;
((void (__fastcall *)(const char *, unsigned int *))func[v6 - 1])("%d", &v6);
}
if ( v6 == 4 )
break;
puts("invalid menu");
}
cleanup();
printf("Are you sure you want to exit? (y/n)", &v6);
v6 = getchar();
}
while ( v6 != 121 );
puts("bye");
return 0;
}
__int64 echo2()
{
char format; // [rsp+0h] [rbp-20h]
(*((void (__fastcall **)(void *))o + 3))(o);
get_input(&format, 32LL);
printf(&format);
(*((void (__fastcall **)(void *))o + 4))(o);
return 0LL;
}
__int64 echo3()
{
char *s; // ST08_8
(*((void (__fastcall **)(void *))o + 3))(o);
s = (char *)malloc(0x20uLL);
get_input(s, 32LL);
puts(s);
free(s);
(*((void (__fastcall **)(void *, signed __int64))o + 4))(o, 32LL);
return 0LL;
}
echo2中存在格式化字符串漏洞可以得到ebp,当我们输入4的时候系统会直接free掉o再问你是否退出,我们可以不退出之后输入3,系统会用刚free掉的o的一部分空间分配一个0x20的堆空间,而o中的o[3]和o[4]是greetings和goodbye函数的指针,我们可以修改goobye的指针,之后我们可以看到name的前八个字节在栈中储存,所以就可以在name中写入shell code。v7的位置是ebp-0x20.
ps:%p:指针(用十六进制打印值的内存地址)。
struct.pack用于将Python的值根据格式符,转换为字符串(因为Python中没有字节(Byte)类型,可以把这里的字符串理解 为字节流,或字节数组)。L表示long八个字节。
strip() 方法用于移除字符串头尾指定的字符(默认为空格或换行符)或字符序列。