Skip to main content

Pwn 101: Xây dựng nền tảng

·1836 words·9 mins
pwn
Author
Lio
Trying to exploit this shell program called life that I never get control of.
Table of Contents
pwn 101 - This article is part of a series.
Part 1: This Article

Disclaimer
#

Series Pwn 101 này mình viết cho vui trong lúc rảnh nhằm mục đích chia sẻ lại mấy cái kiến thức mà mình học được (hoặc tự mình hiểu được nó là như thế) cũng như kinh nghiệm từ khi mới bắt đầu theo mảng Pwnable cho đến giờ. Mấy cái mớ trong này chưa chắc đã đúng hết 100% nhưng nếu thấy không vừa mắt thì cứ coi như là mình viết linh tinh rồi tắt tab này đi là được.

Đầu tiên phải nói là cái mảng này nó khổ, khổ lên khổ xuống, khổ điên khổ khùng. Vừa khổ vừa khó tiếp cận nếu bạn là người mới tập tành chơi CTF. Nên là trước khi đi sâu hơn vào vấn đề thì mình có 1 lời khuyên dành cho các bạn là… bỏ đi mà làm người, tập chơi crypto hay web trước cho dễ làm quen trước ấy rồi quay lại học chơi pwn như mảng phụ chắc cũng chưa muộn đâu.

Còn nếu đã có quyết tâm theo cái mảng này đến cùng thì, welcome to Pwn 101.

Kiến thức và kỹ thuật
#

Để chơi tốt và không mau nản ở cái bộ môn củ chuối này thì dưới đây là một số thứ có thể xem như là hành trang cần thiết và gần như là yêu cầu bắt buộc nếu bạn không muốn tốn thời gian quá lâu cho một bài pwn cực kỳ cơ bản.

Kỹ năng lập trình
#

Cái này thì khỏi phải nói rồi ha?

Làm thế quái nào mà bạn có thể biết được chương trình này bị lỗi gì, có thể khai thác ra sao mà không hiểu được thứ cơ bản nhất là cái mớ code này đang làm gì cơ chứ.

Ừ thì công nhận là đối với mấy bài ở mức cơ bản thì chỉ cần đọc hiểu cái chương trình nó làm gì thôi cũng đủ để solve được rồi. Nhưng càng lên cao thì càng khó detect được lỗi chương trình vì đôi khi nó thật sự rất tinh vi. Nên là nếu không hiểu ý đồ của người tạo ra chương trình thì rất khó để tìm ra lỗi.

Ngoài ra thì mình cũng phải biết cách viết script Python nữa. Thử tưởng tượng bạn vừa tìm ra được lỗi chương trình nhưng mà trước đó phải giải 7749 cái bài toán ngẫu nhiên khác nhau thì mới tới được chỗ này đi, xong bạn cần thử nhập một số từ 1 đến 100 xem cái nào sẽ gây ra lỗi. Vậy thì mỗi khi muốn nhập một số để thử thì bạn lại phải giải 7749 cái bài toán đó lại lần nữa.

Đó là lý do mà chúng ta cần phải biết viết script để tự động hóa việc khai thác lỗi chương trình. Còn tại sao lại là Python thì chắc chắn là do thư viện pwntools cực kỳ tiện lợi của nó rồi.

Đối với phần lớn các thử thách pwn thì mình sẽ đọc pseudocode C được gen ra từ các decompiler là chủ yếu, hoặc lâu lâu thì gặp mấy bài dính tới C++, Rust, Go,… nhưng chủ yếu vẫn là đọc code C và debug cùng con quái vật mang tên Assembly.

Kiến trúc máy tính và mã máy
#

Vì người chơi pwn phải làm việc với những chương trình được viết bằng các ngôn ngữ bậc thấp nên việc hiểu được dưới tầng sâu của máy tính luồng dữ liệu được mang đi đâu và xử lý như thế nào là vô cùng quan trọng.

Có thể kể đến như việc phân biệt little endianbig endian tổ chức dữ liệu khác nhau như thế nào, hay theo như calling convention thì các tham số truyền vào sẽ được tổ chức trong các thanh ghi ra sao khi gọi hàm cũng như thực hiện các system call.

Phần lớn thì các file chương trình pwn sẽ chạy trên kiến trúc AMD x86 hoặc x64, đương nhiên thì thi thoảng cũng sẽ gặp các chương trình chạy trên kiến trúc ARM hoặc RISC-V. Nên các bạn có thể tập trung vào AMD trước còn các kiểu kiến trúc còn lại có thể nghiên cứu tại chỗ nếu gặp phải. Nếu đã có nền tảng vững về luồng thực thi trên AMD rồi thì mình tin là việc nắm bắt và hiểu được các kiểu kiến trúc khác ở mức vận dụng thấp là điều không hề khó.

Think outside of the box
#

Thứ quan trọng nhất và không thể thiếu khi chơi pwn chính là tư duy.

Đâu phải ai cũng nhìn vào cái chương trình nhập dữ liệu cho index bất kỳ của một array và tự hỏi rằng: “Sẽ như thế nào nếu mình chọn index âm?” Và trong trường hợp bị filter đi dấu trừ thì cũng sẽ thử tìm cách nhập số đủ lớn để khiến nó bị tràn sang số âm. Nhưng mà làm thế quái nào biết nó sẽ bị tràn số?

Vậy nên đương nhiên là mỗi tư duy không thì chắc chắn là chưa đủ. Để tận dụng được tư duy đó vào thực tiễn thì kiến thức nền cũng là một phần không thể thiếu, hai thứ này phải đi với nhau thì mới tạo ra được một cá nhân xuất sắc. Mình chắc chắn là điều này là cực kỳ cần thiết ở tất cả các mảng CTF chứ không riêng gì pwn.

