C++ & Windows - Dll Injection by Ntcreatethreadex Function Is Not Worked

I have written DLL injector. I used CreateRemoteThread to inject my DLL to process and all was good. Now i am trying inject DLL to process by undocumented function - NtCreateThreadEx. I have written injector but he is not working.

When i use 32 bit injector to inject 32 bit DLL to 32 bit process all working good. Problem is when i use 64 bit injector to inject 64 bit DLL to 64 bit process.

My DLL code:

#include <windows.h>

///Compilation with option -m64

extern "C" BOOL __stdcall DllMain(HMODULE hDLL, DWORD Reason, LPVOID Reserved)
{
   MessageBox( NULL, "MESSAGE FROM 64 BIT DLL", "Lorem ipsum", MB_ICONINFORMATION | MB_OKCANCEL );
   return 0;
}

My TestApp code

#include <iostream>
#include <windows.h>
int main()
{

   std::cout << " Lorem  IPSUM" << std::endl;

   //HMODULE HDLL = LoadLibraryA("dll64.dll");

   //std::cout << "Error: " << GetLastError() << std::endl;
   while(1)
   {
       std::cout << "petla" << std::endl;
       Sleep(5000);
   }
   return 0;
}

My injector code:

#include <iostream>
#include <string>
#include <windows.h>
///  64 bit OS - Windows 7
///=====================
///* In this same user context ("User")
///TYPE OF(32/64 bits)
///INJECTOR===DLL===PROCESS===RESULT
///   32      32     32      -SUCESS
///   64      64     64      -FALIED (error: 1300)
                    //Handle to process,Address of'LoadLibraryA',see DllAdr
///TO DO
///* Inject DLL to process from normal user context ("User") to higher user context (Zarzadca)
///* Inject DLL to process from normal user context ("User") to other normal user context (User1)


HANDLE NtCreateThreadEx(HANDLE hProcess,LPVOID lpBaseAddress,    LPVOID lpSpace);
int privileges();

