首页
社区
课程
招聘
[原创]一款木马释放器的简单分析及IDA的骚操作
发表于: 2020-10-30 18:17 7787

[原创]一款木马释放器的简单分析及IDA的骚操作

2020-10-30 18:17
7787

这是一款比较简单的木马,通过分析此样本可以训练分析思路、分析逻辑,并且加强IDA的使用.本人安全公司实习生,刚入圈几个月,所以文章中会有说的不对的地方,欢迎指出.择优吸收.

File: virus.exe
SHA1: 71b7322291b5a89d227b5cfe82106fce51036da2
SHA256: b48ebc54b9717bbe3a9de3fd5744c8ad1fdd3a26c7b47f6170b98f8abde9a744
LsHashS: 1155293a7b9091923b1d1511a8d9c17589bb1b55b4613bd55313ba7b3594b899
MD5: 00877507f0b812599868a647330d0630
分析环境 Windows7_Service Pack 1
分析工具 OD IDA 火绒剑 PEID

拖入PEID查一下有没有壳子

image-20201030162643091

yoda's Protector v1.02 (.dll,.ocx) -> Ashkbiz Danehkar (h) [Overlay] *

不了解,只知道有个加密壳

右键查看文件属性

image-20201030162957493

属性为空,至少确定了不是个正规公司开发的程序,直接上火绒剑吧

过滤FILE_open REG_openkey REG_getval FILE_read 行为(个人习惯,因为这几个行为基本没卵用)

image-20201030163049022

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

image-20201030163205846

样本启动了svchost.exe后直接结束了

而下方的行为显然不是svchost.exe应该有的,目测会有一段注入ShellCode的代码

到这里,这个程序基本上可以报毒了 : 静默运行+启动svchost.exe执行敏感代码+无任何文件描述信息

我们接下来要对这个样本进行稍微详细的分析,看看他具体干了什么

将样本拖入IDA32,分别查看字符串+导入表

image-20201030163843540

image-20201030163917123

发现字符串有很多URL还有请求头信息,

我们随便选一个:http://morphed.ru/static.php

去VT查一下

image-20201030164054405

很好,非常不正常!我们又可以为他扣掉几分(所以到现在还是在做黑白鉴定的工作 --_-- )

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

image-20201030164457491

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

image-20201030164604022

一段函数代码+一堆未知数据,暂时记住这个地方,后面可能会用到

简单起个名后,继续分析,我们看到memcpy下面的sub_407AC4紧接着就对这块内存进行了操作,跟进去看看函数内部情况

image-20201030164941108

没有再调用函数,反而进行了很多数据的运算,而一般这种情况不是加密就是解密,结合上面的行为分析结果,加上调用407AC4这个函数后并没有接收这个函数的返回值,推测此处对ShellCode进行了解密一类的操作

回到入口函数,观察下一行代码sub_407B02(pAlloc_, 0x490, LoadLibraryA, GetProcAddress);

参数有很明显的特点:

进入函数内部,为参数命名后,看一下代码

image-20201030165842727

哦吼,又是没有函数调用,全部在对数据进行操作,两层循环嵌套,循环内调用了GetProcAddress和LoadLibrary,根据传入的参数401000 490我们去看看401490都存了些啥

定位到401490D让其以字节显示,观察附近的数据,有了很明显的发现

image-20201030170634441

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

image-20201030171047096

image-20201030171054696

根据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各个窗口的值

image-20201030172633316

我们上文一直按照401000分析的,因为IDA静态分析我们并不知道VirtualAlloc分配到了哪里,所以我们只能忽略入口函数的那句memcpy,但是现在我们动态调试,就可以查看分配的那块内存了:eax = 0x200c0

反汇编窗口跳转到0x200C0,数据窗口跳转到0x20000 (4010C0之前有一段未知数据,我们要弄清楚那段数据)

image-20201030172946769

可以看到,call处的地址都变了,而且OD已经正确识别出了各个函数的名字,这也是为什么IDA无法F5的原因,这里的call的地址都是通过解密函数+地址修复函数进行处理过的

仔细观察,call后面的地址都是小于200C0的,正好对应上了我们20000~200C0这一段未知数据

数据窗口右键->长型->地址

image-20201030173215918

一切都变得清晰了,从20000~200C0是样本自身维护的一张导入表,以供ShellCode使用,400C0~42000包含了一些可执行的代码

点击M右键20000内存段->数据->备份->保存数据到文件

这样,ShellCode这段代码我们就dump下来了,接下来我们要对这段ShellCode进行分析

将dump下来的数据(后文称之为1.mem)拖入IDA32

点击Edit->Segments->Rebase Program进行基地址的修改

image-20201030173739806

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

点击OK,观察代码变化

image-20201030173855390

不再是一堆堆的字节数据了,变成了可读性较高的汇编代码,但是还有一处瑕疵

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弹出脚本选择框

image-20201030175109800

选择1.idc,点打开

image-20201030175135806

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

image-20201030175250337

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

按下F5观察伪源码

image-20201030175557342

这段代码就不详细说明了,大体逻辑就是判断系统位数,取出对应的系统文件,注入恶意代码,运行系统文件

我们的重点在注入到系统文件中的那部分代码是什么,这里我们不分析第二层代码,采用一个更加便捷的方式

我们此处依然采取dump 的方式进行提取,直接运行样本,不做任何阻拦,样本会创建一个被注入了恶意代码的svchost.exe进程,我们火绒剑选择svchost.exe,点击下方内存列表,右击0x20000这块内存,选择内存转储

PS:若火绒剑无法保存,可以尝试使用其他工具进行保存,需要注意的是svchost为64位程序,OD是用不了的,此处推荐PCHunter64

拷贝出来的dump文件才用相同方式拖入IDA,更改基址,批量命名,此处省略

如果操作没有错误,IDA解析后的代码应该如下:

image-20201030180540335

image-20201030180612608

image-20201030180627837

image-20201030180646252

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

image-20201030180753289

注册表操作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;
#define id 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;
#define id 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山水画编辑 ,原因:
收藏
免费 6
支持
分享
最新回复 (6)
雪    币: 83
活跃值: (1092)
能力值: ( LV8,RANK:130 )
在线值:
发帖
回帖
粉丝
2
很好 还可与i这样写ida脚本呢
2020-10-30 20:13
0
雪    币: 1484
活跃值: (14662)
能力值: ( LV12,RANK:380 )
在线值:
发帖
回帖
粉丝
3
killpy 很好 还可与i这样写ida脚本呢
谢大佬夸奖
2020-11-4 09:28
0
雪    币: 528
活跃值: (279)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
老哥  样本能给一份不    
2020-11-7 12:52
0
雪    币: 1484
活跃值: (14662)
能力值: ( LV12,RANK:380 )
在线值:
发帖
回帖
粉丝
5
AaIizzwell 老哥 样本能给一份不 [em_13]
用sha1和hash去找吧,公司样本不能直接发出来的
2020-11-7 12:55
0
雪    币: 528
活跃值: (279)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
哦哦  好的 我用HASH没搜到这个文件  不过还是谢谢啦
2020-11-7 12:57
0
雪    币: 1484
活跃值: (14662)
能力值: ( LV12,RANK:380 )
在线值:
发帖
回帖
粉丝
7
AaIizzwell 哦哦 好的 我用HASH没搜到这个文件 不过还是谢谢啦[em_67]
要是没搜到那可能是用户个人文件,这个没办法传了,抱歉
2020-11-7 13:05
0
游客
登录 | 注册 方可回帖
返回
//