PDA

Просмотр полной версии : сплайсинг GetProcAddress + получение RetEIP


sn0w
26.03.2008, 15:37
вот с какой задачей столкнулся, нужно перехватывать GetProcAddress в целях реверсирования одной байды. итак имеем следующее:

FARPROC (__stdcall* gGetProcAddress)(HMODULE,LPCSTR); - указатель на оригинальную функцию которая вызывается в конце, и собсна сам перехватчик:

FARPROC __stdcall fGetProcAddress(HMODULE hmod, LPCSTR proc)
{
DWORD io;
DWORD ret_eip;
char buf[200];

__asm{ // вот хз как получить RetEIP
push eax;
mov eax,[esp+4]; //тут ясен хер в стеке переменные перехватчика
mov ret_eip,eax;
pop eax;
}

g_dwCallnum++;

itoa(g_dwCallnum, buf, 10);
WriteFile(g_hLog, buf, lstrlenA(buf), &io, 0);
WriteFile(g_hLog, ") GetProcAddress: ", 18, &io, 0);
WriteFile(g_hLog, proc, lstrlenA(proc), &io, 0);
WriteFile(g_hLog, " RetEIP: ", 9, &io, 0);
itoa(ret_eip, buf, 16);
WriteFile(g_hLog, buf, lstrlenA(buf), &io, 0);
WriteFile(g_hLog, "\r\n", 2, &io, 0);

// В лог пишется таким образом: 1) GetProcAddress: ExitWindowsEx RetEIP: 40178A
// Но ессна по вставке асма ясно что RetEIP будет полнейшим бредом.

return gGetProcAddress(hmod,proc);
}

Какбы сделать так чтобы извлекать адрес возврата?

была мысль оформить тело перехватчика в стиле

__declspec(naked) __stdcall fGetProcAddress(HMODULE hmod, LPCSTR proc)
{
__asm {
// тут код записи лога
jmp gGetProcAddress;
}
}

но этож заебешься писать.
кто что может посоветовать?

spider-intruder
26.03.2008, 15:59
А че сплайсинг? Хук не катит? хотя что это изменит.. щас я пороюсь

0x0c0de
26.03.2008, 16:02
>> // вот хз как получить RetEIP
Если не будет локальных переменных, то адрес возврата будет на вершине стека. Я так на асме писала - посмотри в отладчике сколько занимают локальные переменные и учитывай их

KEZ
26.03.2008, 16:08
А че сплайсинг? Хук не катит? хотя что это изменит.. щас я пороюсь


Мда, паук-вторжение опять попытался сказать что-то умное...


Если не будет локальных переменных, то адрес возврата будет на вершине стека. Я так на асме писала - посмотри в отладчике сколько занимают локальные переменные и учитывай их


ну да.. охрененное решение) не юзать переменные и надеется на то, что случай подвернется и будет все на вершине.. а про push reg перед использованием (ebx,esi,edi,ebp) мы забыли

0x0c0de
26.03.2008, 16:16
я не говорю что их не юзать. я говорю посмотреть в отладчике

Xserg
26.03.2008, 16:28
DWORD ret_eip = (DWORD)&hmod - 4;

вернее

DWORD *p = (DWORD *)&hmod - 1;
DWORD ret_eip = p[0];

0x0c0de
26.03.2008, 16:42
>>а про push reg перед использованием
м=\. а ну да, ты прав


1000102A 55 PUSH EBP
1000102B 8BEC MOV EBP,ESP
1000102D 83C4 F8 ADD ESP,-8 ; две локальные переменные


это если в асме. [esp+0с] - адрес возврата. если без локальных, то [esp+4]

sn0w
26.03.2008, 17:16
всем спасибо, проблема решена :)

KEZ
26.03.2008, 21:13
вот ещё одно отличие программиста от хакера с античата... программист не будет делать все через жопу ради быстрого эффекта, а подумает сначала (АСМ вставки это признак необразованости и их надо стараться избегать в программах на С и С++ как минимум)


FARPROC (WINAPI *gGetProcAddress)(HMODULE hModule,LPCTSTR lpProcName);
FARPROC WINAPI fGetProcAddressEip(ULONG dwRetEip,HMODULE hModule,LPCTSTR lpProcName)
{
CHAR szMsg[255];
wsprintf(szMsg,"hModule=%08x,lpProcName=%08x,dwRetEip=%08x",hModule,lpProcName,dwRetEip);
MessageBox(0,szMsg,"GetProcAddress",0);
return gGetProcAddress(hModule,lpProcName);
}
FARPROC __declspec(naked) WINAPI fGetProcAddressStub(HMODULE hModule,LPCTSTR lpProcName)
{
__asm {
push dword ptr [esp]
jmp fGetProcAddressEip
}
}

// ...
Splice(
(ULONG)(GetProcAddress(GetModuleHandle("kernel32.dll"),"GetProcAddress")),
fGetProcAddressStub,
(PULONG)&gGetProcAddress
);
GetProcAddress(GetModuleHandle("kernel32.dll"),"IsDebuggerPresent");