axb_2019_fmt32
axb_2019_fmt32
Involved Knowledge
- format string
Checksec
Arch: i386-32-little
RELRO: Partial RELRO
Stack: No canary found
NX: NX enabled
PIE: No PIE (0x8048000)
Program
Hello,I am a computer Repeater updated.
After a lot of machine learning,I know that the essence of man is a reread machine!
So I'll answer whatever you say!
Please tell me:123
Repeater:123
Analyze
main
int __cdecl __noreturn main(int argc, const char **argv, const char **envp)
{
char s[257]; // [esp+Fh] [ebp-239h] BYREF
char format[300]; // [esp+110h] [ebp-138h] BYREF
unsigned int v5; // [esp+23Ch] [ebp-Ch]
v5 = __readgsdword(0x14u);
setbuf(stdout, 0);
setbuf(stdin, 0);
setbuf(stderr, 0);
puts(
"Hello,I am a computer Repeater updated.\n"
"After a lot of machine learning,I know that the essence of man is a reread machine!");
puts("So I'll answer whatever you say!");
while ( 1 )
{
alarm(3u);
memset(s, 0, sizeof(s));
memset(format, 0, sizeof(format));
printf("Please tell me:");
read(0, s, 256u);
sprintf(format, "Repeater:%s\n", s);
if ( strlen(format) > 0x10E )
break;
printf(format);
}
printf("what you input is really long!");
exit(0);
}
这里注意程序定义s变量时的大小和通过read去接收的大小是不足以形成stackoverflow这个漏洞的
char s[257];
read(0 , s , 256u);
同时这里有一个format string漏洞,我们可以在这里来从栈上泄露或者写入一些东西
sprintf(format, "Repeater:%s\n", s);
Solution 1
观察main函数结构我们可以构造这么一种我们通过format string来泄露出函数真实地址,拿到libc基址,system,然后通过fmtstr_payload将read函数的got表地址改成system,再搭配one_gadget拿到shell
泄露read函数地址
payload = b'a' + p32(read_got) + %8$s
这里因为用户的输入在栈上的偏移为8,这里也就是'a'的偏移为8,那么read的got表地址偏移则为9了,通过%8$s
的方式来泄露read函数的真实地址
拿到read函数真实地址后减去偏移则为libc的基址,本来我是用LibcSearcher来打的,但是无奈libc库不太全,拿到的libc基址有问题,所以手动拿read的地址去找到对应的libc版本
下一步就是找对应的gadgets了
[0x3a80c , 0x3a80e , 0x3a812 , 0x3a819 , 0x5f065 , 0x5f066]
这道题的话0x3a812能打通
其他solution后续进行补充