Merge pull request #6 from Print3M/dev

Version flag & debug bug fixed
This commit is contained in:
Print3M
2025-08-26 12:38:54 +02:00
committed by GitHub
6 changed files with 54 additions and 37 deletions
+4 -7
View File
@@ -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
+1 -1
View File
@@ -117,4 +117,4 @@ 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).
- Support C++ mangled function names
+22 -11
View File
@@ -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 <path> -o <path> -p <path>\n")
fmt.Println()
@@ -62,8 +67,9 @@ func ParseCli() *CliFlags {
fmt.Printf(" %-26s %s\n", "-o, --output <path>", "Output directory (required)")
fmt.Printf(" %-26s %s\n", "-x, --original <path>", "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 <path>", "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 <path>", "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()
+25 -18
View File
@@ -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();
}
#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);
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;
+1
View File
@@ -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");
+1
View File
@@ -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");