안드로이드 유니티 게임 메모리 덤프 방법

홈 > 안드로이드 > 안드로이드
안드로이드

안드로이드 유니티 게임 메모리 덤프 방법

M LIN 63 17839 2

 이번 편은 안드로이드 전체 이미지에 대한 덤프가 아닌 특정 프로세스의 메모리 영역을 덤프 하여 유니티 게임에서 사용되는 "Assembly-CSharp.dll" 또는 "libil2cpp.so" 파일을 추출하는 방법을 설명드리려고 합니다. 해당 방법은 게임 보호 솔루션에 의해 암호화된 파일을 복원하기 위해 복호화 로직을 일일이 직접 분석하기보다는 덤프를 이용하여 쉽게 원본 파일을 확보할 수 있습니다. 

1. gdb gcore
 우선 가장 보편적으로 알려져 있는 방법으로는 gdb의 gcore 명령어를 이용하여 해당 프로세스의 모든 메모리를 덤프한 뒤 WinHex의 "File Recovery by Type" 기능을 이용하여 PE 구조인 파일을 리스트업하고 원본 "Assembly-CSharp.dll" 추출하는 방법이 있습니다. 자세하게 설명드리고 싶지만 이미 친절하게 설명된 튜토리얼 글들이 구글에 굉장히 많습니다. 구글에 "gcore Assembly-CSharp" 검색어로 쉽게 확인할 수 있습니다.

