From ceae65b44414d975fcf26953b3593e02b680084a Mon Sep 17 00:00:00 2001 From: Print3M <92022497+Print3M@users.noreply.github.com> Date: Fri, 15 Aug 2025 18:10:11 +0200 Subject: [PATCH] init --- .vscode/settings.json | 9 ++ README.md | 30 ++++ build.sh | 9 ++ cli/cli.go | 53 +++++++ def/def.go | 68 +++++++++ dll/dll.go | 43 ++++++ go.mod | 11 ++ go.sum | 39 +++++ main.go | 63 ++++++++ shim.cpp | 271 ++++++++++++++++++++++++++++++++++ templates/shim.c.template | 103 +++++++++++++ templates/shim.c.template.bak | 109 ++++++++++++++ tmpl/tmpl.go | 24 +++ 13 files changed, 832 insertions(+) create mode 100644 .vscode/settings.json create mode 100644 README.md create mode 100755 build.sh create mode 100644 cli/cli.go create mode 100644 def/def.go create mode 100644 dll/dll.go create mode 100644 go.mod create mode 100644 go.sum create mode 100644 main.go create mode 100644 shim.cpp create mode 100644 templates/shim.c.template create mode 100644 templates/shim.c.template.bak create mode 100644 tmpl/tmpl.go diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..b2a9d4b --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,9 @@ +{ + "files.associations": { + "algorithm": "cpp", + "*.template": "c", + "cstdarg": "cpp", + "typeinfo": "c", + "functional": "cpp" + } +} \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..a7271d0 --- /dev/null +++ b/README.md @@ -0,0 +1,30 @@ +# DllShimmer + +Compile everything: + +```bash + +x86_64-w64-mingw32-g++ -shared -o version.dll-shim shim.cpp version.def -static-libstdc++ -static-libgcc + +``` + +Features: + +- All functions implemented in the original DLL can be backdoored. +- Backdoored functions work as original, program doesn't crash. +- Forwarded functions are forwarded as original. +- Both MSVC (`#pragma comment`) and GCC forwarding (`.def file`) are supported. + +Caveats: + +1. Probably it doesn't work with floating-point parameters because they require different registers from va_list. +2. Original ordinal numbers of exported and forwarded functions are not preserved +3. There are some huge obfuscated DLLs with weird name mangling and tricks (e.g. Qt framework DLL). I don't recommend to use them as a backdoor base. Just use some normal DLL with 10-30 exported functions and it's going to work perfectly. + +## Nowa architektura + +Najlepiej by było, gdyby original.dll lądował w IAT backdoor.dll ze wszystkimi funkcjami. Wtedy mamy wszystko dostępne od razu, bez dodatkowego używania WinAPI. + +Pojawia się wtedy problem, że nie można importować i eksportować tych samych symboli. + +- Importuj oryginalne \ No newline at end of file diff --git a/build.sh b/build.sh new file mode 100755 index 0000000..be7e134 --- /dev/null +++ b/build.sh @@ -0,0 +1,9 @@ +#!/usr/bin/env bash + +set -ueo pipefail + +go run main.go -i '7z.dll' -p '7z2.dll' --def 'dll.def' -m > shim.cpp + +x86_64-w64-mingw32-g++ -shared shim.cpp dll.def -o 7z.dll-shim -static-libstdc++ -static-libgcc -D DEBUG=1 + +mv 7z.dll-shim ~/vm/Windows\ 11/shared/7z.dll \ No newline at end of file diff --git a/cli/cli.go b/cli/cli.go new file mode 100644 index 0000000..71484a8 --- /dev/null +++ b/cli/cli.go @@ -0,0 +1,53 @@ +package cli + +import ( + "flag" + "fmt" + "os" +) + +type CliFlags struct { + Input string + Proxy string + Mutex bool +} + +func ParseCli() *CliFlags { + var flags CliFlags + + flag.StringVar(&flags.Input, "i", "", "") + flag.StringVar(&flags.Input, "input", "", "") + + flag.StringVar(&flags.Proxy, "p", "", "") + flag.StringVar(&flags.Proxy, "proxy", "", "") + + flag.BoolVar(&flags.Mutex, "m", false, "") + flag.BoolVar(&flags.Mutex, "mutex", false, "") + + flag.Usage = func() { + fmt.Fprintf(os.Stderr, "Usage: DllShimmer -i -o -p \n") + fmt.Println() + fmt.Println("Usage:") + fmt.Println() + fmt.Printf(" %-24s %s\n", "-i, --input ", "Input DLL file (required)") + fmt.Printf(" %-24s %s\n", "-p, --proxy ", "Path to original DLL on target (required)") + fmt.Printf(" %-24s %s\n", "-m, --mutex", "Multiple execution prevention (default: false)") + fmt.Printf(" %-24s %s\n", "-h, --help", "Show this help") + fmt.Println() + fmt.Println("Example:") + fmt.Println() + fmt.Println(" DllShimmer -i version.dll -o shim.c -p 'C:\\Windows\\System32\\version.dll' -m") + fmt.Println() + fmt.Println("Created by Print3M (print3m.github.io)") + fmt.Println() + } + + flag.Parse() + + if flags.Input == "" || flags.Proxy == "" { + flag.Usage() + os.Exit(1) + } + + return &flags +} diff --git a/def/def.go b/def/def.go new file mode 100644 index 0000000..e6deeb4 --- /dev/null +++ b/def/def.go @@ -0,0 +1,68 @@ +package def + +import ( + "log" + "os" +) + +type exportedFunction struct { + OriginalName string + Rename string + Forwarder string +} + +type DefFile struct { + DllName string + Path string + exportedFunctions []exportedFunction +} + +func (d *DefFile) AddExportedFunction(name string) { + d.exportedFunctions = append(d.exportedFunctions, exportedFunction{ + OriginalName: name, + }) +} + +func (d *DefFile) AddRenamedFunction(originalName string, rename string) { + d.exportedFunctions = append(d.exportedFunctions, exportedFunction{ + OriginalName: originalName, + Rename: rename, + }) +} + +func (d *DefFile) AddForwardedFunction(originalName string, forwarder string) { + d.exportedFunctions = append(d.exportedFunctions, exportedFunction{ + OriginalName: originalName, + Forwarder: forwarder, + }) +} + +func (d *DefFile) SaveFile() { + 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 + "\n" + continue + } + + if function.Rename != "" { + // Exported-renamed functions + content += "\t" + function.Rename + "=" + function.OriginalName + "\n" + continue + } + + content += "\t" + function.OriginalName + "\n" + } + + content += "\n" + + err := os.WriteFile(d.Path, []byte(content), 0644) + if err != nil { + log.Fatalf("[!] Error while creating .def file: %v", err) + } +} diff --git a/dll/dll.go b/dll/dll.go new file mode 100644 index 0000000..206b999 --- /dev/null +++ b/dll/dll.go @@ -0,0 +1,43 @@ +package dll + +import ( + "log" + "path/filepath" + + peparser "github.com/saferwall/pe" +) + +type ExportedFunction struct { + Name string + Forwarder string +} + +type Dll struct { + Name string + ExportedFunctions []ExportedFunction +} + +func ParseDll(dllPath string) *Dll { + var dll Dll + + dll.Name = filepath.Base(dllPath) + + pe, err := peparser.New(dllPath, &peparser.Options{}) + if err != nil { + log.Fatalf("[!] Error while opening file: %s, reason: %v", dllPath, err) + } + + err = pe.Parse() + if err != nil { + log.Fatalf("[!] Error while parsing file: %s, reason: %v", dllPath, err) + } + + for _, function := range pe.Export.Functions { + dll.ExportedFunctions = append(dll.ExportedFunctions, ExportedFunction{ + Name: function.Name, + Forwarder: function.Forwarder, + }) + } + + return &dll +} diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..da23ec5 --- /dev/null +++ b/go.mod @@ -0,0 +1,11 @@ +module dllshimmer + +go 1.23.1 + +require ( + github.com/edsrzf/mmap-go v1.2.0 // indirect + github.com/saferwall/pe v1.5.7 // indirect + github.com/secDre4mer/pkcs7 v0.0.0-20240322103146-665324a4461d // indirect + golang.org/x/sys v0.35.0 // indirect + golang.org/x/text v0.28.0 // indirect +) diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..1d4b613 --- /dev/null +++ b/go.sum @@ -0,0 +1,39 @@ +github.com/edsrzf/mmap-go v1.1.0 h1:6EUwBLQ/Mcr1EYLE4Tn1VdW1A4ckqCQWZBw8Hr0kjpQ= +github.com/edsrzf/mmap-go v1.1.0/go.mod h1:19H/e8pUPLicwkyNgOykDXkJ9F0MHE+Z52B8EIth78Q= +github.com/edsrzf/mmap-go v1.2.0 h1:hXLYlkbaPzt1SaQk+anYwKSRNhufIDCchSPkUD6dD84= +github.com/edsrzf/mmap-go v1.2.0/go.mod h1:19H/e8pUPLicwkyNgOykDXkJ9F0MHE+Z52B8EIth78Q= +github.com/saferwall/pe v1.5.7 h1:fxlRLvhyr+3cIs1yturWhWmgACIu147o+xSEYFlUAyA= +github.com/saferwall/pe v1.5.7/go.mod h1:mJx+PuptmNpoPFBNhWs/uDMFL/kTHVZIkg0d4OUJFbQ= +github.com/secDre4mer/pkcs7 v0.0.0-20240322103146-665324a4461d h1:RQqyEogx5J6wPdoxqL132b100j8KjcVHO1c0KLRoIhc= +github.com/secDre4mer/pkcs7 v0.0.0-20240322103146-665324a4461d/go.mod h1:PegD7EVqlN88z7TpCqH92hHP+GBpfomGCCnw1PFtNOA= +github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f h1:v4INt8xihDGvnrfjMDVXGxw9wrfxYyCjk0KbXjhR55s= +golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.35.0 h1:vz1N37gP5bs89s7He8XuIYXpyY0+QlsKmzipCbUtyxI= +golang.org/x/sys v0.35.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.7.0 h1:4BRB4x83lYWy72KwLD/qYDuTu7q9PjSagHvijDw7cLo= +golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.28.0 h1:rhazDwis8INMIwQ4tpjLDzUhx6RlXqZNPEM0huQojng= +golang.org/x/text v0.28.0/go.mod h1:U8nCwOR8jO/marOQ0QbDiOngZVEBB7MAiitBuMjXiNU= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= diff --git a/main.go b/main.go new file mode 100644 index 0000000..24cd25b --- /dev/null +++ b/main.go @@ -0,0 +1,63 @@ +package main + +import ( + "dllshimmer/cli" + "dllshimmer/def" + "dllshimmer/dll" + "dllshimmer/tmpl" + "os/exec" + "path/filepath" +) + +func main() { + flags := cli.ParseCli() + + dll := dll.ParseDll(flags.Input) + + var params tmpl.TemplateParams + params.Functions = dll.ExportedFunctions + params.ProxyDll = flags.Proxy + params.DllName = filepath.Base(flags.Input) + params.Mutex = flags.Mutex + + tmpl.CreateShimCode(params) + + // 1. Create temp .def based on original file + func() { + var def def.DefFile + def.DllName = params.DllName + def.Path = "tmp.def" + + for _, function := range dll.ExportedFunctions { + if function.Forwarder == "" { + def.AddExportedFunction(function.Name) + } else { + def.AddForwardedFunction(function.Name, function.Forwarder) + } + } + + def.SaveFile() + cmd := exec.Command("x86_64-w64-mingw32-dlltool", "-d", "tmp.def", "-l", "tmp.lib") + }() + + // 2. Create new .def based on generated code + func() { + var def def.DefFile + def.DllName = params.DllName + def.Path = "exported.def" + + for _, function := range dll.ExportedFunctions { + if function.Forwarder == "" { + def.AddRenamedFunction(function.Name, function.Name+"Fwd") + } else { + def.AddForwardedFunction(function.Name, function.Forwarder) + } + } + + def.SaveFile() + + }() + +} + +// DllShimmer -i version.dll -o "C:/Windows/System32/version.dll" -p ~/project -m diff --git a/shim.cpp b/shim.cpp new file mode 100644 index 0000000..1ac0b03 --- /dev/null +++ b/shim.cpp @@ -0,0 +1,271 @@ +#include +#include +// Put your imports here... + +// #------------------------------------------------------------------# +// | "DON'T TOUCH" ZONE | +// | (auto generated) | +// #------------------------------------------------------------------# +#define CreateDecoder CreateDecoderOriginal +#define CreateEncoder CreateEncoderOriginal +#define CreateObject CreateObjectOriginal +#define GetHandlerProperty GetHandlerPropertyOriginal +#define GetHandlerProperty2 GetHandlerProperty2Original +#define GetHashers GetHashersOriginal +#define GetIsArc GetIsArcOriginal +#define GetMethodProperty GetMethodPropertyOriginal +#define GetModuleProp GetModulePropOriginal +#define GetNumberOfFormats GetNumberOfFormatsOriginal +#define GetNumberOfMethods GetNumberOfMethodsOriginal +#define SetCaseSensitive SetCaseSensitiveOriginal +#define SetCodecs SetCodecsOriginal +#define SetLargePageMode SetLargePageModeOriginal +#include +#undef CreateDecoder +#undef CreateEncoder +#undef CreateObject +#undef GetHandlerProperty +#undef GetHandlerProperty2 +#undef GetHashers +#undef GetIsArc +#undef GetMethodProperty +#undef GetModuleProp +#undef GetNumberOfFormats +#undef GetNumberOfMethods +#undef SetCaseSensitive +#undef SetCodecs +#undef SetLargePageMode + + +#define MUTEX(name) \ + (CreateMutexA(NULL, TRUE, name) && GetLastError() != ERROR_ALREADY_EXISTS) + +#define ARGS_COUNT 12 + +typedef uint64_t (*Func12)( + uint64_t, uint64_t, uint64_t, uint64_t, + uint64_t, uint64_t, uint64_t, uint64_t, + uint64_t, uint64_t, uint64_t, uint64_t +); + +#define PROXY_FUNCTION(function) \ + va_list ap; \ + va_start(ap, arg1); \ + uint64_t args[ARGS_COUNT]; \ + args[0] = arg1; \ + \ + for (int i = 1; i < ARGS_COUNT ; i++) { \ + args[i] = va_arg(ap, uint64_t); \ + } \ + \ + va_end(ap); \ + \ + HMODULE hModule = LoadLibraryA("7z2.dll"); \ + if (hModule == NULL) { \ + printf("[!] 7z.dll: LoadLibraryA(7z2.dll) failed\n"); \ + printf("\tError code: %lu\n", GetLastError()); \ + } \ + \ + Func12 pFunction = (Func12) GetProcAddress(hModule, function); \ + if (pFunction == NULL) { \ + printf( \ + "[!] 7z.dll: GetProcAddress(%s, 7z2.dll) failed\n", \ + function ); \ + printf("\tError code: %lu\n", GetLastError()); \ + \ + } \ + \ + return pFunction(args[0], args[1], args[2], args[3], args[4], args[5], \ + args[6], args[7], args[8], args[9], args[10], args[11]); \ + +// ---- Forwarded functions ------------------------------------------ + +// #------------------------------------------------------------------# +// | END OF "DON'T TOUCH" ZONE | +// #------------------------------------------------------------------# + +extern "C" __declspec(dllexport) UINT64 CreateDecoder(UINT64 arg1, ...) { + #ifdef DEBUG + printf("[+] 7z.dll: CreateDecoder called\n"); + #endif + + if (MUTEX("Global\\CreateDecoder__0")) { + // Put your code here... + } + + PROXY_FUNCTION("CreateDecoder"); +} + +extern "C" __declspec(dllexport) UINT64 CreateEncoder(UINT64 arg1, ...) { + #ifdef DEBUG + printf("[+] 7z.dll: CreateEncoder called\n"); + #endif + + if (MUTEX("Global\\CreateEncoder__1")) { + // Put your code here... + } + + PROXY_FUNCTION("CreateEncoder"); +} + +extern "C" __declspec(dllexport) UINT64 CreateObject(UINT64 arg1, ...) { + #ifdef DEBUG + printf("[+] 7z.dll: CreateObject called\n"); + #endif + + if (MUTEX("Global\\CreateObject__2")) { + // Put your code here... + } + + PROXY_FUNCTION("CreateObject"); +} + +extern "C" __declspec(dllexport) UINT64 GetHandlerProperty(UINT64 arg1, ...) { + #ifdef DEBUG + printf("[+] 7z.dll: GetHandlerProperty called\n"); + #endif + + if (MUTEX("Global\\GetHandlerProperty__3")) { + // Put your code here... + } + + PROXY_FUNCTION("GetHandlerProperty"); +} + +extern "C" __declspec(dllexport) UINT64 GetHandlerProperty2(UINT64 arg1, ...) { + #ifdef DEBUG + printf("[+] 7z.dll: GetHandlerProperty2 called\n"); + #endif + + if (MUTEX("Global\\GetHandlerProperty2__4")) { + // Put your code here... + } + + PROXY_FUNCTION("GetHandlerProperty2"); +} + +extern "C" __declspec(dllexport) UINT64 GetHashers(UINT64 arg1, ...) { + #ifdef DEBUG + printf("[+] 7z.dll: GetHashers called\n"); + #endif + + if (MUTEX("Global\\GetHashers__5")) { + // Put your code here... + } + + PROXY_FUNCTION("GetHashers"); +} + +extern "C" __declspec(dllexport) UINT64 GetIsArc(UINT64 arg1, ...) { + #ifdef DEBUG + printf("[+] 7z.dll: GetIsArc called\n"); + #endif + + if (MUTEX("Global\\GetIsArc__6")) { + // Put your code here... + } + + PROXY_FUNCTION("GetIsArc"); +} + +extern "C" __declspec(dllexport) UINT64 GetMethodProperty(UINT64 arg1, ...) { + #ifdef DEBUG + printf("[+] 7z.dll: GetMethodProperty called\n"); + #endif + + if (MUTEX("Global\\GetMethodProperty__7")) { + // Put your code here... + } + + PROXY_FUNCTION("GetMethodProperty"); +} + +extern "C" __declspec(dllexport) UINT64 GetModuleProp(UINT64 arg1, ...) { + #ifdef DEBUG + printf("[+] 7z.dll: GetModuleProp called\n"); + #endif + + if (MUTEX("Global\\GetModuleProp__8")) { + // Put your code here... + } + + PROXY_FUNCTION("GetModuleProp"); +} + +extern "C" __declspec(dllexport) UINT64 GetNumberOfFormats(UINT64 arg1, ...) { + #ifdef DEBUG + printf("[+] 7z.dll: GetNumberOfFormats called\n"); + #endif + + if (MUTEX("Global\\GetNumberOfFormats__9")) { + // Put your code here... + } + + PROXY_FUNCTION("GetNumberOfFormats"); +} + +extern "C" __declspec(dllexport) UINT64 GetNumberOfMethods(UINT64 arg1, ...) { + #ifdef DEBUG + printf("[+] 7z.dll: GetNumberOfMethods called\n"); + #endif + + if (MUTEX("Global\\GetNumberOfMethods__10")) { + // Put your code here... + } + + PROXY_FUNCTION("GetNumberOfMethods"); +} + +extern "C" __declspec(dllexport) UINT64 SetCaseSensitive(UINT64 arg1, ...) { + #ifdef DEBUG + printf("[+] 7z.dll: SetCaseSensitive called\n"); + #endif + + if (MUTEX("Global\\SetCaseSensitive__11")) { + // Put your code here... + } + + PROXY_FUNCTION("SetCaseSensitive"); +} + +extern "C" __declspec(dllexport) UINT64 SetCodecs(UINT64 arg1, ...) { + #ifdef DEBUG + printf("[+] 7z.dll: SetCodecs called\n"); + #endif + + if (MUTEX("Global\\SetCodecs__12")) { + // Put your code here... + } + + PROXY_FUNCTION("SetCodecs"); +} + +extern "C" __declspec(dllexport) UINT64 SetLargePageMode(UINT64 arg1, ...) { + #ifdef DEBUG + printf("[+] 7z.dll: SetLargePageMode called\n"); + #endif + + if (MUTEX("Global\\SetLargePageMode__13")) { + // Put your code here... + } + + PROXY_FUNCTION("SetLargePageMode"); +} + + +BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) { + + switch (fdwReason) { + case DLL_PROCESS_ATTACH: { + #ifdef DEBUG + printf("[+] 7z.dll: DLL_PROCESS_ATTACH event\n"); + #endif + } + case DLL_THREAD_ATTACH: + case DLL_THREAD_DETACH: + case DLL_PROCESS_DETACH: + break; + } + + return TRUE; +} \ No newline at end of file diff --git a/templates/shim.c.template b/templates/shim.c.template new file mode 100644 index 0000000..49f89f1 --- /dev/null +++ b/templates/shim.c.template @@ -0,0 +1,103 @@ +#include +#include +// Put your imports here... + +// #------------------------------------------------------------------# +// | "DON'T TOUCH" ZONE | +// | (auto generated) | +// #------------------------------------------------------------------# + +{{- range .Functions}} +#define {{.Name}} {{.Name}}Original +{{- end}} +#include +{{- range .Functions}} +#undef {{.Name}} +{{- end}} +{{ $r := . }} + +#define MUTEX(name) \ + (CreateMutexA(NULL, TRUE, name) && GetLastError() != ERROR_ALREADY_EXISTS) + +#define ARGS_COUNT 12 + +typedef uint64_t (*Func12)( + uint64_t, uint64_t, uint64_t, uint64_t, + uint64_t, uint64_t, uint64_t, uint64_t, + uint64_t, uint64_t, uint64_t, uint64_t +); + +#define PROXY_FUNCTION(function) \ + va_list ap; \ + va_start(ap, arg1); \ + uint64_t args[ARGS_COUNT]; \ + args[0] = arg1; \ + \ + for (int i = 1; i < ARGS_COUNT ; i++) { \ + args[i] = va_arg(ap, uint64_t); \ + } \ + \ + va_end(ap); \ + \ + HMODULE hModule = LoadLibraryA("{{.ProxyDll}}"); \ + if (hModule == NULL) { \ + printf("[!] {{.DllName}}: LoadLibraryA({{.ProxyDll}}) failed\n"); \ + printf("\tError code: %lu\n", GetLastError()); \ + } \ + \ + Func12 pFunction = (Func12) GetProcAddress(hModule, function); \ + if (pFunction == NULL) { \ + printf( \ + "[!] {{.DllName}}: GetProcAddress(%s, {{.ProxyDll}}) failed\n", \ + function ); \ + printf("\tError code: %lu\n", GetLastError()); \ + \ + } \ + \ + return pFunction(args[0], args[1], args[2], args[3], args[4], args[5], \ + args[6], args[7], args[8], args[9], args[10], args[11]); \ + +// #------------------------------------------------------------------# +// | END OF "DON'T TOUCH" ZONE | +// #------------------------------------------------------------------# + +{{- range $i, $v := .Functions }} +{{- if eq (len $v.Forwarder) 0 }} + +__declspec(dllimport) UINT64 {{$v.Name}}(UINT64 arg1, ...); + +extern "C" __declspec(dllexport) UINT64 {{$v.Name}}Fwd(UINT64 arg1, ...) { + #ifdef DEBUG + printf("[+] {{$r.DllName}}: {{$v.Name}} called\n"); + #endif + {{ if $r.Mutex }} + if (MUTEX("Global\\{{$v.Name}}__{{$i}}")) { + // Put your code here... + } + {{- else }} + // Put your code here... + {{- end }} + + PROXY_FUNCTION("{{$v.Name}}"); +} + +{{- end }} +{{- end }} + + +BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) { + + switch (fdwReason) { + case DLL_PROCESS_ATTACH: { + #ifdef DEBUG + printf("[+] {{.DllName}}: DLL_PROCESS_ATTACH event\n"); + #endif + } + case DLL_THREAD_ATTACH: + case DLL_THREAD_DETACH: + case DLL_PROCESS_DETACH: + break; + } + + return TRUE; +} \ No newline at end of file diff --git a/templates/shim.c.template.bak b/templates/shim.c.template.bak new file mode 100644 index 0000000..d0b177d --- /dev/null +++ b/templates/shim.c.template.bak @@ -0,0 +1,109 @@ +#include +#include +// Put your imports here... + +// #------------------------------------------------------------------# +// | "DON'T TOUCH" ZONE | +// | (auto generated) | +// #------------------------------------------------------------------# + +{{- range .Functions}} +#define {{.Name}} {{.Name}}Original +{{- end}} +#include +{{- range .Functions}} +#undef {{.Name}} +{{- end}} +{{ $r := . }} + +#define MUTEX(name) \ + (CreateMutexA(NULL, TRUE, name) && GetLastError() != ERROR_ALREADY_EXISTS) + +#define ARGS_COUNT 12 + +typedef uint64_t (*Func12)( + uint64_t, uint64_t, uint64_t, uint64_t, + uint64_t, uint64_t, uint64_t, uint64_t, + uint64_t, uint64_t, uint64_t, uint64_t +); + +#define PROXY_FUNCTION(function) \ + va_list ap; \ + va_start(ap, arg1); \ + uint64_t args[ARGS_COUNT]; \ + args[0] = arg1; \ + \ + for (int i = 1; i < ARGS_COUNT ; i++) { \ + args[i] = va_arg(ap, uint64_t); \ + } \ + \ + va_end(ap); \ + \ + HMODULE hModule = LoadLibraryA("{{.ProxyDll}}"); \ + if (hModule == NULL) { \ + printf("[!] {{.DllName}}: LoadLibraryA({{.ProxyDll}}) failed\n"); \ + printf("\tError code: %lu\n", GetLastError()); \ + } \ + \ + Func12 pFunction = (Func12) GetProcAddress(hModule, function); \ + if (pFunction == NULL) { \ + printf( \ + "[!] {{.DllName}}: GetProcAddress(%s, {{.ProxyDll}}) failed\n", \ + function ); \ + printf("\tError code: %lu\n", GetLastError()); \ + \ + } \ + \ + return pFunction(args[0], args[1], args[2], args[3], args[4], args[5], \ + args[6], args[7], args[8], args[9], args[10], args[11]); \ + +// ---- Forwarded functions ------------------------------------------ + +{{- range .Functions }} +{{- if .Forwarder }} +#pragma comment(linker, "/EXPORT:{{.Name}}={{.Forwarder}}") +{{- end }} +{{- end }} + +// #------------------------------------------------------------------# +// | END OF "DON'T TOUCH" ZONE | +// #------------------------------------------------------------------# + +{{- range $i, $v := .Functions }} +{{- if eq (len $v.Forwarder) 0 }} + +extern "C" __declspec(dllexport) UINT64 {{$v.Name}}(UINT64 arg1, ...) { + #ifdef DEBUG + printf("[+] {{$r.DllName}}: {{$v.Name}} called\n"); + #endif + {{ if $r.Mutex }} + if (MUTEX("Global\\{{$v.Name}}__{{$i}}")) { + // Put your code here... + } + {{- else }} + // Put your code here... + {{- end }} + + PROXY_FUNCTION("{{$v.Name}}"); +} + +{{- end }} +{{- end }} + + +BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) { + + switch (fdwReason) { + case DLL_PROCESS_ATTACH: { + #ifdef DEBUG + printf("[+] {{.DllName}}: DLL_PROCESS_ATTACH event\n"); + #endif + } + case DLL_THREAD_ATTACH: + case DLL_THREAD_DETACH: + case DLL_PROCESS_DETACH: + break; + } + + return TRUE; +} \ No newline at end of file diff --git a/tmpl/tmpl.go b/tmpl/tmpl.go new file mode 100644 index 0000000..04709b6 --- /dev/null +++ b/tmpl/tmpl.go @@ -0,0 +1,24 @@ +package tmpl + +import ( + "dllshimmer/dll" + "log" + "os" + "text/template" +) + +type TemplateParams struct { + Functions []dll.ExportedFunction + ProxyDll string + DllName string + Mutex bool +} + +func CreateShimCode(params TemplateParams) { + tmpl := template.Must(template.ParseFiles("templates/shim.c.template")) + + err := tmpl.Execute(os.Stdout, params) + if err != nil { + log.Fatalf("[!] Error of template engine: %v", err) + } +}