使用CreateRemoteThread把代码远程注入指定exe执行

http://www.cnblogs.com/inva/p/4971331.html

由于本人也是新手,如果有朋友不懂windows api相关知识,我相信查阅书籍或者百度会比我说有帮助的多,下面就我所做简单复述一下过程。

效果图示如下:

做的这个例子首先是创建了一个MFC 对话框程序,然后自己创建了一个 带有导出函数 (简单的减法) 的DLL , 这个Calc按键就是调用自己DLL里面的减法函数 计算1 - 1, 其次创建一个拥有能够修改进程中某函数的入口代码功能的DLL(为什么是DLL,网上有大量详细的资料,), 然后我们还创建一个windows控制台程序 也就是 调用CreateRemoteThread  让Calc 加载我们准备好的DLL(修改函数入口代码), 因为DLL被加载时我们可以在DLLMain中指定要执行的代码。

未注入代码之前:

 

执行我的 注入程序createremotethread.exe 之后 如下图:

 

可以看到注入成功了, 注入的是什么呢? 这就是 CreateRemoteThread的作用了, 我们向Calc.exe 注入了一个线程,然后这个线程执行了LoadLibrary 函数,

我告诉Calc 要Load 我指定的 DLL, 为什么呢? 因为 我指定的这个DLL 是我们自己创建的, 它里面的函数代码能找到Calc进程中 原来sub函数的地址,然后并

修改sub函数地址处的入口代码,也就是改成 jmp xxx 使Calc 执行我们指定的代码。

 

最重要的CreateRemoteThread:

复制代码
    HANDLE hThread;
    char szLibPath[_MAX_PATH] = "E:\\vs2010project\\InjectDll\\Release\\InjectDll.dll"; //指定注入之后目标进程要加载的DLL

    DWORD hLibModule;

    HANDLE hProcess = NULL;
    hProcess = GetProcessByName("Calc.exe");
    DWORD ERRO = GetLastError();

    if(hProcess == NULL)
        return 0;

    HMODULE modHandle = GetModuleHandle(_T("Kernel32")); //因为kernel32 每一个windows程序进程空间中都有 所以让他调用LOADLIBRARY不成问题void* pLibRemote = VirtualAllocEx(hProcess, NULL, sizeof(szLibPath), MEM_COMMIT, PAGE_EXECUTE_READWRITE);
    LPTHREAD_START_ROUTINE addr = (LPTHREAD_START_ROUTINE)GetProcAddress(modHandle, "LoadLibraryA");
    WriteProcessMemory( hProcess, pLibRemote, (void*)szLibPath, sizeof(szLibPath), NULL);
 
    hThread = CreateRemoteThread(hProcess, NULL, 0,
                                addr,
                                pLibRemote,
                                0,
                                NULL);
    
    WaitForSingleObject(hThread, INFINITE);
    CloseHandle(hThread);
复制代码

 

 

根据进程名字获取进程句柄也是本例子非常关键的部分,可以通过微软提供的api 拍摄进程列表快照, 然后再遍历寻找,代码如下:

复制代码
HANDLE GetProcessByName(const char* name)
{
    EnableDebugPriv();
    DWORD pid = 0;
    HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
    PROCESSENTRY32 process;
    ZeroMemory(&process, sizeof(process));
    process.dwSize = sizeof(process);
    if (Process32First(snapshot, &process))
    {
        do
        {
            if( stricmp(UnicodeToAnsi(process.szExeFile), name) == 0)
            {
                pid = process.th32ProcessID;
                break;
            }
        }while(Process32Next(snapshot, &process));
    }
    CloseHandle(snapshot);
    
    if(pid != 0)
    {
        HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid);        
        return hProcess;
    }

    return NULL;
    
}
复制代码

 

 

其中 关于 CreateRemoteThread 部分的核心代码有许多需要注意的事情 主要有 执行OPENPROCESS之前需要开启特权 代码如下:

复制代码
 1 void EnableDebugPriv()
 2 {
 3     HANDLE hToken;
 4     LUID luid;
 5     TOKEN_PRIVILEGES tkp;
 6 
 7     OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken);
 8 
 9     LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &luid);
10 
11     tkp.PrivilegeCount = 1;
12     tkp.Privileges[0].Luid = luid;
13     tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
14 
15     AdjustTokenPrivileges(hToken, false, &tkp, sizeof(tkp), NULL, NULL);
16 
17     CloseHandle(hToken); 
18 }
复制代码

接下来我们就可以调用openprocess 打开目标进程 进行进一步的操作(调用CreateRemoteThread)达到使目标进程加载我们指定DLL,进而指定DLL被加载时能执行指定代码。

 

最后 关于修改进程中 导入 dll 中的函数的入口处代码 的代码如下:

复制代码
复制代码
BYTE NewCode[5]; //用来替换原入口代码的字节 (jmp xxxx)

typedef int (_cdecl* getsub)(int x,int y);    //typedef 比较少的用法 能定一个函数指针类型 即getsub 
getsub mySub = NULL; //用新定义的类型定义一个变量
FARPROC pfar_sub;   //指向mySub函数的远指针

HANDLE hProcess = NULL; //所处进程的句柄
DWORD pid;    //所处进程ID
复制代码


//修改mySub入口处代码
void modify()
{ 
    assert(hProcess != NULL);

    DWORD dwTemp=0;
    DWORD dwOldProtect;
    
    VirtualProtectEx(hProcess, pfar_sub, 5, PAGE_READWRITE, &dwOldProtect); //将内存保护模式改为可读写,原保护模式保存入dwOldProtect
    WriteProcessMemory(hProcess, pfar_sub, NewCode, 5, 0);
    VirtualProtectEx(hProcess, pfar_sub, 5, dwOldProtect, &dwTemp); //恢复内存保护模式
}

int new_sub(int x,int y)
{
    return 1;
}

int inject()
{
    DWORD dwPid = ::GetCurrentProcessId();
    hProcess = OpenProcess(PROCESS_ALL_ACCESS, 0, dwPid); 

    int addr_farpointer = 0;


    //获取add.dll中的add()函数
    HMODULE hmod = ::LoadLibrary(_T("E:\\vs2010project\\My_Sub\\Debug\\My_Sub.dll"));
    mySub = (getsub)::GetProcAddress(hmod, "mySub");
    pfar_sub=(FARPROC)mySub;
    addr_farpointer = (int)pfar_sub;
        
    if (pfar_sub == NULL)
    {    
        MessageBox(NULL, TEXT("no locate add!!"), TEXT("info"), MB_OK);
        return FALSE;
    }

    NewCode[0] = 0xe9;//0xe9 == jmp
    
    _asm 
    { 
        lea eax, new_sub
        mov ebx, pfar_sub 
        sub eax, ebx 
        sub eax, 5 
        mov dword ptr [NewCode + 1],eax 
    } 

    modify(); 
    MessageBox(NULL, TEXT("Modified SUCCESSFULLY!!"), TEXT("info"), MB_OK);
    return TRUE;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值