[VC++积累]之五、进程注入技术

来源:岁月联盟 编辑:exp 时间:2012-10-09

注入:就是把我的代码,添加到已经远行的远程进程的方法;
在WinNT以后的系列操作系统中,每个进程都有自己的4GB私有进程地址空间,彼此互不相关。
如 :   进程A中的一个地址,比如:0x12345678,到了进程B中的相同地方,存的东西完全不一样,或者说不可预料。
           所以说如果进程A想要看看或者修改进程B地址空间中的内容,就必须深入到其地址空间中,因为DLL是可以被加载到任何进程当中的,所以在进程注入中,DLL应该是主角,也就是说一些核心的代码都应该放在DLL中编写。
来看一下步骤:
1、找到远程进程的processid
2、全权打开它
3、在远程进程中申请一块内存,大小为你要写入的东东的大小
4、在这个申请好的内存里面写入你要注入的东西
5、创建一个远程线程来运行这个内存
6、关闭进程

主要用到的API函数:
OpenProcess(...) //获取已知进程的句柄;
[cpp] 
HANDLE OpenProcess( 
DWORD dwDesiredAccess, //渴望得到的访问权限(标志) 
BOOL bInheritHandle, // 是否继承句柄 
DWORD dwProcessId// 进程标示符 
); 
VirtualAllocEx(...) //在进程中申请空间;
[cpp] 
LPVOID VirtualAllocEx( 
HANDLE hProcess,//申请内存所在的进程句柄 
LPVOID lpAddress,//保留页面的内存地址 
SIZE_T dwSize,//想分配的内存的大小,字节为单位,    实际分配的内存的大小是页内存大小的整数倍 
DWORD flAllocationType,// 
DWORD flProtect// 
); 
WriteProcessMemory(...) //向进程中写入东西;
[cpp] 
BOOL WriteProcessMemory( 
HANDLE hProcess, 
LPVOID lpBaseAddress,//要写的内存首地址,写之前需检查目标地址是否可用 
LPVOID lpBuffer,//指向要写的数据的指针 
DWORD nSize,//要写入的字节数 
LPDWORD lpNumberOfBytesWritten// 
); 
GetProcAddress(...) //取得函数在DLL中的地址;
[cpp]
FARPROC GetProcAddress( 
HMODULE hModule, // DLL模块句柄 
LPCSTR lpProcName // 函数名 
); 
CreateRemoteThread(...) //在其他进程中创建新线程;
[cpp] 
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(...) //关闭句柄;

下面看一下封装好的函数:
[cpp] 
//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  获得进程访问令牌句柄
[cpp]
BOOL OpenProcessToken( 
 __in HANDLE ProcessHandle, //要修改访问权限的进程句柄 
 __in DWORD DesiredAccess, //指定你要进行的操作类型 
 __out PHANDLE TokenHandle //返回的访问令牌指针 
 ); 

AdjustTokenPrivileges对这个访问令牌进行修改
[cpp] 
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   获取本地唯一的标识
[cpp] 
BOOL LookupPrivilegevalue( 
 LPCTSTR lpSystemName, // system name 
 LPCTSTR lpName, // privilege name 
 PLUID lpLuid // locally unique identifier 
 ); 

看一下封装好的函数:
[cpp] 
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
这些在后续的文章中还会讲到。