앵하니의 더 나은 보안

How to analyze Unity Based iOS Games 본문

보안 기술/iOS

How to analyze Unity Based iOS Games

앵한 2024. 6. 23. 18:51

서론

모바일 iOS 게임을 진단하며 알게 된 유니티 기반 iOS게임의 분석법을 정리해보겠다.

 

본론

어떤 차례로 분석을 진행하면 되는지 한번 싹 훑어보자.

i. 심볼릭 정보 복원이 최우선

유니티게임은 심볼릭 정보 복원을 통해 소스코드 내 클래스/함수 명을 복원할 수 있다.
그 방법을 한번 알아보자

  1. 어플리케이션에서 ipa를 추출한다.
    추출에는 주로 frida-ios-dump를 사용하는데,
    그 원리는 대충 어플리케이션을 실행 했을 때 메모리에 적재되는 바이너리 파일을 dump하는 것이다.
    > Q. /var/containers/Bundle/Applicatoin/BundleID에서 파일 추출하면 안되나?
    > A. 어플리케이션을 앱 스토어에서 설치한 경우 해당 경로에있는 바이너리 파일은 애플의 FairPlay DRM이 걸려있어서 분석 불가
  2. 추출한 파일 중
    \Payload\[AppName].app\Frameworks\UnityFramework.framework 경로 ‘UnityFramework' 파일과\Payload\Valkyrious.app\Data\Managed\Metadata경로 'global-setting.json’ 파일을
    unity 게임의 심볼릭을 복원하는 li2cppdumper에 입력해 심볼릭 복원 파일 생성

  3. 복원한 심볼릭 정보는 dnspy를 사용해 확인 가능

ii. 복원한 심볼릭 정보와 기드라 함수 오프셋 맵핑

그리고 복원된 심볼릭 정보를 사용해 기드라의 함수 오프셋과 맵핑 시킴으로써 좀 더 직관적으로 분석할 수 있다.

  1. 파일 UnityFramework를 ghidra로 분석 진행
  2. 분석 완료 후 녹색 재생 버튼을 클릭해 script manager 열기
  3. script manager에서 스크립트 생성 버튼 클릭
  4. 새 스크립트 타입으로 파이썬 언어 선택
  5. 스크립트 이름 설정 후 ok 클릭
  6. 이후 생성된 스크립트의 내용으로 il2cppdumper 경로 내 ghidra.py 의 내용 입력
  7. ghidra.py 파일의 내용 입력 후 실행 버튼 클릭
  8. 실행 시 파일 입력을 요구하는데 이때 il2cppdumper를 통해 생성됐던 심볼릭 복원 관련
    script.json 파일을 입력
  9. 스크립트 동작이 실행되고, 동작이 끝나면 함수명이 복원된 심볼릭과 맵핑돼 좀 더 직관적으로 분석 가능

iii. frida로 함수 후킹 및 Trace

위 두 과정을 마쳤다면 분석을 통해 frida 후킹을 유용하게 사용할 수 있다.

  1. 함수명으로 특정 함수의 기능 추측
  2. frida를 사용해 UnityFramework 모듈에 후킹한 후 RVA 만큼 더해줘서 원하는 함수에 후킹하는 함수 작성, args 및 retval을 조작해 후킹한 함수 관련 데이터 조작 수행
    var moduleBase = Module.findBaseAddress('UnityFramework');
    var methodAddress = moduleBase.add(ptr('0x12345678'));
    
    
    Interceptor.attach(methodAddress, {
        onEnter: function(args) {
            console.log('후킹 메소드 호출');
        },
        onLeave: function(retval) {
            console.log('후킹 메소드 종료');
        }
    });


  3. 해당 함수의 호출 스택이 궁금하다면 Thread.backtrace를 사용해 함수가 어디서 호출됐는지 추적 가능
    var moduleBase = Module.findBaseAddress('UnityFramework');
    var methodAddress = moduleBase.add(ptr('0x12345678'));
    
    
    Interceptor.attach(methodAddress, {
        onEnter: function(args) {
            console.log('후킹 메소드 호출.');
    		var backtrace = Thread.backtrace(this.context, Backtracer.ACCURATE).map(DebugSymbol.fromAddress).join('\n');
    		console.log(backtrace);
        },
        onLeave: function(retval) {
            console.log('후킹 메소드 종료');
        }
    });

    ※ Thread.backtrace결과로 나오는 출력중에 아래로 갈수록 먼저 호출된 함수


    이제 호출된 함수 offset을 확인 후 ghidra에서 찬찬히 분석해보면 된다.
    위 0x4c0b8d8 오프셋을 기준으로 찾아보면

    UnityEngine.Events.InvokableCall는 0x040c0b8d4 오프셋에서 호출됐음을 알 수 있다.
    (호출된 다음 Instruction Point가 스택에 기록되므로 스택에 기록된 오프셋 - 1이 호출된 주소)

결론

갓 li2cppdumper 갓갓 ghidra 갓갓갓 frida

 

 

 

Comments