PinなどのDBIツールでトレースした結果をIDAにマッピングするプラグイン「Lighthouse」を使ってみた

Lighthouseとは

Lighthouse とは、DBIツールでトレースすることで得たコードカバレッジデータを見やすくIDA内の独自のViewに表示し、IDAのDisassembly View、Graph ViewにマッピングしてくれるIDAプラグインである。

github.com

DBI(Dynamic Binary Instrumentation)は実行時にバイナリの内容を書き換えることによって、CPU命令の単位でトレースなどを行う手法である。 Lighthouseは、PinDynamoRIOFridaの3種類のDBIツールに対応している。この記事ではPinを用いた。

インストールする

git cloneして/plugin以下にあるlighthouse_plugin.pyとlighthouseフォルダをIDAの/pluginsフォルダに入れるとインストールできる。 以下はmacOSでのコマンド例だが、OSが違ってもパスが変わるくらいでそんなに変わらないはず。

$ git clone git@github.com:gaasedelen/lighthouse.git
$ cp -R lighthouse/plugin/ /Applications/IDA\ Pro\ 7.1/ida64.app/Contents/MacOS/plugins/

また、PinのログフォーマットをLighthouseで扱える形式にするためのpintoolをビルドしておく必要がある。64bitのMacOSだと、/lighthouse/coverage/pin/obj-intel64/CodeCoverage.dylibが生成される。

$ export PIN_ROOT=~/pin # Pinのインストールパスを指定
$ export PATH=$PATH:$PIN_ROOT
$ cd ~/lighthouse/coverage/pin
$ make
mkdir -p obj-intel64
/Applications/Xcode.app/Contents/Developer/usr/bin/make objects
make[1]: Nothing to be done for `objects'.
/Applications/Xcode.app/Contents/Developer/usr/bin/make libs
make[1]: Nothing to be done for `libs'.
/Applications/Xcode.app/Contents/Developer/usr/bin/make dlls
make[1]: Nothing to be done for `dlls'.
/Applications/Xcode.app/Contents/Developer/usr/bin/make apps
make[1]: Nothing to be done for `apps'.
/Applications/Xcode.app/Contents/Developer/usr/bin/make tools
...

使ってみる

Pinを使って解析したいプログラムをトレースする。 ここでは、最近、Golangで書いているCPUエミュ cibo をPinにかけた。 実行結果はtrace.logとしてファイルに出力される。ちなみにgolangのバイナリの構造はこれがくわしい。

$ pin -t obj-intel64/CodeCoverage.dylib -- cibo hoge/samples/asm/simple_call
CodeCoverage tool by Agustin Gianni (agustingianni@gmail.com)
Logging code coverage information to: trace.log
Loaded image: 0x1000000:0x12fe707 -> cibo
Loaded image: 0x59e1000:0x5a7efff -> dyld
Loaded image: 0x7fff6a7ed000:0x7fff6a820fff -> libclosured.dylib
Loaded image: 0x7fff6acff000:0x7fff6ad00fff -> libSystem.B.dylib
Loaded image: 0x7fff6af33000:0x7fff6af89fff -> libc++.1.dylib
Loaded image: 0x7fff6af8a000:0x7fff6afaefff -> libc++abi.dylib
Loaded image: 0x7fff6c300000:0x7fff6c6eefff -> libobjc.A.dylib
Loaded image: 0x7fff6cd9b000:0x7fff6cd9ffff -> libcache.dylib
Loaded image: 0x7fff6cda0000:0x7fff6cdaafff -> libcommonCrypto.dylib
Loaded image: 0x7fff6cdab000:0x7fff6cdb2fff -> libcompiler_rt.dylib
Loaded image: 0x7fff6cdb3000:0x7fff6cdbbfff -> libcopyfile.dylib
Loaded image: 0x7fff6cdbc000:0x7fff6ce41fff -> libcorecrypto.dylib
Loaded image: 0x7fff6cec9000:0x7fff6cf02fff -> libdispatch.dylib
Loaded image: 0x7fff6cf03000:0x7fff6cf20fff -> libdyld.dylib
Loaded image: 0x7fff6cf21000:0x7fff6cf21fff -> libkeymgr.dylib
Loaded image: 0x7fff6cf2f000:0x7fff6cf2ffff -> liblaunch.dylib
Loaded image: 0x7fff6cf30000:0x7fff6cf34fff -> libmacho.dylib
Loaded image: 0x7fff6cf35000:0x7fff6cf37fff -> libquarantine.dylib
Loaded image: 0x7fff6cf38000:0x7fff6cf39fff -> libremovefile.dylib
Loaded image: 0x7fff6cf3a000:0x7fff6cf51fff -> libsystem_asl.dylib
Loaded image: 0x7fff6cf52000:0x7fff6cf52fff -> libsystem_blocks.dylib
Loaded image: 0x7fff6cf53000:0x7fff6cfdcfff -> libsystem_c.dylib
Loaded image: 0x7fff6cfdd000:0x7fff6cfe0fff -> libsystem_configuration.dylib
Loaded image: 0x7fff6cfe1000:0x7fff6cfe4fff -> libsystem_coreservices.dylib
Loaded image: 0x7fff6cfe5000:0x7fff6cfe6fff -> libsystem_darwin.dylib
Loaded image: 0x7fff6cfe7000:0x7fff6cfedfff -> libsystem_dnssd.dylib
Loaded image: 0x7fff6cfee000:0x7fff6d037fff -> libsystem_info.dylib
Loaded image: 0x7fff6d038000:0x7fff6d05dfff -> libsystem_kernel.dylib
Loaded image: 0x7fff6d05e000:0x7fff6d0a9fff -> libsystem_m.dylib
Loaded image: 0x7fff6d0aa000:0x7fff6d0c9fff -> libsystem_malloc.dylib
Loaded image: 0x7fff6d0ca000:0x7fff6d16efff -> libsystem_network.dylib
Loaded image: 0x7fff6d16f000:0x7fff6d179fff -> libsystem_networkextension.dylib
Loaded image: 0x7fff6d17a000:0x7fff6d183fff -> libsystem_notify.dylib
Loaded image: 0x7fff6d184000:0x7fff6d18bfff -> libsystem_platform.dylib
Loaded image: 0x7fff6d18c000:0x7fff6d197fff -> libsystem_pthread.dylib
Loaded image: 0x7fff6d198000:0x7fff6d19bfff -> libsystem_sandbox.dylib
Loaded image: 0x7fff6d19c000:0x7fff6d19dfff -> libsystem_secinit.dylib
Loaded image: 0x7fff6d19e000:0x7fff6d1a5fff -> libsystem_symptoms.dylib
Loaded image: 0x7fff6d1a6000:0x7fff6d1b9fff -> libsystem_trace.dylib
Loaded image: 0x7fff6d1bb000:0x7fff6d1c0fff -> libunwind.dylib
Loaded image: 0x7fff6d1c1000:0x7fff6d1edfff -> libxpc.dylib

