Frida로 유니티 게임 리버싱하기 (궁수의 전설)

2024. 1. 29. 14:56·Security/Reversing
반응형

서론

이번에는 지금까지 frida와 리버싱을 공부한 것을 토대로 모바일 게임 궁수의 전설(플레이스토어 링크)을 리버싱 해보겠습니다.
 
먼저, frida를 어떻게 사용해야 하는지, 앱 분석은 어떻게 진행되는지 알고 계시는 것을 추천드립니다.

일단 궁수의 전설 앱에서 사용하는 함수를 frida로 후킹하여 우리가 원하는 동작을 하도록 조작할 겁니다. (체력, 공격력 등등)
 

libil2cpp.so 파일 얻기

우리가 현재 하고자 하는것은 궁수의 전설 APK 파일 안에 있는 libil2cpp.so 파일을 얻어 소스코드의 메서드의 심볼 정보(메서드의 이름)와 그 메서드가 메모리에 존재하는 위치를 알아내야 합니다.
 
메서드의 심볼 정보(함수 이름 정보)는 후킹 할 메서드를 고르기 위해 필요하고(캐릭터의 체력을 올리는 메서드, 캐릭터가 죽었을 때 실행되는 메서드 등등) 메서드가 위치하는 메모리 주소는 frida로 해당 메서드를 후킹 할 때 필요합니다.
 
그럼 libil2cpp.so란 무엇일까요? 그 역할을 알아보도록 하겠습니다.
 

IL2CPP란?

https://docs.unity3d.com/kr/2021.3/Manual/IL2CPP.html

 

IL2CPP 개요 - Unity 매뉴얼

