Dll Injection - Vista + UAC

c++ / delphi package - dll injection and api hooking

Is UAC a bad invention?

Yes
9
47%
No
10
53%
 
Total votes: 19

jonny_valentine
Posts: 109
Joined: Thu Dec 30, 2004 9:59 pm
Location: UK

Dll Injection - Vista + UAC

Post by jonny_valentine »

Hi all,

Well, UAC is enabled and even the new DLLInjector.exe application does not appear to inject the .dll into any process.
I try running as normal user and using RunAs to gain admin rights for the injector, both say, 'you must be an administrator to inject'.

I check with ProcessXP from sysinternals and the dll is not there in any case. I use InjectLibrary() call in my own app and it always returns 0... even when called from an NT Service.

edit: My NT Service calls InjectLibrary to inject my dll. Its called with these parameters: ALL_SESSIONS & (~CURRENT_PROCESS), L"hook.dll"

The return value is 0 and not -1 like normal. With AUC disabled this works and on winxp it works.

Any ideas?
Last edited by jonny_valentine on Tue Dec 04, 2007 3:47 pm, edited 1 time in total.
Absolute_Zero
Posts: 39
Joined: Fri Jan 26, 2007 11:12 am

Post by Absolute_Zero »

Injection works for me from a service.
LeVuHoang
Posts: 131
Joined: Fri Oct 22, 2004 8:37 am

Post by LeVuHoang »

Let give it Administrator rights (right-click, choose "Run as Administrator") or you will need to request the service.
madshi
Site Admin
Posts: 10766
Joined: Sun Mar 21, 2004 5:25 pm

Post by madshi »

Basically the needed access rights are identical to XP: In both OSs you need admin rights for system wide injection. However, in Vista when UAC is enabled even admin users don't have admin rights by default. So you need to right click your exe and choose "run as administrator" (as LeVuHoang has already said). Alternatively you can add a manifest to your exe which will tell Vista that your app needs admin rights. If you do that, you don't need to do the "run as admin" step, anymore. However, the end user will still have to confirm the operation. If you don't like all this you need to inject from a service (see HookProcessTermination demo).

One other thing to look for is that the hook dll needs enough NTFS rights or else it might not be injected into all processes successfully. Vista is a bit more strict there than XP was.
aiwnjoo
Posts: 52
Joined: Tue Mar 06, 2007 1:06 pm

Post by aiwnjoo »

Code: Select all

void Inject(HWND hWnd, char* strDll) 
{
GetWindowThreadProcessId(hWnd, &pId);
HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pId);
LPVOID lpRemoteAddress = VirtualAllocEx(hProcess, NULL, strlen(strDll), MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE);
WriteProcessMemory(hProcess, lpRemoteAddress, (LPVOID)strDll, strlen(strDll), NULL);
CreateRemoteThread(hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)GetProcAddress(GetModuleHandle("Kernel32"), "LoadLibraryA"), lpRemoteAddress, 0, NULL);

}  
Nico Bendlin
Posts: 46
Joined: Fri Apr 28, 2006 1:17 pm

Post by Nico Bendlin »

aiwnjoo wrote:CreateRemoteThread(...)
The API does not create threads in other sessions (this behavior is documented in MSDN).

One way to load a library into a process of another session is: Create a suspended thread (ntdll!RtlCreateUserThread) at kernel32!ExitThread, schedule an asynchronous procedure call (ntdll!NtQueueApcThread) at kernel32!LoadLibraryEx, resume the thread (kernel32!ResumeThread - this executes the pending APC), and wait for the end of the thread (kernel32!WaitForSingleObject). APCs do not return a value - therefore the return value of kernel32!LoadLibraryEx is lost. There is much more work required to use this method in the exact same manner as CreateRemoteThread(LoadLibrary) (includes reading the PEB’s loader structures).

Other hints:
  • Never ever use CreateRemoteThread on a target process that differs in 'bitness' (kernel32!IsWow64Process). On some Windows versions this freezes your calling thread.
  • Dynamically determine the kernel32’s image base (might not be loaded at all).
As you can see, it isn’t that simple...
madshi
Site Admin
Posts: 10766
Joined: Sun Mar 21, 2004 5:25 pm

Post by madshi »

