'codegate'에 해당되는 글 3건

  1. 2011.07.16 Codegate 2011 Bin 500 풀이 [ VM ] (1)
  2. 2010.06.21 [ CodeGate 2010 ] Challenge 7 풀이 (2)
  3. 2010.02.03 Code Gate 2009 본선 문제 stego_win 풀이

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

2010.06.21 18:47 WarGame

http://www.vnsecurity.net/2010/03/codegate-2010-challenge7-weak-ssl-cracking/


*이 풀이는 위 두 사이트에서 참조하여 정리하였음을 알려드립니다 




문제의 패킷을 열어보면 , 192.168.100.2 와 192.168.100.4 간의 SSL 통신이 있었음을 알 수 있습니다

패킷의 상세 정보를 보면 RSA 로 암호화 되어 있는 것을 볼 수 있죠

RSA는 대표적인 공개키 알고리즘으로 공개키와 개인키가 모두 있어야만 받은 데이터를 해석 할 수 있습니다



RSA에도 여러 버전이 있는데, 그 버전을 알아야 풀이가 가능하겠죠

지난 번에 포스팅 했던 글에서 공개키의 생성 부분을 잠시 다시 살펴보겠습니다
 
[+] 키의 생성

  1. p \,와 q \, 라고 하는 두 개의 서로 다른 (p \ne q소수를 고른다.
  2. 두 수를 곱하여 N = p q \, 을 찾는다.
  3. \varphi(N) = (p-1)(q-1) \, 를 구한다.
  4. \varphi(N) 보단 작고, \varphi(N)와 서로 소인 정수 를 찾는다.
  5. 유클리드 호제법을 이용하여 d e \equiv 1 \pmod{\varphi(N)} 을 만족시키는 를 구한다.

A의 공개키는 위에서 구한 두 개의 숫자로 이루어진 <Ne>이고, 개인키는 이다. A는 <Ne>만을 B에게 공개하고, B는 이 공개키를 사용하여 자신의 메시지를 암호화하게 된다. 여기서 와 의 보안은 매우 중요하다. 이를 가지고 와 의 계산이 가능하기 때문이다. 그리하여 공개키와 개인키가 생성이 된 후에는 이 두 숫자를 지워버리는 것이 안전하다.



p와 q의 보안은 매우 중요하다고 하였으나

상당 수의 RSA는 p와 q 값이 공개된 상태입니다. 물론 자의적으로 공개한건 아니고

타의적으로 공개되었겠죠 :D



아무튼, p와 q 값을 알기 위해서는 N 값을 알아내서 버전에 맞는 RSA 를 찾아내야 합니다

혹은 패킷에서 추출한 파일을 openssl 로 분석하는 방법이 있겠는데요

Python 코드를 통해 추출하도록 하겠습니다



도출한 N과 e 값을 통해서 p,q 값을 찾습니다

RSA-768 이군요

p , q 값에 확장된 유클리드 호제법을 적용합니다

값이 음수로 나오지만 조건

 d e \equiv 1 \pmod{\varphi(N)} 는 만족하는 것을 확인 하실수 있습니다

이를 통해서, ,개인키 정보를 담은 파일을 만들수 있는데요


이 개인키 파일을 이용해서 ssl 이 적용된 패킷의 정보를 복호화할 수 있습니다



WireShark 를 이용해서 복호화 시켜보면..



쨘-

공개키 구조를 사용한다고 무조건 안전한게 아니군요

하긴 n 값에서 p, q 값을 찾아내리라고 생각지도 못했을 것 같은데 말이죠

이렇게 값이 밝혀진 것을 factor 되었다고 표현하더라구요

RSA 768 같은 경우는 2009년 12월에 factor 되었고..

현재 뚫리지 않은 것 역시 언젠가는 factor 되겠죠

정말이지 보안 분야는 창과 방패의 끝없는 대결같군요 :D

'WarGame' 카테고리의 다른 글

[ CodeGate 2010 ] Challlenge 15 풀이  (0) 2010.07.06
[ CodeGate 2010 ] Challenge 8  (0) 2010.06.22
[ CodeGate 2010 ] Challenge 7 풀이  (2) 2010.06.21
[ Python Challenge ] level 15  (0) 2010.06.08
[ CodeEnge Malware Analysis ] level 8  (0) 2010.05.30
[ CodeEnge Malware Analysis ] level7  (0) 2010.05.30
Posted by LinkC

2010.02.03 00:57 WarGame

먼저 문제는 http://mins4416.tistory.com/

beist lab 오시리스님의 블로그에 올라와있습니다

문제를 보면

out.bmp 와 stego_win.exe 가 있군요

일단 stego_win.exe를 실행시키면

파일 이름을 입력하라고 나옵니다

파일 이름을 올바르게 입력하면 hidden string을 입력하라고 나오는데

다음과 같이 아무렇게나 입력해보면



out.bmp에 결과가 저장되었다고 합니다

out.bmp를 열어보면 아무 변화도 없는것 같지만

hex editor로 두 파일을 열어보면

결과 파일과 처음 지정한 파일이 특정 부분이 1비트씩 달라져있음을 볼 수 있습니다




처음에 보면 굉장히 무질서 하게 달라진것 같은데

분명 어떤 규칙을 가지고 이렇게 바뀌었을 것입죠

그럼 이제 코드를 살펴봅시다

hidden string을 받고 나서

잡다한 준비 과정을 거치고 나면

파일에 기록하는 부분이 나오는군요



위압적인 길이로군요

일단 Hey ray로 뽑아봅시다



소스코드 만만치 않군요 -,.-

소스코드 뒤로 가면 & 연산  | 연산 >> 연산 등이 나오는걸 볼 수 있습니다

bit 연산이 이뤄지는거 같군요 

디버거로 차근차근 진행하면서 소스코드와 비교해봅시다

먼저 처음에 코드를 따라가며 실행한 부분만 보겠습니다



입력한 string의 첫번째 bit 값을 가지고 3번 돕니다

그다음 실행되는

SHR 명령어에 의해서 EDI 값이 오른쪽으로 shift 되고

즉 10000000 에서 01000000 이 되죠

여기서 다시 and 값으로 확인 후 반복문 실행

한 bit 또 shift 하고 and

이런식으로 하다가 and 값이 1이 되는 경우가 있다면

파일에 1씩 더해서 기록합니다



예를 들어 봅시다

hidden string으로 아스키 코드 값이 31인 숫자 '1'을 넣었다고 하면

2진수로 00110001 가 됩니다

가장 안쪽의 반복문은 한 bit당 무조건 3번씩 실행되니까

한 문자당 총 24 ( 8*3 ) 번 반복문을 돌겠군요

0일 경우는 그대로, 1일 경우는 1을 더해서 파일에 기록합니다

그렇다면 파일에는

0 0 0 0 0 0 1 1 1 1 1 1 0 0 0 0
0 0 0 0 0 1 1 1

이런식으로 기록됩니다

이를 쉽게 알아보는 방법으론

헤더를 제외하고 모조리 0으로 채운 bmp 파일을 대상 파일로 지정해주면 되겠죠

한번 맞는지 확인해봅시다




header가 맨 처음에 포함되는걸 감안하면 결과가 생각한대로 나온거 같군요

다만 여기서 주의할 점은 코드값이 0 일때와 짝수, 홀수 일때 각각 다르게 적용된다는 것입니다

먼저 BMP 파일 내용은 모조리 짝수 인걸 눈여겨 봅시다

헤더를 제외한 BMP 파일의 내용중 홀수는 문자열에 의해서 바뀌었다는 것을 보실수 있습니다

0이면 +1을 더해주고 비트가 1이면서 짝수면 하나 빼줍니다

비트가 0이면서 홀수 인경우는 하나 빼줘야 하구요

이를  소스로 짜보면



정도로 생각해볼수 있겠습니다

아직 python 에 익숙하지 않아서 좀 삽질좀 했습니다만.. 아무튼

일단 이 소스는 입력한 문자열 뒤에 BMP 내용은 손대지 않았으니

전에 입력했던 내용이 고스란히 남습니다

하지만 정답을 추출해내는데는 별 상관 없으니 이쯤 하고

거꾸로 파일에서 문자열을 추출해보도록 합시다

24바이트가 한 문자임을 고려하면 추출하는건 훨씬 간단합니다





이렇게 코드를 짜고 돌려보면 쨘~

어때요  참, 쉽죠?






너무 삽질을 많이해서 저런말은 못하겠네요 -,.-

아무튼 좋은 문제 내주신 beist lab 여러분 감사합니다 :D

'WarGame' 카테고리의 다른 글

Vortex level2 풀이  (0) 2010.02.16
Vortex level1 풀이  (0) 2010.02.10
Vortex level0 풀이  (0) 2010.02.04
Code Gate 2009 본선 문제 stego_win 풀이  (0) 2010.02.03
Crackme#15  (0) 2010.01.08
CrackMe#14  (0) 2010.01.06
Posted by LinkC
이전버튼 1 이전버튼

블로그 이미지
LinkC

태그목록

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

공지사항

Yesterday73
Today48
Total320,221

달력

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

최근에 받은 트랙백

글 보관함


. .