生成されたtrace.logをIDAのメニューバーFile -> Load file -> Code coverage fileより読み込む。 f:id:TAKEmaru:20181011233401p:plain

Coverage OverviewというカスタムViewが表示される。Golang製のバイナリで試したため、Coverage率の上位はruntime系の関数が大部分を占めている。シンボルがないバイナリでは、Coverage率が上位の関数をザッと見るのは処理系によっては効率悪いかも。

f:id:TAKEmaru:20181011183102p:plain

フィルタすることもできる。パッケージ名になっているコマンド名でフィルタすると本質っぽい関数だけが表示されていいかんじだった。

f:id:TAKEmaru:20181011183127p:plain

Disassembly View、Graph Viewの中で実際に実行された部分に色をつけてくれる。これは本質ではないアセンブリを読み飛ばすことができるので、すごく便利そう。 f:id:TAKEmaru:20181011183140p:plain

f:id:TAKEmaru:20181011194339p:plain

感想

DBIツールによる動的解析結果を、IDAでの静的解析時に効果的に利用できる点がすばらしいと感じた。 Disassembly View、Graph Viewの中で実際に実行された部分に色をつけてくれるので、読まなくていいアセンブリを無駄に読むことがなくなり解析の効率をあげられそうであった。

また、今回は試してないが複数のトレースログの差分を表示することもできるようで、これによってシンボルがないバイナリでも、Coverage Overviewに本質のルーチンだけをフィルタして表示できそうである。そのうち試してみたい。

Rails appのRuboCopのconfigにはGitHub社で使われているものを使うとよさそう

RuboCopとは

RuboCopRuby向けのコードフォーマッターで、書いたコードがスタイルガイドに準拠しているかシュッとチェックできる。

github.com

-aでauto fixすることができてとても便利であるが、  結構うるさいのでconfigである.rubocop.ymlを調整しないと使いづらい。 

rubocop-github

自分でフォーマッターの出力結果を見ながら、どのコーディングルールをパスするか、ゆるくするかをconfigに書くのはとてもめんどくさい。 なにかいい.rubocop.ymlがないか探してみると、 GitHubが社内で使用しているRuboCopの設定ファイルを github/rubocop-github: Code style checking for GitHub Ruby repositoriesとして公開していた。

github.com

普通のRuboCopで使われているチェック項目をカスタムしているのに加え、 Rails向けのルール(rubocop-github/lib/rubocop/cop/github)が追加されていてとてもよさそう。

導入方法

gemをいれると設定ファイルが追加されるようになっている。

gem "rubocop-github"

gemをインストールすることで追加された設定ファイルを.rubocop.ymlに追加すると使えるようになる。

inherit_gem:
  rubocop-github:
    - config/default.yml
    - config/rails.yml

使い方

普通のRuboCopと同じくrubocopコマンドで使える。

$ rubocop

快適なRuboCopライフを送っていきましょう!!

Android/iOS端末、アプリを扱うのに便利なコマンド、aliasたち

Android/iOS端末、アプリについて取得したい情報があるとき、ついついAndroidiPhoneの端末のUIからがんばってしまいがちだが、 コマンドでやると楽に取得できる。 そんなときに使える、Android/iOSアプリを開発するときや、解析するときに便利なコマンド、aliasたちのまとめ。 普段つかっているのがmacOSなので、macOSでしか動作確認してないです。

Android端末向け

端末のipアドレスを取得する

.bashrcに以下のようにaliasを貼っている。

alias androidip='adb -d shell ip addr show wlan0 | egrep -o "10\.[^\. ]*.[^\. ]*\.[^\. ]*| 172\.[^\. ]*.[^\. ]*\.[^\. ]*| 192\.168\.[^\. ]*\.[^\. ]*" | head -n 1'

以下のように使える。

$ androidip
10.4.56.8/21

スクリーンショットを取る

.bashrcに以下のように関数を定義している。

function androidscreenshot () {
  timestamp=$(date +"%Y-%m-%d-%H-%M-%S")
  adb shell screencap -p /data/local/tmp/screenshot-${timestamp}.png
  adb pull /data/local/tmp/screenshot-${timestamp}.png
  adb shell rm /data/local/tmp/screenshot-${timestamp}.png
}

以下のように使える。

$ androidscreenshot 
/data/local/tmp/screenshot-2018-09-24-18-34-52.png: 1 file pulled. 15.0 MB/s (1999962 bytes in 0.127s)

.apkのパッケージ名を取得する

.bashrcに以下のように関数を定義している。aaptコマンドの結果をgrepしてるだけ。aaptコマンドの使い方を覚えられないので関数にしている。

function packagename () {
  aapt l -a $1 | grep "A: package"
}

以下のように使える。

$ packagename hoge.apk
    A: package="com.xxx.hoge" (Raw: "com.xxx.hoge")

.apkのパーミッションを取得する

.bashrcに以下のように関数を定義している。これもaaptコマンドの結果をgrepしてるだけ。

function apkpermission () {
  aapt l -a $1 | grep -i permission
}

以下のように使える。

$ apkpermission hoge.apk
    E: uses-permission (line=14)
      A: android:name(0x01010003)="android.permission.INTERNET" (Raw: "android.permission.INTERNET")

iOS端末向け

スクリーンショットを取る

libimobiledevice に付属するコマンドを使う。

www.libimobiledevice.org

macOSではhomebrewからインストールできる。

$ brew install libimobiledevice

以下のように使える。

$ idevice_id -l # 接続できてるか確認
7a54172f5b3c2ab46372fb71127fa7b4de8d9d9e
$ idevicescreenshot
Screenshot saved to screenshot-2018-09-24-09-23-58.png

.ipaのインストールパスを取得する

IDAに付属しているios_deployコマンドを使う。IDAを持っている人はIDA Support: Download Centerからダウンロードできる。持っていない人は他のツールからがんばりましょう。

www.hex-rays.com

ios_deployコマンド、微妙に便利だが、公式マニュアルとは違う挙動をするので注意。

$ ios_deploy install -b Payload/hoge.app # 少し時間かかります
$ ios_deploy path -b com.xxxx.xxxxx.hoge
/private/var/containers/Bundle/Application/625D8A60-C8N3-272A-XXXX-XXXXXXXX/hoge.app/hoge

MagSafe2のケーブルを熱収縮チューブで補修した

MagSafe 2のケーブルの皮膜が劣化して、中の電線が見える状態になったので熱収縮チューブで補修した。使い始めて5年なので寿命かな。

f:id:TAKEmaru:20180909031051j:plain

チューブをケーブルで巻いてはんだごてで温めるだけ。

