zoukankan      html  css  js  c++  java
  • [C++] 进程注入dll版

    前言

    这几天在弄进程注入的事情,一直做不出来直接的进程注入,也就是不要dll的注入。因为dll注入据说容易触发杀软,但是弄了两天没弄出来。代码明明不报错,目标进程一旦注入就崩溃,完全没有提示信息,windows日志也没有什么有价值的线索。所以今天就尝试了dll注入,结果一次成功了。。。

    前提

    • 进程间内存独立

    运行在安全模式下的Windows,每个进程的内存空间都是独立的,互相不能访问彼此,所以代码注入才是一件比较麻烦的事情

    • 所有进程中 kernel32.dll地址相同

    每个进程都会加载kernel32.dll,并且在那些进程中,这个库的地址都是一样的

    原理

    dll注入主要分为如下几个步骤

    • 提权:如果不提权的话,进程列表中很多进程是打不开的,并且可能获取不到PROCESS_ALL_ACCESS权限
    • 获取PID:这部分不是必须的,但是PID每次运行都不一样,所以最好能获取,这里通过CreateToolhelp32Snapshot()函数获取进程,遍历结果之后得到对应的PID
    • 打开进程:通过OpenProcess()函数打开进程,同时指定权限是PROCESS_ALL_ACCESS权限,否则后面操作会失败,如果要获取这个权限就得先提权
    • 通过VirtualAllocEx()函数在目标进程中申请内存,然后用WriteProcessMemory()函数将LoadLibraey()函数的参数准备好写入到内存中
    • 通过LoadLibrary()函数加载kernel32.dll,实际上进程都会加载这个,第二次加载似乎直接获取模块句柄了。
    • 通过GetProcAddress()函数获取到LoadLibraryW()函数的地址,因为kernel32.dll在所有进程中的地址都相同,所以,在本进程中获取的函数地址在目标进程中也是那个函数
    • 通过CreateRemoteThread()函数在目标进程中创建一个线程,执行LoadLibraryW()函数载入自己的dll

    代码

    • 注入代码
    #include <windows.h>
    #include <iostream>
    #include <tlhelp32.h>
    
    using namespace std;
    
    DWORD GetPidByName(LPCWSTR lpName)
    {
    	HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0);
    	if (!hSnap)
    	{
    		cout << "创建进程快照失败" << endl;
    		return 0;
    	}
    	PROCESSENTRY32 pe;
    	pe.dwSize = sizeof(PROCESSENTRY32);
    	Process32First(hSnap, &pe);
    	do
    	{
    		if (!_wcsicmp(lpName, pe.szExeFile))
    		{
    			return pe.th32ProcessID;
    		}
    	} while (Process32Next(hSnap,&pe));
    	return 0;
    }
    
    // 提权
    int EnableDebugPrivilege()
    {
    	HANDLE token;
    	TOKEN_PRIVILEGES tp;
    	// 打开进程令牌环
    	if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &token))
    	{
    		cout << "打开进程令牌失败" << endl;
    		return 0;
    	}
    	//  获取进程本地唯一ID
    	LUID luid;
    	if (!LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &luid))
    	{
    		cout << "获取LUID失败" << endl;
    		return 0;
    	}
    	tp.PrivilegeCount = 1;
    	tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
    	tp.Privileges[0].Luid = luid;
    	// 调整进程权限
    	if (!AdjustTokenPrivileges(token, 0, &tp, sizeof(TOKEN_PRIVILEGES), NULL, NULL))
    	{
    		cout << "提权失败" << endl;
    		return 0;
    	}
    	return 1;
    }
    
    int main()
    {
    	if (!EnableDebugPrivilege())
    	{
    		cout << "提权失败"<<endl;
    		return 0;
    	}
    	DWORD dwTargetPid = GetPidByName(L"notepad.exe");
    	if (!dwTargetPid)
    	{
    		cout << "获取PID失败" << endl;
    		return 0;
    	}
    	cout << "PID: " << dwTargetPid << endl;
    
    	// 打开进程
    	HANDLE hTarget = OpenProcess(PROCESS_ALL_ACCESS,false,dwTargetPid);
    	if (!hTarget)
    	{
    		cout << "打开进程失败"<<GetLastError() << endl;
    		return 0;
    	}
    
    	void* pLoadLibFuncParam = nullptr;
    	pLoadLibFuncParam = VirtualAllocEx(hTarget,0,4096,MEM_COMMIT|MEM_RESERVE,PAGE_READWRITE);
    	if (pLoadLibFuncParam == nullptr)
    	{
    		cout << "申请内存失败" << endl;
    		CloseHandle(hTarget);
    		return 0;
    	}
    
    	LPCTSTR lpParam = L"D:\1.dll";
    	if (!WriteProcessMemory(hTarget, pLoadLibFuncParam, (LPCVOID)lpParam, (wcslen(lpParam)+1)*sizeof(TCHAR), NULL))
    	{
    		cout << "写入内存失败" << endl;
    		CloseHandle(hTarget);
    		return 0;
    	}
    	HMODULE hNtdll = LoadLibrary(L"kernel32.dll");
    	if (!hNtdll)
    	{
    		cout << "加载模块错误" <<GetLastError()<< endl;
    		CloseHandle(hTarget);
    		return 0;
    	}
    	cout << "模块句柄: " << hNtdll << endl;
    	void* pLoadLibrary = nullptr;
    	pLoadLibrary = GetProcAddress(hNtdll, "LoadLibraryW");
    	if (pLoadLibrary == nullptr)
    	{
    		cout << "找不到函数" << endl;
    		CloseHandle(hTarget);
    		return 0;
    	}
    	cout << "函数地址: " << pLoadLibrary << endl;
    	DWORD dwThreadId = 0;
    	HANDLE hRemoteThread = CreateRemoteThread(hTarget, NULL, 0, (LPTHREAD_START_ROUTINE)pLoadLibrary, (LPVOID)pLoadLibFuncParam, 0,&dwThreadId);
    	if (!hRemoteThread)
    	{
    		cout << "创建进程失败" << endl;
    		CloseHandle(hTarget);
    		return 0;
    	}
    	cout<<"运行结束"<< hRemoteThread <<endl;
    	getchar();
    	getchar();
    	CloseHandle(hTarget);
    	return 0;
    }
    
    • DLL中的代码

    代码编译之后,放到D:1.dll的位置

    DWORD WINAPI ThreadProc()
    {
        MessageBox(NULL,L"我已成功打入敌人内部 By Startu",L"报告首长",0);
        return 0;
    }
    
    BOOL APIENTRY DllMain( HMODULE hModule,
                           DWORD  ul_reason_for_call,
                           LPVOID lpReserved
                         )
    {
        switch (ul_reason_for_call)
        {
        case DLL_PROCESS_ATTACH:
            CreateThread(NULL,0, (LPTHREAD_START_ROUTINE)ThreadProc,NULL,0,NULL);
            break;
        case DLL_THREAD_ATTACH:
        case DLL_THREAD_DETACH:
        case DLL_PROCESS_DETACH:
            break;
        }
        return TRUE;
    }
    

    一些问题

    • 为什么是LoadLibraryW()

    我最开始获取的函数是LoadLibrary()函数,但是实际上这个函数并不存在,这个只是一个宏,在windows中,有两个函数LoadLibraryW()LoadLibraryA()分别用于,不同的编码

    • 为什么需要在目标进程中申请地址存放参数

    当代码被注入到目标进程之后,实际上这段代码算是目标进程的,如果直接传入参数的本质是传入地址,直接在本进程中传入地址,

    • 调试问题

    dll中的代码,所有的printf() 或者 cout的输出都看不到,曾经我诧异了很久,直到突然想起来,这里的输出都应该是由宿主程序输出的,但是宿主程序没有控制台,所以就看不到了。这种时候 MessageBox()就要用到了。另外,通过 命令行rundll32 1.dll func的方式可以加载dll,执行里面的函数

  • 相关阅读:
    leetcode69
    leetcode204
    leetcode414
    leetcode532
    leetcode28
    leetcode155
    leetcode303
    leetcode190
    2018-7-21-win10-uwp-调用-Microsoft.Windows.Photos_8wekyb3d8bbwe-应用
    2018-7-21-win10-uwp-调用-Microsoft.Windows.Photos_8wekyb3d8bbwe-应用
  • 原文地址:https://www.cnblogs.com/cjdty/p/13171794.html
Copyright © 2011-2022 走看看