Valhalla Legends Forums Archive | Advanced programming | Hooking Winsock

AuthorMessageTime
CupHeadI'm looking to have the user select a process and then, based on that, reroute the calls that that program makes through my program, and then back to the original program.  So far I've heard about replacing the DLL that the target program uses with my own, but this doesn't seem to be a viable solution as my program needs to be able to attach to just about any other program.  There was also code injection, which I'm sure will have to be used at some point, although I'm not sure exactly how.  Lastly, there was overwriting the IAT of the target program, which seems like a good idea, but once again, no idea of how to implement something like that.December 15, 2003, 11:36 AM
KpSince you're doing this to an arbitrary process, there's extra work involved if you decide to patch the IAT (which you'll probably want to do from in-process anyway, via a hook DLL (HDL)).  Specifically, you need to find all loaded modules that have referenced the functions you want and patch them all.  Taking Starcraft as an example: it's easy to get the handle to the Starcraft main image (Starcraft.exe) since it is the main image, but at least some of the networking calls are made in its DLLs (and/or SNPs, which are really just DLLs with a different extension).  So, you'd need to enumerate all the DLLs it has loaded and patch them too, or you'll miss some/all of the calls.

Depending on ease-of-use requirements, it may very well be simpler to have your program just ask the user to look up and supply what DLLs need to be patched.  There's at least one way to enumerate the DLLs, but I've never been able to make it work programmatically.  It clearly does though, as I've seen debuggers do it. :)
December 15, 2003, 12:50 PM
TelosA while back I wrote something to list processes and their modules with sample output like this

Quote
Process: 00000444
        Module [Load Address]: 00400000
        Name: EternalChat.exe
        Image Size: 757760
        Entry Point: 00403e9c
        Module [Load Address]: 77f40000
        Name: ntdll.dll
        Image Size: 761856
        Entry Point: 00000000
        Module [Load Address]: 77e40000
        Name: kernel32.dll
        Image Size: 999424
        Entry Point: 77e4a342
        Module [Load Address]: 73570000
        Name: MSVBVM60.DLL
        Image Size: 1392640
        Entry Point: 73571ae8
        Module [Load Address]: 77d00000
        Name: USER32.dll
        Image Size: 585728
        Entry Point: 77d01b15
        Module [Load Address]: 77c00000
        Name: GDI32.dll
        Image Size: 278528
        Entry Point: 77c01bbe
        Module [Load Address]: 77da0000
        Name: ADVAPI32.dll
        Image Size: 589824
        Entry Point: 77da1aa6
        Module [Load Address]: 77c50000
        Name: RPCRT4.dll
        Image Size: 671744
        Entry Point: 77c57fa0
        Module [Load Address]: 77160000
        Name: ole32.dll
        Image Size: 1196032
        Entry Point: 77161943
        Module [Load Address]: 77ba0000
        Name: msvcrt.dll
        Image Size: 344064
        Entry Point: 77baedaa
        Module [Load Address]: 770e0000
        Name: OLEAUT32.dll
        Image Size: 512000
        Entry Point: 7714cb43
        Module [Load Address]: 744f0000
        Name: MSCTF.dll
        Image Size: 307200
        Entry Point: 744f1416
        Module [Load Address]: 76f90000
        Name: CLBCatQ.DLL
        Image Size: 516096
        Entry Point: 76f93486
        Module [Load Address]: 77010000
        Name: COMRes.dll
        Image Size: 811008
        Entry Point: 77011048
        Module [Load Address]: 77b90000
        Name: VERSION.dll
        Image Size: 32768
        Entry Point: 77b91140
        Module [Load Address]: 27580000
        Name: mscomctl.ocx
        Image Size: 1069056
        Entry Point: 27593990
        Module [Load Address]: 762b0000
        Name: comdlg32.dll
        Image Size: 290816
        Entry Point: 762b1620
        Module [Load Address]: 77290000
        Name: SHLWAPI.dll
        Image Size: 299008
        Entry Point: 772922fb
        Module [Load Address]: 70bc0000
        Name: COMCTL32.dll
        Image Size: 589824
        Entry Point: 70c1f668
        Module [Load Address]: 77380000
        Name: SHELL32.dll
        Image Size: 8245248
        Entry Point: 77382425
        Module [Load Address]: 70ad0000
        Name: comctl32.dll
        Image Size: 942080
        Entry Point: 70ad41c5
        Module [Load Address]: 76300000
        Name: msi.dll
        Image Size: 2179072
        Entry Point: 7630649c
        Module [Load Address]: 22170000
        Name: mswinsck.ocx
        Image Size: 114688
        Entry Point: 22171344
        Module [Load Address]: 71bb0000
        Name: WSOCK32.dll
        Image Size: 36864
        Entry Point: 71bb1060
        Module [Load Address]: 71c00000
        Name: WS2_32.dll
        Image Size: 98304
        Entry Point: 71c01580
        Module [Load Address]: 71bf0000
        Name: WS2HELP.dll
        Image Size: 32768
        Entry Point: 71bf132a
        Module [Load Address]: 20000000
        Name: RICHTX32.OCX
        Image Size: 204800
        Entry Point: 200015fd

If this will be useful at all I will share the code.
December 15, 2003, 04:32 PM
KpI'd be interested in seeing at least the calls that retrieved the information.  My recollection is that I found how you're supposed to do it, but attempting to do it failed rather badly and I never had a chance to find out why.December 15, 2003, 05:09 PM
Teloshttp://www.geocities.com/telosx7/ProcessInformation.htm

Edit: Could be shortened a lot by doing everything in the same loop rather than doing the access checks and then copying.
December 15, 2003, 06:04 PM
Skywing
http://www.geocities.com/telosx7/ProcessInformation.htm

You should keep the process handles open between your loops, otherwise you are vulnerable due to a race condition.  Process objects will be deleted when there are no handles to them and they are terminated, so you need to keep a handle open to prevent a process ID from being reused or otherwise invalidated.
December 15, 2003, 06:07 PM
UserLoser.Speaking of this, I think it'd be neat and very useful if someone were to write a packet logger specifically for protocols such as Battle.net's.  Where the user would see the entire packet recieved & sent, along with it taken apart byte by byte, dword by dword, ect; explaining what each byte/word/dword/string is forDecember 15, 2003, 06:50 PM
Kp
Speaking of this, I think it'd be neat and very useful if someone were to write a packet logger specifically for protocols such as Battle.net's.  Where the user would see the entire packet recieved & sent, along with it taken apart byte by byte, dword by dword, ect; explaining what each byte/word/dword/string is for

IMO, much of the reason this hasn't happened is due to the following:
1) Not much demand
2) The only ones who could do it quickly can analyze the packets by sight, so have no need of a tool to do it for us.

