A forum for reverse engineering, OS internals and malware analysis 

Forum for discussion about user-mode development.
 #27268  by evelyette
 Wed Nov 18, 2015 7:09 pm

I was thinking about a solution to hook a function in DLL, so I'll be able to detect function invocation from any user-land process or a service. The functions are part of a custom DLL which basically have send/recv functions (that I would like to hook), which send something to the server on the Internet and recv a response from the server.

There are a number of techniques I could use including the following:
  • AppInit_DLLs: I could inject a DLL into every process depending upon user32.dll, and then go through a list of imported function to see whether the desired function from a specific module gets loaded. This option has a few disadvantages, because it won't detect if the function is called dynamically inside a process. Also, the DLL won't be injected into processes not using user32.dll.
  • Starting Own Processes: we can start the process inside a debugger or some other master process, but I also want to detect processes when being controlled by the user: if a user invokes a program from Desktop (but also when he writes a cronjob that starts a process using this function)
  • Hooking All Processes: we can hook all of the user-mode functions, so we'll be able to control the process creation at which point we can inject an additional DLL into every process that basically checks for the presence of a function call.
  • Hooking System Processes: I could hook the privileged user-mode system processes like csrss.exe process by hooking the CsrCreateProcess function (exported by csrsrv.dll) where the process gets created. At this point I could inject a DLL into every process being started which would check for the function call.
  • Hooking EAT: I don't want to use this technique as it would require me to change the DLL; I don't want to change the DLL, but want the solution to work seamlessly.
  • Kernel Driver: I know this is the best solution, but I would like to stay in the user-mode; I have administrative privileges in user-mode, so that should be enough to do what I want/need.
  • IFEO: only works for executables, but not DLLs; if I want this to work, I would need to know the name of the process beforehand, as I can only hook DLL loading of a process which has BeingDebugged in PEB set to 1 (the IsDebuggerPresent returns true - this isn't true when a user clicks on a program in the Desktop, since it wasn't started under a debugger).
  • Windows Filtering Platform: I could scan for network packets with WFP, but I'm not sure whether this would work in real-time. The process could be alive for a really short time, so I could miss the opportunity to hook it before it's done executing. I'm guessing with WFP I could only scan Application/Transport/Internet OSI layer, which would require me to know the exact server hostname/IP where the process sends data and receives data from. Let me know if I'm mistaken on this?
Basically I'm looking for a better way of detecting whether a function in a DLL has been invoked without actually changing the DLLs or executables on the system. I can add new files to the filesystem, but shouldn't change/modify/move the already present files. I also have administrator access to the user-mode as I want a user-mode solution, so a kernel-mode solution (although the best) is not an option.

If somebody knows of a better way please let me know.
 #27270  by EP_X0FF
 Thu Nov 19, 2015 4:50 am
Making proxy dll of the same name with re-routed exports? If it old systems like (XP/Vista/7) you can try register it in KnownDlls.
 #27273  by evelyette
 Thu Nov 19, 2015 7:11 pm
Hi, thank you for your answers, I've been using proxy DLL before, just haven't thought of it now. I'm probably going to implement a solution by using it in order to see whether it's a good solution for me, but as far as I can see, I can rename the DLL, and provide a new DLL with the same prototype functions. What puzzles me though is if I can automate this for every Windows system, particularly the newest versions, including 32/64-bit support - I don't see any reason why not, but maybe you have more experience and can enlighten me about whether I'll have any problems doing that.

Besides that, I would like to know:

1. If I hook all processes in the system by implementing a simple DLL which checks if the functions which I would like to monitor are used in the process, would it have a major impact on the stability and performance of the system? I was thinking of a solution with IFEO, which would inject a DLL into initial explorer.exe and csrss.exe, where I would hook the process creation routines: after a process is being created, I would inject the same DLL into the other processes - did anybody implement this yet, did it have a major impact on the system's performance?

