Cheat Engine Forum Index Cheat Engine
The Official Site of Cheat Engine
 
 FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 


Hooking ws2_32->connect()

 
Post new topic   Reply to topic    Cheat Engine Forum Index -> General programming
View previous topic :: View next topic  
Author Message
Unc3nZureD
Newbie cheater
Reputation: 0

Joined: 17 Jul 2013
Posts: 13

PostPosted: Wed Aug 13, 2014 10:50 am    Post subject: Hooking ws2_32->connect() Reply with quote

I'm trying to hook the connect function of a game, but I keep bumping into problems. So, here's my hooked function:

Code:
int WINAPI connectProc(SOCKET s, const struct sockaddr *name, int namelen)
{
    int a;

    UnHookFunction(ws2_32, "connect", connectBk);
    a = connect(s, name, namelen);
    HookFunction(ws2_32, "connect", connectProc, connectBk);

    /* Try to get the IP (I'm not sure if it's the right way, but it's not the important thing yet.
    sockaddr_in* pV4Addr = (struct sockaddr_in*)&name;
    int ipAddr = pV4Addr->sin_addr.s_addr;

    cout << "Connected: " << ipAddr << endl;*/
    printf("connected!\n");

    return a;
}


My hooking functions:
Code:
DWORD HookFunction(HMODULE lpModule, LPCSTR lpFuncName, LPVOID lpFunction, unsigned char *lpBackup)
{
   DWORD pPrevious;
   DWORD pPrevious2;

   DWORD dwAddr = (DWORD)GetProcAddress(lpModule, lpFuncName);
   BYTE jmp[6] = { 0xe9, 0x00, 0x00, 0x00, 0x00, 0xc3 };

   memcpy((LPVOID)lpBackup, (LPVOID)dwAddr, 6);      // ReadProcessMemory
   DWORD dwCalc = ((DWORD)lpFunction - dwAddr - 5);   // dwCalc
   memcpy(&jmp[1], &dwCalc, 4);                  // Set DwCalc

   VirtualProtect((LPVOID)dwAddr, 6, PAGE_EXECUTE_READWRITE, &pPrevious);   // WriteProcessMemory replacer
   memcpy((LPVOID)dwAddr, &jmp[0], 6);                              // WriteProcessMemory replacer
   VirtualProtect((LPVOID)dwAddr, 6, pPrevious, &pPrevious2);            // WriteProcessMemory replacer

   return dwAddr;
}

void UnHookFunction(HMODULE lpModule, LPCSTR lpFuncName, unsigned char *lpBackup)
{
   DWORD pPrevious;
   DWORD pPrevious2;

   DWORD dwAddr = (DWORD)GetProcAddress(lpModule, lpFuncName);

   VirtualProtect((LPVOID)dwAddr, 6, PAGE_EXECUTE_READWRITE, &pPrevious);
   memcpy((LPVOID)dwAddr, &lpBackup[0], 6);
   VirtualProtect((LPVOID)dwAddr, 6, pPrevious, &pPrevious2);
}


When I inject my code, the client won't be able to connect to the server. Could you see any obvious flaws in my code?
Thank you!
Back to top
View user's profile Send private message
Stylo
Grandmaster Cheater Supreme
Reputation: 3

Joined: 16 May 2007
Posts: 1073
Location: Israel

PostPosted: Wed Aug 13, 2014 1:17 pm    Post subject: Reply with quote

That's not a good way of using hooks
- Removing the hook
- Calling the original function
- Restore the hook

Just call the original function from your hook and remove the 0xc3 which is the RET instruction
jump to the connect function address + 5

_________________
Stylo
Back to top
View user's profile Send private message
atom0s
Moderator
Reputation: 205

Joined: 25 Jan 2006
Posts: 8587
Location: 127.0.0.1

PostPosted: Wed Aug 13, 2014 1:32 pm    Post subject: Reply with quote

Like Stylo said, thats kind of an iffy method of hooking.

Look into using a detouring library or do a "hook-hop" like Stylo referred to.

_________________
- Retired.
Back to top
View user's profile Send private message Visit poster's website
Unc3nZureD
Newbie cheater
Reputation: 0

Joined: 17 Jul 2013
Posts: 13

PostPosted: Wed Aug 13, 2014 2:42 pm    Post subject: Reply Reply with quote

Well, yes, I know, it's not the best way, since it's not multithread-safe.

Could you do 2 things for me please?
1st: Any idea why my hook throws error?
2nd: Could you explain that "hook-hop" method? It seems to be interesting, but I can't exactly understand. I don't want to use pre-written libraries, like detours, I like to use my code (or at least which one I understand)

