diff --git a/.vscode/settings.json b/.vscode/settings.json index a5226a2..83e3be0 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -4,6 +4,7 @@ "*.sh.template": "shellscript", "functional": "cpp", "*.template": "cpp", - "cstdarg": "cpp" + "cstdarg": "cpp", + "iostream": "cpp" } } \ No newline at end of file diff --git a/README.md b/README.md index 5aa3730..b758907 100644 --- a/README.md +++ b/README.md @@ -63,6 +63,7 @@ Enable static linking between the proxy DLL (IAT) and the original DLL (EAT). Th This technique has some serious limitations compared to dynamic linking: - You cannot define a full or relative path to the original DLL. The system loader only uses the DLL name form proxy IAT and searches in the default paths. +- You cannot use DLLs with name mangling and special characters such as: `?`, `$`, `@`, `#`. - Limited debugging information. If the original DLL fails to load, the program will usually crash without additional information. However, static linking may be more stealthy and natural in some scenarios. @@ -84,7 +85,7 @@ Example debug output: - Only x86-64 / AMD64 architecture is supported. - Most likely, the generic proxy code will not work for functions with floating-point parameters, as they use different registers than integer ones utilized by DllShimmer. If you know the function signature, you can manually adjust it in the generated file. - Functions with more than 12 arguments will not work because this number has been hardcoded into DllShimmer templates. -- There are some huge obfuscated DLLs with weird name mangling, calling conventions and tricks (e.g. compiled Qt framework DLL). I don't recommend to use them as a proxy DLL. DllShimmer most probably will generate some garbage in this case. +- There are some huge obfuscated DLLs with weird name mangling, calling conventions and tricks (e.g. compiled Qt framework DLL). I don't recommend to use them as a proxy DLL. It might work with dynamic linking but it doesn't work with static linking for sure. ## Troubleshooting @@ -117,4 +118,4 @@ In case of static linking, we really only have one option: ## TODO -- Support C++ mangled function names. Handle special chars: ?, $, @, # +- I still can't get mangled functions to work for static linking. The problem is that afaik MinGW does not allow static import of functions with special characters. No method has worked so far. The end result should be a compiled DLL with mangled functions in IAT. I am unable to achieve this. diff --git a/def/def.go b/def/def.go index 32e8297..39574e5 100644 --- a/def/def.go +++ b/def/def.go @@ -8,34 +8,44 @@ import ( type DefFile struct { DllName string ExportedFunctions []dll.ExportedFunction + // ImportedFunctions []dll.ImportedFunction } func (d *DefFile) GetContent() string { - /* - Example: - - LIBRARY "example.dll" - EXPORTS - */ var content string content += "LIBRARY \"" + d.DllName + "\"\n" - content += "EXPORTS\n" - for _, function := range d.ExportedFunctions { - if function.Forwarder != "" { - // Forwarded functions - content += "\t'" + function.OriginalName + "'='" + function.Forwarder + "'" - } else { - // Exported functions - content += "\t'" + function.OriginalName + "'='" + function.ProxyName + "'" + if len(d.ExportedFunctions) > 0 { + content += "EXPORTS\n" + + for _, function := range d.ExportedFunctions { + if function.Forwarder != "" { + // Forwarded functions + content += "\t'" + function.OriginalName + "'='" + function.Forwarder + "'" + } else { + // Exported functions + content += "\t'" + function.OriginalName + "'='" + function.ProxyName + "'" + } + + // Add ordinals + content += " " + "@" + fmt.Sprintf("%d", function.Ordinal) + + content += "\n" } - - // Add ordinals - content += " " + "@" + fmt.Sprintf("%d", function.Ordinal) - - content += "\n" } + // TODO: REMOVE + /* + if len(d.ImportedFunctions) > 0 { + content += "IMPORTS\n" + + for _, function := range d.ImportedFunctions { + content += "\t'" + function.ProxyName + "'='" + function.DllName + "." + function.OriginalName + "'" + content += "\n" + } + } + */ + return content } diff --git a/main.go b/main.go index 8956b25..a33b825 100644 --- a/main.go +++ b/main.go @@ -24,7 +24,7 @@ func main() { } out.CreateCodeFiles(flags.Mutex, flags.DebugFile, flags.Static) - out.CreateDefFile() + out.CreateDefFile(flags.Static) out.CreateCompileScript(flags.Static) if flags.Static { diff --git a/output/output.go b/output/output.go index 13bb8d2..54bdf12 100644 --- a/output/output.go +++ b/output/output.go @@ -91,7 +91,7 @@ func (o *Output) createHdrCodeFile(params CodeFileParams) { createFileFromTemplate(o, "dllshimmer.h.template", outputPath, params) } -func (o *Output) CreateDefFile() { +func (o *Output) CreateDefFile(isStaticLinked bool) { def := def.DefFile{ DllName: o.Dll.Name, ExportedFunctions: o.Dll.ExportedFunctions, @@ -109,9 +109,17 @@ func (o *Output) CreateDefFile() { } func (o *Output) CreateLibFile() { + var exports []dll.ExportedFunction + for _, function := range o.Dll.ExportedFunctions { + exports = append(exports, dll.ExportedFunction{ + OriginalName: function.OriginalName, + ProxyName: function.OriginalName, + }) + } + def := def.DefFile{ DllName: o.Dll.Original, // In case of static linking Original is DLL name itself - ExportedFunctions: o.Dll.ExportedFunctions, + ExportedFunctions: exports, } temp, err := os.CreateTemp("", "dllshimmer-*.def") @@ -121,6 +129,8 @@ func (o *Output) CreateLibFile() { defer os.Remove(temp.Name()) content := def.GetContent() + println(content) + err = os.WriteFile(temp.Name(), []byte(content), 0644) if err != nil { log.Fatalf("[!] Error while creating '%s' file: %v", temp.Name(), err) diff --git a/templates/static-shim.cpp.template b/templates/static-shim.cpp.template index 8ce8d3e..adaa74e 100644 --- a/templates/static-shim.cpp.template +++ b/templates/static-shim.cpp.template @@ -30,7 +30,6 @@ extern "C" __declspec(dllimport) UINT64 {{$v.OriginalName}}(PARAMS); -// {{$v.OriginalName}} extern "C" UINT64 {{$v.ProxyName}}(PARAMS) { #ifdef DEBUG dbgf("{{$v.OriginalName}} called");