手持ちの熱収縮チューブが見当たらなくて新しく買うことにしたけれど、通販で買うと送料かかるし、秋葉原は遠い。そんな中、東急ハンズで売っているのを知って、会社近くで調達できてよかった。

hands.net

東急ハンズ初めて行ったけど、イヤホンジャックとか抵抗も売っててすごかった。

Homebrewで入るNASMは古すぎて、aptで入るNASMとは挙動が違う

自作CPUエミュの動作確認をしているときに、Homebrewで入るNASMとaptで入るNASMの挙動が違うことに気がついた。

挙動の違いを見る

簡単なコードをアセンブルして違いを見る。

BITS 32
    org 0x7c00
    sub esp, 16

aptで入るNASM

Ubuntuにaptで入るNASMを使って、アセンブルした結果をhexdumpで確認する。

$ nasm sub-test.asm -o sub-test-linux
$ hexdump -C sub-test-linux
00000000  83 ec 10                                          |...|
00000003

0x83のopcodeは、メモリとレジスタの間で8bitの即値を操作する。 ModR/Mによってどんな操作をするのかが分かる。この場合はレジスタの値から8bitの即値を引いている。

Homebrewで入るNASM

macOSにHomebrewで入るNASMを使って、アセンブルした結果をhexdumpで確認する。

$ nasm sub-test.asm -o sub-test-mac
$ hexdump -C sub-test-mac 
00000000  81 ec 10 00 00 00                                 |......|
00000006

0x81のopcodeは、メモリとレジスタの間で32bitの即値を操作する。 この場合もModR/Mによってどんな操作をするのかが分かる。レジスタの値から8bitの即値を引いている。 オペランドに指定している0x16は8bitで収まるのに32bitの無駄に大きい値を扱っていて、うまくアセンブルできていないことがわかる。

バージョンの違いが原因だった

macOSでHomebrewを使ってインストールできる最新のNASMのバージョンは以下の通り。

$ nasm -v
NASM version 0.98.40 (Apple Computer, Inc. build 11) compiled on Aug 24 2016

Ubuntuでaptを使ってインストールできる最新のNASMのバージョンは以下の通り。

$ nasm -v
NASM version 2.10.09 compiled on Jun 28 2018

この通り、バージョンが大幅に違う。 appleが独自にメンテしているからバージョンの進み方が違うのかなと思ったけど、 単に古いだけっぽくて、最新のmacOS向けのビルドは以下のリンクで配布されている。 Index of /pub/nasm/releasebuilds/2.13/macosx

まとめ

このようにアセンブラのversionが違うと、出力されるopcodeが変わってくるので気をつけたい。

LLVM IR、LLVM bitcodeを扱うコマンドたちのメモ

LLVM IR、LLVM bitcodeを扱うコマンドをよく忘れるのでメモしておく。 CのコードをLLVM IR、LLVM bitcodeに変換するコマンド、LLVM bitcodeをインタプリタから実行するコマンド、コンパイルするコマンドなどを書いておく。 以下のCのコードを変換していく。

# include <stdio.h>

int main() { 
  int a = 1;
  int b = 2;
  int sum = a + b;
  printf("%d", sum);
  return 0;
}

LLVM IRを出力する

LLVM内ではLLVM IRという中間言語表現が用いられる。LLVM内で使えるアセンブリのようなものである。 LLVMを用いたコンパイラでは、ソースコードLLVM IRコードに変換したあと、そのLLVM IRコードをターゲットのアーキテクチャのバイナリに変換することでコンパイルが行われる。

Cのコードを変換する

clangに-emit-llvm-Sの2つのオプションを指定して実行するとLLVM IRが出力される。 以下のようにコマンドを実行するとtest.llが出力される。

$ clang test.c -emit-llvm -S

出力されたLLVM IR

以下のようなLLVM IRのコードが出力される。

$ cat test.ll
; ModuleID = 'test.c'
source_filename = "test.c"
target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-apple-macosx10.12.0"

@.str = private unnamed_addr constant [3 x i8] c"%d\00", align 1

; Function Attrs: nounwind ssp uwtable
define i32 @main() #0 {
  %1 = alloca i32, align 4
  %2 = alloca i32, align 4
  %3 = alloca i32, align 4
  %4 = alloca i32, align 4
  store i32 0, i32* %1, align 4
  store i32 1, i32* %2, align 4
  store i32 2, i32* %3, align 4
  %5 = load i32, i32* %2, align 4
  %6 = load i32, i32* %3, align 4
  %7 = add nsw i32 %5, %6
  store i32 %7, i32* %4, align 4
  %8 = load i32, i32* %4, align 4
  %9 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([3 x i8], [3 x i8]* @.str, i32 0, i32 0), i32 %8)
  ret i32 0
}

declare i32 @printf(i8*, ...) #1

attributes #0 = { nounwind ssp uwtable "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="penryn" "target-features"="+cx16,+fxsr,+mmx,+sse,+sse2,+sse3,+sse4.1,+ssse3" "unsafe-fp-math"="false" "use-soft-float"="false" }
attributes #1 = { "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="penryn" "target-features"="+cx16,+fxsr,+mmx,+sse,+sse2,+sse3,+sse4.1,+ssse3" "unsafe-fp-math"="false" "use-soft-float"="false" }

!llvm.module.flags = !{!0}
!llvm.ident = !{!1}

!0 = !{i32 1, !"PIC Level", i32 2}
!1 = !{!"Apple LLVM version 8.0.0 (clang-800.0.38)"}

LLVM bitcodeを出力する

LLVM bitcodeはLLVM IRのバイナリフォーマットである。 LLVM IRと LLVM bitocodeは相互変換でき、LLVM bitcodeはバイナリ(.out, .exeなど)に変換せずとも、LLVMインタプリタから直接実行することができる。

Cのコードを変換する

clangに-emit-llvm-cの2つのオプションを指定して実行するとLLVM bitcodeが出力される。 以下のようにコマンドを実行するとtest.bcが出力される。

$ clang test.c -emit-llvm -c

LLVM IRを変換する

llvm-asコマンドを使うことでLLVM IRをLLVM bitcodeに変換できる。 以下のようにコマンドを実行するとtest.bcが出力される。

$ llvm-as test.ll 

出力されたLLVM bitcode

人の目で直接読むのはきびしい。

