这是一款比较简单的木马,通过分析此样本可以训练分析思路、分析逻辑,并且加强IDA的使用.本人安全公司实习生,刚入圈几个月,所以文章中会有说的不对的地方,欢迎指出.择优吸收.
File: virus.exe
SHA1: 71b7322291b5a89d227b5cfe82106fce51036da2
SHA256: b48ebc54b9717bbe3a9de3fd5744c8ad1fdd3a26c7b47f6170b98f8abde9a744
LsHashS: 1155293a7b9091923b1d1511a8d9c17589bb1b55b4613bd55313ba7b3594b899
MD5: 00877507f0b812599868a647330d0630
分析环境 Windows7_Service Pack 1
分析工具 OD IDA 火绒剑 PEID
拖入PEID查一下有没有壳子

yoda's Protector v1.02 (.dll,.ocx) -> Ashkbiz Danehkar (h) [Overlay] *
不了解,只知道有个加密壳
右键查看文件属性

属性为空,至少确定了不是个正规公司开发的程序,直接上火绒剑吧
过滤FILE_open REG_openkey REG_getval FILE_read
行为(个人习惯,因为这几个行为基本没卵用)

不得不说,火绒剑
真是方便,程序行为十分清晰了

样本启动了svchost.exe
后直接结束了
而下方的行为显然不是svchost.exe
应该有的,目测会有一段注入ShellCode的代码
到这里,这个程序基本上可以报毒了 : 静默运行+启动svchost.exe执行敏感代码+无任何文件描述信息
我们接下来要对这个样本进行稍微详细的分析,看看他具体干了什么
将样本拖入IDA32,分别查看字符串+导入表


发现字符串有很多URL
还有请求头信息,
我们随便选一个:944K9s2c8@1M7q4)9K6b7g2)9J5c8W2)9J5c8X3#2G2M7Y4m8Z5k6h3c8Q4x3X3g2J5N6g2)9J5c8Y4y4@1j5i4c8A6j5#2)9J5k6i4m8Z5M7l9`.`.
去VT查一下

很好,非常不正常!我们又可以为他扣掉几分(所以到现在还是在做黑白鉴定的工作 --_-- )
该步入正题了,上面查看文件属性,文件大小不是很大,字符串和导入表信息也不多,因此我们决定从入口点开始进行分析,在IDA中找到入口点按下F5分析伪源码 (个人比较喜欢F5,但是这是不好的,遇到强度高的样本,F5反而会增加你的工作量)

可以看到上来就开始开辟内存,拷贝0x00401000
处的数据,我们去看看401000
存了些啥

一段函数代码+一堆未知数据,暂时记住这个地方,后面可能会用到
简单起个名后,继续分析,我们看到memcpy下面的sub_407AC4
紧接着就对这块内存进行了操作,跟进去看看函数内部情况

没有再调用函数,反而进行了很多数据的运算,而一般这种情况不是加密就是解密,结合上面的行为分析结果,加上调用407AC4
这个函数后并没有接收这个函数的返回值,推测此处对ShellCode进行了解密一类的操作
回到入口函数,观察下一行代码sub_407B02(pAlloc_, 0x490, LoadLibraryA, GetProcAddress);
参数有很明显的特点:
进入函数内部,为参数命名后,看一下代码

哦吼,又是没有函数调用,全部在对数据进行操作,两层循环嵌套,循环内调用了GetProcAddress和LoadLibrary
,根据传入的参数401000 490
我们去看看401490
都存了些啥
定位到401490
按D
让其以字节显示,观察附近的数据,有了很明显的发现

下面是一个个函数名字符串,我们按A Alt+A
把这些数据以字符串进行展示,观察结果