My code works for other functions, like OpenProcess(), ExitProcess() etc, this is the only one which I can't get to work. connect() returns -1 and GetLastError() thrown something like it couldn't connect (I can't remember anymore)
Back to top
View user's profile Send private message
atom0s
Moderator
Reputation: 205

Joined: 25 Jan 2006
Posts: 8587
Location: 127.0.0.1

PostPosted: Wed Aug 13, 2014 4:19 pm    Post subject: Reply with quote

Your code looks fine to do what it should do but the manner that it is handled like you said is not thread safe and can lead to race conditions and issues with overall connections. You also never told us what issues you are running into though, are you crashing? Getting any errors or faults? Need more info on that part to try and help any.

Quote:
2nd: Could you explain that "hook-hop" method? It seems to be interesting, but I can't exactly understand. I don't want to use pre-written libraries, like detours, I like to use my code (or at least which one I understand)


I think, personally, that's a bit overkill of an attitude to have in terms of using things that work. There is no point in reinventing the wheel over and over again for things that have been done, let alone in a professional manner.

There are other detouring libraries that are fully open source too (like Detours) that are a bit smaller and easier to understand if that is an issue you have with Detours.

As for info on hookhop's, here are some links to explain it fully:
http://forum.cheatengine.org/viewtopic.php?p=4857260#4857260
http://smartz993.wordpress.com/2008/12/07/hot-patching-hook-hopping/#more-16

Some source code that shows how to implement the theory:
https://code.google.com/p/ripe/source/browse/RiPE+DLL/hookhop.h

_________________
- Retired.
Back to top
View user's profile Send private message Visit poster's website
Unc3nZureD
Newbie cheater
Reputation: 0

Joined: 17 Jul 2013
Posts: 13

PostPosted: Wed Aug 13, 2014 5:59 pm    Post subject: Reply with quote

Thanks for the sources, I'll study them Smile

So, the problem is:
- Without hook, connection succeeds.
- With hook the game crashes.

Some words about the "crash".
It's probably not my fault, since this time, I used this function:

Code:
int a;

   UnHookFunction(ws2_32, "connect", connectBk);
   a = connect(s, name, namelen);
   HookFunction(ws2_32, "connect", connectProc, connectBk);

   cout << "Connection tried: " << a << " LastError: " << GetLastError() << endl;

   return a;


it successfully couted the following:
"Connection tried: -1 LastError: 10035"

So, connect() and hooks succeed, they didn't crash, however something went wrong with the connecting, since it returned -1. Probably the game can't handle this error (at least I think).
Back to top
View user's profile Send private message
atom0s
Moderator
Reputation: 205

Joined: 25 Jan 2006
Posts: 8587
Location: 127.0.0.1

PostPosted: Wed Aug 13, 2014 6:20 pm    Post subject: Reply with quote

WSAEWOULDBLOCK
10035

Resource temporarily unavailable.

This error is returned from operations on nonblocking sockets that cannot be completed immediately, for example recv when no data is queued to be read from the socket. It is a nonfatal error, and the operation should be retried later. It is normal for WSAEWOULDBLOCK to be reported as the result from calling connect on a nonblocking SOCK_STREAM socket, since some time must elapse for the connection to be established.

_________________
- Retired.
Back to top
View user's profile Send private message Visit poster's website
Unc3nZureD
Newbie cheater
Reputation: 0

Joined: 17 Jul 2013
Posts: 13

PostPosted: Wed Aug 13, 2014 6:44 pm    Post subject: Reply with quote

Okay, I understand that "It is normal for WSAEWOULDBLOCK to be reported as the result from calling connect", but it still crashes my executable.

Without the hook, executable perfectly works. That's why I can't understand it. This hook should do exactly the same thing as if it didn't exist, isn't it? So even if it's "normal" (I mean the error message), it should simply connect as it does without hook.
Back to top
View user's profile Send private message
atom0s
Moderator
Reputation: 205

Joined: 25 Jan 2006
Posts: 8587
Location: 127.0.0.1

PostPosted: Wed Aug 13, 2014 10:15 pm    Post subject: Reply with quote

Unc3nZureD wrote:
Okay, I understand that "It is normal for WSAEWOULDBLOCK to be reported as the result from calling connect", but it still crashes my executable.

Without the hook, executable perfectly works. That's why I can't understand it. This hook should do exactly the same thing as if it didn't exist, isn't it? So even if it's "normal" (I mean the error message), it should simply connect as it does without hook.


Debug it then and step through your code to find where the crash is happening. Something is not happening correctly, so basically last thing to do is debug and see if you can find any other info out.

_________________
- Retired.
Back to top
View user's profile Send private message Visit poster's website
Unc3nZureD
Newbie cheater
Reputation: 0

Joined: 17 Jul 2013
Posts: 13

PostPosted: Thu Aug 14, 2014 10:07 am    Post subject: Reply with quote

Sorry, crash was my fault. I changed:

Code:
int WINAPI connectProc

to
Code:
int connectProc


Which caused the problem. Now I'm using the good one:
Code:
int WINAPI connectProc

and it isn't crashing anymore.

But my problem still persist. return code is -1, lasterror is 10035. I think that somehow parameters get corrupted before I could connect to the right place. Have you got any idea what could cause it?
Back to top
View user's profile Send private message
atom0s
Moderator
Reputation: 205

Joined: 25 Jan 2006
Posts: 8587
Location: 127.0.0.1

PostPosted: Thu Aug 14, 2014 12:23 pm    Post subject: Reply with quote

Winsock API calling conventions are marked as WSAAPI. (Which in turn is PASCAL, which is __stdcall)

If you remove all the code from your connect hook and just let it pass through like a normal call does it work fine?

Like this:
Code:
int WSAAPI connectProc(SOCKET s, const struct sockaddr* name, int namelen)
{
    UnHookFunction(ws2_32, "connect", connectBk);
    int a = connect(s, name, namelen);
    HookFunction(ws2_32, "connect", connectProc, connectBk);

    return a;
}



I still suggest you just use Detours or another premade lib that can do this easily for you. I am working on a hook at the moment to record some packets for a login server of an MMO which needed a connect hook. Using Detours 3 the code looks like this:

Code:

#define _CRT_SECURE_NO_WARNINGS

#pragma comment(lib, "WS2_32.lib")
#include <WinSock2.h>

#include <Windows.h>
#include <iostream>
#include <string>

#pragma comment(lib, "detours/detours.lib")
#include "detours\detours.h"

/**
 * @brief Winsock detour definitions.
 */
extern "C"
{
    int(WSAAPI * Real_conect)(SOCKET s, const struct sockaddr* name, int namelen) = connect;
};

/**
 * @brief Winsock2 connect detour callback.
 *
 * @brief s         The unconnected socket object.
 * @brief name      The connection information structure.
 * @brief namelen   The connection information structure length.
 *
 * @return Winsock related return.
 */
int WSAAPI Mine_connect(SOCKET s, const struct sockaddr* name, int namelen)
{
    auto sockInfo = *(sockaddr_in*)name;

    char szOutput[1024] = { 0 };
    sprintf_s(szOutput, 1024, "[CONNECT] Connection made to: %u [Family: %d][Port: %d]\n", sockInfo.sin_addr.S_un.S_addr, sockInfo.sin_family, sockInfo.sin_port);
    OutputDebugStringA(szOutput);

    auto f = fopen("C:\\packet.log", "a+");
    if (f)
    {
        fwrite(szOutput, strlen(szOutput), 1, f);
        fclose(f);
    }

    return Real_conect(s, name, namelen);
}

/**
 * @brief Installs detours onto the needed API / functions.
 *
 * @param hinstDLL  Our module base.
 */
void __stdcall InstallHooks(HINSTANCE hinstDLL)
{
    DetourTransactionBegin();
    DetourUpdateThread(::GetCurrentThread());

    DetourAttach(&(PVOID&)Real_conect, Mine_connect);

    DetourTransactionCommit();
}

/**
 * @brief Module entry point.
 *
 * @return True on success, false otherwise.
 */
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
{
    switch (fdwReason)
    {
    case DLL_PROCESS_ATTACH:
        DisableThreadLibraryCalls(hinstDLL);
        InstallHooks(hinstDLL);
        break;
    }

    return TRUE;
}


Very simple to understand the flow of whats going on.

_________________
- Retired.
Back to top
View user's profile Send private message Visit poster's website
Unc3nZureD
Newbie cheater
Reputation: 0

Joined: 17 Jul 2013
Posts: 13

PostPosted: Thu Aug 14, 2014 7:18 pm    Post subject: Reply with quote

Damn, I have to switch to detours. Thank you for your code, it works perfectly. I've got no idea what's the problem with mine Sad

Thank you again!
Back to top
View user's profile Send private message
Display posts from previous:   
Post new topic   Reply to topic    Cheat Engine Forum Index -> General programming All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You can download files in this forum


Powered by phpBB © 2001, 2005 phpBB Group

CE Wiki   IRC (#CEF)   Twitter
Third party websites