2014.01.04 17:57 System


[+] Blah Blah 

 


 

 

2014년 첫 포스팅입니다.

 

마지막 포스팅이 13년 5월 이었으니까 하 죽일놈의 게으름.

 

최근에 모바일쪽 일을 하고 있어서 이번 글 역시 모바일 관련 이야깁니다.

 

android app을 사용하여 shell 을 띄우려면 어떻게 해야 할까요?


크게 2가지 방법이 있습니다.

 

1. App 내에서 shell 실행

 

2. App 에서 호출하는 library 내에서 shell 실행

 

전자는 dalvik vm 내에서 , 후자는 library 가 직접 실행하게 됩니다.


전자의 경우는 app 내의 취약점이라기 보다는 repacking 공격에서 사용되겠죠.

 

본문은 후자의 방법을 통해 취약점을 공략해보는 방법을 기술합니다.

 

 


[+] about vulnerable library

 


 

pc에서 사용되는 많은 library들이 cross-compile을 통해 모바일에서도 재사용되곤 합니다.

 

그 덕에 취약한 library도 자기 영역을 확장시켜가고 있고 여러 플랫폼으로 배포가 이루어진 library들은

 

비단 하나의 플랫폼에만 취약한게 아니게 되었습니다.

 

예를 들어 libpng 라는 이미지 처리 library를 들어보죠.

 

해당 library는 open source project로서 linux의 system library로 실제 사용되고 있으며

 

cross-compile이 가능한 덕에 android에서도 사용하는 사람이 있죠.

 

compile 옵션과 compiler 버전에 따라 약간 달라질 수 있겠지만 취약점이 있으면 사용하고 있는 다른 플랫폼도 취약점에

 

노출될 수 있다는건 누구나 다 알 수 있습니다.  

 

더구나 이미지 파일의 특성 상 파일 전송을 통한 공격이 매우 수월한 것은 두 말 할 필요도 없겠죠.


그런 이유로 android app 내부에서 jni 형태로 호출되는 취약한 image library 가 본문의 희생양으로 출현해주셨습니다.


<Fig 1. libpng 공식 사이트에 올라온 보안 위협>

 

 



[+] attack

 


 

 

libpng의 취약점 중 입맛에 맞는 것으로 하나 골라 공격합니다.

 

x86 shell code 대신 arm shell code를 삽입하고 환경에 맞게 stack 위치만 조정해주면 공격에 성공합니다.

 

참 쉽죠?

 

는 구버전에서만 가능한 일이고, 최신 버전에서는 DEP 덕에  ROP를 사용해야 합니다.

 

ASLR이 적용되어 있기는 하나, system library는 아예 고정적으로 사용하고 있는 경우도 많고 그렇지 않다하더라도

 

대부분 system library 들은 load되는 memory 위치가 대동소이 합니다.

 

그렇기 때문에 ROP 체인을 구성 하실 때, 하나의 system library에서만 모아서 구성하시면 모든 파일에 ASLR이 적용되어있더라도

 

공격 성공 확률을 높이실 수 있습니다.

 

더구나 Process가 다르더라도 system library 들은 같은 위치에 load되는 경우가 많아 한 앱의 memory map을 구했다고 하면

 

공격은 거저 먹는게 되죠. 

 

<Fig2. 두 Process의 memory map 비교>

 

 

필자의 경우 ARM shell code의 재활용을 위해 mprotect를 활용하여 stack에 권한을 주고 shell 을 띄우는 방법을 선택했고,

 

전체 code는 아래 Fig3 처럼 구성될 수 있습니다.

 

<Fig3. ROP 체인 구성>

 

물론 위 code는 얼마든지 유동적으로 바뀔 수 있습니다.

 

모로가도 서울만 가면 되니까요.

 

정리하자면 아래와 같습니다.

 

 

<Fig4. ROP 체인 구성 정리>

 

 

원하는 명령어를 포함하는 ROP 체인 검색 스크립트 +  ROP 체인 구성 스크립트 + 취약 image 생성 스크립트

 

대략 이 3가지 스크립트가 사용된거 같네요.


이렇게 만들어진 취약한 Image를 피해자에게 전송하면 파일 내에 삽입된 code가 실행되고 

 

최종적으로 reverse shell을 얻을 수 있습니다.

 

 

<Fig5. reverse shell을 얻은 모습>




 

[+]  More and more


 

library 내에서 execve 류 함수가 실행되면 Process가 아예 바뀌기 때문에 앱이 죽게 됩니다.

 

물론 시스템에서 재 실행 시켜주기 때문에 잠깐 깜빡거리는 수준이지만 ..


앱이 아예 죽지 않고 임의의 코드를 실행하려면 아래 조건을 만족해야 합니다.

 

1. execve 류 함수 사용 X 

 

2. fork 사용 X [ System 함수는 fork & execve의 조합 사용이므로 역시 불가 ]

 

library 내에서 fork를 사용하게 되면 Fig6 과 같이 정상적으로 생성되지 않고 zombie가 됩니다.


android app은 fork 함수를 지원하지 않는 거 같네요.

 

