Skip to content

Commit 510072a

Browse files
committed
初次提交
0 parents  commit 510072a

20 files changed

+4033
-0
lines changed
Lines changed: 275 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,275 @@
1+
#include <windows.h>
2+
#include <stdio.h>
3+
#include <stdint.h>
4+
#include <stdlib.h>
5+
6+
DWORD RVAtoFileOffset(DWORD RVA, PIMAGE_NT_HEADERS pNtHeader, PIMAGE_SECTION_HEADER pSec);
7+
DWORD GetProcOffset(const char* funcName, LPVOID pBuf);
8+
9+
// 辅助函数:将32位整数打包为小端字节序
10+
void pack(uint32_t val, uint8_t* bytes) {
11+
bytes[0] = val & 0xFF;
12+
bytes[1] = (val >> 8) & 0xFF;
13+
bytes[2] = (val >> 16) & 0xFF;
14+
bytes[3] = (val >> 24) & 0xFF;
15+
}
16+
17+
int wmain(int argc, wchar_t* argv[]) {
18+
19+
printf("╔══════════════════════════════════════════════════════════════════════════════════════╗\n");
20+
printf("║ Convert2Shellcode_embed ║\n");
21+
printf("║------------------------------------------------------------------------------------- ║\n");
22+
printf("║ Function: An improved version of RDI requires implementing the ReflectLoader function║\n");
23+
printf("║ in the DLL by yourself and also needs to be exported. ║\n");
24+
printf("║ Author:oneday ║\n");
25+
printf("║ Compilation Date:%hs %hs ║\n", __DATE__, __TIME__);
26+
printf("╚══════════════════════════════════════════════════════════════════════════════════════╝\n");
27+
printf("\n");
28+
29+
// 检查参数数量
30+
if (argc < 2) {
31+
printf("[-] Error: Missing DLL path parameter\n");
32+
printf("[*] Usage: Convert2Shellcode_embed.exe <DLL Path> [Output File Path] [The Export Function Name of Loader]\n");
33+
printf("[*] Example 1: Convert2Shellcode_embed.exe C:\\path\\to\\ReflectiveDLL.dll\n");
34+
printf("[*] Example 2: Convert2Shellcode_embed.exe C:\\path\\to\\ReflectiveDLL.dll C:\\path\\to\\Shellcode.bin\n");
35+
printf("[*] Example 3: Convert2Shellcode_embed.exe C:\\path\\to\\ReflectiveDLL.dll C:\\path\\to\\Shellcode.bin ReflectiveLoader\n");
36+
return 1;
37+
}
38+
39+
uint8_t bootstrap[24];
40+
uint8_t* dllBytes = NULL;
41+
size_t dllSize = 0;
42+
43+
const wchar_t* dllPath = argv[1];
44+
FILE* dllFile = _wfopen(dllPath, L"rb");
45+
if (!dllFile) {
46+
printf("[-] Error: Unable to open file %s (Error code: %d)\n", dllPath, GetLastError());
47+
return 1;
48+
}
49+
printf("[+] Successfully opened %s\n", dllPath);
50+
51+
// 获取文件大小
52+
fseek(dllFile, 0, SEEK_END);
53+
dllSize = ftell(dllFile);
54+
fseek(dllFile, 0, SEEK_SET);
55+
if (dllSize == 0) {
56+
printf("[-] Error: File size is 0 - %s\n", dllPath);
57+
fclose(dllFile);
58+
return 1;
59+
}
60+
printf("[*] File size is %zu\n", dllSize);
61+
62+
// 读取文件内容
63+
dllBytes = (uint8_t*)malloc(dllSize);
64+
if (!dllBytes) {
65+
printf("[-] Error: Memory allocation failed (requested dllSize: %zu bytes)\n", dllSize);
66+
fclose(dllFile);
67+
return 1;
68+
}
69+
printf("[+] Memory allocation successful, address is 0x%x\n", dllBytes);
70+
71+
size_t bytesRead = fread(dllBytes, 1, dllSize, dllFile);
72+
fclose(dllFile);
73+
if (bytesRead != dllSize) {
74+
printf("[-] Error: File read incomplete (read %zu/%zu bytes)\n", bytesRead, dllSize);
75+
free(dllBytes);
76+
return 1;
77+
}
78+
printf("[*] %zu bytes read into memory\n", bytesRead);
79+
80+
// 假设 ReflectLoader 是目标函数名
81+
const wchar_t* Wide_ReflectiveLoaderName = (argc >= 4) ? argv[3] : L"ReflectiveLoader";
82+
83+
84+
// 计算所需缓冲区大小
85+
size_t size = wcstombs(NULL, Wide_ReflectiveLoaderName, 0) + 1;
86+
char* ReflectiveLoaderName = (char*)malloc(size);
87+
88+
// 执行转换
89+
wcstombs(ReflectiveLoaderName, Wide_ReflectiveLoaderName, size);
90+
91+
DWORD RDIOffset = 0;
92+
RDIOffset = GetProcOffset(ReflectiveLoaderName, dllBytes);
93+
94+
if (!RDIOffset) {
95+
printf("[-] Error: fail to get RDIOffset)\n");
96+
free(dllBytes);
97+
free(ReflectiveLoaderName);
98+
return 1;
99+
}
100+
101+
free(ReflectiveLoaderName);
102+
103+
// 构建stub
104+
int index = 0;
105+
uint8_t stub[23];
106+
107+
// pop r10
108+
stub[index++] = 0x4D;
109+
stub[index++] = 0x5A;
110+
111+
// push r10
112+
stub[index++] = 0x41;
113+
stub[index++] = 0x52;
114+
115+
// call 0
116+
stub[index++] = 0xE8;
117+
stub[index++] = 0x00;
118+
stub[index++] = 0x00;
119+
stub[index++] = 0x00;
120+
stub[index++] = 0x00;
121+
122+
// pop rbx
123+
stub[index++] = 0x5B;
124+
125+
// add rbx,<RDIOffset-9>
126+
stub[index++] = 0x48;
127+
stub[index++] = 0x81;
128+
stub[index++] = 0xC3;
129+
pack(RDIOffset - 9, stub + index);
130+
index += 4;
131+
132+
// push rbp
133+
stub[index++] = 0x55;
134+
135+
// mov rbp, rsp
136+
stub[index++] = 0x48;
137+
stub[index++] = 0x89;
138+
stub[index++] = 0xE5;
139+
140+
// call rbx
141+
stub[index++] = 0xFF;
142+
stub[index++] = 0xD3;
143+
144+
uint8_t* finalcode = (uint8_t*)malloc(dllSize);
145+
if (!finalcode) {
146+
printf("[-] Error: Memory allocation failed (requested finalSize: %zu bytes)\n", dllSize);
147+
free(dllBytes);
148+
return 1;
149+
}
150+
printf("[+] Memory allocation successful, address is 0x%x\n", finalcode);
151+
152+
// 构造最终的shellcode
153+
memcpy(finalcode, dllBytes, dllSize);
154+
memcpy(finalcode, stub, index);
155+
156+
// 释放 DLL 缓冲区
157+
free(dllBytes);
158+
dllBytes = NULL;
159+
160+
// 处理输出文件参数
161+
const wchar_t* outputPath = (argc >= 3) ? argv[2] : L"shellcode_embed.bin";
162+
163+
// 写入文件
164+
HANDLE hFile = CreateFileW(
165+
outputPath,
166+
GENERIC_WRITE,
167+
0,
168+
NULL,
169+
CREATE_ALWAYS,
170+
FILE_ATTRIBUTE_NORMAL,
171+
NULL
172+
);
173+
174+
if (hFile == INVALID_HANDLE_VALUE) {
175+
printf("[-] Error: Unable to create output file %s (Error code: %d)\n", outputPath, GetLastError());
176+
free(finalcode);
177+
return 1;
178+
}
179+
180+
DWORD bytesWritten;
181+
BOOL writeResult = WriteFile(
182+
hFile,
183+
finalcode,
184+
(DWORD)dllSize,
185+
&bytesWritten,
186+
NULL
187+
);
188+
189+
if (!writeResult || bytesWritten != dllSize) {
190+
printf("[-] Error: Failed to write to file (wrote %lu/%zu bytes, error code: %d)\n",
191+
bytesWritten, dllSize, GetLastError());
192+
CloseHandle(hFile);
193+
free(finalcode);
194+
return 1;
195+
}
196+
197+
FlushFileBuffers(hFile);
198+
CloseHandle(hFile);
199+
printf("[+] Successfully generated shellcode file: %s (Size: %zu bytes)\n", outputPath, dllSize);
200+
201+
return 0;
202+
}
203+
204+
//作用:RVA->文件偏移地址
205+
//公式:文件偏移 = 节区文件起始地址(PointerToRawData) + (RVA - 节区虚拟起始地址(VirtualAddress))
206+
DWORD RVAtoFileOffset(DWORD RVA, PIMAGE_NT_HEADERS pNtHeader, PIMAGE_SECTION_HEADER pSec) {
207+
208+
// 遍历节区表
209+
DWORD SectionNumber = pNtHeader->FileHeader.NumberOfSections;
210+
for (int i = 0; i < SectionNumber; i++) {
211+
// 检查RVA是否在当前节区的范围内
212+
if (RVA >= pSec[i].VirtualAddress && RVA < pSec[i].VirtualAddress + pSec[i].SizeOfRawData) {
213+
// 转换RVA到文件偏移地址
214+
return pSec[i].PointerToRawData + (RVA - pSec[i].VirtualAddress);
215+
}
216+
}
217+
// 如果未找到对应的节区,返回无效值
218+
return 0xFFFFFFFF;
219+
}
220+
221+
//作用:该函数通过导出表获得指定函数的地址
222+
DWORD GetProcOffset(const char* funcName, LPVOID pBuf) {
223+
224+
//定位一些相关文件头
225+
PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)pBuf;
226+
PIMAGE_NT_HEADERS pNtHeader = (PIMAGE_NT_HEADERS)((BYTE*)pBuf + pDosHeader->e_lfanew);
227+
PIMAGE_SECTION_HEADER pSec = (PIMAGE_SECTION_HEADER)((LPBYTE)pNtHeader + sizeof(IMAGE_NT_HEADERS));
228+
229+
//获取导出表地址及大小,注意这里是RVA
230+
DWORD exportDirRVA = pNtHeader->OptionalHeader.DataDirectory[0].VirtualAddress;
231+
DWORD exportDirSize = pNtHeader->OptionalHeader.DataDirectory[0].Size;
232+
233+
if (!exportDirRVA) {
234+
printf("[-] Error: This DLL does not have an export table.\n");
235+
return NULL;
236+
}
237+
//定位导出表
238+
//得到的偏移地址是RVA,但是咱们的文件现在只是磁盘文件,所以需要转换为文件偏移
239+
DWORD exportDirFileOffset = RVAtoFileOffset((DWORD)exportDirRVA, pNtHeader, pSec);
240+
241+
//转换之后RVA就变成了文件偏移,然后再定位
242+
PIMAGE_EXPORT_DIRECTORY pExportDir = (PIMAGE_EXPORT_DIRECTORY)((BYTE*)pBuf + exportDirFileOffset);
243+
244+
//解析导出表,这里同理都是RVA
245+
DWORD pRNames = pExportDir->AddressOfNames;
246+
DWORD pFNames = RVAtoFileOffset(pRNames, pNtHeader, pSec);
247+
DWORD* pNames = (DWORD*)((PBYTE)pBuf + pFNames);
248+
249+
DWORD pRFunctions = pExportDir->AddressOfFunctions;
250+
DWORD pFFunctions = RVAtoFileOffset(pRFunctions, pNtHeader, pSec);
251+
DWORD* pFunctions = (DWORD*)((PBYTE)pBuf + pFFunctions);
252+
253+
WORD pRNameOrdinals = pExportDir->AddressOfNameOrdinals;
254+
WORD pFNameOrdinals = RVAtoFileOffset(pRNameOrdinals, pNtHeader, pSec);
255+
WORD* pNameOrdinals = (WORD*)((PBYTE)pBuf + pFFunctions);
256+
257+
// 遍历查找目标函数
258+
DWORD funcRVA = 0;
259+
for (DWORD i = 0; i < pExportDir->NumberOfNames; i++) {
260+
DWORD functionNameRVA = pNames[i];
261+
DWORD functionNameFileOffset = RVAtoFileOffset(functionNameRVA, pNtHeader, pSec);
262+
const char* pName = (char*)((PBYTE)pBuf + functionNameFileOffset);
263+
if (strcmp(pName, funcName) == 0) {
264+
funcRVA = pFunctions[i];
265+
break;
266+
}
267+
}
268+
if (funcRVA == 0) {
269+
printf("\n[-] Function %s not found.\n", funcName);
270+
return NULL;
271+
}
272+
273+
DWORD fileOffset = RVAtoFileOffset(funcRVA, pNtHeader, pSec);
274+
return fileOffset;
275+
}

0 commit comments

Comments
 (0)