IL2CPP(C++로 변환하는 중간 언어) 스크립팅 백엔드는 Mono 백엔드의 대안입니다. IL2CPP는 보다 폭넓은 플랫폼에서 애플리케이션에 대한 더 나은 지원을 제공합니다. IL2CPP 백엔드는 MSIL (Microsoft 중간

docs.unity3d.com

위의 문서는 Unity에서 공식적으로 제공하는 IL2CPP 에 대한 내용입니다.
 
위 글을 정리하자면 Unity 게임을 만들 때, 개발자가 게임을 IL2CPP 방식으로 빌드한다면, 개발자가 코딩한 C# 언어는 IL(Intermediate Language, 중간 언어) 형태로 바뀌고 그 바뀐 IL 언어를 il2cpp.exe 라는 녀석이 C++ 코드로 바꿔주고, 그 바뀐 C++ 코드를 C++ 컴파일러가 게임이 설치될 플랫폼에 따라 네이티브 라이브러리 파일(.exe, .apk, .so)로 바꿔주는 역할을 하는 것입니다.
 
게임이 설치될 플랫폼 환경(CPU의 아키텍처라든지, PC 혹은 모바일에서 설치한다라든지..)에 따라 맞는 네이티브 라이브러리 파일을 만들 수 있습니다. 그래서 미리 컴파일을 해놓고 게임을 실행시킬 수 있기 때문에 로딩 속도가 빠릅니다. 이것을 AOT 컴파일(Ahead-Of-Time Compile)이라고 합니다.
 
또한 개발자가 코딩한 소스코드는 libil2cpp.so 파일에 기계어의 형태로 존재합니다. 하지만 소스코드의 메서드의 심볼 정보(메서드의 이름)는 제거되어 있기 때문에 이를 알아내는 방법이 필요합니다.
 
다행히 메서드의 심볼과 관련된 정보와 메모리에 실행될 때의 위치를 알려주는 유용한 도구가 있습니다.
바로 Il2CppDumper 입니다. (깃허브 링크)
 
Il2CppDumper는 apk 파일 안에 있는 libil2cpp.so 파일과 global-metadata.dat 파일(libil2cpp.so 파일의 심볼들이 들어있습니다.)을 조합해 소스코드의 메서드의 심볼 정보를 복구해 줍니다.
 
그럼 직접 Il2CppDumper를 사용해 심볼을 복구해 봅시다!!
먼저 libil2cpp.so 파일과 global-metadata.dat 파일을 얻기 위해 궁수의 전설 APK 파일을 구해봅시다.
 

궁수의 전설 APK 파일 얻기

우리는 지금까지 frida를 연습할 때 깃허브나 다른 사이트에서 분석할 APK 파일을 얻었는데요,
이제 실제로 운영되고 있는 게임 서비스의 APK  파일을 얻어야 합니다.
 
하지만 구글 플레이스토어에서 다운로드한 뒤 APK를 추출하면 우리가 분석해야 되는 libil2cpp.so파일을 APK 파일 안에서 찾을 수 없습니다.
 
이는 구글 플레이스토어의 정책 때문인데, AAB 형식으로 스토어에 앱을 올리도록 정책이 최근에 바뀌었습니다. (참고: https://yozm.wishket.com/magazine/detail/912/)
AAB로 배포된 앱은 Split Application의 형태로 존재하며 네이티브 라이브러리 파일들이 들어있는 lib 폴더가 없습니다.
 
따라서 apkcombo 사이트(합쳐진 형태의 완전한 APK를 다운로드 받을 수 있습니다.)에서 궁수의 전설을 검색하여 APK 파일을 얻겠습니다.

 


궁수의 전설을 검색하고 다운로드해 줍니다.
 
압축을 해제한 다음 libil2cpp.so 파일과 global-metadata.dat 파일의 경로를 알아둡시다.
 

 

Il2CppDumper 사용하기

libil2cpp.so 파일과 global-metadata.dat 파일을 얻었기 때문에 이제 Il2CppDumper를 사용해봅시다.

https://github.com/Perfare/Il2CppDumper/releases
 

Releases · Perfare/Il2CppDumper

Unity il2cpp reverse engineer. Contribute to Perfare/Il2CppDumper development by creating an account on GitHub.

github.com

 
위 링크에서 최신버전을 다운받고 압축을 풉니다.

 

압축을 풀고 cmd를 켜서 해당 폴더로 이동해줍니다.
그리고 다음 명령어를 사용하여 덤프를 수행합니다.

Il2CppDumper.exe <libil2cpp.so 파일 경로> <global-metadata.dat 파일 경로>

 

 

그러면 폴더에 dump.cs 라는 파일이 생성됩니다.
 

 

이것이 바로 우리가 필요한 메서드의 심볼 정보와 메서드의 메모리 주소 정보를 담고있는 파일입니다.
 
코드 에디터 vscode로 열어서 체력과 관련된 메서드를 열심히 찾아보겠습니다. (HP 로 검색하여 찾아야 합니다.)
 

 

체력 관련 메서드로 의심되는 함수를 찾았습니다.
 
일단 이 함수를 후킹해봅시다.
 
함수 위 주석의 VA가 메서드의 메모리 절대 주소입니다.(프로그램의 ImageBase로부터의 상대 주소는 RVA이고, 파일에서 메서드의 위치는 offset이라고 합니다.) 이 위치를 사용해 frida 후킹 코드를 작성하면 됩니다.
 
그런데 여기서 잠깐 짚고 넘어가야 할 것이 있습니다.

 

Frida 네이티브 라이브러리 후킹이 불가능한 경우

현재 frida는 x86 아키텍처 에뮬레이터(녹스, 블루스택, LD플레이어 등등)에서 로드되는 arm 네이티브 라이브러리 후킹을 지원하지 않습니다.
 
궁수의 전설 APK 파일 압축을 풀고 lib 폴더에 들어가 보면 다음 사진과 같이 arm 네이티브 라이브러리밖에 없는 것을 확인할 수 있습니다. (arm64-v8a 폴더, armeabi-v7a 폴더밖에 없는것을 확인할 수 있습니다. 이는 궁수의 전설 앱이 arm 기반 네이티브 라이브러리만 지원한다는 것을 의미합니다. x86은 지원하지 않습니다.)
 

 

그럼 x86 아키텍처인 녹스 에뮬레이터는 궁수의 전설을 어떻게 실행하는 걸까요?
 
x86 아키텍처 에뮬레이터들은 이 arm 라이브러리들을 libhoudini.so 라는 라이브러리(에뮬레이터 내부의 /system/lib 경로에 들어있습니다.)를 거쳐서 arm 네이티브 라이브러리를 로드하여 해석하기 때문에 실행이 가능한 것입니다.
 
x86에서 arm 네이티브 라이브러리는 libhoudini.so를 거치기 때문에 frida로 x86 환경에서 arm 네이티브 라이브러리 후킹이 불가능합니다.
 
https://github.com/frida/frida/issues/403


http://linforum.kr/bbs/board.php?bo_table=android&wr_id=5246

 

 


따라서 지금까지 x86 아키텍처인 녹스 에뮬레이터를 사용해 온 우리는 어떻게 해야 할까요?
해결할 수 있는 방법은 다음 세 가지가 있습니다.
 

  • 안드로이드 휴대폰을 루팅 하여 frida로 디버깅하기 (안드로이드 휴대폰은 arm 아키텍처를 사용하기 때문에 arm 네이티브 라이브러리 후킹이 가능합니다.)

 

  • 루팅 하지 않은 안드로이드 휴대폰에 frida-gadget을 설치하여 변조한 앱을 기기에 깔아서 frida로 디버깅하기 (frida-gadget은 루팅하지 않은 기기에 frida를 사용할 수 있도록 도와줍니다. 하지만 앱 안에 frida-gadget을 넣어야 하기 때문에 앱의 무결성이 깨집니다. 만약 앱이 스스로 무결성을 검사한다면 그것을 우회해야 정상적으로 작동할 것입니다.)

 

  • ARM 기반 에뮬레이터 사용하기 (그냥 단순하게 생각하여 arm 아키텍처를 사용하는 에뮬레이터를 사용하면 됩니다. 이를 위해 arm 아키텍쳐를 지원하는 클라우드 기반 에뮬레이터인 redroid(깃허브 링크)를 사용하면 됩니다.)

 
루팅 된 단말기가 있다면 편합니다. 어찌되었든 우리는 모바일 게임을 해킹하려고 하는것이기 때문에 컴퓨터에서 에뮬레이터를 사용해 게임을 컨트롤하는것 보다는 실제 단말기에서 게임을 손으로 컨트롤하며 디버깅해야 더 편합니다.
 
따라서 저는 제 단말기를 루팅해 계속하겠습니다.
 
이 글에서 루팅 과정은설명하고있지 않습니다. Magisk를 사용한 루팅 작업을 거친 후 계속해주세요!
 

Frida 후킹 코드 작성하기

frida 후킹 코드는 다음과 같이 작성했습니다.

// archero.js
function getHPMaxBaseHook() {
  let moduleBaseAddr = Module.getBaseAddress('libil2cpp.so');
  /*
   * 아래 오프셋 주소는 궁수의 전설의 소스코드가 업데이트됨에 따라
   * 변할 수 있습니다.
   */
  let offset = 0x2F3BED4;
  let targetRealAddr = moduleBaseAddr.add(offset);

  Interceptor.attach(targetRealAddr, {
    onEnter(args) {
      console.warn('[*] GetHPMaxBase called.');
    },
    onLeave(retval) {
      retval.replace(0x98967F);
    }
  });
}

setTimeout(getHPMaxBaseHook, 1000);

 
libil2cpp.so 라이브러리의 기본 주소에(ImageBase) 함수의 RVA를 더해서 실제 함수가 메모리에 어느 주소에 위치하는지 알아냅니다.(ImageBase + RVA = VA 이므로 메모리에서 해당 메서드가 존재하는 위치인 VA를 얻는 과정입니다.)
 
그다음 Interceptor.attach로 해당 주소에 훅을 걸어서 만약 해당 함수가 호출되면 '[*] GetHPMaxBase called.' 라는 메시지를 출력하고 반환값을 0x98967F(10진수로 99999999)로 바꿔칩니다.
이러면 게임에서 GetHPMaxBase 함수를 호출할 때 마다 리턴값이 99999999로 주어질테니 우리의 기본 체력은 99999999가 될 것입니다.
 
setTimeout을 달아준 이유는 혹시라도 모를 libil2cpp.so 라이브러리가 없다는 오류를 피하기 위해 libil2cpp.so 라이브러리가 충분히 로드 될 시간인 1000ms(1초) 뒤에 libil2cpp.so 관련 작업을 진행하게 한 것입니다.
 
그럼 궁수의 전설 앱을 실행시키고 아래 명령어로 후킹 스크립트를 삽입해봅시다.
 

frida -U "궁수의 전설" -l archero.js

 
게임에서 플레이 버튼을 누르면
 

 
캐릭터의 체력이 99999999로 조작된 것이 보입니다. 성공입니다!
 

참조

  • http://linforum.kr/bbs/board.php?bo_table=android&wr_id=4
  • https://py0zz1.tistory.com/156

#Frida #게임 해킹 #frida 후킹 #frida 유니티 #유니티 게임 해킹 #frida 게임 해킹
반응형

'Security > Reversing' 카테고리의 다른 글

추억의 게임 렙업만이살길2 리버싱 일기 - 1편  (1) 2025.06.01
DLL Injection 기법 - 프로세스에 침투하기  (0) 2024.02.08
윈도우 이벤트 메시지 후킹 기법  (0) 2024.02.06
인라인 패치 기법  (2) 2024.02.04
PE 파일 분석을 위한 C++ 프로그램 제작  (0) 2024.02.01
'Security/Reversing' 카테고리의 다른 글
  • DLL Injection 기법 - 프로세스에 침투하기
  • 윈도우 이벤트 메시지 후킹 기법
  • 인라인 패치 기법
  • PE 파일 분석을 위한 C++ 프로그램 제작
minmoong
minmoong
    반응형
  • minmoong
    minmoong
    minmoong
  • 전체
    오늘
    어제
    • Categories (16)
      • Programming (1)
        • Python (1)
        • WIPI (0)
      • Security (11)
        • Pwnable (2)
        • Reversing (9)
      • 기타 (3)
  • 블로그 메뉴

    • 홈
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    리버싱 기법
    c++
    채팅 버그
    Cpython
    파이썬
    렙업만이살길
    렙업만이살길2
    상남자의 OS
    BiDi
    밀초 버그
    우분투 문제해결
    리버싱
    우분투 깔고
    hopper disassembler 염병
    밀초 채팅 버그
    cpython-internals
    Python
    게임 리버싱
    WIPI 에뮬레이터
    렙업만이살길3
    WIPI emulator
    렙업만이살길1
    역대급 병크
    리버스 엔지니어링
    밀크초코 채팅
    github wie
    후킹
    WIPI 에뮬
    게임 해킹
    밀초
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.5
minmoong
Frida로 유니티 게임 리버싱하기 (궁수의 전설)
상단으로

티스토리툴바