A forum for reverse engineering, OS internals and malware analysis 

Forum for discussion about user-mode development.
 #1565  by Radovan
 Fri Jul 16, 2010 11:54 am
Hello

Can anyone give me some guidelines/snippets on how can i check if my process has been hooked/injected?
 #1568  by EP_X0FF
 Fri Jul 16, 2010 1:48 pm
You can create your protection dll and monitor inside DllMain - DLL_THREAD_ATTACH, DLL_PROCESS_ATTACH events.
 #1814  by Not_ice
 Fri Aug 06, 2010 12:30 am
well there are many method to accomplishing any task, what EP_X0ff suggests is good, but that only will only work on trivial dll injections, not memory injections, and not dll injections that dont HAVE a EP in PE ;)

To accomplish something like this isn't that easy, but here is a few pointers. Look into virtualquery function for 'getting a list of memory regions' to maybe detect injections...Also the module enumeration routines are good to have here to see what modules are 'normally loaded',but to monitor for hooks on self and be able to self correct the hook,that does sound relatively easy to implement, now that I think of it...
 #8723  by _Lynn
 Sat Sep 24, 2011 4:51 am
here's one if you didnt know ;)

GetMappedFileName calls NtQueryVirtualMemory, which will tell you if and what the queried regions executable image name.
 #8778  by Brock
 Tue Sep 27, 2011 3:08 pm
DLL_THREAD_ATTACH monitoring in the protection DLL is only good for remote thread creation style injections into your process, not things like APC injection etc. Bypassing DLL_THREAD_ATTACH would be easy too, like calling DisableThreadLibraryCalls on this "protection DLL" prior to creating your injection thread, since there is no such API available to work with foreign processes I have written a small example below which extends DisableThreadLibraryCalls to work with any process, not just your own. After calling this example the DLL_THREAD_ATTACH injection detection method is useless, one could easily use standard CRT method for injection again without any alerts. I think some stupid game protection uses this method to detect injections, very weak :lol:
Code: Select all
const
   LDR_DISABLE_THREAD_CALLS  =  $00040000;

function DisableThreadLibraryCallsEx(const hProcess: ULONG; bDisable: BOOL; hMod: HMODULE = $FFFF): BOOL;
var
        bRet: ULONG;
     PebAddr: ULONG;
         Peb: TPeb;
         Ldr: TPebLdrData;
      LdrMod: TLdrModule;
      pFlink: Pointer;
       pHead: Pointer;
     dwFlags: ULONG;
    dwModule: ULONG;
     dwPatch: ULONG;
begin
       dwModule := 0;
       dwPatch := 0;
      if (hProcess > 0) then
       begin
         PebAddr := PebBaseAddress(hProcess);
      if NtReadVirtualMemory(hProcess, Ptr(PebAddr), @Peb, sizeof(Peb), @bRet) = 0 then
       begin
      if (Peb.Ldr <> nil) and (Peb.LoaderLock <> nil) and
         (NtReadVirtualMemory(hProcess, Peb.Ldr, @Ldr, sizeof(Ldr), @bRet) = 0)  then
       begin
         pFlink := Ldr.InLoadOrderModuleList.Flink;
         pHead := pFlink;
      while (NtReadVirtualMemory(hProcess, pFlink, @LdrMod, sizeof(LdrMod), @bRet) = 0) do
       begin
      if LdrMod.InLoadOrderModuleList.Flink = pHead then
         Break;
         if (hMod = $FFFF) or (hMod = LdrMod.BaseAddress) then
         begin
         if NtReadVirtualMemory(hProcess, Ptr(DWORD(pFlink) + $34), @dwFlags, sizeof(dwFlags), @bRet) = 0 then
         begin
         if (bDisable) then
         dwFlags := (dwFlags or LDR_DISABLE_THREAD_CALLS)
      else
         dwFlags := (dwFlags xor LDR_DISABLE_THREAD_CALLS);
         if WriteProcessMemory(hProcess, Ptr(DWORD(pFlink) + $34), @dwFlags, sizeof(dwFlags), bRet) then
         inc(dwPatch);
         inc(dwModule);
         end;
         if (hMod <> $FFFF) then
         Break;
         end;
         pFlink := LdrMod.InLoadOrderModuleList.Flink;
        end;
      end;
    end;
  end;
   result := (dwModule > 0) and (dwModule = dwPatch);
end;
 #8783  by newgre
 Tue Sep 27, 2011 8:45 pm
DLL_THREAD_ATTACH monitoring in the protection DLL is only good for remote thread creation style injections into your process, not things like APC injection etc.
Assuming you create a new thread on ExitThread and then queue an APC to this thread, that would also reveal the injection in the APC case, right?
 #8787  by Brock
 Tue Sep 27, 2011 9:40 pm
@Newgre

My code is just an example which disables both THREAD_ATTACH and THREAD_DETACH events from reaching a/the DLL(s) so there's no alert of thread creation or detachment for these systems that will load a "protection" DLL and check for DLL_THREAD_ATTACH events in attempt to discover thread-based DLL injection (CreateRemoteThread, RtlCreateUserThread etc). The concept of DLL_THREAD_ATTACH "spying" is easily bypassed and a stupid idea altogether imho since it only stops mainstream DLL injection methods which use remote threads, not the other trillion methods out there which don't need to spawn new threads "directly".

Some of these include but are not limited to:

[1] SetWindowsHookEx w/ dummy msg callback (assumes the target process has a message queue and links to user32.dll)
[2] APC queuing on preexisting threads to load a DLL
[3] Register manipulation of preexisting thread context. Suspend, get context, set context to load DLL, resume
[4] AppInit_DLLs registry key (Not tested but most likely)
[5] ...
 #8791  by newgre
 Wed Sep 28, 2011 8:18 am
How do you go about queueing an APC to an existing thread? IIRC it is not possible to determine (from usermode) if a thread is in an alertable state. And even if you would find a candidate thread, there would always be a race condition since it could exit / wakeup just before your queue operation succeeds, right?
 #8809  by Brock
 Wed Sep 28, 2011 6:00 pm
How do you go about queueing an APC to an existing thread?
Enumerate all running threads in the target process and queue your APC to each one of these threads via OpenThread/NtOpenThread(THREAD_SET_CONTEXT) -> QueueUserApc/NtQueueApcThread. Whatever code you're trying to execute will not be executed until at least one of those target threads enters an alertable wait-state as you know, no predicting when this may occur if ever at all. Processes with more than one thread are better candidates for entering alertable waits, something like calc.exe with 1 thread will not help you. There is no way to force this from usermode without kernel land help such as (ETHREAD->UserApcPending = TRUE) AFAIK but I would like to be wrong about this entirely.
there would always be a race condition since it could exit / wakeup just before your queue operation succeeds, right?
No. Either the thread checks its APC queue and executes them on exiting (special circumstances) or it enters an alertable wait-state and flushes the queue (all pending APCs are iterated through and executed)