• 【VC++积累】之五、进程注入技术


    注入:就是把我的代码,添加到已经远行的远程进程的方法;

    在WinNT以后的系列操作系统中,每个进程都有自己的4GB私有进程地址空间,彼此互不相关。

    如 :   进程A中的一个地址,比如:0x12345678,到了进程B中的相同地方,存的东西完全不一样,或者说不可预料。

               所以说如果进程A想要看看或者修改进程B地址空间中的内容,就必须深入到其地址空间中,因为DLL是可以被加载到任何进程当中的,所以在进程注入中,DLL应该是主角,也就是说一些核心的代码都应该放在DLL中编写。

    来看一下步骤:

    1、找到远程进程的processid
    2、全权打开它
    3、在远程进程中申请一块内存,大小为你要写入的东东的大小
    4、在这个申请好的内存里面写入你要注入的东西
    5、创建一个远程线程来运行这个内存
    6、关闭进程


    主要用到的API函数:

    OpenProcess(...) //获取已知进程的句柄;

      HANDLE OpenProcess(
      DWORD dwDesiredAccess, //渴望得到的访问权限(标志)
      BOOL bInheritHandle, // 是否继承句柄
      DWORD dwProcessId// 进程标示符
      );
    VirtualAllocEx(...) //在进程中申请空间;
      LPVOID VirtualAllocEx(
      HANDLE hProcess,//申请内存所在的进程句柄
      LPVOID lpAddress,//保留页面的内存地址
      SIZE_T dwSize,//想分配的内存的大小,字节为单位,    实际分配的内存的大小是页内存大小的整数倍
      DWORD flAllocationType,//
      DWORD flProtect//
      );
    WriteProcessMemory(...) //向进程中写入东西;
      BOOL WriteProcessMemory(
      HANDLE hProcess,
      LPVOID lpBaseAddress,//要写的内存首地址,写之前需检查目标地址是否可用
      LPVOID lpBuffer,//指向要写的数据的指针
      DWORD nSize,//要写入的字节数
      LPDWORD lpNumberOfBytesWritten//
      );
    GetProcAddress(...) //取得函数在DLL中的地址;
      FARPROC GetProcAddress(
      HMODULE hModule, // DLL模块句柄
      LPCSTR lpProcName // 函数名
      );
    CreateRemoteThread(...) //在其他进程中创建新线程;
    HANDLE WINAPI CreateRemoteThread( 
    __in HANDLE hProcess, 
    __in LPSECURITY_ATTRIBUTES lpThreadAttributes, //指定了线程的安全属性
    __in SIZE_T dwStackSize, //线程初始大小,以字节为单位,如果该值设为0,那么使用系统默认大小
    __in LPTHREAD_START_ROUTINE lpStartAddress, //在远程进程的地址空间中,该线程的线程函数的起始地址.
    __in LPVOID lpParameter, //  传给线程函数的参数
    __in DWORD dwCreationFlags,// 线程创建的标志
    __out LPDWORD lpThreadId //ID
    );
    CloseHandle(...) //关闭句柄;


    下面看一下封装好的函数:

    //szModule是dll的地址,  dwID是进程的ID
    BOOL insertdll(LPCTSTR szModule, DWORD dwID)
    {
    	HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_CREATE_THREAD | PROCESS_VM_WRITE | PROCESS_VM_OPERATION, FALSE, dwID);
    	if(!hProcess)
    		return FALSE;
    
    	//dll 路径
    	int nByte = (_tcslen(szModule) + 1) * sizeof(TCHAR);
    	//alloc memory
    	LPVOID pAddr = VirtualAllocEx(hProcess, NULL, nByte, MEM_COMMIT, PAGE_READWRITE);
    	//write to process
    	if(!pAddr || !WriteProcessMemory(hProcess, pAddr, szModule, nByte, NULL))
    		return FALSE;
    
    #ifdef _UNICODE
    	PTHREAD_START_ROUTINE pfnStartAddr = (PTHREAD_START_ROUTINE)GetProcAddress(GetModuleHandle(_T("Kernel32")), "LoadLibraryW");
    #else
    	PTHREAD_START_ROUTINE pfnStartAddr = (PTHREAD_START_TOUTINE)GetProcAddress(GetModuleHandle(_T("Kernel32")), "LoadLibraryA");
    #endif
    
    	if(!pfnStartAddr)
    		return FALSE;
    	DWORD dwThreadID = 0;
    	//在其他进程中创建线程
    	HANDLE hRemoteThread = CreateRemoteThread(hProcess, NULL, 0, pfnStartAddr, pAddr, 0, &dwThreadID);
    	if(!hRemoteThread)
    		return FALSE;
    
    	CloseHandle(hRemoteThread);
    	CloseHandle(hProcess);
    	return TRUE;
    }


    有的时候你没有足够的权限是不能对进程进行注入的,你必须提权,这里要用到这几个API函数:

    OpenProcessToken  获得进程访问令牌句柄

     BOOL OpenProcessToken(
      __in HANDLE ProcessHandle, //要修改访问权限的进程句柄
      __in DWORD DesiredAccess, //指定你要进行的操作类型
      __out PHANDLE TokenHandle //返回的访问令牌指针
      );

    AdjustTokenPrivileges对这个访问令牌进行修改

      BOOL AdjustTokenPrivileges(
      HANDLE TokenHandle, // handle to token访问令牌的句柄
      BOOL DisableAllPrivileges, // disabling option  决定所有权
      PTOKEN_PRIVILEGES NewState, // privilege information指明要修改的权限
      DWORD BufferLength, // size of buffer  结构的长度
      PTOKEN_PRIVILEGES PreviousState, // original state buffer  存放修改前访问权限的信息
      PDWORD ReturnLength // required buffer size
      );

    LookupPrivilegevalue   获取本地唯一的标识
     BOOL LookupPrivilegevalue(
      LPCTSTR lpSystemName, // system name
      LPCTSTR lpName, // privilege name
      PLUID lpLuid // locally unique identifier
      );

    看一下封装好的函数:
    BOOL EnablePrivilege(LPCTSTR lpszPrivilegeName, BOOL bEnable)
    {
    	HANDLE hToken = NULL;
    	TOKEN_PRIVILEGES tp;
    	LUID luid;
    
    	if(!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY | TOKEN_READ, &hToken))
    		return FALSE;
    	if(!LookupPrivilegeValue(NULL, lpszPrivilegeName, &luid))
    		return FALSE;
    
    	tp.PrivilegeCount = 1;
    	tp.Privileges[0].Luid = luid;
    	tp.Privileges[0].Attributes = (bEnable)?SE_PRIVILEGE_ENABLED : 0;
    
    	AdjustTokenPrivileges(hToken, FALSE, &tp, NULL, NULL, NULL);
    	CloseHandle(hToken);
    	return (GetLastError() == ERROR_SUCCESS);
    }


    本文讲的是利用远程进程来注入DLL,  
    DLL注入技术还有: 用注册表来注入DLL,      用windows钩子来注入DLL,     用木马DLL来注入DLL,   
                                    用CreateProces来注入代码    用木马DLL 来注入DLL
    这些在后续的文章中还会讲到。


    2012/10/8
    jofranks 于南昌

  • 相关阅读:
    Windows网络编程经验小结
    异步Socket服务器与客户端
    用C#实现C/S模式下软件自动在线升级
    Linux 安装字体
    word 生成目录
    Linux sar使用
    yum 使用说明
    HASH JOIN算法
    row cache lock
    cursor: pin S
  • 原文地址:https://www.cnblogs.com/java20130723/p/3211392.html
Copyright © 2020-2023  润新知