3

I'm using a DLL-injector to inject a dll which goes into the IAT and replaces the system call sendto() with my own.

This is the replace method.

void replaceFunction(DWORD f, DWORD nf)
{
// Base address.
HMODULE hMod = GetModuleHandle(NULL);

// DOS Header.
PIMAGE_DOS_HEADER dosHeader = (PIMAGE_DOS_HEADER)hMod;

// NT Header.
PIMAGE_NT_HEADERS ntHeader = MakePtr(PIMAGE_NT_HEADERS, dosHeader, dosHeader->e_lfanew);

// Import Table descriptor.
PIMAGE_IMPORT_DESCRIPTOR importDesc = MakePtr(PIMAGE_IMPORT_DESCRIPTOR, dosHeader,ntHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress);

// Make writeable.
removeReadOnly(MakePtr(PIMAGE_THUNK_DATA, hMod, importDesc->FirstThunk));

while(importDesc->Name)
{
    PIMAGE_THUNK_DATA pThunk = MakePtr(PIMAGE_THUNK_DATA, dosHeader, importDesc->FirstThunk);

    while (pThunk->u1.Function)
    {
        if(pThunk->u1.Function == f)
        {
            pThunk->u1.Function = nf;
        }
        pThunk++;
    }

    importDesc++;
}
}

Called by:

// Get the Function Address
DWORD f = (DWORD)GetProcAddress(GetModuleHandleA("ws2_32.dll"),"sendto");
DWORD nf = (DWORD)&my_sendto;

// Save real sendto address.
real_sendto = (int (*)(SOCKET s, const char *buf, int len, int flags, const struct sockaddr *to, int tolen))f;

// Replace function.
replaceFunction(f, nf);

This works:

int my_sendto(SOCKET s, const char *buf, int len, int flags, const struct sockaddr *to, int tolen)
{
    CreateThread(NULL, 0, de_sendto, NULL, 0, NULL);
    return real_sendto(s, buf, len, flags, to, tolen);
}

This does not work:

int my_sendto(SOCKET s, const char *buf, int len, int flags, const struct sockaddr *to, int tolen)
{
    int l = real_sendto(s, buf, len, flags, to, tolen);
    CreateThread(NULL, 0, de_sendto, NULL, 0, NULL);
    return l;
}

Upon using the latter version of my_sendto() the host application will crash upon calling sendto().

de_sendto is defined as:

DWORD WINAPI de_sendto(LPVOID args) { }
André
  • 85
  • 1
  • 5
  • 1
    Define _work_ and _not work_ please. – Seth Carnegie Aug 04 '11 at 22:54
  • Also, show the source of the `de_sendto` function if you will. – Seth Carnegie Aug 04 '11 at 22:56
  • not work as in the host application crashes upon calling the sendto() function. – André Aug 04 '11 at 22:58
  • de_sendto is empty, ie: DWORD WINAPI de_sendto(LPVOID args) { } – André Aug 04 '11 at 22:59
  • Are you sure that `my_sendto` has the same calling convention as `sendto` does? When I hooked stuff, that was probably the largest cause of crashes for me. – Seth Carnegie Aug 04 '11 at 23:01
  • The same as this one: http://msdn.microsoft.com/en-us/library/ms740148%28v=vs.85%29.aspx Also, then it should not work in version one? – André Aug 04 '11 at 23:03
  • @Seth: That is a good point. The sendto() in the msdn documentation doesn't show the decorators. If you drill down through winsock2.h, sendto has `WSAAPI` in front of it, which going down further basically turns into `pascal`. – Mark Wilkins Aug 04 '11 at 23:07
  • @Mark @Andrew which turns out to be `far __stdcall` in my Windows.h in MSVC++ 2010. @Andrew try changing it and see if it still crashes. – Seth Carnegie Aug 04 '11 at 23:09
  • @Seth - it looks like you are correct. I followed the wrong one of 10 or so different definitions of PASCAL. – Mark Wilkins Aug 04 '11 at 23:12
  • @Seth, works perfectly. Adding far __stdcall to both my_sendto and real_sendto did the trick! Thanks alot! – André Aug 04 '11 at 23:21

1 Answers1

3

Your calling convention is incorrect. The default calling convention for C++ is __cdecl, but sendto's calling convention is __stdcall. Change the calling convention of my_sendto to __stdcall to fix the crash.

Seth Carnegie
  • 73,875
  • 22
  • 181
  • 249
  • @Mark I only guessed that because it's caused me hours of headache before. Gotta love simulating `__thiscall` from Delphi. – Seth Carnegie Aug 05 '11 at 01:22