$ file test.bc
test.bc: LLVM bitcode, wrapper x86_64
$ hexdump -C test.bc
00000000  de c0 17 0b 00 00 00 00  14 00 00 00 a8 09 00 00  |................|
00000010  07 00 00 01 42 43 c0 de  35 14 00 00 05 00 00 00  |....BC..5.......|
00000020  62 0c 30 24 49 59 be a6  ee d3 3e 2d 44 01 32 05  |b.0$IY....>-D.2.|
00000030  00 00 00 00 21 0c 00 00  1e 02 00 00 0b 02 21 00  |....!.........!.|
00000040  02 00 00 00 13 00 00 00  07 81 23 91 41 c8 04 49  |..........#.A..I|
00000050  06 10 32 39 92 01 84 0c  25 05 08 19 1e 04 8b 62  |..29....%......b|
00000060  80 10 45 02 42 92 0b 42  84 10 32 14 38 08 18 4b  |..E.B..B..2.8..K|
00000070  0a 32 42 88 48 90 14 20  43 46 88 a5 00 19 32 42  |.2B.H.. CF....2B|
00000080  04 49 0e 90 11 22 c4 50  41 51 81 8c e1 83 e5 8a  |.I...".PAQ......|
00000090  04 21 46 06 51 18 00 00  e9 00 00 00 1b 4c 25 f8  |.!F.Q........L%.|
000000a0  ff ff ff ff 01 90 00 0d  08 03 82 1c d2 61 1e c2  |.............a..|
000000b0  41 1c d8 a1 1c da 80 1e  c2 21 1d d8 a1 0d c6 21  |A........!.....!|
....

LLVM bitcodeをLLVM IRにデコンパイル

相互変換できるのでLLVM IRに戻すことができる。すごい。

$ llvm-dis test.bc

LLVM bitcodeをインタプリタで実行する

lliコマンドを使うことでLLVM bitcodeをインタプリタから直接実行できる。

$ lli test.bc 
3

LLVMの bitcodeをバイナリにする

llcコマンドを使うことでLLVM bitcodeをターゲットアーキテクチャアセンブリに変換し、そのアセンブリをclangでコンパイルすることでバイナリが出力される。

$ llc test.bc 
$ clang test.s
$ ./a.out
3

LLVMのPassを題材にした0CTF CTF quals 2017のChoicesを解いた

最近、LLVMに興味があって、いろいろ調べているうちにLLVMのPassのreversingの問題を見つけたので解いてみた。

write-ups-2017/0ctf-quals-2017/reverse/Choices-297 at master · ctfs/write-ups-2017

問題

All roads lead to Vegas.
Compile: clang -Xclang -load -Xclang lib0opsPass.so -mllvm -oopsSeed=BAADF00DCAFEBABE3043544620170318 source.c
Clang && LLVM Version: 3.9.1

Choicesとlib0opsPass.soの2つの64bitのELFバイナリが与えられる。lib0opsPass.soはLLVMのPassのバイナリっぽい。

$ file Choices
Choices: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 2.6.32, not stripped

$ file lib0opsPass.so 
lib0opsPass.so: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, BuildID[sha1]=2662bbaf3e7f926a3773d814e5f3c63240ee57e5, not stripped

解く

ChoicesをIDAで見てみると、main関数でcalculation関数を呼んだ後、memcmpでデータとflagを比較してflagがあってたらCorrect!! The flag is %sを出力している。 f:id:TAKEmaru:20180608031647p:plain

calculation関数はCFGをflattenにする、Control Flow Flatteningという難読化が施されている。このCFGを生成するのにhopperは結構時間かかったけど、IDAはシュッと生成してくれてすごい。高いだけある。

f:id:TAKEmaru:20180608031603p:plain

flattenになっているCFGの一番上でscanfで入力を受けている。

f:id:TAKEmaru:20180608031709p:plain

どのように難読化したのかを知りたいので、lib0opsPass.soをIDAで見る。 OSSLLVMを使った難読化ツールであるobfuscator-llvm/obfuscatorと全く同じシンボルがいくつもあって、これを参考に実装されているのが分かっておもしろい。

Oops::CryptoUtils::hogeのようなシンボルが多数あったので、 ida/idapython_tools/findcrypt · you0708/idaを使って、 暗号で使われている定数の抽出を試みた。以下のようにRijndaelで使われているラウンドキーを見つけることができた。

f:id:TAKEmaru:20180608034828p:plain f:id:TAKEmaru:20180608035745p:plain

このキーは、scramble32関数で使われていた。 switchのcaseで指定する値を生成するのにこの関数は使われていて、Control Flow Flatteningを施すOops::OopsFlattening::flatten関数で呼び出されていた。 switch文を使って無駄に分岐をいれることでCFGをflatにすることができる。 以下にControl Flow Flatteningによる難読化例を示す。 https://github.com/obfuscator-llvm/obfuscator/wiki/Control-Flow-Flatteningよりコードは引用した。

難読化前の例

#include <stdlib.h>
int main(int argc, char** argv) {
  int a = atoi(argv[1]);
  if(a == 0)
    return 1;
  else
    return 10;
  return 0;
}

難読化後の例

case 0の部分に難読化前で行っていたコードが入っている。それ以外の分岐では無意味なコードが実行される。

#include <stdlib.h>
int main(int argc, char** argv) {
  int a = atoi(argv[1]);
  int b = 0;
  while(1) {
    switch(b) {
      case 0:
        # 本来行われる処理
        if(a == 0)
          b = 1;
        else
          b = 2;
        break;
      case 1:
        return 1;
      case 2:
        return 10;
      default:
        break;
    }
  }
  return 0;
}

solverを書く

switch文の中で意味のある処理を行う部分の処理を実行するような値をscanfで入力することを考えればいい。 コンパイル時に指定したseed値のBAADF00DCAFEBABE3043544620170318とLabel%dで読み取られる難読化対象の関数のindex、Rijndaelのラウンドキーによってaesっぽい暗号化をすることによってswitchのcaseの値は生成されている。 aesっぽくあるもののRound数が4回と少ないことや、必要なロジックを省いているので完全なaesではない。 Oops::OopsFlattening::flattenでscramble32関数を呼んでいるあたりのロジックをPythonで書き起こし、switch文の全ての分岐を実行することでflagを出力させる作戦でいく。 scramble32関数は obfuscator/CryptoUtils.cpp at llvm-4.0 · obfuscator-llvm/obfuscator · GitHubと完全に一致していておもしろい。

f:id:TAKEmaru:20180608195754p:plain

RijndaelのラウンドキーをIDAからコピペするのに、ふるかわプロに教えてもらったLazyIDAを使った。便利。

github.com

#!/usr/bin/env python2
# coding: UTF-8


