1+ // DllToShellCode.cpp : 定义控制台应用程序的入口点。
2+ //
3+
4+ #include <stdio.h>
5+ #include <stdint.h>
6+ #include <windows.h>
7+ #include "compress.h"
8+ #include "shellcode_data.h"
9+
10+ #pragma pack(push)
11+ #pragma pack(1)
12+ typedef struct main_config {
13+ uint8_t invokeMode ; // 0 = 调用dllmain lpReserved[param], 1 = 返回导出函数地址
14+ uint32_t depackCodeOffset ; // 解压缩代码偏移 偏移量基于main_config开始
15+ uint32_t unpackSize ; // 未压缩时的大小
16+ uint32_t packedSize ; // 压缩后的大小
17+ uint32_t dllDataOffset ; // dll数据偏移 偏移量基于main_config开始
18+ char param [100 ]; // dllmain参数或导出函数名称
19+ } main_config_t , * main_config_p ;
20+ #pragma pack(pop)
21+
22+ static void show_syntax () {
23+ printf ("DllToShellCode v0.1 [killeven]\n"
24+ " Syntax\n\n"
25+ " BinToHex: DllToShellCode b <in_file> <out_file>\n"
26+ " Compress File: DllToShellCode c mode <in_file> <out_file>\n"
27+ " Dll To ShellCode: DllToShellCode d shellcode_mode <param> compress_mode <in_file> <out_file>\n\n"
28+ " Compress File mode\n"
29+ " \t0 = compress with ntdll\n"
30+ " \t1 = compress with aplib\n"
31+ " DllToShellCode shellcode_mode\n"
32+ " \t0 = only call dllmain, <param> is the dllmain param lpReserved\n"
33+ " \t1 = return export address, <param> is the export name\n"
34+ " DllToShellCode compress_mode\n"
35+ " \t0 = no compress\n"
36+ " \t1 = compress with ntdll\n"
37+ " \t2 = compress with aplib\n" );
38+ }
39+
40+ #define EXIT_SHOW_SYNTAX { show_syntax(); return -1; }
41+
42+ static int bin_to_hex (char * infile , char * outfile ) {
43+ FILE * in , * out ;
44+ fopen_s (& in , infile , "rb" );
45+ if (in == 0 ) {
46+ printf ("[-] open input file error. file name = %s.\n" , infile );
47+ return -1 ;
48+ }
49+ fopen_s (& out , outfile , "w" );
50+ if (out == 0 ) {
51+ _fcloseall ();
52+ printf ("[-] create output file error. file name = %s.\n" , infile );
53+ return -1 ;
54+ }
55+ fseek (in , 0 , SEEK_END );
56+ int fileSize = (int )ftell (in );
57+ fseek (in , 0 , SEEK_SET );
58+ int loop = fileSize / 30 ;
59+ int rest = fileSize % 30 ;
60+ char buf [30 ];
61+ fprintf_s (out , "char ShellCode[%d] = {\n" , fileSize );
62+ for (int i = 0 ; i < loop ; i ++ ) {
63+ fread (buf , 1 , 30 , in );
64+ fputs ("\t\"" , out );
65+ for (int j = 0 ; j < 30 ; j ++ ) {
66+ fprintf_s (out , "\\x%02x" , buf [j ] & 0xFF );
67+ }
68+ fputs ("\"\n" , out );
69+ }
70+ if (rest > 0 ) {
71+ fputs ("\t\"" , out );
72+ fread (buf , 1 , rest , in );
73+ for (int j = 0 ; j < rest ; j ++ ) {
74+ fprintf_s (out , "\\x%02x" , buf [j ] & 0xFF );
75+ }
76+ fputs ("\"\n" , out );
77+ }
78+ fputs ("};" , out );
79+ fflush (out );
80+ _fcloseall ();
81+ return 0 ;
82+ }
83+
84+ /* mode 1 = nt compress, 2 = aplib compress */
85+ static int compress_file (char mode , char * in_file , char * out_file ) {
86+ if (mode != '1' && mode != '2' ) {
87+ printf ("[-] unknow mode.\n" );
88+ EXIT_SHOW_SYNTAX ;
89+ }
90+ FILE * in = 0 , * out = 0 ;
91+ fopen_s (& in , in_file , "rb" );
92+ if (in == 0 ) {
93+ printf ("[-] open input file error.\n" );
94+ return -1 ;
95+ }
96+ fopen_s (& out , out_file , "wb" );
97+ if (out == 0 ) {
98+ _fcloseall ();
99+ printf ("[-] open output file error.\n" );
100+ return -1 ;
101+ }
102+ fseek (in , 0 , SEEK_END );
103+ int fileSize = (int )ftell (in );
104+ fseek (in , 0 , SEEK_SET );
105+ void * fileBuf = malloc (fileSize );
106+ void * compressedBuf = malloc (fileSize );
107+ if (fileBuf == 0 || compressedBuf == 0 ) {
108+ _fcloseall ();
109+ printf ("[-] malloc memory error.\n" );
110+ return -1 ;
111+ }
112+ fread (fileBuf , 1 , fileSize , in );
113+ unsigned int ret = COMPRESS_ERROR ;
114+ if (mode == '1' ) {
115+ printf ("[*] using nt compress flag.\n" );
116+ ret = nt_compress (fileBuf , fileSize , compressedBuf , fileSize );
117+ }
118+ else if (mode == '2' ) {
119+ printf ("[*] using aplib compress flag.\n" );
120+ ret = aplib_compress (fileBuf , fileSize , compressedBuf , fileSize );
121+ }
122+ if (ret != COMPRESS_ERROR ) {
123+ printf ("[*] compress sucess orign size = %d, compressed size = %d.\n" , fileSize , ret );
124+ fwrite (compressedBuf , 1 , ret , out );
125+ } else {
126+ printf ("[-] compress error.\n" );
127+ }
128+ fflush (out );
129+ _fcloseall ();
130+ free (fileBuf );
131+ free (compressedBuf );
132+ return 0 ;
133+ }
134+
135+ static PIMAGE_NT_HEADERS get_nt_header (void * buf ) {
136+ PIMAGE_DOS_HEADER dh = (PIMAGE_DOS_HEADER )buf ;
137+ if (IsBadReadPtr (buf , sizeof (IMAGE_DOS_HEADER ))) return 0 ;
138+ if (dh -> e_magic != IMAGE_DOS_SIGNATURE ) return 0 ;
139+ PIMAGE_NT_HEADERS nh = (PIMAGE_NT_HEADERS )((uint8_t * )buf + dh -> e_lfanew );
140+ if (IsBadReadPtr (nh , sizeof (IMAGE_NT_HEADERS ))) return 0 ;
141+ if (nh -> Signature != IMAGE_NT_SIGNATURE ) return 0 ;
142+ if ((nh -> FileHeader .Characteristics & IMAGE_FILE_EXECUTABLE_IMAGE ) == 0 ) return 0 ;
143+ return nh ;
144+ }
145+
146+ static int is_dll (PIMAGE_NT_HEADERS nh ) {
147+ return (nh -> FileHeader .Characteristics & IMAGE_FILE_DLL ) > 0 ? 1 : 0 ;
148+ }
149+
150+ static int is_x64 (PIMAGE_NT_HEADERS nh ) {
151+ if (nh -> FileHeader .Machine != IMAGE_FILE_MACHINE_AMD64 ||
152+ nh -> OptionalHeader .Magic != IMAGE_NT_OPTIONAL_HDR64_MAGIC )
153+ return 0 ;
154+ return 1 ;
155+ }
156+
157+ /*
158+ shellcode_mode
159+ 0 = only call dllmain, <param> is the dllmain param lpReserved
160+ 1 = return export address, <param> is the export name
161+ compress_mode
162+ 0 = no compress
163+ 1 = compress with ntdll
164+ 2 = compress with aplib
165+ */
166+ static int dll_to_shellcode (char shellcode_mode , char * param , char compress_mode , char * in_file , char * out_file ) {
167+ if (shellcode_mode != '0' && shellcode_mode != '1' ) {
168+ printf ("[-] unknow shellcode mode.\n" );
169+ EXIT_SHOW_SYNTAX ;
170+ }
171+ if (compress_mode != '0' && compress_mode != '1' && compress_mode != '2' ) {
172+ printf ("[-] unknow compress mode.\n" );
173+ EXIT_SHOW_SYNTAX ;
174+ }
175+ FILE * in = 0 , * out = 0 ;
176+ if (fopen_s (& in , in_file , "rb" ) != 0 ) {
177+ printf ("[-] can't open input file!\n" );
178+ return -1 ;
179+ }
180+ if (fopen_s (& out , out_file , "wb" ) != 0 ) {
181+ _fcloseall ();
182+ printf ("[-] can't create output file!\n" );
183+ return -1 ;
184+ }
185+ fseek (in , 0 , SEEK_END );
186+ uint32_t inFileSize = ftell (in );
187+ fseek (in , 0 , SEEK_SET );
188+ void * fileBuf = malloc (inFileSize );
189+ if (fileBuf == 0 ) {
190+ _fcloseall ();
191+ printf ("[-] malloc file buf error.\n" );
192+ return -1 ;
193+ }
194+ fread (fileBuf , 1 , inFileSize , in );
195+ PIMAGE_NT_HEADERS nh = get_nt_header (fileBuf );
196+ if (nh == 0 ) {
197+ _fcloseall ();
198+ free (fileBuf );
199+ printf ("[-] invalid pe file, can't find pe header.\n" );
200+ return -1 ;
201+ }
202+ if (is_dll (nh ) == 0 ) {
203+ _fcloseall ();
204+ free (fileBuf );
205+ printf ("[-] pe file is not a dll.\n" );
206+ return -1 ;
207+ }
208+ size_t paramLen = strlen (param );
209+ if (paramLen > 100 ) {
210+ printf ("[-] param only can receive 99 length char.\n" );
211+ return -1 ;
212+ }
213+ main_config_t config ;
214+ memset (& config , 0 , sizeof (config ));
215+ strcpy_s (config .param , sizeof (config .param ), param );
216+ config .invokeMode = shellcode_mode == '0' ? 0 : 1 ;
217+ config .unpackSize = inFileSize ;
218+ int x64 = is_x64 (nh );
219+ printf ("[*] pe file paltform: %s\n" , x64 == 1 ? "x64" : "x86" );
220+ int mainCodeSize = 0 ;
221+ void * mainCode = get_shellcode_main (x64 , & mainCodeSize );
222+ if (compress_mode == '0' ) {
223+ printf ("[*] writing main shellcode to file, size = %d.\n" , mainCodeSize );
224+ fwrite (mainCode , 1 , mainCodeSize , out );
225+ fflush (out );
226+ config .depackCodeOffset = 0 ;
227+ config .packedSize = inFileSize ;
228+ config .dllDataOffset = sizeof (config );
229+ printf ("[*] writing config data to file, size = %d.\n" , sizeof (config ));
230+ fwrite (& config , 1 , sizeof (config ), out );
231+ printf ("[*] writing dll data to file, size = %d.\n" , inFileSize );
232+ fwrite (fileBuf , 1 , inFileSize , out );
233+ printf ("[+] gen shellcode sucess, total size = %d.\n" , mainCodeSize + sizeof (config ) + inFileSize );
234+ fflush (out );
235+ _fcloseall ();
236+ free (fileBuf );
237+ return 0 ;
238+ }
239+ void * compressed = malloc (inFileSize );
240+ unsigned int compressedSize = 0 ;
241+ if (compressed == 0 ) {
242+ _fcloseall ();
243+ free (fileBuf );
244+ printf ("[-] malloc compressed data error.\n" );
245+ return -1 ;
246+ }
247+ int decompressCodeSize = 0 ;
248+ void * decompressCode = 0 ;
249+ if (compress_mode == '1' ) {
250+ decompressCode = get_shellcode_ntdll (x64 , & decompressCodeSize );
251+ compressedSize = nt_compress (fileBuf , inFileSize , compressed , inFileSize );
252+ } else if (compress_mode == '2' ) {
253+ decompressCode = get_shellcode_aplib (x64 , & decompressCodeSize );
254+ compressedSize = aplib_compress (fileBuf , inFileSize , compressed , inFileSize );
255+ } else {
256+ exit (-1 );
257+ }
258+ if (compressedSize == COMPRESS_ERROR ) {
259+ printf ("[-] compress file data error.\n" );
260+ _fcloseall ();
261+ free (fileBuf );
262+ free (compressed );
263+ return -1 ;
264+ }
265+ printf ("[*] writing main shellcode to file, size = %d.\n" , mainCodeSize );
266+ fwrite (mainCode , 1 , mainCodeSize , out );
267+ config .depackCodeOffset = sizeof (config );
268+ config .packedSize = compressedSize ;
269+ config .dllDataOffset = sizeof (config ) + decompressCodeSize ;
270+ printf ("[*] writing config data to file, size = %d.\n" , sizeof (config ));
271+ fwrite (& config , 1 , sizeof (config ), out );
272+ printf ("[*] writing decompress code to file, size = %d.\n" , decompressCodeSize );
273+ fwrite (decompressCode , 1 , decompressCodeSize , out );
274+ printf ("[*] write compressed data to file, size = %d.\n" , compressedSize );
275+ fwrite (compressed , 1 , compressedSize , out );
276+ printf ("[+] gen shellcode sucess, total size = %d.\n" , mainCodeSize + sizeof (config ) + decompressCodeSize + compressedSize );
277+ fflush (out );
278+ _fcloseall ();
279+ free (fileBuf );
280+ free (compressed );
281+ return 0 ;
282+ }
283+
284+ #define CHECK_PARAM (a ) { if (a[0] == 0 || a[1] != 0) EXIT_SHOW_SYNTAX; }
285+
286+ int main (int argc , char * argv [])
287+ {
288+ if (argc == 4 ) {
289+ CHECK_PARAM (argv [1 ]);
290+ if (toupper (argv [1 ][0 ]) != 'B' ) EXIT_SHOW_SYNTAX ;
291+ printf ("[BinToHex Mode]\n\tinput = %s, output = %s .\n" , argv [2 ], argv [3 ]);
292+ return bin_to_hex (argv [2 ], argv [3 ]);
293+ }
294+ else if (argc == 5 ) {
295+ CHECK_PARAM (argv [1 ]);
296+ if (toupper (argv [1 ][0 ]) != 'C' ) EXIT_SHOW_SYNTAX ;
297+ printf ("[Compress Mode]\n\t"
298+ "mode = %c, input = %s, output = %s ].\n" , argv [2 ][0 ], argv [3 ], argv [4 ]);
299+ return compress_file (argv [2 ][0 ], argv [3 ], argv [4 ]);
300+ }
301+ if (argc == 7 ) {
302+ CHECK_PARAM (argv [1 ]);
303+ CHECK_PARAM (argv [2 ]);
304+ CHECK_PARAM (argv [4 ]);
305+ if (toupper (argv [1 ][0 ]) != 'D' ) EXIT_SHOW_SYNTAX ;
306+ printf ("[Dll to ShellCode Mode]\n\t"
307+ "shellcode_mode = %c, param = %s, compress_mode = %c, input = %s, output = %s.\n" ,
308+ argv [2 ][0 ], argv [3 ], argv [4 ][0 ], argv [5 ], argv [6 ]);
309+ return dll_to_shellcode (argv [2 ][0 ], argv [3 ], argv [4 ][0 ], argv [5 ], argv [6 ]);
310+ }
311+ EXIT_SHOW_SYNTAX ;
312+ return 0 ;
313+ }
0 commit comments