<Fig6. fork 사용 후 Process>

 

3. stack 복구

 

취약점 발생 구간과 메모리 참조 영역을 주의 깊게 살펴보셔야 합니다.


덮어 씌운 부분이 후에 참조될 경우 crash가 날 수 있으니까요.


취약 함수가 return 값을 가지고 있는지, 가지고 있다면 어디서 참조 하는지 ..


호출된 jni 함수가 아예 void return 이면 그 쪽으로 단번에 넘어가버리는 게 가장 좋겠죠.

 

아무튼 이런 조건이 맞는다면 execve 함수 사용이 제한되기는 하나 특정 코드는 무인지 공격이 가능하게 됩니다.

 

예를 들어 stack 에 권한을 주는 코드를 무인지로 실행한다던가 말이죠.

 

 

 

저작자 표시
신고
Posted by LinkC

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

2013.01.03 14:24 System

[+] Introduction 


 

새해 첫 포스팅입니다.

 

<Fig0. 2013년 어서와>

 

이 글 읽는 여러분 모두 죽음에 한발짝 더 다가오신걸 환영합니다 ^0 ^

 

아무튼 오늘의 주제는 널리 쓰이는 상용 Protector Themida 의 Anti reversing 중 몇 가지를 분석해보고자 합니다.

 

Themida는 API redirection에 Debugger Detection , Resource Encryption , Memory guard 등

 

온갖 기법을 사용합니다.

 

그 중에서도 이번에 타겟은 Debugger Detection 과 Monitor Blocker 입니다.

 

 

[+] Running shot


 

실제로 위 기법들이 동작했을 때의 모습을 살펴보죠.

 

<Fig1. Debugger Detection>

 

<Fig2. Monitor Blocker>

 

 

컴퓨터에 관심이 많으시고 게임을 꽤 즐기시는 분들은 몇번 씩 봤을 법한 Mesasge Box입니다.

 

"A monitor program has been found running in your system. Please, unload it from memory and restart your program."

 

위 Mesage를 보는건 아래와 같은 상황이겠죠.

 

1. Protection이 걸린 Program을 실행 시키고 Debugger를 실행했을 때 [ 혹은 그 반대 ]

 

2. Protection이 걸린 Program을 실행 시키고 Monitoring Program 을 실행했을 때 [ 혹은 그 반대 ]

2-1. Monitoring Program을 한번 이상 실행 시키고 종료 한 다음, Protection 이 걸린 Program 을 실행 했을 때

 

실행 중에도 잡아내는 것을 보면 Program 실행시에 한번 Check 하는 것이 아니라,

 

별도의 Thread가 주기적으로 확인한다는 것을 알 수 있습니다.

 

다만, 의문이 생기는건 2-1 번이죠. 왜 Monitoring Program을 종료시켰는데도 이런 Message가 뜨는가?

 

잠깐(?) , 머리 좀 식히려 게임을 켰을 때 반겨주는게 짱세고 귀여운 캐릭터가 아니라

 

흰색 바탕에 검정 글씨가 점철된 저런 기계적인 그래픽 덩어리라니!

 

우리에게 공부만 하라는 컴퓨터의 아름다운 배려에 현기증만 납니다.

 

<Fig2-1. 아 현기증 난단 말이에요>

 

저렇게 되면 재부팅을 하는 수밖에 없거든요.

 

Monitoring Program은 진작 껐는데 그걸 또 어떻게 알았는지 ...

 

이 현기증의 근원지는 뒤에서 설명하도록 하겠습니다.

 

 

 

 

[+] How to run


 

실제로 내부적으로 사용한 방법을 살펴보면 복잡하지 않습니다.

 

 

<Fig0-1. 진짜로 안복잡함 ㅋ>

 

다만 이 기법들 모두 실행 프로그램 내부에 포함되기 때문에 기법 자체도

 

Themida의 가호 아래 있게 되고, 이 때문에 파악하는데 애로사항이 꽃피게 됩니다.

 

1. API Name 및 인자 확인

 

우리가 Themida의 투명 망토를 걷고 확인해야 할 것은 API Name 및 인자입니다.

 

문제는 이 투명 망토 성능이 꽤 괜찮다는 건데요.

 

Themida 가 직접 호출하는 API는 기본 Hooking 방법으로는 알기 쉽지 않습니다.

 

API 초반부를 타지 않고 중반부터 타는 형식을 사용하거든요.

 

그 덕에 함수 초반에 거는 Hooking 방법은 무용지물이 됩니다.

 

[ 물론 특정 Hooking 하는 Service를 이용하기 위해 이 기법을 사용하지 않는 것도 Themida의 옵션에 존재합니다. ]

 

하지만 이 방법도 하위 함수가 존재하는 API 에서는 별 소용이 없습니다.

 

예를 들어 Printf 를 호출하면 내부에서 Writefile [ Windows의 경우 ] 를 다시 부르게 되는데

 

Writefile에 Hooking 을 걸고 Tracing 하면 얼추 어떤 함수를 호출했는지, 어떤 의도를 가지는지 확인 할 수 있다는 겁니다.

 

