某远程加载马样本分析学习
前言
在freebuf上看到一篇名为:一个CS马伪装下的loader样本分析
跟着复现了一下,由于底子不够分析的可能不全。
用到的工具
Exeinfo
Detect Easy
IDA 7.5
API Monitor v2.0
Process Monitor
PEview
OD
分析过程
根据文章给出的样本下载链接查看:https://app.any.run/tasks/ffc1ecff-e461-4474-8352-551db7e7b06f/
先在app.any.run看了一下分析结果
请求了两个URL,其中一个是二进制数据
http://8.210.181.149:16678/9jhQ
目前得到的信息:
IP:8.210.181.149 - 归属地:香港
样本标记:Cobalt strike
执行方法疑似远程加载payload
微步社区查询该IP,已被标记
viz.greynoise.io未标记cs
VT查杀
将样本下载到本地分析
md5 hash:3f37fc95aa5c8f7c304aa0dfc3ffbf2e
打开属性看到个数字签名
Detect lt Easy拖进去查看,没有加壳,VC++写的
查看导入的dll,就发现一个kernel.dll。windows API隐藏导入
该技术参考链接:https://blog.scrt.ch/2020/07/15/engineering-antivirus-evasion-part-ii/
IDA静态分析
尝试搜索main函数,发现可以直接找到入口点(估计freebuf那篇文章作者用的是IDA 7.0没找到入口点)
跟到_main_0函数
首先跟踪__CheckForDebuggerJustMyCode
dword_517944值看不到定义的是什么
往下面能看到调用了一堆API
先不看这些API,继续分析_main_0。_CheckForDebuggerJustMycode
后执行VirtualAlloc分配内存
之后调用_memmove函数,跟踪其unk_515000指针
数组合并,hex转换回字符串
在解码后看到远程下载链接的路径9jhQ
在payload尾部可以看见IP
j__memmove函数分析,把VirtualAlloc分配内存的指针传入,把&unk_515000指针传入该函数,传入大小799
memmove函数为一个解码payload用的函数
void *__cdecl memmove(void *a1, const void *Src, size_t Size)
{
const __m128i *v3; // esi
size_t v4; // ecx
__m128i *v5; // edi
void *result; // eax
__int64 v7; // xmm1_8
__m128i v8; // xmm1
const __m128i *v9; // esi
__m128i v10; // xmm3
__m128i v11; // xmm0
__m128i v12; // xmm5
const __m128i *v13; // esi
__m128i v14; // xmm1
const __m128i *v15; // esi
__m128i v16; // xmm3
__m128i v17; // xmm0
__m128i v18; // xmm5
__m128i v19; // xmm1
const __m128i *v20; // esi
__m128i v21; // xmm3
__m128i v22; // xmm0
__m128i v23; // xmm5
__m128i v24; // xmm1
__int32 v25; // eax
__int64 v26; // xmm1_8
char v27; // dl
size_t v28; // ecx
const __m128i *v29; // esi
__m128i *v30; // edi
int v31; // edx
char v32; // dl
size_t v33; // ecx
int v34; // edx
__int8 *v35; // esi
char *v36; // edi
__m128i v37; // xmm1
__m128i v38; // xmm2
__m128i v39; // xmm3
__m128i v40; // xmm4
__m128i v41; // xmm5
__m128i v42; // xmm6
__m128i v43; // xmm7
__m128i v44; // xmm1
int v45; // eax
size_t v46; // edx
size_t j; // edx
__m128i v48; // xmm1
__m128i v49; // xmm2
__m128i v50; // xmm3
__m128i v51; // xmm5
__m128i v52; // xmm6
__m128i v53; // xmm7
size_t k; // edx
__m128i v55; // xmm1
unsigned int v56; // ecx
char v57; // al
unsigned int l; // ecx
int v59; // ecx
unsigned int v60; // eax
int v61; // ecx
unsigned int i; // eax
size_t v63; // [esp-4h] [ebp-Ch]
v3 = (const __m128i *)Src;
v4 = Size;
v5 = (__m128i *)a1;
if ( a1 > Src && a1 < (char *)Src + Size )
{
v29 = (const __m128i *)((char *)Src + Size);
v30 = (__m128i *)((char *)a1 + Size);
if ( Size >= 0x20 )
{
if ( _bittest(&dword_5153EC, 1u) )
{
for ( ; ((unsigned __int8)v30 & 0xF) != 0; v30->m128i_i8[0] = v29->m128i_i8[0] )
{
--v4;
v29 = (const __m128i *)((char *)v29 - 1);
v30 = (__m128i *)((char *)v30 - 1);
}
do
{
if ( v4 < 0x80 )
break;
v29 -= 8;
v30 -= 8;
v37 = _mm_loadu_si128(v29 + 1);
v38 = _mm_loadu_si128(v29 + 2);
v39 = _mm_loadu_si128(v29 + 3);
v40 = _mm_loadu_si128(v29 + 4);
v41 = _mm_loadu_si128(v29 + 5);
v42 = _mm_loadu_si128(v29 + 6);
v43 = _mm_loadu_si128(v29 + 7);
*v30 = _mm_loadu_si128(v29);
v30[1] = v37;
v30[2] = v38;
v30[3] = v39;
v30[4] = v40;
v30[5] = v41;
v30[6] = v42;
v30[7] = v43;
v4 -= 128;
}
while ( (v4 & 0xFFFFFF80) != 0 );
if ( v4 >= 0x20 )
{
do
{
v29 -= 2;
v30 -= 2;
v44 = _mm_loadu_si128(v29 + 1);
*v30 = _mm_loadu_si128(v29);
v30[1] = v44;
v4 -= 32;
}
while ( (v4 & 0xFFFFFFE0) != 0 );
}
}
else
{
if ( ((unsigned __int8)v30 & 3) != 0 )
{
v31 = (unsigned __int8)v30 & 3;
v4 = Size - v31;
do
{
v30[-1].m128i_i8[15] = v29[-1].m128i_i8[15];
v29 = (const __m128i *)((char *)v29 - 1);
v30 = (__m128i *)((char *)v30 - 1);
--v31;
}
while ( v31 );
}
if ( v4 >= 0x20 )
{
v32 = v4;
v33 = v4 >> 2;
v34 = v32 & 3;
v35 = &v29[-1].m128i_i8[12];
v36 = &v30[-1].m128i_i8[12];
while ( v33 )
{
*(_DWORD *)v36 = *(_DWORD *)v35;
v35 -= 4;
v36 -= 4;
--v33;
}
switch ( v34 )
{
case 0:
result = a1;
break;
case 1:
v36[3] = v35[3];
result = a1;
break;
case 2:
v36[3] = v35[3];
v36[2] = v35[2];
result = a1;
break;
case 3:
v36[3] = v35[3];
v36[2] = v35[2];
v36[1] = v35[1];
result = a1;
break;
}
return result;
}
}
}
for ( ; (v4 & 0xFFFFFFFC) != 0; v4 -= 4 )
{
v30 = (__m128i *)((char *)v30 - 4);
v29 = (const __m128i *)((char *)v29 - 4);
v30->m128i_i32[0] = v29->m128i_i32[0];
}
for ( ; v4; --v4 )
{
v30 = (__m128i *)((char *)v30 - 1);
v29 = (const __m128i *)((char *)v29 - 1);
v30->m128i_i8[0] = v29->m128i_i8[0];
}
result = a1;
}
else
{
if ( Size < 0x20 )
goto CopyUpDwordMov;
if ( Size < 0x80 )
{
if ( !_bittest(&dword_5153EC, 1u) )
goto Dword_align;
goto XmmCopySmallTest;
}
if ( _bittest(dword_51628C, 1u) )
{
qmemcpy(a1, Src, Size);
return a1;
}
if ( (((unsigned int)Src ^ (unsigned int)a1) & 0xF) == 0 && _bittest(&dword_5153EC, 1u) )
{
v45 = (unsigned __int8)Src & 0xF;
if ( ((unsigned __int8)Src & 0xF) != 0 )
{
v63 = Size - (16 - v45);
v60 = 16 - v45;
v61 = v60 & 3;
if ( (v60 & 3) != 0 )
{
do
{
v5->m128i_i8[0] = v3->m128i_i8[0];
v3 = (const __m128i *)((char *)v3 + 1);
v5 = (__m128i *)((char *)v5 + 1);
--v61;
}
while ( v61 );
}
for ( i = v60 >> 2; i; --i )
{
v5->m128i_i32[0] = v3->m128i_i32[0];
v3 = (const __m128i *)((char *)v3 + 4);
v5 = (__m128i *)((char *)v5 + 4);
}
v4 = v63;
}
v46 = v4;
v4 &= 0x7Fu;
for ( j = v46 >> 7; j; --j )
{
v48 = _mm_load_si128(v3 + 1);
v49 = _mm_load_si128(v3 + 2);
v50 = _mm_load_si128(v3 + 3);
*v5 = _mm_load_si128(v3);
v5[1] = v48;
v5[2] = v49;
v5[3] = v50;
v51 = _mm_load_si128(v3 + 5);
v52 = _mm_load_si128(v3 + 6);
v53 = _mm_load_si128(v3 + 7);
v5[4] = _mm_load_si128(v3 + 4);
v5[5] = v51;
v5[6] = v52;
v5[7] = v53;
v3 += 8;
v5 += 8;
}
XmmCopySmallTest:
if ( !v4 )
return a1;
for ( k = v4 >> 5; k; --k )
{
v55 = _mm_loadu_si128(v3 + 1);
*v5 = _mm_loadu_si128(v3);
v5[1] = v55;
v3 += 2;
v5 += 2;
}
CopyUpDwordMov:
v56 = v4 & 0x1F;
if ( v56 )
{
v57 = v56;
for ( l = v56 >> 2; l; --l )
{
v5->m128i_i32[0] = v3->m128i_i32[0];
v5 = (__m128i *)((char *)v5 + 4);
v3 = (const __m128i *)((char *)v3 + 4);
}
v59 = v57 & 3;
if ( (v57 & 3) != 0 )
{
do
{
v5->m128i_i8[0] = v3->m128i_i8[0];
v3 = (const __m128i *)((char *)v3 + 1);
v5 = (__m128i *)((char *)v5 + 1);
--v59;
}
while ( v59 );
}
}
return a1;
}
if ( !_bittest(dword_51628C, 0) || ((unsigned __int8)a1 & 3) != 0 )
{
Dword_align:
if ( ((unsigned __int8)a1 & 3) != 0 )
{
do
{
v5->m128i_i8[0] = v3->m128i_i8[0];
--v4;
v3 = (const __m128i *)((char *)v3 + 1);
v5 = (__m128i *)((char *)v5 + 1);
}
while ( ((unsigned __int8)v5 & 3) != 0 );
}
goto Dword_align_Ok;
}
if ( ((unsigned __int8)Src & 3) != 0 )
{
Dword_align_Ok:
v27 = v4;
if ( v4 >= 0x20 )
{
v28 = v4 >> 2;
qmemcpy(v5, v3, 4 * v28);
v13 = (const __m128i *)((char *)v3 + 4 * v28);
v5 = (__m128i *)((char *)v5 + 4 * v28);
switch ( v27 & 3 )
{
case 0:
goto TrailingUp0;
case 1:
goto TrailingUp1;
case 2:
goto TrailingUp2;
case 3:
goto TrailingUp3;
}
}
goto CopyUpDwordMov;
}
if ( _bittest((const int *)&v5, 2u) )
{
v4 = Size - 4;
v3 = (const __m128i *)((char *)Src + 4);
*(_DWORD *)a1 = *(_DWORD *)Src;
v5 = (__m128i *)((char *)a1 + 4);
}
if ( _bittest((const int *)&v5, 3u) )
{
v7 = v3->m128i_i64[0];
v4 -= 8;
v3 = (const __m128i *)((char *)v3 + 8);
v5->m128i_i64[0] = v7;
v5 = (__m128i *)((char *)v5 + 8);
}
if ( ((unsigned __int8)v3 & 7) != 0 )
{
if ( _bittest((const int *)&v3, 3u) )
{
v8 = _mm_load_si128((const __m128i *)((char *)v3 - 12));
v9 = (const __m128i *)((char *)v3 - 12);
do
{
v10 = _mm_load_si128(v9 + 1);
v4 -= 48;
v11 = _mm_load_si128(v9 + 2);
v12 = _mm_load_si128(v9 + 3);
v9 += 3;
*v5 = _mm_alignr_epi8(v10, v8, 12);
v5[1] = _mm_alignr_epi8(v11, v10, 12);
v8 = v12;
v5[2] = _mm_alignr_epi8(v12, v11, 12);
v5 += 3;
}
while ( v4 >= 0x30 );
v13 = (const __m128i *)&v9->m128i_i8[12];
}
else
{
v19 = _mm_load_si128((const __m128i *)((char *)v3 - 4));
v20 = (const __m128i *)((char *)v3 - 4);
do
{
v21 = _mm_load_si128(v20 + 1);
v4 -= 48;
v22 = _mm_load_si128(v20 + 2);
v23 = _mm_load_si128(v20 + 3);
v20 += 3;
*v5 = _mm_alignr_epi8(v21, v19, 4);
v5[1] = _mm_alignr_epi8(v22, v21, 4);
v19 = v23;
v5[2] = _mm_alignr_epi8(v23, v22, 4);
v5 += 3;
}
while ( v4 >= 0x30 );
v13 = (const __m128i *)&v20->m128i_i8[4];
}
}
else
{
v14 = _mm_load_si128((const __m128i *)((char *)v3 - 8));
v15 = (const __m128i *)((char *)v3 - 8);
do
{
v16 = _mm_load_si128(v15 + 1);
v4 -= 48;
v17 = _mm_load_si128(v15 + 2);
v18 = _mm_load_si128(v15 + 3);
v15 += 3;
*v5 = _mm_alignr_epi8(v16, v14, 8);
v5[1] = _mm_alignr_epi8(v17, v16, 8);
v14 = v18;
v5[2] = _mm_alignr_epi8(v18, v17, 8);
v5 += 3;
}
while ( v4 >= 0x30 );
v13 = (const __m128i *)&v15->m128i_i8[8];
}
while ( 2 )
{
if ( _bittest((const int *)&v4, 2u) )
{
v25 = v13->m128i_i32[0];
v4 -= 4;
v13 = (const __m128i *)((char *)v13 + 4);
v5->m128i_i32[0] = v25;
v5 = (__m128i *)((char *)v5 + 4);
}
if ( _bittest((const int *)&v4, 3u) )
{
v26 = v13->m128i_i64[0];
v4 -= 8;
v13 = (const __m128i *)((char *)v13 + 8);
v5->m128i_i64[0] = v26;
v5 = (__m128i *)((char *)v5 + 8);
}
switch ( v4 )
{
case 0u:
TrailingUp0:
result = a1;
break;
case 1u:
TrailingUp1:
v5->m128i_i8[0] = v13->m128i_i8[0];
result = a1;
break;
case 2u:
TrailingUp2:
v5->m128i_i8[0] = v13->m128i_i8[0];
v5->m128i_i8[1] = v13->m128i_i8[1];
result = a1;
break;
case 3u:
TrailingUp3:
v5->m128i_i8[0] = v13->m128i_i8[0];
v5->m128i_i8[1] = v13->m128i_i8[1];
v5->m128i_i8[2] = v13->m128i_i8[2];
result = a1;
break;
default:
v24 = _mm_loadu_si128(v13);
v4 -= 16;
++v13;
*v5++ = v24;
continue;
}
break;
}
}
return result;
}
懒得分析解密过程,直接将样本关闭ASLR,拖入OD断点对应的位置分析
关闭ASLR参考链接:关闭ASLR
PEView查看对应的偏移地址将40 81改为00 81 (小端内存读为80 41)
(搜索 40 81的第一个位置修改)
(修改之后)
OD打开Ctrl+G转到对应的地址,断点
F8到把v4作为函数执行的时候
读取UA头和winnet
然后读完部分payload后读取自身
(这里是看freebuf那篇文章所理解的)
OD验证
之后获取Kernel.dll所有的函数
利用GetProcAddress获取了对应的API函数地址,并实例化该API
利用OD插件windows API断点下断GetProcAddress能看到所有实例化的API
(太多了就不一一列出来了)
原本想跟着IDA的函数调用图一步一步OD调,然后不知道为什么无法生成,直接OD定位到main函数地址调试
跟踪到Address:00453510的call执行完后就退出了,所以跟进去
跟进第一个call
得到wininet关键字
跟进call ebp发现获取自身加载的Module
加载了wchar.h,获取LoadLibraryExA关键字并实例化
加载twain_32.dll
解除IP地址
解密出UA头
在wininet下断点,得到返回的数据
23:26分
由于底子不行,调试到后面不会弄只能跟跟马子的行为
OD里的字符串
文章后面作者成功dump了下载的第二段payload并解密保存
(实在是断不到那个解密后得到PE的点)
目标行为
读取对应的注册表和收集cookie保存在某个txt上传
远程下载
总结
之前并没有这么分析过,经过这次分析学习到了一些东西
- 样本关闭ASLR
- IDA和OD调试对比
- 断点的一些技巧
转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。
文章标题:某远程加载马样本分析学习
本文作者:九世
发布时间:2020-12-18, 11:33:14
最后更新:2020-12-19, 01:02:57
原始链接:http://jiushill.github.io/posts/8f916cea.html版权声明: "署名-非商用-相同方式共享 4.0" 转载请保留原文链接及作者。