블로그 이전했습니다. https://jeongzero.oopy.io/
[CodeEngine] Basic RCE L18
본문 바로가기
워게임/CodeEngn

[CodeEngine] Basic RCE L18

728x90

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:

...

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:

...

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);

이렇게 나오는데 그냥 어셈으로 보는게 더 편하다

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

4. 몰랐던 개념


728x90

'워게임 > CodeEngn' 카테고리의 다른 글

[CodeEngine] Basic RCE L20  (0) 2021.01.18
[CodeEngine] Basic RCE L19  (0) 2021.01.13
[CodeEngine] Basic RCE L17  (0) 2021.01.11
[CodeEngine] Basic RCE L16  (0) 2021.01.04
[CodeEngine] Basic RCE L14  (0) 2021.01.02