'WriteUp'에 해당되는 글 4건

  1. 2016.02.01 Crackit2.exe Writeup
  2. 2016.01.15 Crackit2.exe Writeup
  3. 2016.01.14 Crackit2.exe Writeup
  4. 2016.01.11 [예시] Easy Keygen (100pt)
2016. 2. 1. 02:21

Crackit2.exe 의 flag 를 찾는 것이 목표이다.

기본적으로 프로그램을 실행시켜서 아무 값이나 입력하면 다음과 같다.

Ollydbg를 이용하여 이 프로그램을 열고 "All referenced text string" 창을 열면 다음과 같이 "ACCESS DENIED" 와 "ACCESS GRANTED" 를 찾을 수 있다.

"ACCESS GRANTED" 와 ACCESS DENIED" 분기문으로 갈리는 지점을 찾아가면 다음과 같다.

004027A7 에서 EAX 값을 테스트하여 바로 JNZ 를 통해 분기하는 것을 알 수 있다.

004027A7을 실행하기 직전의 레지스터 값을 보면 다음과 같다.

EAX에 FFFFFFFF가 들어있는데, 위의 분기문에서 "ACCESS DENIED"가 있는 부분으로 점프하지 않고 "ACCESS GRANTED"가 있는 부분으로 넘어가기 위해서는 EAX의 값이 0이 되어야 함을 알 수 있다.


이제 다시 프로그램을 처음부터 실행시켜 보자.

빈칸에 아무 값이나 입력하고 코드 부분을 보면 다음과 같은 내용이 나온다.

004022E4에서 PUSH EAX 을 실행하는데, EAX에는 내가 입력한 값이 들어있었다. 따라서 EAX 값을 스택에 저장한 뒤 MSVBVM60.__vbaLenBstr 함수를 호출하여 입력한 값의 길이를 구하게 된다. 그 값은 다시 EAX에 저장되게 된다. 그 후 004022ED에서 CMP EAX,7 을 실행하는데, 이는 그 길이가 7인지 확인하는 부분이다.

그 밑으로 몇줄 내려오면 다음과 같다.

0040230C 에서 JE 명령어가 나오는데, 이는 CMP EAX,7에서 EAX가 7이 아닐 경우 zero flag가 1이 되기 때문에 점프를 실행하게 된다. EAX가 7이면 바로 다음 줄의 명령을 실행하게 된다.

일단 7이 아닌 크기의 문자열을 입력하여 점프를 실행하면 이 글의 첫 부분에서 말했던 분기점 부분으로 바로 넘어가게 된다.

0040279D에서 "yes"라는 값을 스택에 넣고 vbaStrCmp 함수를 호출한다. 그런데, vbaStrCmp는 스택에 있는 두 개의 값을 불러들여 비교하게 되는데, "yes"가 하나 들어있기 때문에 비교하면 EAX에 FFFFFFFF라는 값이 결과값으로 들어가게 된다. 따라서 바로 "ACCESS DENIED" 부분으로 넘어가게 된다. 즉, 이제 나는 7글자의 문자열을 입력한 뒤 그 문자열을 분석하는 코드를 지나면서 스택에 "yes"가 들어갈 수 있게 하면 된다.

이제 문자열 7개를 분석하는 부분에 초점을 맞춘다. 그 중 어떠한 값을 스택에 넣고 vbaStrCmp를 호출한 뒤 점프를 실행하는 부분을 발견할 수 있다.

그 중 최초로 값을 비교하는 부분에서 스택을 확인하면 내가 입력했던 값이 한 글자씩 차례대로 스택에 저장되어 있음을 확인할 수 있다.

즉, 내가 입력했던 글자 하나하나를 비교하여 틀리면 바로 점프를 통해 넘어가는 코드 내용임을 알 수 있다. 따라서 코드에 나와있는 유니코드에 해당하는 글자 7개가 flag임을 알 수 있다. 그런데 flag에서 4번째와 6번째 문자는 char 형으로 저장되고, 나머지는 유니코드로 저장된다. 따라서 비교할 때도 그렇게 비교하게 되는데, 위에 코드에서 유니코드 부분과 char 부분을 구분할 필요가 있다. 따라서 유니코드를 char로 변환하면 flag가 최종적으로 "Ech3l0n" 임을 알 수 있다.