Nico Bendlin wrote:Never ever use CreateRemoteThread on a target process that differs in 'bitness' (kernel32!IsWow64Process). On some Windows versions this freezes your calling thread.
Can you give me a bit more information about that? I'm using CreateRemoteThread from within a 64bit process to inject dlls into 32bit processes and it seems to work well for me in Vista64 and XP64. Am I missing something? Thanks!
LooneyLynn
Posts: 17
Joined: Fri Jul 11, 2008 11:05 am

Post by LooneyLynn »

>I'm using CreateRemoteThread from within a 64bit process to inject dlls into 32bit processes

That won't work... The WOW64 prevents such operations... I can't image that "it worked well on Vista64" because it doesn't for me ^^...

>CreateRemoteThread does not create threads in other sessions (this behavior is documented in MSDN).

Thats simply wrong; BTW just because something is stated in MSDN it doesn't have to be true ^^... You have to call it from within a system service and it will work well! But I agree in case of Windows Vista SP1 and Windows Server 2008 SP1. There it won't work anymore and you will have to switch to NtCreateThreadEx() which is available only since Vista...

> Dynamically determine the kernel32’s image base (might not be loaded at all)

You know any process where this is not the case??

regards
chris
iconic
Site Admin
Posts: 1067
Joined: Wed Jun 08, 2005 5:08 am

Post by iconic »

@LooneyLynn
> Dynamically determine the kernel32’s image base (might not be loaded at all)
You know any process where this is not the case??
System (PID 4) loads NO DLLs yet you can still obtain a process handle to dump it's memory etc. so I mentioned this, don't ask me how you can obtain a handle and work with the system process just download my tool kX-Ray and find out for yourself as you can see it can dump its memory just fine so I would consider this a process that escapes what you claim as all processes must load kernel32 considering it's not always true. With technical details aside, SMSS.exe (Windows NT Session Manager) does NOT load kernel32.dll either, it loads ntdll.dll only but since most kernel32.dll calls end up in ntdll.dll anyhow it doesn't need to load kernel32.dll so there's a more real world scenario for you.

So yes, Nico was right in saying that it's good to determine the image base of kernel32.dll dynamically from process to process to play it extra safe. The fact is in NT-based OS the image base should be the same from process to process, the same applies to user32.dll and ntdll.dll assuming they're loaded in a process. Only a relocation would cause the base address to differ and this is certainly not common since these DLLs are loaded VERY early.
LooneyLynn
Posts: 17
Joined: Fri Jul 11, 2008 11:05 am

Post by LooneyLynn »

I know from my CreateAndInject() method that every normal process that can be started with CreateProcess() will always have kernel32.dll loaded into memory without having any user specific code executed. So it seems to be enforced by windows which is obviously clear, because otherwise you wouldn't even be able to load any DLL.

But okay, there might be exceptions with Microsoft's raw system services which are managing processes itself. Maybe just don't hook them, because this won't be the only applying exception ;-)
iconic
Site Admin
Posts: 1067
Joined: Wed Jun 08, 2005 5:08 am

Post by iconic »

Maybe just don't hook them, because this won't be the only applying exception
Well, the problem with this is (madCodeHook is affected by this too), let's say you made SMSS an exception, as in do not inject into this process and hook for example. The idea of system-wide injection is to force every running process on NT (minus System of course) to load your code. If you hooked let's say NtTerminateProcess() to "protect" your application other "normal" processes wouldn't be able to terminate your process via calling this API in a conventional manner (standard API calling and no INT 0x2E stuff) but SMSS.exe could call NtTerminateProcess() on your process since it loads ntdll.dll and shatter your entire "protection" logic.

Obviously, this isn't a real world scenario since SMSS would never behave this way but I think a lot of system wide injection authors may be displeased with this exception because I can think of "real world" scenarios to where one may want to hook an ntdll API that is most likely called by SMSS so I truly feel that in this case you're not getting the whole system wide picture of API monitoring. Of course this is simply my humble opinion and I understand that madCodeHook will not inject into SMSS even with the flags SYSTEM_PROCESSES specified within InjectLibrary() because it doesn't load certain DLLs, primarily kernel32, and madCodeHook must be "stable" for the masses so it's well understood and I respect that. I can't really complain however, Microsoft's own documented ways to inject DLLs (SetWindowsHookXx variants and the AppInit_DLLs registry key) methods both require the target process (process that is loading your DLL) to link with user32.dll so obviously SMSS is an instant exception here as well ;)

--Iconic
LooneyLynn
Posts: 17
Joined: Fri Jul 11, 2008 11:05 am