Rijndael_Te0 = [
    0xC66363A5, 0xF87C7C84, 0xEE777799, 0xF67B7B8D, 0xFFF2F20D, 0xD66B6BBD, 0xDE6F6FB1, 0x91C5C554, 0x60303050, 0x02010103, 0xCE6767A9, 0x562B2B7D, 0xE7FEFE19, 0xB5D7D762, 0x4DABABE6, 0xEC76769A, 0x8FCACA45, 0x1F82829D, 0x89C9C940, 0xFA7D7D87, 0xEFFAFA15, 0xB25959EB, 0x8E4747C9, 0xFBF0F00B, 0x41ADADEC, 0xB3D4D467, 0x5FA2A2FD, 0x45AFAFEA, 0x239C9CBF, 0x53A4A4F7, 0xE4727296, 0x9BC0C05B, 0x75B7B7C2, 0xE1FDFD1C, 0x3D9393AE, 0x4C26266A, 0x6C36365A, 0x7E3F3F41, 0xF5F7F702, 0x83CCCC4F, 0x6834345C,
    0x51A5A5F4, 0xD1E5E534, 0xF9F1F108, 0xE2717193, 0xABD8D873, 0x62313153, 0x2A15153F, 0x0804040C, 0x95C7C752, 0x46232365, 0x9DC3C35E, 0x30181828, 0x379696A1, 0x0A05050F, 0x2F9A9AB5, 0x0E070709, 0x24121236, 0x1B80809B, 0xDFE2E23D, 0xCDEBEB26, 0x4E272769, 0x7FB2B2CD, 0xEA75759F, 0x1209091B, 0x1D83839E, 0x582C2C74, 0x341A1A2E, 0x361B1B2D, 0xDC6E6EB2, 0xB45A5AEE, 0x5BA0A0FB, 0xA45252F6, 0x763B3B4D, 0xB7D6D661, 0x7DB3B3CE, 0x5229297B, 0xDDE3E33E, 0x5E2F2F71, 0x13848497, 0xA65353F5, 0xB9D1D168,
    0x00000000, 0xC1EDED2C, 0x40202060, 0xE3FCFC1F, 0x79B1B1C8, 0xB65B5BED, 0xD46A6ABE, 0x8DCBCB46, 0x67BEBED9, 0x7239394B, 0x944A4ADE, 0x984C4CD4, 0xB05858E8, 0x85CFCF4A, 0xBBD0D06B, 0xC5EFEF2A, 0x4FAAAAE5, 0xEDFBFB16, 0x864343C5, 0x9A4D4DD7, 0x66333355, 0x11858594, 0x8A4545CF, 0xE9F9F910, 0x04020206, 0xFE7F7F81, 0xA05050F0, 0x783C3C44, 0x259F9FBA, 0x4BA8A8E3, 0xA25151F3, 0x5DA3A3FE, 0x804040C0, 0x058F8F8A, 0x3F9292AD, 0x219D9DBC, 0x70383848, 0xF1F5F504, 0x63BCBCDF, 0x77B6B6C1, 0xAFDADA75,
    0x42212163, 0x20101030, 0xE5FFFF1A, 0xFDF3F30E, 0xBFD2D26D, 0x81CDCD4C, 0x180C0C14, 0x26131335, 0xC3ECEC2F, 0xBE5F5FE1, 0x359797A2, 0x884444CC, 0x2E171739, 0x93C4C457, 0x55A7A7F2, 0xFC7E7E82, 0x7A3D3D47, 0xC86464AC, 0xBA5D5DE7, 0x3219192B, 0xE6737395, 0xC06060A0, 0x19818198, 0x9E4F4FD1, 0xA3DCDC7F, 0x44222266, 0x542A2A7E, 0x3B9090AB, 0x0B888883, 0x8C4646CA, 0xC7EEEE29, 0x6BB8B8D3, 0x2814143C, 0xA7DEDE79, 0xBC5E5EE2, 0x160B0B1D, 0xADDBDB76, 0xDBE0E03B, 0x64323256, 0x743A3A4E, 0x140A0A1E,
    0x924949DB, 0x0C06060A, 0x4824246C, 0xB85C5CE4, 0x9FC2C25D, 0xBDD3D36E, 0x43ACACEF, 0xC46262A6, 0x399191A8, 0x319595A4, 0xD3E4E437, 0xF279798B, 0xD5E7E732, 0x8BC8C843, 0x6E373759, 0xDA6D6DB7, 0x018D8D8C, 0xB1D5D564, 0x9C4E4ED2, 0x49A9A9E0, 0xD86C6CB4, 0xAC5656FA, 0xF3F4F407, 0xCFEAEA25, 0xCA6565AF, 0xF47A7A8E, 0x47AEAEE9, 0x10080818, 0x6FBABAD5, 0xF0787888, 0x4A25256F, 0x5C2E2E72, 0x381C1C24, 0x57A6A6F1, 0x73B4B4C7, 0x97C6C651, 0xCBE8E823, 0xA1DDDD7C, 0xE874749C, 0x3E1F1F21, 0x964B4BDD,
    0x61BDBDDC, 0x0D8B8B86, 0x0F8A8A85, 0xE0707090, 0x7C3E3E42, 0x71B5B5C4, 0xCC6666AA, 0x904848D8, 0x06030305, 0xF7F6F601, 0x1C0E0E12, 0xC26161A3, 0x6A35355F, 0xAE5757F9, 0x69B9B9D0, 0x17868691, 0x99C1C158, 0x3A1D1D27, 0x279E9EB9, 0xD9E1E138, 0xEBF8F813, 0x2B9898B3, 0x22111133, 0xD26969BB, 0xA9D9D970, 0x078E8E89, 0x339494A7, 0x2D9B9BB6, 0x3C1E1E22, 0x15878792, 0xC9E9E920, 0x87CECE49, 0xAA5555FF, 0x50282878, 0xA5DFDF7A, 0x038C8C8F, 0x59A1A1F8, 0x09898980, 0x1A0D0D17, 0x65BFBFDA, 0xD7E6E631,
    0x844242C6, 0xD06868B8, 0x824141C3, 0x299999B0, 0x5A2D2D77, 0x1E0F0F11, 0x7BB0B0CB, 0xA85454FC, 0x6DBBBBD6, 0x2C16163A
]

