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.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

2012.12.27 20:25 System

[+] Introduction 


 

사람이 가장 잉여스러워지는 시간인 방학이 찾아왔습니다.


정신차리고 보니 크리스마스가 지났네요 

 

<Fig. 24일에 올렸어야 할 짤방>

 


왠지 1년 전에도 이와 비슷한 일이 있었던 것 같지만 그냥 넘어가요 우리..


아무튼 새해가 찾아오기 전에 글이라도 하나 올려야 제 자신에게 변명거리라도 될 거 같아요.

 

 




[+] What is "Code obfuscation"? 


 

코드 난독화는 Program들이 나날이 자신들을 역공학 해주는 리버서들의 열정에 몸둘바를 몰라 만들어낸 일종의


자기 방어술입니다.


리버서들의 목적이 대부분 악용에 있다 보니 , Program 업체들은 자신들의 자산이 까발려지지 않기 위해 혹은 악용되지 않기 위해


Anti-debugging 부터 해서 실행 압축 [ Packer ] , 여기서 더 나아간 Protector 까지 적용합니다.


물론 , 이 기술들이 악성 코드에 적용되고 있는 건 다시 말할 것도 없겠죠.


이 중에서 코드 난독화는 Protector에 흔히 적용되는 기술인데 말그대로 코드를 읽기 어렵게 하는 겁니다.


암호화 하고 코드를 치환하고 API 호출을 빙빙 돌려서 정적 분석 뿐만 아니라 동적 분석 까지 막는 것이 그들의 임무입니다.


리버서들이 해석하기 어렵게 코드를 짜야 합니다. 이를 해석해주는 Disassembler가 해석하기 어렵게 코드를 짜야 합니다.

 

이를 위해서 실제 소스 코드 상에서 말도 안되는 Dummy code를 집어넣어 흐름을 헷갈리게 만드는 경우도 있습니다만,

 

그보다는 Assembly 단에서 명령어를 꼬아서 혼란시키는 방법을 많이 사용하고 있습니다.

 

오늘 말하려고 하던 주제가 여기서 더 깊숙히 들어가면 멀어지는 관계로 간단히 정리만 하고 넘어가죠.

 

Disassembly 기법은 크게 2가지 정도 나눌 수 있습니다.

 

- Linear sweep

 

- Recursive traversal

 

이 2가지 방법의 알고리즘을 이해하고 나서,

 

그 알고리즘으로서는 해석하면 실제 실행한 것과 다른 결과를 내는 임의의 코드를 삽입하는 거죠.

 

실행과는 전혀 상관 없는 Dummy assembly 를 잔뜩 집어 넣는 방식도 해석하는 입장에서는 정말 짜증날 수 밖에 없습니다.

 

 

<Fig. 코드 난독화가 되어 있는 것을 확인했을 때>

 

 

 

