Easy_CrackMe

 

Reversing.kr의 첫번째 문제입니다.

파일을 다운 받아 실행하면 다음과 같은 창이 뜹니다.



 

값을 입력해서 맞지 않으면 다음과 같은 창이 뜹니다.



 

이 문제는 Password를 찾는 문제가 될듯 합니다.

 

OllydbgEasy_CrackMe를 열도록 하겠습니다.

 

Excutable modulesEasy_CrackMeEntry Point가 적혀 있네요.

Easy_CrackMeEntry Point0x00401188라고 적혀 있습니다.

 

이곳으로 이동하겠습니다.

Easy_CrackMe.text 섹션에 들어온듯 합니다.

 

우리가 하고자 하는 것은 password를 찾는 것입니다.

입력값이 password가 맞는지 검증을 통해 값이 맞다면 맞다는 출력을,

값이 틀리다면 값이 틀리다는 출력을 하겠죠.

위에서 보았듯이 값이 틀릴때는 “Incorrect Password”가 출력이 됩니다.

 

그럼 Incorrect Password 문자열 출력 전후로 해서 password를 비교하는 부분이 있을겁니다.

 

그럼 먼저 Incorrect Password를 찾아보도록 하겠습니다.

Text strings referencedIncorrect Password가 있네요.

저기로 이동해보도록 하겠습니다.

 

0x00401135부분이 Incorrect Password라는 MessageBox를 띄우는 부분으로 보입니다.

이 부분은 0x004010B5, 0x004010CD, 0x0040110B, 0x00401112에서 Jump되는데요.

즉 네부분에서 조건을 검사하고 그것이 맞지 않다면 이부분으로 넘어 오는 것으로 보입니다.

 

그럼 각 부분에 중단점을 걸고 프로그램을 실행하여 값을 입력해보겠습니다.

중단점에서 멈췄습니다.

이 윗부분에서 조건을 검사하고 조건이 맞지 않기 때문에 메시지 박스 쪽으로 넘어 가게 되겠죠.

 

이 윗부분을 확인해보도록 하겠습니다.

이 부분이 첫번째 조건 검사부분 입니다.

 

트레이스 하면서 동작을 하나씩 분석하도록 하겠습니다.

이쪽 루틴에 들어와 메모리에 공간을 100byte확보하여 줍니다.

그리고 ECX 0x18을 넣고, EAX의 값을 0으로 바꿔 줍니다.

 

그리고 0x00401094에서 스택에 0x64를 넣어주고, 0x00401096의 코드를 통해 EDI부터 EDI+24byte까지를 0으로 초기화 해줍니다.

 

그리고 0x004010AA에서 GetDlgItemText을 호출하여 입력한 값을 Buffer(0x0019F9E8)에 읽어옵니다.

https://msdn.microsoft.com/ko-kr/library/windows/desktop/ms645489(v=vs.85).aspx

 

그리고 읽어온 값의 두번째 글자(입력값: ABCDEFGHIJKLMNOP)a인지 확인 합니다.

 

만약 입력한 값의 두번째 글자가 a가 아니라면 Incorrect Password메시지 출력부로 이동하게 됩니다.

 

입력값의 두번째 글자를 a로 바꾸고 진행하면 두번째 조건 검사부로 넘어가게 됩니다.

 

두번째 조건 검사부 입니다.

스택에 25y라는 문장이 들어있는 주소와 입력값의 세번째 글자가 들어있는 주소를 스택에 넣고 함수를 하나 호출합니다.

 

호출된 함수의 내부는 다음과 같습니다.

 

0x00401156에서 ECX2를 넣고 바로 아래에서 ECX0인지 검사해서 분기를 나눕니다. 0x00401181에서 MOV EAX, ECX하는 것으로 보아 ECX0이면 함수를 종료하는듯 합니다.

 

그리고 EBX2를 넣고, EDIESI에 입력한 문자열의 세번째 글자의 주소를 넣어줍니다.

그리고 EAX0으로 만들어 주고 REPNE SCAS BYTE PTR ES:[EDI]를 수행합니다.