Rijndael_Te1 = [
    0xA5C66363, 0x84F87C7C, 0x99EE7777, 0x8DF67B7B, 0x0DFFF2F2, 0xBDD66B6B, 0xB1DE6F6F, 0x5491C5C5, 0x50603030, 0x03020101, 0xA9CE6767, 0x7D562B2B, 0x19E7FEFE, 0x62B5D7D7, 0xE64DABAB, 0x9AEC7676, 0x458FCACA, 0x9D1F8282, 0x4089C9C9, 0x87FA7D7D, 0x15EFFAFA, 0xEBB25959, 0xC98E4747, 0x0BFBF0F0, 0xEC41ADAD, 0x67B3D4D4, 0xFD5FA2A2, 0xEA45AFAF, 0xBF239C9C, 0xF753A4A4, 0x96E47272, 0x5B9BC0C0, 0xC275B7B7, 0x1CE1FDFD, 0xAE3D9393, 0x6A4C2626, 0x5A6C3636, 0x417E3F3F, 0x02F5F7F7, 0x4F83CCCC, 0x5C683434,
    0xF451A5A5, 0x34D1E5E5, 0x08F9F1F1, 0x93E27171, 0x73ABD8D8, 0x53623131, 0x3F2A1515, 0x0C080404, 0x5295C7C7, 0x65462323, 0x5E9DC3C3, 0x28301818, 0xA1379696, 0x0F0A0505, 0xB52F9A9A, 0x090E0707, 0x36241212, 0x9B1B8080, 0x3DDFE2E2, 0x26CDEBEB, 0x694E2727, 0xCD7FB2B2, 0x9FEA7575, 0x1B120909, 0x9E1D8383, 0x74582C2C, 0x2E341A1A, 0x2D361B1B, 0xB2DC6E6E, 0xEEB45A5A, 0xFB5BA0A0, 0xF6A45252, 0x4D763B3B, 0x61B7D6D6, 0xCE7DB3B3, 0x7B522929, 0x3EDDE3E3, 0x715E2F2F, 0x97138484, 0xF5A65353, 0x68B9D1D1,
    0x00000000, 0x2CC1EDED, 0x60402020, 0x1FE3FCFC, 0xC879B1B1, 0xEDB65B5B, 0xBED46A6A, 0x468DCBCB, 0xD967BEBE, 0x4B723939, 0xDE944A4A, 0xD4984C4C, 0xE8B05858, 0x4A85CFCF, 0x6BBBD0D0, 0x2AC5EFEF, 0xE54FAAAA, 0x16EDFBFB, 0xC5864343, 0xD79A4D4D, 0x55663333, 0x94118585, 0xCF8A4545, 0x10E9F9F9, 0x06040202, 0x81FE7F7F, 0xF0A05050, 0x44783C3C, 0xBA259F9F, 0xE34BA8A8, 0xF3A25151, 0xFE5DA3A3, 0xC0804040, 0x8A058F8F, 0xAD3F9292, 0xBC219D9D, 0x48703838, 0x04F1F5F5, 0xDF63BCBC, 0xC177B6B6, 0x75AFDADA,
    0x63422121, 0x30201010, 0x1AE5FFFF, 0x0EFDF3F3, 0x6DBFD2D2, 0x4C81CDCD, 0x14180C0C, 0x35261313, 0x2FC3ECEC, 0xE1BE5F5F, 0xA2359797, 0xCC884444, 0x392E1717, 0x5793C4C4, 0xF255A7A7, 0x82FC7E7E, 0x477A3D3D, 0xACC86464, 0xE7BA5D5D, 0x2B321919, 0x95E67373, 0xA0C06060, 0x98198181, 0xD19E4F4F, 0x7FA3DCDC, 0x66442222, 0x7E542A2A, 0xAB3B9090, 0x830B8888, 0xCA8C4646, 0x29C7EEEE, 0xD36BB8B8, 0x3C281414, 0x79A7DEDE, 0xE2BC5E5E, 0x1D160B0B, 0x76ADDBDB, 0x3BDBE0E0, 0x56643232, 0x4E743A3A, 0x1E140A0A,
    0xDB924949, 0x0A0C0606, 0x6C482424, 0xE4B85C5C, 0x5D9FC2C2, 0x6EBDD3D3, 0xEF43ACAC, 0xA6C46262, 0xA8399191, 0xA4319595, 0x37D3E4E4, 0x8BF27979, 0x32D5E7E7, 0x438BC8C8, 0x596E3737, 0xB7DA6D6D, 0x8C018D8D, 0x64B1D5D5, 0xD29C4E4E, 0xE049A9A9, 0xB4D86C6C, 0xFAAC5656, 0x07F3F4F4, 0x25CFEAEA, 0xAFCA6565, 0x8EF47A7A, 0xE947AEAE, 0x18100808, 0xD56FBABA, 0x88F07878, 0x6F4A2525, 0x725C2E2E, 0x24381C1C, 0xF157A6A6, 0xC773B4B4, 0x5197C6C6, 0x23CBE8E8, 0x7CA1DDDD, 0x9CE87474, 0x213E1F1F, 0xDD964B4B,
    0xDC61BDBD, 0x860D8B8B, 0x850F8A8A, 0x90E07070, 0x427C3E3E, 0xC471B5B5, 0xAACC6666, 0xD8904848, 0x05060303, 0x01F7F6F6, 0x121C0E0E, 0xA3C26161, 0x5F6A3535, 0xF9AE5757, 0xD069B9B9, 0x91178686, 0x5899C1C1, 0x273A1D1D, 0xB9279E9E, 0x38D9E1E1, 0x13EBF8F8, 0xB32B9898, 0x33221111, 0xBBD26969, 0x70A9D9D9, 0x89078E8E, 0xA7339494, 0xB62D9B9B, 0x223C1E1E, 0x92158787, 0x20C9E9E9, 0x4987CECE, 0xFFAA5555, 0x78502828, 0x7AA5DFDF, 0x8F038C8C, 0xF859A1A1, 0x80098989, 0x171A0D0D, 0xDA65BFBF, 0x31D7E6E6,
    0xC6844242, 0xB8D06868, 0xC3824141, 0xB0299999, 0x775A2D2D, 0x111E0F0F, 0xCB7BB0B0, 0xFCA85454, 0xD66DBBBB, 0x3A2C1616
]

