【问题标题】:Failing dll injectiondll注入失败
【发布时间】:2011-01-28 08:55:30
【问题描述】:

我正在为我的网络制作安全程序。其中一个实例是检查和监控调用了哪些 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;
        }
    }
}

【问题讨论】:

  • 我想编辑您的问题以将您的代码直接添加到问题中,但它太长了!你真的希望有人审查你的整个代码吗?!
  • 不,我不是,事实上,在我尝试将代码注入系统进程之前,代码工作正常,没有错误也没有问题。在其他应用程序中它工作正常。
  • 问题是这个问题在过去的bin早已消失之后仍然会在这里(并且可以通过谷歌搜索)。
  • @Unknown:pastbin 上的代码示例不会永远存在。当代码示例将在几天/几个月/几年内消失时,这个问题将保留,但将包含一个死链接。
  • 我现在可以将它们添加到我的帖子中,问题是我第一次发布此问题时无法使用工具栏。

标签: c++ windows dll code-injection


【解决方案1】:

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

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

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

4) 我假设执行注入的进程和您要注入的进程都是相同的架构,您不是在 x64 上运行 x86 exe 并希望注入 x64 exe?

【讨论】:

  • 1:我运行的 Windows 版本比 Vista 晚,但我应该如何处理呢?我读到可以使用 NTCreateThread 将代码注入受保护的进程(回答 3)也许这种方式不可能......但话又说回来,我如何让我的代码在受保护的进程中运行。你有什么建议吗?还有为什么它不能在 windows xp 中工作?
  • 我建议你让它工作,首先在 XP 上使用 CreateRemoteThread()。我认为它对于“正常”过程可靠吗?问题 4 的答案如何?修复 3 中详述的错误后,代码的工作方式是否有所不同?
  • 我已经在调试器中查看了它,分配不是问题,一切都适合一个不错的 0 初始化缓冲区。 dll 是 32 位的,可以在 x64 和 x86 系统上正常工作,但不能在系统进程上工作,但是我会仔细检查
  • @Unknown,那么目前的状态是什么?您是否检查过建议 #4,即您是否尝试将 x32 dll 放入 x64 进程(这是错误的)?
  • 我知道这是一个旧帖子,但你找到答案了吗?
【解决方案2】:

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

  1. 将注入器和注入 dll 编译为 x64。
  2. 使用 RtlCreateUserThread 代替 CreateRemoteThread 和 NtCreateThreadEx(均失败)。

【讨论】:

    【解决方案3】:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-08-08
      • 1970-01-01
      • 2020-08-08
      • 1970-01-01
      • 1970-01-01
      • 2011-10-17
      • 2010-12-06
      相关资源
      最近更新 更多