Доброго времени суток!
Столкнулся с новой для себя проблемой разломанного стека функции в процессе ревёрса.
Приложение использует старенький DirectDraw для рисования.
| fun_directDrawCreateSurface |
| LPDIRECTDRAWSURFACE __usercall fun_directDrawCreateSurface@<eax>(int a1@<ebp>, unsigned __int16 width, unsigned __int16 height, int a4)
{
int Dst; // [esp+8h] [ebp-6Ch]
int v6; // [esp+Ch] [ebp-68h]
int v7; // [esp+10h] [ebp-64h]
int v8; // [esp+14h] [ebp-60h]
char v9; // [esp+50h] [ebp-24h]
LPDIRECTDRAWSURFACE surfacePtr; // [esp+6Ch] [ebp-8h]
int v11; // [esp+70h] [ebp-4h]
memset(&Dst, 0, 0x6Cu);
v7 = height;
Dst = 108;
v8 = width;
v6 = 4103;
v11 = 64;
qmemcpy(&v9, &unk_4DE5E8, 0x20u);
if ( !a4 )
v11 = 2112;
if ( ((int (__cdecl *)(LPDIRECTDRAW, int *, unsigned __int16 *, _DWORD, int, int, int, int))lpDD->lpVtbl->CreateSurface)(
lpDD,
&Dst,
&height,
0,
Dst,
v6,
v7,
v8) )
{
return 0;
}
AM_BltSurface(a1, surfacePtr, 0);
return surfacePtr;
}
|
| |
Сигнатура функции CreateSurface очень простая, и в ней и не пахнет 7 параметрами:
HRESULT (__stdcall *CreateSurface)(IDirectDraw *This, LPDDSURFACEDESC, LPDIRECTDRAWSURFACE *, IUnknown *)
При этом легко заметить, что вначале расположена структура DDSURFACEDESC, размер которой как раз равен 0x6C.
Но есть проблема.
| Структура _DDSURFACEDESC |
| struct _DDSURFACEDESC
{
DWORD dwSize;
DWORD dwFlags;
DWORD dwHeight;
DWORD dwWidth;
union
{
LONG lPitch;
DWORD dwLinearSize;
};
DWORD dwBackBufferCount;
union
{
DWORD dwMipMapCount;
DWORD dwZBufferBitDepth;
DWORD dwRefreshRate;
};
DWORD dwAlphaBitDepth;
DWORD dwReserved;
LPVOID lpSurface;
DDCOLORKEY ddckCKDestOverlay;
DDCOLORKEY ddckCKDestBlt;
DDCOLORKEY ddckCKSrcOverlay;
DDCOLORKEY ddckCKSrcBlt;
DDPIXELFORMAT ddpfPixelFormat;
DDSCAPS ddsCaps;
};
|
| |
LPVOID lpSurface; расположена по смещению ebp-1Ch, а при сопоставлении со структурой LPDIRECTDRAWSURFACE surfacePtr; начинает указывать на DDPIXELFORMAT ddpfPixelFormat (ebp-8h).
| Получается вот такая каша. |
| LPDIRECTDRAWSURFACE __usercall fun_directDrawCreateSurface@<eax>(int a1@<ebp>, unsigned __int16 width, unsigned __int16 height, int a4)
{
_DDSURFACEDESC Dst; // [esp+8h] [ebp-6Ch]
memset(&Dst, 0, 0x6Cu);
Dst.dwHeight = height;
Dst.dwSize = 108;
Dst.dwWidth = width;
Dst.dwFlags = 4103;
Dst.ddsCaps.dwCaps = 64;
qmemcpy(&Dst.ddpfPixelFormat, &unk_4DE5E8, sizeof(Dst.ddpfPixelFormat));
if ( !a4 )
Dst.ddsCaps.dwCaps = 2112;
if ( ((int (__cdecl *)(LPDIRECTDRAW, _DDSURFACEDESC *, unsigned __int16 *, _DWORD, DWORD, DWORD, DWORD, DWORD))lpDD->lpVtbl->CreateSurface)(
lpDD,
&Dst,
&height,
0,
Dst.dwSize,
Dst.dwFlags,
Dst.dwHeight,
Dst.dwWidth) )
{
return 0;
}
AM_BltSurface(a1, (LPDIRECTDRAWSURFACE)Dst.ddpfPixelFormat.dwRGBAlphaBitMask, 0);
return (LPDIRECTDRAWSURFACE)Dst.ddpfPixelFormat.dwRGBAlphaBitMask;
}
|
| |
Само собой, это рабочий код, который прекрасно функционирует.
В чём может быть проблема? Как её исправить? Насколько я понимаю, стек ломает вызов CreateSurface, но как подсказать Hex-Rays, что он неправ?
"Хаос всегда побеждает порядок, поскольку лучше организован." (с) Терри Пратчетт