'WriteUp' 카테고리의 다른 글

Crackit2.exe Writeup  (0) 2016.01.15
Crackit2.exe Writeup  (0) 2016.01.14
[예시] Easy Keygen (100pt)  (0) 2016.01.11
Posted by 알 수 없는 사용자
2016. 1. 15. 16:09

버튼 하나만 있는 아주 간단하고 문제의 목적을 알 수 있다. PEiD로 확인해보면 VB프로그램인 것을 알 수 있다.


VB 디컴파일러로 확인해보면 하나밖에 없는 버튼을 클릭했을 때 어느 코드가 실행되는 지 알 수 있다.


디컴파일러에서 확인한 0x402240의 주소를 확인하니 클릭 시 실행되는 게 맞다. 이후에 나오는 코드들은 모두 클릭 후에 실행되는 코드들이다.


처음으로 denied로 점프하는 분기문이 있는 부분이다. 이 곳에서는 __vbaLenBstr함수를 호출하여 입력한 문자열의 길이를 확인한다. 문자열의 길이가 7이 아니면 denied를 출력하는 곳으로 점프한다.


입력한 문자열의 길이가 7인 경우 점프되지 않고 아래의 이 코드들이 실행된다. __vbaObjSet, __vbaHresultCheckObj, rtcMidCharBstr, __vbaStrMove, __vbaStrI2, __vbaFreeStrList, __vbaFreeObj, __vbaFreeVar 함수들이 실행된다.

할당과 해제에 관련된 함수를 제외하고 살펴보자. rtcMidCharBstr 함수는 입력한 문자열에서 한 문자를 가져온다. __vbaStrI2 함수는 문자열을 다른 문자열로 바꿔주는 역할을 한다. 이러한 코드가 총 7개가 있다.

4번째와 6번째에는 __vbaStrI2 함수가 없는 것만 빼면 동일하다.


이 코드들이 실행되면 어떤 값들이 저장되는 지 알아보기 위해 문자열 1234567 을 입력해보았다.

위의 코드와 비슷한 코드 7개들 모두 실행한 후의 스택 영역이다. 스택에는 문자열을 가리키는 포인터들이 저장된다. 중간에 문자열로 표시되지 않는 곳을 따라가보면 아래와 같은 값이 저장되어있다.




스택이 가리키는 문자열은 순서대로 "49", "50", "51", "\x34", "53", "\x36", "55" 이다. 1씩 증가하는 문자열을 입력했고, 스택에서도 1씩 커지는 문자열들을 가리키고 있다. 여기서 __vbaStrI2 함수가 한 문자를 10진수 아스키 코드 문자열로 변환하는 것을 알 수 있다. 4, 6 번째 문자를 처리할 때는 __vbaStrI2 함수가 없기 때문에 문자의 16진수 값이 그대로 저장된다.

char 

10 

16 

49 

31 

50 

32

51 

33 

52 

34 

53 

35 

54 

36 

55 

37 

코드를 실행하면 위의 표와 같이 문자열이 생성되고 각 스택에서 문자열들을 가리킨다.


각 문자를 처리하면 위 사진의 코드가 실행된다. 문자열을 비교하는 __vbaStrCmp 함수가 7번 실행된다. 비교하는 문자열이 다를 경우 denied를 출력하는 곳으로 점프한다. 7번의 __vbaStrCmp에는 순서대로 "69", "99", "104", "\x33", "108", "\x30", "110"의 문자열들이 비교된다.

이 조건을 만족하기 위해서는 아래의 표와 같이 문자열을 구성해야한다.

char 

10 

16 

E

69

45

c

99

63

h

104

68

3

51

33

l

108

6C

0

48

30

n

110

6E 







'WriteUp' 카테고리의 다른 글

Crackit2.exe Writeup  (0) 2016.02.01
Crackit2.exe Writeup  (0) 2016.01.14
[예시] Easy Keygen (100pt)  (0) 2016.01.11
Posted by 지환태
2016. 1. 14. 16:52

