K1ngD0m Rush 0r1g1ns

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

K1ngD0m Rush 0r1g1ns

S tutorial1 31 14013 4

디펜스형 게임.. 시간 순삭하기 좋은 게임이죠. 인앱구매 말고도 앱 자체 구매때 돈좀 들길래 쪼잔하게 mod 포럼을 방문, 크리스탈 무한과 모든 히어로들이 언락된 apk를 받아서 즐기려고 했습니다.

하지만 막상 받고보니 all heroes 언락이 되지않고 자꾸 구매하라고 뜨더군요.

해서 내가 한번 언락해 보자식으로 분석 해보기로 했습니다.

61d48728b3df9c46ab0fda12cff0f56b_1571148065_141.JPG

크리스탈 갯수는 mod되어 무한대에 가까운 수치로 조정되어 있습니다.


61d48728b3df9c46ab0fda12cff0f56b_1571148065_2079.JPG

히어로는 기본 히어로, 특정 갯수의 별을 수집했을때 언락되는 것들 말고는 모두다 구매해서 쓰라고 표시되고 있었습니다.

61d48728b3df9c46ab0fda12cff0f56b_1571148065_2335.JPG
오리지날 apk와 mod apk 의 차이점은 data.save 라는 파일이 assets 폴더에 생성되 있었으며 smali\com\savegame 클래스파일이 생성되어 있었습니다.

61d48728b3df9c46ab0fda12cff0f56b_1571148345_7474.JPG

파일이 꾀 크네요 smali 주제에

61d48728b3df9c46ab0fda12cff0f56b_1571148430_2054.JPG

어엌. 그럼 그렇치 SavesRestoringPortable 파일은 해커가 추가시킨듯한 파일이었으며 아마 해당 smali를 통해 save.dat 파일을 핸들링 할 것 같습니다.

비교적 단순하게 난독화 시킨듯 하여 online java compiler 사이트를 방문하여 즉석으로 간단한 복호화를 진행 하였습니다.

61d48728b3df9c46ab0fda12cff0f56b_1571148685_9894.JPG

함수를 호출하여 특정 문자들을 리턴받는것을 알 수 있습니다. 문자를 반환하는 함수들을 싹다 복사하여 옮긴 뒤 print 함수를 통해 출력해 보도록 했습니다.

61d48728b3df9c46ab0fda12cff0f56b_1571148828_336.JPG

흠? 암호화 알고리즘이 사용되었습니다. data.save 파일을 aes-256 알고리즘을 사용하여 복호화 한 뒤 unzip 함수를 이용하여 압축해제를 진행합니다.
어떤 파일들이 압축되어 있는지 궁금하여 aes 복호화 진행후 까보았습니다.

61d48728b3df9c46ab0fda12cff0f56b_1571149108_1659.JPG

압축파일 내부에는 킹덤러쉬가 사용하는 데이터를 압축해 놓았습니다. 살펴보니 file/save 폴더에서 사용자가 결제한 리스트, save slot 등이 보관되 있었습니다.

61d48728b3df9c46ab0fda12cff0f56b_1571149291_3758.JPG

ㅇㅇㅇㅇㅇㅇㅇ

61d48728b3df9c46ab0fda12cff0f56b_1571149371_3595.JPG

구매 결제 내역. 하지만 이걸 넣어줬다고 해서 실제 게임에서 기능들이 오픈되지 않습니다.ㅜㅜ
61d48728b3df9c46ab0fda12cff0f56b_1571149371_3841.JPG
슬롯에 크리스탈 갯수가 박혀있습니다. 이건 제대로 작동 하더군요!


킹덤러쉬는 libsdl라이브러리, love 2d 게임엔진을 통하여 게임이 개발되었습니다.(luajit) 따라서 lua와 관련된 파일을 찾아댕긴결과 obb 쪽에서 바이너리화된 lua 파일들을 발견할 수 있었습니다. luajit 을 디컴파일 할 수 있는 툴을 활용하여 대략적으로 구매된 상품을 어떻게 적용시키는지 파악할 수 있었습니다.

61d48728b3df9c46ab0fda12cff0f56b_1571149742_5751.JPG
61d48728b3df9c46ab0fda12cff0f56b_1571149742_6051.JPG
디컴파일된 remote_config_defaults.lua 파일에서 공략해야할 상품목록을 파악할 수 있었습니다. 모든 히어로팩!

이때부터 든 생각이 결국엔 smali에서 결제를 처리하겠구나 싶어서 jadx 를통해 classes.dex 파일을 열어 보았습니다.

61d48728b3df9c46ab0fda12cff0f56b_1571149938_6678.JPG

.. 게임수준.. 패키지 오지게 많구연!

여러가지 정보들을 모으며 삽질한 결과. 갓덤러쉬는 google-inapp service를 사용하여 결제시스템을 구축하였습니다.

61d48728b3df9c46ab0fda12cff0f56b_1571150091_9397.JPG

우리가 눈여겨 보아야 할곳은 

ownedSkus

purchaseDataList
signatureList

3개의 변수입니다. 스트링형 어레이 배열로 관리되고 있으며 어디선가 오브젝트를 얻어와 담아주고 있었습니다.

해당 배열들이 null,배열 사이즈가 0이 아니라면 purchase 객체를 생성하도록 합니다.

61d48728b3df9c46ab0fda12cff0f56b_1571150330_172.JPG


61d48728b3df9c46ab0fda12cff0f56b_1571150484_8807.JPG

