首页
论坛
课程
招聘
[原创]病毒木马常用手段之自我创建
2022-5-18 00:17 3596

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

2022-5-18 00:17
3596

前言

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

一、编译源码

程序源代码如下
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
//子进程要执行的代码
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);
}

二、程序编译好以后,我们使用OD进行调试分析

根据特征找到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快捷键),然后就可以愉快的调试啦!!
图片描述
图片描述

四、总结

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


【看雪培训】《Adroid高级研修班》2022年夏季班招生中!

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