From 5428e31ed8bba2625f214936f0b4ddf7cc466ecc Mon Sep 17 00:00:00 2001 From: Print3M <92022497+Print3M@users.noreply.github.com> Date: Sat, 23 Aug 2025 15:25:43 +0200 Subject: [PATCH 1/3] README update --- README.md | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/README.md b/README.md index 181dbc5..326d94c 100644 --- a/README.md +++ b/README.md @@ -113,8 +113,4 @@ In the case of dynamic linking, we have two options: In case of static linking, we really only have one option: -1. Move the original DLL to the `Current Directory`. - -## TODO - -- Cache LoadLibraryA() and GetProcAddress() pointers not to call WinAPI every time (better performance and more stealthy). +1. Move the original DLL to the `Current Directory`. \ No newline at end of file From 1dce132583a41267c033d4d19755559fc340ba4d Mon Sep 17 00:00:00 2001 From: Print3M <92022497+Print3M@users.noreply.github.com> Date: Sun, 24 Aug 2025 18:07:57 +0200 Subject: [PATCH 2/3] Version flag implemented --- cli/cli.go | 33 ++++++++++++++++++++++----------- 1 file changed, 22 insertions(+), 11 deletions(-) diff --git a/cli/cli.go b/cli/cli.go index 2afc133..e5817ca 100644 --- a/cli/cli.go +++ b/cli/cli.go @@ -7,13 +7,16 @@ import ( "strings" ) +const VERSION = "1.1.1" + type CliFlags struct { - Input string - Output string - Original string - Mutex bool - Static bool - DebugFile string + Input string + Output string + Original string + Mutex bool + Static bool + DebugFile string + ShowVersion bool } func IsValidDllName(filename string) bool { @@ -45,7 +48,6 @@ func ParseCli() *CliFlags { 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, "") @@ -53,6 +55,9 @@ func ParseCli() *CliFlags { flag.BoolVar(&flags.Static, "static", false, "") + flag.BoolVar(&flags.ShowVersion, "v", false, "") + flag.BoolVar(&flags.ShowVersion, "version", false, "") + flag.Usage = func() { fmt.Fprintf(os.Stderr, "Usage: DllShimmer -i -o -p \n") fmt.Println() @@ -62,8 +67,9 @@ 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 a file (default: stdout)") fmt.Printf(" %-26s %s\n", " --static", "Static linking to original DLL via IAT (default: false)") + fmt.Printf(" %-26s %s\n", " --debug-file ", "Save debug logs to a file (default: stdout)") + fmt.Printf(" %-26s %s\n", "-v, --version", "Show version of DllShimmer") fmt.Printf(" %-26s %s\n", "-h, --help", "Show this help") fmt.Println() fmt.Println("Example:") @@ -76,6 +82,11 @@ func ParseCli() *CliFlags { flag.Parse() + if flags.ShowVersion { + fmt.Printf("DllShimmer %s\n", VERSION) + os.Exit(0) + } + if flags.Input == "" || flags.Output == "" || flags.Original == "" { flag.Usage() os.Exit(1) @@ -91,7 +102,7 @@ func ParseCli() *CliFlags { } func PrintBanner() { - banner := ` + banner := fmt.Sprintf(` ▓█████▄ ██▓ ██▓ ▒██▀ ██▌▓██▒ ▓██▒ By @Print3M ░██ █▌▒██░ ▒██░ (print3m.github.io) @@ -99,7 +110,7 @@ func PrintBanner() { ░▒████▓ ░██████▒░██████▒ Documentation: ▒▒▓ ▒ ░ ▒░▓ ░░ ▒░▓ ░ github.com/Print3M/DllShimmer ░ ▒ ▒ ░ ░ ▒ ░░ ░ ▒ ░ - ░ ░ ░ ░ ░ ░ ░ 2025 + ░ ░ ░ ░ ░ ░ ░ %s ░ ░ ░ ░ ░ ░ ██████ ██░ ██ ██▓ ███▄ ▄███▓ ███▄ ▄███▓▓█████ ██▀███ @@ -111,7 +122,7 @@ func PrintBanner() { ░ ░▒ ░ ░ ▒ ░▒░ ░ ▒ ░░ ░ ░░ ░ ░ ░ ░ ░ ░▒ ░ ▒░ ░ ░ ░ ░ ░░ ░ ▒ ░░ ░ ░ ░ ░ ░░ ░ ░ ░ ░ ░ ░ ░ ░ ░ ░ ░ -` +`, VERSION) fmt.Print(banner) fmt.Println() From 2e6de47e5cf2868cc0122e7a86f05772d8ce36b6 Mon Sep 17 00:00:00 2001 From: Print3M <92022497+Print3M@users.noreply.github.com> Date: Tue, 26 Aug 2025 11:11:50 +0200 Subject: [PATCH 3/3] Debug cannot be disabled bug fixed --- .github/workflows/release.yml | 11 +++---- README.md | 6 +++- templates/dllshimmer.h.template | 45 +++++++++++++++++------------ templates/dynamic-shim.cpp.template | 1 + templates/static-shim.cpp.template | 1 + 5 files changed, 37 insertions(+), 27 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 82747a3..cf84aad 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.1.0 --cleanup-tag --yes || echo "No release or tag found for 1.1.0" + gh release delete 1.1.1 --cleanup-tag --yes || echo "No release or tag found for 1.1.1" - name: Create Release id: create_release @@ -55,13 +55,10 @@ jobs: env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: - tag_name: 1.1.0 - release_name: DllShimmer 1.1.0 + tag_name: 1.1.1 + release_name: DllShimmer 1.1.1 body: | - - [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. + - [x] "Debug cannot be disabled" bug fixed. draft: false prerelease: false diff --git a/README.md b/README.md index 326d94c..cdf688e 100644 --- a/README.md +++ b/README.md @@ -113,4 +113,8 @@ In the case of dynamic linking, we have two options: In case of static linking, we really only have one option: -1. Move the original DLL to the `Current Directory`. \ No newline at end of file +1. Move the original DLL to the `Current Directory`. + +## TODO + +- Support C++ mangled function names diff --git a/templates/dllshimmer.h.template b/templates/dllshimmer.h.template index 51ba456..ef4fe47 100644 --- a/templates/dllshimmer.h.template +++ b/templates/dllshimmer.h.template @@ -48,7 +48,7 @@ void initDbg() { {{- end }} } -char gTimeBuf[9]; // "HH:MM:SS" + null +char gTimeBuf[9]; // "HH:MM:SS" + \0 char *getCurrentTime() { time_t t = time(NULL); @@ -61,19 +61,21 @@ char *getCurrentTime() { } void dbgf(const char *fmt, ...) { - if (gCtx.dbgOut == NULL) { - initDbg(); - } - - va_list ap; - va_start(ap, fmt); - - fprintf(gCtx.dbgOut, "[DBG] {{.DllName}} | %s | ", getCurrentTime()); - vfprintf(gCtx.dbgOut, fmt, ap); - fprintf(gCtx.dbgOut, "\n"); - fflush(gCtx.dbgOut); - - va_end(ap); + #ifdef DEBUG + if (gCtx.dbgOut == NULL) { + initDbg(); + } + + va_list ap; + va_start(ap, fmt); + + fprintf(gCtx.dbgOut, "[DBG] {{.DllName}} | %s | ", getCurrentTime()); + vfprintf(gCtx.dbgOut, fmt, ap); + fprintf(gCtx.dbgOut, "\n"); + fflush(gCtx.dbgOut); + + va_end(ap); + #endif } void dbgCurrentDirectory() { @@ -81,6 +83,7 @@ void dbgCurrentDirectory() { DWORD len = GetCurrentDirectoryA(MAX_PATH, buf); if (len == 0 || len >= MAX_PATH) { dbgf("GetCurrentDirectoryA failed"); + return; } @@ -92,9 +95,11 @@ FuncPtr getProxyFunc(const char *funcName) { if (gCtx.module == NULL) { gCtx.module = LoadLibraryA("{{.Original}}"); if (gCtx.module == NULL) { - dbgf("LoadLibraryA({{.Original}}) failed"); - dbgf("\tError code: %lu", GetLastError()); - dbgCurrentDirectory(); + #ifdef DEBUG + dbgf("LoadLibraryA({{.Original}}) failed"); + dbgf("\tError code: %lu", GetLastError()); + dbgCurrentDirectory(); + #endif return NULL; } @@ -109,8 +114,10 @@ FuncPtr getProxyFunc(const char *funcName) { FuncPtr pFunc = (FuncPtr)GetProcAddress(gCtx.module, funcName); if (pFunc == NULL) { - dbgf("GetProcAddress(%s, {{.Original}}) failed", funcName); - dbgf("\tError code: %lu", GetLastError()); + #ifdef DEBUG + dbgf("GetProcAddress(%s, {{.Original}}) failed", funcName); + dbgf("\tError code: %lu", GetLastError()); + #endif } gCtx.functions[strFuncName] = pFunc; diff --git a/templates/dynamic-shim.cpp.template b/templates/dynamic-shim.cpp.template index 8cb9ece..2b1b1ae 100644 --- a/templates/dynamic-shim.cpp.template +++ b/templates/dynamic-shim.cpp.template @@ -11,6 +11,7 @@ {{- if eq (len $v.Forwarder) 0 }} +// {{$v.Name}} extern "C" UINT64 {{$v.Name}}Fwd(PARAMS) { #ifdef DEBUG dbgf("{{$v.Name}} called"); diff --git a/templates/static-shim.cpp.template b/templates/static-shim.cpp.template index d84a3e4..58f4746 100644 --- a/templates/static-shim.cpp.template +++ b/templates/static-shim.cpp.template @@ -30,6 +30,7 @@ extern "C" __declspec(dllimport) UINT64 {{$v.Name}}(PARAMS); +// {{$v.Name}} extern "C" UINT64 {{$v.Name}}Fwd(PARAMS) { #ifdef DEBUG dbgf("{{$v.Name}} called");