이번에 풀 문제는 Crackit2.exe이다.

먼저 기본적으로 실행을 해본다.

 

입력 값을 요구하는 것으로 보아 키 값을 찾아야 하는 문제로 추측된다.

 

대충 아무거나 입력해봤더니 "ACCESS DENIED"가 떴다.

위 문자열은 키 값을 '판단' 한 후 뜨는 문자열이므로 ollydbg에서 위 문자열을 띄우는 루틴을 찾는 다면

키 값을 비교하는 루틴도 찾을 수 있을 것으로 판단된다. 

 



crackit2.exe를 ollydbg에서 실행한다.

 



ollydbg상에서 오른쪽 클릭 -> Search for -> all referenced text strings 를 클릭한다. 예상대로 문자열 목록을 보면

"ACCESS DENIED"가 존재한다. 또한 "ACCESS GRANTED"가 있는 것으로 보아 키값 비교 성공시 ACESS GRANTED가 뜰것으로 예상된다.

 

 referenced string 창에서 ACCESS DENIED를 더블클릭하면 위 사진처럼 "ACCESS DENIED"의 위치가 나온다.

comment 부분을 살펴보면 위쪽에 ACESS GRANTED가 있음을 알 수 있다.

ACCESS GRANTED 메세지가 push되고 함수가 호출되어야 키값이 맞다는 뜻인데, 004027A9를 보면 ACESS GRANTED 문자열이 있는 부분을 건너뛰고 ACCESS DENIED가 있는 쪽으로 JUMP하는 명령이 있다. 이 부분의 조건이 키값을 바르게 입력했는지 여부를 나타낸다. 4027A9 분기점은 EAX 값이 결정하고 이 값은 4027A2의 CALL EDI에서 결정된다. 

 



CALL EDI 부분에 브레이크포인트를 걸고 확인해보니 vbaStrCmp 함수를 호출함을 알 수 있다. 비교하는 문자열은 "yes"인데, 스택을 확인해보니 또다른 비교 문자열이 비어있다. 402781의 "yes" 문자열이 스택에 넣어지지 못했음을 의미한다. 

 



 하여 402781 주소의 "yes"가 어디서 건너뛰어졌는지를 찾아보면 402793으로 점프 되는 곳이 있음이 보인다. 이를 따라가본다.



40230c 주소에서 JUMP가 이루어졌음을 알 수 있다. 어떤 조건으로 점프되었는지를 살펴보면 상단에 vbaLenBstr 함수가 있는데, 이는 문자열의 길이를 나타내는 함수이다. 그리고 그 밑에 CMP 명령으로 7과 비교하는 부분이 있다. 즉, 입력하는 문자열의 길이가 7이 되어야 함을 알 수 있다.

 



길이가 7이 되어야 함을 알아냈으므로, 밑으로 내리다 보면 핵심 루틴이 보인다. 바로 문자열을 한캐릭터씩 비교하는 부분이다. 유니코드로 친절하게 69,99,104,108,110이 제공되어있다. 허나 이는 5자리 뿐이다. 자세히 보면 comment에는 보이지 않지만 104와 108 사이, 108과 110 사이에도 비교하는 값들이 있음을 알 수 있다. 이 값들은 디버깅을 통해 파악하도록 한다. 앞 세글자인 69,99,104는 아스키 코드 상에서 E,c,h이다.

 



 위 처럼 브레이크 포인트를 건다. 파라미터로 00401CD0를 넣음을 알 수 있다. 헥스 덤프 창에서 ctrl+g 버튼을 눌러 해당 주소로 가본다.

4010CD0에는 값 33이 들어있음을 알 수 있다.

 

같은 방식으로 6번째 문자는 0이 들어있음을 알 수 있다.

 

그리하여 위 아스키 값들을 문자로 변환하면 키값은 Ech3l0n이다

 

 



clear

'WriteUp' 카테고리의 다른 글

