Page cover

🤕ret2libc

Challenge

Ở thử thách này, tôi chỉ nhận được file libc.so.6.

Và 2 file docker để chạy môi trường trên máy của mình.

Chạy file buildnrun.sh để setup môi trường.

Netcat vào môi trường này

==> Tôi đã ghi đè 40 byte để có thể xảy ra lỗi *** stack smashing detected ***.

Overview

Tôi sẽ nói qua về lỗi này 1 chút trước khi bắt đầu phân tích bài này. Tôi có chương trình cơ bản sau:

+ Phần mũi tên màu xanh chính là canary vì canary thường có byte \x00 ở cuối

+ Phần mũi tên màu vàng có thể là giá trị 0x1 hoặc giá trị 0x0

+ Ngay bên dưới nó là __libc_start_call_main nếu ret ở hàm main.

+ Bên dưỡi nó nữa là 1 byte null

+ Và bên dưới byte null nó là địa chỉ của hàm main().

Khi mà ta ghi đè lên canary thì lỗi này sẽ xảy ra. Mà giá trị canary chỉ xuất hiện khi stack-protector được bật. Vậy nên, bạn có thể đoán được luôn rằng chương trình bên trên cũng được bật stack giống như chương trình này.

Vậy kĩ thuật bypass Canary là cần thiết :>>

Script

Quay trở lại vấn đề chính. Một câu hỏi đặt ra đó là làm thế nào để có thể bypass được Canary. Thì đơn giản chỉ là gửi 1 payload có chứa giá trị của canary là được. Vậy làm thế nào để biết được giá trị canary đó ?

Bạn chỉ cần làm được 2 việc trên thì mọi chuyện coi như xong

Leak Canary

Trong bước này, ta phải leak từng byte ra ngoài màn hình để chương trình không bị lỗi.

Và giá trị của canary có thể như sau:

Byte cuối cùng có nó luôn là \x00 nên ta phải lặp lại tất cả là 7 lần và ta sẽ thử từ 0x00 --> 0xFF.

Trước tiên tạo khung chương trình đã:

Đây là phần code của tôi để leak được canary theo như logic trên.

Sau khi bạn chạy code trên thì bạn sẽ nhận được canary được leak ra.

Vậy bước tiếp theo là leak địa chỉ ngay sau canary. Có thể là địa chỉ libc hoặc địa chỉ của file binary. Nhưng tôi khá chắc chắn 80% là libc.

Leak LIBC

Bạn hãy nhìn lại phần Overview trước khi làm tiếp.

Ngay sau canary là byte 0x01 (Cái này có thể set 0x0 hoặc 0x1). Và địa chỉ libc.
Payload của tôi có thể là như vậy

Nhưng có 1 vấn đề: Đó là ta không có file binary để lấy các gadget như pop rdi. Nên tôi sẽ phải leak được địa chỉ libc để có thể lấy được các gadget ở file libc.so.6.

Vậy giờ lấy như nào?

triangle-exclamation

Nếu leak từng byte của 1 địa chỉ libc thì ta cần tất cả (6-1) lần thực hiện. Vì 1 địa chỉ thường chiếm 6 bytes. Mà ta đã đoán được 1,5 bytes của địa chỉ đó rồi. (thực ra là 2,5 bytes - tính cả byte 0x7F).

Vậy tổng lần thực hiện là 5 lần. Lần đầu tiên tôi sẽ xử lí 0,5 byte của bytes thứ 2 trước. (Làm tương tự như với canary)

Đây là phần code mà tôi sẽ lấy 2 byte cuối cùng của địa chỉ libc.

Tiếp theo tôi sẽ xử lí 4 bytes tiếp theo.

Có vẻ như là chính xác rồi

Bạn có thể thêm đoạn này vào chương trình:

Để nó in ra như thế này:

Libc Base

Sau khi leak được địa chỉ của libc thì tôi sẽ đi tìm libc base. Và các rop_gadget của file libc đó.

Số liệu kia tôi lấy từ file elf ở phần overview gồm libc base và __libc_start_...

Get Shell

Phần này làm tương tự như các bài khác:

Okii, vậy đã khai thác thành công:

Full Payload

Last updated