Hello

Một bài RE firmware của thiết bị IoT Arduino Uno. Trước khi bắt đầu đọc tiếp các bạn nên đọc trước bài hướng dẫn RE Arduino Uno mình đã viết để bắt đầu RE.

Link challenge: Hello.hex

Dùng XLoader nạp vào board chạy thử

Chương trình giao tiếp qua cổng Serial 9600 baud yêu cầu nhập vào key nếu nhập đúng sẽ có flag trả về. Okie bắt đầu với việc tìm đoạn assembly in dòng correct. Để tìm được ta cần hiểu cơ chế load data vào RAM trước khi chạy của AVR. Các chuỗi có sẵn được chương trình lưu vào đây và dùng chứ không dùng trong binary. Đoạn copy vào RAM:

Dữ liệu ở Z Pointer (r30, r31) = 0x1CA2 copy vào RAM ở X Pointer (r26, r27) = 0x0100. Với vòng lặp copy đến 0x020E tức là sẽ copy 0x020E – 0x0100 = 0x10E byte từ vị trí 0x1CA2 trong binary đến 0x0100. Như vậy, chuỗi correct nằm ở 0x1D57 của binary sẽ nằm ở 0x01B5 ở trong RAM. Vậy sẽ có đoạn load giá trị này để in chuỗi ta tìm giá trị 0xB5 trong IDA

Như vậy ta tìm được hàm check là sub_1F2. Nhìn vào sơ đồ của nó ta sẽ thấy nó là dạng các if lồng vào nhau.

Nếu các bạn đã tham gia WhiteHat hoặc DTU Final năm vừa rồi thì sẽ biết ngay dạng này là hệ phương trình dùng Sage hoặc Z3 để giải. Bài này gần như ko cần RE nhiều, vấn đề là làm sao lập hệ phương trình khi decompiler của IDA bị vô hiệu hóa. Trước khi lập hệ phuong trình mình cần hiều hệ phương trình được lập như thế nào đã. Cơ bản là có 2 loại biểu thức

Loại 1

1 hằng số được load vào r26 và 1 byte dữ liệu ta nhập vào load vào r18 nhờ trước nó đã đẩy vào stack ở Y pointer, được truyền vào hàm sub_E28(r26,r18) (Đáng nhẽ là truyền vào int 4 byte nhưng mà chương trình này chỉ dùng 1 byte thôi nên mình chỉ quan tâm đến r26 và r18)

Cơ bản chỉ là nhân 2 số với nhau thôi nhưng mà do AVR dùng RISC nên lệnh nó mới dài như thế.

Loại 2:

Load 1 hằng số vào thanh ghi và thực hiện lặp để shift left giá trị được chúng ta nhập vào. Cơ bản là phép << (shift left) thôi nhưng do AVR không cho phép shift left 3 mà phải shift left 3 lần.

Như vậy các biểu thức trong phương trình đơn giản là char nhân với hằng số hoặc, char << thôi. Dựa vào 2 pattern này mình viết code để có thể generate ra các biểu thức. Code (file partX.txt là code assembly lấy từ IDA ở mỗi nhanh if):

Với code trên thì mình có thể tạo ra được đúng 12/16 phương trình. Còn lại sẽ bị sai. Để xác định phương trình sai mình sẽ dùng debug. Chiến thuật cơ bản là truyền vào 16 byte bất kỳ. Lấy biểu thức mình generate ra được tính giá trị rồi so sánh với giá trị chương trình khi debug tính ra (chỗ compare trước khi qua nhánh khác). Để qua được nhanh khác thì ta sẽ chỉnh thanh ghi lại cho đúng giá trị nó cần. Mặc dù hơi cục xúc nhưng mà đây là cách nhanh nhất mình có thể nghĩ ra để xác định được 16 pt có cái nào sai ko. Với phương trình sai thì các bạn chỉ việc ngồi đọc code lại hoặc debug là dễ dàng tìm ra chỗ sai ngay.

Sau khi có phương trình quăng vào z3 giải thôi. Ez:

Nhập vào chuong trinh trên board ta sẽ có flag:

Bài này thật sự khó ở việc đây là kiến trúc mới AVR với lại tập lệnh của nó ít nên 1 công việc mà code assembly của nó dài quá mức. Các bạn nên thử làm để quen với nó.

Cảm ơn các bạn vì dành thời gian đọc bài viết. 😀

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s