From 590b32dc01c3adbaddf69e72a794d693709a0ace Mon Sep 17 00:00:00 2001 From: Print3M <92022497+Print3M@users.noreply.github.com> Date: Fri, 22 Aug 2025 21:23:44 +0200 Subject: [PATCH 1/5] Header file created --- main.go | 4 +- output/output.go | 43 ++++++++++----------- output/utils.go | 24 +++++++++++- templates/dllshimmer.h.template | 53 ++++++++++++++++++++++++++ templates/dynamic-shim.cpp.template | 58 +---------------------------- templates/static-shim.cpp.template | 21 +---------- 6 files changed, 104 insertions(+), 99 deletions(-) create mode 100644 templates/dllshimmer.h.template diff --git a/main.go b/main.go index 7ff1617..bf4c078 100644 --- a/main.go +++ b/main.go @@ -23,7 +23,7 @@ func main() { TemplatesFS: &templatesFS, } - out.CreateCodeFile(flags.Mutex, flags.Static) + out.CreateCodeFiles(flags.Mutex, flags.Static) out.CreateDefFile() out.CreateCompileScript(flags.Static) @@ -35,7 +35,7 @@ func main() { fmt.Println("Success! What to do next?") fmt.Println() fmt.Printf(" 1. Jump into the '%s/' directory.\n", out.OutputDir) - fmt.Printf(" 2. Add your backdoor to the '%s' file.\n", out.GetCodeFileName()) + fmt.Printf(" 2. Add your backdoor to the '%s' file.\n", out.GetCppCodeFileName()) fmt.Printf(" 3. Compile project using the '%s' script.\n", out.GetCompileScriptName()) fmt.Println() } diff --git a/output/output.go b/output/output.go index b028486..93e8324 100644 --- a/output/output.go +++ b/output/output.go @@ -23,10 +23,14 @@ func (o *Output) GetDefFileName() string { return o.Dll.Name + ".def" } -func (o *Output) GetCodeFileName() string { +func (o *Output) GetCppCodeFileName() string { return o.Dll.Name + ".cpp" } +func (o *Output) GetHdrCodeFileName() string { + return "dllshimmer.h" +} + func (o *Output) GetCompileScriptName() string { return "compile.sh" } @@ -56,21 +60,7 @@ func (o *Output) GetTemplate(filename string) *template.Template { return template.Must(template.New("new").Parse(string(content))) } -func (o *Output) CreateCodeFile(mutex bool, isStaticLinked bool) { - templateFile := "dynamic-shim.cpp.template" - if isStaticLinked { - templateFile = "static-shim.cpp.template" - } - - tmpl := o.GetTemplate(templateFile) - outputPath := filepath.Join(o.OutputDir, o.GetCodeFileName()) - - f, err := os.Create(outputPath) - if err != nil { - log.Fatalf("[!] Error while creating '%s' file: %v", outputPath, err) - } - defer f.Close() - +func (o *Output) CreateCodeFiles(mutex bool, isStaticLinked bool) { params := CodeFileParams{ Functions: o.Dll.ExportedFunctions, OriginalPath: sanitizePathForInjection(o.Dll.OriginalPath), @@ -78,12 +68,23 @@ func (o *Output) CreateCodeFile(mutex bool, isStaticLinked bool) { DllName: o.Dll.Name, } - err = tmpl.Execute(f, params) - if err != nil { - log.Fatalf("[!] Error of template engine: %v", err) + o.createCppCodeFile(params, isStaticLinked) + o.createHdrCodeFile(params) +} + +func (o *Output) createCppCodeFile(params CodeFileParams, isStaticLinked bool) { + templateFile := "dynamic-shim.cpp.template" + if isStaticLinked { + templateFile = "static-shim.cpp.template" } - fmt.Printf("[+] '%s' file created\n", outputPath) + outputPath := filepath.Join(o.OutputDir, o.GetCppCodeFileName()) + createFileFromTemplate(o, templateFile, outputPath, params) +} + +func (o *Output) createHdrCodeFile(params CodeFileParams) { + outputPath := filepath.Join(o.OutputDir, o.GetHdrCodeFileName()) + createFileFromTemplate(o, "dllshimmer.h.template", outputPath, params) } func (o *Output) CreateDefFile() { @@ -166,7 +167,7 @@ func (o *Output) CreateCompileScript(isStaticLinked bool) { defer f.Close() params := CompileScriptParams{ - Code: o.GetCodeFileName(), + Code: o.GetCppCodeFileName(), Def: o.GetDefFileName(), Output: o.GetOutputDllName(), IsStaticLinked: isStaticLinked, diff --git a/output/utils.go b/output/utils.go index 6c80986..7777050 100644 --- a/output/utils.go +++ b/output/utils.go @@ -1,7 +1,29 @@ package output -import "strings" +import ( + "fmt" + "log" + "os" + "strings" +) func sanitizePathForInjection(path string) string { return strings.ReplaceAll(path, "\\", "\\\\") } + +func createFileFromTemplate[K interface{}](o *Output, template string, outputPath string, params K) { + tmpl := o.GetTemplate(template) + + f, err := os.Create(outputPath) + if err != nil { + log.Fatalf("[!] Error while creating '%s' file: %v", outputPath, err) + } + defer f.Close() + + err = tmpl.Execute(f, params) + if err != nil { + log.Fatalf("[!] Error of template engine: %v", err) + } + + fmt.Printf("[+] '%s' file created\n", outputPath) +} diff --git a/templates/dllshimmer.h.template b/templates/dllshimmer.h.template new file mode 100644 index 0000000..b468247 --- /dev/null +++ b/templates/dllshimmer.h.template @@ -0,0 +1,53 @@ +#pragma once + +// #------------------------------------------------------------------# +// | "DON'T TOUCH" ZONE | +// | (auto generated) | +// #------------------------------------------------------------------# + +#include +#include + +#define T UINT64 +#define PARAMS \ + T a1, T a2, T a3, T a4, T a5, T a6, T a7, T a8, T a9, T a10, T a11, T a12 +#define ARGS a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12 + +typedef T (*FuncPtr)(PARAMS); + + +void PrintCurrentDirectory() { + char buf[MAX_PATH]; + DWORD len = GetCurrentDirectoryA(MAX_PATH, buf); + if (len == 0 || len >= MAX_PATH) { + printf("\tGetCurrentDirectoryA failed\n"); + return; + } + + printf("\tCurrent directory: '%s'\n", buf); +} + + +FuncPtr getProxyFunc(const char *funcName) { + HMODULE hModule = LoadLibraryA("{{.OriginalPath}}"); + if (hModule == NULL) { + printf("[!] {{.DllName}}: LoadLibraryA({{.OriginalPath}}) failed\n"); + printf("\tError code: %lu\n", GetLastError()); + PrintCurrentDirectory(); + } + + FuncPtr pFunc = (FuncPtr)GetProcAddress(hModule, funcName); + if (pFunc == NULL) { + printf("[!] {{.DllName}}: GetProcAddress(%s, {{.OriginalPath}}) failed\n", + funcName); + printf("\tError code: %lu\n", GetLastError()); + } + + return pFunc; +} + + +#define MUTEX(name) \ + (CreateMutexA(NULL, TRUE, name) && GetLastError() != ERROR_ALREADY_EXISTS) + +#define PROXY_FUNCTION(funcName) getProxyFunc(funcName)(ARGS); \ No newline at end of file diff --git a/templates/dynamic-shim.cpp.template b/templates/dynamic-shim.cpp.template index 68285fb..ff20245 100644 --- a/templates/dynamic-shim.cpp.template +++ b/templates/dynamic-shim.cpp.template @@ -3,63 +3,9 @@ // Author: Print3M (print3m.github.io/) {{- $r := . }} +#include "dllshimmer.h" #include #include -#include -// Put your imports here... - -// #------------------------------------------------------------------# -// | "DON'T TOUCH" ZONE | -// | (auto generated) | -// #------------------------------------------------------------------# - -#define MUTEX(name) \ - (CreateMutexA(NULL, TRUE, name) && GetLastError() != ERROR_ALREADY_EXISTS) - -#define ARGS_COUNT 12 - -typedef uint64_t (*Func12)( - uint64_t, uint64_t, uint64_t, uint64_t, - uint64_t, uint64_t, uint64_t, uint64_t, - uint64_t, uint64_t, uint64_t, uint64_t -); - -#define T UINT64 -#define PARAMS T a1, T a2, T a3, T a4, T a5, T a6, T a7, T a8, T a9, T a10, T a11, T a12 -#define ARGS a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12 - -void PrintCurrentDirectoryA() { - char buf[MAX_PATH]; - DWORD len = GetCurrentDirectoryA(MAX_PATH, buf); - if (len == 0 || len >= MAX_PATH) { - printf("\tGetCurrentDirectoryA failed\n"); - return; - } - printf("\tCurrent directory: '%s'\n", buf); -} - -#define PROXY_FUNCTION(function) \ - \ - HMODULE hModule = LoadLibraryA("{{.OriginalPath}}"); \ - if (hModule == NULL) { \ - printf("[!] DismCore.dll: LoadLibraryA(DismCore2.dll) failed\n"); \ - printf("\tError code: %lu\n", GetLastError()); \ - PrintCurrentDirectoryA(); \ - } \ - \ - Func12 pFunction = (Func12) GetProcAddress(hModule, function); \ - if (pFunction == NULL) { \ - printf( \ - "[!] {{.DllName}}: GetProcAddress(%s, {{.OriginalPath}}) failed\n", \ - function ); \ - printf("\tError code: %lu\n", GetLastError()); \ - } \ - \ - return pFunction(ARGS); \ - -// #------------------------------------------------------------------# -// | END OF "DON'T TOUCH" ZONE | -// #------------------------------------------------------------------# {{- range $i, $v := .Functions }} {{- if eq (len $v.Forwarder) 0 }} @@ -76,7 +22,7 @@ extern "C" UINT64 {{$v.Name}}Fwd(PARAMS) { // Put your code here... {{- end }} - PROXY_FUNCTION("{{$v.Name}}"); + return PROXY_FUNCTION("{{$v.Name}}"); } {{- end }} diff --git a/templates/static-shim.cpp.template b/templates/static-shim.cpp.template index a1818e6..fbc7f9e 100644 --- a/templates/static-shim.cpp.template +++ b/templates/static-shim.cpp.template @@ -10,6 +10,7 @@ // | "DON'T TOUCH" ZONE | // | (auto generated) | // #------------------------------------------------------------------# +#include "dllshimmer.h" {{- range .Functions}} #define {{.Name}} {{.Name}}Original @@ -20,24 +21,6 @@ {{- end}} {{ $r := . }} -void PrintCurrentDirectoryA() { - char buf[MAX_PATH]; - DWORD len = GetCurrentDirectoryA(MAX_PATH, buf); - if (len == 0 || len >= MAX_PATH) { - printf("\tGetCurrentDirectoryA failed\n"); - return; - } - printf("\tCurrent directory: '%s'\n", buf); -} - - -#define MUTEX(name) \ - (CreateMutexA(NULL, TRUE, name) && GetLastError() != ERROR_ALREADY_EXISTS) - -#define T UINT64 -#define PARAMS T a1, T a2, T a3, T a4, T a5, T a6, T a7, T a8, T a9, T a10, T a11, T a12 -#define ARGS a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12 - // #------------------------------------------------------------------# // | END OF "DON'T TOUCH" ZONE | // #------------------------------------------------------------------# @@ -72,7 +55,7 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) { case DLL_PROCESS_ATTACH: { #ifdef DEBUG printf("[+] {{.DllName}}: DLL_PROCESS_ATTACH event\n"); - PrintCurrentDirectoryA(); + PrintCurrentDirectory(); #endif } case DLL_THREAD_ATTACH: From 89528c302336faf9c7518eafbd8161e4372f0bc9 Mon Sep 17 00:00:00 2001 From: Print3M <92022497+Print3M@users.noreply.github.com> Date: Sat, 23 Aug 2025 11:21:14 +0200 Subject: [PATCH 2/5] Debug to file param added --- .vscode/settings.json | 3 +- README.md | 1 - cli/cli.go | 29 +++++++++------- dll/dll.go | 6 ++-- main.go | 4 +-- output/output.go | 32 ++++++++++-------- templates/dllshimmer.h.template | 51 +++++++++++++++++++++-------- templates/dynamic-shim.cpp.template | 6 ++-- templates/static-shim.cpp.template | 6 ++-- 9 files changed, 86 insertions(+), 52 deletions(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index 8a00b2c..581c6d4 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -2,6 +2,7 @@ "files.associations": { "*.cpp.template": "cpp", "*.sh.template": "shellscript", - "functional": "cpp" + "functional": "cpp", + "*.template": "cpp" } } \ No newline at end of file diff --git a/README.md b/README.md index 6e8ac5f..cba476e 100644 --- a/README.md +++ b/README.md @@ -103,4 +103,3 @@ In case of static linking, we really only have one option: - Cache LoadLibraryA() and GetProcAddress() pointers not to call WinAPI every time (better performance and more stealthy). - Improve the shim template code (leave as little code in the macro as possible. Is the macro actually required now when we use args/params trick?) -- Maybe move boilerplate code into header file? diff --git a/cli/cli.go b/cli/cli.go index c6c8699..7991f11 100644 --- a/cli/cli.go +++ b/cli/cli.go @@ -8,11 +8,12 @@ import ( ) type CliFlags struct { - Input string - Output string - OriginalPath string - Mutex bool - Static bool + Input string + Output string + Original string + Mutex bool + Static bool + DebugFile string } func IsValidDllName(filename string) bool { @@ -41,8 +42,11 @@ func ParseCli() *CliFlags { flag.StringVar(&flags.Output, "o", "", "") flag.StringVar(&flags.Output, "output", "", "") - flag.StringVar(&flags.OriginalPath, "x", "", "") - flag.StringVar(&flags.OriginalPath, "original-path", "", "") + flag.StringVar(&flags.Original, "x", "", "") + flag.StringVar(&flags.Original, "original", "", "") + + flag.StringVar(&flags.DebugFile, "d", "", "") + flag.StringVar(&flags.DebugFile, "debug-file", "", "") flag.BoolVar(&flags.Mutex, "m", false, "") flag.BoolVar(&flags.Mutex, "mutex", false, "") @@ -54,10 +58,11 @@ func ParseCli() *CliFlags { fmt.Println() fmt.Println("Usage:") fmt.Println() - fmt.Printf(" %-26s %s\n", "-i, --input ", "Input DLL file (required)") - fmt.Printf(" %-26s %s\n", "-o, --output ", "Output directory (required)") - fmt.Printf(" %-26s %s\n", "-x, --original-path ", "Path to original DLL on target (required)") + fmt.Printf(" %-26s %s\n", "-i, --input ", "Input DLL file (required)") + fmt.Printf(" %-26s %s\n", "-o, --output ", "Output directory (required)") + fmt.Printf(" %-26s %s\n", "-x, --original ", "Path to original DLL on target (required)") fmt.Printf(" %-26s %s\n", "-m, --mutex", "Multiple execution prevention (default: false)") + fmt.Printf(" %-26s %s\n", " --debug-file ", "Save debug logs to file") fmt.Printf(" %-26s %s\n", " --static", "Static linking to original DLL via IAT (default: false)") fmt.Printf(" %-26s %s\n", "-h, --help", "Show this help") fmt.Println() @@ -71,12 +76,12 @@ func ParseCli() *CliFlags { flag.Parse() - if flags.Input == "" || flags.Output == "" || flags.OriginalPath == "" { + if flags.Input == "" || flags.Output == "" || flags.Original == "" { flag.Usage() os.Exit(1) } - if flags.Static && !IsValidDllName(flags.OriginalPath) { + if flags.Static && !IsValidDllName(flags.Original) { fmt.Fprintf(os.Stderr, "[!] Invalid '-x' parameter value:\n") fmt.Fprintf(os.Stderr, "In case of static linking enabled '-x' parameter must be valid Windows DLL file name with no path information. E.g. kernel32.dll, user32.dll.") os.Exit(1) diff --git a/dll/dll.go b/dll/dll.go index 3dfdaf6..b24ac1a 100644 --- a/dll/dll.go +++ b/dll/dll.go @@ -15,15 +15,15 @@ type ExportedFunction struct { type Dll struct { Name string - OriginalPath string + Original string ExportedFunctions []ExportedFunction } -func ParseDll(path string, originalPath string) *Dll { +func ParseDll(path string, original string) *Dll { var dll Dll dll.Name = filepath.Base(path) - dll.OriginalPath = originalPath + dll.Original = original pe, err := peparser.New(path, &peparser.Options{}) if err != nil { diff --git a/main.go b/main.go index bf4c078..8956b25 100644 --- a/main.go +++ b/main.go @@ -18,12 +18,12 @@ func main() { cli.PrintBanner() out := output.Output{ - Dll: dll.ParseDll(flags.Input, flags.OriginalPath), + Dll: dll.ParseDll(flags.Input, flags.Original), OutputDir: filepath.Clean(flags.Output), TemplatesFS: &templatesFS, } - out.CreateCodeFiles(flags.Mutex, flags.Static) + out.CreateCodeFiles(flags.Mutex, flags.DebugFile, flags.Static) out.CreateDefFile() out.CreateCompileScript(flags.Static) diff --git a/output/output.go b/output/output.go index 93e8324..35f81c7 100644 --- a/output/output.go +++ b/output/output.go @@ -44,10 +44,12 @@ func (o *Output) GetLibFileName() string { } type CodeFileParams struct { - Functions []dll.ExportedFunction - OriginalPath string - Mutex bool - DllName string + Functions []dll.ExportedFunction + Original string + Mutex bool + DllName string + DebugFile string + IsStaticLinked bool } func (o *Output) GetTemplate(filename string) *template.Template { @@ -60,21 +62,23 @@ func (o *Output) GetTemplate(filename string) *template.Template { return template.Must(template.New("new").Parse(string(content))) } -func (o *Output) CreateCodeFiles(mutex bool, isStaticLinked bool) { +func (o *Output) CreateCodeFiles(mutex bool, debugFile string, isStaticLinked bool) { params := CodeFileParams{ - Functions: o.Dll.ExportedFunctions, - OriginalPath: sanitizePathForInjection(o.Dll.OriginalPath), - Mutex: mutex, - DllName: o.Dll.Name, + Functions: o.Dll.ExportedFunctions, + Original: sanitizePathForInjection(o.Dll.Original), + Mutex: mutex, + DllName: o.Dll.Name, + DebugFile: sanitizePathForInjection(debugFile), + IsStaticLinked: isStaticLinked, } - o.createCppCodeFile(params, isStaticLinked) + o.createCppCodeFile(params) o.createHdrCodeFile(params) } -func (o *Output) createCppCodeFile(params CodeFileParams, isStaticLinked bool) { +func (o *Output) createCppCodeFile(params CodeFileParams) { templateFile := "dynamic-shim.cpp.template" - if isStaticLinked { + if params.IsStaticLinked { templateFile = "static-shim.cpp.template" } @@ -113,8 +117,8 @@ func (o *Output) CreateDefFile() { func (o *Output) CreateLibFile() { var def def.DefFile - // In case of static linking OriginalPath is DLL name itself - def.DllName = o.Dll.OriginalPath + // In case of static linking Original is DLL name itself + def.DllName = o.Dll.Original for _, function := range o.Dll.ExportedFunctions { if function.Forwarder == "" { diff --git a/templates/dllshimmer.h.template b/templates/dllshimmer.h.template index b468247..3fb7448 100644 --- a/templates/dllshimmer.h.template +++ b/templates/dllshimmer.h.template @@ -5,49 +5,72 @@ // | (auto generated) | // #------------------------------------------------------------------# -#include #include +#include #define T UINT64 #define PARAMS \ T a1, T a2, T a3, T a4, T a5, T a6, T a7, T a8, T a9, T a10, T a11, T a12 #define ARGS a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12 -typedef T (*FuncPtr)(PARAMS); +#define logf(...) fprintf(CTX.dbgOut, __VA_ARGS__) + +typedef struct { + FILE *dbgOut; +} Ctx; + +Ctx CTX; + +void InitCTX() { +{{- if gt (len .DebugFile) 0 }} + + CTX.dbgOut = fopen("{{.DebugFile}}", "w"); + if (!CTX.dbgOut) { + // TODO: Change to message box + perror("fopen"); + } + +{{- else }} + + CTX.dbgOut = stdout; + +{{- end }} +} +typedef T (*FuncPtr)(PARAMS); -void PrintCurrentDirectory() { +void LogCurrentDirectory() { char buf[MAX_PATH]; DWORD len = GetCurrentDirectoryA(MAX_PATH, buf); if (len == 0 || len >= MAX_PATH) { - printf("\tGetCurrentDirectoryA failed\n"); + logf("\tGetCurrentDirectoryA failed\n"); return; } - printf("\tCurrent directory: '%s'\n", buf); + logf("\tCurrent directory: '%s'\n", buf); } - FuncPtr getProxyFunc(const char *funcName) { - HMODULE hModule = LoadLibraryA("{{.OriginalPath}}"); + HMODULE hModule = LoadLibraryA("{{.Original}}"); if (hModule == NULL) { - printf("[!] {{.DllName}}: LoadLibraryA({{.OriginalPath}}) failed\n"); - printf("\tError code: %lu\n", GetLastError()); - PrintCurrentDirectory(); + logf("[!] {{.DllName}}: LoadLibraryA({{.Original}}) failed\n"); + logf("\tError code: %lu\n", GetLastError()); + LogCurrentDirectory(); } FuncPtr pFunc = (FuncPtr)GetProcAddress(hModule, funcName); if (pFunc == NULL) { - printf("[!] {{.DllName}}: GetProcAddress(%s, {{.OriginalPath}}) failed\n", + logf("[!] {{.DllName}}: GetProcAddress(%s, {{.Original}}) failed\n", funcName); - printf("\tError code: %lu\n", GetLastError()); + logf("\tError code: %lu\n", GetLastError()); } return pFunc; } - #define MUTEX(name) \ (CreateMutexA(NULL, TRUE, name) && GetLastError() != ERROR_ALREADY_EXISTS) -#define PROXY_FUNCTION(funcName) getProxyFunc(funcName)(ARGS); \ No newline at end of file +#define PROXY_FUNCTION(funcName) getProxyFunc(funcName)(ARGS); + +// TODO: Cache LoadLibraryA() and GetProcAddress() result diff --git a/templates/dynamic-shim.cpp.template b/templates/dynamic-shim.cpp.template index ff20245..0faa018 100644 --- a/templates/dynamic-shim.cpp.template +++ b/templates/dynamic-shim.cpp.template @@ -8,11 +8,12 @@ #include {{- range $i, $v := .Functions }} + {{- if eq (len $v.Forwarder) 0 }} extern "C" UINT64 {{$v.Name}}Fwd(PARAMS) { #ifdef DEBUG - printf("[+] {{$r.DllName}}: {{$v.Name}} called\n"); + logf("[+] {{$r.DllName}}: {{$v.Name}} called\n"); #endif {{ if $r.Mutex }} if (MUTEX("Global\\{{$v.Name}}__{{$i}}")) { @@ -26,6 +27,7 @@ extern "C" UINT64 {{$v.Name}}Fwd(PARAMS) { } {{- end }} + {{- end }} @@ -34,7 +36,7 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) { switch (fdwReason) { case DLL_PROCESS_ATTACH: { #ifdef DEBUG - printf("[+] {{.DllName}}: DLL_PROCESS_ATTACH event\n"); + logf("[+] {{.DllName}}: DLL_PROCESS_ATTACH event\n"); #endif } case DLL_THREAD_ATTACH: diff --git a/templates/static-shim.cpp.template b/templates/static-shim.cpp.template index fbc7f9e..25e5926 100644 --- a/templates/static-shim.cpp.template +++ b/templates/static-shim.cpp.template @@ -32,7 +32,7 @@ extern "C" __declspec(dllimport) UINT64 {{$v.Name}}(PARAMS); extern "C" UINT64 {{$v.Name}}Fwd(PARAMS) { #ifdef DEBUG - printf("[+] {{$r.DllName}}: {{$v.Name}} called\n"); + logf("[+] {{$r.DllName}}: {{$v.Name}} called\n"); #endif {{ if $r.Mutex }} if (MUTEX("Global\\{{$v.Name}}__{{$i}}")) { @@ -54,8 +54,8 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) { switch (fdwReason) { case DLL_PROCESS_ATTACH: { #ifdef DEBUG - printf("[+] {{.DllName}}: DLL_PROCESS_ATTACH event\n"); - PrintCurrentDirectory(); + logf("[+] {{.DllName}}: DLL_PROCESS_ATTACH event\n"); + LogCurrentDirectory(); #endif } case DLL_THREAD_ATTACH: From 1c64b0788c2d59d4afc3293e27357f51495a0967 Mon Sep 17 00:00:00 2001 From: Print3M <92022497+Print3M@users.noreply.github.com> Date: Sat, 23 Aug 2025 13:50:43 +0200 Subject: [PATCH 3/5] Update README, better debug handling, timestamp added --- .vscode/settings.json | 3 +- README.md | 15 ++++--- cli/cli.go | 2 +- templates/dllshimmer.h.template | 66 ++++++++++++++++++++++------- templates/dynamic-shim.cpp.template | 6 +-- templates/static-shim.cpp.template | 8 ++-- 6 files changed, 71 insertions(+), 29 deletions(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index 581c6d4..a5226a2 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -3,6 +3,7 @@ "*.cpp.template": "cpp", "*.sh.template": "shellscript", "functional": "cpp", - "*.template": "cpp" + "*.template": "cpp", + "cstdarg": "cpp" } } \ No newline at end of file diff --git a/README.md b/README.md index cba476e..e779848 100644 --- a/README.md +++ b/README.md @@ -38,15 +38,15 @@ Example: Parameters: -**`-i / --input `** [required] +**`-i / --input `** [required] The original DLL that you want to backdoor. -**`-o / --output `** [required] +**`-o / --output `** [required] The path to the directory where DllShimmer will save all generated files. -**`-x / --original-path `** [required] +**`-x / --original `** [required] In case of dynamic linking (default) provide the path where the proxy DLL will find the original DLL on the target system. @@ -67,7 +67,13 @@ This technique has some serious limitations compared to dynamic linking: However, static linking may be more stealthy and natural in some scenarios. -By default, DllShimmer always uses dynamic linking with the `LoadLibraryA()` and `GetProcAddress()` functions. +Default: DllShimmer always uses dynamic linking with the `LoadLibraryA()` and `GetProcAddress()` functions. + +**`--debug-file `** [optional] + +Save debug logs to a file. Logs are written to a file on an ongoing basis while the program is running. + +Default: DllShimmer always writes debug logs to STDOUT. ## Limitations @@ -102,4 +108,3 @@ In case of static linking, we really only have one option: ## TODO - Cache LoadLibraryA() and GetProcAddress() pointers not to call WinAPI every time (better performance and more stealthy). -- Improve the shim template code (leave as little code in the macro as possible. Is the macro actually required now when we use args/params trick?) diff --git a/cli/cli.go b/cli/cli.go index 7991f11..2afc133 100644 --- a/cli/cli.go +++ b/cli/cli.go @@ -62,7 +62,7 @@ func ParseCli() *CliFlags { fmt.Printf(" %-26s %s\n", "-o, --output ", "Output directory (required)") fmt.Printf(" %-26s %s\n", "-x, --original ", "Path to original DLL on target (required)") fmt.Printf(" %-26s %s\n", "-m, --mutex", "Multiple execution prevention (default: false)") - fmt.Printf(" %-26s %s\n", " --debug-file ", "Save debug logs to file") + fmt.Printf(" %-26s %s\n", " --debug-file ", "Save debug logs to a file (default: stdout)") fmt.Printf(" %-26s %s\n", " --static", "Static linking to original DLL via IAT (default: false)") fmt.Printf(" %-26s %s\n", "-h, --help", "Show this help") fmt.Println() diff --git a/templates/dllshimmer.h.template b/templates/dllshimmer.h.template index 3fb7448..2a393b7 100644 --- a/templates/dllshimmer.h.template +++ b/templates/dllshimmer.h.template @@ -7,27 +7,34 @@ #include #include +#include #define T UINT64 #define PARAMS \ T a1, T a2, T a3, T a4, T a5, T a6, T a7, T a8, T a9, T a10, T a11, T a12 #define ARGS a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12 -#define logf(...) fprintf(CTX.dbgOut, __VA_ARGS__) +typedef T (*FuncPtr)(PARAMS); typedef struct { FILE *dbgOut; } Ctx; -Ctx CTX; +Ctx CTX = {.dbgOut = NULL }; + +void initDbg() { + if (CTX.dbgOut != NULL) return; -void InitCTX() { {{- if gt (len .DebugFile) 0 }} CTX.dbgOut = fopen("{{.DebugFile}}", "w"); if (!CTX.dbgOut) { - // TODO: Change to message box - perror("fopen"); + MessageBoxA( + NULL, + "fopen({{.DebugFile}}) failed", + "DllShimmer", + MB_OK | MB_ICONINFORMATION + ); } {{- else }} @@ -37,32 +44,61 @@ void InitCTX() { {{- end }} } -typedef T (*FuncPtr)(PARAMS); +char TIME_BUF[9]; // "HH:MM:SS" + null + +char *getCurrentTime() { + time_t t = time(NULL); + struct tm lt; + localtime_s(<, &t); + + strftime(TIME_BUF, sizeof(TIME_BUF), "%H:%M:%S", <); + + return TIME_BUF; +} + +void dbgf(const char *fmt, ...) { + if (CTX.dbgOut == NULL) { + initDbg(); + } + + va_list ap; + va_start(ap, fmt); + + fprintf(CTX.dbgOut, "[DBG] {{.DllName}} | %s | ", getCurrentTime()); + vfprintf(CTX.dbgOut, fmt, ap); + fprintf(CTX.dbgOut, "\n"); + fflush(CTX.dbgOut); + + va_end(ap); +} + +void InitCache() { + +} -void LogCurrentDirectory() { +void dbgCurrentDirectory() { char buf[MAX_PATH]; DWORD len = GetCurrentDirectoryA(MAX_PATH, buf); if (len == 0 || len >= MAX_PATH) { - logf("\tGetCurrentDirectoryA failed\n"); + dbgf("GetCurrentDirectoryA failed"); return; } - logf("\tCurrent directory: '%s'\n", buf); + dbgf("\tCurrent directory: '%s'", buf); } FuncPtr getProxyFunc(const char *funcName) { HMODULE hModule = LoadLibraryA("{{.Original}}"); if (hModule == NULL) { - logf("[!] {{.DllName}}: LoadLibraryA({{.Original}}) failed\n"); - logf("\tError code: %lu\n", GetLastError()); - LogCurrentDirectory(); + dbgf("LoadLibraryA({{.Original}}) failed"); + dbgf("\tError code: %lu", GetLastError()); + dbgCurrentDirectory(); } FuncPtr pFunc = (FuncPtr)GetProcAddress(hModule, funcName); if (pFunc == NULL) { - logf("[!] {{.DllName}}: GetProcAddress(%s, {{.Original}}) failed\n", - funcName); - logf("\tError code: %lu\n", GetLastError()); + dbgf("GetProcAddress(%s, {{.Original}}) failed", funcName); + dbgf("\tError code: %lu", GetLastError()); } return pFunc; diff --git a/templates/dynamic-shim.cpp.template b/templates/dynamic-shim.cpp.template index 0faa018..8cb9ece 100644 --- a/templates/dynamic-shim.cpp.template +++ b/templates/dynamic-shim.cpp.template @@ -13,7 +13,7 @@ extern "C" UINT64 {{$v.Name}}Fwd(PARAMS) { #ifdef DEBUG - logf("[+] {{$r.DllName}}: {{$v.Name}} called\n"); + dbgf("{{$v.Name}} called"); #endif {{ if $r.Mutex }} if (MUTEX("Global\\{{$v.Name}}__{{$i}}")) { @@ -32,11 +32,11 @@ extern "C" UINT64 {{$v.Name}}Fwd(PARAMS) { BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) { - + switch (fdwReason) { case DLL_PROCESS_ATTACH: { #ifdef DEBUG - logf("[+] {{.DllName}}: DLL_PROCESS_ATTACH event\n"); + dbgf("DLL_PROCESS_ATTACH"); #endif } case DLL_THREAD_ATTACH: diff --git a/templates/static-shim.cpp.template b/templates/static-shim.cpp.template index 25e5926..d84a3e4 100644 --- a/templates/static-shim.cpp.template +++ b/templates/static-shim.cpp.template @@ -10,11 +10,11 @@ // | "DON'T TOUCH" ZONE | // | (auto generated) | // #------------------------------------------------------------------# -#include "dllshimmer.h" {{- range .Functions}} #define {{.Name}} {{.Name}}Original {{- end}} +#include "dllshimmer.h" #include {{- range .Functions}} #undef {{.Name}} @@ -32,7 +32,7 @@ extern "C" __declspec(dllimport) UINT64 {{$v.Name}}(PARAMS); extern "C" UINT64 {{$v.Name}}Fwd(PARAMS) { #ifdef DEBUG - logf("[+] {{$r.DllName}}: {{$v.Name}} called\n"); + dbgf("{{$v.Name}} called"); #endif {{ if $r.Mutex }} if (MUTEX("Global\\{{$v.Name}}__{{$i}}")) { @@ -54,8 +54,8 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) { switch (fdwReason) { case DLL_PROCESS_ATTACH: { #ifdef DEBUG - logf("[+] {{.DllName}}: DLL_PROCESS_ATTACH event\n"); - LogCurrentDirectory(); + dbgf("DLL_PROCESS_ATTACH event"); + dbgCurrentDirectory(); #endif } case DLL_THREAD_ATTACH: From 0d6b7c2a1070e8e0cc622c2df2e4375d379f1c51 Mon Sep 17 00:00:00 2001 From: Print3M <92022497+Print3M@users.noreply.github.com> Date: Sat, 23 Aug 2025 14:56:45 +0200 Subject: [PATCH 4/5] README improvements, new release --- .github/workflows/release.yml | 14 +++---- README.md | 12 +++++- templates/dllshimmer.h.template | 67 ++++++++++++++++++++------------- 3 files changed, 58 insertions(+), 35 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 18dc39f..82747a3 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -47,7 +47,7 @@ jobs: env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | - gh release delete 1.0.5 --cleanup-tag --yes || echo "No release or tag found for 1.0.5" + gh release delete 1.1.0 --cleanup-tag --yes || echo "No release or tag found for 1.1.0" - name: Create Release id: create_release @@ -55,13 +55,13 @@ jobs: env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: - tag_name: 1.0.5 - release_name: DllShimmer 1.0.5 + tag_name: 1.1.0 + release_name: DllShimmer 1.1.0 body: | - DllShimmer Weaponize DLL hijacking easily. Backdoor any function in any DLL. - - - [x] GitHub Actions workflow improvements - - [x] Windows build improvements + - [x] Dynamic linking is now cached (both LoadLibraryA and GetProcAddress). Performance improved. + - [x] Better debug log format: timestamp added. + - [x] New parameter: `--debug-file`. Save debug logs to file. + - [x] README updated. draft: false prerelease: false diff --git a/README.md b/README.md index e779848..181dbc5 100644 --- a/README.md +++ b/README.md @@ -71,10 +71,14 @@ Default: DllShimmer always uses dynamic linking with the `LoadLibraryA()` and `G **`--debug-file `** [optional] -Save debug logs to a file. Logs are written to a file on an ongoing basis while the program is running. +Save debug logs to a file. Logs are written to a file on an ongoing basis while the program is running. If selected, logs are not printed to STDOUT. Default: DllShimmer always writes debug logs to STDOUT. +Example debug output: + +![Example debug output](_img/img-2.png) + ## Limitations - Only x86-64 / AMD64 architecture is supported. @@ -84,6 +88,12 @@ Default: DllShimmer always writes debug logs to STDOUT. ## Troubleshooting +Before you start troubleshooting: + +1. Read "Limitations". +2. Make sure you don't use static linking (`--static`). It's easier to debug with dynamic linking (default). +3. Save debug output to file (`--debug-file`). + ### _In the generated `.cpp` file, I don't see all the exported functions from the original DLL._ Functions defined in the original DLL as “forwarded” are not included in the `.cpp` file. However, they are visible in the `.def` file. They will also be exported after compilation, exactly as in the original DLL. diff --git a/templates/dllshimmer.h.template b/templates/dllshimmer.h.template index 2a393b7..aa859e0 100644 --- a/templates/dllshimmer.h.template +++ b/templates/dllshimmer.h.template @@ -8,27 +8,31 @@ #include #include #include +#include +#include + #define T UINT64 -#define PARAMS \ - T a1, T a2, T a3, T a4, T a5, T a6, T a7, T a8, T a9, T a10, T a11, T a12 +#define PARAMS T a1, T a2, T a3, T a4, T a5, T a6, T a7, T a8, T a9, T a10, T a11, T a12 #define ARGS a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12 typedef T (*FuncPtr)(PARAMS); typedef struct { FILE *dbgOut; + HMODULE module; + std::unordered_map functions; } Ctx; -Ctx CTX = {.dbgOut = NULL }; +Ctx gCtx = { .dbgOut = NULL, .module = NULL }; void initDbg() { - if (CTX.dbgOut != NULL) return; + if (gCtx.dbgOut != NULL) return; {{- if gt (len .DebugFile) 0 }} - CTX.dbgOut = fopen("{{.DebugFile}}", "w"); - if (!CTX.dbgOut) { + gCtx.dbgOut = fopen("{{.DebugFile}}", "w"); + if (!gCtx.dbgOut) { MessageBoxA( NULL, "fopen({{.DebugFile}}) failed", @@ -39,43 +43,39 @@ void initDbg() { {{- else }} - CTX.dbgOut = stdout; + gCtx.dbgOut = stdout; {{- end }} } -char TIME_BUF[9]; // "HH:MM:SS" + null +char gTimeBuf[9]; // "HH:MM:SS" + null char *getCurrentTime() { time_t t = time(NULL); struct tm lt; localtime_s(<, &t); - strftime(TIME_BUF, sizeof(TIME_BUF), "%H:%M:%S", <); + strftime(gTimeBuf, sizeof(gTimeBuf), "%H:%M:%S", <); - return TIME_BUF; + return gTimeBuf; } void dbgf(const char *fmt, ...) { - if (CTX.dbgOut == NULL) { + if (gCtx.dbgOut == NULL) { initDbg(); } va_list ap; va_start(ap, fmt); - fprintf(CTX.dbgOut, "[DBG] {{.DllName}} | %s | ", getCurrentTime()); - vfprintf(CTX.dbgOut, fmt, ap); - fprintf(CTX.dbgOut, "\n"); - fflush(CTX.dbgOut); + fprintf(gCtx.dbgOut, "[DBG] {{.DllName}} | %s | ", getCurrentTime()); + vfprintf(gCtx.dbgOut, fmt, ap); + fprintf(gCtx.dbgOut, "\n"); + fflush(gCtx.dbgOut); va_end(ap); } -void InitCache() { - -} - void dbgCurrentDirectory() { char buf[MAX_PATH]; DWORD len = GetCurrentDirectoryA(MAX_PATH, buf); @@ -87,20 +87,35 @@ void dbgCurrentDirectory() { dbgf("\tCurrent directory: '%s'", buf); } + FuncPtr getProxyFunc(const char *funcName) { - HMODULE hModule = LoadLibraryA("{{.Original}}"); - if (hModule == NULL) { - dbgf("LoadLibraryA({{.Original}}) failed"); - dbgf("\tError code: %lu", GetLastError()); - dbgCurrentDirectory(); + // Module pointer is cached + if (gCtx.module == NULL) { + gCtx.module = LoadLibraryA("{{.Original}}"); + if (gCtx.module == NULL) { + dbgf("LoadLibraryA({{.Original}}) failed"); + dbgf("\tError code: %lu", GetLastError()); + dbgCurrentDirectory(); + + return NULL; + } + } + + std::string strFuncName(funcName); + + // Function pointer is cached + if (gCtx.functions.find(strFuncName) != gCtx.functions.end()) { + return gCtx.functions[strFuncName]; } - FuncPtr pFunc = (FuncPtr)GetProcAddress(hModule, funcName); + FuncPtr pFunc = (FuncPtr)GetProcAddress(gCtx.module, funcName); if (pFunc == NULL) { dbgf("GetProcAddress(%s, {{.Original}}) failed", funcName); dbgf("\tError code: %lu", GetLastError()); } + gCtx.functions[strFuncName] = pFunc; + return pFunc; } @@ -108,5 +123,3 @@ FuncPtr getProxyFunc(const char *funcName) { (CreateMutexA(NULL, TRUE, name) && GetLastError() != ERROR_ALREADY_EXISTS) #define PROXY_FUNCTION(funcName) getProxyFunc(funcName)(ARGS); - -// TODO: Cache LoadLibraryA() and GetProcAddress() result From baa6708d0fe3af409abcf4271c21d9cb36093db6 Mon Sep 17 00:00:00 2001 From: Print3M <92022497+Print3M@users.noreply.github.com> Date: Sat, 23 Aug 2025 15:01:03 +0200 Subject: [PATCH 5/5] indentation fix --- _img/img-2.png | Bin 0 -> 16675 bytes templates/dllshimmer.h.template | 114 ++++++++++++++++---------------- 2 files changed, 56 insertions(+), 58 deletions(-) create mode 100644 _img/img-2.png diff --git a/_img/img-2.png b/_img/img-2.png new file mode 100644 index 0000000000000000000000000000000000000000..73b58dc02fd40c993489010f95e0b4399b4897aa GIT binary patch literal 16675 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 literal 0 HcmV?d00001 diff --git a/templates/dllshimmer.h.template b/templates/dllshimmer.h.template index aa859e0..51ba456 100644 --- a/templates/dllshimmer.h.template +++ b/templates/dllshimmer.h.template @@ -19,31 +19,31 @@ typedef T (*FuncPtr)(PARAMS); typedef struct { - FILE *dbgOut; - HMODULE module; - std::unordered_map functions; + FILE *dbgOut; + HMODULE module; + std::unordered_map functions; } Ctx; Ctx gCtx = { .dbgOut = NULL, .module = NULL }; void initDbg() { - if (gCtx.dbgOut != NULL) return; + if (gCtx.dbgOut != NULL) return; {{- if gt (len .DebugFile) 0 }} gCtx.dbgOut = fopen("{{.DebugFile}}", "w"); - if (!gCtx.dbgOut) { - MessageBoxA( - NULL, - "fopen({{.DebugFile}}) failed", - "DllShimmer", - MB_OK | MB_ICONINFORMATION - ); - } + if (!gCtx.dbgOut) { + MessageBoxA( + NULL, + "fopen({{.DebugFile}}) failed", + "DllShimmer", + MB_OK | MB_ICONINFORMATION + ); + } {{- else }} - gCtx.dbgOut = stdout; + gCtx.dbgOut = stdout; {{- end }} } @@ -51,18 +51,18 @@ void initDbg() { char gTimeBuf[9]; // "HH:MM:SS" + null char *getCurrentTime() { - time_t t = time(NULL); - struct tm lt; - localtime_s(<, &t); - - strftime(gTimeBuf, sizeof(gTimeBuf), "%H:%M:%S", <); - - return gTimeBuf; + time_t t = time(NULL); + struct tm lt; + localtime_s(<, &t); + + strftime(gTimeBuf, sizeof(gTimeBuf), "%H:%M:%S", <); + + return gTimeBuf; } void dbgf(const char *fmt, ...) { if (gCtx.dbgOut == NULL) { - initDbg(); + initDbg(); } va_list ap; @@ -77,49 +77,47 @@ void dbgf(const char *fmt, ...) { } void dbgCurrentDirectory() { - char buf[MAX_PATH]; - DWORD len = GetCurrentDirectoryA(MAX_PATH, buf); - if (len == 0 || len >= MAX_PATH) { - dbgf("GetCurrentDirectoryA failed"); - return; - } - - dbgf("\tCurrent directory: '%s'", buf); + char buf[MAX_PATH]; + DWORD len = GetCurrentDirectoryA(MAX_PATH, buf); + if (len == 0 || len >= MAX_PATH) { + dbgf("GetCurrentDirectoryA failed"); + return; + } + + dbgf("\tCurrent directory: '%s'", buf); } - FuncPtr getProxyFunc(const char *funcName) { - // Module pointer is cached - if (gCtx.module == NULL) { - gCtx.module = LoadLibraryA("{{.Original}}"); + // Module pointer is cached if (gCtx.module == NULL) { - dbgf("LoadLibraryA({{.Original}}) failed"); - dbgf("\tError code: %lu", GetLastError()); - dbgCurrentDirectory(); - - return NULL; + gCtx.module = LoadLibraryA("{{.Original}}"); + if (gCtx.module == NULL) { + dbgf("LoadLibraryA({{.Original}}) failed"); + dbgf("\tError code: %lu", GetLastError()); + dbgCurrentDirectory(); + + return NULL; + } } - } - - std::string strFuncName(funcName); - - // Function pointer is cached - if (gCtx.functions.find(strFuncName) != gCtx.functions.end()) { - return gCtx.functions[strFuncName]; - } - FuncPtr pFunc = (FuncPtr)GetProcAddress(gCtx.module, funcName); - if (pFunc == NULL) { - dbgf("GetProcAddress(%s, {{.Original}}) failed", funcName); - dbgf("\tError code: %lu", GetLastError()); - } - - gCtx.functions[strFuncName] = pFunc; - - return pFunc; -} + std::string strFuncName(funcName); + + // Function pointer is cached + if (gCtx.functions.find(strFuncName) != gCtx.functions.end()) { + return gCtx.functions[strFuncName]; + } + + FuncPtr pFunc = (FuncPtr)GetProcAddress(gCtx.module, funcName); + if (pFunc == NULL) { + dbgf("GetProcAddress(%s, {{.Original}}) failed", funcName); + dbgf("\tError code: %lu", GetLastError()); + } + + gCtx.functions[strFuncName] = pFunc; + + return pFunc; +} -#define MUTEX(name) \ - (CreateMutexA(NULL, TRUE, name) && GetLastError() != ERROR_ALREADY_EXISTS) +#define MUTEX(name) (CreateMutexA(NULL, TRUE, name) && GetLastError() != ERROR_ALREADY_EXISTS) #define PROXY_FUNCTION(funcName) getProxyFunc(funcName)(ARGS);