int main()
{
    int PIDOfProcess = 0;
    std::string pathToDLL = "dll64.dll\0";  ///find DLL in local directory
    DWORD PID        = (DWORD)PIDOfProcess; ///PID
    HANDLE HProcess  = NULL;                ///Handle to process
    LPVOID LibAddr   = NULL;                ///Address of procedure 'LoadLibraryA'
    LPVOID DllAdr    = NULL;                ///Address of memory in other process
    HANDLE hThread   = NULL;                ///Handle to remote thread
    int WirteStatus  = 0;                   ///Status of writing to memory of other process

    std::cout << "ptr size = " << sizeof(void *) << std::endl;

    std::cout << "Get PID of process" << std::endl;
    std::cin >> PIDOfProcess;
    PID = (DWORD)PIDOfProcess;

    ///std::cout << "Get path to DLL" << std::endl;
    ///std::cin >> pathToDLL;

    if( privileges() != 0 )
    {
        std::cout <<  "Cannot get the right privileges" << std::endl;
    }

    HProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, PID);
    if(HProcess == NULL)
    {
        std::cout << "Could not find process" << std::endl;
        std::cout << GetLastError() << std::endl;
        system("pause");
        return GetLastError();
    }

    DllAdr = (LPVOID)VirtualAllocEx(HProcess, NULL, pathToDLL.size() +1, MEM_RESERVE|MEM_COMMIT, PAGE_EXECUTE_READWRITE);
    if(DllAdr == NULL)
    {
        std::cout <<"Can not allocate memory." << std::endl;
        std::cout << GetLastError() << std::endl;
        system("pause");
        return GetLastError();
    }

    WirteStatus = WriteProcessMemory(HProcess, (LPVOID)DllAdr, pathToDLL.c_str() ,pathToDLL.size()+1, NULL);
    if(WirteStatus == 0)
    {
        std::cout << "Could not write to process's address space" << std::endl;
        std::cout << GetLastError() << std::endl;
        system("pause");
        return GetLastError();
    }

    LibAddr = (LPVOID)GetProcAddress(GetModuleHandle("kernel32.dll"), "LoadLibraryA");
    if(LibAddr == NULL)
    {
        std::cout << "Unable to locate LoadLibraryA" << std::endl;
        std::cout << GetLastError() << std::endl;
        system("pause");
        return GetLastError();
    }

    hThread = NtCreateThreadEx(HProcess,LibAddr,DllAdr);
    ///DWORD threadId = 0;
    ///hThread = CreateRemoteThread(HProcess, NULL, 0, (LPTHREAD_START_ROUTINE)LibAddr, DllAdr, 0, &threadId);
    if(hThread == NULL)
    {
        std::cout << "Error: ";
        std::cout << GetLastError() << std::endl;
        system("pause");
        return GetLastError();
    }
    system("pause");
}
HANDLE NtCreateThreadEx(HANDLE hProcess,LPVOID lpBaseAddress,LPVOID lpSpace)
{
    ///The prototype of NtCreateThreadEx from undocumented.ntinternals.com
    typedef DWORD (WINAPI * functypeNtCreateThreadEx)(
        PHANDLE                 ThreadHandle,
        ACCESS_MASK             DesiredAccess,
        LPVOID                  ObjectAttributes,
        HANDLE                  ProcessHandle,
        LPTHREAD_START_ROUTINE  lpStartAddress,
        LPVOID                  lpParameter,
        BOOL                    CreateSuspended,
        DWORD                   dwStackSize,
        DWORD                   Unknown1,
        DWORD                   Unknown2,
        LPVOID                  Unknown3
    );

    HANDLE                      hRemoteThread           = NULL;
    HMODULE                     hNtDllModule            = NULL;
    functypeNtCreateThreadEx    funcNtCreateThreadEx    = NULL;

    //Get handle for ntdll which contains NtCreateThreadEx
    hNtDllModule = GetModuleHandle( "ntdll.dll" );
    if ( hNtDllModule == NULL )
    {
        std::cout << "Cannot get module  ntdll.dll  error: " << GetLastError() << std::endl;
        return NULL;
    }
    funcNtCreateThreadEx = (functypeNtCreateThreadEx)GetProcAddress( hNtDllModule, "NtCreateThreadEx" );
    if ( !funcNtCreateThreadEx )
    {
        std::cout << "Cannot get procedure address  error: " << GetLastError() << std::endl;
        return NULL;
    }
    funcNtCreateThreadEx( &hRemoteThread,  /*GENERIC_ALL*/0x1FFFFF, NULL, hProcess, (LPTHREAD_START_ROUTINE)lpBaseAddress, lpSpace, FALSE, NULL, NULL, NULL, NULL );
    std::cout << "Status NtCreateThreadEx  " << GetLastError()       << std::endl;
    std::cout << "hRemoteThread:           " << hRemoteThread        << std::endl;
    std::cout << "hNtDllModule:            " << hNtDllModule         << std::endl;
    std::cout << "funcNtCreateThreadEx:    " << funcNtCreateThreadEx << std::endl;
    return hRemoteThread;
}
int privileges()
{
  HANDLE Token;
  TOKEN_PRIVILEGES tp;
  if(OpenProcessToken( GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,&Token)) ///It opens the access token associated with a process.
  {
    LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &tp.Privileges[0].Luid);///Function retrieves the locally unique identifier (LUID)

    tp.PrivilegeCount = 1;
    tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;

        if (AdjustTokenPrivileges(Token, false, &tp, sizeof(tp), NULL, NULL) != 0)///Function enables or disables privileges in the specified access token.
        {
            return 0; //OK
        }
   }
   return 1;
}

When i use 64 bit injector to inject 64 bit DLL to 64 bit process, function NtCreateThreadEx return code of error 1300 and my DLL doesn't execute. I use to compile on 64 bit architecture: g++ (tdm64-1) 5.1.0 I am working on Virus Windows 7 64 bit as normal user. Run as administrator doesn't help. I dont know why it doesn't work, what i doing wrong.

PS: When i use 32 bit injector to inject 32 bit DLL to 32 bit process, function NtCreateThreadEx return code of error 1300 but my DLL execute. In 32 bit version TestApp GetLastError return code 1114. I use to compile on 32 bit architecture: g++ (tdm-2) 4.8.1

I include image

I based on:
 - Dll Injection (polish)
====
 
- Ask about NtCreateThreadEx in Window 7 x64!
=====
 Code Injections [beginner and advanced]
=====
 Remote Thread Execution in System Process using NtCreateThreadEx for Vista & Windows7
=====
 Systemowe kody błędów (1300-1699) (polish)


Link to my topic on other forum (polish): 
3

1 Answer

My injector is working when i use him to inject DLL to other process in my user space (i am working as normal user) but it is not working when i am injecting to csrss.exe (or other system's process). I get code of error 5 - Access Denied, when i run injector as Administrator i get code of error 0 (SUCCESS?) but my DLL not aborting process ( abort() - i try do BSoD).

I read about Session Separation and i think it is reason of my problem so i have one question: How i can hacking Windows :) If it is imposibble can i inject DLL as normal user to proces in Administrator context (or other normal user's process) ?

1

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Alexander Ross

Alexander Ross

Gaming, Esports & Interactive Media Writer

Alexander Ross has covered the video game industry for a decade, writing deep dives on game design, esports tournaments, VR developments, and gaming culture.

Share this article
Twitter Facebook Pinterest