따라서 Themida 내부에서 사용하는 함수를 확인하기 위해서는 비교적 아래단의 함수를 Monitoring 하는 것이 좋습니다.

 

이를 통해 NTQuerySystemInformationRtlMultiByteToUnicodeN 을 주기적으로 호출함을 확인 할 수 있었습니다.

 

 

2. String 확인

 

많은 힌트가 되는 String 입니다.

 

Themida에서 사용하는 String 은 2가지 종류가 있을겁니다.

 

1. API 의 인자로 주는 String

2. 내부적으로 사용하는 Data String

 

전자의 예는 Fig1이나 2에서 보았던  A  ~ has been found 이런 Message 들입니다.

 

이 녀석들은 MessageBox 를 호출 할 때 인자를 평문으로 주어야 합니다. 

 

[ 물론 Program 내부에는 암호화 되어 들어가 있기 때문에 Program의 Hex 값을 검색해서는 나오지 않습니다. ]

 

그 때문에 이런 녀석들은 동작 중에 Memory Dump를 떠서 확인하면

 

그대로 찍히게 됩니다. 이 방법은 Program의 사용자가 지정한 문자열 역시 마찬가지겠죠.

 

 

<Fig3. Memory Dump를 뜨고 문자열을 확인한 모습>

 

후자는 약간 까다롭습니다.

 

예를 들어 문자열 비교를 할 때, 한 글자씩 비교 하는 함수를 임의로 만들어서 사용하거나

 

Hash 값 등을 사용하여 비교 한다고 하면 내부적으로 사용하는 문자열을 알기 귀찮아지죠.

 

다행인건 , Themida가 Hash 값 까진 쓰지 않았다는 겁니다.

 

친절하게도 Themida에서는 String을 Multi byte -> Unicode로 Converting 하는데 API 를 사용하고 있더군요.

 

하위 함수인 RtlMultiByteToUnicodeN 를 Monitoring 해서 사용하는 문자열을 긁어내면 다음과 같습니다.

 

<Fig4. Themida가 내부적으로 사용하는 String들>

 

String은 위대했습니다.

 

어떤 함수를 이용할건지도 대충 감이 오네요.

 

Thread를 돌면서 FindWindow 로 저들을 확인하고 있었던 거겠죠.

 

또 NtQuerySystemInformation 에서 얻어온 String 과 비교를 한 것이구요.

 

실제로 Loading 되는 Module Name을 확인해봅시다.

 

 

<Fig5. System에 Load 된 Driver>

 

Monitoring Program중 하나인 Process Monitor 에서 Load 시킨 PROCMON23.sys가 Unload 되지 않고 남아 있습니다.

 

이게 바로 Monitoring Program을 종료 시켜도 Themida에서 계속 잡는 이유죠.

 

 

 

[+] Bypassing!


 

Findwindows를 이용한 방법은 말 그대로 내부 class 이름을 죄다 바꿔주면 됩니다.

 

Debugger 쪽은 손쉽게 우회가 가능하죠.

 

그렇다면 Monitor blocker는 어떻게 우회할까요?

 

[ Themida 적용 Program 실행시에도 Monitoring Program을 실행하고자 한다면 Class 이름 바꾸는것은 물론 선행되어야 합니다. ]

 

저 Driver를 Unload 시켜야 하겠죠?

 

Process Monitor에서는 왜 Unload시키지 않을 까요?

 

Sysinternals의 admin group 중 한명이 이렇게 대답했다고 하는군요.

 

<Fig6. Driver를 Unload시키지 않는 이유>

 

<Fig7. Driver를 Unload 시키지 않는 이유>

 

뭐 둘다 같은 이야기를 하고 있는거 같네요.

 

이걸 Unload 시켜야 재부팅 하는 수고를 덜 수 있을 텐데 말이죠.

 

Anti Rootkit Program을 써서 이걸 강제로 삭제 시켜버리는 방법도 시도해봤습니다만 삭제가 안됩니다.

 

위에서 언급한 것처럼 강제로 하려고 했다간 BSOD 를 볼 것 같고 해서 강제로 Unload 시키는 방법 외에 다른 방법을 찾아봐야겠군요.

 

그럼 어떤 방법이 있을 까요?

 

Themida에서는 Driver의 문자열 정보만 확인 하는 걸로 보입니다.

 

그렇다면 다른 이름으로 저 Driver를 올리면 되죠.

 

Process Monitor 내에서 참조하는 모든 Driver Name을 임의의 문자열로 바꾸면 됩니다.

 

이렇게 하면 Monitor Driver를 강제로 Unload 하지 않고도 실행 할 수 있습니다.

 

 

[+] Conclusion


 

야호 재부팅 안해도 된다!

 

그냥 재부팅 하신다구여?

 

죄송해여..

 

근데 솔직히 이게 더 귀찮은듯

 

 

 

 

 

 

 

저작자 표시 비영리
신고
Posted by LinkC

블로그 이미지
LinkC

태그목록

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

공지사항

Yesterday143
Today101
Total282,956

달력

 « |  » 2017.09
          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

최근에 받은 트랙백

글 보관함


. .