2. fridump
 해당 방법도 대부분이 이미 알고 있는 방법으로 생각됩니다. 먼저 frida 설치 및 기본적인 세팅을 마친 뒤, 깃허브에서 fridump 스크립트를 받습니다. (링크 : https://github.com/Nightbringer21/fridump)
다운로드하였다면  
"fridump.py -u -s 패키지명" 다음과 같은 커맨드를 이용하여 손쉽게 프로세스 내 메모리를 덤프 할 수 있습니다. 위와 마찬가지로 WinHex를 이용하여 덤프된 데이터 중 원본 DLL 파일 또는 so 파일을 추출할 수 있습니다.

3. libmono.so의 mono_image_open_from_data_with_name 함수 후킹하기
MonoImage* (*mono_image_open_from_data_with_name) (char *data, unsigned int data_len, bool need_copy, MonoImageOpenStatus *status, bool refonly, const char * name);
 가장 확실하게 dll 파일을 덤프 할 수 있는 방법으로 libmono.so의 mono_image_open_from_data_with_name 함수를 후킹하여손 쉽게 원본 파일을 추출할 수 있습니다. 해당 함수는 mono 이미지를 로드할 때 사용되는 함수입니다. 유니티 모듈은 dll 파일을 로드할때 해당 함수를 호출하게 되는데 이때 인라인 후킹을 이용하여 추출할 수 있습니다. 먼저 함수를 호출하고 name 인자값이  "Assembly-CSharp.dll"일 경우 실제 사용되는 dll코드가 복사되어 있는 첫번째 인자값 data를 파일로 만들도록 코드를 구현해주면 됩니다. 밑에 예제 코드와 같이 원본 파일을 얻을 수 있습니다.  

1
2
3
4
5
6
7
8
9
10
int mono_image_open_from_data_with_name_mod(char *data, int data_len, int need_copy, void *status, int refonly, const char *name) {
    LOGD("mono_image_open_from_data_with_name, name: %s, len: %d, buff: %s", name, data_len, data);
    int ret = mono_image_open_from_data_with_name_original(data, data_len, need_copy, status, refonly, name);
    if(strstr(name,"Assembly-CSharp.dll")){
        LOGD("mono_image_open_from_data_with_name, buff: %s", data);
        saveFile(data, data_len,"Assembly-CSharp.dll");
    }
    return ret;
}
 

또한 모드앱 또는 보호 솔루션들은 해당 함수 내에 복호화 로직이 포함되어 있는 경우가 많습니다. 덤프를 시도하기 전에 해당 함수를 디컴파일 하여 어떠한 방법으로 복호화되는지 확인하는 것도 분석 방법 중 하나입니다. 소개해드린 방법 외에도 해당 함수를 반환하기 전에 복호화된 데이터를 가로채는 방법이 있습니다. memcpy 함수를 후킹하여 앞에 2바이트가 0x4D5A 이면 파일을 생성하여 떨구도록 하는 방법도 있어 후킹 프레임워크(Frida, Xposed 등)로 쉽게 원본 파일을 확보할 수 있습니다. 그 외에도 반환값인 image의 raw_data 필드를 가져와서 파일을 만들어도 됩니다. 이렇듯 해당 함수 로직만 분석한다면 쉽게 원본 파일을 확보할 수 있습니다.

img.pngmono_image_open_from_data_with_name [1]
img.pngmono_image_open_from_data_with_name [2]

본문에 소개해드린 방법 외에도 다양한 방법들이 존재하며 각각 환경에 맞는 덤프방법을 이용하시면 됩니다. 
 대부분의 방법은 ptrace 디버깅을 이용하여 메모리를 추출하는 방법을 사용 할 텐데 대다수의 보호솔루션은 실제 메모리가 로드되기 이전에 안티디버깅(ptrace) 또는 안티덤프(inotify)가 적용 되어있어 추출이 까다로워질 수 있습니다. 이런경우 직접 보호솔루션을 코드 패치하거나 해당 함수들을 후킹하여 정상적인 작동이 안 되도록 조작한다면 실제 원본 데이터를 얻을 수 있을 것입니다.

63 Comments
S 코드몽키 2019.10.03 14:30  
1 번 2번은 구글링 열심히하면 문외한이라도 어찌어찌 따라할수있지만 3번은 안드로이드와  리버싱 지식이 없다면 .. 관련 종사자가 아닌이상..^^;
5 파파엄마 2019.10.03 15:08  
3번 내용 유익했습니다~ 감사합니다 !
4 엘라로즈 2019.10.03 15:44  
좋은 내용 감사합니다~
M LIN 2019.10.03 18:04  
린엔진 덤프 기능이 젤 편해요ㅋㅋ
2 mlsand 2019.10.03 19:58  
좋은 내용 감사드립니다
2 마루야 2019.10.03 22:17  
좋은내용 감사합니다
4 sodamari 2019.10.04 06:38  
열심히 도전해봐야겠습니다
1 dl1233 2019.10.04 10:41  
어렵네요..ㅎㅎ  감사합니다
4 신사 2019.10.04 13:42  
감사합니당~
3 배움 2019.10.04 14:53  
3번은 눈으로 봐도 잘 모르겠네요.
2 초보 2019.10.05 02:18  
린엔진이 제일편하죠..
2 icebone 2019.10.07 11:58  
3번은 mono만 가능하겠네요 il2cpp도 비슷한 함수가 있을듯한데...
3 뾰족 2019.10.16 18:43  
오늘 보안 솔루션 회사랑 미팅했는데, libil2cpp.so 파일을 암호화 해주고, 안티디버깅이 제공 되고, 리패키징을 못하게 막아 준다고 하던데... 메모리 접근하면 앱 자동 종료되고... 근데 3번 마지막 말씀 같이... 어셈블리로 된 코드를 수정하여 재빌드해서 대체할 수 있다면... 보안 솔루션 회사 제품도 뚫릴 수 있다는 거군요.
S 코드몽키 2019.10.16 20:00  
철권에서 이런말이있죠 VS 폴 피닉스전.
누구나 그럴싸한 계획을 가지고 있다. 명치에 한대 맞아보기전까진 (feat 붕권)

싸인코드 보안도 범우주적인 보안솔루션이니 뭐니 해외 해커 도발하는 스샷찍어가며 자기네가 최고다 뿜뿜 거렸지만 결국.. 요샌 해외포럼쪽가보면 싸인코드는 동네북이됬다죠

어차피 보안과 해킹은 창과 방패싸움같아요
방어측이 압도적으로 불리한 창과 방패싸움..

보안솔루션 만드는 인력과 시간은 한정되있는데 스토어에 출시되서 보안솔루션이 노출되는순간 전세계 해커짱들에게 어택땅 찍히니까요
1 야마간다 2019.10.16 20:07  
쉬워보이지만 어렵네요 초보한테는 ㅠㅠ
1 rok795 2019.10.21 12:09  
좋은 정보 감사합니다.
1 yoshicuda 2019.10.21 17:25  
I only use gdb. Thanks for share fridump method
2 에스트 2019.11.04 12:39  
배워갑니다
복화화되는지 확인하는 것도 << 오타 있네요
2 djucd 2019.11.06 17:21  
후킹 굉장히 어려워 보이네요
1 수호 2019.11.09 03:53  
감사합니다.

Congratulation! You win the 3 축하드립니다! 당첨되셨어요~!

4 py0zz1 2019.11.24 03:42  
감사합니다!
2 95grit 2019.12.06 23:50  
감사합니다
2 빙굴 2019.12.12 07:50  
추출을 해야지 보이는 파일들이었군요..
2 songod 2019.12.19 17:09  
감사합니다.
1 rafael 2019.12.28 12:28  
감사합니다
2 데스깃 2019.12.29 06:00  
mono_image_open_from_data_with_name_mod 함수가 호출되는 시점이 아닌 지연 호출되는 DLL의 경우는 어떤 방법으로 덤프를 딸 수 있을까요?
S Dhhd 2020.01.04 12:50  
감사합니다
1 ab1313 2020.01.06 10:05  
감사합니다
28 사딸라 2020.01.07 08:14  
감사합니다.
1 케록 2020.01.08 16:36  
어렵네요..아직은... 기초가 필요해요..
13 Rohas 2020.01.09 16:13  
감사합니다!
1 lacey 2020.01.20 18:30  
감사합니다!
1 lin26 2020.01.26 15:13  
저는 아직 3번까지 가기에는 갈 길이 멀다는 것을 알았습니다. 감사합니다.
2 개미개미 2020.03.07 00:55  
3번은 보고있어도 뭘 보고 있는 건지 모르겠네요..
7 래바리 2020.04.03 18:50  
감사합니다.
1 바람과같이 2020.04.13 00:29  
감사합니다
2 rjsejrrjsejr 2020.04.16 05:24  
감사합니다~
1 derelikt 2020.05.02 05:01  
fridump로 덤프한 데이터에서 dll이나 so는 어떻게 추출하면 되나요?
1 레어메드 2020.05.16 18:06  
감사합니당!!
1 레어메드 2020.05.16 18:07  
정말감사합니당~!!
7 임중호 2020.05.24 01:27  
실패했습니다....
1 Haul 2020.05.24 18:58  
저도 fridump로 덤프한 데이터에서 dll 추출하는 법이 궁금하네요
1 주황버섯 2020.06.29 11:31  
감사합니다
1 피통왕구키 2020.07.19 00:04  
감사합니다.
1 아리송당 2020.07.30 09:44  
감사합니다.~
4 쿨록 2020.08.07 18:51  
천천히 해봐야겠다..
1 나난논가다 2020.08.29 14:04  
감사합니다!
1 녹아요 2020.09.07 16:26  
천천히 공부하다 보면 언젠가는 알아듣겠죠
2 ranie 2020.09.26 20:30  
감사합니다 ^^^

Congratulation! You win the 20 축하드립니다! 당첨되셨어요~!

2 ranie 2020.09.26 20:32  
감사합니다
2 호랑이쿨광 2020.09.28 01:04  
음...어렵네요
1 뼈뿌이없다 2020.10.31 15:54  
좋은내용 감사합니다. 이해가 잘안됨 ㅋㅋ
2 해커꿈나무 2020.11.13 22:51  
갑사합니다
2 매코미 2020.11.15 00:02  
감사합니다
5 킹왕짱 2021.02.02 05:01  
보면 볼수록 파고들고 싶은 툴인데
너무 어렵게 느껴집니다
예제 따라하기가 있다면 도움이 될 것 같습니다
1 미쓰라준 2021.02.04 17:56  
여기서 부터 천천히 시작해보겠습니다.
1 곤뇽 2021.03.07 23:33  
감사합니다
2 준섭이당 2021.07.05 01:17  
ㄱㅅㅎㄴㄷ
2 공적1 2021.09.06 03:03  
감사합니다~
1 둘기랑 2021.09.13 21:16  
감사합니다.
1 nickname 2021.12.26 18:26  
정말 감사드립니다
1 richardson 2023.05.24 00:48  
tranks
1 GR3K 2023.05.24 00:56  
thanks