сплайсинг GetProcAddress + получение RetEIP

Discussion in 'С/С++, C#, Rust, Swift, Go, Java, Perl, Ruby' started by sn0w, 26 Mar 2008.

  1. sn0w

    sn0w Статус пользователя:

    Joined:
    26 Jul 2005
    Messages:
    1,023
    Likes Received:
    1,296
    Reputations:
    327
    вот с какой задачей столкнулся, нужно перехватывать 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;
    }
    }

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

    spider-intruder Elder - Старейшина

    Joined:
    9 Dec 2005
    Messages:
    700
    Likes Received:
    339
    Reputations:
    37
    А че сплайсинг? Хук не катит? хотя что это изменит.. щас я пороюсь
     
  3. 0x0c0de

    0x0c0de Elder - Старейшина

    Joined:
    25 May 2007
    Messages:
    441
    Likes Received:
    396
    Reputations:
    297
    >> // вот хз как получить RetEIP
    Если не будет локальных переменных, то адрес возврата будет на вершине стека. Я так на асме писала - посмотри в отладчике сколько занимают локальные переменные и учитывай их
     
  4. KEZ

    KEZ Ненасытный школьник

    Joined:
    18 May 2005
    Messages:
    1,604
    Likes Received:
    754
    Reputations:
    397
    Мда, паук-вторжение опять попытался сказать что-то умное...

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

    0x0c0de Elder - Старейшина

    Joined:
    25 May 2007
    Messages:
    441
    Likes Received:
    396
    Reputations:
    297
    я не говорю что их не юзать. я говорю посмотреть в отладчике
     
  6. Xserg

    Xserg Elder - Старейшина

    Joined:
    9 Dec 2006
    Messages:
    135
    Likes Received:
    127
    Reputations:
    53
    DWORD ret_eip = (DWORD)&hmod - 4;

    вернее

    DWORD *p = (DWORD *)&hmod - 1;
    DWORD ret_eip = p[0];
     
    #6 Xserg, 26 Mar 2008
    Last edited: 26 Mar 2008
  7. 0x0c0de

    0x0c0de Elder - Старейшина

    Joined:
    25 May 2007
    Messages:
    441
    Likes Received:
    396
    Reputations:
    297
    >>а про push reg перед использованием
    м=\. а ну да, ты прав

    Code:
    1000102A    55              PUSH EBP
    1000102B    8BEC            MOV EBP,ESP
    1000102D    83C4 F8         ADD ESP,-8 ; две локальные переменные
    
    это если в асме. [esp+0с] - адрес возврата. если без локальных, то [esp+4]
     
  8. sn0w

    sn0w Статус пользователя:

    Joined:
    26 Jul 2005
    Messages:
    1,023
    Likes Received:
    1,296
    Reputations:
    327
    всем спасибо, проблема решена :)
     
    1 person likes this.
  9. KEZ

    KEZ Ненасытный школьник

    Joined:
    18 May 2005
    Messages:
    1,604
    Likes Received:
    754
    Reputations:
    397
    вот ещё одно отличие программиста от хакера с античата... программист не будет делать все через жопу ради быстрого эффекта, а подумает сначала (АСМ вставки это признак необразованости и их надо стараться избегать в программах на С и С++ как минимум)

    Code:
    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");
    
     
    1 person likes this.