avastのretdec
avastがデコンパイラを公開したので使ってみた。 お題はちょっと前のsharif-ctf2018のvuln4で、試しにデコンパイルしてみる。
インストール
まずはretdecをインストールする。
githubのリポジトリにインストールのやり方があるのでプラットフォームに合わせてインストール。
ubuntuだとaptで入るcmakeじゃバージョンが低くてコンパイルできないので、cmakeも別途入れる必要があった。
とりあえずコンパイルしてインストールすると様々なツールとスクリプトがインストールされる。
ぱっと見た感じだとマルウェア解析をやりやすくするための解析ツールとかLLVM IRのトランスレータとかも入るみたいなので使ってみたい。
他にも簡単に使えるようにするためのスクリプトも入る。
デコンパイルするにはretdec-decompiler.sh
を実行すればいい。
デコンパイル
vuln4をデコンパイルしてみる。
retdec-decompiler.sh vuln4
簡単過ぎてビックリする。
デコンパイルすると、いくつかのファイルが生成された。 + vuln4.c + vuln4.c.backend.bc + vuln4.c.backend.ll + vuln4.c.frontend.dsm + vuln4.c.json
vuln4.c以外は中間生成物っぽい? vuln4.cがデコンパイル結果になる。
// // This file was generated by the Retargetable Decompiler // Website: https://retdec.com // Copyright (c) 2018 Retargetable Decompiler <info@retdec.com> // #include <stdint.h> #include <stdio.h> #include <stdlib.h> #include <string.h> // ------------------- Function Prototypes -------------------- int32_t __x86_get_pc_thunk_bx(int32_t a1); int32_t _start(int32_t a1); int32_t copy_it(int32_t a1); int32_t function_8048360(int32_t a1); int32_t function_8048370(int32_t a1); int32_t function_8048380(int32_t a1, int32_t a2, int32_t a3); int32_t function_8048390(int32_t a1, int32_t a2); int32_t function_80483a0(int32_t a1); int32_t function_80483b0(int32_t a1, int32_t a2, int32_t a3, int32_t a4, int32_t a5, int32_t a6, int32_t a7, int32_t a8); // --------------------- Global Variables --------------------- int32_t g1 = 0; // eax int32_t g2 = 0; int32_t (*g3)(int32_t) = NULL; // ------------------------ Functions ------------------------- // Address range: 0x8048360 - 0x804836f int32_t function_8048360(int32_t a1) { // entry return ((int32_t (*)(int32_t))&g3)(g2); } // Address range: 0x8048370 - 0x804837f int32_t function_8048370(int32_t a1) { // 0x8048370 g1 = fflush(); return function_8048360(0); } // Address range: 0x8048380 - 0x804838f int32_t function_8048380(int32_t a1, int32_t a2, int32_t a3) { // 0x8048380 g1 = fgets(); return function_8048360(8); } // Address range: 0x8048390 - 0x804839f int32_t function_8048390(int32_t a1, int32_t a2) { // 0x8048390 g1 = strcpy(); return function_8048360(16); } // Address range: 0x80483a0 - 0x80483af int32_t function_80483a0(int32_t a1) { // 0x80483a0 g1 = puts(); return function_8048360(24); } // Address range: 0x80483b0 - 0x80483bf int32_t function_80483b0(int32_t a1, int32_t a2, int32_t a3, int32_t a4, int32_t a5, int32_t a6, int32_t a7, int32_t a8) { // 0x80483b0 g1 = __libc_start_main(); return function_8048360(32); } // Address range: 0x80483d0 - 0x80483ff int32_t _start(int32_t a1) { int32_t v1 = g1; // 0x80483d8 int32_t v2 = v1; // bp-4 int32_t v3; int32_t result = function_80483b0(0x80484ea, a1, (int32_t)&v3, 0x8048580, 0x80485e0, 0, (int32_t)&v2, v1); // 0x80483ec return result; } // Address range: 0x8048400 - 0x8048403 int32_t __x86_get_pc_thunk_bx(int32_t a1) { // entry return g1; } // Address range: 0x80484cb - 0x80484e9 int32_t copy_it(int32_t a1) { // entry int32_t v1; // bp-22 function_8048390((int32_t)&v1, a1); return 0; } // Address range: 0x80484ea - 0x8048571 int main(int argc, char ** argv) { // entry function_80483a0((int32_t)"This time it is randomized..."); function_80483a0((int32_t)"You should find puts yourself"); function_8048370(*(int32_t *)0x80498a4); int32_t v1; // bp-66 int32_t v2 = &v1; // 0x804853a function_8048380(v2, 200, *(int32_t *)0x80498a0); copy_it(v2); function_80483a0((int32_t)"done!"); return 0; } // --------------- Dynamically Linked Functions --------------- // int32_t __libc_start_main(void); // int32_t fflush(void); // int32_t fgets(void); // int32_t puts(void); // int32_t strcpy(void); // --------------------- Meta-Information --------------------- // Detected compiler/packer: gcc (4.7.2) // Detected functions: 10 // Decompilation date: 2018-02-06 22:45:20
元のvuln4が分岐もループもほとんどない単純なプログラムだからどの程度できるのかよく分からない。 pltっぽいところも関数にしているのが少し分かりにくいが、結構リバーシングの手間が省けるんじゃないだろうか? どの程度使えるのかこれから試していきたい。