Exetools

Exetools (https://forum.exetools.com/index.php)
-   Source Code (https://forum.exetools.com/forumdisplay.php?f=46)
-   -   [C/ASM] Easy to use DLL hijacking examples (https://forum.exetools.com/showthread.php?t=18332)

zeffy 07-27-2017 05:40

[C/ASM] Easy to use DLL hijacking examples
 
Hi, I've been working on a project where I needed to inject some code into a process via a hijacked DLL. I understand this is a pretty simple thing to do, but when I looked around, there wasn't really a lot of good examples. The automatic project generators I've found also either output poor code or just don't work at all.

So instead, I wrote my own solution. It's a couple of template projects that have all the code required for being a drop in replacement for either winmm.dll or version.dll.

https://github.com/zeffy/proxydll_template

For an example using version.dll (the project that I needed this for): https://github.com/zeffy/disablesteamlinkfilter

- The original DLL and its functions are lazy-loaded upon request using an asm springboard (x86 and x64 are both supported).
- The projects are also set up in a way where you can easily create versions of both dlls for the same code base.
- Works well with Tsuda Kageyu's minhook for additional hooking.

I've found that this method isn't compatible with all processes, but usually at least one of the DLLs will work.

It's still a work in progress, but it works well for me. Any criticisms or suggestions are definitely welcome.

CrackAttackz 08-21-2017 09:45

Looks very neat, I'll have to play around with it a bit more. Do you know how how far backward compatible it is with older versions of Windows?

zeffy 08-21-2017 10:56

Thanks for showing an interest! :D

The only APIs it uses are LoadLibrary, GetProcAddress, GetSystemDirectory and a couple CRT functions, so I think it should be pretty backwards compatible, though I haven't tested them on anything prior to Windows 7. Other than that, you might have to adjust the project settings to target older systems, I'm not really sure.

On a side note, I've noticed the x64 versions can be a little unreliable (have experienced non-consistent crashes using the winmm.dll proxy with a game I was reversing) that could be due to stack management issues in the assembly. But the x86 builds should be stable.

SinaDiR 08-21-2017 16:23

Quote:

Originally Posted by CrackAttackz (Post 110218)
Looks very neat, I'll have to play around with it a bit more. Do you know how how far backward compatible it is with older versions of Windows?

Works fine on windows XP sp3

atom0s 08-21-2017 16:58

Here is another way you can make a proxy fairly easy and slim. Since you do not need to know the actual function prototype/parameters when exporting things that are just using direct jumps via inline asm, you can mix and abuse macros with inline asm to export things easy.

PHP Code:

#include <Windows.h>

HMODULE g_ModuleHandle nullptr;       // This proxies module handle.
HMODULE g_RealModuleHandle nullptr;   // The real modules handle being proxied.

/**
 * Obtains the original export from the real module.
 */
BOOL APIENTRY GetRealExport(const charnameFARPROCout)
{
    
// Ensure the real module is loaded..
    
if (g_RealModuleHandle == nullptr)
        return 
FALSE;

    
// Todo: Add any type of function caching if you want here..

    // Obtain the real export function..
    
*out = ::GetProcAddress(g_RealModuleHandlename);
    return (*
out == nullptr);
}

/**
 * Generates an export function wrapper for the given exported function by name.
 */
#define EXPORTORIG(n)                               \
    
FARPROC orig_##n = nullptr;                     \
    
__declspec(nakedvoid __stdcall real_##n() {   \
        
GetRealExport(#n, &orig_##n);               \
        
__asm jmp orig_##n                          \
    
}

EXPORTORIG(Direct3DCreate9);

/**
 * Initialize the proxy for use.
 */
BOOL APIENTRY InitializeProxy(HINSTANCE hinstDLL)
{
    
// Store the modules handle..
    
g_ModuleHandle hinstDLL;

    
// Build the path to the original module..
    
char path[MAX_PATH] = { };
    ::
GetSystemDirectory(pathMAX_PATH);
    
strcat_s(path"\\d3d9.dll");

    
// Load the original module..
    
g_RealModuleHandle = ::LoadLibrary(path);
    if (
g_RealModuleHandle == nullptr)
        return 
FALSE;

    return 
TRUE;
}

/**
 * Entry point.
 */
BOOL APIENTRY DllMain(HINSTANCE hinstDLLDWORD fdwReasonLPVOID lpvReserved)
{
    switch (
fdwReason)
    {
    case 
DLL_PROCESS_ATTACH:
        ::
DisableThreadLibraryCalls(hinstDLL);
        return 
InitializeProxy(hinstDLL);
    }
    return 
TRUE;


And in the .def file:

PHP Code:

LIBRARY
EXPORTS
    Direct3DCreate9 
real_Direct3DCreate9 

Beings that this is using a macro for the dirty work/heavy lifting you can easy create a template/skeleton project to auto-generate the entire proxy dll for you like this just by having it read the original exports from the target file and generating the rest.

Note, this method as-is will have issues with exports that are by ordinal and not by name. You would have to tweak the generated names a tad to work with ords instead.

zeffy 08-21-2017 17:30

Thank you for sharing your code atom0s! I've used something very similar to it before I created these template projects. The reason I opted to use complete ASM instead of inline is because it isn't supported by VC in x64 builds, only x86.

Additionally, calling your InitializeProxy (and thus LoadLibrary) from DllMain can cause the process to deadlock under certain conditions. For this reason, MSDN specifically advises people not to call LoadLibrary from DllMain. Although I've never encountered it happen in practice, that could change in the future or in edge cases. That's why I opted to delay the loading until one of its functions is actually called. Either approach works though. :)

atom0s 08-21-2017 17:34

Quote:

Originally Posted by zeffy (Post 110227)
Thank you for sharing your code atom0s! I've used something very similar to it before I created these template projects. The reason I opted to use complete ASM instead of inline is because it isn't supported by VC in x64 builds, only x86.

Additionally, calling your InitializeProxy (and thus LoadLibrary) from DllMain can cause the process to deadlock under certain conditions. For this reason, MSDN specifically advises people not to call LoadLibrary from DllMain. Although I've never encountered it happen in practice, that could change in the future or in edge cases. That's why I opted to delay the loading until one of its functions is actually called. Either approach works though. :)

I generally do the same with late loading, generally via exporting an 'Install' function from the main hook and using a loader to invoke it. The example above was just a quick throw together to show off the macro method of making a fast proxy.

zeffy 08-23-2017 15:46

Quote:

Originally Posted by atom0s (Post 110228)
I generally do the same with late loading, generally via exporting an 'Install' function from the main hook and using a loader to invoke it. The example above was just a quick throw together to show off the macro method of making a fast proxy.

That's a neat idea about exporting an 'Install' function!

I've actually been working on simplifying my project using macros similar to how you did (except in the assembly), which has made it much easier to maintain compared to before. I also fixed the "random" crashing bug that I referred to earlier (which was caused by stack corruption and some of the volatile registers getting mutilated by my proc resolver function :o). If you or anyone else is interested in taking a look, here's an example of the changes I've made:
https://github.com/zeffy/proxydll_te...inmm/winmm.asm

Edit: OK I really fixed the register mutilation now... I was restoring r8 to r9 and r9 to r8 in the last commit. :o :o :o

SinaDiR 06-04-2019 03:33

zeffy did you try to compile 64-bit? I was succeed on compile x86 but stuck on x64, what did I miss?

SinaDiR 06-04-2019 04:09

I have no permission to edit my post.
The problem was the VS could not locate 'ksamd64.inc' I solved the problem by pass the exact path of the file.
Thank you

ionioni 03-10-2020 01:03

https://github.com/zeffy/proxydll_template latest commit to date 70b8764
x64 dll hijacker made using this might cause errors on some Windows flavours & build configs due to wrong stack alignment in the "PRX_EXPORT64 macro procname:req, ordinal:req" defined in each asm file, causing a #GP fault on instructions needing 16 byte boundary (movaps), it happened some dozen chained calls from the unaligned stack place, in system area.

Fix:
alloc_stack 20h to alloc_stack 28h
....
add rsp, 20h to add rsp, 28h
in the macro function definition of the asm file

zeffy 03-12-2020 10:40

Quote:

Originally Posted by ionioni (Post 119515)
https://github.com/zeffy/proxydll_template latest commit to date 70b8764
x64 dll hijacker made using this might cause errors on some Windows flavours & build configs due to wrong stack alignment in the "PRX_EXPORT64 macro procname:req, ordinal:req" defined in each asm file, causing a #GP fault on instructions needing 16 byte boundary (movaps), it happened some dozen chained calls from the unaligned stack place, in system area.

Fix:
alloc_stack 20h to alloc_stack 28h
....
add rsp, 20h to add rsp, 28h
in the macro function definition of the asm file

Thanks, I have committed the changes you suggested. I don't have time to test it, but I'm sure it works fine.

Just fyi, I haven't been maintaining these templates recently, because I switched to using __pfnDliNotifyHook2 to implement DLL proxying on my personal projects, and haven't had time to create new templates for all the DLLs supported by this project.

FoxB 08-26-2022 13:35

@zeffy: you can up your https://github.com/zeffy/proxydll_template ?

Mahmoudnia 08-26-2022 16:40

Quote:

Originally Posted by FoxB (Post 125832)
@zeffy: you can up your https://github.com/zeffy/proxydll_template ?


try this

HTML Code:

https://github.com/blaquee/proxydll_template

zeffy 08-27-2022 01:46

1 Attachment(s)
Quote:

Originally Posted by FoxB (Post 125832)
@zeffy: you can up your https://github.com/zeffy/proxydll_template ?

sure, here is the latest with git history. the one linked above is a little outdated, I think.

alt: hxxps://www11.zippyshare.com/v/5pjAlw1a/file.html

FoxB 08-27-2022 16:55

ok
we can not load dll from %systemroot%\system32 in some situations.
the behavor is change if used the registry data for "SafeDllSearchMode" is set 1 in
[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager]

or
"DevOverrideEnable" is set 1 in
[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options]
with .local for the executable file extension

Stingered 08-28-2022 05:30

Quote:

Originally Posted by FoxB (Post 125838)
ok
we can not load dll from %systemroot%\system32 in some situations.
the behavior is change if used the registry data for "SafeDllSearchMode" is set 1 in
[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager]

or
"DevOverrideEnable" is set 1 in
[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options]
with .local for the executable file extension

I don't understand how setting SafeDllSearchMode to 1, change any behavior. Value 1 is enabled and ON by default (at least on current OS - XP/Win7 probably not). But this value only change the search order, not remove them:

Standard Search Order for Desktop Applications
The standard DLL search order used by the system depends on whether safe DLL search mode is enabled or disabled. Safe DLL search mode places the user's current directory later in the search order.

Safe DLL search mode is enabled by default. To disable this feature, create the HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\SafeDllSearchMode registry value and set it to 0. Calling the SetDllDirectory function effectively disables SafeDllSearchMode while the specified directory is in the search path and changes the search order as described in this topic.

If SafeDllSearchMode is enabled, the search order is as follows:

The directory from which the application loaded.
The system directory. Use the GetSystemDirectory function to get the path of this directory.
The 16-bit system directory. There is no function that obtains the path of this directory, but it is searched.
The Windows directory. Use the GetWindowsDirectory function to get the path of this directory.
The current directory.
The directories that are listed in the PATH environment variable. Note that this does not include the per-application path specified by the App Paths registry key. The App Paths key is not used when computing the DLL search path.


If SafeDllSearchMode is disabled, the search order is as follows:

The directory from which the application loaded.
The current directory.
The system directory. Use the GetSystemDirectory function to get the path of this directory.
The 16-bit system directory. There is no function that obtains the path of this directory, but it is searched.
The Windows directory. Use the GetWindowsDirectory function to get the path of this directory.
The directories that are listed in the PATH environment variable. Note that this does not include the per-application path specified by the App Paths registry key. The App Paths key is not used when computing the DLL search path.


Also, the DevOverrideEnable is used for DLL redirection.

hxxps://github.com/MicrosoftDocs/win32/blob/docs/desktop-src/Dlls/dynamic-link-library-redirection.md

There must be a PEfilename.exe.local file created in the same directory of the "older" DLL to allow the dependent application to load from the location on executable that need specific DLL.

I actually don't know if this even an issue due to DLL search order mechanics in place today. I know I use this in Win7 (for certain DLLs - maybe known DLLs? I can't recall), but on Win10/11 I just drop a .DLL I build into the folder of the EXE I want to patch it's memory. EXE loads my DLL and I can call Loadlibrary() to load \system32 DLL to handle any function requests that the EXE may call.

acme 09-08-2022 18:30

Wanna give big shout to everybody on this thread because shared very useful links and tips, I was working in a past project about DLL hijacking to and found many useful info here than from documentation alredy wrote around :)

Always the best people in here <3

Fyyre 09-16-2022 22:44

Quote:

Originally Posted by zeffy (Post 125834)
sure, here is the latest with git history. the one linked above is a little outdated, I think.

alt: hxxps://www11.zippyshare.com/v/5pjAlw1a/file.html

@zeffy

Hello my friend! (long time no speak!)

Told you those hook templates are awesome ; )


@FoxB - I cannot say I have encountered this behavior, not if using DLLs such as d3d9.dll or version.dll - or simply loading SysInternals ProcMon and watching all of the system32 Dlls it tries to load from the application directory ^^

-Fyyre

FoxB 09-17-2022 23:23

1 Attachment(s)
@Fyyre: i just compile the proxy 'version.dll' and try to use it.
on attached screen we can to see my 'version.dll' and original dll is not load from %systemroot%\system32\

same for 'iphlpapi.dll'


All times are GMT +8. The time now is 12:46.

Powered by vBulletin® Version 3.8.8
Copyright ©2000 - 2023, vBulletin Solutions, Inc.
Always Your Best Friend: Aaron, JMI, ahmadmansoor, ZeNiX