[+] what`s the applicability of code obfuscation?


 

코드 난독화의 대상이 될만한 것이 무엇이 있을까요?


Disassembly 혹은 Decompile이 매우 쉽게 이루어지며 그 결과물이 실제와 가장 근접한 것이 이 난독화의 힘을 가장 많이 볼 수 있지 않나 싶은데요.

 

떠오르신 바로 그겁니다.

 

Java

 

아니라구요? ㅈㅅ...

 

Java는 그 특성상 구동방식이 일반 Application 과 다르기 때문에 코드 난독화를 적용하는데 어려움이 있는 건 사실입니다.

 

하지만 Java에서도 C, C++ 를 사용할 수 있는 방법이 있으니 [ 즉 우리가 알고 있는 Disassembly 를 적용할 수 있는 언어 ]

 

그것이 바로 JNI [ Java Native Interface ] 입니다.

 

* 이 방법외에도 이미 Java 에서는 안드로이드 시장이 활성화됨에 따라 Dex guard, Pro guard 등 코드 분석을 어렵게 하는 방식들이 존재합니다.

 

 

 

 

[+] Considering about JNI 


 

JNI 는 Java에서 Loadlibrary 를 통해 C, C++ 혹은 assembly 로  이루어진 library 를 호출 할 수 있도록 하는 Framework 입니다.

 

원래 목적은 말그대로 C, C++ 등으로 이루어진 library 를 추가 구현 없이 java에서 사용하기 위함입니다.

 

혹은 복잡한 수학연산 등은 JVM 보다 native code가 빠르므로 JNI 를 이 분야에서 사용하기도 하죠.

 

아무튼 이 JNI 를 통해서 기존에 사용했던 코드 난독화 기법등을 사용할 수 있게 됩니다.

 

Library 자체를 packing 하여 실행 압축을 사용할 뿐만 아니라 dummy code등을 사용할 수 있죠.

 

추가적으로 api redirection 이나 함수 포인터를 이용하여 분기 하는 모듈을 리버서에게 노출 시키지도 않을 수 있습니다.

 

가변 인자를 사용하면 모든 함수들의 호출을 일반화 할 수 있고, 함수를 구분하는 식별 인자 또한 고정방식이 아니라

 

유동적으로 변하되 항상 같은 값을 유도할 수 있게 만들 수 있죠.

 

이렇듯 코드 난독화 기법은 고정적인 방법이 아니라 얼마든지 다양한 방법으로 접근 할 수 있습니다.

 

 

 

 

 

 

쓰고보니 별로 기술적인 내용이 들어갈 게 없네요..

 

기존 난독화 기술을 설명하자니 좀 식상할 것 같고 .. 좀 더 신박한 난독화 기술이 있다면 들고 오도록 하겠습니다.

 

 

Posted by LinkC

2012.10.05 11:43 System

[+] Introduction


 

오늘의 주절 거림 대상은 감성의 iOS 입니다.


맛폰 사용률이 급격히 늘어나면서 모바일 보안쪽도 덩달아 관심을 받고 있는데요.


개방적인 안드로이드에 비해서 iOS는 상당한 제약을 두고 있죠.


그 덕에 루팅은 매우 쉽게 되고 있는 반면, 탈옥 쪽은 iOS가 버전업을 할 떄마다 전투가 벌어집니다.


Soft 단에서는 물론 Hard 측에서도 탈옥 감지 루틴을 넣어두었고 탈옥폰에서는 동작 하지 않도록 하는 어플들도 


간혹 보이고 있습니다. 


전에는 bootrom, loader, kernel 정도만 수정했어도 됐는데 말이죠. 라고


쉽게는 말했지만 그렇게 호락호락한 작업은 아닙니다.


boot rom , loader 의 check를 우회하고 들어가서 loader를 교체하고 kernel을 수정해야 합니다.


그러니까 교도관을 속이고 감옥에 들어가서 탈출할 수 있도록 시스템을 분석 후 교체 하고 


최후에는 우리쪽 교도관을 세워야 된다는 소리죠.


프리즌 브레이크보다 더 스릴 넘치는 이야기가 아닐 수 없군요.


 

<Fig. 시도조차 못하겠는데요>



 

이렇게 사람들이 저마다 석호필을 꿈꾸며 탈옥하고자 하는 이유는 여러가지가 있습니다.


애플이 막아둔 기능의 활성화 , customizing  혹은 사형선고를 받은 형을 구하러 간다던가 하는 걸로요.


다행스럽게도 이번 포스팅에서 다룰 부분은 탈옥한 상태의 iPhone을 대상으로 이루어집니다. 괜찮아요. 어렵지 않아요.


kernel patch, boot loader 수정 원리 등은 추후 포스팅에서 다룰 수 있... 지 않을까 생각해봅니다.

 

iPhone 의 Hooking은 Mobile Substrate라는 기본 탈옥 library를 이용하며 본 포스팅은 이를 분석하는 글입니다.

 

Library의 함수명 , 사용 방법 보다는 동작 원리 등에 중점을 두고 쓰도록 하죠.

 

 

 

 


[+]  Find how to patch the code 


 

가장 기본이 되는 Hooking의 원리는 물론 Code Patching 이겠죠.

 

그런데 이 Code Patching 을 어떻게 하느냐?

 

 

 

1. 원격으로 Thread를 만들어 Code를 삽입. 실행.

 

- Code Injection 얘기죠. 다만, 이미 실행되 Process를 Target으로 잡고 있으며 ,

 

새로 실행되는 Process를 감시해야되는 점이 단점으로 남죠.

 

게다가 iOS의 특성상 Sandbox 로 각 Process간에 벽이 존재하는 점 또한 큰 걸림돌이 됩니다.

 

탈옥 했다는 것은 곧 Sandbox를 탈출했다는 소리지만, 일반 앱들은 아직 mobile user 로 돌아가며

 

Sandbox 내에 있어요.

 

 

 

2. dylib 를 injection 한다.

 

 - Windows의 DLL Injection과 유사한 방법입니다. 다만 특정 Process에서 Target Process로 DLL을 Load 시키는 것이 아니라

 

[ 이 방법대로 하면 Code Injection 과 별 다를바가 없죠 . ]

 

Process가 실행 될 때 dylib [ 동적 library ]를 강제로 Loading 하게 만들고 내부에서 Code를 수정하는 방식입니다.

 

Windows 에서도 Process 시작시에 DLL을 강제 Loading하는 방법이 있죠.

 

자기 자신에서 Code를 바꾸기 때문에 Sandbox도 문제가 될 건 없어요.

 

다만.. iOS의 kernel은 기본적으로 한 메모리 구역에 쓰기 속성과 실행 속성을 동시에 줄 수 없습니다.

 

이 부분은 kernel 단에서 수정이 되어야 하는 것이고, 탈옥을 하면서 이루어진 kernel patch 중 하나가 됩니다.

 

하지만 기본적으로 text 영역엔 쓰기 속성이 없기 때문에 Patch 하기 전에는 쓰기 속성을 주셔야겠죠.

 

 

 

3. kernel level의 system call table을 바꾼다.

 

- kernel hooking 입니다. 사실 불특정 다수의 Process를 control할 때 가장 우아한 방법이긴 합니다만, 

 

이번 포스팅의 주제는 User level hooking 이므로 넘어가도록 하겠습니다.

 

iOS의 Kernel level hooking 은 이미 작년에 유동훈님이 성공하셨다고 하더군요. 시연은 Android만 하셨다고 들었습니다.

 

이번 Code Engn 에서 android 취약점 공격 분석에 관해 발표도 하셨더라구요.

 

http://codeengn.com/file/conference/2012/2012_6th_CodeEngn_[x82]_%EB%AA%A8%EB%B0%94%EC%9D%BC_%EC%8A%A4%EB%A7%88%ED%8A%B8_%ED%94%8C%EB%9E%AB%ED%8F%BC_%EC%9B%90%EA%B2%A9_%EB%A1%9C%EC%BB%AC_%EC%B7%A8%EC%95%BD%EC%A0%90_%EA%B3%B5%EA%B2%A9_%EB%B6%84%EC%84%9D.pdf

 

 

흥미로운 주제니 한번씩 보고 가시는것도 좋을거 같네요.

 

 

 

[+] Analysis the hooking method 


dylib를 로딩 시켰다면 이제 쓸 영역에 쓰기 권한을 주어야 합니다.

 

vm_protect 함수를 이용하여 해당 부분에 쓰기 권한을 주고 난 후 Code를 바꿔봅시다.

 

여기서 주의할 점은 ARM + THUMB mode 둘 다 생각하셔야 된다는 건데요,

 

16bit instruction 을 지원하기 위해 만든 THUMB mode 가 아직도 사용됨에 따라 그쪽 분기를 따로 만들어야 합니다.

 

[ 물론 이 부분은 mobile substrate에서 자동으로 해줍니다. ]

 

아무튼 mode가 달라지면 patch 해야 하는 code 자체가 달라지므로 주의를 해야 합니다.

 

ARM mode는 1 instruction 이 4byte고 THUMB mode는 1 instruction 이 2byte 라서 말이죠.

 

그렇기 때문에 같은 명령어라도 THUMB mode에서는 ARM mode에서 존재하는 instruction 을 재현하기 위해

 

여러가지 instruction 을 조합해서 쓰곤 합니다.

 

그렇게 때문에 hooking 하는데 쓰이는 code는 mode별로 크게 다르지 않아요.

 

THUMB mode 같은 경우는 ARM mode로 바꾼 후 patch 하는게 편하겠죠.

 

windows에서 흔히 쓰는 방법과 크게 다르지 않습니다. JMP! JMP!

 

 

 

<Fig1. Hooking 할 함수에 code patching 을 한 상태>

 

bx pc 명령어를 사용하여 제자리 JMP!

 

그리고 ARM mode로 변경합니다.

 

 

 

<Fig2. Hooking 할 함수중 일부. ARM mode로 변경>

 

ldr 명령어를 통해 pc counter가 가리키는 곳의 주소로 다시 JMP! 합니다.

 

*gdb에서는 끝자리가 홀수 일경우 THUMM mode , 짝수일 경우 ARM mode로 출력합니다.

 

 

<Fig3. 다음 점프할 곳은 0x658984!>

 

0x658984는 저희가 입력한 Code가 있는 곳입니다.

 

 

<Fig4. 사용자가 지정한 custom function 으로 이동한 모습>

 

중간에 blx는 원본 함수를 호출한 건데요. 이 부분은 code patching으로 잘려나간 원본 함수의 초반 부분과

 

JMP 이후의 원본 함수의 주소 값으로 다시 되돌아가는 명령어가 있습니다.

 

<Fig5. intermediate code>

 

 

<Fig6. 되돌아갈 함수의 주소>

 

그리고 원본 함수 대신 실행된 code는 저희가 지정한 dylib에 있어야 정상일테니 확인해봅시다.

 

<Fig7. hooked code가 지정한 dylib에 있는 것을 확인한 모습>

 

 

[+]Conclusion 


 

 

 

<Fig. 뭐래는거야>

 

 

제가 작성했는데도 뭔 소린지 모르겠어요.

 

정리해봅시다. 

<Fig8. Hooking의 흐름>

 

이렇게 보니 별거 아니군요?

 

비슷한 방법이다 보니 Hooking 을 방지 하는 방법도 windows와 비슷한 맥락에서 막을 수 있을거 같습니다.

 

1차적으로는 탈옥되었는지 여부를 판단하면 되겠죠.

 

실제로 skype는 이를 감지하여 비정상 동작을 하더군요. 게다가 gdb도 못붙이게 하구요.

 

아무튼 , 기회가 된다면 다음엔 탈옥시 kernel patch 하는 부분을 살펴볼까 합니다.

 

근데 iOS image내부에 kernelcache 가 IV , Key가 안맞는지 풀리지 않아서 언제가 될런지는 모르겠네요.
 

 

 

 

 

 

 

 

 


Posted by LinkC

2012.09.29 13:47 System

 [+] Introduction


 

모든 Thread가 멈춰있는데 memory 가 변경되는 process가 있을까요?

 

<Fig0. 흥미로운데 이거>

 

 

 

 

[+] Analysis 


 

몇가지 짐작 해 볼 수 있는 건 있네요.

 

1. Remote Create Thread를 이용한 다른 프로세스의 간섭

 

 - 아, 이건 결국 Thread를 Target Process에 생성하고 그 Thread도 멈춰있다고 생각하면 기각이겠군요.

 

2. Shared Memory 를 이용한 접근

 

 -  Thread는 정지 하고 있어도 값이 변경되니 이게 정답일까요?

 

 

하지만 iOS의 sandbox가 출동하면 어떨까?

 

Windows 는 Process 서로 간의 벽이 낮지만 iOS는 상당히 폐쇄적입니다.

 

모래 상자 하나씩 잡고 각자 놀아요.

 

하지만 예외가 있는데요.

 

Audio 처리가 바로 그 중 하나 입니다.

 

iOS의 Audio 처리는 Core Audio 를 기반으로 하죠.

 

다음은 iOS Dev Center에서 가져온 Core Audio 구조입니다.

 

 

<Fig1. iOS Core Audio architecture>

 

 

Core Audio는 kernel realtime thread 를 지원받는 Frame work 인데요.

 

Audio unit 을 통해 이에 접근 할 수 있고 Real time 으로 처리되는 Audio Data를 얻을 수 있다는 거죠.

 

아래 그림을 통해 좀 더 쉽게 이해해봅시다. 마찬가지로 DevCenter 펌

 

 

<Fig2. Audio processing graph>

 

앞서 Real time 처리 된다고 언급 했던 것을 기억하시나요?

 

AudioUnitRender 함수를 호출시 얻어오는 Audio Data가 그 시간의 정적인 Data를 Copy 해오는게 아니라

 

계속 변하고 있는 Memory 의 주소를 가리킨다는 것입니다.

 

공유 메모리와 비슷한 개념으로 이해하시면 될 것 같군요.

 

다만 User level process간 통신이 아니라 kernel 과 User level process간의 공유메모리로 보심이 옳겠죠. 

 

 

 

<Fig3. gdb 로 Bp가 걸려 있는 시점에서 같은 주소를 Dump했을 때 Data가 달라지는 모습>

 

[+] Conclusion 


처리 방식이 상당히 흥미롭습니다.

 

Audio Unit을 사용하는 Process가 많으면 많을수록 Overhead가 줄어들것이고 kernel 과의 통신을 통해

 

sandbox 의 존재 의의를 지켰다는 점에서도 이 감성은 높이살만 한 거 같습니다.

 

흠.. kernel의 Audio module 쪽에 접근하여 경계를 깰 수 있다면 이것 또한 재밌는 이슈가 되겠네요.

 

내용 정리는 위키에게 맡깁니다.

 

 

 

다음 포스팅은 iOS Hooking에 관한 것이 될 거 같군요.

 

올해 안에 다시 뵙도록 하겠습니다 ㅂㅂ

 

 

Posted by LinkC

2012.08.04 15:26 System

[+] Introduction 



요즘 날씨 정말 덥네요.

 

컴퓨터 + 냉장고 열기 덕분에 제 방은 사막화 되어 가고 있습니다.

 

아 불지옥이 여기구나 ㅎㅎㅎㅎㅎ


 

<Fig0. 으앙 더워서 쥬금 ㅋ>

 

아무튼 오늘은 ftp나 WebDav 등을 물리 디스크처럼 마운팅 해 주는 프로그램을 분석하는 글을 써보도록 하겠습니다.

 

[ 사실 Driver와 DLL, Service 간의 통신에 초점을 맞췄습니다만 ]

 

그저 통신 방식 등을 알리는 글이라 해당 프로그램에 피해가 가진 않을거라고 봅니다만,

 

만약 관계자 분께서 이 글이 거슬린다고 하시면 바로 내리도록 하죠.

 

소개드릴 프로그램의 이름은 'NetDrive' 입니다.

 

Windows에서는 기본적으로  Network Drive 형태로 마운팅 하는건 지원합니다.

 

하지만 위 프로그램처럼 물리 디스크 처럼 사용하는건 지원하지 않죠.

 

 

[+] Analysis 


 

프로그램 UI 는 과감히 패스 하고 바로 분석 들어갑니다.

 

일단 프로그램을 깔게되면 Service를 설치하게 됩니다.

 

A. Service는 실행파일과 통신할 Pipe [ 단방향 공유메모리 ]를 만듦.

 

B. 프로그램을 실행하면 ndapi.dll이라는 dll을 Load.

 

C. CreateFile 로 A에서 만든 Pipe에 접속.

 

<Fig1. CreateFile로 Service와 통신할 Pipe에 접속하는 모습>

 

D. 프로그램 설치 후에 접속할 Server의 정보를 입력한 후 Connect. [ ftp 나 WebDav 등 사용자가 입력한 주소에 접속을 시도 ]

E. DLL내의 MountDrive 호출.

  

<Fig2. DLL 내의 Export 함수>

 

F. WriteFile을 통해 접속한 Pipe에 접속 정보를 기록. 

 

<Fig3. WriteFile을 통해 Pipe에 접속 정보를 기록하는 모습>

 

 

G. Service에서는 해당 pipe를 계속 감시하고 있다가 정보가 쓰여지면 위 정보에 해당하는 함수를 호출 [위 경우는 Drive Mount ]

 

 

<Fig4. Switch 문을 통해 해당하는 함수를 호출하는 모습>

 

 

H. Drive의 Mount에 앞서 지정한 Server가 실제 동작하는 Server인지 Test Connection을 진행.

 

 

<Fig5. Server 접속 정보를 체크하는 모습>

 

I. Service에서 Driver가 Load 되었는지를 확인하고 Load 되어있지 않으면 OpenSCManger , OpenService를 통해 Driver Load. Drive 명은 ndfs.sys

<Fig6. OpenService를 통해 Driver를 Load하는 모습>

 

J. Load 한 Driver를 CreateFile로 Open

<Fig7. Driver를 CreateFile로 Open 하는 모습>

 

 

K. DeviceIOControl을 통해 Driver와 통신하여 Drive Mount 시도.

 

<Fig8. DeviceIOControl을 통해 Driver와 통신하는 모습>

 

L. DefineDosDevice를 통해 지정한 DriveLetter에 Symbolic Link를 생성

 

<Fig9. DefineDosDevice를 통해 Symbol Link를 생성하는 모습>

 

 

<Fig10. DefineDosDevice함수와 인자가 나타내는 정보>

 

 

M. Netdrive에서는 Service와 통신하며 상태 갱신. [ Logging in… -> Mount Starting… -> Establishing Communication… -> Mounting Driver… -> Setting Volume Lable -> Mount Compelte. ]

 

<Fig11. Service와 통신하며 상태를 갱신하는 모습>

 

 

N. Mount가 완료되고 Explorer를 통해 폴더를 열어줌. 

 

<Fig12. Mount가 완료된 모습>

 

 

O. Disconnect 시에는 UnMountDrive가 호출되고 DefineDosDevice를 통해 해제.

 

<Fig13. UnMount 호출시의 모습>

 

 

Service, Driver, DLL 간의 통신 방식을 정리해보면 아래와 같습니다.

 

 

<Fig14. NetDrive 동작 개요도>

 

 

 재밌네요.

 

이번 글은 Network drive를 Mounting 하는 과정을 분석하기 보다는 Driver와 DLL  그리고 Service 간에 통신하는 방법에 초점을 맞추고

 

써보았습니다.

 

 

[+] Chat 


시원한 곳에서는 졸리고 퍼져서 집에 가서 글 써야징 ★

 

집에서는 덥고 짜증나서 시원한 곳 가면 글 써야징 ☆

 

<Fig. Just like inception!>

 

 

 

Posted by LinkC

2012.07.29 01:54 System

[+] Introduction 


 

생각보다 빨리 글을 쓰게 됐네요

 

잉여력이 자꾸만  상승하는 관계로 위해 간단하고 짧고 가벼운 주제로 올려보겠습니다.

 

 

<Fig0. 호오 잉여력이 상승하는군요>

 

오늘의 주제는 CLSID 를 이용한 파일, 폴더 숨기기 입니다.

 

간단히 말씀드리자면 휴지통을 이용한 방식인데요.

 

이 방법을 이용하면 숨김 파일 혹은 시스템 파일 보기로는 파일을 확인할 수 없으나

 

cmd 창의 dir /A 를 이용하면 가능합니다.

 

이 만들어진 폴더를 복사 할 내부의 파일, 폴더 이름이 노출될 수 있으니 재미로만 보시면 될거 같네요.

 

 

[+] Analysis 


 

새 폴더를 만들고 폴더 명을 다음과 같이 지정해줍니다.

 

"1.{645FF040-5081-101B-9F08-00AA002F954E}"

 

물론 1 대신 아무거나 입력하셔도 됩니다.

 

그렇게 만들어 주시면 휴지통과 같은 모습, 속성의 폴더가 생깁니다.

 

이 휴지통은 해당하는 드라이브의 실제 휴지통과 내용을 공유하고 있죠.

 

 

<Fig1. 어멋, 휴지통이 뙇! >

 

저 폴더 명의 의미가 무엇인고 하니

 

CLSID 이고 우리가 쓴 건 바로 휴지통에 해당하는 CLSID 였던거죠

 

<Fig2. 휴지통의 CLSID 를 확인>

 

이렇게 만든 폴더는 굉장히 특이한 속성을 가지고 있습니다.

 

들어가보면 휴지통과 다를바가 없죠.

 

파일, 폴더 생성 등은 되지 않습니다만..  [ 물론 CreateFile이나 CreateDirectory를 이용하면 가능합니다. ]

 

외부에서 복사가 가능합니다.

 

그냥 드래그를 하면 삭제가 되어버리니 cmd 창의 copy 명령어를 이용합시다.

 

숨김, 시스템 파일은 xcopy 에서 h 옵션을 주면 가능합니다.

 

 

<Fig3. xcopy 명령어를 이용하여 파일을 복사한 모습>

 

이렇게 파일을 복사하고 나면

 

dir 명령어로는 확인할 수 없고 dir /A 명령어를 통해서만 확인할 수 있는 구조가 완성됩니다. [ 숨김 속성을 주었을 때 ]

 

해당 휴지통으로 들어가면 텅텅 비어있어 확인하는게 불가능하구요

 

 

<Fig4. dir 명령어를 통한 파일 확인>

 

일반인은 확인 하기 어렵겠죠?

 

자신의 비밀스러운 파일이나 폴더등은 여기다가 두시면 되겠습니다.

 

물론 누가 폴더 통째로 삭제 할때의 책임은 제가 지지 않습니다 ㅎㅅㅎ

 

 

 

그냥 이런 색다른 방법도 있다구요.. 네..

 

 

 

 

Posted by LinkC

2012.07.28 12:40 System

 

[+]... 


 

<Fig0. 죽었어..>

 

네 반년 넘도록 죽었습니다. 빠져가지고..

 

다시 살아나도록 발버둥 치고 있어요.

 

이와 비슷한 전개를 작년에 본것 같은 것은 착각일겁니다.

 

아무튼 이번에 포스팅할 글은 E-book 보안에 관한 글입니다.

 

사실 심도 있는 내용의 포스팅은 아니고 한번 쯤 그냥 훑어볼만한 주제죠.

 

인터넷에서 책을 구매하신다면 종이책이 아닌 전자책 형식으로 판매하는 곳을 보셨을 겁니다.

 

사실 종이책의 책장 넘기는 맛이라던가 소장의 가치도 정말 무시할 수 없습니다만, E-book 은 또 그 나름대로의 매력을 가지고 있죠.

 

요즘 같이 스마트 기기가 많이 보급됨에 따라 E-book 이 상당한 인기 몰이를 하고 있습니다.

 

문제는 전자 문서 형식이다 보니 배포가 될 수 있는 위험성을 가지고 있고, 이에 따라 각 업체들은 여러가지 보안 기술들을 적용하게 됩니다.

 

 

 

[+] Analysis 


 

분석에 앞서 어떤 업체들이 E-book 단말기를 사용하는지 그 단말기의 지원 포맷이 무엇인지 살펴봅시다.

 

 

<Fig1. E-book 제공 업체별 단말기 및 지원 포맷>

 

호오 ePub 포맷이 많이 보이는군요.

 

ePub 포맷은 특정 파일 및 폴더들을 담고 있는 압축 포맷입니다.

 

 

<Fig2. ePub 포맷의 파일 구조>

 

 

META-INF 에는 폴더, 파일 구조, 컨텐츠 외의 내용들이 XML 형태로 저장되어 있고

 

OEBPS 에는 컨텐츠 내용이 들어있습니다.

 

하지만 이 표준화된 포맷은 자체적으로 보안 기술이 적용되어 있지 않아 각 업체별로 DRM을 걸고 있습니다.

 

그것도 다 따로 따로요..

 

 

<Fig3. 업체별 DRM 적용 기술>

 

 

실제로 이 DRM 기술들을 분석해보면 아래와 같은 구조를 가지고 있는 것을 파악 할 수 있습니다.

 

아무래도 특정 회사의 DRM 구조를 언급하는것은 피하고자 업체 명 , 아이콘등은 지운것을 감안하고 봐주세요

 

<Fig4. 모 업체의 DRM 기술 분석>

 

 

다른 업체의 DRM 기술들도 거의 비슷한 구조를 가지고 있습니다.

 

훈훈하게도 모두 암호화는 꼬박꼬박 하고 있습니다.

 

 

<Fig5. 모 업체의 DRM 기술 분석2>

 

사실 별 다를건 없습니다만 모든 업체별로 암호화 방식, 메모리 로딩 방식이 다르다 보니 한 업체의 ePub 파일이

 

다른 업체의 뷰어로 열리지도 않고 각 전용 뷰어로만 열리는 사태가 일어납니다.

 

 

 

[+] Problem & Solution


 

문제는 국내 모든 업체들의 뷰어를 살펴보았습니다만.. 모든 업체들이 하나 같이 복호화 함수 하나를 통해 ePub 파일 통째로 혹은 한 페이지 별로 복호화를 수행해 낸다는 점이죠.

 

어떤 프로그램이든지 Crack 될 수 있는 가능성이 존재합니다만 현재 eBook 뷰어들은 너무나도 취약합니다

 

아무리 복잡한 암호화 기술을 걸어도 말짱 도루묵이라는 겁니다.

 

 

 

<Fig6. 복호화하여 추출한 이미지 파일>

 

파일 개별로 암호화를 한 업체에게는 칭찬을 해 주고는 싶다는건

 

풰이크고

 

Decrypt 함수에 후킹 걸고 저장 루틴을 씌운다음에

 

그냥 파일 한페이지씩 쭉 읽어들이면 책 한권이 무방비 상태로 뚝딱 생기는 겁니다.

 

여기서 제가 말씀드리고 싶은 점은 좀 더 꼬아놓는 기술이 필요하다는 거죠.

 

Cracker를 귀찮게 하세요.

 

단번에 복호화를 하지 말고 부분 부분 하여 그걸 또 XOR 하고 Decrypt 된 Page에 또 Decoding 작업을 하고

 

또 이미지를 한번에 출력하는게 아니라 수십 조각으로 나눠서 임의의 순서로 출력을 한다던지 하는 것이 필요하다는 겁니다.

 

뷰어에 Anti debugging 이라던가 상용 Packer 등을 적용시킨다던가 하는 작업 역시 추가되면 더 좋겠죠.

 

암호화하는 알고리즘을 백방 강화 시켜봐야 헛수고라는걸 아셔야해요. [ 물론 그렇다고 해서 Base64 뭐 이런걸로 Encoding 하는건

 

문제가 있습니다;;  적용한 암호가 뚫려버리는건 그만큼 더 문제가 있겠죠 ]

 

이 부분은 구현을 하기 나름이니

 

 

또 하나 문제는 업체 하나가 뷰어를 복잡하게 바꿔놓아도

 

다른 업체가 그대로면 유출되겠군요.

 

책을 한 도서 업체만 판매하지는 않을테니까요.

 

좀 더 표준화된 기술이 공통적으로 적용되어야 할 것 같습니다

 

 

 

 

E-book이 보급화가 된다면 추후 이 문제가 불거질 수 있겠습니다만

 

아직은 좀 조용한 모양이네요.

 

하지만 불법 스캔보다 훨씬 쉽고 모든 파일에 적용가능까지 한 이상

 

9시 뉴스 타는것도 시간문제가 아닐까요?

 

...

 

ePub 파일이 암호화 되었다고 , 자신이 사용하는 뷰어는 전용뷰어라고 안심하지 마세요.

 

그럼 반년 안에 다시 포스팅 할 수 있길 기원하며 이만 패킷을 쏩니다 ㅎㅅㅎ

 

 

 

 

 

 

 

 

Posted by LinkC

2011.12.24 13:49 System

[+]Introduction


아주 간만에 포스팅입니다.

1,2주 안하다보니 한달이 되고 두달이 되고..

 

<Fig0. 하라는 공부는 안하고!>

좀 더 심도있는 내용을 올리고 싶었는데 그게 또 핑계거리가 되서 블로그에 글을 안쓰고 있네요.

그래서 간단한 내용이라도 올리고자 합니다.

Global Hooking 을 거는 손쉬운 방법으로는 SetWindowHookEx가 있죠.

Windows 에서 자동으로 Injection을 시켜주기 떄문에 Process의 생성을 catch 해서 따로 Injection 해줄필요도 없구요.

이 부분에 관해서는 Reversecore님 Blog에 아주 자세히 설명되어있기 떄문에 참조하시길 바랍니다.

제가 이번에 쓸 내용은 SetWindowsHookEX를 이용해서 Hooking 을 걸고 UnHookWindowHookEx를 이용하여 해제했는데도 

박혀있는 DLL 을 강제로 Ejection 시키는 방법입니다.

[ 추후 UnHookWindowsHookEx를 이용하지 않고 Hooking을 해제하는 방법도 올리도록 하겠습니다 :D 

Windows7 에 올라와서 물리 메모리에 접근하는게 좀 까다로워져서 고생중이네요. Driver 없이 User 모드에서 가능한지를 살펴보고 있습니다

XP는 되는데 음.. ]



[+]Problem



UnHookWindowsEx만 호출한 경우 대부분의 Process에서는 DLL이 Ejection 되지 않습니다.

[ 물론 해제가 되는 Process도 있습니다. Process 내부에서 Message 처리를 열심히 하는 녀석들이죠.

대부분 UI 가 사용자에게 보여지고 있는 상태의 녀석들이구요. ]

보통 UnHook 후에 SendMessage 를 Broadcasting 하게 뿌려서 Process에 해제하게 되죠.

이 Message는 의미있는 Message 일 필요는 없습니다. 

Message가 오면 Hook Chain을 알아서 갱신하니까요.

아무튼 이렇게 Message 를 뿌려줘도 DLL이 빠지지 않는 Process가 존재하게 됩니다.

대표적으로 AdobeARM.exe Chrome의 Rundll32.exe가 있죠.

물론 항상 빠지지 않는건 아니고 간혹 빠지지 않는 현상을 보게 됩니다.

이런 Process들은 대부분 단일 Thread라는 점을 확인할 수 있는데요.

정리하자면

1. UnHook할 때는 Message를 뿌려서 받은 Process들은 해제가 된다.

2. UnHook 되지 않는 녀석들은 대부분 단일 Thread이다.

3. 위 Process 들도 항상 DLL이 Ejection 안되는건 아니다.

이 부분에서 문제점을 유추할 수 있습니다. 

Process에 외부에서 들어온 Message를 처리할 Thread가 없으면 DLL이 Ejection 되지 않는다.

라는 점입니다.



[+]Solution


그렇다면 위 문제는 어떻게 해결해야 할까요?

많은 분들이 FreeLibrary를 CreateRemoteThread를 이용해서 삽입하는 방법을 생각하셨을겁니다.

흠, 하지만 이 방법에는 문제점이 있는데

FreeLibrary시에 해당 DLL에 접근하고 있는 Thread가 있으면 그대로 프로그램이 뻗어버린다는 것이죠.

DLL Unload 뭐 이런 Error가 났던걸로 기억합니다.

결국 DLL이 자동으로 Ejection 되게 하려면 Message를 처리하도록 만들어야한다는거죠.

Message 처리 루틴 Thread를 Process에 삽입하고 다시 Message를 보내볼까요?

너무 번거롭습니다.

생각해보면 Process 자체에서 Ejection 해주는게 아님을 파악할 수 있습니다.

빈 Message를 받았을 때 Hook Chain에 없는 DLL을 빼주는게 Process 자체 역할을 아니니까요.

Process는 단순히 Message를 받는 것이고 이 때 발생한 특정 Event를 Windows에서 받고 Ejection 해준다고 판단 내릴 수 있겠군요.

그렇다면 직접 Message를 발생시키면 어떨까요?

Code Injection을 통해서 DLL이 빠지지 않는 Process에서 Message를 발생하도록 하는거죠.

아래 Code Inejction Code는 Reversecore님의 Code를 상당부분 인용했습니다.

http://www.reversecore.com/82 

먼저 사용할 함수를 정의합니다.




다음은 실행코드입니다.

함수 호출에 필요한 String을 먼저 삽입하고 그곳을 참조하는 방법입니다.



SendMessage를 쓰기 보다 SendMssageTimeOut을 썼고

Parameter 간소화를 위해 Broadcasting을 합니다.

위와 같은 방법을 이용하면 DLL이 정상적으로 잘 Ejection되는 것을 확인하실 수 있을겁니다.

어때요 참 쉽죠?


글이 올라온 날이 12월 24일이라는 건 신경안쓰셔도 됩니다








Posted by LinkC

2011.05.18 16:31 System

[+] Introduction


 Pydbg. 요즘들어 주목 받고 있는 Script 언어 중 하나인 Python의 Debugging Module 입니다.

Python 언어 자체가 심플하고 이해하기 쉽기 때문에 이를 이용하나 Pydbg도 상당히 접근하기 용이합니다.

물론 Python의 고질적인 문제인 속도는 안고 가야 할 문제입니다만..

이번 포스팅에서는 Pydbg의 Snapshot 기능이 가지고 있는 문제점에 대해서 써볼까 합니다.

Snapshot 기능에 대해 간단히 설명하자면 말그대로 특정 지점의 정보를 Snapshot 찍듯이 찍고

Restore를 통해 찍은 시점으로 돌아가는 거라고 보시면 되겠네요.

예를 들어서 금요일 저녁에 Snapshot을 찍어놓고 

일요일 저녁에 저장해뒀던 Snapshot으로 Restore 하는거죠.

...


<Fig0. 울지마라>

상당히 유용한 기능입니다.

특정 루틴을 반복하는데 좋겠죠? 

아무튼 해당 기능을 사용하는데 약간 문제가 있는데요,

첫번째는 Pydbg File 자체를 수정하지 않고 일어나는 문제점을 해결 하는 방법이고

두번째는 Pydbg File 자체를 수정하는 방법입니다.

간단하기로는 후자가 간단합니다. 단 두글자만 수정하면 끝나요.

포스팅은 전자에 중점을 두고 기술하도록 하겠습니다.




[+] Problem


snapshot의 사용방법은 간단합니다.

pydbg의 객체의 process_snapshot() method를 호출해주면 되죠

복구는 process_restore() 입니다.

그리고 해당 method를 호출해주기 전에

모든 thread를 멈추고 snapshot해야 한다고 pydbg의 제작자 pedram amini 가 명시하고 있습니다

그러니까 이런 식으로 해야겠죠.

SnapShot

dbg.suspend_all_threads()

dbg.process_snapshot()

dbg.resume_all_threads()


Restore 

dbg.suspend_all_threads()

dbg.process_restore()

dbg.resume_all_threads()



예제를 통해 문제를 살펴보죠.

간단한 문자열을 출력하는 다음과 같은 코드가 있습니다.

여기서는 puts를 이용하였으나, printf 문도 동일한 문제가 일어납니다.


*해당 문제는 VS2010의 msvcr100.dll 에서는 발생하지 않습니다만

Windows의 기본 C- Runtime Libary인 msvcrt.dll 을 썼을때는 해당 문제가 발생합니다.

확인해보면  msvcr100.dll에서는 별도의 예외처리가 들어갑니다. 

해당 예외 원인은 뒤에서 설명하도록 하죠.




<Fig1.  예제 프로그램>

Friday nigth에 snapshot 을 찍고

Sunday night 에 restore를 해보면

정상적으로 작동하지 않는걸 확인해볼 수 있습니다.

<Fig2. 정상적으로 출력되지 않고 종료된 모습>
 
나머지도 출력이 되지 않는걸로 봐선 Handling 되지 않는 예외가 발생하여 프로그램이

죽었다고 보면 되겠죠.

발생하는 예외의 Call Stack을 확인해보면

EnterCriticalSection 이후에 발생하는 것을 볼 수 있습니다.

예외가 나는 경우를 확인해보면 항상 같은 곳에서 발생하지는 않습니다만

EnterCriticalSection 함수에 진입하고 나서 발생하는것은 변함이 없습니다.

EnterCriticalSection?

동기화를 위해 사용되는 방법중 임계영역[  Critical Section ] 을 이용하는데 사용되는 함수입니다.

단일 Thread 프로그램인데 무슨 동기화냐 하시는분이 계실지도 모르겠는데

기본적인 Console 출력 함수들은 모두 동기화 작업을 거칩니다. 



왜 이런 문제가 발생할까요?


[+] Analysis


예외 원인을 보면 Access Violation이 주로 일어납니다.

일단 Snapshot method가 호출되었을 때 저장되는 내용을 한번 살펴보겠습니다.


<Fig3. 각 Thread의 Context를 get_thread_context를 통해 저장한 모습>

Context에는 어떤 내용이 저장되는고 하니

<Fig4. WinNT.h에 있는 CONTEXT Structure의 구조>
 

해당 함수에서는 CPU Register를 저장합니다. 

이후 메모리를 돌며 쓰기가 불가능한 곳과 실행파일 이미지를 제외한 영역을 저장합니다.


 <Fig5. 쓰기 가능한 메모리 영역을 저장하는 부분>

 바로 이곳이 문제입니다.

 stack 값이나 Register 영역 값은 모두 정상적으로 복구되는데 실행 파일 이미지에 저장되는 변수는 그대로 남아있는 것입니다.

 즉, data 영역에 저장되는 전역변수가 문제가 될 수 있다는 거죠.

Critical Section의 구조를 살펴봅시다.

<Fig6. Critical Section 구조체의 모습>

첫번째 member를 보면  _RTL_CRITICAL_SECTION_DEBUG 이라는 Linked List 형태의 구조체를 가리키고 있는

포인터 임을 확인 할 수 있습니다.

자 그렇다면 정리해봅시다.

전역변수로 지정된 Critical Section 구조체는 Restore 되어도 변하지 않습니다.

그대로 남아있다는 소리죠.

그런데 해당 구조체가 가리키고 있는 _RTL_CRITICAL_SECTION_DEBUG 구조체는 

Restore 되면 Snapshot 될 때의 상태로 돌아가게 됩니다.

즉 , InitializeCriticalSection이 호출되기 전 상태로 돌아간다는 말입니다.

여기서 문제가 일어납니다.

전역 변수를 참조해보았을때 , 이미 Initialize 된 Critical Section 이 있는 것을 확인됩니다.

이를 사용했더니 실제로는 Initialize 되지 않는 Critical Section 이라는 거죠.

그 포인터가 가리키는 쓰레기 값을 가지고 연산을 했으니 Error가 나는게 당연했겠죠?

여기서 프로그램마다 메모리 값이 다르니 예외가 발생하는 곳도 달랐을 겁니다.

정리하자면, 해당 변수는 정상적으로 Restore 되지 않았는데 가리키는 영역은 Restore 되었다는 거죠.

물론 EnterCritialSection 안에서 나는건 공통적입니다만..

위 사항은 Console 출력 함수에서 적용되는 문제입니다.

Image 영역에 있는 메모리에 있는 변수에 접근하는 모든 것이 문제가 될 수 있습니다.

예를 들면 File Pointer 연산이 있겠죠




 [+] Solution  

 
1.  Snapshot을 찍을때 Image 영역까지 합니다.
 
가장 심플하고 간단하죠.

모든 전역변수도 정상적으로 변경이 되구요

Pedram Amini가 왜 Image 영역을 막아뒀는지는 모르겠습니다만

pydbg를 보면 필요하면 해제하라고 명시되어있습니다.

흠.. 다른 문제가 생길 수 있을지는 좀 더 봐야 할거 같네요.


2. 해당 변수의 snapshot 상태로 직접 돌려준다.

Console 출력 함수들의 경우 해당 Critical Section 영역을 0으로 덮어버리면 알아서 다시 할당하기 때문에

문제가 일어나지 않습니다.

File Pointer의 경우 현재 위치를 가리키고 있는 포인터를 원하는 위치로 돌려주는 식으로 우회가 가능하겠습니다.

좀 번거롭죠. 사용하는 함수마다 이렇게 해 줘야 하는 불편함이 있구요.



3. Image 영역에 쓰는 변수에 접근하지 않는다.

.... 

네 피하면 되는겁니다.

핵심적인 부분만 Snapshot , Restore 합니다. 

지역변수 연산만 한다면 이 방법이 먹히겠죠.

어떠한 수정도 없지만 그만큼 한계가 있는 방식입니다.



<Fig7. 이게 꿈이라고 말하지 말아주세요>

 


Posted by LinkC
이전버튼 1 2 3 이전버튼

블로그 이미지
LinkC

태그목록

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

공지사항

Yesterday73
Today51
Total320,224

달력

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

최근에 받은 트랙백

글 보관함


. .