mirror of
https://github.com/Print3M/DllShimmer
synced 2026-06-06 16:34:32 +00:00
@@ -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
|
||||
|
||||
|
||||
@@ -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
@@ -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()
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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");
|
||||
|
||||
Reference in New Issue
Block a user