REPNE : 같지 않을 때까지 반복 수행

SCAS BYTE PTR ES:[EDI] : 1ByteEDI의 값과 AX의 값을 비교

즉 같지 않을 때까지 EDI1Byte씩 늘려가며 AX와 값을 비교 진행 합니다.

 

그리고 NEG ECX를 통해 ECX의 부호를 반전시키고 EBX와 값을 더해줍니다.

그리고 EDI에 세번째 입력 글자의 메모리 주소를 넣고, ESI5y의 주소를 넣고 다시 비교합니다.

REPE CMPS BYTE PTR ES:[EDI], BYTE PTR DS:[ESI]이므로 ESIEDI의 값이 같을 때까지 반복 진행합니다.

그리고 AL5y5를 집어넣고, EDI-1과 비교합니다. 이렇게 입력값의 세번째 글자와 5와 비교하게 됩니다.

그리고 AL값이 EDI-1보다 크다면 0x0040117F, 값이 같다면 0x00401181로 이동하게 됩니다.

 

0x0040117F에서는 ECX에 보수를 취하고 0x00401181에서는 ECX의 값은 EAX에 넣어줍니다. 그리고 레지스터의 값을 복구하고 함수를 리턴해 줍니다.

 

현재 넣어준 값은 잘못된 값이므로 EAX1이 들어가고 RETN하게 됩니다.

 

그리고 EAX의 값이 0이 아니라면 다시 Incorrect Password로 넘어가게 됩니다.

 

그럼 5y와 값을 비교한다는 것을 알았으므로 다시 입력값을 수정하여 두번째 조건 검사부로 이동하겠습니다.

사용자 입력값의 세번째 글자와 5y를 비교하는 부분입니다.


0x0040116F에서 5를 비교하고 0x00401176에서 y를 비교합니다.

값이 같으므로 0x0040117B의 코드를 통해 0x00401181로 가서 EAX0을 전달하고 리턴하게 됩니다.

 

EAX의 값이 0이므로 세번째 조건 검사부로 이동하게 됩니다.

 

ESI“R3versing”의 주소값을 넣어주고, EAX에 입력값의 4번째 글자의 주소를 넣어줍니다.

그리고 거기서 한글자씩 뽑아서 비교를 하여 값이 다르다면 0x00401102로 이동합니다.

 

그리고 캐리 플래그를 포함하여 EAX에서 EAX값을 뺍니다.

그리고 EAX의 값이 0아니라면 Incorrect Password로 이동합니다.

그럼 R3versing과 비교한다는 것을 알았으므로 이를 넣어 다시 실행하도록 하겠습니다.

 

R3versing과 사용자 입력값의 세번째부터의 글자가 동일하다면 사용자 입력값의 해당 글자가 NULL인지 확인합니다.

즉 문자열의 끝인지 확인하는 것이죠, 문자열의 끝에 도달했다면 0x004010FE로 이동합니다.


그렇게 두번 검사를 진행하고 다시 0x004010DA로 이동하여 반복합니다.

 

만약 글자가 더 많다면 위의 그림처럼 되어 EAX1이 남고 다시 Incorrect Password 출력부로 이동하게 됩니다.

 

입력값을 다시 맞게 수정하여 실행하도록 하겠습니다.

정상적으로 코드를 빠져나와 XOR EAX,EAX연산을 통해 EAX0으로 만들어 줄것으로 보입니다. 그리고 JMP를 통해 SBB EAX,EAXSBB EAX,-1을 건너 뜁니다.

 

그리고 사용자 입력값의 첫번째 글자의 값이 0x45(E)인지 검사합니다.

현재 첫번째 글자의 값이 A이므로 Incorrect Password부분으로 이동하겠네요.


그럼 다시 입력값을 수정하여 실행하도록 하겠습니다.

성공적으로 문제를 해결하였습니다.

올바른 패스워드는 Ea5yReversing이었습니다.

너무 세세하게 적었나 내용이 길어졌네요

+ Recent posts