diff --git a/DarkLoadLibrary/amsi.dll b/DarkLoadLibrary/amsi.dll new file mode 100644 index 0000000..5cd2d9a Binary files /dev/null and b/DarkLoadLibrary/amsi.dll differ diff --git a/DarkLoadLibrary/include/darkloadlibrary.h b/DarkLoadLibrary/include/darkloadlibrary.h index 219f660..e5780d1 100644 --- a/DarkLoadLibrary/include/darkloadlibrary.h +++ b/DarkLoadLibrary/include/darkloadlibrary.h @@ -36,4 +36,7 @@ PDARKMODULE DarkLoadLibrary( LPVOID lpFileBuffer, DWORD dwLen, LPCWSTR lpwName -); \ No newline at end of file +); + +SIZE_T WideStringLength(LPWSTR str); +BOOL WideStringCompare(LPWSTR lpwStr1, LPWSTR lpwStr2, SIZE_T cbMaxCount); \ No newline at end of file diff --git a/DarkLoadLibrary/include/pebutils.h b/DarkLoadLibrary/include/pebutils.h index 5bf1f41..bb35324 100644 --- a/DarkLoadLibrary/include/pebutils.h +++ b/DarkLoadLibrary/include/pebutils.h @@ -1,4 +1,5 @@ #include +#include #include "pebstructs.h" #include "darkloadlibrary.h" @@ -16,7 +17,14 @@ typedef NTSTATUS(NTAPI* RTLHASHUNICODESTRING)(UNICODE_STRING* String, BOOLEAN Ca typedef SIZE_T(NTAPI* RTLCOMPAREMEMORY)(const VOID* Source1, const VOID* Source2, SIZE_T Length); typedef int(__cdecl* _WCSNICMP)(const wchar_t* _Str1, const wchar_t* _Str2, size_t _MaxCount); typedef int(__cdecl* STRCMP)(const char* _Str1, const char* _Str2); -typedef size_t(__cdecl* MBSTOWCS)(wchar_t* Dest, const char* _Source, size_t _MaxCount); +typedef int(WINAPI *MULTIBYTETOWIDECHAR)( + UINT CodePage, + DWORD dwFlags, + LPCCH lpMultiByteStr, + int cbMultiByte, + LPWSTR lpWideCharStr, + int cchWideChar +); typedef int(__cdecl* _WCSICMP)(const wchar_t* _Str1, const wchar_t* _Str2); #ifdef _WIN64 diff --git a/DarkLoadLibrary/src/darkloadlibrary.c b/DarkLoadLibrary/src/darkloadlibrary.c index cf6a43f..a998d23 100644 --- a/DarkLoadLibrary/src/darkloadlibrary.c +++ b/DarkLoadLibrary/src/darkloadlibrary.c @@ -1,6 +1,40 @@ #include "darkloadlibrary.h" #include "ldrutils.h" +SIZE_T WideStringLength(LPWSTR str) +{ + SIZE_T len = 0; + SIZE_T i = 0; + + while (str[i++]) + ++len; + + return len; +} + +BOOL WideStringCompare(LPWSTR lpwStr1, LPWSTR lpwStr2, SIZE_T cbMaxCount) +{ + BOOL match = TRUE; + + for (SIZE_T i = 0; i < cbMaxCount; i++) + { + WCHAR a, b; + a = lpwStr1[i]; + b = lpwStr2[i]; + if (a >= 'A' && a <= 'Z') + a += 32; + if (b >= 'A' && b <= 'Z') + b += 32; + if (a != b) + { + match = FALSE; + break; + } + } + + return match; +} + BOOL ParseFileName( PDARKMODULE pdModule, LPWSTR lpwFileName diff --git a/DarkLoadLibrary/src/main.c b/DarkLoadLibrary/src/main.c index 014e32c..d48b5cc 100644 --- a/DarkLoadLibrary/src/main.c +++ b/DarkLoadLibrary/src/main.c @@ -13,7 +13,7 @@ VOID main() PDARKMODULE DarkModule = DarkLoadLibrary( LOAD_LOCAL_FILE, - L"TestDLL.dll", + L"amsi.dll", NULL, 0, NULL diff --git a/DarkLoadLibrary/src/pebutils.c b/DarkLoadLibrary/src/pebutils.c index 55aba36..7743f5b 100644 --- a/DarkLoadLibrary/src/pebutils.c +++ b/DarkLoadLibrary/src/pebutils.c @@ -26,8 +26,6 @@ PLDR_DATA_TABLE_ENTRY2 FindLdrTableEntry( PPEB2 pPeb; PLDR_DATA_TABLE_ENTRY2 pCurEntry; PLIST_ENTRY pListHead, pListEntry; - - _WCSNICMP p_wcsnicmp = (_WCSNICMP)GetFunctionAddress(IsModulePresent(L"ucrtbased.dll"), "_wcsnicmp"); pPeb = (PPEB2)READ_MEMLOC(PEB_OFFSET); @@ -44,10 +42,10 @@ PLDR_DATA_TABLE_ENTRY2 FindLdrTableEntry( pCurEntry = CONTAINING_RECORD(pListEntry, LDR_DATA_TABLE_ENTRY2, InLoadOrderLinks); pListEntry = pListEntry->Flink; - INT BaseName1 = p_wcsnicmp(BaseName, pCurEntry->BaseDllName.Buffer, (pCurEntry->BaseDllName.Length / sizeof(wchar_t)) - 4); - INT BaseName2 = p_wcsnicmp(BaseName, pCurEntry->BaseDllName.Buffer, pCurEntry->BaseDllName.Length / sizeof(wchar_t)); + //BOOL BaseName1 = WideStringCompare(BaseName, pCurEntry->BaseDllName.Buffer, (pCurEntry->BaseDllName.Length / sizeof(wchar_t)) - 4); + BOOL BaseName2 = WideStringCompare(BaseName, pCurEntry->BaseDllName.Buffer, WideStringLength(BaseName)); - if (!BaseName1 || !BaseName2) + if (BaseName2 == TRUE) { return pCurEntry; } @@ -64,6 +62,11 @@ PRTL_RB_TREE FindModuleBaseAddressIndex() PRTL_BALANCED_NODE pNode = NULL; PRTL_RB_TREE pModBaseAddrIndex = NULL; + /* + TODO: + Implement these manually cause these could totally be hooked + and various other reasons + */ RTLCOMPAREMEMORY pRtlCompareMemory = (RTLCOMPAREMEMORY)GetFunctionAddress(IsModulePresent(L"ntdll.dll"), "RtlCompareMemory"); STRCMP pstrcmp = (STRCMP)GetFunctionAddress(IsModulePresent(L"ntdll.dll"), "strcmp"); @@ -307,11 +310,27 @@ HMODULE IsModulePresentA( char* Name ) { - MBSTOWCS pmbstowcs = (MBSTOWCS)GetFunctionAddress(IsModulePresent(L"ucrtbased.dll"), "mbstowcs"); + MULTIBYTETOWIDECHAR pMultiByteToWideChar = (MULTIBYTETOWIDECHAR)GetFunctionAddress(IsModulePresent(L"kernel32.dll"), "MultiByteToWideChar"); - wchar_t wtext[500]; - pmbstowcs(wtext, Name, strlen(Name) + 1); - return IsModulePresent(wtext); + WCHAR* wideName = NULL; + DWORD wideNameSize = 0; + + // MultiByteToWideChar returns size in characters, not bytes + wideNameSize = pMultiByteToWideChar(CP_UTF8, 0, Name, -1, NULL, 0) * 2; + + /* + Attempt to allocate this on the stack, seeing as it's faster and we can attempt + to avoid funny shit like heap fragmentation on a simple temp var + */ + wideName = (WCHAR*)_malloca(wideNameSize); + + pMultiByteToWideChar(CP_UTF8, 0, Name, -1, wideName, wideNameSize); + + HMODULE hModule = IsModulePresent(wideName); + + _freea(wideName); + + return hModule; } HMODULE IsModulePresent( @@ -336,6 +355,10 @@ HMODULE IsModulePresent( pLdrTbl = (PLDR_DATA_TABLE_ENTRY2)ucModPtrOff; + /* + TODO: + Make this its own ANSI case-insensitive string compare function + */ BOOL match = TRUE; for (int i = 0; i < pLdrTbl->BaseDllName.Length/2; i++) {