Tools
#

Trong quá trình chơi pwn thì tool (công cụ) là một người bạn đồng hành cực kỳ quan trọng không những để khiến việc đọc hiểu, debug chương trình trở nên dễ dàng hơn mà còn nhờ đó tăng tốc độ solve các thử thách. Vậy thì đâu là những tool cần có đối với một pwner? Dưới đây là một số tool mà mình thấy rằng hầu như không thể thiếu mỗi khi chơi pwn.

Decompiler/Disassembler
#

Đây là thứ giúp dịch ngược các file ELF, thứ mà chứa toàn các đoạn code assembly (hợp ngữ) về pseudocode (mã giả) cho dễ đọc. Các đoạn code này thường vẫn sẽ là C hoặc C++. Một số decompiler/disassembler nổi tiếng hiện nay có thể kể đến như:

IDA: Có thể xem như là loại tốt nhất hiện nay. Nếu như bạn có điều kiện thì đầu tư một bản IDA Pro chắc chắn không hề lãng phí. Tuy nhiên thì bản IDA Free vẫn hỗ trợ rất tốt đối với phần lớn các thử thách pwn hiện nay. Hoặc đơn giản hơn là tìm crack trên mạng mà down về thôi.

Ghidra: Tool này thì free nhưng mà mình chưa xài bao giờ. Mình có xem qua được một số pseudocode mà nó tạo ra thông qua các writeup đọc trên mạng hoặc từ người quen sử dụng và phải nói thật là mình không thích cái cách mà nó đặt tên cho các biến local của hàm, nhìn thật sự rất khó chịu. Nhưng mà ai thích thì cứ xài thôi vì nó free mà.

Binary Ninja: Có trả phí (đắt vl) nhưng offer nhiều chức năng hữu ích và quan trọng nhất là dark theme.

Ngoài ra thì vẫn còn các decompiler/disassembler khác mà mình chưa có cơ hội tiếp xúc đủ nhiều nhưng mà dưới đây là ảnh so sách các pseudocode của các decompiler/disassembler mà mình yeet được từ reddit.

decompiler

Debugger (with plugins)
#

Trong quá trình phân tích luồng thực thi hay hành vi của chương trình đối với những input khác nhau thì việc sử dụng các debugger để dừng chương trình nhằm kiểm tra các thanh ghi, bộ nhớ được tổ chức và sắp xếp ra sao là một phần công việc không thể thiếu. Phần lớn thì mọi người sẽ sử dụng gdb nhưng mà chỉ nhiêu đó thôi thì chưa đủ để có cái nhìn tổng quan cũng như là có thể quan sát được chi tiết chương trình tại một thời điểm nhất định được.

Chính vì vậy mà đối với lựa chọn một plugin phù hợp để bổ trợ cho công đoạn debug thì mình cực kỳ recommend pwndbg. Đối với một người đã từng sử dụng qua cả PEDA GEF rồi quay xe sang pwndbg thì theo đánh giá cá nhân của mình, các tính năng của pwndbg mang lại trải nghiệm tốt hơn rất nhiều.

Miscellaneous
#

Ngoài những tool cụ thể kể trên thì việc solve các thử thách pwn đôi khi cũng sẽ dùng đến một số tool nhất định khác phù hợp cho các công việc đặc thù cụ thể có thể kể đến như:

Docker: Phần lớn các file cho thử thách pwn sẽ được deploy trên remote server với nhiều kiểu config khác nhau nên đôi khi chúng ta phải sử dụng docker dể thiết lập môi trường ở local sao cho giống với remote nhất có thể cũng như lấy về được phiên bản libc mà chương trình sẽ sử dụng.

pwninit: Sau khi đã có được file libc mà chương trình sẽ sử dụng tại remote server rồi thì làm cách nào để liên kết nó với file chương trình chúng ta đang có ở local thì đây chính là giải pháp.

ROPgadget ropper: 2 tool này chủ yếu để hỗ trợ tìm kiếm các gadget, có những gadget xuất hiện ở tool này nhưng tool kia lại không tìm ra được và ngược lại. Còn nếu như bạn hiện tại vẫn chưa biết gadget là gì thì đừng lo vì các phần sau của series mình sẽ đề cập và giới thiệu đến nó lại.

one_gadget: Tool này giúp tìm kiếm các địa chỉ lệnh mà chỉ cần nhảy tới đó thì sẽ auto chiếm được shell chương trình tuy nhiên drawback của nó là yêu cầu phải thỏa mãn một số điều kiện về giá trị nhất định tại một vài thanh ghi.

Last words
#

Nhiêu đó là những gì đúc kết được trong suốt quá trình học chơi pwn của mình. Tuy nhiên như đã nói ở đầu bài viết thì những gì mình viết ra chưa chắc đã đúng hết 100% và các bạn muốn dấn thân vào mảng Pwnable cũng không bắt buộc phải nằm hết toàn bộ rồi mới học chơi.

Mình cũng đã từng chả biết code Python là gì, chả biết mấy cài hàm trong C nó làm việc ra sao cũng như không biết đọc cả assembly nhưng cứ làm tới đâu thì học, nghiên cứu tới đó là ổn.

Lượng kiến thức để chơi tốt được pwn thì rộng bao la và chắc chắn là không ai có thể nắm hết được trong ngày một ngày hai được nên thứ mình mong muốn có được ở những người chơi pwn chỉ cần là ngọn lửa đam mê cháy mãi không bao giờ tắt là được.

end

pwn 101 - This article is part of a series.
Part 1: This Article