首页
社区
课程
招聘
[原创]病毒木马常用手段之自我创建
发表于: 2022-5-18 00:17 7522

[原创]病毒木马常用手段之自我创建

2022-5-18 00:17
7522

在分析样本时,我们会遇到各种骚操作,自我创建就是其中一种,简而言之就是将自身作为子进程运行,并且以子进程运行时会有不同的动作,如套娃创建子进程,执行shellcode等等。虽然这种手段并没有多么高明,但是在实际情况中常常会遇到,调试起来也比较麻烦,而且在真实环境中往往会更加复杂,所以掌握各种奇淫巧计是我等“杀人越货,行走江湖”必不可少的功夫,废话少说,开始开始实战!

根据特征找到main函数,我的是VS2013编译的,你的特征可能和我的不一样 !
图片描述
调用CreateProcessW以挂起方式创建子进程
图片描述

可以看到目前子进程处于挂起状态
图片描述

使用GetThreadContext获取子进程的主线程的CONTEXT结构体
图片描述
修改子进程的主线程的CONTEXT结构体中的EIP的值为ChildProc,然后调用SetThreadContext进行设置
图片描述

恢复子进程的主线程
图片描述

调用WaitForSingleObject进入等待状态直到子进程运行完毕
图片描述
点击确定后子程序结束运行并返回
图片描述

假如我们想要调试ChildProc函数,有很多方法可以用,比如在OD中直接将EIP的值设置为ChildProc的起始地址,或者将PE文件的EntryPoint修改为ChildProc的起始地址,但是很多时候,以上两种方法并不管用,除此之外还有一种方法,就是使用OD的实时调试模式。

1、设置OD为实时调试模式
图片描述
图片描述

2、将虚拟地址00171000(ChildProc函数在内存的位置)转换为文件偏移地址(在文件中的位置),
图片描述
得到的结果为400
图片描述

使用十六进制编辑器将对应的位置修改为CC并保存,如下图:
修改前
图片描述
修改并保存

图片描述

再次使用OD调试,在ResumeThread处下断点,单步步过
图片描述

因为OD已经被设置为实时调试器,所以当有异常触发时,会被系统自动调用,并将其附加到对应的进程上,此时就可以开始调试了,最后别忘了把CC恢复为原代码(0x6A)(Crtl+E快捷键),然后就可以愉快的调试啦!!
图片描述
图片描述

自我创建技术在病毒木马等恶意软件中非常常见,经常借助该技术躲避安全软件查杀,为了方便演示,所以示例程序比较简单,但是掌握各种调试技巧,在遇到复杂的程序时才能游刃有余,手到擒来!

//子进程要执行的代码
void ChildProc()
{
    MessageBox(NULL, L"This is a child process!", L"DebugMe2", MB_OK);
 
    ExitProcess(0);
}
 
//主函数
void _tmain(int argc, TCHAR *argv[])
{
    TCHAR                   szPath[MAX_PATH] = { 0, };
    STARTUPINFO                si = { sizeof(STARTUPINFO), };
    PROCESS_INFORMATION        pi = { 0, };
    CONTEXT                 ctx = { 0, };
 
    _tprintf(L"This is a parent process!\n");
 
    if (!GetModuleFileName(NULL, szPath, sizeof(TCHAR) * MAX_PATH))
    {
        printf("GetModuleFileName() failed! [%d]\n", GetLastError());
        return;
    }
 
    // 创建子进程
    if (!CreateProcess(
        szPath,
        NULL,
        NULL,
        NULL,
        FALSE,
        CREATE_SUSPENDED,
        NULL,
        NULL,
        &si,
        &pi))
    {
        printf("CreateProcess() failed! [%d]\n", GetLastError());
        return;
    }
 
    // 修改EIP
    ctx.ContextFlags = CONTEXT_FULL;
    if (!GetThreadContext(pi.hThread, &ctx))
    {
        printf("GetThreadContext() failed! [%d]\n", GetLastError());
        return;
    }
 
    ctx.Eip = (DWORD)ChildProc;
 
    if (!SetThreadContext(pi.hThread, &ctx))
    {
        printf("SetThreadContext() failed! [%d]\n", GetLastError());
        return;
    }
 
    // 恢复线程
    if (-1 == ResumeThread(pi.hThread))
    {
        printf("ResumeThread() failed! [%d]\n", GetLastError());
        return;
    }
 
    //等待返回
    WaitForSingleObject(pi.hProcess, INFINITE);
 
    CloseHandle(pi.hProcess);
    CloseHandle(pi.hThread);
}
//子进程要执行的代码
void ChildProc()
{
    MessageBox(NULL, L"This is a child process!", L"DebugMe2", MB_OK);
 
    ExitProcess(0);
}
 
//主函数
void _tmain(int argc, TCHAR *argv[])
{
    TCHAR                   szPath[MAX_PATH] = { 0, };
    STARTUPINFO                si = { sizeof(STARTUPINFO), };
    PROCESS_INFORMATION        pi = { 0, };
    CONTEXT                 ctx = { 0, };
 
    _tprintf(L"This is a parent process!\n");
 
    if (!GetModuleFileName(NULL, szPath, sizeof(TCHAR) * MAX_PATH))
    {
        printf("GetModuleFileName() failed! [%d]\n", GetLastError());
        return;
    }
 
    // 创建子进程
    if (!CreateProcess(
        szPath,
        NULL,
        NULL,
        NULL,
        FALSE,
        CREATE_SUSPENDED,
        NULL,

[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

最后于 2022-5-18 00:18 被寒江独钓_编辑 ,原因:
收藏
免费 5
支持
分享
最新回复 (1)
雪    币: 603
活跃值: (376)
能力值: ( LV3,RANK:25 )
在线值:
发帖
回帖
粉丝
2
自我创建 好像 不可以 注入到其他进程中,可用性上有待斟酌
2022-6-7 09:53
0
游客
登录 | 注册 方可回帖
返回
//