MFC-进程注入

进程注入:就是把自己的dll插入系统服务程序中 

为什么要进行进程注入:

到了WinNT以后的系列操作系统中,每个进程都有自己的4GB私有进程地址空间,彼此互不相关。进程A中的一个地址,比如:0x12345678,到了进程B中的相同地方,存的东西完全不一样,或者说不可预料。所以说如果进程A想要看看或者修改进程B地址空间中的内容,就必须深入到其地址空间中,因为DLL是可以被加载到任何进程当中的,所以在进程注入中,DLL应该是主角,也就是说一些核心的代码都应该放在DLL中编写

注入的优点:就是进程隐藏,能穿透防火墙 

注入的缺点:如果DLL程序的算法不是很好,或者DLL文件有Bug,那么将影响目标进程的执行效率,或者说干脆目标进程崩溃

用远程线程技术来实现进程的注入

新建项目 

这个项目不需要界面的,所以创建win32工程

 因为不需要界面和资源,所以要删除一些文件

 在工程cpp中只留入口点,其余删除,如下

复制代码
// Project1.cpp : 定义应用程序的入口点。
//

#include "framework.h"
#include "Project1.h"


int APIENTRY wWinMain(_In_ HINSTANCE hInstance,
                     _In_opt_ HINSTANCE hPrevInstance,
                     _In_ LPWSTR    lpCmdLine,
                     _In_ int       nCmdShow)
{
    return 0;
}
复制代码

 

此时编译一下,应该成功

代码:

h文件

#pragma once

BOOL Inject(LPCTSTR szModule, DWORD dwID);
/*
* 参数1:LPCTSTR 动态链接库的路径
* 参数2:DWORD 目标进程ID
*/

cpp文件

复制代码
// Project1.cpp : 定义应用程序的入口点。
//

#include "framework.h"
#include "Project1.h"


int APIENTRY wWinMain(_In_ HINSTANCE hInstance,
                     _In_opt_ HINSTANCE hPrevInstance,
                     _In_ LPWSTR    lpCmdLine,
                     _In_ int       nCmdShow)
{
    
    HANDLE hToken;     //存放获得的令牌
    TOKEN_PRIVILEGES tp;   //令牌权限结构体
    
    BOOL b = OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken);//获取当前进程的令牌
   

    if (!b) {
        MessageBox(NULL, _T("获取进程的令牌句柄失败"), NULL, NULL);
    }

    BOOL b1 = LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &tp.Privileges[0].Luid);//获取本地系统的指定权限
    
    if (!b1) {
        MessageBox(NULL, _T("获取系统权限的特权值失败"), NULL, NULL);
    }

    tp.PrivilegeCount = 1;  //只启动调试权限,所以权限的个数是一个
    tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;  //属性设置
    
    BOOL b2 = AdjustTokenPrivileges(hToken, FALSE, &tp, sizeof(tp), NULL, NULL);//修改访问令牌的权限
   
    DWORD d = GetLastError();

    if (d != ERROR_SUCCESS) {
        MessageBox(NULL, _T("权限修改失败"), NULL, NULL);
    }

    if (d == ERROR_SUCCESS) {
        
        MessageBox(NULL, _T("权限修改成功"), NULL, NULL);
    }


    CloseHandle(hToken);
    
    
    
    HWND hWnd = ::FindWindow(_T("TFrmMain"), NULL);//获取与指定窗口类名和窗口名的最顶层窗口的窗口句柄
    //寻找 语音计算器 进程
    if (!hWnd) {
        MessageBox(NULL,_T("请打开语音计算器"),NULL,NULL);
        ExitProcess(0);
    }

    unsigned long pid;
    ::GetWindowThreadProcessId(hWnd, &pid);//获取指定进程的进程ID
    /*
    参数:HANDLE Process  进程的句柄
            句柄必须具有PROCESS_QUERY_INFORMATION或PROCESS_QUERY_LIMITED_INFORMATION访问权限
    返回值:如果函数成功,则返回值为进程标识符
            如果函数失败,则返回值为零
    */

    if(pid ==0){
        MessageBox(NULL, _T("语音计算器进程ID获取失败"), NULL, NULL);
        ExitProcess(0);
    }


    b=Inject(_T("D:\\bb\\MFCdll\\Debug\\MFCdll.dll"), pid);//调用函数
        
    return 0;
}

