失败的dll注入

时间:2011-01-28 08:55:31

标签: c++ windows dll code-injection

我正在为我的网络制作安全程序。其中一个例子是检查和监控api和库的调用。这样做的dll和随之而来的程序已经完成了。但是有一个问题我似乎无法修复。

尝试使用NtCreateThreadEx将我的dll注入系统进程(例如explorer.exe,我的主要测试系统进程)时,我得到了返回值:C0000022,这意味着类似于:Status_Access_Denied(它在NTSTATUS中返回,但DWORD会这样做)

我不知道该怎么做,我是以管理员身份运行,我提出了我的权限,并使用了正确的功能,但仍然得到c0000022

这是我用来注入的代码

#include "main.h"

typedef DWORD NTSTATUS;

struct NtCreateThreadExBuffer{
    ULONG Size;
    ULONG Unknown1;
    ULONG Unknown2;
    PULONG Unknown3;
    ULONG Unknown4;
    ULONG Unknown5;
    ULONG Unknown6;
    PULONG Unknown7;
    ULONG Unknown8;
};


typedef NTSTATUS (WINAPI *LPFUN_NtCreateThreadEx)
(
 OUT PHANDLE hThread,
 IN ACCESS_MASK DesiredAccess,
 IN LPVOID ObjectAttributes,
 IN HANDLE ProcessHandle,
 IN LPTHREAD_START_ROUTINE lpStartAddress,
 IN LPVOID lpParameter,
 IN BOOL CreateSuspended,
 IN ULONG StackZeroBits,
 IN ULONG SizeOfStackCommit,
 IN ULONG SizeOfStackReserve,
 OUT LPVOID lpBytesBuffer
);

using namespace std;

//#define CREATE_THREAD_ACCESS (PROCESS_CREATE_THREAD | PROCESS_QUERY_INFORMATION | PROCESS_VM_OPERATION | PROCESS_VM_WRITE | PROCESS_VM_READ)
#define CREATE_THREAD_ACCESS ( PROCESS_ALL_ACCESS )

BOOL LoadDll(char *procName, char *dllName);
BOOL InjectDLL(DWORD dwProcessID, char *dllName);

BOOL LoadDll(char *dllName, DWORD dwProcID){

    printf("Process Id to Inject: %d",dwProcID);

    if(!dwProcID){
        printf("No vailid PID\n");
        return false;
    }

    FILE* FileCheck = fopen(dllName, "r");

    if(FileCheck==NULL){
        printf("\nUnable to inject %s", dllName);
        return false;
    }

    fclose(FileCheck);


    if(!InjectDLL(dwProcID, dllName)){

        printf("injection failed\n");
        return false;
    } else {
        return true;
    }

}