Crackit2.exe Writeup  (0) 2016.02.01
Crackit2.exe Writeup  (0) 2016.01.15
[예시] Easy Keygen (100pt)  (0) 2016.01.11
Posted by 키흐
2016. 1. 11. 11:53

  이번에 풀 문제는 Easy Keygen이라는 문제이다.


문제를 클릭하여 압축 파일을 받으면 압축 파일 안에는 ReadMe.txt와 문제 바이너리 파일이 함께 있다.


ReadMe.txt를 읽어보면 시리얼이 5B134977135E7D13 인 이름을 찾으라는 말이 나와있다. 이 이름이 이 문제의 flag 임을 알 수 있다.


   그리고 문제 바이너리는 .exe 파일임을 확인하고 실행시켜보면 이름을 입력하라고 나오고 이름을 입력하면 시리얼을 입력하라고 나오는데 시리얼은 뭔지 모르므로 아무 값이나 입력하면 틀렸다고 나오고 프로그램은 종료된다.


   해당 바이너리를 OllyDbg로 열고 앞선 문제풀이에서 했듯이 이 프로그램에 속한 문자열을 살펴보면 다음과 같다.



   위의 문자열들을 보고 프로그램이 어떤 방식으로 돌아갈 것인지 상상해보면 다음과 같다.

   우선 프로그램은 이름에 따라 다른 시리얼을 생성하는 것 같다.

   프로그램은 이름을 입력 받은 후에 그 이름에 알맞은 시리얼을 생성한다.

   그리고 우리가 입력하는 시리얼을 받아서 프로그램이 생성한 시리얼과 비교한다.

   비교 결과, 같으면 Correct! 라는 문자열을, 다르면 Wrong 이라는 문자열을 출력한 후 종료된다.


   따라서 우리는 우선, Name을 기반으로 시리얼을 만드는 방법을 알아낸 후에 그 방법을 거꾸로 적용하여 시리얼이 5B134977135E7D13인 이름을 찾아야 한다. Name을 기반으로 시리얼을 만드는 부분은 우선 우리가 Name을 입력한 후에 있을 것이므로 이름을 입력하는 부분으로 가서 살펴보기로한다. 그 부분은 다음과 같다.



   이름을 입력하라는 글자를 화면에 띄운 뒤, scanf로 우리의 입력을 받아들이는 모습이다. 이 뒤에 우리가 입력한 문자열을 이용해서 시리얼을 만드는 곳이 있다. 그 부분은 다음과 같다.



   위의 어셈블리를 디버깅하며 해석해보면 다음과 같은 일을 한다.

1. 입력한 Name의 길이를 구한다.

2. Name의 길이만큼 루프를 돈다.

3. 루프를 돌때마다 0x10, 0x20, 0x30 과 차례대로 번갈아가며 Name의 문자들과 하나씩 xor한다.

4. xor한 결과들을 저장한다. 그 것이 시리얼이다.


   따라서 우리는 위의 방법을 거꾸로 진행하면 문제를 풀 수 있다.

xor은 다시 xor하면 원래 값이 나오므로, 주어진 시리얼 5B134977135E7D13 을 두 글자를 한 16진수 숫자로 생각하여 0x10, 0x20, 0x30과 차례대로 번갈아가며 xor 해주면 그 결과가 이번 문제의 답이다.


   필자는 이를 스크립트를 이용해 해결했으며, 이 문제에 사용된 스크립트는 다음과 같다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#-*- coding: utf-8 -*-
__author__ = 'mojo'
 
Name = ""
Serial = "5B134977135E7D13"
key = [0x100x200x30]
 
j=0
for i in range(len(Serial)/2) :
    if(j==len(key)):
        j = 0
    serial_piece = Serial[2*i:2*(i+1)]
    tmp_name = int(serial_piece,16)^key[j]
    Name += chr(tmp_name)
    j+=1
 
print Name
cs


   그 결과 나오는 이름이 Flag 다.


'WriteUp' 카테고리의 다른 글

Crackit2.exe Writeup  (0) 2016.02.01
Crackit2.exe Writeup  (0) 2016.01.15
Crackit2.exe Writeup  (0) 2016.01.14
Posted by 알 수 없는 사용자