Jump to content
Nytro

[C] Dynamic API calling

Recommended Posts

[C] Dynamic API calling

Author: :D

/*
Calling Windows API without using any API.
32bit version.
Tested on Win7 x64.
by :D
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 pointers
than doing 1 function call for each API I want to use. Or doing a function
call 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 longer
working 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 to
I 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/

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.



×
×
  • Create New...