23 (DWORD)((PBYTE)exit - (PBYTE)shellcode_start),
24 (DWORD)((PBYTE)wstr_len - (PBYTE)shellcode_start),
25 (DWORD)((PBYTE)hash_string - (PBYTE)shellcode_start),
26 (DWORD)((PBYTE)str_cpy - (PBYTE)shellcode_start),
27 (DWORD)((PBYTE)str_toi - (PBYTE)shellcode_start),
28 (DWORD)((PBYTE)str_chr - (PBYTE)shellcode_start),
29 (DWORD)((PBYTE)ansi_to_wide - (PBYTE)shellcode_start),
30 (DWORD)((PBYTE)wstr_cpy - (PBYTE)shellcode_start),
31 (DWORD)((PBYTE)wstr_i_cmp - (PBYTE)shellcode_start),
32 (DWORD)((PBYTE)get_dll_handle - (PBYTE)shellcode_start),
33 (DWORD)((PBYTE)load_dll - (PBYTE)shellcode_start),
34 (DWORD)((PBYTE)resolve_api_set - (PBYTE)shellcode_start),
35 (DWORD)((PBYTE)get_symbol_ptr - (PBYTE)shellcode_start),
36 (DWORD)((PBYTE)load_syms - (PBYTE)shellcode_start)
40 #pragma runtime_checks("", off)
43 VOID shellcode::exit()
50 size_t shellcode::wstr_len(PWSTR str)
52 PWCHAR s = (PWCHAR)str;
58 DWORD shellcode::hash_string(PCHAR str)
80 VOID shellcode::str_cpy(PCHAR out, PSTR in)
82 while (*in) *out++ = *in++;
87 DWORD shellcode::str_toi(PSTR str)
98 result = (10 * result) + digit;
106 PCHAR shellcode::str_chr(PSTR str, CHAR chr)
110 if (*str == chr) {
return str; };
116 VOID shellcode::ansi_to_wide(PCHAR str, PWCHAR out,
size_t size)
119 size /=
sizeof(WCHAR);
123 while (--size && *str) {
124 *out++ = (WCHAR)*str++;
132 VOID shellcode::wstr_cpy(PWSTR str1, PCWSTR str2,
size_t length)
135 while (length--) *str1++ = *str2++;
141 INT shellcode::wstr_i_cmp(PWSTR str1, PCWSTR str2,
size_t length)
155 }
while (((c1 == c2) || (c1 - c2 == 32) ||
156 (c2 - c1 == 32)) && --length);
163 HANDLE shellcode::get_dll_handle(HANDLE pe_base, PDWORD sh_funs, PWSTR dll_name)
166 auto fun_wstr_i_cmp =
sh_resolve(pe_base, sh_funs, wstr_i_cmp);
167 auto fun_resolve_api_set =
sh_resolve(pe_base, sh_funs, resolve_api_set);
170 PPEB pPeb = NtCurrentTeb()->ProcessEnvironmentBlock;
171 PLIST_ENTRY head = &pPeb->Ldr->InMemoryOrderModuleList;
176 PLIST_ENTRY current = head;
177 while ((current = current->Flink) != head)
180 PLDR_DATA_TABLE_ENTRY data_table = CONTAINING_RECORD(current, LDR_DATA_TABLE_ENTRY, InMemoryOrderLinks);
183 if (!fun_wstr_i_cmp(((PUNICODE_STRING)(&data_table->Reserved4))->Buffer,
187 return data_table->DllBase;
192 WCHAR api_schema[] = { L
'a', L
'p', L
'i', L
'-', L
'\0' };
193 WCHAR ext_schema[] = { L
'e', L
'x', L
't', L
'-', L
'\0' };
194 if (!fun_wstr_i_cmp(dll_name, api_schema,
sizeof(
"api")) ||
195 !fun_wstr_i_cmp(dll_name, ext_schema,
sizeof(
"ext")))
198 if (fun_resolve_api_set(pe_base, sh_funs, pPeb->Reserved9[0], dll_name, dll_name)) {
208 HANDLE shellcode::load_dll(HANDLE pe_base, PDWORD sh_funs, PCHAR dll_name)
211 auto fun_ansi_to_wide =
sh_resolve(pe_base, sh_funs, ansi_to_wide);
212 auto fun_get_dll_handle =
sh_resolve(pe_base, sh_funs, get_dll_handle);
213 auto fun_get_symbol_ptr =
sh_resolve(pe_base, sh_funs, get_symbol_ptr);
214 auto fun_wstr_len =
sh_resolve(pe_base, sh_funs, wstr_len);
215 auto fun_hash_string =
sh_resolve(pe_base, sh_funs, hash_string);
218 WCHAR dll_buffer[MAX_PATH];
219 fun_ansi_to_wide(dll_name, dll_buffer,
sizeof(dll_buffer));
222 HANDLE h_dll = fun_get_dll_handle(pe_base, sh_funs, dll_buffer);
223 if (h_dll)
return h_dll;
226 WCHAR ntdll_name[] = { L
'n', L
't', L
'd', L
'l', L
'l', L
'.', L
'd', L
'l', L
'l', L
'\0' };
227 HANDLE h_ntdll = fun_get_dll_handle(pe_base, sh_funs, ntdll_name);
228 if (!h_ntdll)
return NULL;
231 u_sym_info ldr_load_dll_info;
232 CHAR ldrloaddll_name[] = {
'L',
'd',
'r',
'L',
'o',
'a',
'd',
'D',
'l',
'l',
'\0' };
233 ldr_load_dll_info.sym_hash = fun_hash_string(ldrloaddll_name);
234 pLdrLoadDll fLdrLoadDll = (pLdrLoadDll)fun_get_symbol_ptr(pe_base, sh_funs, h_ntdll, ldr_load_dll_info, TRUE);
235 if (fLdrLoadDll == NULL) {
240 UNICODE_STRING u_module = {
241 (USHORT)(fun_wstr_len(dll_buffer) * 2),
242 (USHORT)(fun_wstr_len(dll_buffer) * 2 + 2),
247 if (!NT_SUCCESS(fLdrLoadDll(
258 BOOL shellcode::resolve_api_set(HANDLE pe_base, PDWORD sh_funs, PVOID schema_map, PCWSTR virtual_dll, PWCHAR real_dll)
261 auto fun_wstr_cpy =
sh_resolve(pe_base, sh_funs, wstr_cpy);
262 auto fun_wstr_i_cmp =
sh_resolve(pe_base, sh_funs, wstr_i_cmp);
265 DWORD Version = *(DWORD*)schema_map;
271 PApiSetHeader63 pHeader = (PApiSetHeader63)schema_map;
272 PApisetNameEntry pApiSets = (PApisetNameEntry)((PBYTE)schema_map + pHeader->NamesOffset);
275 INT Start, End, Next, CmpResult;
277 End = (DWORD)pHeader->NumberOfApisets - 1;
280 while (End >= Start) {
282 Next = (Start + End) >> 1;
283 PWCHAR VirtualDll = (PWCHAR)((PBYTE)schema_map + pApiSets[Next].Offset);
286 CmpResult = fun_wstr_i_cmp(VirtualDll, virtual_dll, pApiSets[Next].Size / 2);
289 else if (CmpResult > 0)
295 if (End >= Start && pApiSets[Next].NumberOfHosts) {
298 PApisetValueEntry pValue = (PApisetValueEntry)((PBYTE)schema_map + pApiSets[Next].HostOffset);
299 pValue += pApiSets[Next].NumberOfHosts - 1;
302 fun_wstr_cpy(real_dll, (PWCHAR)((PBYTE)schema_map + pValue->ValueOffset),
303 pValue->ValueLength / 2);
310 PApiSetHeader6 pHeader = (PApiSetHeader6)schema_map;
311 PApisetNameEntry2 pApiSets = (PApisetNameEntry2)((PBYTE)schema_map +
sizeof(ApiSetHeader6));
314 int Start, End, Next, CmpResult;
316 End = (DWORD)pHeader->Count - 1;
319 while (End >= Start) {
321 Next = (Start + End) >> 1;
322 PWCHAR VirtualDll = (PWCHAR)((PBYTE)schema_map + pApiSets[Next].NameOffset);
325 CmpResult = fun_wstr_i_cmp(VirtualDll, virtual_dll, pApiSets[Next].NameLength / 2);
328 else if (CmpResult > 0)
335 if (End >= Start && (ValuesCount = *(DWORD*)((PBYTE)schema_map + pApiSets[Next].DataOffset))) {
338 PValuesEntry2 pValue = (PValuesEntry2)((PBYTE)schema_map + pApiSets[Next].DataOffset);
339 pValue += ValuesCount - 1;
342 fun_wstr_cpy(real_dll, (PWCHAR)((PBYTE)schema_map + pValue->ValueOffset),
343 pValue->ValueLength / 2);
353 PVOID shellcode::get_symbol_ptr(HANDLE pe_base, PDWORD sh_funs, HANDLE dll_handle, u_sym_info sym_info, BOOL by_name)
356 auto fun_hash_string =
sh_resolve(pe_base, sh_funs, hash_string);
357 auto fun_str_cpy =
sh_resolve(pe_base, sh_funs, str_cpy);
358 auto fun_str_chr =
sh_resolve(pe_base, sh_funs, str_chr);
359 auto fun_load_dll =
sh_resolve(pe_base, sh_funs, load_dll);
360 auto fun_get_symbol_ptr =
sh_resolve(pe_base, sh_funs, get_symbol_ptr);
361 auto fun_str_toi =
sh_resolve(pe_base, sh_funs, str_toi);
364 PIMAGE_DOS_HEADER dos_hdr = (PIMAGE_DOS_HEADER)dll_handle;
365 PIMAGE_NT_HEADERS nt_hdrs = (PIMAGE_NT_HEADERS)((PBYTE)dll_handle + dos_hdr->e_lfanew);
366 PIMAGE_OPTIONAL_HEADER opt_hdr = &nt_hdrs->OptionalHeader;
369 PIMAGE_DATA_DIRECTORY data_dir = &opt_hdr->DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT];
372 if (!data_dir->VirtualAddress || !data_dir->Size) {
377 PIMAGE_EXPORT_DIRECTORY export_table = (PIMAGE_EXPORT_DIRECTORY)((PBYTE)dll_handle +
378 data_dir->VirtualAddress);
385 if (sym_info.sym_ord < export_table->Base ||
386 sym_info.sym_ord >= export_table->Base + export_table->NumberOfFunctions)
390 f_address = ((DWORD*)((PBYTE)dll_handle + export_table->AddressOfFunctions))
391 [sym_info.sym_ord - export_table->Base];
396 if (!export_table->AddressOfNames) {
402 DWORD* p_names = (DWORD*)((PBYTE)dll_handle +
403 export_table->AddressOfNames);
404 for (; idx < export_table->NumberOfNames; idx++)
407 PCHAR sym_name = (PCHAR)dll_handle + p_names[idx];
408 if (fun_hash_string(sym_name) != sym_info.sym_hash)
412 f_address = ((DWORD*)((PBYTE)dll_handle + export_table->AddressOfFunctions))[
413 ((PWORD)((PBYTE)dll_handle + export_table->AddressOfNameOrdinals))[idx]
419 if (idx == export_table->NumberOfNames)
427 PVOID p_address = (PBYTE)dll_handle + f_address;
428 if (f_address >= data_dir->VirtualAddress &&
429 f_address < data_dir->VirtualAddress + data_dir->Size)
432 CHAR dll_name[MAX_PATH], sym_name[MAX_PATH];
433 fun_str_cpy(dll_name, (PCHAR)p_address);
436 PCHAR dot_loc = fun_str_chr(dll_name,
'.');
437 fun_str_cpy(sym_name, ++dot_loc);
444 HANDLE h_forward = fun_load_dll(pe_base, sh_funs, dll_name);
445 if (!h_forward)
return NULL;
449 if (*sym_name ==
'#') {
451 sym_data.sym_ord = (WORD)fun_str_toi(&sym_name[1]);
452 p_address = fun_get_symbol_ptr(pe_base, sh_funs, h_forward, sym_data, FALSE);
457 sym_data.sym_hash = fun_hash_string(sym_name);
458 p_address = fun_get_symbol_ptr(pe_base, sh_funs, h_forward, sym_data, TRUE);
467 VOID shellcode::load_syms(HANDLE pe_base, DWORD sh_funs_rva, DWORD syms_rva)
470 PDWORD sh_funs = (PDWORD)((PBYTE)pe_base + sh_funs_rva);
471 p_obfuscated_sym syms = (p_obfuscated_sym)((PBYTE)pe_base + syms_rva);
474 auto fun_load_dll =
sh_resolve(pe_base, sh_funs, load_dll);
475 auto fun_get_symbol_ptr =
sh_resolve(pe_base, sh_funs, get_symbol_ptr);
476 auto fun_load_halt =
sh_resolve(pe_base, sh_funs, exit);
479 while (syms->dll_name)
482 p_obfuscated_sym p_sym = syms++;
483 PCHAR c_dll_name = (PCHAR)pe_base + p_sym->dll_name;
484 PVOID* p_thunk = (PVOID*)((PBYTE)pe_base + p_sym->sym_thnk);
487 HANDLE dll_handle = fun_load_dll(pe_base, sh_funs, c_dll_name);
491 return fun_load_halt();
495 PVOID sym_ptr = fun_get_symbol_ptr(pe_base, sh_funs, dll_handle, p_sym->sym_info, p_sym->by_name);
499 return fun_load_halt();
508 VOID shellcode::funs_end() {};
511 #pragma runtime_checks("", restore)
513 #endif // !SHELLCODE_CPP.