2013.05.06 01:53 WarGame

[+] ... 


 


시간이 널널해지면 널널해질수록 블로그 글 작성 횟수가 줄어들고 있습니다.


문제를 푼건 1달 전 쯤인거 같은데 이제서야 키보드를 잡았네요.


이번 문제는 android platform이 대상입니다.


생각해보니 일반 pc 말고  mobile platform 을 대상으로 하는 wargame을 대상으로 글을 쓰는 건 이게 처음인 것 같네요.



[+] ? 


 

문제 파일은 아래 링크에서 받을 수 있습니다.

 

 

 

Bluebox 라는 Android 보안 회사에서 낸 문제입니다.

 

우리 보안이 자신 있으니 깨보아라 같은 경우가 아니라

 

회사 홍보 겸 샘플로 간단히 제작한 걸로 보입니다.

 

먼저 App을 받아 폰에서 실행 시켜보도록 하죠.

 

 

<Fig1. App 실행 화면 >

 


군더더기 없는 깔끔한 문제군요.

 

특정 String을 입력하면 통과하는 간단한 crackme 입니다.

 

이제 code를 뜯어보기 위해 App 압축을 풀어보..

 

는 풀리지 않습니다.  암호가 걸려있다는군요..

 

위 링크에 있는 unpack.py 를 통해 압축을 해제 하셔야 합니다.

 

<Fig2. unpack.py>

 

Mobile에 설치할 때는 아무 이상 없이 설치 되었는데 PC에서는 압축 해제가 되지 않는다?

 

상당히 흥미로운 주제입니다.

 

중요한 부분은 이 한줄이죠.

 

member.flag_bits ^= member.flag_bits%2

 

특정 flag를 제거합니다. 


Zip file의 format 을 확인해보면.. 암호화 여부를 판단하는 bit 임을 확인 할 수 있군요.


Android 의 apk manager는 password flag를 무시하고 설치를 시도하기에 이런 트릭을 걸 수 있습니다.


역으로 pack 하는 것도 매우 간단합니다.


Local file Header 와 Central directory file header 의 general purpose bit flag에 xor 1을 해주면 되죠.


어떠한 apk 파일이라도 쉽게 이런 트릭을 걸 수 있다는 점에서 꽤 유용해보이네요.

 

아무튼 이렇게 압축을 해제하고 decompile 해서 문제를 구성하는 간단한 알고리즘을 풀면 해결!

 

...

 

되면 이렇게 글을 쓸 일도 없었겠죠.

 

여러모로 트릭이 몇가지 씩 들어간 문제인데요.

 

코드를 확인해 보시면 아래와 같이 so file을 Load하는 것을 볼 수 있습니다.

 

<Fig2. MainActivity 에서 so file을 Load하는 모습>

 

JNI 를 통하여 so file의 함수를 호출합니다.

 

readmem 함수는 다시 search 함수를 호출하게 되고... 이 함수는

 

 

 

 

<Fig3. search 함수 >

 


 

findmagic 함수를 통해 memory 상에서 dex file이 올라간 시작 지점을 찾고 [ dex\x0a ]

 

Lava/lang/String 의 add Method의 위치를 찾습니다.

 

그 후 mprotect 함수를 사용하여 [ sub_F04 부분 ] 쓰기 속성을 준 뒤

 

memcpy 를 통해 inject 함수에 있는 assembly 를 복사합니다.

 

즉, So file에서 Memory에 Load된 String Class의 add method를 Code Injection 한 겁니다.

 

정확히 말하자면 덮어 씌운 거지요.

 

그러니까 앞서 살펴 본 decompiled code는 전혀 실행이 되지 않을 거란 겁니다.
 


[+] !




Injection 될 Code는 아래와 같습니다.

 

 

<Fig4. Injection 될 길이 0xDE의 Code>



add method가 시작하는 address에 이 code를 덮어 씌우신 후 다시 분석 하면 된다는 거죠.

 

ida를 활용하여 해당 function 의 address를 확인합시다.  직접 memory를 dump 뜬 후에 비교하는 방법으로도 address를 쉽게 구할 수 있습니다.

 

