Собственно маленький пример загрузки dll через недокументированную LdrLoadDll из Ntdll.dll. Код полностью независим от Kernel32.dll, что даёт возможность использования его в shellcode. Для получения адреса ntdll.dll используется трюк с PEB, а для поиска адреса LdrLoadDll
используется самописанный парсер заголовка PE, аналог GetProcAddress. Всё предельно просто, но мало ли кому пригодится.
* код работает только под x86, чуть позже добавлю и для x64
* код работает только под x86, чуть позже добавлю и для x64
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 | // -------------------------------------------------------------- // This is example, how to load libraries using Ntdll.LdrLoadDll, // without Kernel32.dll // by JKornev <c> http://k0rnev.blogspot.com // -------------------------------------------------------------- #include <Windows.h> #include <stdio.h> typedef struct _LSA_UNICODE_STRING { USHORT Length; USHORT MaximumLength; PWSTR Buffer; } UNICODE_STRING, *PUNICODE_STRING; typedef struct _PEB_LDR_DATA { ULONG Length; BOOLEAN Initialized; PVOID SsHandle; LIST_ENTRY InLoadOrderModuleList; LIST_ENTRY InMemoryOrderModuleList; LIST_ENTRY InInitializationOrderModuleList; } PEB_LDR_DATA, *PPEB_LDR_DATA; typedef struct _LDR_DATA_TABLE_ENTRY { LIST_ENTRY InLoadOrderLinks; LIST_ENTRY InMemoryOrderLinks; LIST_ENTRY InInitializationOrderLinks; PVOID DllBase; PVOID EntryPoint; ULONG SizeOfImage; UNICODE_STRING FullDllName; UNICODE_STRING BaseDllName; ULONG Flags; USHORT LoadCount; USHORT TlsIndex; union { LIST_ENTRY HashLinks; struct { PVOID SectionPointer; ULONG CheckSum; }; }; ULONG TimeDateStamp; } LDR_DATA_TABLE_ENTRY, *PLDR_DATA_TABLE_ENTRY; typedef NTSTATUS (NTAPI *LdrLoadDllProc)(PWCHAR PathToFile, ULONG Flags, PUNICODE_STRING ModuleFileName, HMODULE *ModuleHandle); // Unicode string compare BOOL StrCmpW(LPWSTR str1, LPWSTR str2) { int i = 0; for (i = 0; ; i++) { if (str1[i] != str2[i]) { break; } if (!str1[i]) { return TRUE; } } return FALSE; } // String compare BOOL StrCmp(LPSTR str1, LPSTR str2) { int i = 0; for (i = 0; ; i++) { if (str1[i] != str2[i]) { break; } if (!str1[i]) { return TRUE; } } return FALSE; } // Searching module base address from LDR_MODULE list LPVOID GetModuleBaseAddr(LPWSTR mod_name) { DWORD peb = __readfsdword(0x30); LPVOID baseaddr = NULL; PPEB_LDR_DATA pldr_data = *(PPEB_LDR_DATA *)(peb + 0x0C); PLDR_DATA_TABLE_ENTRY pldr_mod = (PLDR_DATA_TABLE_ENTRY)((UINT)pldr_data->InMemoryOrderModuleList.Blink - 8), pldr_first; pldr_first = pldr_mod; do { if (pldr_mod->DllBase && StrCmpW(pldr_mod->BaseDllName.Buffer, mod_name)) { return pldr_mod->DllBase; } pldr_mod = (PLDR_DATA_TABLE_ENTRY)((UINT)pldr_mod->InMemoryOrderLinks.Blink - 8); } while (pldr_first != pldr_mod); return NULL; } // Searching export procedure address from PE module(dll) FARPROC GetExportProcAddr(LPVOID mod_base, LPSTR proc_name) { PIMAGE_DOS_HEADER pdos; PIMAGE_OPTIONAL_HEADER32 popt32; PIMAGE_EXPORT_DIRECTORY pexp; PDWORD pnames, pfuncs; PWORD pords; int i; LPSTR proc; //getting export directory pdos = (PIMAGE_DOS_HEADER)mod_base; if (pdos->e_magic != IMAGE_DOS_SIGNATURE) { return NULL; } popt32 = (PIMAGE_OPTIONAL_HEADER32)(pdos->e_lfanew + (UINT)mod_base + 4 + sizeof(IMAGE_FILE_HEADER)); pexp = (PIMAGE_EXPORT_DIRECTORY)(popt32->DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress + (UINT)mod_base); if (!pexp) {//export not found return NULL; } //searching function name pnames = (PDWORD)(pexp->AddressOfNames + (UINT)mod_base); pords = (PWORD)(pexp->AddressOfNameOrdinals + (UINT)mod_base); pfuncs = (PDWORD)(pexp->AddressOfFunctions + (UINT)mod_base); for (i = 0; i < pexp->NumberOfNames; i++) { proc = (LPSTR)(pnames[i] + (UINT)mod_base); if (StrCmp(proc, proc_name)) { break; } } if (i == pexp->NumberOfNames) {//not found return NULL; } return (FARPROC)(pfuncs[pords[i]] + (UINT)mod_base); } // Loading .dll example, without Kernel32.dll HMODULE LoadLibraryFromNtDll(LPWSTR lib_path) { HMODULE hmod, hlib = 0; LdrLoadDllProc LdrLoadDll; NTSTATUS res; UNICODE_STRING uni; hmod = (HMODULE)GetModuleBaseAddr(L"ntdll.dll"); if (!hmod) { return NULL; } LdrLoadDll = (LdrLoadDllProc)GetExportProcAddr(hmod, "LdrLoadDll"); uni.Buffer = lib_path; uni.Length = wcslen(lib_path) * 2; uni.MaximumLength = uni.Length + 2; res = LdrLoadDll(NULL, 0, &uni, &hlib); if (res) { return NULL; } return hlib; } int main(int argc, char *argv[]) { if (!LoadLibraryFromNtDll(L"testlib.dll")) { printf("Loading DLL failed!\n"); } else { printf("Loading DLL ok!\n"); } getchar(); return 0; } |
Комментариев нет:
Отправить комментарий