Nt Filesystem Dupe
March 21, 2024 ยท View on GitHub
A library for file & module redirection and hiding, by hooking various Nt APIs.
This project is inspired by CODEX Steam emu and based on reversing it. Credits to them.
Solution structure
The solution is divided into 3 projects:
nt_file_dupe: The actual library, this is a static library (.lib)dll_interface: A thin wrapper.dllproject around the static library, exporting the necessary functionstestxxx: A simple console app to test the library + helpers
JSON file format:
{
"myfile.txt": {
"mode": "file_redirect",
"to": "myfile.org",
"file_must_exist": true
},
"path/myfile_22.txt": {
"mode": "file_redirect",
"to": "path/myfile_22.org",
},
"../../folder/some_file.txt": {
"mode": "file_redirect",
"to": "../../folder/some_file.org",
},
"hideme.txt": {
"mode": "file_hide"
},
"../hideme_22.txt": {
"mode": "file_hide"
},
"prevent_me.dll": {
"mode": "module_prevent_load"
},
"prevent_me": {
"mode": "module_prevent_load"
},
"my_module_org.dll": {
"mode": "module_redirect",
"to": "my_module_mod.dll"
},
"my_module_org": {
"mode": "module_redirect",
"to": "my_module_mod"
}
}
Each JSON key is considered the original file, the value/object for that key defines the action for the original file.
The entry type is determined by the mode JSON key.
-
mode
file_redirect
Redirect original file creation/openingtoa target file.
Target files are always hidden.file_hide
Hide the file, as if it doesn't exist on disk.
module_prevent_load
Prevent loading the module viaLoadLibrary()and its variants.module_redirect
Redirect the loading operationtoanother target module.
Target modules are always hidden and cannot be loaded by the process.module_hide_handle
PreventGetModuleHandle()from succeeding, this won't affectLoadLibrary()and its variants.
As if the module doesn't exist in the current process memory.
-
to
Defines which target file/module to redirect the original file/module to.
Only useful whenmodeis:file_redirectmodule_redirect
-
file_must_exist(default =false)
When set totrue, the JSON entry will be skipped if the original file doesn't exist, or the target file doesn't exist infile_redirectmode
Check the example sample.json
Behavior
In case this is a file entry, the paths to the original or target files could be absolute or relative.
Relative paths will be relative to the location of the current .exe, not the current directory.
In case this is a module entry, the paths to the original or target modules must be just their filenames.
Both the original and target files/modules must have the same filename length.
Additionally, if this is a file entry, they must exist in the same dir.
Target files/modules are hidden by default, for example, in the JSON file defined above:
myfile.orgWill be hidden and cannot be opened/createdmy_module_mod.dllWill be hidden and cannot be loaded
If file_must_exist = true, then this JSON entry will be ignored without an error if:
- The original file was missing
- The
mode=file_redirectand the target file, defined by the JSON keyto, is missing
The dll will try to load only one of the following files upon startup in that order:
- A JSON file with the same name as the
.dllitself nt_file_dupe.jsonnt_file_dupe_config.jsonnt_fs_dupe.jsonnt_fs_dupe_config.jsonnt_dupe.jsonnt_dupe_config.json
Any of these files must exist beside the .dll, not the current running .exe
Upon startup, the dll will try to hide itself, both on disk and in memory.
Additionally in the debug build, it will try to hide the log file on disk.
How use the pre-built .dll:
- Create a
.jsonfile with some entries as shown above - Rename the
.jsonfile to the same name of the.dll, for example if the.dllis callednt_file_dupe.dll, then the.jsonfile must be namednt_file_dupe.json - Place both the
.dlland the.jsonfiles beside each other in the same folder - Load the
.dllinside your target, either modify the imports table with something likeCFF Explorer, or use any dll loader/injector
Note that the functions to add entries are not thread safe.
How to link and use as a static lib (.lib):
- Open the Visual Studio solution file
nt_file_dupe.slnand build the projectnt_file_dupe.
Make sure to select the right architecture (x64orx86) and build type (releaseordebug) - Assuming for example you've selected
Debug | x64, the library will be built inbin\x64\nt_file_dupe\nt_file_dupe_static.lib - In your own Visual Studio project, you must use C++ language version >=
C++17,
add the static.libfile as an input to the linker: .lib files as linker input - Finally, add the folder
nt_file_dupe\includeas an extra include directory: Additional include directories - Everything will be under the namespace
ntfsdupe:: - Check how the
.dllwrapper project is importing the required.hppfiles, and using the library in its DllMain
How to link and use as a dynamic lib (.dll):
- Open the Visual Studio solution file
nt_file_dupe.slnand build the projectdll_interface.
Make sure to select the right architecture (x64orx86) and build type (releaseordebug) - Assuming for example you've selected
Debug | x64, the library will be built as 2 parts in
Notice that thebin\Debug\x64\dll_interface\nt_file_dupe.dll bin\Debug\x64\dll_interface\nt_file_dupe.lib.dllfile must be accompanied by a small-sized.libfile which we'll use next - In your own Visual Studio project, you must use C++ language version >=
C++17,
add the static.libfile as an input to the linker: .lib files as linker input - Finally, add the folder
dll_interface\includeas an extra include directory: Additional include directories - All available exports will have this prefix
ntfsdupe_#include "nt_file_dupe.hpp" int main() { ntfsdupe_load_file(L"myfile.json"); ntfsdupe_add_entry(ntfsdupe::itf::Mode::file_hide, L"some_file.dll", nullptr); return 0; } - The file
nt_file_dupe.dllwill be added to your imports table, so make sure to copy this.dllfile beside your project's build output