해당 CTF는 모바일 유니티(Unity) 게임의 미션은 보스를 잡은 후 플래그(Flag) 값을 획득하는 문제입니다.
CTF - 미션
앱 설치 후 캐릭터가 몬스터에게 다가갈 경우 2~3번 어택 당한 후 게임이 끝납니다.
Game Over 화면
Unity - ILB2CPP의 컴파일 과정을 알아야합니다.
0x1) ILB2CPP의 경우 IL를 C++ 소스코드로 변환
> C++ 컴파일러에 전달된 네이티브 라이브러리(*.SO)파일이 생성되는
구조로 AOT 컴파일 방식을 사용
0x2) IL코드를 읽고 기계어를 수행하는 JIT 컴파일 방식이 아님
> 미리 기계어를 만들고 수행하는 방식으로 속도 향상
0x3) 코드 크기를 줄일 수 있음(장점)
> IOS-64BIT Build 지원
> Interpreter를 거치지 않고 Instruction을 CPU가 바로 처리
0x4) 디버깅이 어려움(단점)
> Build 시간이 MONO 보다 느림
> Reflection을 사용하는 JSON 라이브러리에서 버그 발생률 높음
즉 Unity 컴파일 과정을 보면 il2cpp build 방식을 사용하며, IL Assembly 코드를 il2cpp.exe에 C++ 소스코드로 변환 과정을 거치고, C++ 컴파일러에 전달하여 Native library를 생성합니다.
IL2CPP – AOT 컴파일
Adventure of Warrior-fixed 앱을 디컴파일 후 "lib > armeabi-v7a" 경로에 "libil2cpp.so"파일을 확인할 수 있습니다.
Adventure of Warrior-fixed > libil2cpp.so
디컴파일된 "libil2cpp.so"파일을 IDA or Ghidra로 확인 시 심볼릭이 깨져있어 내부 메소드 정보를 확인할 수 없습니다.
"Il2CppDumper"도구를 사용하여 "libil2cpp.so"의 심볼릭을 복구합니다.
※"Il2CppDumper"도구로 "libil2cpp.so"의 심볼릭을 복구 시 "libil2cpp.so"와 "global-metadata.dat"를 지정합니다.
libil2cpp.so 심볼릭 복구
심볼릭 복구 시 아래 그림과 같이 "/Il2CppDumper-v6.6.5/DummyDll" 폴더에 "Assembly-CSharp.dll"파일이 생성됩니다.
Assembly-CSharp.dll
"Assembly-CSharp.dll"을 디컴파일 시 "SetHp" 함수가 확인 됐으며 해당 함수 "Offset 0x590FCC"의 값을 1만으로 리플레이스 되도록 후킹합니다.
Assembly-CSharp.dll - ShtHp Offset
FRIDA를 이용하여 SetHp 함수 값을 변조 후킹 시 캐릭터가 몬스터에 의해 죽지 않으며, Flag 값을 획득했습니다.
Flag 획득
※) JIT(Just-In-Time)
> 바이트코드를 컴퓨터 프로세서(CPU)로 직접 보낼 수 있는 명령어로 바꾸는 프로그램
※) IL(Intermediate Language)
> 스택 기반 어셈블리 언어
※) AOT컴파일(Ahead-Of-Time Compilation)
> 소스코드를 미리 컴파일 하는 방식을 의미
※) Reflection
> 구체적인 클래스 타입을 몰라도 클래스의 메소드들을 접근할 수 있게 하는 JAVA API