'Themida'에 해당되는 글 2건

  1. 2013.01.03 By-passing the parts of themida's anti-reversing (1)
  2. 2011.07.16 Codegate 2011 Bin 500 풀이 [ VM ] (1)

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

2011.07.16 21:45 WarGame

[+] Introduction

 


 이번에 소개할 문제는 VM 관련 문제 입니다.

VM을 이용한 기술은 VCP [ Virtualized Code Protection ] 이 있으며 해당 기술은 Protector 에 많이 쓰이곤 합니다.

언뜻 봐도 " Code를 Virtualize 하여 Protect 한다 " 라는것을 의미한다는거라고 쉽게 추측 할 수 있죠.

상용 Packer 인 Themida에 실제로 쓰이고 있는 기술이기도 하구요.

물론 Themida에는 VCP 뿐만 아니라 여러가지 Anti Reversing 기술들이 들어가있습니다만..

 이 포스팅에서는 VM만을 다루도록 하겠습니다.

 * VM이 적용되면 Reversing 하는 입장에서는 상당히 귀찮아집니다.

뒤에서 설명하겠지만 Assembly Language 로 한줄씩 실행되기 떄문에 

전체적인 구조를 살펴보려면 Script를 짜거나 손으로 직접 모아야 하기 떄문이죠.

디버거로 열어봤는데...


<Fig 0. VM이 딱 ! >


 <Fig0-1. 5초후에 빡침이 딱!>



[+] Problem


<Fig1. Bin500을 실행 시켰을 때 >

 

먼저 Debugger로 문자열을 확인해보면

key File로 짐작되는 문자열 'codegate.key' 를 찾을 수 있습니다.

적당히 아무내용이나 집어넣어서 재실행 시켜보면

역시 유효하지 않은 파일이라고 하는군요.

<Fig2. 해당 파일이 올바르지 않을 때 메세지> 

이런 류의 문제라면 해당 Key 파일을 검사하는 부분을 우회해도 

암호가 나오지 않고 그 파일을 가지고 연산을 하기 떄문에

해당 파일의 내용을 정확히 복구를 해야 합니다.

 파일을 열어 Verify 하는 부분을 찾으려 해도 도통 보이지 않는군요.

이 문제의 핵심인 Verify 부분이 VM에 의해 실행되기 때문이죠.


[+] Analysis

 
그렇다면 Debugger로 확인을 해봅시다. 

<Fig3. VirtualAlloc을 통해 특정 메모리 영역을 할당받는 모습>

 해당 영역을 확인해보면 아시겠지만

애초에 VM 영역에서 시작하네요.

후에 VirtualAlloc 을 호출하고 특정 영역에  RWE 권한을 모두 줍니다.

계속 따라가보면 VirtualAlloc을 한번 더 호출하고 .. [ 같은 크기, 다른 위치에 RWE 권한을 줍니다 ] 

이 할당한 영역에 특정 명령어를 수행하는 것을 확인 할 수 있습니다.

<Fig4. VirtualAlloc에 할당된 영역에서 코드를 실행하고 있는 모습>
 
그 후에 다시 0x40ABBD로 Return해서 특정 루틴을 반복합니다.


<Fig5. Code를 가져와 Decrypt하는 부분>

0x0040A94A를 호출함으로써 실행할 Code를 복호화 하는데

해당 함수를 살펴보면 다음과 같습니다.


<Fig6. Fig5의 Decrypt함수 내부>

 

사실 위 함수가 문제를 푸는데 큰 도움이 되는 건 아닙니다.

CPU가 해석 할 수 있는 일반 기계어로 복호화 하는 과정이지

Key 파일의 내용을 확인하는 과정이 아니기 떄문이죠.

하지만 VM의 동작 방식은 확인을 하고 갑시다.

대략적인 VM의 구현은 다음과 같습니다.

<Fig7. VM의 동작 방식>

실제 문제 파일을 Debugging 해보면 아시겠지만

text 영역과 VM 영역이 번갈아 가며 실행되는 것을 볼 수 있습니다.

Sensitive 한 곳은 VM 처리가 되어있는거죠.