2. WFP: if I know at least one unique field in the TCP/IP stack, so I can catch a packet being sent to the network by using WFP, will the signaling from Windows WFP about a detected packet arrive in my own process before the process is done executing? What puzzles me is that the Windows might signal the presence of a packet being sent out to the network, but when my process receives the signal and has a chance to inspect it, the original process would have already received a response and terminate, so it wouldn't give me enough time to hook it? Let's forget about the send function for now, and only think about hooking the recv function (since we can't really hook the send via this method). Keep in mind that we can be on a gigabit network and packet is sent to a machine in lan, so it's super fast.

3. Hooking System Processes: if I hook the CsrCreateProcess in csrss.exe do I also have to hook the process creation functions in order to inject a DLL into every newly created process? Can I possibly rather hook the dll loader instead and check which DLL gets loaded and hook there - where might I look for something like that?

4. KnownDLLs: does newer Windows versions other than XP/Vista/7 have any similar mechanism to KnownDLLs that I'm not aware of, which could come in handy instead of KnownDLLs?

Thank you
 #27276  by Brock
 Fri Nov 20, 2015 3:03 pm
In general, DLL injection + API Hooking offer negligible system-wide performance degradation, so it's a good solution for some tasks but if there are documented callbacks this is the best way to go since you're not competing with other code that may have already hooked the same API etc. DLLs are loaded in-context with the affected process and doesn't function out-of-context which would carry more overhead, so again it's a good solution assuming you're not hooking hundreds or even thousands of usermode APIs per process. A few things to note about DLL injection, out of the box you'll fail to inject into protected process such as AudioDG, (CSRSS in Windows 8.1+ etc) so you will not be able to monitor these processes without disabling their protection which in itself is a bad idea because you're opening your system up to potential security breaches. You may also struggle to inject into processes which run isolated aka sandboxed with lower integrity (chrome browser for example). Metro apps can be injected but your DLL needs to contain the ALL APPLICATION PACKAGES group in its file permissions, which can easily be done by dropping it into a folder such as WINDOWS, Program Files, System32 etc. or applying this in the ACL yourself for the DLL.

As for your CsrCreateProcess hook inside csrsrv.dll, this will not be possible on Windows 8.1+ since CSRSS is now protected at least not from a DLL injection perspective. On legacy OS you'd need to hook CsrCreateProcess in every instance of CSRSS since there is one instance per session, with that API you would not need to hook any other process creation APIs system-wide but it's still a hassle as I've mentioned needing to be in all instances. Also, what's to prevent a process from spawning a child process suspended and patching it so it doesn't inform CSRSS before running? It's quite easy to do. You lack specificity when it comes to your final goal details and although you elaborate as to what certain methods are potentially available to you and what you've tried you're not really expanding on your premise. All we know is that you wish to hook some network based API system-wide and nothing more... Seems a bit vague to be frank. The more information you divulge the better the feedback
 #27396  by evelyette
 Fri Dec 11, 2015 8:14 am

I have another question for you. I've created a proxy DLL for Windows 7 x86/64 by following this tutorial: http://www.codeproject.com/Articles/165 ... omatically. This works fine until I try it on the system DLL C:\windows\system32\dnsapi.dll, where things break. Basically I've created just a clean DLL where I've hooked all the function by using the following - I haven't actually implemented any of the functions in order to test a clean setup first.
Code: Select all
extern "C" __declspec(naked) void __stdcall BreakRecordsIntoBlob_() { __asm { jmp m[0*4] } }
But even on a clean setup, this doesn't work. After I reboot the machine, none of the programs that rely on that DLL are working anymore; the IE reports the website is unavailable, which is due to the dnsapi.dll, which doesn't seem to work properly.

Also is there any way to tell Windows to reload the changed/moved DLL, so the Windows restart wouldn't be needed?

Is it possible that MFC DLLs have anything to do with the problem; do I need to write a MFC DLLs proxy - I haven't found anything about it on the internet, but I'm assuming it should be the same as DLL proxy, except adding the MFC into it like described here: http://www.codeproject.com/Articles/251 ... -Beginners

If anybody was faced with this kind of problem, I would be glad if he can provide some pointers?
 #27399  by evelyette
 Fri Dec 11, 2015 5:43 pm
I've determined a few extra points. After renaming the original dnsapi.dll to dnsapi_.dll and copying the proxy dll dnsapi.dll into it's place, I've rebooted a computer for changes to take effect. During bootup, the services that use the dnsapi.dll are logging errors about not being a win32 applications, for example: "DHCP Client is not a win32 application". Therefore, after reboot, a lot of services can't start because of this error and the windows networking stack isn't working. I've followed this tutorial: http://www.codeproject.com/Articles/165 ... omatically

If I remove the proxy dll and reinstate the original dnsapi.dll everything works as expected? The problem is really weird, since I didn't actually override any of the functions, but only used __declspec(naked) specification for every function, thus the function call should be forwarded to the original DLL. I've also traced this in ImmDbg and the dnsapi.dll (proxy dll) gets called, after which the call is passed to dnsapi_.dll (original dll), but after that the 1460 error happens, which is a timeout error, because of a problem somewhere in the network stack (of course there's a problem if the whole networking isn't working).

Any comments/ideas are welcome, because this has been bugging me for some time now. Especially since I'm just forwarding the calls to the original DLL, which should make everything work, but apparently not so. Could it be that I've build the DLL somehow wrongly and the services are therefore reporting that themselves are not win32 applications (since the loaded DLL isn't right somehow).
 #27401  by evelyette
 Sat Dec 12, 2015 9:26 am
I'm attaching the Visual Studio project code, which implements the dnsapi.dll functionality; this is the basic code which was created for Windows 7 x64 operating system, but from what I've seen the DLL has the same functions on other versions of Windows system, so the code should be the same.
You do not have the required permissions to view the files attached to this post.
 #27406  by evelyette
 Sun Dec 13, 2015 12:21 pm
nullptr wrote:Are you replacing the 32 bit dll in the syswow64 directory?
Hi, I've tried two possibilities:

1: Replace the 32-bit DLL in syswow64 and rebooted the computer at which time everything worked, but the programs then called 64-bit dnsapi.dll from the system32 folder, so I wasn't able to intercept the function calls.

2. Then I also replaced the 64-bit DLL in system32 folder by the same code except compiled with x64 profile in Visual Studio - basically I've just switched to this profile in a drop-down menu (1-click). When also replacing the DLL in system32 with this DLL and after rebooting the computer, everything stops working.

Is it possible that Visual Studio didn't actually compile a 64-bit DLL, but did something else instead? How do you usually compile the 64-bit DLL?

Btw: Is it possible for changes to take affect when replacing the DLLs without rebooting a computer, that would same quite some time when testing.