Hook Winsock connect

Jan 11, 2015 at 1:05 PM
Hi!

I'm trying to use EasyHook to create connection logger.

I'm declaring connect delegate this way (took from pinvoke.net):
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
private delegate int ConnectDelegate(IntPtr s, ref sockaddr_in addr, int addrsize);

[DllImport("Ws2_32.dll", SetLastError = true)]
private static extern int connect(IntPtr s, ref sockaddr_in addr, int addrsize);
sockaddr_in:
[StructLayout(LayoutKind.Sequential)]
public struct sockaddr_in
{
    public ushort sin_family;
    public ushort sin_port;
    public in_addr sin_addr;

    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
    public byte[] sin_zero;
}
and finally in_addr:
[StructLayout(LayoutKind.Explicit, Size = 4)]
public struct in_addr
{
        [FieldOffset(0)] public byte s_b1;
        [FieldOffset(1)] public byte s_b2;
        [FieldOffset(2)] public byte s_b3;
        [FieldOffset(3)] public byte s_b4;

        [FieldOffset(0)] public ushort s_w1;
        [FieldOffset(2)] public ushort s_w2;

        [FieldOffset(0)] public uint s_addr;
}
All hooking stuff is just same as in FileMon example. Hooked function looks like this:
private int Connect_Hooked(IntPtr s, ref sockaddr_in addr, int addrsize)
{
    var connectResult = connect(s, ref addr, addrsize);
    return connectResult;
}
You may notice this code is not doing anything. So this should work almost same as without any hooks.
But this is not woking :)
variable connectResult here will be -1 (SOCKET_ERROR). Google says i should check GetLastError and WSAGetLastError. I tried both but they give me 0.
I guess there is a problem mapping sockaddr_in struct, but i don't know how to debug it...
Please, tell me what am i doing wrong :)

Thanks in advance.
Jan 11, 2015 at 8:37 PM
Edited Jan 13, 2015 at 12:42 AM
So, i did some research, and it seems like EasyHook is overriding LastError, so program code always has GetLastError = 0.

Here, i tried to intercept Firefox connections, but it didn't work, so i attached ollydbg to find out whats going on there:
CPU Disasm
Address   Hex dump          Command                                  Comments
0F7D11E2  |.  51            PUSH ECX                                 ; /Arg3
0F7D11E3  |.  52            PUSH EDX                                 ; |Arg2
0F7D11E4  |.  56            PUSH ESI                                 ; |Arg1
0F7D11E5  |.  FF15 7C738F0F CALL DWORD PTR DS:[<&WSOCK32.#4>]        ; \WS2_32.connect <-- here Firefox trying to connect
0F7D11EB  |.  894424 0C     MOV DWORD PTR SS:[ESP+0C],EAX
0F7D11EF  |.  83F8 FF       CMP EAX,-1
0F7D11F2  |.- 0F85 82000000 JNE 0F7D127A
0F7D11F8  |.  FF15 A8738F0F CALL DWORD PTR DS:[<&WSOCK32.#111>]      ; [WS2_32.WSAGetLastError <-- here its looking for error code
Internally, winsock connect function is using SetLastError to set it to WSAEWOULDBLOCK (10035), because the socket was marked as non-blocking. If i dont inject my library with hook, firefox is getting correct error code after calling connect. If i inject my library, then firefox is always getting 0 from WSAGetLastError (which is just a wrapper for GetLastError).

I rewrote delegate and dllimport declaration, thought it would help, but it didn't...
Here how i have it now:
[UnmanagedFunctionPointer(CallingConvention.StdCall, SetLastError = true)]
private delegate int ConnectDelegate(IntPtr s, IntPtr addr, int addrsize);

[DllImport("Ws2_32.dll", SetLastError = true, CallingConvention = CallingConvention.StdCall)]
private static extern int connect(IntPtr s, IntPtr addr, int addrsize);

private int Connect_Hooked(IntPtr s, IntPtr sockAddrPtr, int addrsize)
{
    return connect(s, sockAddrPtr, addrsize);
}
Is this behaviour normal for EasyHook?