Jump to content
Nytro

[C] Dynamic API calling

Recommended Posts

Posted

[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/

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...