Rijndael_Te2 = [
    0x63A5C663, 0x7C84F87C, 0x7799EE77, 0x7B8DF67B, 0xF20DFFF2, 0x6BBDD66B, 0x6FB1DE6F, 0xC55491C5, 0x30506030, 0x01030201, 0x67A9CE67, 0x2B7D562B, 0xFE19E7FE, 0xD762B5D7, 0xABE64DAB, 0x769AEC76, 0xCA458FCA, 0x829D1F82, 0xC94089C9, 0x7D87FA7D, 0xFA15EFFA, 0x59EBB259, 0x47C98E47, 0xF00BFBF0, 0xADEC41AD, 0xD467B3D4, 0xA2FD5FA2, 0xAFEA45AF, 0x9CBF239C, 0xA4F753A4, 0x7296E472, 0xC05B9BC0, 0xB7C275B7, 0xFD1CE1FD, 0x93AE3D93, 0x266A4C26, 0x365A6C36, 0x3F417E3F, 0xF702F5F7, 0xCC4F83CC, 0x345C6834,
    0xA5F451A5, 0xE534D1E5, 0xF108F9F1, 0x7193E271, 0xD873ABD8, 0x31536231, 0x153F2A15, 0x040C0804, 0xC75295C7, 0x23654623, 0xC35E9DC3, 0x18283018, 0x96A13796, 0x050F0A05, 0x9AB52F9A, 0x07090E07, 0x12362412, 0x809B1B80, 0xE23DDFE2, 0xEB26CDEB, 0x27694E27, 0xB2CD7FB2, 0x759FEA75, 0x091B1209, 0x839E1D83, 0x2C74582C, 0x1A2E341A, 0x1B2D361B, 0x6EB2DC6E, 0x5AEEB45A, 0xA0FB5BA0, 0x52F6A452, 0x3B4D763B, 0xD661B7D6, 0xB3CE7DB3, 0x297B5229, 0xE33EDDE3, 0x2F715E2F, 0x84971384, 0x53F5A653, 0xD168B9D1,
    0x00000000, 0xED2CC1ED, 0x20604020, 0xFC1FE3FC, 0xB1C879B1, 0x5BEDB65B, 0x6ABED46A, 0xCB468DCB, 0xBED967BE, 0x394B7239, 0x4ADE944A, 0x4CD4984C, 0x58E8B058, 0xCF4A85CF, 0xD06BBBD0, 0xEF2AC5EF, 0xAAE54FAA, 0xFB16EDFB, 0x43C58643, 0x4DD79A4D, 0x33556633, 0x85941185, 0x45CF8A45, 0xF910E9F9, 0x02060402, 0x7F81FE7F, 0x50F0A050, 0x3C44783C, 0x9FBA259F, 0xA8E34BA8, 0x51F3A251, 0xA3FE5DA3, 0x40C08040, 0x8F8A058F, 0x92AD3F92, 0x9DBC219D, 0x38487038, 0xF504F1F5, 0xBCDF63BC, 0xB6C177B6, 0xDA75AFDA,
    0x21634221, 0x10302010, 0xFF1AE5FF, 0xF30EFDF3, 0xD26DBFD2, 0xCD4C81CD, 0x0C14180C, 0x13352613, 0xEC2FC3EC, 0x5FE1BE5F, 0x97A23597, 0x44CC8844, 0x17392E17, 0xC45793C4, 0xA7F255A7, 0x7E82FC7E, 0x3D477A3D, 0x64ACC864, 0x5DE7BA5D, 0x192B3219, 0x7395E673, 0x60A0C060, 0x81981981, 0x4FD19E4F, 0xDC7FA3DC, 0x22664422, 0x2A7E542A, 0x90AB3B90, 0x88830B88, 0x46CA8C46, 0xEE29C7EE, 0xB8D36BB8, 0x143C2814, 0xDE79A7DE, 0x5EE2BC5E, 0x0B1D160B, 0xDB76ADDB, 0xE03BDBE0, 0x32566432, 0x3A4E743A, 0x0A1E140A,
    0x49DB9249, 0x060A0C06, 0x246C4824, 0x5CE4B85C, 0xC25D9FC2, 0xD36EBDD3, 0xACEF43AC, 0x62A6C462, 0x91A83991, 0x95A43195, 0xE437D3E4, 0x798BF279, 0xE732D5E7, 0xC8438BC8, 0x37596E37, 0x6DB7DA6D, 0x8D8C018D, 0xD564B1D5, 0x4ED29C4E, 0xA9E049A9, 0x6CB4D86C, 0x56FAAC56, 0xF407F3F4, 0xEA25CFEA, 0x65AFCA65, 0x7A8EF47A, 0xAEE947AE, 0x08181008, 0xBAD56FBA, 0x7888F078, 0x256F4A25, 0x2E725C2E, 0x1C24381C, 0xA6F157A6, 0xB4C773B4, 0xC65197C6, 0xE823CBE8, 0xDD7CA1DD, 0x749CE874, 0x1F213E1F, 0x4BDD964B,
    0xBDDC61BD, 0x8B860D8B, 0x8A850F8A, 0x7090E070, 0x3E427C3E, 0xB5C471B5, 0x66AACC66, 0x48D89048, 0x03050603, 0xF601F7F6, 0x0E121C0E, 0x61A3C261, 0x355F6A35, 0x57F9AE57, 0xB9D069B9, 0x86911786, 0xC15899C1, 0x1D273A1D, 0x9EB9279E, 0xE138D9E1, 0xF813EBF8, 0x98B32B98, 0x11332211, 0x69BBD269, 0xD970A9D9, 0x8E89078E, 0x94A73394, 0x9BB62D9B, 0x1E223C1E, 0x87921587, 0xE920C9E9, 0xCE4987CE, 0x55FFAA55, 0x28785028, 0xDF7AA5DF, 0x8C8F038C, 0xA1F859A1, 0x89800989, 0x0D171A0D, 0xBFDA65BF, 0xE631D7E6,
    0x42C68442, 0x68B8D068, 0x41C38241, 0x99B02999, 0x2D775A2D, 0x0F111E0F, 0xB0CB7BB0, 0x54FCA854, 0xBBD66DBB, 0x163A2C16
]