Post by LooneyLynn »

Okey I got your idea but user mode hooking isn't that applicable for system wide hooking... Maybe you should consider kernel mode hooking or Vista Security API for such tasks ;-)...

You will never be able to get "protection" secure in any way if you use user mode hooking...

regards
chris
iconic
Site Admin
Posts: 1067
Joined: Wed Jun 08, 2005 5:08 am

Post by iconic »

Agreed. The idea of usermode hooking for security reasons without also hooking kernel APIs is not very sound in my honest opinion. Then again, hooking is not a new concept at all and very detectable, hook removal can also be fairly trivial. If you'd like you can check out a project that I am undertaking called kX-Ray located here. Both ring3 and ring0 API hooks can be removed in a stable manner. Of course, the purpose of my tool is to break rootkits or other malware that could pose a direct threat to your system. One thing to note about the Ring3 hooks section of kX-Ray is this... at the moment only ntdll, user32 and kernel32 APIs are checked for the presence of hooks in all processes and only inline hooks are detected (code overwriting methods = inline). No support yet for IAT/EAT hooks but will add later on when I have the time.

kX-Ray Build 56 is the most recent release I have made, the only reason I have Build 54 still listed on this forum is because it only adds 1 new option and that's a "Nullify Hook" option. The option writes a retn CPU instruction (0xC3) at the hook callback's function prologue in order to stomp it out so there's no need to "unhook" it. It's just a back up or alternative to unhooking, of course that works perfectly okay too. If you want to see this build just change the filename in the download link to 56 instead of what's shown as 54.

I'm also working on a process manipulation library that is pretty nice considering it's completely raw and all exported functions do not use windows APIs internally whatsoever, making the hooking of underlying internal aspects of the exported function impossible from ring3. Some exported functions are not exposed by Windows so the void for some useful process functions are filled on top of the fact that others are emulated. I'll most likely share the DLL or static .DCU file here in the Fun Talk area when I have time to complete it.

--Iconic
LooneyLynn
Posts: 17
Joined: Fri Jul 11, 2008 11:05 am

Post by LooneyLynn »

Is there any source code out for this??? But nice idea if it works... Your Ring 0 protection is for pre-Vista? Something like PatchGuard ^^?

Maybe you want to look at http://www.codeplex.com/easyhook to see my hooking library ^^...

I am thinking of adding Ring 0 hooking support for PatchGuard 2 and 3 to EasyHook. But I am not really sure if there is an audience for kernel hooking (see my other thread in this forum...). What do you think; you seem to be interested in things like that...? Having the possibility to hook all PASSIVE_LEVEL Ring 0 APIs with usual NET code from user mode? I think that would be a nice twist ;-)...


regards
chris
iconic
Site Admin
Posts: 1067
Joined: Wed Jun 08, 2005 5:08 am

Post by iconic »

Is there any source code out for this?
No, due to the fact that it's security software and some things that are undocumented need to remain unknown to the general public.
But nice idea if it works...
Of course it does :D kX-Ray functions similarly to other anti-rootkit tools (Some IceSword features, Rootkit Unhooker features etc.)
Your Ring 0 protection is for pre-Vista?
Yes. Windows 2000, XP/MCE and Windows 2003. The 2 latest builds are also compatible with the aforementioned except for the fact that I have seriously improved the hidden process detection and haven't had the time to use the same method in any other OS aside from XP, so the 2 newest builds I lock down to XP only until I can extend support for this.
Something like PatchGuard ^^?
Patch Guard only detects kernel API modifications in x64 OS if I am not mistaken and even when it does, it will issue a bug check if I recall. So in this regard, kX-Ray is very much different and again it functions much like your public anti-rootkit tools do which will allow you to actually unhook the API without causing a bug check to be issued.

I think that hooking kernel functions in general is kernel mode perversion and should be avoided. kX-Ray itself sets no API hooks at all in usermode nor kernel mode. No code injection is used either. In this respect it is not by any means confused with malware. The problem with writing any code hook library (your library, uall's collection, madCodeHook, afxcodehook, EliCZ's package etc) is once public a lot of children will use this library for bad intentions and that may cause your package as a whole to be labeled as malware-oriented.

If you were to support kernel hooking, I'd suggest limiting which APIs can be hooked with your library, as some will without a doubt be hooked only for bad purposes. Just my 2 cents...
Post Reply