Search

[CodeEngine] Basic RCE L18

Tags
reversing
Category
CodeEngn
Last Edited time
2022/01/07 12:50
Visibility
Public

1. 문제

CodeEngn 이름의 키 값을 찾으면 된다
패킹은 따로 안되어있는것 같다

2. 접근방법

키젠 하는 부분을 찾고, 코드로 포팅해서 풀어도 되고 생성된 키 값이랑 입력한 키 값이랑 비교하는 부분을 찾는 방법도 있다.
... dword_408CF0 = GetDlgItemTextA(hWnd, 1001, String, 512);// return Name size v9 = GetDlgItemTextA(hWnd, (int)aXspD3rRedCrew, byte_4086F0, 512); sub_403F80((int)byte_4086F0, v9); // v9=0 sub_404058((unsigned int *)String, byte_4088F0); v10 = sub_404820(byte_4088F0, dword_408CF0, byte_408AF0); v11 = 0x524544; LOBYTE(v11) = *((_BYTE *)sub_404768 + (_DWORD)v10); wsprintfA( key_gen, "%.8X%.8X", 0x407AF0 * (v11 + LOBYTE(byte_4088F0[0])) + v11, 0x407AF0 * (v11 + LOBYTE(byte_4088F0[0])) - 5796720); wsprintfA((LPSTR)byte_4088F0, "%.8X%.8X", dword_407AF0[1] ^ dword_407AF0[0], v12); GetDlgItemTextA(hWnd, 1004, serial, 512); if ( !lstrcmpiA(serial, key_gen) ) return MessageBoxA(hWnd, "Your serial is correct\r\n now you know what 2 do :p", aG0od, 0x40u); MessageBoxA(hWnd, Text, Caption, 0x10u); break; case 0x3EA: ...
C
복사
strcmp로 입력한 serial과 생성된 key를 비교한다. 사실 저 key_gen 이 정답이다. 너무 쉬우니까 어떻게 키젠을 하는지 추가로 확인해보자

3. 풀이

... dword_408CF0 = GetDlgItemTextA(hWnd, 1001, String, 512);// return Name size v9 = GetDlgItemTextA(hWnd, (int)aXspD3rRedCrew, byte_4086F0, 512); sub_403F80((int)byte_4086F0, v9); // v9=0 sub_404058((unsigned int *)String, byte_4088F0); v10 = sub_404820(byte_4088F0, dword_408CF0, byte_408AF0); v11 = 0x524544; LOBYTE(v11) = *((_BYTE *)sub_404768 + (_DWORD)v10); wsprintfA( key_gen, "%.8X%.8X", 0x407AF0 * (v11 + LOBYTE(byte_4088F0[0])) + v11, 0x407AF0 * (v11 + LOBYTE(byte_4088F0[0])) - 5796720); wsprintfA((LPSTR)byte_4088F0, "%.8X%.8X", dword_407AF0[1] ^ dword_407AF0[0], v12); GetDlgItemTextA(hWnd, 1004, serial, 512); if ( !lstrcmpiA(serial, key_gen) ) return MessageBoxA(hWnd, "Your serial is correct\r\n now you know what 2 do :p", aG0od, 0x40u); MessageBoxA(hWnd, Text, Caption, 0x10u); break; case 0x3EA: ...
C
복사
key_gen 변수는 wsprintfA를 이용하여 생성한다. 총16바이트 사이즈이며 공백은 0으로 채운다.
상위 8바이트는 v11, byte_4088F0 변수를 이용하여 계산하게 되는데 저 두 변수가 어떠한 값을 같는지만 확인해보면 키젠을 쉽게 이해할 수 있다.
우선 byte_4088F0 은 총 2번 이용되는데 처음 sub_404058 함수에서 어떠한 값이 들어가는지 확인해보자. 처음에는 널 값으로 채워져 있던 공간이
해당 함수가 호출되고 나면 8바이트의 값이 써진다. 이는 해당 함수 내부에서 xor 연산들이 계산된 결과이다
그다음 sub_404820 함수에서 byte_4088F0 이 어떻게 쓰이는지 봐보자
값의 변화가 없다. 따라서 byte_4088F0 는 최종적으로 위 8바이트 값이다.
이제 v11이 뭔지 확인해보자.
v11 = 0x524544; LOBYTE(v11) = *((_BYTE *)sub_404768 + (_DWORD)v10);
C
복사
이렇게 나오는데 그냥 어셈으로 보는게 더 편하다
ecx는 0이여서 eax는 결국 아까 그 8바이트 중 첫바이트값인 0xCD가 들어간다.
그다음 [ebx+404768] 에 들어있는 한바이트를 dl 로 복사한다. 여기서 ebx는 0x10이다
마지막으로 eax와 edx를 더한다. 이 값이 바로 v11이다.
키젠은 이제 v11byte_4088F0 를 이용해서 간단한 연산으로 생성된다
.text:0040117F imul eax, 407AF0h .text:00401185 add edx, eax .text:00401187 sub eax, 587370h
Bash
복사

4. 몰랐던 개념