BOOL InjectDLL(DWORD dwProcessID, char *dllName){

    HANDLE hProc;
    HANDLE hToken;
    char buf[50]={0};
    LPVOID RemoteString, LoadLibAddy;

    if(!dwProcessID)return false;


    HANDLE hCurrentProc = GetCurrentProcess();

    if (!OpenProcessToken(hCurrentProc,TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES,&hToken)){

        printf("OpenProcessToken Error:%d\n", GetLastError());


    } else {

        if (!RaisePrivleges(hToken, (char*)SE_DEBUG_NAME)){

            printf("SetPrivleges SE_DEBUG_NAME Error:%d\n", GetLastError());

        }

    }


    if (hToken)CloseHandle(hToken);

    hProc = OpenProcess(CREATE_THREAD_ACCESS, FALSE, dwProcessID);

    printf("\nHandle to process: %x\n", hProc);

    if(!hProc){

        printf("OpenProcess() failed: %d", GetLastError());
        return false;

    }

    LoadLibAddy = (LPVOID)GetProcAddress(GetModuleHandle("kernel32.dll"), "LoadLibraryA");


    if(!LoadLibAddy){

        printf("GetProcAddress() failed: %d", GetLastError());
        return false;

    }

    RemoteString = (LPVOID)VirtualAllocEx(hProc, NULL, strlen(dllName), MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE);

    if(RemoteString == NULL){

        printf("VirtualAllocEx() failed: %d", GetLastError());
        return false;

    }


    printf("\nRemote address: %x\n", RemoteString);

    if(WriteProcessMemory(hProc, (LPVOID)RemoteString, dllName, strlen(dllName), NULL) == NULL){

        printf("WriteProcessMemory() failed: %d", GetLastError());
        return false;

    }

/*
if(!CreateRemoteThread(hProc, NULL, NULL, (LPTHREAD_START_ROUTINE)LoadLibAddy, (LPVOID)RemoteString, NULL, NULL)){

  printf("CreateRemoteThread() failed: %d", GetLastError());
     return false;

}
*/

    HMODULE modNtDll = GetModuleHandle("ntdll.dll");


    if( !modNtDll )
    {
        printf("n failed to get module handle for ntdll.dll, Error=0x%.8x", GetLastError());
        return 0;
    }

    LPFUN_NtCreateThreadEx funNtCreateThreadEx =
                                                (LPFUN_NtCreateThreadEx) GetProcAddress(modNtDll, "NtCreateThreadEx");


    if( !funNtCreateThreadEx )
    {
        printf("n failed to get function (NTCreateThreadEx) address from ntdll.dll, Error=0x%.8x\nTrying CreateRemoteThread api\n", GetLastError());

        if(!CreateRemoteThread(hProc, NULL, NULL, (LPTHREAD_START_ROUTINE)LoadLibAddy, (LPVOID)RemoteString, NULL, NULL)){

            printf("CreateRemoteThread() failed: %d", GetLastError());
            return false;

        } else {
            printf("CreateRemoteThread success!\n");
            return true;
        }


        return 0;
    }


    NtCreateThreadExBuffer ntbuffer;

    memset (&ntbuffer,0,sizeof(NtCreateThreadExBuffer));
    DWORD temp1 = 0;
    DWORD temp2 = 0;
    HANDLE pRemoteThread = NULL;

    ntbuffer.Size = sizeof(NtCreateThreadExBuffer);
    ntbuffer.Unknown1 = 0x10003;
    ntbuffer.Unknown2 = 0x8;
    ntbuffer.Unknown3 = &temp2;
    ntbuffer.Unknown4 = 0;
    ntbuffer.Unknown5 = 0x10004;
    ntbuffer.Unknown6 = 4;
    ntbuffer.Unknown7 = &temp1;
    ntbuffer.Unknown8 = 0;

    NTSTATUS status = funNtCreateThreadEx(
                                          &pRemoteThread,
                                          0x1FFFFF,
                                          NULL,
                                          hProc,
                                          (LPTHREAD_START_ROUTINE) LoadLibAddy,
                                          (LPVOID)RemoteString,
                                          FALSE, //start instantly
                                          NULL,
                                          NULL,
                                          NULL,
                                          &ntbuffer
                                         );

    printf("NTCreateThreadEx return: %x\n", status);

    // Resume the thread execution

    WaitForSingleObject(pRemoteThread, INFINITE);


    //Check the return code from remote thread function
    DWORD dwExitCode;
    if( GetExitCodeThread(pRemoteThread, (DWORD*) &dwExitCode) )
    {
        printf("\n Remote thread returned with status = %d\n", dwExitCode);
    }


    CloseHandle(pRemoteThread); 


    CloseHandle(hProc);
    return true;

}


BOOL RaisePrivleges( HANDLE hToken, char *pPriv ){

    TOKEN_PRIVILEGES tkp;
    tkp.PrivilegeCount = 1;
    tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
    tkp.Privileges[0].Luid.HighPart = 0;
    tkp.Privileges[0].Luid.LowPart = 0;

    if (!LookupPrivilegeValue(NULL, pPriv, &tkp.Privileges[0].Luid)){

        printf("LookupPrivilegeValue Error:%d\n", GetLastError());
        return FALSE;

    }

    int iRet = AdjustTokenPrivileges(hToken, FALSE, &tkp, 0x10, (PTOKEN_PRIVILEGES)NULL, 0);

    if (iRet == NULL){

        printf( "AdjustTokenPrivileges Error:%d\n", GetLastError());
        return TRUE;

    } else {

        iRet = GetLastError();

        switch (iRet){

            case ERROR_NOT_ALL_ASSIGNED:
                printf("AdjustTokenPrivileges ERROR_NOT_ALL_ASSIGNED\n" );
                return FALSE;

            case ERROR_SUCCESS:
                return TRUE;

            default:
                printf("AdjustTokenPrivileges Unknow Error:%d\n", iRet);
                return FALSE;
        }
    }
}

3 个答案:

答案 0 :(得分:2)

1)如果您在VISTA或更高版本上运行,那么您可能会尝试从“非受保护进程”注入“受保护进程”。请参阅MSDN中的Process Security and Access Rights。非受保护进程无法在受保护进程中创建线程;虽然我必须承认,当您请求不适当的访问权限而不是后续的创建线程调用失败时,我希望打开进程的调用失败。

2)您为什么使用NtCreateThreadEx()而不是简单地调用CreateRemoteThread()

3)这可能不是你问题的原因,但是......你没有为字符串中的空终止符分配内存,你应该分配strlen(dllName) + 1

4)我假设正在进行注入的进程和你注入的进程都是相同的体系结构,你没有在x64上运行x86 exe并期望注入到x64 exe中吗? / p>

答案 1 :(得分:2)

由于很难找到这个问题的正确答案,即使线程陈旧,我也会发帖。 我试图在Win7 x64上注入x64服务并继续遇到同样的问题。我的解决方案是:

  1. 将进样器和进样dll编译为x64。
  2. 而不是CreateRemoteThread& NtCreateThreadEx(均失败)使用RtlCreateUserThread。

答案 2 :(得分:-1)

您必须指定注入的DLL的完整路径,否则将找不到它。