🌉Widget - Angstrom2023
Bài này tuy có hàm win nhưng tôi sẽ làm nó theo hướng RCE(remote code execution)
Analysis
Ta có thấy ngay đây là lỗi BufferOverFlow bằng việc tăng size lên kích thước lớn sau đó ta có overflow ra khỏi 24bytes mà chương trình cung cấp cho buf
Và đây là lỗi format strings ta có nhìn thấy bằng mắt thường. Bắt đầu đi vào việc tìm kiếm vùng đất mới thôi nào.
Nhưng mà trước khi đi thì ta cần có bản đồ(script) để đi đúng đường trước:
Trước tiên ta sẽ sử dụng lỗi format strings để tìm ra địa chỉ leak libc (bởi vì trên file
ELF
không tồn tai gadgetpop rdi; ret
) nên tôi mới phải leak địa chỉ libc để lấy các gadget trên libc.Sau đó sẽ dùng Format string để ret2libc. Sau đó lấy shellcode của nó.
Bước 1: Leak libc address.
Trước khi ta bắt đầu vào bài toán, tôi sẽ note lại 1 vài địa chỉ quan trọng:
0x401455 : read(OverFlow)
0x4014c0 : format string
0x4014c7 : return
Địa chỉ tôi khoanh tròn ở trên kia là địa chỉ libc như nó sẽ là địa chỉ ret sẽ gọi tới nên ta không thể dùng đó để leak. Hình dung: Khi tôi overflow đến đó xong chèn các gadget vào thì nó sẽ chẳng thể nào leak ra được vì địa chỉ đó đã bị ghi đè bởi các gadget và nó sẽ leak ra địa chỉ của các gadget như bên dưới:
Vậy nên bạn hãy cẩn thận với nó hơn
.
Cái trên là cái ban đầu bạn nhìn thấy ở ảnh trên cái dưới là cái tôi thấy khi mở rộng stack ra 50.
Có thể thấy nó ở vị trí (0xd8-0x38)/8 = 20
so với cái libc ban đầu. Và bạn có thể dựa vào libc bên trên tính được offset của libc bên dưới: kết quả là nó ở offset thứ 33
.
Như vậy, bạn có thể thấy nó đã đúng :)).
Libc address đã có. Vậy bây giờ ta cần tính toán so với libc_base
của phiên chạy gdb-pwndbg này. Vì nó sẽ không thay đổi sau những lần chạy.
Bạn chỉ cần làm theo tôi:
Cái tôi khoanh tròn đó chính là libc base trong phiên chạy này. Vậy bây giờ chỉ cần tính độ chênh lệch của nó:
Vậy độ chênh lệch của nó chính là 0x29e40
. Việc cần làm để lấy được libc_base thật đó là: lấy địa chỉ libc_leak thật trừ đi độ chênh lệch là xong :3
Tôi có script sau để có thể leak được libc address ra màn hình:
Tôi sẽ xử lí script của tôi để lấy ra được libc address:
Rồi khi mà ta leak được libc thì chương trình cũng đã cạn không có bất kì địa chỉ nào để có thể ret về ==> Bởi vậy tôi sẽ quay trở lại main 1 lần nữa để thực hiện overflow và ROpgadget
Mà để thực hiện được nó ta cần quay lại và gửi lại format string và gửi lại payload để nó có thể ret lại chương trình.
Tôi sẽ tính offset đến ret:
Nhưng thật là phiền khi ta có hàm này để nó tránh return lại chương trình:
Bởi vậy tôi sẽ return đến sau nó để có thể đúng:
Tôi chọn called = 1
để return :v.
Oke vậy chương trình đã quay trở lại và ta thấy Amount
trên màn hình:
Nhưng điều gì khiến ta bị"got EOF..."
?
Chương trinh đã bị hỏng và lỗi Bus error: lỗi này liên quan đến đường truyền data, hay gì đó, bởi vậy tôi nghi địa chỉ của cái gì đó không tồn tại ở đây (vì chỉ có địa chỉ không tồn tại thì mới không thể mov dữ liệu vào đó). Check nó.
Yeb. ta đã ghi đè lên địa chỉ của nó một cách thậm tệ.
Điều bây giờ chúng ta cần làm đó là checkxem địa chỉ ban đầu của nó là bao nhiêu và chỉnh lại script.
Khi ta chạy đến nó trên gdb và kiểm tra lại thì nó chứa byte 0x00
và có địa chỉ là 0x7fffffffdf7c
. Nhưng do tôi ghi đè lên địa chỉ của nó nên tôi phải kiếm 1 địa chỉ khác để thay thế nó. bởi vậy tôi sẽ dùng những địa chỉ ở .bss
section.
Tôi sẽ lấy luôn địa chỉ ở dòng cuối cùng kia để tránh xảy ra lỗi.
Biết được offset của nó là 32 và có địa chỉ để ghi đè nên script của tôi sau đó sẽ như sau:
Oke vậy phần này không còn lỗi nữa:
tiếp theo ta sẽ đến bước tiếp theo:
Bước 2: Overflow + ROPgadget.
Tất nhiên là ta phải gửi lại 1 lần nữa.
Trước khi gửi tôi muốn kiểm tra lại 1 lần nữa:
Mọi thứ như tôi mong muốn.
Tôi vẫn chưa rõ 1 vài lí do gì mà payload của tôi không hoạt động và xảy ra lỗi này:
Vấn đề này tôi sẽ sửa chữa sau.
Trong phần này tôi sẽ dùng công cụ one-gadget
để giải quyết nốt bài này:
One gadget
Now we find the offsets of the one_gadgets in the libc.
Bất kỳ one_gadget nào cũng tốt miễn là các ràng buộc được đáp ứng. Tôi đã chọn cái yêu cầu RSI và RDX phải rỗng vì chúng thường là các tiện ích ngắn. Sau đó, chúng ta phải tìm các tiện ích thích hợp để làm cho RSI và RDX trở nên vô hiệu. Tôi chỉ cố gắng tìm các thiết bị pop phù hợp để thực hiện công việc này.
Searching for POP RDX, RSI gadget
ROPgadget --binary /lib/x86_64-linux-gnu/libc.so.6 | grep "pop rsi "
ROPgadget --binary /lib/x86_64-linux-gnu/libc.so.6 | grep "pop rdi "
Kinh nghiệm rút ra:
Là dùng One-gadget đi cmmm bài loz.
Với khi gặp lỗi ở đâu thì nên xem đó là lỗi gì và phân tích địa chỉ bla bla.
Dường như trong system(/bin/sh) vẫn còn uẩn khúc gì đó khó mà giải thích được.
Và khi muốn return lại 1 hàm thì hãy chú ý pass những điều kiện không cần thiết. Hết!!!
Last updated