Nytro Posted January 23, 2012 Report Posted January 23, 2012 [C] Dynamic API calling Author: /*Calling Windows API without using any API.32bit version.Tested on Win7 x64.by January, 2012.This is how I've been doing my API calling for years.I believe I first started doing it with the Ju u stealer.Using an array of function pointers and an array of hashes for each library,I find it much easier to gather all of the necessary API pointersthan doing 1 function call for each API I want to use. Or doing a functioncall every time I want to use an API.get_k32base() has been changed from what it used to be because I found it was no longerworking on my win7. I do not guarantee it's effectiveness on other OS's.#trinity OG production.Fuck your crew.*/#include <windows.h>//I didn't have the header for these two structs so that's why they're here...typedef struct _UNICODE_STRING { USHORT Length; USHORT MaximumLength; PWSTR Buffer;} UNICODE_STRING, *PUNICODE_STRING;typedef struct _LDR_MODULE { LIST_ENTRY InLoadOrderModuleList; LIST_ENTRY InMemoryOrderModuleList; LIST_ENTRY InInitializationOrderModuleList; PVOID BaseAddress; PVOID EntryPoint; ULONG SizeOfImage; UNICODE_STRING FullDllName; UNICODE_STRING BaseDllName; ULONG Flags; SHORT LoadCount; SHORT TlsIndex; LIST_ENTRY HashTableEntry; ULONG TimeDateStamp;} LDR_MODULE, *PLDR_MODULE;//definitions for API we are importing.typedef HMODULE (WINAPI *LoadLibraryW_)(LPCWSTR lpLibFileName);typedef int (WINAPI *MessageBoxW_)(HWND hWnd, LPCWSTR lpText, LPCWSTR lpCaption, UINT uType);typedef int (WINAPI *MessageBoxA_)(HWND hWnd, LPCSTR lpText, LPCSTR lpCaption, UINT uType);//hashes for API we are importing.#define dwLoadLibraryW 0x5FBFF111#define dwMessageBoxW 0x384F14CA#define dwMessageBoxA 0x384F14B4//function pointers for API we are importing.static LoadLibraryW_ LLW;static MessageBoxW_ MBW;static MessageBoxA_ MBA;//Arrays for API we are importing.//Must have a corresponding array of hashes and addresses function pointers for each library.//Kernel32//Yes, I know it's dumb to have an array of 1 element...but that's just how the function works.//This could be redone so that you don't need the Kernel32Hashes array but it's in here for uniformity.static const DWORD Kernel32Hashes[] = { dwLoadLibraryW };static LPVOID* Kernel32Ptrs[] = { (LPVOID*)&LLW };//User32//MessageBoxW AND MessageBoxA?!? Yeah... I didn't have any better ideas for a simple example.static const DWORD User32Hashes[] = { dwMessageBoxW, dwMessageBoxA };static LPVOID* User32Ptrs[] = { (LPVOID*)&MBW, (LPVOID*)&MBA };//code..int _lstrcmpW_(LPCWSTR str1, LPCWSTR str2)/*lstrcmpW replacement function so that there is no unnecessary imports in the IAT.this doesn't behave exactly as lstrcmpW but I don't need it toI just needed it to tell if two strings are the same, I don't care what the numerical difference is.It would be advisable to turn this into something that compares the hash of the two strings but its whatevs.inputs: two null terminated, wide character strings.outputs: 0 if strings are the same, else -1.*/{if (*str1 == 0 || *str2 == 0) return -1;while (*str1 && *str2){ if (*str1 != *str2) return -1; str1++; str2++;}if (*str1 || *str2) return -1;return 0;}DWORD DJBHash(LPCSTR str)/* not by me.old, simple hashing function, don't know the real author.modified to specifically hash null terminated ASCII strings.inputs: null terminated string.outputs: 32-bit hash of input null terminated string.*/{ DWORD hash = 5381; for(; *str; str++) { hash = ((hash << 5) + hash) + (*str); } return hash;}LPVOID GetAPI_FROM_DJB(const LPVOID library, const DWORD APIHASH)/*GetProcAddress replacement. Uses hashes of api names instead of strings.inputs:library = handle or base address to library (DLL) currently loaded in memory.APIHASH = hash of API name we are searching for.outputs:on success: pointer to library function that can be called from a function pointer.on error: NULL.*/{PIMAGE_EXPORT_DIRECTORY lExport;DWORD x;if (library){ lExport = (PIMAGE_EXPORT_DIRECTORY)((DWORD)library + ((PIMAGE_NT_HEADERS)((DWORD)library + ((PIMAGE_DOS_HEADER)library)->e_lfanew))->OptionalHeader.DataDirectory[0].VirtualAddress); DWORD *Names = (DWORD*)((DWORD)library + lExport->AddressOfNames); WORD *Ordinals = (WORD*)((DWORD)library + lExport->AddressOfNameOrdinals); DWORD *Functions = (DWORD*)((DWORD)library + lExport->AddressOfFunctions); for (x = 0; x < lExport->NumberOfNames; x++) { if (DJBHash((char*)(Names[x] + (DWORD)library)) == APIHASH) return (LPVOID)(Functions[Ordinals[x]] + (DWORD)library); }}return NULL;}LPVOID get_k32base()/*The assembly code is not mine, just modified from an old source by drn. I believe it was originally by Vecna or somebody.inputs: none, obviously.outputs: base address of kernel32.dll (if you are using windows2000 this will fail if kernel32 is not already linked in the import table, due to bug in win2k.)*/{LPVOID k32base = NULL;PLDR_MODULE lm, lol;__asm{ pushad xor eax, eax mov eax, fs:[eax+30h] mov eax, [eax+0ch] mov esi, [eax+0ch] lodsd mov [lm], eax popad }lol = lm;while (true){ if (!lm->BaseDllName.Buffer) break; if (_lstrcmpW_(L"kernel32.dll", lm->BaseDllName.Buffer) == 0) { k32base = lm->BaseAddress; break; } lm = (PLDR_MODULE)lm->InLoadOrderModuleList.Flink; if (lm == lol || !lm) //don't wanna loop infinitely if user is on win2k or some future Windows that doesn't explicitly link kernel32. break;}return k32base;}void fillAPIPtrs(const LPVOID DllBase, const DWORD dwNumFuncs, const DWORD *HashArray, LPVOID **PtrArray)/*Will fill an array of pointers to API from within a given library.inputs: DllBase: Base address of library we are searching. dwNumFuncs: Number of members in HashArray and PtrArray. Basically the number of API we are searching for in the library. HashArray: Array of DWORDS that are corresponding hashes for pointers to be filled in PtrArray. Must be same size as PtrArray. PtrArray: Array of function pointers to be filled. Must be same size as HashArray.outputs: none, fills PtrArray with (hopefully) valid pointers to desired API.*/{DWORD i;for (i = 0; i < dwNumFuncs; i++) *PtrArray[i] = GetAPI_FROM_DJB(DllBase, HashArray[i]);}int main(){LPVOID k32;LPVOID user32;k32 = get_k32base();fillAPIPtrs(k32, sizeof(Kernel32Hashes) / sizeof(DWORD), Kernel32Hashes, Kernel32Ptrs);if (LLW){ user32 = LLW(L"user32"); if (user32) { fillAPIPtrs(user32, sizeof(User32Hashes) / sizeof(DWORD), User32Hashes, User32Ptrs); if (MBW && MBA) { if (MBW(NULL, L":D", L"Hello World!", MB_YESNO) == IDYES) MBA(NULL, "Party All the Time", "\\o/", MB_OK); else MBA(NULL, "y u gay?", "D:", MB_OK); } }}return 0;}Sursa: http://www.hackhound.org/forum/topic/43503-dynamic-api-calling/ Quote