Dynamic with mangled works, static with mangled doesn't

This commit is contained in:
Print3M
2025-08-26 14:06:37 +02:00
parent 48fdeb76bd
commit b6617fb3e9
6 changed files with 47 additions and 26 deletions
+2 -1
View File
@@ -4,6 +4,7 @@
"*.sh.template": "shellscript",
"functional": "cpp",
"*.template": "cpp",
"cstdarg": "cpp"
"cstdarg": "cpp",
"iostream": "cpp"
}
}
+3 -2
View File
@@ -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.
+29 -19
View File
@@ -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
}
+1 -1
View File
@@ -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 {
+12 -2
View File
@@ -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)
-1
View File
@@ -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");