그래픽 문제를 많이 접해보지는 못해서 좀 힘들긴 했다. 저 가리는 모션을 패치하자.
int __stdcall WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
{
HCURSOR v6; // rax
HWND v7; // rax
HWND v8; // rbx
HACCEL v9; // rbx
WNDCLASSEXW v11; // [rsp+60h] [rbp-A8h] BYREF
struct tagMSG Msg; // [rsp+B0h] [rbp-58h] BYREF
LoadStringW(hInstance, 0x67u, WindowName, 100);
LoadStringW(hInstance, 0x6Du, ClassName, 100);
v11.cbSize = 80;
v11.style = 3;
v11.lpfnWndProc = (WNDPROC)sub_1400032F0;
*(_QWORD *)&v11.cbClsExtra = 0i64;
v11.hInstance = hInstance;
v11.hIcon = LoadIconW(hInstance, (LPCWSTR)0x6B);
v6 = LoadCursorW(0i64, (LPCWSTR)0x7F00);
*(__m128i *)&v11.hbrBackground = _mm_load_si128((const __m128i *)&xmmword_1400053F0);
v11.hCursor = v6;
v11.lpszClassName = ClassName;
v11.hIconSm = LoadIconW(hInstance, (LPCWSTR)0x6C);
RegisterClassExW(&v11);
qword_140007880 = (__int64)&unk_1400078A0;
v7 = CreateWindowExW(0, ClassName, WindowName, 0xC80000u, 0x80000000, 0, 600, 200, 0i64, 0i64, hInstance, 0i64);
v8 = v7;
if ( v7 )
{
hWnd = v7;
dword_140007920 = 600;
dword_140007924 = 200;
GdiplusStartup(&unk_1400078A0, &dword_1400078A8, 0i64);
ShowWindow(v8, nShowCmd);
UpdateWindow(v8);
v9 = LoadAcceleratorsW(hInstance, (LPCWSTR)0x6D);
while ( GetMessageW(&Msg, 0i64, 0, 0) )
{
if ( !TranslateAcceleratorW(Msg.hwnd, v9, &Msg) )
{
TranslateMessage(&Msg);
DispatchMessageW(&Msg);
}
}
LODWORD(v7) = Msg.wParam;
}
return (int)v7;
}
뭐가 많이 복잡하긴 하다.
RegisterClassExW(&v11); 이 부분을 보자. 콜백함수이ㅏㄷ.
v11을 분석해보자 ...?
v11.lpfnWndProc = (WNDPROC)sub_1400032F0; 주소는 32F0을 보면 되겠다.
LRESULT __fastcall sub_1400032F0(HWND a1, UINT a2, WPARAM a3, LPARAM a4)
{
LRESULT result; // rax
_QWORD *v5; // rbx
__int64 v6; // rbx
__int64 v7; // [rsp+20h] [rbp-18h] BYREF
switch ( a2 )
{
case 2u:
PostQuitMessage(0);
result = 0i64;
break;
case 0xFu:
qword_140007910 = (__int64)BeginPaint(hWnd, &Paint);
v5 = (_QWORD *)GdipAlloc(16i64);
if ( v5 )
{
*v5 = 0i64;
v5[1] = 0i64;
v7 = 0i64;
*((_DWORD *)v5 + 2) = GdipCreateFromHDC(qword_140007910, &v7);
*v5 = v7;
}
else
{
v5 = 0i64;
}
qword_140007918 = (__int64)v5;
sub_140002C40();
v6 = qword_140007918;
if ( qword_140007918 )
{
GdipDeleteGraphics(*(_QWORD *)qword_140007918);
GdipFree(v6);
}
EndPaint(hWnd, &Paint);
result = 0i64;
break;
case 0x202u:
InvalidateRect(hWnd, 0i64, 1);
UpdateWindow(hWnd);
result = 0i64;
break;
default:
result = DefWindowProcW(a1, a2, a3, a4);
break;
}
return result;
}
beginPaint와 endPaint 부분 사이에 플래그를 출력할 것 같다.
begin과 end사이에서 호출하는 함수가 있어서, 한 번 확인해보고자 했다.
char __fastcall sub_140002C40(__int64 a1, int a2)
{
int v2; // ebx
int v3; // edx
int v4; // edx
int v5; // edx
int v6; // edx
int v7; // edx
int v8; // edx
int v9; // edx
int v10; // edx
int v11; // edx
int v12; // edx
int v13; // edx
int v14; // edx
int v15; // edx
int v16; // edx
int v17; // edx
int v18; // edx
int v19; // edx
int v20; // edx
int v21; // edx
int v22; // edx
int v23; // edx
int v24; // edx
int v25; // edx
int v26; // edx
__int64 v27; // rbx
__int64 v28; // r8
__int64 v29; // r8
__int64 v30; // rdx
__int64 v31; // r8
__int64 v32; // rdx
__int64 v33; // r8
__int64 v34; // rdx
__int64 v35; // r8
__int64 v36; // rdx
__int64 v37; // r8
__int64 v38; // rdx
__int64 v39; // r8
__int64 v40; // rdx
__int64 v41; // r8
__int64 v42; // r8
__int64 v43; // rdx
__int64 v44; // r8
__int64 v45; // r8
__int64 v46; // rdx
__int64 v47; // r8
v2 = qword_140007880;
sub_140002B80(qword_140007880, a2, 30, 470, 80, -16777216);
sub_140002B80(v2, v3, 35, 470, 75, -16777216);
sub_140002B80(v2, v4, 40, 470, 70, -16777216);
sub_140002B80(v2, v5, 45, 470, 65, -16777216);
sub_140002B80(v2, v6, 50, 470, 60, -16777216);
sub_140002B80(v2, v7, 55, 470, 55, -16777216);
sub_140002B80(v2, v8, 60, 470, 50, -16777216);
sub_140002B80(v2, v9, 65, 470, 45, -16777216);
sub_140002B80(v2, v10, 70, 470, 40, -16777216);
sub_140002B80(v2, v11, 75, 470, 75, -16777216);
sub_140002B80(v2, v12, 80, 400, 60, -16777216);
sub_140002B80(v2, v13, 30, 470, 90, -16777216);
sub_140002B80(v2, v14, 35, 470, 30, -16777216);
sub_140002B80(v2, v15, 40, 470, 35, -16777216);
sub_140002B80(v2, v16, 45, 470, 50, -16777216);
sub_140002B80(v2, v17, 50, 470, 40, -16777216);
sub_140002B80(v2, v18, 55, 400, 90, -16777216);
sub_140002B80(v2, v19, 60, 470, 60, -16777216);
sub_140002B80(v2, v20, 65, 470, 30, -16777216);
sub_140002B80(v2, v21, 70, 470, 80, -16777216);
sub_140002B80(v2, v22, 75, 470, 70, -16777216);
sub_140002B80(v2, v23, 80, 470, 60, -16777216);
sub_140002B80(v2, v24, 80, 470, 80, -16777216);
sub_140002B80(v2, v25, 80, 470, 70, -16777216);
sub_140002B80(v2, v26, 90, 470, 90, -16777216);
v27 = qword_140007880;
sub_1400017A0(qword_140007880, 40i64, v28, 4278190080i64);
sub_140001C80(v27, 80i64, v29, 4278190080i64);
sub_140002640(v27, v30, v31, 4278190080i64);
sub_1400020F0(v27, v32, v33, 4278190080i64);
sub_140002390(v27, v34, v35, 4278190080i64);
sub_140001240(v27, v36, v37, 4278190080i64);
sub_140001F20(v27, v38, v39, 4278190080i64);
sub_140001560(v27, v40, v41, 4278190080i64);
sub_140001C80(v27, 360i64, v42, 4278190080i64);
sub_1400019D0(v27, v43, v44, 4278190080i64);
sub_1400017A0(v27, 440i64, v45, 4278190080i64);
sub_140002870(v27, v46, v47, 4278190080i64);
return 0;
}
뭘 자꾸 그린다. v27값을 설정해주는 부분을 기준으로 위 함수, 아래 함수를 분석해보고싶다.
__int64 __fastcall sub_140002B80(__int64 a1, __int64 a2, unsigned int a3, int a4, int a5, unsigned int a6)
{
int v9; // eax
__int64 v10; // rsi
int v11; // eax
__int64 v12; // rbx
int v13; // eax
__int64 v15; // [rsp+30h] [rbp-38h] BYREF
__int64 v16; // [rsp+38h] [rbp-30h]
v16 = 0i64;
v15 = 0i64;
v9 = GdipCreatePen1(a6, a2, 0i64, &v15);
v10 = *(_QWORD *)(a1 + 120);
LODWORD(v16) = v9;
v11 = GdipDrawLineI(*(_QWORD *)v10, v15, 150i64, a3, a4, a5);
if ( v11 )
*(_DWORD *)(v10 + 8) = v11;
v12 = *(_QWORD *)(a1 + 120);
v13 = GdipSetSmoothingMode(*(_QWORD *)v12, 4i64);
if ( v13 )
*(_DWORD *)(v12 + 8) = v13;
return GdipDeletePen(v15);
}
펜1?을 만들고, DrawLine을 하는 점으로 보아 정말 무엇인가를 그린다고 생각할 수 있겠다.
실제로 이렇게 그림을 그려나가는 것을 디버깅을 통해 확인할 수 있다.
그렇다면 sub_140002B80을 nop 해줘야겠다.
함수를 nop으로 바꾸는 것 보다, 실행되자마자 ret하도록 바꾸는 것이 더 편하다.