reversing의 기초를 다지고자 Lena tutorial이라는 reversing 문제들을 풀어봤습니다.
우선 1,2번 문제의 목표는 다음과 같습니다.
해당 문제는 다음과 같이 구성 되어있습니다.
이 중에서 reverseMe.exe라는 실행 파일을 crack하는게 1번 문제의 목적입니다. 문제 이름과 마찬가지로 Ollydebug라는 프로그램과 assebler에 익숙해지고 reverseMe.exe를 패치하면 됩니다.
olly로 프로그램을 확인해보면 다음과 같은 assembly 코드가 보입니다.
한줄씩 실행을 시켜보면 다음과 같은 분기점이 나옵니다. 해당 분기점에서 jnz에 의해 eax와 -1이 다르면 jump를 하게 됩니다.
eax는 CreateFileA를 실행한 결과 값의 return 값을 가지고 있고 CreateFileA는 인자로 0x00402079(FileName: "Keyfile.dat"), C0000000, 3, 0, 3을 가집니다. 이때 마지막인자인 3에 의해 "Keyfile.dat"과 일치하는 파일이 있다면 그 파일을 여는 작업을 수행합니다. 만약 파일이 존재하지 않거나 파일을 여는데 실패한다면 -1을 반환하고 성공적으로 작업을 마치면 다른 값을 반환합니다. 즉, 이 파일은 KEY 파일이 존재하지 않아 위에서 본것과 같은
"Evaluation period out of date. Purchase new license"
라는 문구를 출력하게 됩니다. 이를 우회하는 방법으로는 두 가지가 있습니다.
첫번째는 KEY파일을 만들어주는 것입니다. KEY파일을 복구한다면 큰 작업없이 파일을 정상적으로 실행 할 수 있습니다. 하지만 이 방법은 문제에서 요구하는 방식과는 다른 방식입니다.
두번째는 문제에서 요구하는대로 KEY 파일을 확인하는 루틴을 우회하도록 patch하는 것입니다.
위에 루틴을 우회하고 나오는 코드입니다. 위에서부터 실행되면서 중간중간 아래에 있는
"Keyfile is not valid. Sorry."
라는 MessageBox를 생성하는 것을 알 수 있습니다.
해당 JNZ는 JMP로, JL은 NOP으로 patch하여 우회하면 가장 마지막에 있는
JMP reverseM.00401205라는 부분을 볼 수 있습니다.
이 jmp문을 따라가 보면 다음과 같이 성공했다는 messageBox가 생성되고 프로그램이 종료되는 것을 확인할 수 있습니다.
이렇게 문제 1번을 해결했습니다.
하지만 이렇게 olly에서 patch만 한다면 일회성일 뿐이므로 메모리를 복사하여 저장함으로써 항상 루틴을 우회하는 crack을 만들 수 있습니다.
이렇게 olly의 기능을 사용하여 crack까지 만들면서 1번 문제는 끝났습니다.
2번문제는 다음과 같이 구성되어 있으며 1번과 같은 reverseMe.exe를 앞에서 말한 1번째 방법으로 해결해야 합니다. 즉, key 파일을 다시 만들어야 합니다.
코드는 다음과 같고 이제 이 코드에서 key 파일의 정보를 알아내야 합니다.
우선 key 파일의 파일 이름은 쉽게 알아낼 수 있습니다. CreateFile 함수에 첫번째 인자로 들어간 "Keyfile.dat"이 key파일의 이름이 됩니다.
다음으로 Key 파일의 key의 길이와 내용이 메모리에 올라가는 위치는 ReadFile 함수의 인자를 통해 알 수 있습니다.
다음과 같이 pBytesRead는 파일의 길이가 담긴 메모리 주소를, Buffer는 파일의 내용이 담긴 주소를 나타냅니다.
이제 비교문을 확인하여 Key파일을 다시 만들 수 있습니다.
코드를 보면 먼저 ebx, esi를 0으로 초기화한 이후 파일의 길이가 0x10(16)보다 작은지 확인합니다. 그렇기에 key 파일의 길이는 최소 16이여야 합니다.
다음으로 [ebx+40211a] 주소에 저장된 값을 가져와 0과 비교를 합니다. 이는 파일의 내용을 ebx를 증가시키며 한글자씩 읽어와 비교하는 것입니다. 즉, string의 index를 1씩 증가시키며 비교하는 반복문을 나타냅니다.
이때 string의 글자가 0과 같으면 cmp esi, 8로 가서 esi가 8보다 작은지를 확인하여 작다면 "Keyfile is not valid. Sorry"라는 messageBox를 생성합니다.
0이 아니라면 47과 같은지 확인하고 같다면 esi와 ebx를 1씩 증가시키고 아니라면 ebx만 1 증가시킵니다. 즉, 이 코드는 정리하자면 0x47과 같은 값이 8번 이상 있으면 정상적인 keyfile이라는 의미가 됩니다.
따라서 0x47은 아스키코드로 G를 나타내므로 G가 최소 8개 있는 16자리 이상의 문자열은 모두 Key가 됩니다.
이제 메모장에 G를 16번 입력하고 Keyfile.dat으로 저장하여 reverseMe.exe와 같은 경로에 두고 실행시키면 2번문제를 해결 할 수 있습니다.