Page cover

Buffer Overflow Prep

Vietnamese version

Prepare

Trước khi đọc bài này, tôi nghĩ bạn nên có kiến thức nền về Buffer Overflow trên OS Linux, vì nó khá dễ, Đối với Windows nó phức tạp hơn 1 chút. Hmm, dù sao thì bạn nên học từ dễ đến khó để đạt được hiệu suất tối ưu nhất

Connect Machine bằng Remote Desktop Connection (credential: admin/password)

Some Binaries:

  • The SLMail installer.

  • The brainpan binary.

  • The dostackbufferoverflowgood binary.

  • The vulnserver binary.

  • A custom written "oscp" binary which contains 10 buffer overflows, each with a different EIP offset and set of badchars.

Guide for Exploiting Buffer Overflow: http://github.com/Tib3rius/Pentest-Cheatsheets/blob/master/exploits/buffer-overflows.rst

Machine này sẽ ôn luyện cho các bro ôn thi OSCP, nhưng tôi không có tiền thi nên tôi sẽ explorer nó hết mức có thể :>>

Quy trình cho exploit:

  • Fuzzing

  • Control EIP

  • Finding JMP ESP gadget

  • Finding Bad Chars

  • Generate Shellcode

  • Exploitation

Từng quy trình tôi sẽ làm rõ bên dưới:

Overflow 1

Đầu tiên, Tôi sẽ run oscp.exe với Immunity Debugger và đây là Output

Netcat đến IP của machine và port 1337.

Fuzzing

Tôi sử dụng script python sau để fuzzing buffer

Sau khi chạy script và sending payload thì màn hình Remote sẽ như sau:

Chú ý vào thanh status sẽ thấy rằng chương trình bị crash do địa chỉ EIP không được xác định

Controlling EIP

Tôi sử dụng script này để tìm ra chính xác padding đến EIP:

Output:

Sau khi chạy, ta có value của EIP là: 0x61757461. Sử dụng cyclic để tìm ra padding:

Sau khi đã biết chính xác padding để ghi đè đến EIP, tôi sẽ thay thế nó bằng 1 address JMP ESP.

Finding Bad Chars

Việc tìm bad chars để xem kí tự nào là kí tự sẽ bị thay đổi bởi chương trình. Khi các bad char được gửi lên server nó sẽ được thay thế bằng cặp từ \x0D\x0A (tức \r\n - cặp giá trị kết thúc dòng trong Windows). Từ đó ta có thể loại bỏ các kí tự đó trong shellcode của mình, không gây ra hỏng Shellcode.

Phạm vi của ASCII Table: từ 0 -> 256 nhưng tôi sẽ không gửi byte \x00 lên vì nó sẽ gây ra terminate chuỗi :>> nên sẽ loại luôn kí tự từ đầu.

Ta có thể thấy payload đã được thay đổi từ byte \x07 -> Bad char:

Remove nó khỏi mảng bad_char:

Làm tương tự với các byte tiếp theo:

Ta sẽ có list bad char: \x07, \x2e, \xa0.

Hoặc ta sẽ sử dụng command sau:

Mona sẽ gen cho tôi 1 file bin tại vị trí:

Sử dụng tệp này để so sánh với phần pattern bad chars:

Trong đó address là địa chỉ bắt đầu từ chuỗi \x01\x02\x03\....\xFF

Đây là output:

Ảnh tượng trưng...

Finding JMP ESP gadget

Sau khi tôi tìm được các badchar thì tôi sẽ tìm các jump point trên memory của chương trình bằng command sau:

Nếu khi bạn enter thì của sổ Log Data sẽ hiện ra như sau:

Có thể thấy nó load lên các gadget từ Lib: essfunc.dll

Thì ta có tổng là 9 jump point. Bạn có thể pick bừa 1 cái để làm jump point

Chú ý dòng sau:

Giải thích dòng trên:
  • 0x625011f7: Đây là địa chỉ bộ nhớ trong process của chương trình, nơi tìm thấy lệnh jmp esp

  • {PAGE_EXECUTE_READ}: Phân vùng bộ nhớ này có thể đọc và thực thi được

  • [essfunc.dll]: thư viện DLL chứa lệnh jmp esp tại địa chỉ 0x625011f7

  • Trạng thái các cơ chế bảo vệ:

    • ASLR: False -> địa chỉ của essfunc.dll không thay đổi mỗi lần chương trình chạy.

    • Rebase: False -> địa chỉ sẽ không thay đổi address base của nó sau mỗi lần chạy.

    • SafeSEH: False -> DLL này không có danh sách các exception handlers an toàn. Điều này có thể giúp ta ghi đè SEH handler nếu muốn exploit SEH

    • OS: False -> DLL này không phải DLL của hệ điều hành Windows. Tức nó có thể bị khai thác dễ hơn các thư viện: ntdll.dll, kernel32.dll.

Quay trở lại CPU Windows: Windows > CPU - main thread, module oscp

Generate Shellcode

Bây giờ ta sẽ có viễn cảnh khai thác như sau:

Nếu Stack chứa shellcode thì sau khi JMP ESP, shellcode sẽ được thực thi

Tôi sẽ gen shellcode reverse shell bằng Metasploit như sau:

Sau khi gửi payload lên server ta có thể thấy shellcode đã bị ảnh hưởng:

Tính từ JMP ESP đến phần không bị ảnh hưởng là: 0x194FA40 - 0x194FA24 = 28 byte

Tôi sẽ padding với NOP operator: \x90

Đây chính là các NOP byte mà tôi đã chèn vào.

Final payload:

Done:

Overflow 2

Sau khi làm xong bài 1 thì tôi sẽ làm tiếp bài 2. Nhưng tôi sẽ không giải thích nhiều nữa nếu không có gì thay đổi với bài trước

Crash at 800 bytes:

Tôi sẽ tìm ra chính xác vị trí nó với cyclic:

Pattern tại thanh ghi EIP:

Có vẻ 634 là giá trị offset chính xác đến EIP. Ở dưới đây bạn thấy rằng \x0A\x0D là vì payload tôi gửi lên là bad chars (Giữa 256 kí tự, tôi lại chọn đúng kí tự badchars 🤡)

Sau 1 hồi tôi tìm được 5 bad chars:

Done:

Do kĩ thuật khai thác ở bài lab này tương tự nhau nên tôi sẽ chỉ làm những bước quan trọng nhất để chuẩn bị cho việc khai thác.

Overflow 3

Overflow 4

Overflow 5

Overflow 6

Overflow 7

Overflow 8

Overflow 9

Overflow 10

Last updated

Was this helpful?