远程线程注入(三)DLL注入

DLL注入和远程线程注入类似,我们只需要将要执行的函数体放到dll文件中,然后获得kernel32.dll中的LoadLibraryA()和GetProcAddress()的地址,

将这两个函数的地址作为参数传递给远程线程中,利用CreateRemoteThread开启远程线程,在远程线程中加载测试dll文件中即可。

需要用到 远程线程注入(一)中的msg.dll,依然是拿QQ开刀- -

上代码:

//远程DLL注入
#include <windows.h>
#include <cstdio>

typedef struct _RemotePara
{
    char dwMessageBox[12];
    
    DWORD pLoadlibrary;
    
}RemotePara;    //传入到远程线程中的参数

DWORD _stdcall ThreadProc(RemotePara *lpPara)   //远程线程函数
{
    typedef int (_stdcall *MMessageBoxA)(HWND, LPCTSTR, LPCTSTR, DWORD);
    
    typedef HINSTANCE (_stdcall *mLoadLibrary)(LPCTSTR);
    
    mLoadLibrary myLoadLibrary;
    
    myLoadLibrary = (mLoadLibrary) lpPara->pLoadlibrary;
    
    myLoadLibrary(lpPara->dwMessageBox);
    
    return 0;
}

void EnableDebugPriv()  //提权操作
{
    HANDLE hToken;
    
    LUID sedebugnameValue;
    
    TOKEN_PRIVILEGES tkp;
    
    if (!OpenProcessToken( GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken))
    {
        return;
    }
    if (!LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &sedebugnameValue))
    {
        CloseHandle(hToken);
        
        return;
    }
    tkp.PrivilegeCount = 1;
    
    tkp.Privileges[0].Luid = sedebugnameValue;
    
    tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
    
    if ( !AdjustTokenPrivileges(hToken, FALSE, &tkp, sizeof tkp, NULL, NULL) )
    {
        CloseHandle(hToken);
    }
}

DWORD GetProcessID(char *FileName)  //根据进程名,获得进程ID
{
    HANDLE hProcess;
    PROCESSENTRY32 pe;
    BOOL bRet;

    //进行进程快照
    hProcess = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);

    pe.dwSize = sizeof(PROCESSENTRY32);

    //找到第一个进程
    bRet = Process32First(hProcess, &pe);
    
    //循环比较
    while(bRet)
    {
        if(strcmp(FileName, pe.szExeFile) == 0)
        {
            //返回得到的ProcessID
            return pe.th32ProcessID;
        }
        else
        {
            //指向下一个进程
            bRet = Process32Next(hProcess,&pe);
        }
    }

    return NULL;
}


int main()
{
    const DWORD THREADSIZE = 1024 * 4;  //4MB的空间

    DWORD byte_write;

    EnableDebugPriv();  //提权
    
    //打开被注入进程
    HANDLE hWnd = ::OpenProcess(PROCESS_ALL_ACCESS, FALSE, GetProcessID("QQ.exe"));
    if (!hWnd)
    {
        return 1;
    }
    
    //在被注入进程中申请内存空间
    void *pRemoteThread = VirtualAllocEx(hWnd, 0, THREADSIZE, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
    if (!pRemoteThread)
    {
        return 2;
    }
    
    //将远程线程函数写入被注入进程
    if ( !WriteProcessMemory(hWnd, pRemoteThread, (LPCVOID)&ThreadProc, THREADSIZE, 0) )
    {
        return 3;
    }
    
    //为将要传入线程的参数赋值
    RemotePara myRemotePara;

    ZeroMemory(&myRemotePara, sizeof(myRemotePara));

    HINSTANCE hker = LoadLibrary("kernel32.dll");
    
    //获得LoadLibraryA的函数地址
    myRemotePara.pLoadlibrary = (DWORD)GetProcAddress(hker, "LoadLibraryA");

    strcat(myRemotePara.dwMessageBox, "msg.dll");  //相对地址默认是在System32或者SysWOW64里面

    FreeLibrary(hker);
    
    //在被注入进程中申请传入参数的空间
    RemotePara *pRemotePara = (RemotePara *)VirtualAllocEx(hWnd, 0, sizeof(RemotePara), MEM_COMMIT, PAGE_READWRITE);
    if (!pRemotePara)
    {
        return 4;
    }
    
    //将参数写入被注入进程
    if ( !WriteProcessMemory(hWnd, pRemotePara, &myRemotePara, sizeof(RemotePara), 0) )
    {
        return 5;
    }
    
    //启动远程线程
    HANDLE hTread = CreateRemoteThread(hWnd, 0, 0, (DWORD(_stdcall *)(void *))pRemoteThread, pRemotePara, 0, &byte_write);
    if (!hTread)
    {
        return 6;
    }
    return 0;
}

 

注入Dll:

1,OpenProcess获得要注入进程的句柄

2,VirtualAllocEx在远程进程中开辟出一段内存,长度为strlen(dllname)+1;

3,WriteProcessMemory将Dll的名字写入第二步开辟出的内存中。

4,CreateRemoteThread将LoadLibraryA作为线程函数,参数为Dll的名称,创建新线程

5,CloseHandle关闭线程句柄

卸载Dll:

1,CreateRemoteThread将GetModuleHandle注入到远程进程中,参数为被注入的Dll名

2,GetExitCodeThread将线程退出的退出码作为Dll模块的句柄值。

3,CloseHandle关闭线程句柄

3,CreateRemoteThread将FreeLibraryA注入到远程进程中,参数为第二步获得的句柄值。

4,WaitForSingleObject等待对象句柄返回

5,CloseHandle关闭线程及进程句柄。

posted @ 2013-09-27 20:54  瓶哥  Views(685)  Comments(0Edit  收藏  举报