Rijndael_Te3 = [
    0x6363A5C6, 0x7C7C84F8, 0x777799EE, 0x7B7B8DF6, 0xF2F20DFF, 0x6B6BBDD6, 0x6F6FB1DE, 0xC5C55491, 0x30305060, 0x01010302, 0x6767A9CE, 0x2B2B7D56, 0xFEFE19E7, 0xD7D762B5, 0xABABE64D, 0x76769AEC, 0xCACA458F, 0x82829D1F, 0xC9C94089, 0x7D7D87FA, 0xFAFA15EF, 0x5959EBB2, 0x4747C98E, 0xF0F00BFB, 0xADADEC41, 0xD4D467B3, 0xA2A2FD5F, 0xAFAFEA45, 0x9C9CBF23, 0xA4A4F753, 0x727296E4, 0xC0C05B9B, 0xB7B7C275, 0xFDFD1CE1, 0x9393AE3D, 0x26266A4C, 0x36365A6C, 0x3F3F417E, 0xF7F702F5, 0xCCCC4F83, 0x34345C68,
    0xA5A5F451, 0xE5E534D1, 0xF1F108F9, 0x717193E2, 0xD8D873AB, 0x31315362, 0x15153F2A, 0x04040C08, 0xC7C75295, 0x23236546, 0xC3C35E9D, 0x18182830, 0x9696A137, 0x05050F0A, 0x9A9AB52F, 0x0707090E, 0x12123624, 0x80809B1B, 0xE2E23DDF, 0xEBEB26CD, 0x2727694E, 0xB2B2CD7F, 0x75759FEA, 0x09091B12, 0x83839E1D, 0x2C2C7458, 0x1A1A2E34, 0x1B1B2D36, 0x6E6EB2DC, 0x5A5AEEB4, 0xA0A0FB5B, 0x5252F6A4, 0x3B3B4D76, 0xD6D661B7, 0xB3B3CE7D, 0x29297B52, 0xE3E33EDD, 0x2F2F715E, 0x84849713, 0x5353F5A6, 0xD1D168B9,
    0x00000000, 0xEDED2CC1, 0x20206040, 0xFCFC1FE3, 0xB1B1C879, 0x5B5BEDB6, 0x6A6ABED4, 0xCBCB468D, 0xBEBED967, 0x39394B72, 0x4A4ADE94, 0x4C4CD498, 0x5858E8B0, 0xCFCF4A85, 0xD0D06BBB, 0xEFEF2AC5, 0xAAAAE54F, 0xFBFB16ED, 0x4343C586, 0x4D4DD79A, 0x33335566, 0x85859411, 0x4545CF8A, 0xF9F910E9, 0x02020604, 0x7F7F81FE, 0x5050F0A0, 0x3C3C4478, 0x9F9FBA25, 0xA8A8E34B, 0x5151F3A2, 0xA3A3FE5D, 0x4040C080, 0x8F8F8A05, 0x9292AD3F, 0x9D9DBC21, 0x38384870, 0xF5F504F1, 0xBCBCDF63, 0xB6B6C177, 0xDADA75AF,
    0x21216342, 0x10103020, 0xFFFF1AE5, 0xF3F30EFD, 0xD2D26DBF, 0xCDCD4C81, 0x0C0C1418, 0x13133526, 0xECEC2FC3, 0x5F5FE1BE, 0x9797A235, 0x4444CC88, 0x1717392E, 0xC4C45793, 0xA7A7F255, 0x7E7E82FC, 0x3D3D477A, 0x6464ACC8, 0x5D5DE7BA, 0x19192B32, 0x737395E6, 0x6060A0C0, 0x81819819, 0x4F4FD19E, 0xDCDC7FA3, 0x22226644, 0x2A2A7E54, 0x9090AB3B, 0x8888830B, 0x4646CA8C, 0xEEEE29C7, 0xB8B8D36B, 0x14143C28, 0xDEDE79A7, 0x5E5EE2BC, 0x0B0B1D16, 0xDBDB76AD, 0xE0E03BDB, 0x32325664, 0x3A3A4E74, 0x0A0A1E14,
    0x4949DB92, 0x06060A0C, 0x24246C48, 0x5C5CE4B8, 0xC2C25D9F, 0xD3D36EBD, 0xACACEF43, 0x6262A6C4, 0x9191A839, 0x9595A431, 0xE4E437D3, 0x79798BF2, 0xE7E732D5, 0xC8C8438B, 0x3737596E, 0x6D6DB7DA, 0x8D8D8C01, 0xD5D564B1, 0x4E4ED29C, 0xA9A9E049, 0x6C6CB4D8, 0x5656FAAC, 0xF4F407F3, 0xEAEA25CF, 0x6565AFCA, 0x7A7A8EF4, 0xAEAEE947, 0x08081810, 0xBABAD56F, 0x787888F0, 0x25256F4A, 0x2E2E725C, 0x1C1C2438, 0xA6A6F157, 0xB4B4C773, 0xC6C65197, 0xE8E823CB, 0xDDDD7CA1, 0x74749CE8, 0x1F1F213E, 0x4B4BDD96,
    0xBDBDDC61, 0x8B8B860D, 0x8A8A850F, 0x707090E0, 0x3E3E427C, 0xB5B5C471, 0x6666AACC, 0x4848D890, 0x03030506, 0xF6F601F7, 0x0E0E121C, 0x6161A3C2, 0x35355F6A, 0x5757F9AE, 0xB9B9D069, 0x86869117, 0xC1C15899, 0x1D1D273A, 0x9E9EB927, 0xE1E138D9, 0xF8F813EB, 0x9898B32B, 0x11113322, 0x6969BBD2, 0xD9D970A9, 0x8E8E8907, 0x9494A733, 0x9B9BB62D, 0x1E1E223C, 0x87879215, 0xE9E920C9, 0xCECE4987, 0x5555FFAA, 0x28287850, 0xDFDF7AA5, 0x8C8C8F03, 0xA1A1F859, 0x89898009, 0x0D0D171A, 0xBFBFDA65, 0xE6E631D7,
    0x4242C684, 0x6868B8D0, 0x4141C382, 0x9999B029, 0x2D2D775A, 0x0F0F111E, 0xB0B0CB7B, 0x5454FCA8, 0xBBBBD66D, 0x16163A2C
]


def gen_pool():
    out = []
    for i in range(0x2000):
      ctr = '\0' * 8 + struct.pack('>Q', i+1)
      out.append(aes.encrypt(ctr))
    return ''.join(out)

def scramble32(input, key):
    # Round 1
    tmpA = 0x0
    tmpA ^= Rijndael_Te0[((input >> 24) ^ key[0]) & 0xFF]
    tmpA ^= Rijndael_Te1[((input >> 16) ^ key[1]) & 0xFF]
    tmpA ^= Rijndael_Te2[((input >> 8) ^ key[2]) & 0xFF]
    tmpA ^= Rijndael_Te3[((input >> 0) ^ key[3]) & 0xFF]

    # Round 2
    tmpB = 0x0
    tmpB ^= Rijndael_Te0[((tmpA >> 24) ^ key[4]) & 0xFF]
    tmpB ^= Rijndael_Te1[((tmpA >> 16) ^ key[5]) & 0xFF]
    tmpB ^= Rijndael_Te2[((tmpA >> 8) ^ key[6]) & 0xFF]
    tmpB ^= Rijndael_Te3[((tmpA >> 0) ^ key[7]) & 0xFF]

    # Round 3
    tmpA = 0x0
    tmpA ^= Rijndael_Te0[((tmpB >> 24) ^ key[8]) & 0xFF]
    tmpA ^= Rijndael_Te1[((tmpB >> 16) ^ key[9]) & 0xFF]
    tmpA ^= Rijndael_Te2[((tmpB >> 8) ^ key[10]) & 0xFF]
    tmpA ^= Rijndael_Te3[((tmpB >> 0) ^ key[11]) & 0xFF]

    # Round 4
    tmpB = 0x0
    tmpB ^= Rijndael_Te0[((tmpA >> 24) ^ key[12]) & 0xFF]
    tmpB ^= Rijndael_Te1[((tmpA >> 16) ^ key[13]) & 0xFF]
    tmpB ^= Rijndael_Te2[((tmpA >> 8) ^ key[14]) & 0xFF]
    tmpB ^= Rijndael_Te3[((tmpA >> 0) ^ key[15]) & 0xFF]

    LOAD32Hed = ((key[2] << 8) | (key[1] << 16) | (key[0] << 24) | key[3])
    return LOAD32Hed ^ tmpB

pool = gen_pool()

enc = map(ord, pool[:16])

for i in range(1000):
    x = scramble32(i, enc)
    print(struct.unpack('<i', struct.pack('<I', x))[0])

flag!!

$ python solver.py |./Choices 
Correct!! The flag is flag{wHy_d1D_you_Gen3R47e_cas3_c0nst_v4lUE_in_7h15_way?}