즉 우리가 원하는 것은 ' Codegate.key 파일을 입력 받고 난 후 실패 메세지가 나오기 전까지의 연산 과정 ' 입니다.

이것은 1Byte 씩 검사하여 다르면 바로 실패로 return 하는 과정일수도 있고

전체 내용을 모두 검사한 후 최종적으로 실패를 판단할 수도 있습니다.

물론 전자가 훨씬 까다로워집니다. 실행중에 비교 값을 바꿔야하니까요.

ReadFile에 BP를 걸고 해당 파일을 읽어 온 후에 Buffer에 접근 하는 부분을 잡아보면

최종 Code가 실행되는 곳을 잡을 수 있습니다.

이곳을 보면 Fig4에서 할당한 곳과는 다른 공간임을 알 수 있습니다.

즉, 복호화된 Code가 실행 되는 부분은 2군데이며 

1. 일반 적인 Code가 실행되는 부분

2. Key 파일의 내용을 검사하는 부분


이 되겠습니다.

두 부분을 모두 BP 걸고 확인해보면 아시겠지만 Call , JMP 문을 찾아 볼 수 없다는걸 알 수 있습니다.

Call이나 JMP문이 가고자 하는 곳은 VM에서는 외부 , 즉 원본 프로그램의 text 영역입니다.

이 부분으로 가려면 해당 주소에 맞는 연산이 또 별도로 필요하죠.

문제 풀이엔 별로 중요한 내용이 아닙니다만,

'VM은 이런식으로 구현되고 있다' 라는 것은 염두해두시는게 좋습니다.



[+] Solution



이 다음부턴 딱히 설명 드릴게 없습니다.

Script를 짜거나 손으로 직접 코드를 바꾸시면서 진행을 하셔야 합니다.

운이 나쁘게도 앞서 설명드린 1Byte 씩 검사하고 아닐 경우 실패로 간주하는 타입이군요.

Script로 모으기 짜증 + 1  이 되었습니다.

아무튼 해당 Code를 모으면 다음과 같은 모습입니다.

Pydbg의 HardWare BP를 이용한건데 가변길이라 그런지 

다음 명령어까지 받아오더군요.. 쩝..


<Fig8. Xor, Cmp 부분 중 일부를 긁어온 모습>

이 부분을 예로 들자면

al 로 가져온 값을 xor 0x46 하고 이 값을 cmp 합니다.

xor  [ Data  ] , 0x46

cmp ( [ Data ] ^ 0x 46 )  , 0xf0

즉 Data 의 값은 0x46 과 Xor를 했을 때 0xF0 가 나오는 0xB6 이 되겠네요.

이런 식으로 Codegate.key 값을 하나씩 복원합니다.

Codegate key 값이 총 100 Byte 니 벼..별거 아니군요.

Xor 부분과 cmp 부분을 parsing 매 Byte마다 바꿔주면

다음과 같은 원본 데이터를 얻을 수 있습니다.

<Fig9. 원본 Key File >

이를 codegate.key 에 저장하면 


<Fig10. 해독된 Key File>

이게 정답은 아니겠죠?

100Byte의 16진수가 뭘 의미 할까요.

흠 분포도를 보면 문자를 의미하는건 아닌거 같습니다.

그리고 저 출력 방식도 의심해볼만 하죠

4 * 25 형식입니다.

또, 0x80 0x00 이 유독 눈에 많이 띄는걸 볼 수 있는데..

일단 이를 binary 값으로 바꿔보았습니다.


<Fig11. Binary 값으로 바꾼 모습>



<Fig11-1. !?>
왜 4 * 25 형식으로 출력했는지 알겠네요.

0x80이 binary 값으로 1000 0000 이니까

뒤의 0을 떼버리면 25 * 25 형식의 값이 완성됩니다.

여기에 모서리 부분을 보면 1과 0이 규칙적으로 나열되어있는데

전 이걸 QR 코드라고 판단했고 이를 만들어보면..



QR Code Reader로 읽어보니

I_am_in_C0d3gat3_2011!!

이라는 답이 나오는군요.















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

블로그 이미지
LinkC

태그목록

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

공지사항

Yesterday57
Today61
Total309,989

달력

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

최근에 받은 트랙백

글 보관함


. .