Exetools

Exetools (https://forum.exetools.com/index.php)
-   General Discussion (https://forum.exetools.com/forumdisplay.php?f=2)
-   -   Hooking WMI (.NET Application) (https://forum.exetools.com/showthread.php?t=14432)

aldente 07-31-2012 01:14

Hooking WMI (.NET Application)
 
Hello!

I have a .NET application which uses WMI to query the "Win32_Processor" class:
http://msdn.microsoft.com/en-us/library/windows/desktop/aa394373(v=vs.85).aspx

I want to hook the function call and modify the string returned in "ProcessorId".

How would you do that, when working with a .NET application?

I would prefer a "high level" general solution (e.g. a Loader) which also works for future versions of the software, instead of modifying the application directly.

Ember 08-01-2012 11:29

This is easy. You can do it very easily by using Microsoft Detours and injecting a DLL into the target process.

Code:

#define WIN32_LEAN_AND_MEAN
#define _WIN32_DCOM
#include <Windows.h>
#include <comdef.h>
#include <WbemIdl.h>
#include "detours.h"

typedef HRESULT (__stdcall *PGET) (DWORD junk, LPCWSTR, LONG, VARIANT*, CIMTYPE*, LONG*);
PGET OrigGet;
BOOL bHooked = FALSE;

HRESULT __stdcall NewGet(DWORD junk, LPCWSTR wszName, LONG lFlags, VARIANT *pVal, CIMTYPE *pvtType, LONG *plFlavor)
        if(!wcscmp(wszName, L"ProcessorId")) //CPUID
        {
                pVal->vt = VT_BSTR;
                V_BSTR(pVal) = L"PUT SPOOFED PROCESSOR ID HERE";
        }
        else return OrigGet(junk, wszName, lFlags, pVal, pvtType, plFlavor);
        return 1;
}

BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD dwReason, LPVOID lpReserved)
{
        if (dwReason == DLL_PROCESS_ATTACH && !bHooked)
        {
                bHooked = TRUE;
                OrigGet = (PGET)DetourFunction((LPBYTE)DetourFindFunction("fastprox.dll", "?Get@CWbemObject@@UAGJPBGJPAUtagVARIANT@@PAJ2@Z"), (LPBYTE)NewGet);
        }
        return TRUE;
}


aldente 08-03-2012 05:48

Thanks for your answer!

But:
I'm new to Detours, and I'm having trouble to get your DLL to work...

The current version of Detours deos not support "DetourFunction", I had to change the DLLMain function:

Code:

BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD dwReason, LPVOID lpReserved)
{
        if (dwReason == DLL_PROCESS_ATTACH && !bHooked)
        {
                bHooked = TRUE;
                OrigGet = (PGET)DetourFindFunction("fastprox.dll", "?Get@CWbemObject@@UAGJPBGJPAUtagVARIANT@@PAJ2@Z");

                DetourAttach(&(PVOID&)OrigGet, (LPBYTE)NewGet);
        }
        return TRUE;
}

Is that correct?


Also I wonder how to inject this DLL into the .NET process...
Could this be done using "DetourCreateProcessWithDllEx"?

Ember 08-03-2012 06:28

1 Attachment(s)
Please see attached for my copy of detours.h and detours.lib

You can write a simple loader that could start up the app with CreateProcess(), using information from the lpProcessInformation param to get the process' handle.

Note: you may need to enable SeDebugPrivilege first before doing any of this. Code borrowed from online.
Code:

BOOL EnableDebugPrivilege()
{
        HANDLE          hToken;
        LUID            sedebugnameValue;
        TOKEN_PRIVILEGES tp;
 
        if ( !OpenProcessToken( 
                GetCurrentProcess(),
                TOKEN_ADJUST_PRIVILEGES | // to adjust privileges
                TOKEN_QUERY,              // to get old privileges setting
                &hToken 
                ) )
                //
                // OpenProcessToken() failed
                //
                return FALSE;
        //
        // Given a privilege's name SeDebugPrivilege, we should locate its local LUID mapping.
        //
        if ( !LookupPrivilegeValue( NULL, SE_DEBUG_NAME, &sedebugnameValue ) )
        {
                //
                // LookupPrivilegeValue() failed
                //
                CloseHandle( hToken );
                return FALSE;
        }
 
        tp.PrivilegeCount = 1;
        tp.Privileges[0].Luid = sedebugnameValue;
        tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
 
        if ( !AdjustTokenPrivileges( hToken, FALSE, &tp, sizeof(tp), NULL, NULL ) )
        {
                //
                // AdjustTokenPrivileges() failed
                //
                CloseHandle( hToken );
                return FALSE;
        }
 
        CloseHandle( hToken );
        return TRUE;
}

This function is borrowed from another site. Just pass it your handle and a full path to your DLL that you want to inject. I have not tested it, but it looks like it should work fine.
Code:

BOOL bInjectLibrary(HANDLE hProcess, char* szDllToInjectPath)
{
        LPVOID lpRemoteAddress = VirtualAllocEx(hProcess, NULL, strlen(szDllToInjectPath), MEM_COMMIT, PAGE_READWRITE);

        if(!lpRemoteAddress)
                return FALSE;

        if(!WriteProcessMemory(hProcess, lpRemoteAddress, (LPVOID)szDllToInjectPath, strlen(szDllToInjectPath), NULL))
                return FALSE;

        HANDLE hThread = NULL;

        if(!(hThread = CreateRemoteThread(hProcess, NULL, NULL, (LPTHREAD_START_ROUTINE)GetProcAddress(GetModuleHandle("KERNEL32.DLL"), "LoadLibraryA"), lpRemoteAddress, NULL, NULL)))
                return FALSE;

        WaitForSingleObject(hThread, INFINITE);

        if(!VirtualFreeEx(hProcess, lpRemoteAddress, 0, MEM_RELEASE))
                return FALSE;

        CloseHandle(hThread);

        return TRUE;
}