根据401490
附近的字符串,我们最终可以推测出sub_407B02
处的函数用于加载函数,模拟导入表功能,将其命名FixImport
回到主函数继续分析:return ((int (__stdcall *)(_DWORD))(pAlloc_0 + 0xC0))(sub_407992);
可以看到这行代码用于执行4010C0
出的函数,传入参数为407992
,一个函数地址
我们之前记得401000
向下是由一段数据+一段函数代码组成
而这行代码以函数指针的形式调用了4010C0
的代码,却不是直接写成函数
由此我们验证了上文对401000
处数据为ShellCode的猜想,接下来我们则需要知道4010C0
干了什么
进入4010C0
,在4010C0
处按P
,使IDA识别为函数
按F5,解析为伪源码,发现失败,提示call的地址找不到?这是怎么回事?
还记得上文中有两个函数分别对401000
附近的数据进行了解密+修复导入函数一类的操作吗?
没错,这段代码只有在401000
段被正确修复后才能执行,至此,我们需要使用OD进行动态调试来dump出401000处的数据
打开OD,拖入样本,在地址0040798E
处下断点 (4010C0处为函数头部,在40798E处调用了这个函数)
观察OD各个窗口的值

我们上文一直按照401000
分析的,因为IDA静态分析我们并不知道VirtualAlloc分配到了哪里,所以我们只能忽略入口函数的那句memcpy
,但是现在我们动态调试,就可以查看分配的那块内存了:eax = 0x200c0
反汇编窗口跳转到0x200C0
,数据窗口跳转到0x20000
(4010C0之前有一段未知数据,我们要弄清楚那段数据)

可以看到,call处的地址都变了,而且OD已经正确识别出了各个函数的名字,这也是为什么IDA无法F5的原因,这里的call的地址都是通过解密函数+地址修复函数进行处理过的
仔细观察,call后面的地址都是小于200C0
的,正好对应上了我们20000~200C0
这一段未知数据
数据窗口右键->长型->地址

一切都变得清晰了,从20000~200C0
是样本自身维护的一张导入表,以供ShellCode使用,400C0~42000
包含了一些可执行的代码
点击M
右键20000
内存段->数据->备份->保存数据到文件
这样,ShellCode这段代码我们就dump下来了,接下来我们要对这段ShellCode进行分析
将dump下来的数据(后文称之为1.mem)拖入IDA32
点击Edit->Segments->Rebase Program进行基地址的修改

由于OD中内存申请地址为0x20000
我们也要在IDA中设置为0x20000
以保证IDA能正确解析汇编代码
点击OK,观察代码变化

不再是一堆堆的字节数据了,变成了可读性较高的汇编代码,但是还有一处瑕疵
20000~200C0
处应该有一些函数的,IDA这里没有为我们解析,这会让我们分析工作量增加,我们接下来要使用IDA的脚本执行功能:
点击File->Produce FIle->Dump database to IDC file...->保存
此时,我们dump文件同目录下会生成一个与dump文件同名的idc文件:1.idc
用notepad++将其打开
我们会看到这样一段代码,把函数内容全部删除,只留下Bytes(); // individual bytes (code,data)
接下来Ctrl+F
搜索Bytes
,我们看看这个Bytes
函数干了什么
可以看到Bytes
调用了Bytes_0
,我们再搜索Bytes_0
去看看他的内容
可以看到一大堆函数代码,不要管,全部删除
接下来我们要用到一个函数 set_name (地址,"名字");
这是IDA提供的接口,用于为地址命名
我们需要将20000~200C0
处的函数全部命名
回到OD,数据窗口定位到20000
,复制全部函数数据
将上面这段数据以set_name (xxx,"xxx");
的格式进行替换,具体替换方法可以手动替换,也可以正则替换,看各位喜好
替换完的结果:
将这段数据复制到Bytes_0
函数体中,结果如下
保存,退出,回到IDA,按Alt+F7
弹出脚本选择框

选择1.idc
,点打开

可以神奇的发现,20000
开始的地址已经被IDA正确解析,在200C0
处按P
,让IDA将其解释为一个函数头部

这样就是我们最终弄好的结果,IDA可以正确解析这段代码,我们看的也会特别清晰
按下F5观察伪源码