이를 통해 구한 실제 파일의 offset 은 0x27680 입니다.

 

 classes.dex파일에 저 code를 덮어 씌운 다음 Tool을 돌려보면..


 dex2jar 는 해석을 못하고 오류를 뱉습니다.


baksmali도 안되네요.


IDA도 안되요. 

<Fig. 아오.. >


 

다행히 한 Tool에서 오류가 나는 곳이 다른 Tool에서는 잘 분석 될 때도 있더군요.

 

이건 뭐 드래곤볼도 아니고 Code를 모아 소원을 빌어 문제를 해결하는 것도 아니고 ..

 

아무튼 한땀한땀 짜깁기를 하면 ..

 

<Fig5. 모은 Dalvik code>

 

뭐 아무튼 실마리는 다 모였고 Tool에서 해석되다 만 Code들과 Hand-ray를 사용하면

 

아래와 같은 Code를 얻을 수 있습니다.

 

<Fig6. Code를 다 모았으니 문제를 풀어주세요!>

 

 

사실 ... 부분은 모든 Tool이 Error를 낸 부분인데

 

다행히 4byte 정도라 manual 해석 및 추측이 가능한데요.

 

map.put 이 들어가겠죠.

 

자.. 이제 package 쪽은 다 해결 됐습니다.

 

마지막으로 본 문제쪽 Java Code를 살펴봐야 합니다

 

문제에 앞서 ..

 

한가지 퀴즈를 내볼까요?

 

Lјava/lang/String 과 Ljava/lang/String;

 

같을까요 다를까요?

 

 

 

...

 

다릅니다.

 

아니 이게 무슨 소리야..

 

ј가 j가 아니라니

 

사실 전자의 j로 보이는 문자는

 

0xD1 0x98의 Unicode 문자입니다.

 

이런 거지같..

 

그런고로

 

전자 Fake j는 출제자의 Class를 참조하고

 

후자 진짜 j는 java 기본 Class를 따릅니다.

 

까도 까도 깔게 나오는 너란 문제.. 양파 같은 문제..

 

<Fig7. Verify Botton을 눌렀을 때 호출되는 함수>

 

 

fake.String 에서 new를 통해 생성하는 건 위에서 한땀 한땀 빚어낸 Add Method를 타게 됩니다.

 

남은 잡다구리한 함수를 거쳐 생성한 String  "RKGMKAQEGJATGAVWABJKGTG" 를

 

add method에 넣고 돌려주면 답이 나옵니다.


THECHANGESAREALWABSHERE

THECHANGESAREALWAYSHERE

 

2가지네요.

 

 

<Fig8. 보고 싶던 너>

 

 


[+]  ++ 


Code injection을 통해 동적으로 Code를 바꾼다.

 

난독화에 있어 괜찮은 방법이 될 수 있을 거 같습니다.

 

특정 함수가 불릴때만 잠깐 바꾼다면 Memory dump를 통해 알아내기도 힘들겠죠.

 

물론 넣을 Code가 다 노출되는 단점이 있습니다만.. 이 또한 알아보기 어렵도록 꼬아놔야할 겁니다.

 

섞고 , 섞고, 돌리고 섞고..

 

하지만 이렇게 꼬아놔도 어쨌든 깨지는건 시간의 문제이기 때문에 많은 기업들이 이제

 

Hardware를 이용한 보안 기술 접목을 준비하고 있습니다.

 

TPM 이나 Trust zone을 사용해서 말이죠.

 

이러한 Hard 기반 보안 기술이 과연 얼마나 튼튼한 방패가 될 지는 아직 두고봐야 할 것 같습니다.


 

Posted by LinkC

블로그 이미지
LinkC

태그목록

Tistory Cumulus Flash tag cloud by BLUEnLIVE requires Flash Player 9 or better.

공지사항

Yesterday67
Today83
Total310,078

달력

 « |  » 2018.05
    1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30 31    

최근에 받은 트랙백

글 보관함


. .