리버스엔지니어링 문제 20

2015. 4. 13. 10:54Security ★ Development/Reversing

반응형

http://codeengn.com/challenges/basic/20


프로그램을 실행하면 별다른 동작을 하지 않습니다.  키 파일이 필요하다고 하고 crackme3.key라는 이름의 파일을 요구하는 것 같으니 만들어주고 디버깅해봅니다.

00401188위치에서 AL이 1이면 크랙 성공 메시지를 띄우도록 되어있습니다.

AL을 1로 바꾸면 메시지창이 뜹니다.  

저 이상한 영어가 나온 부분은 CodeEngn으로 바꿔야합니다.


시작 부분부터 천천히 보면 CreateFileA, ReadFile부분이 있습니다.  crackme3.key라는 파일을 열고 ReadFile을 하는데 4021A0위치의 값을 12와 비교하고 있습니다.  해당 위치는 pBytesRead부분이고 12는 10진수로 18을 의미합니다.  읽어들인 길이가 18인지 아닌지를 검사하고 있습니다.  같지 않다면 00401037로 점프하게 되고 Uncracked메시지를 볼 수 있습니다.  그대로 계속 진행하면 Cracked by: 다음에 아무 문자열도 뜨지 않습니다.

0040109F위치에서도 같은 곳으로 점프하게 되는데 점프 한 후 Uncracked메시지가 뜨는 것을 보면 이 범위 내에서 크랙의 성공여부가 갈린다고 볼 수 있습니다.

* crackme3.key의 데이터 길이는 18자리이어야합니다.

CALL 00401311에서 해주는 일이 무엇인지 보겠습니다.  해당 CALL을 지나고 EBP, ESP의 문자열이 ESI에서 변경되니 볼 필요가 있을 것 같습니다.

함수를 호출하기 전에 문자열을 스택에 넣습니다.


함수 내부에서는 먼저 ECX, EAX 레지스터를 초기화해줍니다.

00401315 : 문자열을 ESI로 옮겨줍니다.

00401319 : 41 'A'를 BL로 옮겨줍니다.

0040131B : ESI의 첫번째 바이트를 AL로 옮겨줍니다.

0040131D : AL과 BL를 XOR연산해줍니다.  값은 AL에 저장됩니다.

0040131F : AL의 값을 ESI에 다시 넣어줍니다.

ESI를 증가시키고 BL도 증가시켜줍니다.

00401324 : 4020F9의 위치에 EAX(AL)을 더해줍니다.

AL이 0이면 종료.  (값이 없다는 것을 의미합니다.)

BL이 4F이면 종료. (즉, 14번 반복해줍니다.)


즉, 연산결과는 4020F9의 위치에 누적됩니다.


다시 빠져나와서 4020F9위치의 값과 0x12345678을 XOR연산합니다.

0040109F에 점프문이 있는데 여기서 위로 점프할 경우 Uncrack 메시지가 뜨고 아래로 내려갈 경우 Crack이 뜹니다.  점프문 위를 보면 EAX와 4020F9의 값이 같지 않을 때 Uncrack으로 간다는 것을 볼 수 있습니다.

바로 위의 CALL을 보면 파일의 문자열중 끝 4자리를 EAX로 가져옵니다.  결과적으로 이 EAX와 4020F9가 같아야합니다.


즉, 정리하자면

파일입력값 -> CALL호출을 통해 한글자씩 누적 -> 결과값에 0x12345678과 XOR -> 이 값이 파일입력값의 마지막 4자리와 같으면 통과

그런데 마지막 4자리는 파일입력값에 따라 달라지므로 입력값을 정하기 전에는 알 수 없습니다.

마지막에 크랙에 성공했을 때의 부분을 보면 

이런 부분이 있습니다.


위까지는 코드의 흐름을 본 것이고 분석을 하기 위해서는 이제부터가 중요합니다.

00402008을 PUSH하는 부분이 있는데 그부분의 값을 보면 이상한 값이 들어있습니다.  실행을 처음으로 돌려보면 파일입력값이 들어가 있는 것을 볼 수있고 이상한 값은 크랙 성공시 출력되는 메시지입니다.  파일입력값이 이상한 값으로 변경되고 메시지에 출력되는 것으로 볼 때 이상한 값은 CodeEngn이 되어야하고 입력값을 그에 맞춰줘야한다고 볼 수 있습니다.  입력값은 CALL을 통해 4020F9에 누적이 되며 그와 별도로 해당 위치의 메모리를 바꿉니다.  즉! CALL(00401311)에서 입력값을 A~의 값을 통해 xor해준 결과가 메시지의 값이 됩니다.  이 값이 CodeEngn이 되어야 하므로 역연산을 해줍니다.  C^A, o^B... 그럼 값은 02 2d 27 21 0 28 20 26이 나옵니다.  그리고 이값의 누적결과를 0x12345678과 xor해주면 1234557b라는 값이 나옵니다.  그런데 xor한 누적값은 CodeEngn까지만 입력한 값이므로 이 이상의 연산은 되면 안됩니다.  14번 반복인데 8번만 해야하므로 마지막 9번째는 'I', 49를 넣어주어야 합니다.  그 뒤의 값은 무엇이 되도 상관없습니다.  그럼 나온 값을 파일로 만들어야 하는데 hex값을 메모장에 쓸 수는 없기 때문에 hex editor로 직접 넣어줍니다.

마지막 1234557b를 그냥 순서대로 넣으면 안되는데 왜냐하면 EAX의 값과 endian이 다릅니다.  바꿔서 넣어줍니다.

아래는 성공한 hex값과 크랙성공메시지, 메모장의 값입니다.