Search

[reversing.kr] ImagePrc

Tags
reversing
Category
reversing.kr
Last edited time
2022/01/07 12:50
Visibility
Public

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; }
C++
복사
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
Bash
복사
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; .....
Bash
복사
가로 200, 세로 150인 것을 알수 있고 정답이미지는 24bit bmp 파일인 것을 알수있다.
따라서 200X150 bmp 파일을 만들고 리소스로 아까 복사한것을 넣어서 bmp를 만들면된다.
42 4D : 시그니처
C6 5F 01 00 : 파일 전체 사이즈
00 00 : 예약 필드
00 00
36 00 00 00 : 실제 리소스 오프셋

4. 몰랐던 개념

CreateCompatibleBitmap
CreateCompatibleDC