Audit code->bug

Ta Sung
tradahacking
Published in
5 min readAug 16, 2017

Hôm nay lại là 1 ngày đẹp trời :)) và mình sẽ lại viết tiếp về cách mà mình đã audit code và tìm ra bug này.

Nếu các bạn đã đọc bài trước của mình viết về sử dụng fuzzer để tìm bug trong interpreter perl, còn bài này mình sẽ viết về auditcode để tìm bug trong 1 thư viện dùng để parse xml trên perl.
Mục đích lần auditcode tìm bug này là để hiểu cách perl nó chạy và từ đó viết exploit. Sau khi xem qua sourcecode của perl thấy nó có vẻ lớn, nếu ôm hết cái đống này vào người thì chắc gg sớm =)). Nên mình kiếm thằng plugin nào code vừa đủ bem. Và mình đã chọn 1 thằng Lib-XML để audit code vì xem qua source nó cũng nhỏ + mình cũng có kiến thức về xml nữa nên sẽ không mất thời gian để đọc hiểu xml nữa, nhiệm vụ của mình bây giờ chỉ là đọc code libxml và bem :P

Vì mình chơi pwnable khá nhiều nên mình biết thằng perl này sẽ có thể exploitable cao nếu mình tìm được 1 bug trên heap. Vấn đề heap và exploitable của nó thì hẹn các bạn vào 1 bài khác :). Nếu bạn nào hứng thú với pwnable thì có thể vào pwnable.tw hoặc pwnable.kr để chơi, còn gặp khó khăn thì có thể hỏi trong slack kênh #pwnable của VNSec ,mình hay lên đây hóng mấy ông anh nên nếu gặp mình cũng sẽ trả lời cho các bạn =))

Okie không dài dòng nữa, download source của nó về và quất thôi :V.
Đọc file README và build ta sẽ được như hình:

build -libxml

sau khi build và make install nó mình sẽ viết 1 đoạn script nhỏ như hình:

script-test

Và bắt đầu sử dụng gdb-peda để debug thử xem nó chạy kiểu gì.

gdb-perl

chạy gdb và sử dụng lệnh vmmap ta sẽ thấy perl sẽ load lên libxml2.so.2.9.3 và LibXML.so.

Ta thấy libxml2.so.2.9.3 được load lên từ folder lib của linux còn LibXML.so được load lên từ folder của perl nên ta có thể đoán thằng LibXML.so này sẽ dùng các API của thằng libxml2.so để viết. Vì vậy mình sẽ chỉ tập trung vào LibXML.so.

Load LibXML.so vào IDA ta sẽ thấy hàm boot_XML_LibXML là hàm dùng để nạp các functions vào cho perl. Qua đây ta có thể thấy rõ các API có thể được call trực tiếp từ perl.

Như đã nói ở đầu bài, mình sẽ cố gắng tìm 1 bug trên heap để viết exploit. Theo thói quen khi chơi pwn mình sẽ search các hàm có free trong đó :D

các hàm có free

Ở đây mình chọn PmmFreeNode , click vào để xem nó:

tiếp tục flow như vậy thì mình thấy thằng PmmREFCNT_dec sẽ call tới thằng PmmFreeNode. Vào sublime mở folder XML-LibXML-2.0129 lên sử dụng tính năng tìm trong folder từ khóa “PmmREFCNT_dec” ta sẽ được kết quả:

PmmREFCNT_dec

Vì trước đây mình có coi mấy cái bug php của 1đàn anh như nồi nên mình có gặp mấy cái khái niệm Gabage_Collector (GC)Reference_Counting (REFCNT), ở đây mình sẽ giải thích sơ nó theo cách hiểu của mình nếu có gì thọt thì các bạn có thể góp ý dưới phần comment để mình sửa vô nha :P

Vì perl là 1 interpreter có khả năng tự động cấp phát và thu gom bộ nhớ khi người dùng không sử dụng nữa. Để làm việc này nó cần 1 chiếc xe chuyên đi dạo các objects và thu gom bộ nhớ không dùng nữa, chiếc xe này chính là GC. Các objects cần có 1 kí hiệu(REFCNT≤0) để cho GC biết khi nó không còn dùng nữa. Vậy REF_CNT của object là cái vẹo gì mà đòi làm kí hiệu?
Vì 1 object X có thể có nhiều thằng khác vay mượn và sử dụng, và REFCNT của object X ở đây là tổng số các liên kết vay mượn. Nếu như REFCNT≤0 thì lúc này có nghĩa là object X không ai thèm sử dụng nữa nên bây giờ nó được xem như rác và GC sẽ thu gom lại nó.

Quay lại với hình PmmREFCNT_dec ở trên ta thấy đoạn description ở đây nói với đại ý là hàm này sẽ giảm thằng REFCNT xuống 1, nếu như cái thằng REFCNT ≤0 thì sẽ free thằng proxy node còn nếu nó là 1 phần của subtree (REFCNT>0) thì lúc này nó sẽ chỉ sửa lại REFCNT và xóa subtree nếu không cần nữa. Vì vậy chìa khóa để free trong hàm này là REFCNT.

Ta thấy chỉ cần thằng REFCNT tăng, giảm sai một nhịp là coi như xong :)).
Tiếp tục kiểm tra xem thằng nào gọi PmmREFCNT_dec ta thấy có thằng PmmFixOwner, Và thằng PmmFixOwner được khá nhiều thằng call tới.

Và ở đây mình thấy có 1 thằng replaceNode khá là ảo, vì kinh nghiệm chơi ctf của mình thì mấy cái hàm replace này hay bị lỗi kiểu X.replace(X) . Tới khúc này nhát coi code nữa quá nên viết luôn 1 đoạn script để chơi luôn thay vì audit tiếp.

chạy phát thì thấy kết quả khá là ảo :D

Nhìn vậy là hiểu rồi, useafterfree chắc luôn=)))

Bài này tới đây thôi, hẹn các bạn 1 ngày đẹp trời khác mình sẽ viết về cách mình build payload exploit cho cái bug này :)).

--

--