Also, if it were to be a true packet logger for the TCP stream, that'd be a much bigger nuisance than just something which can take a precaptured packet and present it in appropriate form.
December 15, 2003, 10:16 PM
TelosI was not sure if this was the place to post this but I found an odd behavior in EnumProcessModules.  When I pass my array of HMODULEs to the call in order to be filled if it does not contain enough members then [this does not seem to be documented] various other data members in the program are overwritten.  In my case the overwritten variable was the DWORD count of processes so the program started trying to close HANDLEs that were not there and access memory at an array index far past the end.  I did not test but this behavior may also affect EnumProcesses.

On the other note I updated the program so that it will not be vulnerable to race conditions http://www.geocities.com/telosx7/source/procinfo/ProcessInformation.htm.  Thanks Skywing.
December 16, 2003, 10:11 AM
UserLoser.
Speaking of this, I think it'd be neat and very useful if someone were to write a packet logger specifically for protocols such as Battle.net's.  Where the user would see the entire packet recieved & sent, along with it taken apart byte by byte, dword by dword, ect; explaining what each byte/word/dword/string is for

IMO, much of the reason this hasn't happened is due to the following:
1) Not much demand
2) The only ones who could do it quickly can analyze the packets by sight, so have no need of a tool to do it for us.

Also, if it were to be a true packet logger for the TCP stream, that'd be a much bigger nuisance than just something which can take a precaptured packet and present it in appropriate form.

