+311
Cargo.lock
+311
Cargo.lock
···
1
+
# This file is automatically @generated by Cargo.
2
+
# It is not intended for manual editing.
3
+
version = 4
4
+
5
+
[[package]]
6
+
name = "bitflags"
7
+
version = "1.3.2"
8
+
source = "registry+https://github.com/rust-lang/crates.io-index"
9
+
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
10
+
11
+
[[package]]
12
+
name = "cc"
13
+
version = "1.2.46"
14
+
source = "registry+https://github.com/rust-lang/crates.io-index"
15
+
checksum = "b97463e1064cb1b1c1384ad0a0b9c8abd0988e2a91f52606c80ef14aadb63e36"
16
+
dependencies = [
17
+
"find-msvc-tools",
18
+
"shlex",
19
+
]
20
+
21
+
[[package]]
22
+
name = "cfg-if"
23
+
version = "1.0.4"
24
+
source = "registry+https://github.com/rust-lang/crates.io-index"
25
+
checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801"
26
+
27
+
[[package]]
28
+
name = "find-msvc-tools"
29
+
version = "0.1.5"
30
+
source = "registry+https://github.com/rust-lang/crates.io-index"
31
+
checksum = "3a3076410a55c90011c298b04d0cfa770b00fa04e1e3c97d3f6c9de105a03844"
32
+
33
+
[[package]]
34
+
name = "generic-array"
35
+
version = "0.14.9"
36
+
source = "registry+https://github.com/rust-lang/crates.io-index"
37
+
checksum = "4bb6743198531e02858aeaea5398fcc883e71851fcbcb5a2f773e2fb6cb1edf2"
38
+
dependencies = [
39
+
"typenum",
40
+
"version_check",
41
+
]
42
+
43
+
[[package]]
44
+
name = "libc"
45
+
version = "0.2.177"
46
+
source = "registry+https://github.com/rust-lang/crates.io-index"
47
+
checksum = "2874a2af47a2325c2001a6e6fad9b16a53b802102b528163885171cf92b15976"
48
+
49
+
[[package]]
50
+
name = "libudis86-sys"
51
+
version = "0.2.1"
52
+
source = "registry+https://github.com/rust-lang/crates.io-index"
53
+
checksum = "139bbf9ddb1bfc90c1ac64dd2923d9c957cd433cee7315c018125d72ab08a6b0"
54
+
dependencies = [
55
+
"cc",
56
+
"libc",
57
+
]
58
+
59
+
[[package]]
60
+
name = "log"
61
+
version = "0.4.20"
62
+
source = "registry+https://github.com/rust-lang/crates.io-index"
63
+
checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f"
64
+
65
+
[[package]]
66
+
name = "lumen-plugin"
67
+
version = "0.1.0"
68
+
dependencies = [
69
+
"cc",
70
+
"log",
71
+
"retour",
72
+
"windows",
73
+
]
74
+
75
+
[[package]]
76
+
name = "mach2"
77
+
version = "0.4.3"
78
+
source = "registry+https://github.com/rust-lang/crates.io-index"
79
+
checksum = "d640282b302c0bb0a2a8e0233ead9035e3bed871f0b7e81fe4a1ec829765db44"
80
+
dependencies = [
81
+
"libc",
82
+
]
83
+
84
+
[[package]]
85
+
name = "mmap-fixed-fixed"
86
+
version = "0.1.3"
87
+
source = "registry+https://github.com/rust-lang/crates.io-index"
88
+
checksum = "0681853891801e4763dc252e843672faf32bcfee27a0aa3b19733902af450acc"
89
+
dependencies = [
90
+
"libc",
91
+
"winapi",
92
+
]
93
+
94
+
[[package]]
95
+
name = "once_cell"
96
+
version = "1.21.3"
97
+
source = "registry+https://github.com/rust-lang/crates.io-index"
98
+
checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d"
99
+
100
+
[[package]]
101
+
name = "region"
102
+
version = "3.0.2"
103
+
source = "registry+https://github.com/rust-lang/crates.io-index"
104
+
checksum = "e6b6ebd13bc009aef9cd476c1310d49ac354d36e240cf1bd753290f3dc7199a7"
105
+
dependencies = [
106
+
"bitflags",
107
+
"libc",
108
+
"mach2",
109
+
"windows-sys",
110
+
]
111
+
112
+
[[package]]
113
+
name = "retour"
114
+
version = "0.3.1"
115
+
source = "registry+https://github.com/rust-lang/crates.io-index"
116
+
checksum = "a9af44d40e2400b44d491bfaf8eae111b09f23ac4de6e92728e79d93e699c527"
117
+
dependencies = [
118
+
"cfg-if",
119
+
"generic-array",
120
+
"libc",
121
+
"libudis86-sys",
122
+
"mmap-fixed-fixed",
123
+
"once_cell",
124
+
"region",
125
+
"slice-pool2",
126
+
]
127
+
128
+
[[package]]
129
+
name = "shlex"
130
+
version = "1.3.0"
131
+
source = "registry+https://github.com/rust-lang/crates.io-index"
132
+
checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
133
+
134
+
[[package]]
135
+
name = "slice-pool2"
136
+
version = "0.4.3"
137
+
source = "registry+https://github.com/rust-lang/crates.io-index"
138
+
checksum = "7a3d689654af89bdfeba29a914ab6ac0236d382eb3b764f7454dde052f2821f8"
139
+
140
+
[[package]]
141
+
name = "typenum"
142
+
version = "1.19.0"
143
+
source = "registry+https://github.com/rust-lang/crates.io-index"
144
+
checksum = "562d481066bde0658276a35467c4af00bdc6ee726305698a55b86e61d7ad82bb"
145
+
146
+
[[package]]
147
+
name = "version_check"
148
+
version = "0.9.5"
149
+
source = "registry+https://github.com/rust-lang/crates.io-index"
150
+
checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a"
151
+
152
+
[[package]]
153
+
name = "winapi"
154
+
version = "0.3.9"
155
+
source = "registry+https://github.com/rust-lang/crates.io-index"
156
+
checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
157
+
dependencies = [
158
+
"winapi-i686-pc-windows-gnu",
159
+
"winapi-x86_64-pc-windows-gnu",
160
+
]
161
+
162
+
[[package]]
163
+
name = "winapi-i686-pc-windows-gnu"
164
+
version = "0.4.0"
165
+
source = "registry+https://github.com/rust-lang/crates.io-index"
166
+
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
167
+
168
+
[[package]]
169
+
name = "winapi-x86_64-pc-windows-gnu"
170
+
version = "0.4.0"
171
+
source = "registry+https://github.com/rust-lang/crates.io-index"
172
+
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
173
+
174
+
[[package]]
175
+
name = "windows"
176
+
version = "0.44.0"
177
+
source = "registry+https://github.com/rust-lang/crates.io-index"
178
+
checksum = "9e745dab35a0c4c77aa3ce42d595e13d2003d6902d6b08c9ef5fc326d08da12b"
179
+
dependencies = [
180
+
"windows-targets 0.42.2",
181
+
]
182
+
183
+
[[package]]
184
+
name = "windows-sys"
185
+
version = "0.52.0"
186
+
source = "registry+https://github.com/rust-lang/crates.io-index"
187
+
checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
188
+
dependencies = [
189
+
"windows-targets 0.52.6",
190
+
]
191
+
192
+
[[package]]
193
+
name = "windows-targets"
194
+
version = "0.42.2"
195
+
source = "registry+https://github.com/rust-lang/crates.io-index"
196
+
checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071"
197
+
dependencies = [
198
+
"windows_aarch64_gnullvm 0.42.2",
199
+
"windows_aarch64_msvc 0.42.2",
200
+
"windows_i686_gnu 0.42.2",
201
+
"windows_i686_msvc 0.42.2",
202
+
"windows_x86_64_gnu 0.42.2",
203
+
"windows_x86_64_gnullvm 0.42.2",
204
+
"windows_x86_64_msvc 0.42.2",
205
+
]
206
+
207
+
[[package]]
208
+
name = "windows-targets"
209
+
version = "0.52.6"
210
+
source = "registry+https://github.com/rust-lang/crates.io-index"
211
+
checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973"
212
+
dependencies = [
213
+
"windows_aarch64_gnullvm 0.52.6",
214
+
"windows_aarch64_msvc 0.52.6",
215
+
"windows_i686_gnu 0.52.6",
216
+
"windows_i686_gnullvm",
217
+
"windows_i686_msvc 0.52.6",
218
+
"windows_x86_64_gnu 0.52.6",
219
+
"windows_x86_64_gnullvm 0.52.6",
220
+
"windows_x86_64_msvc 0.52.6",
221
+
]
222
+
223
+
[[package]]
224
+
name = "windows_aarch64_gnullvm"
225
+
version = "0.42.2"
226
+
source = "registry+https://github.com/rust-lang/crates.io-index"
227
+
checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8"
228
+
229
+
[[package]]
230
+
name = "windows_aarch64_gnullvm"
231
+
version = "0.52.6"
232
+
source = "registry+https://github.com/rust-lang/crates.io-index"
233
+
checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3"
234
+
235
+
[[package]]
236
+
name = "windows_aarch64_msvc"
237
+
version = "0.42.2"
238
+
source = "registry+https://github.com/rust-lang/crates.io-index"
239
+
checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43"
240
+
241
+
[[package]]
242
+
name = "windows_aarch64_msvc"
243
+
version = "0.52.6"
244
+
source = "registry+https://github.com/rust-lang/crates.io-index"
245
+
checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469"
246
+
247
+
[[package]]
248
+
name = "windows_i686_gnu"
249
+
version = "0.42.2"
250
+
source = "registry+https://github.com/rust-lang/crates.io-index"
251
+
checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f"
252
+
253
+
[[package]]
254
+
name = "windows_i686_gnu"
255
+
version = "0.52.6"
256
+
source = "registry+https://github.com/rust-lang/crates.io-index"
257
+
checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b"
258
+
259
+
[[package]]
260
+
name = "windows_i686_gnullvm"
261
+
version = "0.52.6"
262
+
source = "registry+https://github.com/rust-lang/crates.io-index"
263
+
checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66"
264
+
265
+
[[package]]
266
+
name = "windows_i686_msvc"
267
+
version = "0.42.2"
268
+
source = "registry+https://github.com/rust-lang/crates.io-index"
269
+
checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060"
270
+
271
+
[[package]]
272
+
name = "windows_i686_msvc"
273
+
version = "0.52.6"
274
+
source = "registry+https://github.com/rust-lang/crates.io-index"
275
+
checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66"
276
+
277
+
[[package]]
278
+
name = "windows_x86_64_gnu"
279
+
version = "0.42.2"
280
+
source = "registry+https://github.com/rust-lang/crates.io-index"
281
+
checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36"
282
+
283
+
[[package]]
284
+
name = "windows_x86_64_gnu"
285
+
version = "0.52.6"
286
+
source = "registry+https://github.com/rust-lang/crates.io-index"
287
+
checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78"
288
+
289
+
[[package]]
290
+
name = "windows_x86_64_gnullvm"
291
+
version = "0.42.2"
292
+
source = "registry+https://github.com/rust-lang/crates.io-index"
293
+
checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3"
294
+
295
+
[[package]]
296
+
name = "windows_x86_64_gnullvm"
297
+
version = "0.52.6"
298
+
source = "registry+https://github.com/rust-lang/crates.io-index"
299
+
checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d"
300
+
301
+
[[package]]
302
+
name = "windows_x86_64_msvc"
303
+
version = "0.42.2"
304
+
source = "registry+https://github.com/rust-lang/crates.io-index"
305
+
checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0"
306
+
307
+
[[package]]
308
+
name = "windows_x86_64_msvc"
309
+
version = "0.52.6"
310
+
source = "registry+https://github.com/rust-lang/crates.io-index"
311
+
checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
+27
Cargo.toml
+27
Cargo.toml
···
1
+
2
+
[package]
3
+
name = "lumen-plugin"
4
+
version = "0.1.0"
5
+
edition = "2021"
6
+
7
+
build = "build.rs"
8
+
9
+
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
10
+
11
+
[lib]
12
+
crate-type = ["cdylib"]
13
+
14
+
[dependencies]
15
+
log = "0.4"
16
+
retour = { version = "0.3.1" }
17
+
18
+
[profile.release]
19
+
panic = 'unwind'
20
+
strip = 'debuginfo'
21
+
lto = 'thin'
22
+
23
+
[target.'cfg(windows)'.dependencies]
24
+
windows = { version = "0.44", features = ["Win32_System_Diagnostics_ToolHelp", "Win32_System_Diagnostics_Debug", "Win32_System_SystemInformation", "Win32_UI_WindowsAndMessaging", "Win32_System_Memory", "Win32_Foundation"] }
25
+
26
+
[build-dependencies]
27
+
cc = "1.0.83"
+5
build.rs
+5
build.rs
+19
helper.c
+19
helper.c
···
1
+
#include <stdarg.h>
2
+
#include <stddef.h>
3
+
#include <stdint.h>
4
+
5
+
extern size_t get_callui();
6
+
#define callui(...) ((int(*)(int,...))get_callui())( __VA_ARGS__ )
7
+
8
+
9
+
static int vmsg(const char *fmt, va_list ca) {
10
+
return callui(23, fmt, ca);
11
+
}
12
+
13
+
int msg(const char *fmt, ...) {
14
+
va_list va;
15
+
va_start(va, fmt);
16
+
int r = vmsg(fmt, va);
17
+
va_end(va);
18
+
return r;
19
+
}
+3
rust-toolchain.toml
+3
rust-toolchain.toml
+45
src/ida/bindings.rs
+45
src/ida/bindings.rs
···
1
+
/// Provides low-level interface to IDA
2
+
use std::ffi::{c_char, CStr};
3
+
4
+
#[cfg_attr(target_os = "windows", link(name = "ida", kind = "raw-dylib"))]
5
+
extern "C" {
6
+
pub static callui: extern "C" fn(i32, ...) -> usize;
7
+
fn verror(fmt: *const c_char, va: std::ffi::VaList) -> !;
8
+
}
9
+
10
+
#[link(name = "helper", kind = "static")]
11
+
extern "C" {
12
+
fn msg(fmt: *const c_char, ...);
13
+
}
14
+
15
+
#[no_mangle]
16
+
unsafe extern "C" fn get_callui() -> usize {
17
+
callui as _
18
+
}
19
+
20
+
pub fn info<T: AsRef<CStr>>(s: T) {
21
+
let s = s.as_ref().as_ptr();
22
+
23
+
unsafe {
24
+
msg(c"%s\n".as_ptr(), s);
25
+
}
26
+
}
27
+
28
+
unsafe extern "C" fn _fatal(fmt: *const c_char, mut va: ...) -> ! {
29
+
verror(fmt, va.as_va_list());
30
+
}
31
+
32
+
/// Display fatal error message to UI and quit.
33
+
pub fn fatal<T: AsRef<CStr>>(msg: T) -> ! {
34
+
unsafe {
35
+
_fatal(c"%s".as_ptr(), msg.as_ref().as_ptr());
36
+
}
37
+
}
38
+
39
+
pub fn get_kernel_version() -> String {
40
+
let mut buf = [0u8; 1024];
41
+
let res = unsafe { callui(52, buf.as_mut_ptr(), buf.len()) as isize };
42
+
assert!(res > 0, "failed to get kernel version");
43
+
let r = (buf[..res as usize]).to_owned();
44
+
String::from_utf8(r).unwrap()
45
+
}
+29
src/ida/logging.rs
+29
src/ida/logging.rs
···
1
+
use std::ffi::CStr;
2
+
3
+
use super::bindings::info;
4
+
use log::Log;
5
+
6
+
pub struct IdaLogger;
7
+
impl Log for IdaLogger {
8
+
fn enabled(&self, _metadata: &log::Metadata) -> bool {
9
+
true
10
+
}
11
+
12
+
fn log(&self, record: &log::Record) {
13
+
let level = record.level().as_str().chars().next().unwrap_or_default();
14
+
let msg = format!("lumen: {level} {}\x00", record.args());
15
+
if let Ok(cs) = CStr::from_bytes_until_nul(msg.as_bytes()) {
16
+
info(cs);
17
+
}
18
+
}
19
+
20
+
fn flush(&self) {}
21
+
}
22
+
impl IdaLogger {
23
+
pub fn init() {
24
+
unsafe {
25
+
let _ = log::set_logger_racy(&IdaLogger);
26
+
log::set_max_level(log::LevelFilter::Trace);
27
+
}
28
+
}
29
+
}
+93
src/ida/plugin_wrapper.rs
+93
src/ida/plugin_wrapper.rs
···
1
+
use std::{
2
+
ffi::{c_void, CString},
3
+
os::raw::c_char,
4
+
panic::PanicHookInfo,
5
+
ptr::null_mut,
6
+
sync::{Mutex, Once},
7
+
};
8
+
9
+
use log::{error, info, trace};
10
+
11
+
use super::bindings::fatal;
12
+
use super::logging::IdaLogger;
13
+
14
+
#[no_mangle]
15
+
#[used]
16
+
static PLUGIN: Plugin = Plugin::new();
17
+
18
+
static PLUGIN_DATA: Mutex<Option<crate::Plugin>> = Mutex::new(None);
19
+
20
+
fn handle_panic(pi: &PanicHookInfo) {
21
+
let msg = pi.to_string();
22
+
let msg = CString::new(msg).unwrap_or_default();
23
+
fatal(msg);
24
+
}
25
+
26
+
fn init_globals() {
27
+
static ONCE: Once = Once::new();
28
+
ONCE.call_once(|| {
29
+
IdaLogger::init();
30
+
std::panic::set_hook(Box::new(handle_panic));
31
+
});
32
+
}
33
+
34
+
#[repr(C)]
35
+
struct Plugin {
36
+
version: i32,
37
+
flags: i32,
38
+
init: extern "C" fn() -> *mut c_void,
39
+
term: Option<extern "C" fn()>,
40
+
run: Option<extern "C" fn(usize) -> bool>,
41
+
comment: *const c_char,
42
+
help: *const c_char,
43
+
wanted_name: *const c_char,
44
+
wanted_hotkey: *const c_char,
45
+
}
46
+
unsafe impl Sync for Plugin {}
47
+
impl Plugin {
48
+
const fn new() -> Self {
49
+
Self {
50
+
version: 900,
51
+
flags: 0, //0x08, // 0x08 /* PLUGIN_UNL */,
52
+
init: Self::init,
53
+
run: Some(Self::run),
54
+
term: Some(Self::term),
55
+
comment: c"CMT".as_ptr(),
56
+
help: c"Assists in switching between default and custom lumina servers".as_ptr(),
57
+
wanted_name: c"Lumina switcher".as_ptr(),
58
+
wanted_hotkey: c"ALT+L".as_ptr(),
59
+
}
60
+
}
61
+
62
+
extern "C" fn init() -> *mut c_void {
63
+
init_globals();
64
+
trace!("init() called");
65
+
66
+
let mut lock = PLUGIN_DATA.lock().unwrap();
67
+
if lock.is_none() {
68
+
if let Some(x) = crate::Plugin::new() {
69
+
*lock = Some(x);
70
+
} else {
71
+
error!("failed to init plugin");
72
+
return null_mut();
73
+
}
74
+
}
75
+
76
+
2 as _
77
+
}
78
+
79
+
extern "C" fn run(arg: usize) -> bool {
80
+
trace!("run({arg}) called");
81
+
let mut lock = PLUGIN_DATA.lock().unwrap();
82
+
if let Some(plugin) = lock.as_mut() {
83
+
return plugin.run(arg);
84
+
}
85
+
true
86
+
}
87
+
88
+
extern "C" fn term() {
89
+
info!("term() called");
90
+
let mut lock = PLUGIN_DATA.lock().unwrap();
91
+
lock.take();
92
+
}
93
+
}
+114
src/lib.rs
+114
src/lib.rs
···
1
+
#![feature(c_variadic)]
2
+
3
+
use std::ffi::c_void;
4
+
5
+
use log::{error, info, trace, warn};
6
+
use platform::Module;
7
+
8
+
mod ida;
9
+
mod platform;
10
+
11
+
const ANCHOR_STR: &[u8] = b"2.5.4.3";
12
+
13
+
fn get_verify_function_addr() -> Option<usize> {
14
+
let module = match Module::get_module_by_name(&["ida64.dll", "ida.dll"]) {
15
+
Ok(None) => {
16
+
error!("IDA64 module not found!");
17
+
return None;
18
+
}
19
+
Ok(Some(v)) => v,
20
+
Err(err) => {
21
+
error!("Failed to enumerate modules! err={err}");
22
+
return None;
23
+
}
24
+
};
25
+
trace!("ida @ 0x{:06x}", module.get_base());
26
+
let cert_field_str_addr = match module.find_in_image(ANCHOR_STR, 8) {
27
+
None => {
28
+
error!("anchor not found!");
29
+
return None;
30
+
}
31
+
Some(v) => v,
32
+
};
33
+
trace!("anchor string found @ 0x{cert_field_str_addr:06x}, finding xrefs");
34
+
let mut xrefs = module.xrefs_to(cert_field_str_addr);
35
+
let xref = xrefs.next()?;
36
+
if xrefs.next().is_some() {
37
+
warn!("more than 1 xrefs found!");
38
+
}
39
+
trace!("xref @ {xref:08x} ({:08x})", xref - module.get_base());
40
+
41
+
let is_cert_valid = module.find_prologue(xref)?;
42
+
trace!("cert_valid_offset @ {is_cert_valid:08x}");
43
+
44
+
Some(is_cert_valid)
45
+
}
46
+
47
+
/// IDA 9.1: Size 0xE0
48
+
#[repr(C)]
49
+
struct IdaTlsConnection {
50
+
vtable: *const c_void,
51
+
}
52
+
53
+
struct Plugin {
54
+
verify_cert_detour: retour::GenericDetour<extern "C" fn(thus: *mut IdaTlsConnection) -> bool>,
55
+
}
56
+
impl Plugin {
57
+
extern "C" fn patch_is_cert_valid(this: *mut IdaTlsConnection) -> bool {
58
+
trace!("patch_is_cert_valid(this={this:p})");
59
+
60
+
true
61
+
}
62
+
63
+
pub fn new() -> Option<Self> {
64
+
let cert_offset = get_verify_function_addr()?;
65
+
66
+
let verify_cert_detour = unsafe {
67
+
retour::GenericDetour::new::<extern "C" fn(thus: *mut IdaTlsConnection) -> bool>(
68
+
std::mem::transmute(cert_offset),
69
+
Self::patch_is_cert_valid,
70
+
)
71
+
}
72
+
.inspect_err(|err| {
73
+
error!("failed to init detour: {err}");
74
+
})
75
+
.ok()?;
76
+
unsafe {
77
+
if let Err(err) = verify_cert_detour.enable() {
78
+
error!("failed to enable detour: {err}");
79
+
return None;
80
+
}
81
+
}
82
+
83
+
Some(Self { verify_cert_detour })
84
+
}
85
+
86
+
pub fn run(&mut self, _: usize) -> bool {
87
+
let is_enabled = self.verify_cert_detour.is_enabled();
88
+
let res = unsafe {
89
+
if is_enabled {
90
+
self.verify_cert_detour.disable()
91
+
} else {
92
+
self.verify_cert_detour.enable()
93
+
}
94
+
};
95
+
if let Err(err) = res {
96
+
error!("failed to toggle detour: {err}");
97
+
} else {
98
+
if is_enabled {
99
+
info!("detour disabled")
100
+
} else {
101
+
info!("detour enabled");
102
+
}
103
+
}
104
+
true
105
+
}
106
+
}
107
+
impl Drop for Plugin {
108
+
fn drop(&mut self) {
109
+
trace!("cleaning up...");
110
+
unsafe {
111
+
_ = self.verify_cert_detour.disable();
112
+
}
113
+
}
114
+
}
+7
src/platform/mod.rs
+7
src/platform/mod.rs
+221
src/platform/windows.rs
+221
src/platform/windows.rs
···
1
+
use std::marker::PhantomData;
2
+
use std::ptr::addr_of;
3
+
use windows::Win32::{
4
+
Foundation::CloseHandle,
5
+
System::Diagnostics::{
6
+
Debug::{ImageNtHeader, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ, IMAGE_SECTION_HEADER},
7
+
ToolHelp::{
8
+
CreateToolhelp32Snapshot, Module32FirstW, Module32NextW, MODULEENTRY32W,
9
+
TH32CS_SNAPMODULE,
10
+
},
11
+
},
12
+
};
13
+
14
+
unsafe fn get_name(ptr: *const u16) -> String {
15
+
let mut len = 0;
16
+
while unsafe { *ptr.add(len) } != 0 {
17
+
len += 1;
18
+
}
19
+
20
+
let data = unsafe { core::slice::from_raw_parts(ptr, len) };
21
+
String::from_utf16_lossy(data)
22
+
}
23
+
24
+
#[repr(transparent)]
25
+
struct Handle(windows::Win32::Foundation::HANDLE);
26
+
impl From<&Handle> for windows::Win32::Foundation::HANDLE {
27
+
fn from(val: &Handle) -> Self {
28
+
val.0
29
+
}
30
+
}
31
+
impl Drop for Handle {
32
+
fn drop(&mut self) {
33
+
unsafe {
34
+
CloseHandle(self.0);
35
+
}
36
+
}
37
+
}
38
+
39
+
pub struct Module {
40
+
base: usize,
41
+
}
42
+
43
+
struct SectionIter<'a> {
44
+
base: usize,
45
+
idx: usize,
46
+
_phantom: std::marker::PhantomData<&'a ()>,
47
+
}
48
+
impl<'a> Iterator for SectionIter<'a> {
49
+
type Item = Section<'a>;
50
+
51
+
fn next(&mut self) -> Option<Self::Item> {
52
+
unsafe {
53
+
let nt_image = ImageNtHeader(self.base as _);
54
+
let section_addr_start = addr_of!((*nt_image).OptionalHeader) as usize
55
+
+ (*nt_image).FileHeader.SizeOfOptionalHeader as usize;
56
+
let sections = core::slice::from_raw_parts(
57
+
section_addr_start as *const IMAGE_SECTION_HEADER,
58
+
(*nt_image).FileHeader.NumberOfSections as usize,
59
+
);
60
+
61
+
if self.idx >= sections.len() {
62
+
return None;
63
+
}
64
+
65
+
loop {
66
+
let r = §ions[self.idx];
67
+
self.idx += 1;
68
+
69
+
let is_read = (r.Characteristics.0 & (IMAGE_SCN_MEM_READ.0)) != 0;
70
+
71
+
if !is_read {
72
+
continue;
73
+
}
74
+
75
+
let is_execute = (r.Characteristics.0 & (IMAGE_SCN_MEM_EXECUTE.0)) != 0;
76
+
77
+
let start = self.base + r.VirtualAddress as usize;
78
+
let len = r.Misc.VirtualSize as usize;
79
+
80
+
return Some(Section {
81
+
base: std::slice::from_raw_parts(start as *const u8, len),
82
+
is_execute,
83
+
});
84
+
}
85
+
}
86
+
}
87
+
}
88
+
89
+
struct Section<'a> {
90
+
base: &'a [u8],
91
+
is_execute: bool,
92
+
}
93
+
94
+
impl Module {
95
+
fn walk_sections<'a>(&self) -> impl Iterator<Item = Section<'a>> {
96
+
SectionIter {
97
+
base: self.base,
98
+
idx: 0,
99
+
_phantom: PhantomData,
100
+
}
101
+
}
102
+
103
+
pub fn find_in_image(&self, needle: &[u8], alignment: usize) -> Option<usize> {
104
+
for section_data in self
105
+
.walk_sections()
106
+
.filter(|s| !s.is_execute)
107
+
.map(|v| v.base)
108
+
{
109
+
for idx in (0..section_data.len() - needle.len()).step_by(alignment) {
110
+
let scope = §ion_data[idx..][..needle.len()];
111
+
if scope == needle {
112
+
let cert_data_addr = addr_of!(section_data[idx]);
113
+
return Some(cert_data_addr as usize);
114
+
}
115
+
}
116
+
}
117
+
118
+
None
119
+
}
120
+
121
+
pub fn get_base(&self) -> usize {
122
+
self.base
123
+
}
124
+
125
+
pub fn get_module_by_name(names: &[&str]) -> Result<Option<Module>, windows::core::Error> {
126
+
let handle = unsafe { CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, 0)? };
127
+
let handle = &Handle(handle);
128
+
129
+
let mut entry = MODULEENTRY32W {
130
+
dwSize: std::mem::size_of::<MODULEENTRY32W>() as _,
131
+
..Default::default()
132
+
};
133
+
134
+
if !unsafe { Module32FirstW(handle, &mut entry).as_bool() } {
135
+
return Err(windows::core::Error::from_win32());
136
+
}
137
+
138
+
loop {
139
+
let module_base = entry.modBaseAddr as usize;
140
+
let module_name = unsafe { get_name(entry.szModule.as_ptr()) };
141
+
142
+
for name in names {
143
+
if module_name == *name {
144
+
return Ok(Some(Module { base: module_base }));
145
+
}
146
+
}
147
+
148
+
if unsafe { !Module32NextW(handle, &mut entry).as_bool() } {
149
+
break;
150
+
}
151
+
}
152
+
153
+
Ok(None)
154
+
}
155
+
156
+
pub fn xrefs_to(&self, ptr: usize) -> impl Iterator<Item = usize> {
157
+
self.walk_sections()
158
+
.filter(|sec| sec.is_execute)
159
+
.map(move |section| {
160
+
let ptr = ptr;
161
+
section
162
+
.base
163
+
.windows(7)
164
+
.filter(move |&b| {
165
+
if !(b[0] == 0x4c && b[1] == 0x8d) {
166
+
return false;
167
+
}
168
+
let modrm = b[2];
169
+
let mod_bits = (modrm & 0b1100_0000) >> 6;
170
+
let rm_bits = modrm & 0b0111;
171
+
if mod_bits != 0 || rm_bits != 5 {
172
+
return false;
173
+
}
174
+
175
+
let displacement = &b[3..];
176
+
177
+
let base = b.as_ptr() as usize + b.len();
178
+
let displacement = {
179
+
let mut v = [0u8; 4];
180
+
v.copy_from_slice(displacement);
181
+
i32::from_ne_bytes(v)
182
+
};
183
+
184
+
base.wrapping_add_signed(displacement as isize) as usize == ptr
185
+
})
186
+
.map(|v| v.as_ptr() as usize)
187
+
})
188
+
.flatten()
189
+
}
190
+
191
+
pub fn find_prologue(&self, addr: usize) -> Option<usize> {
192
+
for section in self.walk_sections().filter(|v| v.is_execute) {
193
+
let start = section.base.as_ptr() as usize;
194
+
let end = start + section.base.len();
195
+
if !(start <= addr && addr < end) {
196
+
continue;
197
+
}
198
+
let scan_len = addr - start;
199
+
let search_space = §ion.base[..scan_len];
200
+
for idx in (2..search_space.len() - 1).filter(|v| v % 0x10 == 0).rev() {
201
+
let data = &search_space[idx..];
202
+
if data.len() < 4 {
203
+
continue;
204
+
}
205
+
206
+
// alignment data...
207
+
if !(search_space[idx - 2] == 0xcc && search_space[idx - 1] == 0xcc) {
208
+
continue;
209
+
}
210
+
211
+
// REX prefix
212
+
if !(0x40..=0x4f).contains(&data[0]) {
213
+
continue;
214
+
}
215
+
216
+
return Some(idx + search_space.as_ptr() as usize);
217
+
}
218
+
}
219
+
return None;
220
+
}
221
+
}