Self-Improvement

x64dbg(x64dbg, x32dbg) Easy_CrackMe 풀이 분석 본문

리버싱 기초

x64dbg(x64dbg, x32dbg) Easy_CrackMe 풀이 분석

JoGeun 2020. 5. 6. 18:13

http://reversing.kr/challenge.php 에서 Easy_CrackMe.exe를 다운받아 준다.

 

해당 프로그램을 실행하면 입력할 수 있는 메시지 박스와 입력 값이 패스워드와 같지 않다면 "Incorrect Password" 메시지 창이 뜨게 된다. 이 점으로 볼때 패스워드를 찾아야 한다는 것을 알 수 있다.

 

프로그램을 x32dbg로 열어준다. EIP는 00401188주소에서 시작하며 친절하게 EntryPoint라고 되어있다.

 

2가지 접근법이 존재한다.

1. 프로그램을 실행했을 때 메시지 박스가 뜬것을 감안하여 F8로 하나씩 실행하면서 메시지 박스를 호출하는 곳을 찾아내고 패스워드를 비교하는 곳도 찾아내어 분석한다.

 

2. 패스워드가 올바르지 않다고 메시지가 뜬 문자열을 찾은 후 해당 문자열을 호출한 곳 주변을 분석한다.

 

위 2가지 중에 첫 번째는 시간이 많이 소유되어 2번째로 진행을 해준다.

 

문자열을 검색하기 위해 [오른쪽 마우스 - 다음을 찾기 - 모든 모듈 - 문자열 참조]하여 "Incorrect Password"를 찾아준다.

 

해당 문자열을 호출하는 주소 0040113C로 접근해 준다. 

 

문자열을 호출하는 함수 및 모듈의 시작과 끝을 알기 위해 [오른쪽 마우스 - 분석 - 모듈 분석]한 뒤 모듈의 첫 시작부분에 BP(브레이크 포인트)을 설정해 준다.

 

이제 F9를 눌러서 BP가 설정된 부분까지 진행을 해주면 처음에 봤던 메시지 박스가 나오게 된다.

 

메시지 박스에 123456789를 입력한 후 F8로 진행을 해준다.

처음과 끝 스택의 흐름을 제외한 중요한 어셈블리어 부터 분석을 해본다.

 

esp+70의 값 esp+8 주소, 3E8(10진수로 1000)을 인자로 하여 GetDlgItemText 함수를 호출하고 있다.

GetDlgItemText 함수을 보았을때 esp+8엔 위에 입력한 "123456789"을 받게되며 1000은 버퍼의 크기를 나타내고 있는것으로 보인다.

(esp+70은 무엇일까요.. hDlg?)

 

GetDlgItemText 함수 호출이 종료된 뒤 "cmp esp+5,61"로 esp+5에는 "32"가 들어있으며 32(10진수 2) 와 61(10진수 a)을 비교하는 구문이다. 

동일하지 않을 시 jne로 인해 401135 주소로 이동하게 되며 "incorrect Password" 문자열로 출력이 이루어진다.

 

즉, 두번째 문자열은 "a"이어야 한다.

다시 재실행하여 "1a3456789"로 입력하여 이어서 한다.

 

jne의 바로 아래 "push 2"로 2를 스택에 넣어주며 "lea ecx, esp+A"로 esp+A의 주소를 ecx에 할당해준다.

esp+A의 데이터에는 "3456789" 값이 있다. 

이어서 "push 406078"로 "5y" 문자열과 ecx를 인자로 하여 sub_401150 함수를 호출하고 있다.

sub_401150 함수는 따로 분석하지  않으며 요약하면 세번째, 네번째 자리의 값을 "5y" 와 비교하는 함수이다.

 

다시 재실행하여 "1a5y56789"로 입력하여 이어서 한다.

이어서 위의 sub_401150 함수에서 "5y"를 비굑하고 나오면 "test eax,eax"로 eax가 0인지 비교하게 되며 0이 아닐시에는 401135주소 즉 "incorrect Password" 문자열로 끝나게 된다.

 

sub_401150에서 "5y" 비교하여 현재는 eax가 0으로 되어 다음라인으로 계속 진행된다.

"mov esi, 40606c"로 "R3versing" 문자열이 esi에 할당된다.

"lea eax, esp+10"으로 esp+10에는 입력했던 "56789" 문자열의 주소를 eax에 할당된다.

"mov dl, eax" 는 eax의 1바이트 즉 하나의 문자열 "5"를 dl에 할당한다.

"mov bl, esi" 는 esi의 1바이트 즉 하나의 문자열 "R"를 bl에 할당한다.

"mov cl, dl" dl의 값 "5"를 cl에 할당한다

"cmp dl, bl" dl의 값 "5"와 bl의 값 "R"을 비교한다.

같지 않다면 401102로 이동하며 결국은 "incorrect Password" 문자열이 출력되고 종료된다.

 

만약 같아서 다음 행으로 진행되면 "test c1,c1"으로 c1이 0인지 확인한다. (입력한 문자열이 없을 경우를 확인하는 구문)

"mov dl, eax+1"으로 eax의 값 "56789"에서 "6"을 dl에 할당해주는 것이다.

"mov bl, esi+1"으로 esi의 값 "R3versing"에서 "3"을 bl에 할당해주는 것이다.

그 다음 역시나 둘을 비교하여 같지 않다면 401102 주소로 이동하여 "incorrect Password"로 진행되고 값이 닽다면 eax, esi에 2를 더하여 앞에 비교했던 "56"과 "R3"값을 제외한 나머지 문자열 부터 시작하게 되고 "test c1,c1"으로 입력한 값에서 다음 문자열이 존재하는지도 확인하게 된다.

즉 eax는 "789"값을 가지게 되고 esi는 "versing"을 가지게 된다. 그 다음 4010DA 주소로 이동한 후 맨 처음 둘을 비교한 구문부터 다시 시작하게 되는 반복문이다.

 

즉 재실행하여 "1a5yR3versing"입력한 후 진행해준다.

 

계속 이어서 다음 행으로 진행한다.

"xor eax,eax"로 eax을 0으로 만들어준다.

"jmp 401107"로 401107 주소로 이동한다.

 

"test eax,eax"로 eax가 0인지 확인하며 위에 xor 연산으로 인해 0이 되어있음으로 401135(incorrect Password)로 이동하지 않는다.

"cmp esp+4, 45"를 진행하게 되며 esp+4의 값을 확인하면 "1"이며 이를 45(10진수 E)와 비교하고 있다. 

같지 않을시엔 401135(incorrect Password)로 이동한다.

 

esp+4의 값 "1"이 어디서 왔는지 잘 생각해보면 처음 GetDlgItemText 함수 호출이 끝나고 esp+5인 입력한 값의 2번째 값과 "a"를 비교했던것이 있다.

 

이를 통해 esp+4는 입력한 값 "1a5yR3versing" 중 첫 번째 값인 "1"을 나타내는 것이다.

이 값이 "E"와 같으면 이어서 "Congratulation !!" 문자열과 함께 메시지 박스가 나오는 것을 알 수 있다.

 

즉, 다시 재실행하여 "Ea5yR3versing"으로 시작하면 "Congratulation !!" 메시지 박스가 출력되며 해결이 된다.

 

잘못된 점이나 단어 등 지적해주시면 감사하겠습니다.