리버싱

리버싱 #1

karma2 2024. 7. 5. 16:50

나는 정적 분석은 몇 번 해봤지만, 동적 분석에 대한 지식이 얕아서 그냥 무작정 삽질을 해보며 보안을 무력화하려 하였다.

그래서 먼저 apk파일을 다운 받고 라이브러리 폴더의 라이브러리 파일을 살펴봤는데, 예전엔 x86 라이브러리도 있었던 것 같은데, 최근엔 에뮬레이터에서 libhoudini로 ARM 라이브러리를 번역하면 되기 때문에 개발자 측에서 굳이 x86 라이브러리를 빌드할 이유가 없어서 자연스레 사라진 것 같다. 그래서 Frida 후킹을 할 때 좀 애를 먹었는데, 앱 모듈 리스트를 뜯어봐도 libil2cpp.so가 없어서 방법을 찾던 중 frida gadget를 앱에 추가하여 후킹을 하는 방법을 알게 되었다. (더 좋은 방법 있으면 알려주세요. 아무리 찾아도 x86 emulator 환경에서 데몬 권한으로 arm 후킹 하는 방법이 없음)

근데 또 이 게임은 무결성 감지가 있는 듯 했다,,,, (ㅅ발) 그래서 그냥 생으로 라이브러리를 분석해 볼 수밖에 없었다. 하지만 libil2cpp도 암호화가 되어 있는지, 알아먹을 수 없는 코드로 도배가 되어 있었다.

암호화된 libil2cpp.so

(귀납적 탐구 방법이랍시고, 어려운 게임부터 보안 무력화 하겠다고 설쳤으니 벌어진 사태인 듯 하다....)

더 절망적인 것은 앱이 튕구기 전에 프리징 시켜놓고 복호화된 libil2cpp 라이브러리를 따려고 frida를 첨에 쓴 거였는데, pThread로 디버깅 감지를 하는 것인지 프로세스가 두 개나 떠 있었다. 그래서 삽질좀 하다가 어떻게 하는지 몰라서 걍 포기하고 코드나 분석해 보기로 했다. 지금 생각해 보니 pThread에 훅 걸어서 주소값 인터셉트 해서 오버플로우로 메모리값 위변조 했으면 됐을 것 같기도... Thread가 메모리보다 늦게 실행되는 걸로 알아서.. 근데 frida 사용법을 잘 몰라서 힘들 듯하다.

 

 

어쨌든 저 암호화된 오프셋 전에 li2cpp init부분이 있는데 거긴 IDA가 분석을 아예 못 했음 (이건 암호화 때문인지 뭔지..)

그래서 apk파일 라이브러리는 때려치움

IDA 윗 부분에 있는 로딩바 (뭐라 부르는 지 모름)

그리고 apk파일을 jadx로 디컴파일 해봤는데, 거기서 /system/xbin/su 파일이 존재하면 루팅 감지하는 로직이 있는데, 이건 로직은 같지만 그 부분에서 감지하는 게 아닌 것 같았다. (근데 이건 frida가 후킹이 안 돼서 확인할 방법이 없음)

아니 싹다 암호화 해놨네

실제로 내가 su파일을 "su2"로 rename 해서 앱 실행을 해본 결과 감지를 하지 않았다. 그래서 루팅 감지는 비교적 쉽고, 치팅툴 감지도 있는데, 이건 어떻게 우회하는지 모르겠음. jadx로 분석해 봐도 암호화 안 되어 있는 부분만 분석하니까 딱히 감지하는 로직이 없었음. 

 

 그리고 코드 좀 살펴보려고 ipa파일을 꺼냈다. 

IPA 파일

참고로 IPA는 App store에 release 할 때 자체적으로 암호화가 되어 있는데, 이건 외국의 개고수 분들이 원본 파일을 후킹 해서 갖고 오는 사이트를 만들어 놨길래 거기서 Decrypted 된 IPA파일을 받아왔다 ㅎㅎ.

 

Il2cppdumper로 dump 하고 분석을 시작했다.

좀 살펴보다가 Dummydll폴더에서 신기한 게 있었다. 

12KB ㄷㄷ

용량이 미친 듯이 적은 모습. 즉, 클라이언트 로직은 여기에 없다는 것이다. 다른 게임들은 다 여기다 집어넣는데, 이 게임은 특이하게 나온 지 얼마 안 돼서 그런가 GameClient.dll이 따로 있었다. 거기에 Codestage Anti Cheat Toolkit 클래스도 들어있었는데, 이건 왜 있는지 모르겠다. (메모리 위변조해도 감지를 안 해서 외장 치트툴로 위변조 하면 Hack을 쓸 수 있긴 하다.) 

 

어쨌든 담에 또 무력화를 하게 된다면, pThread를 후킹 해서 어떻게 감지하는지 좀 살펴보고, frida gadget 붙이고,  IDA에 들어있는 바이너리 파일을 좀 분석해 보자. 

아직 상대하기엔 너무 강한 앱가드였다,,,,

 

 

setTimeout(() => {
  var module = Process.findModuleByName("libhoudini.so");
  var il2cpp = module.base;
  var offset = module.size;
  
  var file = new File("/sdcard/Download/dec_libil2cpp.so", "wb");
  var buf = il2cpp.readByteArray(offset);
  file.write(buf);
  file.close();
}, 5000);

이건 여담인데 libhoudini에 어떻게 스택 되는지 궁금해서 동적 덤프 좀 하려고 하니까 permission denied error 나던데 아니 진짜 나한테 왜 그러는 거임? su권한 있고 chmod로 777 권한까지 프리다 서버에 줬는데 뭔 권한이 없다는 건지.. 짜증 나서 못 해 먹겠다.