블로그 이전했습니다. https://jeongzero.oopy.io/
[reversing.kr] ImagePrc
본문 바로가기
워게임/reversing.kr

[reversing.kr] ImagePrc

728x90

1. 문제


1) 문제 확인

그림을 그리고 누르면 틀렸다고 한다. 어떤 그림을 맞추는건가 싶다.

2) 코드흐름 파악

int __stdcall sub_401130(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
{
  HDC v4; // eax
  int result; // eax
  HGDIOBJ v6; // eax
  HDC v7; // esi
  void *v8; // esi
  HRSRC v9; // eax
  HGLOBAL v10; // eax
  _BYTE *v11; // eax
  signed int v12; // edi
  _BYTE *v13; // ecx
  int v14; // eax
  char pv; // [esp+8h] [ebp-80h]
  LONG v16; // [esp+Ch] [ebp-7Ch]
  UINT cLines; // [esp+10h] [ebp-78h]
  struct tagBITMAPINFO bmi; // [esp+20h] [ebp-68h]

  if ( Msg <= 0x111 )
  {
    if ( Msg != 0x111 )
    {
      switch ( Msg )
      {
        case 1u:
          v7 = GetDC(hWnd);
          hbm = CreateCompatibleBitmap(v7, 200, 150);
          hdc = CreateCompatibleDC(v7);
          h = SelectObject(hdc, hbm);
          Rectangle(hdc, -5, -5, 205, 205);
          ReleaseDC(hWnd, v7);
			    ....

        case 0xFu:
          v4 = BeginPaint(hWnd, (LPPAINTSTRUCT)bmi.bmiColors);
          BitBlt(v4, 0, 0, 200, 150, hdc, 0, 0, 0xCC0020u);
          EndPaint(hWnd, (const PAINTSTRUCT *)bmi.bmiColors);
          return 0;
      }
      return DefWindowProcA(hWnd, Msg, wParam, lParam);
    }
    if ( wParam == 100 )
    {
      GetObjectA(hbm, 24, &pv);
      memset(&bmi, 0, 0x28u);
      bmi.bmiHeader.biHeight = cLines;
      bmi.bmiHeader.biWidth = v16;
      bmi.bmiHeader.biSize = 40;
      bmi.bmiHeader.biPlanes = 1;
      bmi.bmiHeader.biBitCount = 24;
      bmi.bmiHeader.biCompression = 0;
      GetDIBits(hdc, (HBITMAP)hbm, 0, cLines, 0, &bmi, 0);
      v8 = operator new(bmi.bmiHeader.biSizeImage);
      GetDIBits(hdc, (HBITMAP)hbm, 0, cLines, v8, &bmi, 0);
      v9 = FindResourceA(0, (LPCSTR)0x65, (LPCSTR)0x18);
      v10 = LoadResource(0, v9);
      v11 = LockResource(v10);
      v12 = 0;
      v13 = v8;
      v14 = v11 - (_BYTE *)v8;
      while ( *v13 == v13[v14] )
      {
        ++v12;
        ++v13;
        if ( v12 >= 90000 )
        {
          sub_401500(v8);
          return 0;
        }
      }
      MessageBoxA(hWnd, Text, Caption, 0x30u); //wrong 출력
      sub_401500(v8);
      return 0;
    }
    return 0;
  }
 ...
  return result;
}

wrong 문자열을 타고 가보면 어디서 호출되는지 찾을 수 있다. v13==v13[v14]를 루프를 돌면서 확인하는데, 어셈으로 보면 다음과 같다

.text:004013A3                 mov     dl, [ecx]
.text:004013A5                 mov     bl, [eax+ecx]
.text:004013A8                 cmp     dl, bl
.text:004013AA                 jnz     short loc_4013CD
.text:004013AC                 inc     edi
.text:004013AD                 inc     ecx
.text:004013AE                 cmp     edi, 15F90h
.text:004013B4                 jl      short loc_4013A3
.text:004013B6                 push    esi             ; lpMem
.text:004013B7                 call    sub_401500
.text:004013BC                 add     esp, 4
.text:004013BF                 xor     eax, eax
.text:004013C1                 pop     ebx
.text:004013C2                 pop     edi
.text:004013C3                 pop     esi
.text:004013C4                 add     esp, 80h
.text:004013CA                 retn    10h

ecx와 ecx+eax를 비교하고, edi가 0x15f90인지 비교하는 루프를 돈다. ecx에 어떤값이 들어가는 지 확인하면서 진행하면 될듯싶다.

2. 접근방법


FindResource, LoadResource, LockResource 를 거쳐 esi에 0x4b80048 주소가 저장된다. esi가 곧 ecx에 들어가므로 뭐가 들어있는지 확인해보자

0x4b80048 부터 0x15f90 까지 괴상한 값이 들어가 있다. 이거를 한바이트씩 90000바이트 비교한다. 이는 pe 구조중 리소스 영역에 들어 있는 값이다

3. 풀이


덤프 창에서 shift+C로 0x4b80048 + 90000 까지 복사한다음 bmp 파일로 만들어준다.

또한 비트맵 이미지를 만들때

switch ( Msg )
      {
        case 1u:
          v7 = GetDC(hWnd);
          hbm = CreateCompatibleBitmap(v7, 200, 150);
          hdc = CreateCompatibleDC(v7);
          h = SelectObject(hdc, hbm);
          Rectangle(hdc, -5, -5, 205, 205);
          ReleaseDC(hWnd, v7);
          ::wParam = (WPARAM)CreateFontA(12, 0, 0, 0, 400, 0, 0, 0, 0x81u, 0, 0, 0, 0x12u, pszFaceName);
          dword_4084E0 = (int)CreateWindowExA(
                                0,
                                ClassName,
                                WindowName,
                                0x50000000u,
                                60,

.........

if ( wParam == 100 )
    {
      GetObjectA(hbm, 24, &pv);
      memset(&bmi, 0, 0x28u);
      bmi.bmiHeader.biHeight = cLines;
      bmi.bmiHeader.biWidth = v16;
      bmi.bmiHeader.biSize = 40;
      bmi.bmiHeader.biPlanes = 1;
      bmi.bmiHeader.biBitCount = 24;
      bmi.bmiHeader.biCompression = 0;
      GetDIBits(hdc, (HBITMAP)hbm, 0, cLines, 0, &bmi, 0);
      v8 = operator new(bmi.bmiHeader.biSizeImage);
      GetDIBits(hdc, (HBITMAP)hbm, 0, cLines, v8, &bmi, 0);
      v9 = FindResourceA(0, (LPCSTR)0x65, (LPCSTR)0x18);
      v10 = LoadResource(0, v9);
      v11 = LockResource(v10);
      v12 = 0;

.....

가로 200, 세로 150인 것을 알수 있고 정답이미지는 24bit bmp 파일인 것을 알수있다.

따라서 200X150 bmp 파일을 만들고 리소스로 아까 복사한것을 넣어서 bmp를 만들면된다.

  • 42 4D : 시그니처
  • C6 5F 01 00 : 파일 전체 사이즈
  • 00 00 : 예약 필드
  • 00 00
  • 36 00 00 00 : 실제 리소스 오프셋

4. 몰랐던 개념


  • CreateCompatibleBitmap
  • CreateCompatibleDC
728x90

'워게임 > reversing.kr' 카테고리의 다른 글

[reversing.kr] Direct 3D FPS  (0) 2020.12.21
[reversing.kr] Position  (0) 2020.12.16
[reversing.kr] Replace  (0) 2020.12.14
[reversing.kr] Music Player.exe  (0) 2020.12.11
[reversing.kr] easy elf  (0) 2020.12.10