Page 1 of 1

InjectLibraryW() between sessions in windows 7/8?

Posted: Tue Aug 19, 2014 9:01 pm
by TCS
Hey,

I am trying to call "InjectLibraryW()" from windows service to a 32bit application in another session, but the function fails, and GetLastError() return ERROR_SUCCESS.
Is it even possible? or do I have to create a new process in the other session?


Thanks in advance!

Re: InjectLibraryW() between sessions in windows 7/8?

Posted: Tue Aug 19, 2014 9:10 pm
by iconic
Injecting from a service will work for any process in any session (assuming it's not smss or a Windows protected process such as audiodg.exe which are special exceptions). Where is your DLL located on disk, is it accessible to all processes i.e> C:\? Lastly, are you injecting with special flags or injecting into a single process? What does your InjectLibraryW() call look like? Is this Delphi or c/c++?

--Iconic

Re: InjectLibraryW() between sessions in windows 7/8?

Posted: Wed Aug 20, 2014 7:15 am
by TCS
Sorry it took me a while to answer!

First of all, I had a little mistake, the error returns is ERROR_INVALID_PARAMETER. I guess I am missing something :-( .

The DLL is located on the disk, and I am giving the function the full path:
c:\program files\....\injectee.dll

The HANDLE to the injected process (which is explorer.exe) is valid with PROCESS_ALL_ACCESS permissions.
The code I am executing is (C++):

Code: Select all

BOOL is_injected = InjectLibraryW(fullpath_dll.c_str(), (HANDLE)proc_handle, 10000);
is_injected is FALSE.

I should also point out that I am not using the injection driver (it is not loaded).

Thanks again!

Re: InjectLibraryW() between sessions in windows 7/8?

Posted: Wed Aug 20, 2014 2:45 pm
by TCS
Just an update, I am getting "ERROR_INVALID_PARAMETER" not "ERROR_SUCCESS".

Re: InjectLibraryW() between sessions in windows 7/8?

Posted: Wed Aug 20, 2014 8:33 pm
by madshi
Some questions:

(1) Have you called InitializeMadCHook() before calling InjectLibraryW()?
(2) How are you testing is_injected for true/false? Some people have been using "if (is_injected == FALSE)" in the past, which is not the correct way to check BOOL values, so I'm asking just to be safe.
(3) Try giving the hook dll read/execute NTFS rights for "Everyone", just to make sure it's not an NTFS security rights problem.
(4) Try injecting a dll which is already loaded, e.g. kernel32.dll. Does that return succeess or does that also fail?

Re: InjectLibraryW() between sessions in windows 7/8?

Posted: Thu Aug 21, 2014 5:10 pm
by TCS
(1) Have you called InitializeMadCHook() before calling InjectLibraryW()?
Yes, not necessarily in the same thread that is doing the actual inject. Is it important?
I tried to call InitializeMadCHook() in the specific injecting thread and it didn't help much.

(2) How are you testing is_injected for true/false? Some people have been using "if (is_injected == FALSE)" in the past, which is not the correct way to check BOOL values, so I'm asking just to be safe.
Is that okay?

Code: Select all

BOOL is_injected = InjectLibraryW(fullpath_dll.c_str(), (HANDLE)proc_handle, 10000);
		
// if injection itself fails
if(!is_injected)
{
	// handle error
}
(3) Try giving the hook dll read/execute NTFS rights for "Everyone", just to make sure it's not an NTFS security rights problem.
Done. Didn't help.

(4) Try injecting a dll which is already loaded, e.g. kernel32.dll. Does that return succeess or does that also fail?[/quote]
Tried injecting kernel32.dll and got the same result, last error is 0x57...

Important:
Doing these tests I noticed that the injection does succeed (The DLL is being loaded), but the function still returns FALSE. I have to know if the DLL got injected successfully (I can think of workarounds, but I prefer the "correct" way). Looks like I am missing something out.

Re: InjectLibraryW() between sessions in windows 7/8?

Posted: Thu Aug 21, 2014 5:24 pm
by madshi
InitializeMadCHook() doesn't have to be called in the same thread, it just needs to be completed before you use madCodeHook in any thread.

Your "if" statement should work just fine.

Try calling EnableAllPrivileges() before calling InjectLibraryW(). Does that help?

Code: Select all

void WINAPI EnableAllPrivileges( void )
{
    HANDLE hToken;


    if (OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken))
    {
        __try
        {
            DWORD returnLength;
            GetTokenInformation(hToken, TokenPrivileges, NULL, 0, &returnLength);
            if (returnLength != 0)
            {
                TOKEN_PRIVILEGES *pTokenPrivileges = (TOKEN_PRIVILEGES *) LocalAlloc(LPTR, returnLength*2);
                if (GetTokenInformation(hToken, TokenPrivileges, pTokenPrivileges, returnLength * 2, &returnLength))
                {
                    LUID backup;
                    if (!LookupPrivilegeValue(NULL, SE_BACKUP_NAME, &backup))
                    {
                        backup.HighPart = 0;
                        backup.LowPart = 0;
                    }
                    LUID restore;
                    if (!LookupPrivilegeValue(NULL, SE_RESTORE_NAME, &restore))
                    {
                        restore.HighPart = 0;
                        restore.LowPart = 0;
                    }
                    LUID owner;
                    if (!LookupPrivilegeValue(NULL, SE_TAKE_OWNERSHIP_NAME, &owner))
                    {
                        owner.HighPart = 0;
                        owner.LowPart = 0;
                    }
                    // Update all the privileges to enable except backup and restore
                    //      Enabling backup/restore privileges breaks Explorer's Samba support
                    for (int i = 0; i < (int) pTokenPrivileges->PrivilegeCount - 1; i++)
                    {
                        if ( ( (pTokenPrivileges->Privileges[i].Luid.HighPart !=  backup.HighPart) ||
                            (pTokenPrivileges->Privileges[i].Luid.LowPart  !=  backup.LowPart)     ) &&
                            ( (pTokenPrivileges->Privileges[i].Luid.HighPart != restore.HighPart) ||
                            (pTokenPrivileges->Privileges[i].Luid.LowPart  != restore.LowPart)     ) &&
                            ( (pTokenPrivileges->Privileges[i].Luid.HighPart !=   owner.HighPart) ||
                            (pTokenPrivileges->Privileges[i].Luid.LowPart  !=   owner.LowPart)     )    )
                        {
                            pTokenPrivileges->Privileges[i].Attributes = pTokenPrivileges->Privileges[i].Attributes | SE_PRIVILEGE_ENABLED;
                        }
                    }
                    AdjustTokenPrivileges(hToken, FALSE, pTokenPrivileges, returnLength, NULL, NULL);
                }
                LocalFree(pTokenPrivileges);
            }
        }
        __finally
        {
            CloseHandle(hToken);
        }
    }
}
And how long does InjectLibraryW() take until it returns? Maybe it gets stuck for the full timeout duration of 10 seconds and then returns with a failure result? Or does it return sooner than that?

Re: InjectLibraryW() between sessions in windows 7/8?

Posted: Thu Aug 21, 2014 6:56 pm
by TCS
(1) EnableAllPrivileges() did not work
(2) It does not wait all 10 seconds (it doesn't get stuck inside).

Re: InjectLibraryW() between sessions in windows 7/8?

Posted: Thu Aug 21, 2014 7:16 pm
by madshi
Can you create a little demo project for me which reproduces the problem? That would be great! You can hardcode the process ID if that makes your life easier. I can modify the process ID when compiling and testing here. I'll be on vacation the next week, though, so I won't be able to look into this until the week after that.

Re: InjectLibraryW() between sessions in windows 7/8?

Posted: Sun Aug 24, 2014 9:55 am
by TCS
Okay, I found the problem, but not the solution...

I have a driver that notifies my service when a process has been created. Once I get this message I inject the library into the process.
If I inject at the moment of the notification I get that error, if I wait a bit, I don't.

Is there a way to fix this (lets recall that the injection works!) ???

Re: InjectLibraryW() between sessions in windows 7/8?

Posted: Thu Sep 04, 2014 9:54 am
by madshi
Is it possible that the new process isn't really "known" in user land yet at the moment when you try to inject? If your driver signals the new process to user land very quickly, maybe this could explain this problem? I'm not totally sure, though.

Is there a reason you're not using the madCodeHook driver? It injects the dll from within the driver, which works around any such issues as mentioned above.