• Welcome to Valhalla Legends Archive.
 

Hooking Winsock in Warcraft 3

Started by Excel, August 05, 2006, 12:02 PM

Previous topic - Next topic

Excel

I am looking to hook the winsock calls that war3 uses but am having a few problems.  This seems like the most technical forum of the ones I've found, so I'm hoping someone here might have some info for me. :)

Here is what I am hooking so far
Quote
Examining C:\Program Files\Warcraft III\war3.exe
... hooking wsock32.dll : recv ( ordinal 0x16 )
... hooking wsock32.dll : send ( ordinal 0x19 )
... hooking wsock32.dll : recvfrom ( ordinal 0x17 )
... hooking wsock32.dll : accept ( ordinal 0x1 )
... hooking wsock32.dll : socket ( ordinal 0x23 )
... hooking wsock32.dll : closesocket ( ordinal 0x3 )

I successfully hook accept and send, however never get any recv data.  Does anyone have any suggestions why this is?  I am thinking that war3 might use a different function to receive data ( which doesn't really make sense ).  I am also thinking that the real receive function is done through a different dll import ( not in war3.exe ).  I am pretty confident that my hooking system is working properly ( as I am hooking accept and send fine ) and would rather not post code for it.  I'm hoping someone knows a little more about which imports are used.

Here are thewinsock imports war3.exe is using.

wsock32.dll
            56E1E4 Import Address Table
            56D94C Import Name Table
                 0 time date stamp
                 0 Index of first forwarder reference

                  Ordinal    13 listen (forwarded to ws2_32.listen)
                  Ordinal    57 gethostname (forwarded to ws2_32.gethostname)
                  Ordinal    14 ntohl (forwarded to ws2_32.ntohl)
                  Ordinal    11 inet_ntoa (forwarded to ws2_32.inet_ntoa)
                  Ordinal    15 ntohs (forwarded to ws2_32.ntohs)
                  Ordinal    10 inet_addr (forwarded to ws2_32.inet_addr)
                  Ordinal    16 recv
                  Ordinal    19 send (forwarded to ws2_32.send)
                  Ordinal    17 recvfrom
                  Ordinal    20 sendto (forwarded to ws2_32.sendto)
                  Ordinal    52 gethostbyname (forwarded to ws2_32.gethostbyname)
                  Ordinal     4 connect (forwarded to ws2_32.connect)
                  Ordinal   116 WSACleanup (forwarded to ws2_32.WSACleanup)
                  Ordinal   115 WSAStartup (forwarded to ws2_32.WSAStartup)
                  Ordinal    12 ioctlsocket (forwarded to ws2_32.ioctlsocket)
                  Ordinal     2 bind (forwarded to ws2_32.bind)
                  Ordinal     5 getpeername (forwarded to ws2_32.getpeername)
                  Ordinal     9 htons (forwarded to ws2_32.htons)
                  Ordinal     1 accept (forwarded to ws2_32.accept)
                  Ordinal     6 getsockname (forwarded to ws2_32.getsockname)
                  Ordinal    21 setsockopt
                  Ordinal    23 socket (forwarded to ws2_32.socket)
                  Ordinal   111 WSAGetLastError (forwarded to ws2_32.WSAGetLastError)
                  Ordinal     3 closesocket (forwarded to ws2_32.closesocket)
                  Ordinal    18 select (forwarded to ws2_32.select)


Does anyone know how many connections are made to the server?  I believe it just has one socket clientside and serverside per connection.

Any discussion would be great, hopefully I don't get flamed too much for being new.  ::)

Maddox

It uses WSARecv and IO Completion Ports.
asdf.

Excel

How come when I do:

C:\Program Files\Warcraft III>dumpbin /imports war3.exe

It only shows imports on wsock32.dll and none on ws2_32.dll?

Also, I was able to place the hook on WSARecv, but it was never called.  Will hooking that function call not work?

Excel

Hrmm... I still can't figure out why my hook to receive Warcraft 3 data isn't working.  I hook on all the receive functions from wsock32.dll as well as ws2_32.dll which seem to be the only ones that would make sense.

"Examining" happens when a LoadLibrary call is made
"importing" happens as I iterate through the import table
"hooking" happens when I match an import with one in my list-to-hook ( by name or ordinal )
Quote
Examining C:\WINDOWS\system32\wsock32.dll
... importing WS2_32.dll : (null) ( ordinal 0x21 )
... hooking WS2_32.dll : ntohs ( ordinal 0x21 )
... importing WS2_32.dll : (null) ( ordinal 0x7 )
... hooking WS2_32.dll : getsockopt ( ordinal 0x7 )
... importing WS2_32.dll : WSARecvFrom ( ordinal 0x0 )
... hooking WS2_32.dll : WSARecvFrom ( ordinal 0x73 )
... importing WS2_32.dll : WSARecv ( ordinal 0x0 )
... hooking WS2_32.dll : WSARecv ( ordinal 0x71 )
Quote
Examining C:\Program Files\Warcraft III\war3.exe
... importing wsock32.dll : (null) ( ordinal 0x13 )
... importing wsock32.dll : (null) ( ordinal 0x57 )
... importing wsock32.dll : (null) ( ordinal 0x14 )
... importing wsock32.dll : (null) ( ordinal 0x11 )
... importing wsock32.dll : (null) ( ordinal 0x15 )
... importing wsock32.dll : (null) ( ordinal 0x10 )
... importing wsock32.dll : (null) ( ordinal 0x16 )
... hooking wsock32.dll : recv ( ordinal 0x16 )
... importing wsock32.dll : (null) ( ordinal 0x19 )
... hooking wsock32.dll : send ( ordinal 0x19 )
... importing wsock32.dll : (null) ( ordinal 0x17 )
... hooking wsock32.dll : recvfrom ( ordinal 0x17 )
... importing wsock32.dll : (null) ( ordinal 0x20 )
... importing wsock32.dll : (null) ( ordinal 0x52 )
... importing wsock32.dll : (null) ( ordinal 0x4 )
... importing wsock32.dll : (null) ( ordinal 0x116 )
... importing wsock32.dll : (null) ( ordinal 0x115 )
... importing wsock32.dll : (null) ( ordinal 0x12 )
... importing wsock32.dll : (null) ( ordinal 0x2 )
... importing wsock32.dll : (null) ( ordinal 0x5 )
... importing wsock32.dll : (null) ( ordinal 0x9 )
... importing wsock32.dll : (null) ( ordinal 0x1 )
... hooking wsock32.dll : accept ( ordinal 0x1 )
... importing wsock32.dll : (null) ( ordinal 0x6 )
... importing wsock32.dll : (null) ( ordinal 0x21 )
... importing wsock32.dll : (null) ( ordinal 0x23 )
... hooking wsock32.dll : socket ( ordinal 0x23 )
... importing wsock32.dll : (null) ( ordinal 0x111 )
... importing wsock32.dll : (null) ( ordinal 0x3 )
... hooking wsock32.dll : closesocket ( ordinal 0x3 )
... importing wsock32.dll : (null) ( ordinal 0x18 )

Any other suggestions for me?  Perhaps you could explain how IO Completion Ports work more ( if you think this is the reason ).  My hooking works with other network applications.. so it's gotta be a quirk with Warcraft 3 that I just haven't found yet.

Excel

#4
Woops... just found this thread ( http://forum.valhallalegends.com/index.php?topic=15438.0 ) and also realized that maybe I should have had this topic posted in General Programming.

Edit: I also just found this article by the great company Sysinternals ( http://www.sysinternals.com/Information/IoCompletionPorts.html )

Excel

Here is some debug output I created to show what is happening with the hooked calls I have setup.


This is what happens when war3.exe is loaded and a user clicks the Battle.NET button and the sits at the login screen for about 5 minutes or so ( the last sitting CreateIoCompletionPort calls are from idleing ).
Quote
CreateIoCompletionPort ret=8820
CreateIoCompletionPort ret=8824
CreateIoCompletionPort ret=8820
CreateIoCompletionPort ret=8820
CreateIoCompletionPort ret=8820
CreateIoCompletionPort ret=8820
CreateIoCompletionPort ret=8820
CreateIoCompletionPort ret=8820
CreateIoCompletionPort ret=8820
CreateIoCompletionPort ret=8820
CreateIoCompletionPort ret=8820
CreateIoCompletionPort ret=8820
CreateIoCompletionPort ret=8820
CreateIoCompletionPort ret=8820
CreateIoCompletionPort ret=8820
CreateIoCompletionPort ret=8820
CreateIoCompletionPort ret=8820
CreateIoCompletionPort ret=9424
Accept Connection on socket 957
ntohs ret=0
CreateIoCompletionPort ret=9424
Send Data ( 1 bytes )
Send Data ( 58 bytes )
GetQueuedCompletionStatus ret=1
Send Data ( 8 bytes )
GetQueuedCompletionStatus ret=1
CreateIoCompletionPort ret=8820
CreateIoCompletionPort ret=8820
CreateIoCompletionPort ret=8820
CreateIoCompletionPort ret=8820
CreateIoCompletionPort ret=8820
CreateIoCompletionPort ret=8820
CreateIoCompletionPort ret=8820
CreateIoCompletionPort ret=8820
Send Data ( 147 bytes )
GetQueuedCompletionStatus ret=1
GetQueuedCompletionStatus ret=1
Send Data ( 30 bytes )
Send Data ( 36 bytes )
Send Data ( 32 bytes )
Send Data ( 35 bytes )
Send Data ( 4 bytes )
GetQueuedCompletionStatus ret=1
CreateIoCompletionPort ret=8820
CreateIoCompletionPort ret=8820
CreateIoCompletionPort ret=8820
CreateIoCompletionPort ret=8820
CreateIoCompletionPort ret=8820
CreateIoCompletionPort ret=8820
CreateIoCompletionPort ret=8820
CreateIoCompletionPort ret=8820
GetQueuedCompletionStatus ret=1
Send Data ( 30 bytes )
GetQueuedCompletionStatus ret=1
GetQueuedCompletionStatus ret=1
GetQueuedCompletionStatus ret=1
GetQueuedCompletionStatus ret=1
GetQueuedCompletionStatus ret=1
GetQueuedCompletionStatus ret=1
GetQueuedCompletionStatus ret=1
GetQueuedCompletionStatus ret=1
GetQueuedCompletionStatus ret=1

Here are all the hooks I have in place

API_HOOK_INFO hookTable[ ] =
  {
  { "ws2_32.dll", "socket", 0x17, 0 },
  { "ws2_32.dll", "recv", 0x10, 0 },
  { "ws2_32.dll", "send", 0x13, 0 },
  { "ws2_32.dll", "closesocket", 0x03, 0 },
  { "ws2_32.dll", "accept", 0x01, 0 },
  { "ws2_32.dll", "WSASocketA", 0x4E, 0 },
  { "ws2_32.dll", "WSASocketW", 0x4F, 0 },
  { "ws2_32.dll", "WSASend", 0x48, 0 },
  { "ws2_32.dll", "WSAAccept", 0x1A, 0 },
  { "ws2_32.dll", "WSARecv", 0x47, 0 },
 
  { "wsock32.dll", "accept", 0x01, 0 },
  { "wsock32.dll", "closesocket", 0x03, 0 },
  { "wsock32.dll", "recv", 0x10, 0 },
  { "wsock32.dll", "send", 0x13 ,0 },
  { "wsock32.dll", "socket", 0x17, 0 },
  { "wsock32.dll", "recvfrom", 0x11, 0 },
   
  { "ws2_32.dll", "WSARecvFrom", 0x49, 0 },
  { "ws2_32.dll", "getsockopt", 0x07, 0 },
  { "ws2_32.dll", "ntohs", 0x15, 0 },

    { "kernel32.dll", "CreateIoCompletionPort", 0x56, 0 },
    { "kernel32.dll", "GetQueuedCompletionStatus", 0x1AA, 0 },
    { "kernel32.dll", "OutputDebugStringA", 0x27C, 0 }
     
  };


I handle the connect, close, send, recv functions with callback functions.  The other oddball functions i've hooked ( as an afterthought ) simply output the functionname and the return value ( EAX ).