Eh, well yesterday i checked vl.com/skywing after I posted this and saw a "Bnparser" that he's developing.  It says "Bnparser is a Network Monitor parser plugin to handle various Battle.net protocols.".  Sounds like he's making a program just like this or something similiar
December 16, 2003, 10:52 AM
Skywing
Speaking of this, I think it'd be neat and very useful if someone were to write a packet logger specifically for protocols such as Battle.net's.  Where the user would see the entire packet recieved & sent, along with it taken apart byte by byte, dword by dword, ect; explaining what each byte/word/dword/string is for

IMO, much of the reason this hasn't happened is due to the following:
1) Not much demand
2) The only ones who could do it quickly can analyze the packets by sight, so have no need of a tool to do it for us.

Also, if it were to be a true packet logger for the TCP stream, that'd be a much bigger nuisance than just something which can take a precaptured packet and present it in appropriate form.

Eh, well yesterday i checked vl.com/skywing after I posted this and saw a "Bnparser" that he's developing.  It says "Bnparser is a Network Monitor parser plugin to handle various Battle.net protocols.".  Sounds like he's making a program just like this or something similiar
I haven't really worked on that for awhile now, though.  Not sure if it'll ever get to a useable state.
December 16, 2003, 10:53 AM
Arsenic
there's extra work involved if you decide to patch the IAT (which you'll probably want to do from in-process anyway, via a hook DLL (HDL)).  Specifically, you need to find all loaded modules that have referenced the functions you want and patch them all.

Also, if the application loads the Winsock DLL at run-time, you won't find the reference in the IAT of the executable or its modules. So if you want to have an efficicient sniffer you will have to play with the Winsock DLL directly in the target process memory, or then intercept its loading at run-time.
December 18, 2003, 10:51 PM
ArtaThat's a good point. It might be worth hooking the process's LoadLibrary import (if it exists) and patching DLLs as they're loaded.December 19, 2003, 12:23 AM
AdronYou still won't get the ones that aren't dynamically loaded. And you can't attach after the program is already running. The way I like to do it is to patch winsock itself, the entry-points, to jump to your hooks. That's the way WSHook.dll does it!December 19, 2003, 06:38 AM
taylorjonlThis is a little project I ran into while searching the internet.

http://www.codeproject.com/dll/apihijack.asp#xx590524xx

Hope it is helpful.
December 20, 2003, 10:03 AM
CupHeadThat does look helpful, thanks.December 20, 2003, 11:37 AM
MeeksYea IMO, the most appropriate solution here is called several things, one of which is Extended Code Overwriting another is Detouring, there's a few more but it's all the same thing.  This is by no means exact, it is just a brief synapsis:

* This is a 32 bit implementation.

* Always pay respect to memory.  Use VirtualProtect to obtain the correct access rights before writing to memory.

* A trampoline function is a function that you allocate space for and it matches the parameters of your target function you want to hook.  It's intention is to preserve the bytes you will have to overwrite in order to perform the hook.

1. Copy the first 5 bytes to the trampoline function.
2. Write an unconditional JMP instruction to the trampoline function.
3. Write the 32 bit address of the 6th byte of the target function to the trampoline function.

* Pay very careful attention not to cut an assembly instruction off.  If you do, you will cause uncontrolled behavior.  The number of bytes you will copy from the target function to the trampoline function depends upon the assembly instructions, so open up OllyDbg.

* A Detour function is one that is called in place of the target function.

* Be sure the target function and your Detour function have identical parameters and are of the same calling convention.

4. Overwrite the first byte of the target function with an unconditional JMP instruction.
5. Overwrite the next 4 bytes with the 32 bit address of your Detour function.

Now when the target function is called, it is rerouted to your Detour function, add the changes needed or simply log the activity, now you may call the trampoline function to execute the original target functions contents.  It really is as simple as that.  There are several examples including source code.  Hope this helps.
February 13, 2008, 05:14 PM
ColTGreat post Meeks, only 5 years later. February 13, 2008, 05:51 PM
SphtI think he's from the future.  tell us, saddam hussein was captured last week.  what ends up happening to him?February 13, 2008, 06:21 PM
YeggAt least he provided information of use in the event someone searches for a similar topic and finds this site.


February 14, 2008, 12:21 AM
MeeksWow, how'd I over look that one, lol.  Oops.September 15, 2008, 06:59 PM