purchase 객체의 생성자를 주요깊게 보셔야합니다. 첫번째 파라미터인 purchaseinfo 는 purchase 의 json 객체를 생성할 수 있도록 json 문법을 이용하여 데이터를 가공하셔야 합니다. 2번째 파라미터는 해당 구매상품의 검증값으로 보시면 됩니다.(이 뒤에 시그니쳐값을 비교하여 상품 구매 유효성 검사를 진행합니다.)

61d48728b3df9c46ab0fda12cff0f56b_1571150833_6832.JPG

ownedSkus

purchaseDataList
signatureList

3개의 변수에 임의로 생성한 문자 오브젝트들을 넘겨줄 수 있도록 바꿨습니다.

ownedSkus , signatureList 변수에는 아무 문자열이든 상관이 없습니다. 하지만 2번째 변수인 purchaseDataList는 json 파싱이 가능하도록 가공시켜주어야 합니다.

저는 모든 히어로를 이용하고 싶으니 com.ironhidegames.kingdomrush.origins.offer.heropackall5 제품명을 전달해 주도록 했습니다.


"{\"orderId\" : \"1\",\"packageName\" : \"com.ironhidegames.android.kingdomrushorigins\",\"productId\" : \"com.ironhidegames.kingdomrush.origins.offer.heropackall5\",\"purchaseTime\" : 15608190,\"token\" : {\"purchaseToken\" : \"YOYO\"},\"autoRenewing\" : true}"

61d48728b3df9c46ab0fda12cff0f56b_1571151094_8142.JPG

아까 말했던 signature 값으로 상품구매가 유효한지를 체크하는 구간입니다. 쉽게 boolean 형태로 return 하고 있어 그냥 분기점을 바꿔 sb 오브젝트가 무사히 반환될 수 있게 하면 됩니다.
여기까지 하면 될줄 알았으나! 자꾸 purchase 생성자에서 json 예외를 던져 purchase 객체를 생성해내지를 못했습니다.

61d48728b3df9c46ab0fda12cff0f56b_1571151685_8051.JPG

private final String mOriginalJson; final 키워드가 문제였습니다. ( 이거찾느라 ㅈ빠짐진짜) 해당 final 키워드를 제거하고 다시 테스트를 진행한 결과.


61d48728b3df9c46ab0fda12cff0f56b_1571151936_0321.JPG
모든 히어로들을 선택할 수 있게 되었습니다.

이제 겜 즐기러가야지.



31 Comments
6 지존 2019.10.16 00:32  
좋은 글 감사합니다
8 리피트싯 2019.10.16 09:51  
final 변수는 값을 한번만 할당하는것이 가능합니다.
읽기는 여러번가능

final int a=1;
a= 10; <<오류남
final int b ;
b= 5;
b= 10; <<오류남
6 하늘사자 2019.10.16 10:14  
좋은 정보 감사합니다.. 고생하셨습니다.
8 아수라발발이 2019.10.16 11:52  
좋은정보 주셨으니 이제 따라해봐야겠죠?
3 라피스넷 2019.10.16 14:22  
좋은 정보 감사드립니다

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

13 백형이 2019.10.16 17:59  
정보 감사합니다.
4 knock31 2019.10.16 20:06  
잘보고 갑니다~
S 코드몽키 2019.10.17 01:22  
ㅗㅜㅑ 좋은정보공유 감사합니다

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

3 아토 2019.10.19 08:08  
감사합니다아~
1 라면집이사장님 2019.10.20 12:43  
대단하네요
3번 정독했는데 아직도 잘 이해가 안되는 부분들이 많네요..
1 yoshicuda 2019.10.21 16:38  
skill writting very good.
1 drockefeler007 2019.10.22 22:08  
좋은정보 주셨으니 이제 따라해봐야겠죠?
2 charlie 2019.10.22 22:16  
좋은 글 감사합니다^^
5 다뚫어 2019.10.28 10:37  
좋은정보 감사합니다
2 진방 2019.11.18 16:02  
와 몇번을 읽어봐도 어떻게 한건지 초반 부분말곤 이해가 안가네요 ㅋㅋㅋ
1 korea112 2019.11.30 22:23  
좋은정보 감사합니다
2 리리 2019.12.11 18:10  
신기하네요
2 빙굴 2019.12.12 08:23  
감사합니다. 공부할게 많네요
3 가람 2019.12.17 08:28  
감사합니다!! 공부해보겠습니다 ㅎㅎ
3 초코몽 2019.12.22 03:12  
이무꺼도 모르겠네요 ㅜㅜ뭐부터 공부해야히는지
1 구구긍 2020.01.01 03:08  
apk를 완전 분석하셧구뇨요 ㄷㄷㄷ

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

2 해키 2020.01.03 17:04  
정말 감사합니다
28 사딸라 2020.01.07 08:28  
제대로 까셨네요 ㄷㄷ
4 알려주세요오 2020.01.21 23:50  
일단 댓글박고 나중에봐야징
7 래바리 2020.04.03 18:41  
감사합니다.
1 sdfadf 2020.04.05 21:04  
와 엄청 복잡하네요;
2 삼도네 2020.06.08 06:52  
멋지십니다~^^
11 망수리 2020.06.08 10:33  
워~~엄청복잡하네요..ㅋㅋ
1 qsdfg 2020.10.04 17:45  
좋은정보 감사합니다
1 kyo23 2021.02.08 12:51  
감사합니다
2 우류 2021.12.27 15:15  
댓글내용 확인