远程线程注入(二)线程注入

文章本来是想转这位大大的:http://blog.csdn.net/gaoxin1076/article/details/8117151

谁知道他的代码在我的Codeblocks上根本不能运行,改了好多处还是无解- -

于是乎我参考了别人的代码做了一些修改,能够在Codeblocks上编译,能够注入一些非系统进程,例如QQ- -,但是像explorer.exe、services.exe之类的系统进程

在启动远程线程时会失败,暂时还不知道为何。。

先奉上代码:

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

typedef struct _RemotePara
{
    char dwMessageBox[12];

    DWORD pMessageBox;
}RemotePara;    //传入到远程线程中的参数


DWORD _stdcall ThreadProc(RemotePara *lpPara)   //远程线程函数
{
    typedef int (_stdcall *MMessageBoxA)(HWND, LPCTSTR, LPCTSTR, DWORD);

    MMessageBoxA myMessageBox;

    myMessageBox = (MMessageBoxA)lpPara->pMessageBox;

    myMessageBox(NULL, lpPara->dwMessageBox, lpPara->dwMessageBox, MB_OK);

    return 0;
}

void EnableDebugPriv(void)  //提权操作
{
    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);
    }
}

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

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

    pe.dwSize = sizeof(PROCESSENTRY32);

    //开始进程查找
    bRet = Process32First(hProcess, &pe);
    //循环比较,得出ProcessID

    while(bRet)
    {
        if(strcmp(FileName, pe.szExeFile) == 0)
        {
            return pe.th32ProcessID;
        }
        else
        {
            bRet = Process32Next(hProcess,&pe);
        }
    }

    //返回得到的ProcessID
    return NULL;
}


int main(void)
{
    const DWORD THREADSIZE = 1024 * 4;

    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("user32.dll");

    //获得MessageBox的函数地址
    myRemotePara.pMessageBox = (DWORD)GetProcAddress(hker, "MessageBoxA");

    strcat(myRemotePara.dwMessageBox, "hello\0");

    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;
}

创建远程线程有以下几个步骤:

1.获得想要注入代码的进程的句柄,PROCESS_ALL_ACCESS表示获得所有权限

HANDLE hWnd = OpenProcess(PROCESS_ALL_ACCESS, FALSE, GetProcessID("QQ.exe"));

 

2.在远程线程中为传送过去的函数申请内存

void *pRemoteThread = VirtualAllocEx(hWnd, 0, THREADSIZE, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);

 

3.将远程线程函数写入被注入进程

WriteProcessMemory(hWnd, pRemoteThread, (LPCVOID)&ThreadProc, THREADSIZE, 0);

 

4.获得MessageBoxA在user32.dll中的真正地址

 myRemotePara.pMessageBox = (DWORD)GetProcAddress(hker, "MessageBoxA");

 

5.在远程进程中为传送过去的参数申请内存

RemotePara *pRemotePara = (RemotePara *)VirtualAllocEx(hWnd, 0, sizeof(RemotePara), MEM_COMMIT, PAGE_READWRITE);

 

6.将参数写入注入进程

WriteProcessMemory(hWnd, pRemotePara, &myRemotePara, sizeof(RemotePara), 0);

 

7.最后启动远程线程

HANDLE hTread = CreateRemoteThread(hWnd, 0, 0, (DWORD(_stdcall *)(void *))pRemoteThread, pRemotePara, 0, &byte_write);

 

第一次远程注入可以成功,第二次就不行了,就不能弹出对话框了,貌似进程打开之后马上就关闭了。个人以为原因可能处在dll的fdwReason。有时间尝试着调试一下。

自己改了一下,应该是这样的。上面的代码里面没有FreeLibrary,那么dll还是在远程地址空间里面。第二次想要注入的时候是不会发送DLL_PROCESS_ATTACH 消息的。

DLL_PROCESS_ATTACH消息的发送是这样的:

线程调用LoadLibrary   -->   Dll是否已经被映射到了进程的地址空间中  (如果是)  -->   递增DLL的使用计数  -->  使用计数器是否等于1 (如果是) -->  调用DLL的DllMain并且传入DLL_PROCESS_ATTACH

所以说,在Dll已经被映射到了进程地址空间之后,只不过DLL的使用计数增加了,如果是2,那么很明显就不会调用DLL的DllMain并且传入DLL_PROCESS_ATTACH

但是如果我把dll改一下,把弹框代码写在DLL_THREAD_ATTACH里面,那么每次创建线程的时候就都会收到DLL_THREAD_ATTACH消息了。

 

脑子里面还是很乱- -

暂时先就这样吧。。

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