REVERSING WITH IDA FROM SCRATCH (P24)

m4n0w4r
tradahacking
Published in
6 min readOct 25, 2019

Phần 24 này tôi sẽ thực hành với file đã gửi kèm ở phần trước. Cách làm với IDA2.exe cũng tương tự như cách đã thực hiện với file IDA1.exe, chỉ khác là trong file này có hai biến cần kiểm tra điều kiện, nếu thỏa mãn cả hai thì chúng ta sẽ tới được đoạn code hiển thị thông báo “ you are a winnner man je\n “:

Như trên hình ta thấy biến var_14 được so sánh với giá trị 0x71727374h còn biến var_C được so sánh với giá trị 0x91929394, do đó ta phải tìm cách để có thể thay đổi giá trị các biến này. Trước tiên, tôi sẽ đổi tên chúng thành cookiecookie_2 để dễ dàng nhận biết trong code của chương trình:

Sau khi đổi tên xong, chọn lần lượt từng biến này và nhấn “ X “:

Ta thấy rằng các biến này duy nhất được truy cập thông qua lệnh LEA trước khi thực hiện hàm printf(). Lệnh LEA sẽ lấy thông tin địa chỉ của các biến để in ra màn hình, bên dưới là câu lệnh CMP làm nhiệm vụ so sánh. Như vậy là giá trị của các biến này không hề bị thay đổi trong hàm main().

Do đó, theo suy luận tương tự như phần trước, ta phải thay đổi giá trị của các biến này để có thể tới được thông báo hiển thị “… winner… “. Mà như đã thấy ở trên hình thì các biến này đều được so sánh với một giá trị cụ thể do chương trình mặc định sẵn. Vì vậy, để có thể thay đổi các biến thì khả năng sẽ phải thực hiện overflow lên vùng buffer, để từ đó có thể ghi đè giá trị ta mong muốn lên các biến này.

Bên cạnh các biến cookie mà ta vừa phân tích ở trên, để ý một chút các bạn sẽ thấy trong file IDA2.exe này còn có thêm một biến khác là var_10. Ban đầu, biến này được khởi gán bằng 0:

Nhấn ‘ X ‘ để xem biến này còn được sử dụng ở những chỗ nào khác:

Theo kết quả trên hình, ta thấy ngoài lệnh khởi gán nó bằng 0 thì biến này còn được truy cập ở hai vị trí khác nữa thông qua lệnh LEA. Chúng ta sẽ xem xét từng chỗ một, nhưng trước tiên ta thực hiện việc điều chỉnh lại các tham số được truyền cho các hàm APIs để cho dễ nhìn hơn. Áp dụng kỹ thuật đã làm với file IDA1.exe, kết quả có được như sau:

Sau khi thay đổi xong các bạn sẽ thấy code nhìn rõ ràng hơn nhiều so với ban đầu, qua đó ta cũng hiểu được cách mà chương trình truyền tham số cho hàm APIs. OK, giờ quay lại vấn đề lúc trước, ta kiểm tra các đoạn code khác có truy cập tới biến var_10:

Phân tích đoạn code trên hình, đầu tiên thông qua lệnh LEA thì eax sẽ có được địa chỉ của biến, sau đó thực hiện tăng nội dung hay tăng giá trị của nó lên 1 thông qua lệnh INC. Sau đó, lấy lại địa chỉ của biến một lần nữa và truyền nó như một tham số của hàm printf(). Như vậy, hàm printf() sẽ in ra địa chỉ của biến chứ không phải là giá trị của biến.

Dựa vào thông tin chương trình sẽ in ra màn hình dòng thông báo “ flag %x”, tôi đổi tên biến var_10 thành flag. Tuy nhiên, sau quá trình phân tích thì thấy rằng biến này không có ảnh hưởng gì tới quá trình hoạt động của chương trình.

Tóm lại, chúng ta chỉ cần nghiên cứu biến Buffer vì các biến ở trên biến này được sinh ra trong quá trình compile chương trình, được sử dụng làm các biến tạm thời chứ không có tác động đến chương trình:

Nhấp đúp vào biến Buffer, ta sẽ chuyển tới màn hình cung cấp thông tin biểu diễn Stack của hàm main() như hình dưới đây:

Rõ ràng, biến Buffer này là một nơi được dành riêng trong bộ nhớ, được sử dụng để lưu thông tin mà người dùng nhập vào từ bàn phím thông qua giao diện console. Biến này được truyền vào là một tham số của hàm gets():

Để kiểm tra kích thước của buffer này ta nhấn chuột phải và chọn Array, IDA sẽ cung cấp thông tin mà nó phân tích được:

Như vậy Buffer có kích thước gồm 68 phần tử, mỗi phần tử là 1 byte. Ta nhấn OK để đồng ý chuyển đổi, kết quả có được như hình:

Với kết quả có được, ta biết rằng đầu tiên phải điền đầy buffer với 68 ký tự, và do hạn chế của hàm gets nên chúng ta có thể overflow buffer này và ghi đè thêm 4 bytes vào biến cookie nằm bên dưới của buffer. Tiếp theo là ghi đè lên 4 bytes của biến flag ( một dword (dd)) và cuối cùng là 4 bytes của biến cookie_2:

Tổng kết lại: user_input= 68 *”A”+ cookie + flag + cookie2. Với thông tin như vậy, chúng ta có thể xây dựng một python script như sau:

from subprocess import *import structp = Popen([r'IDA2.exe', 'f'], stdout=PIPE, stdin=PIPE, stderr=STDOUT)cookie=struct.pack("<L",0x71727374)cookie2=struct.pack("<L",0x91929394)flag=struct.pack("<L",0x90909090)print " Attach to the debugger and press Enter\n"raw_input()user_input=68 *"A"+ cookie + flag + cookie2p.stdin.write(user_input)testresult = p.communicate()[0]print user_inputprint(testresult)

Kiểm tra thử script, tôi có được kết quả như sau:

Như vậy là thành công!

Trong phần 24 này tôi gửi kèm thêm 2 file IDA3.exeIDA4.exe ( https://mega.nz/#!bOxGWISb!kYzE2SsWPyo0YQg5tL72qy14ntuMlic02ML5bg7-GD0) để các bạn thực hành như một bài tập về nhà.

Hẹn gặp lại các bạn ở phần 25!

Xin gửi lời cảm ơn chân thành tới thầy Ricardo Narvaja!

m4n0w4r

Ủng hộ tác giả

Nếu bạn cảm thấy những gì tôi chia sẻ trong bài viết là hữu ích, bạn có thể ủng hộ bằng “bỉm sữa” hoặc “quân huy” qua địa chỉ:

Tên tài khoản: TRAN TRUNG KIEN
Số tài khoản: 0021001560963
Ngân hàng: Vietcombank

--

--