• [Reversing.kr] 6_ImagePrc

    2020. 2. 5.

    by. ugonfor

    그림그리는 문제였다....

    난 왜 이런문제를 한참동안 생각한걸까

     

     

    문제는 그림을 그려서 Check을 하면, 맞는 지 여부가 나오는 문제였다.

     

    한참동안은 문제에서 correct같은 문자가 나올거라 생각을 했는 데, string을 보아도 아무것도 없어서 MessageBox를 출력하기 전쯤을 유심히 살펴보았다. 다음은 MessageBox를 출력하는 것이 있는 부분이 있는 Main함수의 수도코드이다.

    int __stdcall main_(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
    {
      HDC v4; // eax
      int result; // eax
      HGDIOBJ v6; // eax
      HDC v7; // esi
      void *Prc; // esi
      HRSRC src; // eax
      HGLOBAL src_; // eax
      _BYTE *Resource; // eax
      int count; // edi
      _BYTE *Prc_; // ecx
      int v14; // eax
      char pv[4]; // [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);
              output_inf = CreateCompatibleDC(v7);
              h = SelectObject(output_inf, hbm);
              Rectangle(output_inf, -5, -5, 205, 205);
              ReleaseDC(hWnd, v7);
              ::wParam = (WPARAM)CreateFontA(12, 0, 0, 0, 400, 0, 0, 0, 0x81u, 0, 0, 0, 0x12u, "Georgia");
              Button = (int)CreateWindowExA(
                              0,
                              "Button",
                              "Check",
                              0x50000000u,
                              60,
                              85,
                              80,
                              28,
                              hWnd,
                              (HMENU)0x64,
                              hInstance,
                              0);
              SendMessageA((HWND)Button, 0x30u, ::wParam, 0);
              return 0;
            case 2u:
              v6 = SelectObject(output_inf, h);
              DeleteObject(v6);
              DeleteDC(output_inf);
              PostQuitMessage(0);
              return 0;
            case 0xFu:
              v4 = BeginPaint(hWnd, (LPPAINTSTRUCT)bmi.bmiColors);
              BitBlt(v4, 0, 0, 200, 150, output_inf, 0, 0, 0xCC0020u);
              EndPaint(hWnd, (const PAINTSTRUCT *)bmi.bmiColors);
              return 0;
          }                                         // making messageBox
          return DefWindowProcA(hWnd, Msg, wParam, lParam);
        }
        if ( wParam == 100 )                        // check
        {
          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(output_inf, (HBITMAP)hbm, 0, cLines, 0, &bmi, 0);
          Prc = operator new(bmi.bmiHeader.biSizeImage);
          GetDIBits(output_inf, (HBITMAP)hbm, 0, cLines, Prc, &bmi, 0);
          src = FindResourceA(0, (LPCSTR)'e', (LPCSTR)24);
          src_ = LoadResource(0, src);
          Resource = LockResource(src_);
          count = 0;
          Prc_ = Prc;
          v14 = Resource - (_BYTE *)Prc;
          while ( *Prc_ == Prc_[v14] )
          {
            ++count;
            ++Prc_;
            if ( count >= 0x15F90 )
            {
              reset(Prc);
              return 0;
            }
          }
          MessageBoxA(hWnd, "Wrong", "ImagePrc", 0x30u);
          reset(Prc);
          return 0;
        }
        return 0;
      }
      switch ( Msg )
      {
        case 0x200u:
          if ( dword_47D7F8 )
          {
            MoveToEx(output_inf, x, y, 0);
            LineTo(output_inf, (unsigned __int16)lParam, (unsigned int)lParam >> 16);
            x = (unsigned __int16)lParam;
            y = (unsigned int)lParam >> 16;
            InvalidateRect(hWnd, 0, 0);
          }
          return 0;
        case 0x201u:
          dword_47D7F8 = 1;
          y = (unsigned int)lParam >> 16;
          x = (unsigned __int16)lParam;
          result = 0;
          break;
        case 0x202u:
          dword_47D7F8 = 0;
          result = 0;
          break;
        default:
          return DefWindowProcA(hWnd, Msg, wParam, lParam);
      }
      return result;
    }

    여기서 주목해야하는 점은... wrong 위쪽에 있는 bmi.bmiheader부분이다.

    저부분을 못봐서 한참동안 생각했다지 ^^.....

     

    저쯤을 아래에 잘라서 다시 가져왔다.

      if ( wParam == 100 )                        // check
        {
          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(output_inf, (HBITMAP)hbm, 0, cLines, 0, &bmi, 0);
          Prc = operator new(bmi.bmiHeader.biSizeImage);
          GetDIBits(output_inf, (HBITMAP)hbm, 0, cLines, Prc, &bmi, 0);
          src = FindResourceA(0, (LPCSTR)'e', (LPCSTR)24);
          src_ = LoadResource(0, src);
          Resource = LockResource(src_);
          count = 0;
          Prc_ = Prc;
          v14 = Resource - (_BYTE *)Prc;
          while ( *Prc_ == Prc_[v14] )
          {
            ++count;
            ++Prc_;
            if ( count >= 0x15F90 )
            {
              reset(Prc);
              return 0;
            }
          }
          MessageBoxA(hWnd, "Wrong", "ImagePrc", 0x30u);

    위에 보면, bmi.bmiheader가 있고, FindResourceA로 리소스를 받아서, 저장하고, while문에서 내가 입력해준 값이랑 리소스랑 비교하는 부분이 있다!!!! 그리고 틀리면 wrong을 출력하는 것이죠....

     

    하....

    리소스가 있구나...

    그래서 리소스해커로 열어보았다... 진작열어볼껄...

    정말 무언가가 있더라... bmiheader를 검색해보니까 bmp파일의 헤더라더라. 그래서 확인해보니 FF는 흰색이고 00은 검은색의 데이터였다.

     

    그러면, 저값이 데이터니까 HxD로 열어서 bmp파일의 파일헤더랑 이미지헤더만 잘 조작해주면 된다.

    그 부분은 다음블로그를 참고했다.

     

     

    [BITMAP]비트맵 데이터 파일 구조

    http://www.fortunecity.com/skyscraper/windows/364/bmpffrmt.html Bimap 데이터 파일 기본 구조 File Header 파일 헤더의 구성은 BITMAPFILEHEADER 라는 구조체에 정의 되어 있고 아래 표와 같은 구조를 지닌다...

    jae02.tistory.com

     

    저위에 FF부분빼고 저 만~큼 헤더를 잘 적절히 조정해줬다. 참고로 수도코드에 보면 헤더에 대한 값들이 적혀있으니, 디버깅할때 브포걸어서 거기있는 값들 잘 가져와야 한다 ㅇㅇ...

     

    그렇게 했더니 다음처럼 나왔지롱

    GOT

    FLAG는 GOT

    ㅠ ㅠ

     

    쉬운문젠데 오래걸려서 화난다

    'Writeup > Wargame_Writeup' 카테고리의 다른 글

    [Flare-on 2019] Wopr  (0) 2020.02.05
    [Reversing.kr] 11_Easy ELF  (0) 2020.02.05
    [Reversing.kr] 5_Replace.exe  (0) 2020.02.04
    HackCTF j0n9hyun's secret  (0) 2020.01.23
    HackCTF Unexploitable #2  (0) 2020.01.23

    댓글