Remember to close your handle to the process when done.

aldente 08-04-2012 22:31

1 Attachment(s)
Ok, thanks for your version of the Detours library, with that one I could build the DLL.

However, injection/hooking does not work properly, yet.

This is basically what my loader looks like:

Code:

// Get debug privilege
EnableDebugPrivilege();

// Create process
result = CreateProcess(NULL, &ExePathAndCmdLineVec[0], NULL, NULL, FALSE, CREATE_SUSPENDED, NULL, &WorkingDirVec[0], &si, &pi);
if(!result)
{
        return -1;
}

// Inject DLL
bInjectLibrary(pi.hThread, DllPath.c_str());

// Resume process execution
ResumeThread(pi.hThread);


Are you sure this kind of injection works for .NET applications?

I attached a sample executable... It is not the target, but it works just like the target. I couldn't manage to manipulate the "ProcessorId"-Entry using your DLL...

Ember 08-05-2012 01:43

Code:

bInjectLibrary(pi.hThread, DllPath.c_str());

// Resume process execution
ResumeThread(pi.hThread);

This is wrong. It should be:
Code:

bInjectLibrary(pi.hProcess, DllPath.c_str());

// Resume process execution
ResumeThread(pi.hProcess);

//Close thread handle
CloseHandle(pi.hThread);

//Close process handle
CloseHandle(pi.hProcess);

I don't know if creating the process suspended might prevent DLL injection from working properly so you might want to take that (and the CloseHandle() and ResumeThread() call with the hThread param) out.

aldente 08-05-2012 06:13

ResumeThread() has to be called with pi.hThread, that was right. The process will stay suspended, if you call it with pi.hProcess.
But apart from that, I tried your suggestions.

I also tried to start the process non-suspended, which doesn't work either...

This injection stuff is a debugging nightmare, you can't debug it in the development environment, and debugging in IDA doesn't work neither because of all this .NET stuff... :-(

Don't you have somer loader, which is known working for .NET applications?

Ember 08-05-2012 09:19

Quote:

Originally Posted by aldente (Post 79908)
ResumeThread() has to be called with pi.hThread...

Sorry yes that was a typo. Are you on a x64 system? If the .NET metadata in your target executable is not marked as 32bit required then it will spawn as a 64bit process. This will result in failure. You will need to compile the DLL as a 64bit DLL to inject.

I have successfully got the DLL working in your test app, spoofing processor ID with my hook + this loader: http://code.google.com/p/injector/

Command line: newloaderv4.1.exe --lib "E:\Downloads\WmiSpoof.dll" --launch Test.exe

http://i.imgur.com/2rqsj.png

aldente 08-05-2012 18:47

1 Attachment(s)
Yes, I am on a x64 system...

I just tried the loader you mentioned in a virtual machine (x86), but without any success either...

Code:

newloaderv4.1.exe --lib WmiSpoof_x86_StaticRuntime.dll --launch Test.exe
The loader starts Test.exe, but the loader console window stays open (nothing is shown after "Email: [email protected]").
When I close Test.exe, the loader outputs:
Code:

Error: [@InjectLibraryW] Unknown Error (LoadLibraryW).
Error: [@SuspendResumeProcess] NtResumeProcess. [NtStatus: 0xC000010A] [LastErro
r: 6]
Error: [@InjectLibraryW] Could not resume process.
Error: [@commandline_parser] Injection failed.

How did you build your DLL?
I built it Non-Unicode with static runtime ('release' mode) with MSVC 2010.
I tried other options as well, neither worked (dynamic runtime, Unicode).

Does my attached DLL work for you?

(Thanks for your patience, by the way!)

Ember 08-06-2012 02:23

Yes, it works when I run the injector from administrative cmd line and modify the exe to have 32bit required in the .NET metadata header.

aldente 08-06-2012 04:52

So why doesn't it work for me?

I tried to run it on Windows XP x86, as the Administrator user... No luck!

What's your version of the .NET Framework? Maybe that's the difference...

Ember 08-06-2012 06:59

You are hooking a non-framework native module. I do not know what to tell you if it does not work on XP (unless you are lacking runtimes for VS2010 or something, even though it does not import it). I am on Windows 7 Ultimate x64 SP1 with all updates and it works fine, and it worked when I was on XP SP3 as well.

When I compile modules like that I link against the latest WDK libs and headers to cut down on size and importing anything from the new runtimes. It will link against msvcrt.dll instead.

Perhaps you can PM me and tell me what you want to spoof your processor ID to and I can compile one in my environment and you can try it.

aldente 08-07-2012 01:32

I tested the exact same binaries on a third machine, and these are the results:

Win7 SP1 x64: Does not work
WinXP SP3 x86: Does not work
Win7 SP1 x86: Works

Strange, but now I have at least one working system. I'll do some testing to find out why it doesn't work on the other ones.

Thanks for all your help!


All times are GMT +8. The time now is 10:41.

Powered by vBulletin® Version 3.8.8
Copyright ©2000 - 2026, vBulletin Solutions, Inc.
Always Your Best Friend: Aaron, JMI, ahmadmansoor, ZeNiX