BOOL Inject(LPCTSTR szModule, DWORD dwID) {   //在目标进程中装载dll
    
    HANDLE process = OpenProcess(PROCESS_QUERY_INFORMATION |PROCESS_VM_OPERATION | PROCESS_CREATE_THREAD |PROCESS_VM_READ | PROCESS_VM_WRITE | PROCESS_QUERY_INFORMATION, FALSE, dwID);
    if (!process) {
        MessageBox(NULL, _T("进程权限获取失败"), NULL, NULL);
        return FALSE;
    }

    int cByte = (_tcslen(szModule)+1)*sizeof(TCHAR);
    //dll路径的字节数
    LPVOID pAddr = VirtualAllocEx(process,NULL, cByte, MEM_COMMIT, PAGE_READWRITE);
    if (!pAddr || !WriteProcessMemory(process, pAddr, szModule, cByte,NULL)) {
        MessageBox(NULL, _T("路径写入失败"), NULL, NULL);
        return FALSE;
    }

    PTHREAD_START_ROUTINE pfnStartAddr =(PTHREAD_START_ROUTINE)GetProcAddress(GetModuleHandle(_T("Kernel32")), "LoadLibraryW");
    //获取Kernel32动态链接库中LoadLibraryW函数的地址

    if (!pfnStartAddr) {
        MessageBox(NULL, _T("LoadLibraryW函数地址获取失败"), NULL, NULL);
        return FALSE;
    }

    DWORD dwThreadID = 0;
    HANDLE hRemoteThread = CreateRemoteThread(process,NULL,0, pfnStartAddr, pAddr,0,&dwThreadID);//创建远程线程
    /*
    【在目标进程中装载dll】
    参数1:HANDLE hProcess  线程所属进程的进程句柄
            该句柄必须具有 PROCESS_CREATE_THREAD, PROCESS_QUERY_INFORMATION, PROCESS_VM_OPERATION, PROCESS_VM_WRITE,和PROCESS_VM_READ 访问权限
    参数2:LPSECURITY_ATTRIBUTES lpThreadAttributes 一个指向 SECURITY_ATTRIBUTES 结构的指针, 该结构指定了线程的安全属性  
    参数3:SIZE_T dwStackSize   线程栈初始大小,以字节为单位,如果该值设为0,那么使用系统默认大小
    参数4:LPTHREAD_START_ROUTINE lpStartAddress   在远程进程的地址空间中,该线程的线程函数的起始地址
    参数5:LPVOID lpParameter    传给线程函数的参数
    参数6:DWORD dwCreationFlags 线程的创建标志
            0     线程创建后立即运行
            CREATE_SUSPENDED=0x00000004   线程创建后先将线程挂起,直到 ResumeThread 被调用
            STACK_SIZE_PARAM_IS_A_RESERVATION=0x00010000    dwStackSize 参数指定为线程栈预订大小,如果STACK_SIZE_PARAM_IS_A_RESERVATION没有被指定,dwStackSize 参数指定为线程栈分配大小.
    参数7:LPDWORD lpThreadId    指向新创建线程ID的指针,如果创建失败,该参数为NULL
    
    返回值:成功返回新线程句柄,失败返回NULL
    */

    if (!hRemoteThread) {
        MessageBox(NULL, _T("远程线程创建失败"), NULL, NULL);
        return FALSE;
    }

    CloseHandle(hRemoteThread);
    CloseHandle(process);
    return TRUE;

}
复制代码

 

运行

注意:管理员身份运行

 

出现这个窗口时,说明进程注入成功,dll中的函数开始执行了 

 

  

实例工程下载:

链接:https://pan.baidu.com/s/1sE89t5ctZs1uPVPJ7Y91Dw
提取码:6666

 

MFCdll下载:

链接:https://pan.baidu.com/s/1cIoSVYz5JKeJm4KDSVkYOg
提取码:6666

 

语音计算器下载:

链接:https://pan.baidu.com/s/1SWVEgBCjTcPk5_wyBXmnjA
提取码:6666

 

 

 

 

posted @   天子骄龙  阅读(144)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
历史上的今天:
2019-05-22 初等函数
2019-05-22 python-第三方包的安装和升级和卸载
点击右上角即可分享
微信分享提示

目录导航