这段代码就不详细说明了,大体逻辑就是判断系统位数,取出对应的系统文件,注入恶意代码,运行系统文件
我们的重点在注入到系统文件中的那部分代码是什么,这里我们不分析第二层代码,采用一个更加便捷的方式
我们此处依然采取dump 的方式进行提取,直接运行样本,不做任何阻拦,样本会创建一个被注入了恶意代码的svchost.exe
进程,我们火绒剑选择svchost.exe,点击下方内存列表,右击0x20000
这块内存,选择内存转储
PS:若火绒剑无法保存,可以尝试使用其他工具进行保存,需要注意的是svchost为64位程序,OD是用不了的,此处推荐PCHunter64
拷贝出来的dump文件才用相同方式拖入IDA,更改基址,批量命名,此处省略
如果操作没有错误,IDA解析后的代码应该如下:




到了这里样本的最终行为已经毫无遮拦了,我们甚至不用进入F5分析逻辑,只需简单的观察字符串即可分析出这个样本的大致行为逻辑

注册表操作API+启动项目录字符串 = 添加开机自启
网络操作相关API用于发送请求,可能是下载一个恶意程序亦或是上传一段用户隐私数据
整篇文章对于代码的分析很少,各位如果想要细致分析可以自行抠代码,没有了保护,所有写法已经是透明的了,因此继续逆向只是个体力活,我这里就不演示了
主要是给初学的小白演示下这种多层代码释放嵌套的样本怎么处理,已经IDA的强大功能
择优吸收
static main(void)
{
/
/
set
'loading idc file'
mode
set_inf_attr(INF_GENFLAGS, INFFL_LOADIDC|get_inf_attr(INF_GENFLAGS));
GenInfo();
/
/
various settings
Segments();
/
/
segmentation
Enums();
/
/
enumerations
Structures();
/
/
structure types
ApplyStrucTInfos();
/
/
structure
type
infos
Patches();
/
/
manual patches
SegRegs();
/
/
segment register values
Bytes();
/
/
individual bytes (code,data)
Functions();
/
/
function definitions
/
/
clear
'loading idc file'
mode
set_inf_attr(INF_GENFLAGS, ~INFFL_LOADIDC&get_inf_attr(INF_GENFLAGS));
}
static main(void)
{
/
/
set
'loading idc file'
mode
set_inf_attr(INF_GENFLAGS, INFFL_LOADIDC|get_inf_attr(INF_GENFLAGS));
GenInfo();
/
/
various settings
Segments();
/
/
segmentation
Enums();
/
/
enumerations
Structures();
/
/
structure types
ApplyStrucTInfos();
/
/
structure
type
infos
Patches();
/
/
manual patches
SegRegs();
/
/
segment register values
Bytes();
/
/
individual bytes (code,data)
Functions();
/
/
function definitions
/
/
clear
'loading idc file'
mode
set_inf_attr(INF_GENFLAGS, ~INFFL_LOADIDC&get_inf_attr(INF_GENFLAGS));
}
static main(void)
{
Bytes();
/
/
individual bytes (code,data)
}
static main(void)
{
Bytes();
/
/
individual bytes (code,data)
}
static Bytes(void) {
Bytes_0();
end_type_updating(UTP_STRUCT);
}
static Bytes(void) {
Bytes_0();
end_type_updating(UTP_STRUCT);
}
static Bytes_0(void) {
auto x;
update_extra_cmt (
0X20000
, E_PREV
+
0
,
"; File Name : G://1.mem"
);
update_extra_cmt (
0X20000
, E_PREV
+
1
,
"; Format : Binary file"
);
update_extra_cmt (
0X20000
, E_PREV
+
2
,
"; Base Address: 0000h Range: 0000h - 2000h Loaded length: 2000h"
);
create_dword (
0X20000
);
create_dword (
0X20004
);
create_dword (
0X20008
);
create_dword (
0X2000C
);
create_dword (
0X20010
);
create_dword (
0X20014
);
create_dword (
0X20018
);
create_dword (
0X2001C
);
create_dword (
0X20020
);
create_dword (
0X20024
);
create_dword (
0X20028
);
create_dword (
0X2002C
);
create_word (
0X20036
);
create_word (
0X2003A
);
create_dword (
0X2003C
);
make_array (
0X2003C
,
0X9
);
create_strlit (
0X20060
,
0X20068
);
set_name (
0X20060
,
"a753"
);
create_strlit (
0X20068
,
0X20094
);
set_name (
0X20068
,
"aSystem32Wuaucl"
);
create_strlit (
0X20094
,
0X200C0
);
set_name (
0X20094
,
"aSyswow64Svchos"
);
create_insn (
0X200C0
);
create_insn (x
=
0X200C3
);
op_hex (x,
1
);
create_insn (
0X2014F
);
create_insn (
0X203C9
);
set_cmt (
0X2041D
,
"Trap to Debugger"
,
0
);
create_insn (x
=
0X2041D
);
op_hex (x,
0
);
create_insn (
0X2041E
);
create_insn (
0X20424
);
create_insn (
0X2042A
);
create_insn (
0X20430
);
create_insn (
0X20436
);
create_insn (
0X2043C
);
create_insn (
0X20442
);
create_insn (
0X20448
);
create_insn (
0X2044E
);
create_insn (
0X20454
);
create_insn (
0X2045A
);
create_insn (
0X20460
);
create_insn (
0X20466
);
create_insn (
0X2046C
);
create_insn (
0X20472
);
create_insn (
0X20478
);
create_insn (
0X2047E
);
create_insn (
0X20484
);
create_insn (
0X2048A
);
create_dword (x
=
0X20490
);
op_plain_offset (x,
0
,
0
);
op_plain_offset (x,
128
,
0
);
create_dword (
0X20494
);
make_array (
0X20494
,
0X2
);
create_byte (
0X2049D
);
make_array (
0X2049D
,
0X3
);
create_dword (x
=
0X204A0
);
op_plain_offset (x,
0
,
0
);
op_plain_offset (x,
128
,
0
);
create_dword (x
=
0X204A4
);
op_plain_offset (x,
0
,
0
);
op_plain_offset (x,
128
,
0
);
make_array (
0X204A8
,
0X8
);
make_array (
0X204B2
,
0X2
);
create_dword (
0X204B4
);
make_array (
0X204B4
,
0X6
);
create_dword (x
=
0X204CC
);
op_plain_offset (x,
0
,
0
);
op_plain_offset (x,
128
,
0
);
create_dword (x
=
0X204D0
);
op_plain_offset (x,
0
,
0
);
op_plain_offset (x,
128
,
0
);
create_byte (
0X204D5
);
make_array (
0X204D5
,
0X3
);
make_array (
0X204DA
,
0X2
);
make_array (
0X204DE
,
0X2
);
make_array (
0X204E2
,
0X2
);
create_dword (x
=
0X204E4
);
op_plain_offset (x,
0
,
0
);
op_plain_offset (x,
128
,
0
);
create_dword (x
=
0X204E8
);
op_plain_offset (x,
0
,
0
);
op_plain_offset (x,
128
,
0
);
make_array (
0X204EE
,
0X2
);
make_array (
0X204F2
,
0X2
);
make_array (
0X204F6
,
0X2
);
make_array (
0X204FA
,
0X6
);
create_dword (x
=
0X20500
);
op_plain_offset (x,
0
,
0
);
op_plain_offset (x,
128
,
0
);
create_dword (x
=
0X20504
);
op_plain_offset (x,
0
,
0
);
op_plain_offset (x,
128
,
0
);
create_byte (
0X20509
);
make_array (
0X20509
,
0X3
);
create_dword (x
=
0X2050C
);
op_plain_offset (x,
0
,
0
);
op_plain_offset (x,
128
,
0
);
make_array (
0X20512
,
0X2
);
create_byte (
0X20515
);
make_array (
0X20515
,
0X3
);
make_array (
0X20519
,
0X7
);
create_strlit (
0X20522
,
0X20533
);
set_name (
0X20522
,
"aNtdelayexecuti"
);
create_strlit (
0X20536
,
0X2053E
);
set_name (
0X20536
,
"aZwclose"
);
create_byte (
0X2053F
);
create_strlit (
0X20541
,
0X20550
);
set_name (
0X20541
,
"aWcreatesection"
);
create_strlit (
0X20552
,
0X20565
);
set_name (
0X20552
,
"aZwmapviewofsec"
);
create_strlit (
0X20569
,
0X20582
);
set_name (
0X20569
,
"aWqueryinformat"
);
create_word (
0X20582
);
create_strlit (
0X20585
,
0X20593
);
set_name (
0X20585
,
"aWresumethread"
);
create_strlit (
0X20597
,
0X205AB
);
set_name (
0X20597
,
"aWunmapviewofse"
);
create_strlit (
0X205AC
,
0X205B6
);
set_name (
0X205AC
,
"aNtdllDll"
);
create_strlit (
0X205B8
,
0X205C4
);
set_name (
0X205B8
,
"aClosehandle"
);
create_strlit (
0X205C7
,
0X205D2
);
set_name (
0X205C7
,
"aReatefilew"
);
create_strlit (
0X205D5
,
0X205E3
);
set_name (
0X205D5
,
"aReateprocessw"
);
create_strlit (
0X205E7
,
0X205F2
);
set_name (
0X205E7
,
"aXitprocess"
);
create_word (
0X205F2
);
create_strlit (
0X205F4
,
0X20607
);
set_name (
0X205F4
,
"aGetmodulefilen"
);
create_byte (
0X20609
);
make_array (
0X20609
,
0X3
);
create_strlit (
0X2060C
,
0X2061B
);
set_name (
0X2060C
,
"aTmodulehandlew"
);
create_strlit (
0X2061E
,
0X2062F
);
set_name (
0X2061E
,
"aGetthreadconte"
);
create_strlit (
0X20633
,
0X20647
);
set_name (
0X20633
,
"aEtwindowsdirec"
);
create_strlit (
0X2064B
,
0X20662
);
set_name (
0X2064B
,
"aEtenvironmentv"
);
create_strlit (
0X20664
,
0X20671
);
set_name (
0X20664
,
"aVirtualalloc"
);
create_byte (
0X20673
);
create_strlit (
0X20674
,
0X20680
);
set_name (
0X20674
,
"aVirtualfree"
);
create_strlit (
0X20682
,
0X2068B
);
set_name (
0X20682
,
"aLstrcatw"
);
create_strlit (
0X2068C
,
0X20699
);
set_name (
0X2068C
,
"aKernel32Dll"
);
make_array (
0X20699
,
0X3
);
create_dword (
0X2069C
);
make_array (
0X2069C
,
0X25A
);
create_dword (x
=
0X21004
);
op_plain_offset (x,
0
,
0
);
op_plain_offset (x,
128
,
0
);
create_word (
0X2100A
);
create_dword (
0X2100C
);
make_array (
0X2100C
,
0X3FD
);
}
static Bytes_0(void) {
auto x;
update_extra_cmt (
0X20000
, E_PREV
+
0
,
"; File Name : G://1.mem"
);
update_extra_cmt (
0X20000
, E_PREV
+
1
,
"; Format : Binary file"
);
update_extra_cmt (
0X20000
, E_PREV
+
2
,
"; Base Address: 0000h Range: 0000h - 2000h Loaded length: 2000h"
);
create_dword (
0X20000
);
create_dword (
0X20004
);
create_dword (
0X20008
);
create_dword (
0X2000C
);
create_dword (
0X20010
);
create_dword (
0X20014
);
create_dword (
0X20018
);
create_dword (
0X2001C
);
create_dword (
0X20020
);
create_dword (
0X20024
);
create_dword (
0X20028
);
create_dword (
0X2002C
);
create_word (
0X20036
);
create_word (
0X2003A
);
create_dword (
0X2003C
);
make_array (
0X2003C
,
0X9
);
create_strlit (
0X20060
,
0X20068
);
set_name (
0X20060
,
"a753"
);
create_strlit (
0X20068
,
0X20094
);
set_name (
0X20068
,
"aSystem32Wuaucl"
);
create_strlit (
0X20094
,
0X200C0
);
set_name (
0X20094
,
"aSyswow64Svchos"
);
create_insn (
0X200C0
);
create_insn (x
=
0X200C3
);
op_hex (x,
1
);
create_insn (
0X2014F
);
[注意]看雪招聘,专注安全领域的专业人才平台!
最后于 2020-10-30 18:31
被SSH山水画编辑
,原因: