记一次钓鱼邮件-分析(上)
2023-6-14 23:45:39 Author: 渗透安全团队(查看原文) 阅读量:8 收藏

前言

最近项目上收到了许多钓鱼邮件,部门大佬对其进行分析后,本文是对部门大佬的分析进行一个复现。从中学习到了很多。这里团队的Snab师傅就带大家一起学习一下,如若有错请指正,一起学习进步。

一共分为两篇:

针对于钓鱼邮件当中的原文件进行分析

针对释放后的木马文件进行分析

思路

1、先将其解压,上传沙箱帮助分析             
2、通过ida、xdebug进行分析             
3、首先判断其语言             
4、分析其所调用的api函数             
5、分析应用行为             
6、找到外联地址

沙箱分析

在线沙箱地址           

https://s.threatbook.com/ --微步          可以看到该exe释放了3个文件            
分别是:            
Bplnfg.exe            
xxxx.pdf            
wsqmcons.exe            
           
其中 使用了Bplnfg.exe 调用了wsqmcons.exe 和 ping.exe            
看一下微步沙箱的进程分析

该钓鱼文件执行了以下步骤            
1、利用释放的Bplnfg.exe  运行了 释放的 xxx.pdf            
2、Bplnfg.exe 运行了 释放的wsqmcons.exe            
3、ping -5 8.8.8.8 并删除了自生 
         
           
通过 BpLnfg.exe /c start、BpLnfg.exe /c ping、del 等命令            
可以大致猜测BpLnfg.exe 大概率是一个类似commond.exe的东西            
           
而沙箱没有分析出来外联的地址            
则可能存在以下情况:            
1、反沙箱            
通过检测当前运行环境是否正常,如果不正常则直接结束线程            
调用sleep函数进行延时,沙箱的分析是有时间限制的,sleep延时个30分钟就能过沙箱检测            
2、该初始的钓鱼文件并不是藏有shellcode的文件            
而其释放的wsqmcons.exe可能才是最终的木马文件

判断该木马所使用的语言

使用工具:           
ExeinfoPe、idea、CFF exploer等

ExeinfoPe  

可以看到其是使用 Golang语言编写的 一个exe

Ida  

通过idea反编译的到的符号表可以看到 有很多 golang的特征              
可以完全确定其使用的语言就是golang

静态分析

以下是通过ida对木马进行 反编译得到的代码进行大致的猜测

一个程序需要运行起来都必须需要一个 主函数入口            
一般都为main函数            
该木马没有混淆可以直接通过反编译看到其使用的函数

Main()  

main_Hvdf_HCzKr() --隐藏窗口  

先从 main函数入手                
               
打开看到其main函数的内容长这样    
                

void __cdecl main_main(){  main_Hvdf_HCzKr();  main_Start_Func_HCzKr((__int64)&byte_55859B, 40LL, (__int64)&byte_54F93F, 6LL, 0LL, 0LL, 30LL, 60LL, 10LL);  从第一个main_Hvdf_Hczkr() 开始void main_Hvdf_HCzKr(){  main_ShowConsoleAsync(0LL);}ShowConsoleAsync是golang里面隐藏/显示windows系统下的黑色命令窗口

         
               
以下是钓鱼文件中 main_ShowConsoleAsync 具体的实现方法                
但他要怎么做 做什么我们只需要知道 他是为了隐藏窗口就足够了,我们的目的不在这里                

void __golang main_ShowConsoleAsync(__int64 a1)                {                  github_com_gonutz_ide_w32_GetConsoleWindow();                  if ( v1 )                  {                    v4 = v1;                    github_com_gonutz_ide_w32_GetWindowThreadProcessId(v1);                    github_com_gonutz_ide_w32_GetCurrentProcessId();                    if ( v2 == v3 )                      github_com_gonutz_ide_w32_ShowWindowAsync(v4, a1);                  }

main_Start_Func_HCzKr() --核心  

Copy_cmd_pLTZN() --复制cmd 

可以看到这个函数前面声明了很多变量 做了一些判断                  
我们可以很清楚的看到图里有一个函数
                 

Copy_cmd_pLTZN();                                    __int128 main_Copy_cmd_pLTZN()                  {                    main_Get_Home_pLTZN();                    v5 = v1;                    v7 = v0;                    v2 = main_RandStringBytesRmndr_pLTZN(6LL);                     v6 = runtime_concatstring4(0LL, v7, v5, (__int64)&byte_55204B, 17LL, v2, v3, (__int64)&byte_54F497, 4LL);                    main_CopyFileddd_pLTZN(v6, v4, (__int64)&dword_5551A4, 27LL);                    *(_QWORD *)&result = v6;                    *((_QWORD *)&result + 1) = v4;                    return result;                  }                                   main_Get_Home_pLTZN --获取环境变量当中的值                  {                    v6 = os_Getenv((__int64)&byte_5500E5, 9LL);                    v2 = os_Getenv((__int64)&byte_54FD9B, 8LL);                    v0 = runtime_concatstring2(0LL, v6, v3, v2, v3);                    v1 = v5;                    if ( !v5 )                    {                      v0 = os_Getenv((__int64)&word_55084A, 11LL);                      v1 = v4;                    }                    *(_QWORD *)&result = v0;                    *((_QWORD *)&result + 1) = v1;                    return result;                  }     

RandStringBytesRmndr_pLTZN --生成一个随机字符串                  
runtime_concatstring--将生成的随机字符串与其他进行拼接                  
CopyFileddd_pLTZN--将文件复制文件                  
                 
结合反编译代码和其函数名字 Copy_cmd可以大致猜测:                  
生成一串随机字符串xxx,并将cmd复制到某个目录下重命名为xxx.exe

GetCurrentAbPathByExecutable() --读取文件路径\目录遍历  

回到main_Start_Func_HCzKr()当中 来看这个函数                  

main_GetCurrentAbPathByExecutable_pLTZN();                  {                    os_Executable(); --获取当前运行环境的路径                    v6 = v2;                    v7 = v1;                    if ( v3 )                    {                      v8[0] = *(_QWORD *)(v3 + 8);                      v8[1] = v5;                      v5 = log_Fatal((__int64)v8, 1LL, 1LL);                    }                    v4 = path_filepath_Dir(v7, v6); --获取当前运行环境的上级目录                    path_filepath_EvalSymlinks(v4, v5); --获取所执行的文件的绝对路径                    return v6;                  }                  

                 
通过几个golang当中"path/filepath"包下的函数 os.Executable()、filepath.Dir()、filepath.EvalSymlinks()                  
大致可以猜测其是在读取文件路径\目录遍历

main_Run_normal_file_HCzK() --写文件->打开文件  
 {                    v9 = runtime_concatstring2(0LL, (__int64)&byte_54F873, 6LL, a5, a6); --字符串拼接                    v6 = HCzKr_Asset(v9, v10);                    io_ioutil_WriteFile(a3, a4, v6, v7, v8, 493);                    main_Open_normal_file_pLTZN(a1, a2, a3, a4, 0LL, 0LL);                   }

HCzKr_Asset --暂时没看懂

io_ioutil_WriteFile --创建文件写入数据

main_Open_normal_file_pLTZN --打开创建的文件

main_Run_and_Task_HCzKr --释放木马文件并执行  
{                    random_path_HCzKr = main_Get_random_path_HCzKr((__int64)&dword_55300C, 20LL, 0LL, 0LL);                    main_Get_muma_file_HCzKr(a1, a2, random_path_HCzKr);                    main_Update_task_HCzKr(random_path_HCzKr);                  }
main_Get_random_path_HCzKr
main_Get_Home_HCzKr(); v4 = runtime_concatstring2(0LL, v8, v10, a1, a2); if ( !a4 ) { main_Get_random_name_HCzKr(); } *(_QWORD *)&result = path_filepath_Join((__int64)v15, 2LL, 2LL); *((_QWORD *)&result + 1) = v12; main_Get_Home_HCzKr 与上面的GetCurrentAbPathByExecutable.Get_Home大致一样 main_Get_random_name_HCzKr 与GetCurrentAbPathByExecutable.RandStringBytesRmndr大致一样 path_filepath_Join golang当中"path/filepath"的函数 用于路径拼接
main_Get_muma_file_HCzKr --创建木马文件
{ v11 = runtime_concatstring2(0LL, (__int64)&byte_54F873, 6LL, a5, a6); HCzKr_Asset(v11, v12); io_ioutil_WriteFile(a3, a4, v8, v9, v10, 493); if ( a8 ) main_Open_normal_file_pLTZN(a1, a2, a3, a4, a7, a8); else main_Open_normal_file_pLTZN(a1, a2, a3, a4, 0LL, 0LL); }
main_Update_task_HCzKr --创建计划任务

可以看到Update_task_HCzKr当中多处引用了来自github上面的函数                 

github_com_capnspacehook_taskmaster_Connect                      // Connect connects to the local Task Scheduler service, using the current                      连接到本地任务计划程序服务                      // token for authentication. This function must run before any other functions                      用于身份验证的令牌                                   github_com_capnspacehook_taskmaster__ptr_TaskService_GetRegisteredTasks                            // GetRegisteredTasks enumerates the Task Scheduler database for all currently                     registered tasks.                            所有当前注册的任务枚举任务计划程序数据库                                   github_com_capnspacehook_taskmaster_TaskService_NewTaskDefinition                            // NewTaskDefinition returns a new task definition that can be used to register a new task.                            返回可用于注册新任务的新任务定义                            // Task settings and properties are set to Task Scheduler default values.                            任务设置和属性设置为“任务计划程序”默认值                                              github_com_capnspacehook_taskmaster__ptr_TaskService_UpdateTask                            //UpdateTask updates a registered task.                            更新注册表                                   github_com_capnspacehook_taskmaster__ptr_TaskService_CreateTask                            //CreateTask creates a registered task on the connected computer.                            在连接的计算机上创建一个已注册的任务

具体做了什么事情,还是得通过调试去看

main_Hide_clean_pLTZN --执行命令  
 {                    v6 = os_exec_Command(a1, a2, (__int64)v7, 10LL, 10LL);                    v4 = (_BYTE *)runtime_newobject((__int64)&RTYPE_syscall_SysProcAttr);                    *v4 = 1;                    v5 = v6;                    if ( dword_7B7D70 )                      runtime_gcWriteBarrier();                    else                      *(_QWORD *)(v6 + 152) = v4;                    os_exec__ptr_Cmd_Start(v5);                    }

动态调试

隐藏窗口  

可以看到当我们将木马文件丢到 x64dbg里面的时候他有一个窗口

在任意一处下断点后运行后 窗口不见了              
但是程序还在运行              
那么则证实了对静态分析当中的 main_Hvdf_HCzKr 将窗口进行了隐藏

按照反编译出来得到的地址,这里就是木马文件主函数的入口地点

获取计算机当前用户目录  

复制CMD.exe  

获取了一个字符串

将其释放到 C:\Users\wowfk\AppData\Roaming\ 下面

将C\windows\system32\cmd.exe复制到C:\Users\wowfk\AppData\Roaming\BpLnfg.exe

往下走可以看到此处调用了 readfile和writeFile              
读取cmd.exe,将内容写进BpLnfg.exe

在 Win64 里使用下面寄存器来传递参数:              
    rcx - 第 1 个参数               
    rdx - 第 2 个参数               
    r8 - 第 3 个参数               
    r9 - 第 4 个参数

创建xxx.PDF文件  

通过复制cmd后得到的BpLnfg.exe 打开该pdf文件

创建木马文件 

启动木马文件

查看该环境是否联网并删除自身


总结

本次对这个释放文件的木马也就是出售的木马的分析到这也就结束了,如果要说这个木马文件有什么缺点的话:就是太过明显了,释放出来的pdf文件和原来的文件名称都不一致。下篇文章会对初始木马释放的shellcode木马进行分析。如果在日常防护当中,有人中了钓鱼邮件并点击了,请第一时间进行断网处理(断开互联网,有插入网线的也拔了)!!!


付费圈子

欢 迎 加 入 星 球 !

代码审计+免杀+渗透学习资源+各种资料文档+各种工具+付费会员

进成员内部群

星球的最近主题和星球内部工具一些展示

加入安全交流群

                               

关 注 有 礼

关注下方公众号回复“666”可以领取一套领取黑客成长秘籍

 还在等什么?赶紧点击下方名片关注学习吧!


干货|史上最全一句话木马

干货 | CS绕过vultr特征检测修改算法

实战 | 用中国人写的红队服务器搞一次内网穿透练习

实战 | 渗透某培训平台经历

实战 | 一次曲折的钓鱼溯源反制

免责声明
由于传播、利用本公众号渗透安全团队所提供的信息而造成的任何直接或者间接的后果及损失,均由使用者本人负责,公众号渗透安全团队及作者不为承担任何责任,一旦造成后果请自行承担!如有侵权烦请告知,我们会立即删除并致歉。谢谢!
好文分享收藏赞一下最美点在看哦

文章来源: http://mp.weixin.qq.com/s?__biz=MzkxNDAyNTY2NA==&mid=2247506218&idx=3&sn=28679c7829c2d497505fde3415138500&chksm=c1762485f601ad9338e315b1efce4564f4182543f84469419525f8138500c9837058259d8bbb#rd
如有侵权请联系:admin#unsafe.sh