zoukankan      html  css  js  c++  java
  • Ring3下的DLL注入(NtCreateThreadEx + LdrLoadDll方式实现,可以注入系统进程)

    工具介绍及使用请移步:http://blog.csdn.net/sunflover454/article/details/50441014

    本文首发在零日安全论坛:http://www.jmpoep.com/thread-833-1-1.html


    使用NtCreateThreadEx + LdrLoadDll方式实现远程线程注入的特色在于比一般的远程线程注入稳定,可以注入系统进程,服务进程等。


    核心源代码如下,完整源代码,请在文章末尾下载。

    1. //OD跟踪,发现最后调用的是NtCreateThreadEx,所以这里手动调用  
    2. HANDLE Cx64Inject::MyCreateRemoteThread(HANDLE hProcess, LPTHREAD_START_ROUTINE pThreadProc, LPVOID pRemoteBuf)  
    3. {  
    4.         HANDLE hThread = NULL;  
    5.         FARPROC pFunc = NULL;  
    6.         if( IsVistaOrLater())// Vista, 7, Server2008  
    7.         {  
    8.                 pFunc = GetProcAddress(GetModuleHandleW(L"ntdll.dll"), "NtCreateThreadEx");  
    9.                 if( pFunc == NULL )  
    10.                 {  
    11.                         MyOutputDebugStringA("MyCreateRemoteThread() : GetProcAddress("NtCreateThreadEx") 调用失败!错误代码: [%d]", GetLastError());  
    12.                         return NULL;  
    13.                 }  
    14.                 ((_NtCreateThreadEx64)pFunc)(&hThread,0x1FFFFF,NULL,hProcess,pThreadProc,pRemoteBuf,FALSE,NULL,NULL,NULL,NULL);  
    15.                 if( hThread == NULL )  
    16.                 {  
    17.                         MyOutputDebugStringA("MyCreateRemoteThread() : NtCreateThreadEx() 调用失败!错误代码: [%d]", GetLastError());  
    18.                         return NULL;  
    19.                 }  
    20.         }  
    21.         else// 2000, XP, Server2003  
    22.         {  
    23.                 hThread = CreateRemoteThread(hProcess,NULL,0,pThreadProc,pRemoteBuf,0,NULL);  
    24.                 if( hThread == NULL )  
    25.                 {  
    26.                         MyOutputDebugStringA("MyCreateRemoteThread() : CreateRemoteThread() 调用失败!错误代码: [%d]", GetLastError());  
    27.                         return NULL;  
    28.                 }  
    29.         }  
    30.         if( WAIT_FAILED == WaitForSingleObject(hThread, INFINITE) )  
    31.         {  
    32.                 MyOutputDebugStringA("MyCreateRemoteThread() : WaitForSingleObject() 调用失败!错误代码: [%d]", GetLastError());  
    33.                 return NULL;  
    34.         }  
    35.         return hThread;  
    36. }  
    //OD跟踪,发现最后调用的是NtCreateThreadEx,所以这里手动调用
    HANDLE Cx64Inject::MyCreateRemoteThread(HANDLE hProcess, LPTHREAD_START_ROUTINE pThreadProc, LPVOID pRemoteBuf)
    {
            HANDLE hThread = NULL;
            FARPROC pFunc = NULL;
            if( IsVistaOrLater())// Vista, 7, Server2008
            {
                    pFunc = GetProcAddress(GetModuleHandleW(L"ntdll.dll"), "NtCreateThreadEx");
                    if( pFunc == NULL )
                    {
                            MyOutputDebugStringA("MyCreateRemoteThread() : GetProcAddress("NtCreateThreadEx") 调用失败!错误代码: [%d]", GetLastError());
                            return NULL;
                    }
                    ((_NtCreateThreadEx64)pFunc)(&hThread,0x1FFFFF,NULL,hProcess,pThreadProc,pRemoteBuf,FALSE,NULL,NULL,NULL,NULL);
                    if( hThread == NULL )
                    {
                            MyOutputDebugStringA("MyCreateRemoteThread() : NtCreateThreadEx() 调用失败!错误代码: [%d]", GetLastError());
                            return NULL;
                    }
            }
            else// 2000, XP, Server2003
            {
                    hThread = CreateRemoteThread(hProcess,NULL,0,pThreadProc,pRemoteBuf,0,NULL);
                    if( hThread == NULL )
                    {
                            MyOutputDebugStringA("MyCreateRemoteThread() : CreateRemoteThread() 调用失败!错误代码: [%d]", GetLastError());
                            return NULL;
                    }
            }
            if( WAIT_FAILED == WaitForSingleObject(hThread, INFINITE) )
            {
                    MyOutputDebugStringA("MyCreateRemoteThread() : WaitForSingleObject() 调用失败!错误代码: [%d]", GetLastError());
                    return NULL;
            }
            return hThread;
    }

    1. //在目标进程中创建线程并注入dll  
    2. BOOL Cx64Inject::InjectDll(DWORD dwProcessId,LPCWSTR lpcwDllPath)  
    3. {  
    4.         BOOL bRet = FALSE;  
    5.         HANDLE hProcess = NULL, hThread = NULL;  
    6.         LPVOID pCode = NULL;  
    7.         LPVOID pThreadData = NULL;  
    8.         __try  
    9.         {  
    10.                 if(!EnableDebugPrivilege())  
    11.                 {  
    12.                         MyOutputDebugStringA("InjectDll() : EnableDebugPrivilege() 调用失败!错误代码: [%d]", GetLastError());  
    13.                         return -1;  
    14.                 }  
    15.                 //打开目标进程;  
    16.                 hProcess = OpenProcess(PROCESS_ALL_ACCESS, TRUE, dwProcessId);  
    17.                 DWORD dwError = GetLastError();  
    18.                 if (hProcess == NULL)  
    19.                         __leave;  
    20.                 //申请空间,把我们的代码和数据写入目标进程空间里;  
    21.                 //写入数据;  
    22.                 THREAD_DATA data;  
    23.                 HMODULE hNtdll = GetModuleHandleW(L"ntdll.dll");  
    24.                 data.fnRtlInitUnicodeString = (pRtlInitUnicodeString)GetProcAddress(hNtdll,"RtlInitUnicodeString");  
    25.                 data.fnLdrLoadDll = (pLdrLoadDll)GetProcAddress(hNtdll,"LdrLoadDll");  
    26.                 memcpy(data.DllName, lpcwDllPath, (wcslen(lpcwDllPath) + 1)*sizeof(WCHAR));  
    27.                 data.DllPath = NULL;  
    28.                 data.Flags = 0;  
    29.                 data.ModuleHandle = INVALID_HANDLE_VALUE;  
    30.                 pThreadData = VirtualAllocEx(hProcess, NULL, 4096, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);  
    31.                 if (pThreadData == NULL)  
    32.                         __leave;  
    33.                 BOOL bWriteOK = WriteProcessMemory(hProcess, pThreadData,&data,sizeof(data), NULL);  
    34.                 if (!bWriteOK)  
    35.                         __leave;  
    36.                 MyOutputDebugStringA("pThreadData = 0x%p", pThreadData);  
    37.                 //写入代码;  
    38.                 DWORD SizeOfCode = (DWORD)ThreadProcEnd - (DWORD)ThreadProc;  
    39.                 pCode = VirtualAllocEx(hProcess, NULL, SizeOfCode, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);  
    40.                 if (pCode == NULL)  
    41.                 {  
    42.                         MyOutputDebugStringA("InjectDll() : pCode = VirtualAllocEx() 调用失败!错误代码: [%d]", GetLastError());  
    43.                         __leave;  
    44.                 }                  
    45.                 bWriteOK = WriteProcessMemory(hProcess, pCode, (PVOID)ThreadProc, SizeOfCode, NULL);  
    46.                 if (!bWriteOK)  
    47.                         __leave;  
    48.                 MyOutputDebugStringA("pCode = 0x%p", pCode);  
    49.                 //创建远程线程,把ThreadProc作为线程起始函数,pThreadData作为参数;  
    50.                 hThread = MyCreateRemoteThread(hProcess, (LPTHREAD_START_ROUTINE)pCode, pThreadData);  
    51.                 if (hThread == NULL)  
    52.                         __leave;  
    53.                 //等待完成;  
    54.                 WaitForSingleObject(hThread, INFINITE);  
    55.                 bRet = TRUE;  
    56.         }  
    57.         __finally  
    58.         {  
    59.                 if (pThreadData != NULL)  
    60.                         VirtualFreeEx(hProcess, pThreadData, 0, MEM_RELEASE);  
    61.                 if (pCode != NULL)  
    62.                         VirtualFreeEx(hProcess, pCode, 0, MEM_RELEASE);  
    63.                 if (hThread != NULL)  
    64.                         CloseHandle(hThread);  
    65.                 if (hProcess != NULL)  
    66.                         CloseHandle(hProcess);  
    67.         }  
    68.    
    69.         return bRet;  
    70. }  
    //在目标进程中创建线程并注入dll
    BOOL Cx64Inject::InjectDll(DWORD dwProcessId,LPCWSTR lpcwDllPath)
    {
            BOOL bRet = FALSE;
            HANDLE hProcess = NULL, hThread = NULL;
            LPVOID pCode = NULL;
            LPVOID pThreadData = NULL;
            __try
            {
                    if(!EnableDebugPrivilege())
                    {
                            MyOutputDebugStringA("InjectDll() : EnableDebugPrivilege() 调用失败!错误代码: [%d]", GetLastError());
                            return -1;
                    }
                    //打开目标进程;
                    hProcess = OpenProcess(PROCESS_ALL_ACCESS, TRUE, dwProcessId);
                    DWORD dwError = GetLastError();
                    if (hProcess == NULL)
                            __leave;
                    //申请空间,把我们的代码和数据写入目标进程空间里;
                    //写入数据;
                    THREAD_DATA data;
                    HMODULE hNtdll = GetModuleHandleW(L"ntdll.dll");
                    data.fnRtlInitUnicodeString = (pRtlInitUnicodeString)GetProcAddress(hNtdll,"RtlInitUnicodeString");
                    data.fnLdrLoadDll = (pLdrLoadDll)GetProcAddress(hNtdll,"LdrLoadDll");
                    memcpy(data.DllName, lpcwDllPath, (wcslen(lpcwDllPath) + 1)*sizeof(WCHAR));
                    data.DllPath = NULL;
                    data.Flags = 0;
                    data.ModuleHandle = INVALID_HANDLE_VALUE;
                    pThreadData = VirtualAllocEx(hProcess, NULL, 4096, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
                    if (pThreadData == NULL)
                            __leave;
                    BOOL bWriteOK = WriteProcessMemory(hProcess, pThreadData,&data,sizeof(data), NULL);
                    if (!bWriteOK)
                            __leave;
                    MyOutputDebugStringA("pThreadData = 0x%p", pThreadData);
                    //写入代码;
                    DWORD SizeOfCode = (DWORD)ThreadProcEnd - (DWORD)ThreadProc;
                    pCode = VirtualAllocEx(hProcess, NULL, SizeOfCode, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
                    if (pCode == NULL)
                    {
                            MyOutputDebugStringA("InjectDll() : pCode = VirtualAllocEx() 调用失败!错误代码: [%d]", GetLastError());
                            __leave;
                    }                
                    bWriteOK = WriteProcessMemory(hProcess, pCode, (PVOID)ThreadProc, SizeOfCode, NULL);
                    if (!bWriteOK)
                            __leave;
                    MyOutputDebugStringA("pCode = 0x%p", pCode);
                    //创建远程线程,把ThreadProc作为线程起始函数,pThreadData作为参数;
                    hThread = MyCreateRemoteThread(hProcess, (LPTHREAD_START_ROUTINE)pCode, pThreadData);
                    if (hThread == NULL)
                            __leave;
                    //等待完成;
                    WaitForSingleObject(hThread, INFINITE);
                    bRet = TRUE;
            }
            __finally
            {
                    if (pThreadData != NULL)
                            VirtualFreeEx(hProcess, pThreadData, 0, MEM_RELEASE);
                    if (pCode != NULL)
                            VirtualFreeEx(hProcess, pCode, 0, MEM_RELEASE);
                    if (hThread != NULL)
                            CloseHandle(hThread);
                    if (hProcess != NULL)
                            CloseHandle(hProcess);
            }
     
            return bRet;
    }
    以上是远程线程注入类的两个核心函数,下面是调用实例:
    1. Cx64Inject inject;  
    2. if (inject.InjectDll(g_dwPID,g_szDllPath))  
    3. {  
    4.         ::MessageBox(NULL,L"注入成功",L":)",MB_ICONINFORMATION);  
    5. }  
    6. else  
    7. {  
    8.         ::MessageBox(NULL,L"注入失败!",L"失败",MB_ICONERROR);  
    9. }  
    Cx64Inject inject;
    if (inject.InjectDll(g_dwPID,g_szDllPath))
    {
            ::MessageBox(NULL,L"注入成功",L":)",MB_ICONINFORMATION);
    }
    else
    {
            ::MessageBox(NULL,L"注入失败!",L"失败",MB_ICONERROR);
    }

    封装成类了,使用起来很简单的。
    有一点需要注意的是x64注入的意思是只能将64位dll注入64位进程。
    x86注入的意思是32位dll注入32位进程。


    源代码下载:

    DLL注入工具x86Inject_v1.2完整源代码(VS2010)下载地址:http://download.csdn.net/detail/sunflover454/9385421

    DLL注入工具x64Inject_v1.1完整源代码(VS2010)下载地址:http://download.csdn.net/detail/sunflover454/9385408


    相关下载:

    DLL注入工具成品(x86)下载地址:http://download.csdn.net/detail/sunflover454/9385346

    DLL注入工具成品(x64)下载地址:http://download.csdn.net/detail/sunflover454/9385355


    转载请注明出处,谢谢!
    原帖地址:http://blog.csdn.net/sunflover454/article/details/50441146


    jpg改rar

  • 相关阅读:
    白盒测试的特点
    什么是黑盒测试
    黑盒测试优缺点
    单元测试
    孤立的测试策略
    自顶向下的单元测试策略
    自底向上的单元测试策略
    tabbedApliction
    redis的key对应mysql数据表设计
    达内javase_day1笔记
  • 原文地址:https://www.cnblogs.com/kuangke/p/6259191.html
Copyright © 2011-2022 走看看