1use once_cell::sync::Lazy;
14use parking_lot::Mutex;
15use std::collections::HashMap;
16use std::ffi::{CStr, c_char};
17use std::sync::atomic::{AtomicU64, Ordering};
18
19pub const MEM_OK: i32 = 0;
21pub const MEM_ERR_GENERIC: i32 = -1;
22pub const MEM_ERR_NULL: i32 = -2;
23pub const MEM_ERR_NOT_FOUND: i32 = -3;
24pub const MEM_ERR_EXISTS: i32 = -4;
25pub const MEM_ERR_ALLOC: i32 = -5;
26pub const MEM_ERR_PROTECT: i32 = -6;
27pub const MEM_ERR_PATCH: i32 = -7;
28pub const MEM_ERR_RELOC: i32 = -8;
29pub const MEM_ERR_THREAD: i32 = -9;
30pub const MEM_ERR_SYMBOL: i32 = -10;
31pub const MEM_ERR_RANGE: i32 = -11;
32pub const MEM_ERR_EMPTY: i32 = -12;
33pub const MEM_ERR_HW_LIMIT: i32 = -13;
34
35fn hook_err(e: &crate::memory::manipulation::hook::HookError) -> i32 {
38 use crate::memory::manipulation::hook::HookError;
39 match e {
40 HookError::AlreadyExists(_) => MEM_ERR_EXISTS,
41 HookError::ImageBaseNotFound(_) => MEM_ERR_NOT_FOUND,
42 HookError::AllocationFailed => MEM_ERR_ALLOC,
43 HookError::ProtectionFailed(_) => MEM_ERR_PROTECT,
44 HookError::PatchFailed => MEM_ERR_PATCH,
45 HookError::RelocationFailed => MEM_ERR_RELOC,
46 HookError::ThreadError(_) => MEM_ERR_THREAD,
47 HookError::SymbolError(_) => MEM_ERR_SYMBOL,
48 }
49}
50
51fn patch_err(e: &crate::memory::manipulation::patch::PatchError) -> i32 {
52 use crate::memory::manipulation::patch::PatchError;
53 match e {
54 PatchError::InvalidHex(_) => MEM_ERR_GENERIC,
55 PatchError::ImageBaseNotFound(_) => MEM_ERR_NOT_FOUND,
56 PatchError::ProtectionFailed(_) => MEM_ERR_PROTECT,
57 PatchError::ThreadError(_) => MEM_ERR_THREAD,
58 PatchError::EmptyInstructions => MEM_ERR_EMPTY,
59 PatchError::CaveError(_) => MEM_ERR_ALLOC,
60 PatchError::BranchOutOfRange => MEM_ERR_RANGE,
61 PatchError::VerificationFailed => MEM_ERR_PATCH,
62 }
63}
64
65fn rw_err(e: &crate::memory::manipulation::rw::RwError) -> i32 {
66 use crate::memory::manipulation::rw::RwError;
67 match e {
68 RwError::NullPointer => MEM_ERR_NULL,
69 RwError::ImageBaseNotFound(_) => MEM_ERR_NOT_FOUND,
70 RwError::ProtectionFailed(_) => MEM_ERR_PROTECT,
71 RwError::ThreadError(_) => MEM_ERR_THREAD,
72 }
73}
74
75#[cfg(target_os = "ios")]
76fn brk_err(e: &crate::memory::platform::breakpoint::BrkHookError) -> i32 {
77 use crate::memory::platform::breakpoint::BrkHookError;
78 match e {
79 BrkHookError::TooManyHooks => MEM_ERR_HW_LIMIT,
80 BrkHookError::AlreadyExists(_) => MEM_ERR_EXISTS,
81 BrkHookError::ExceedsHwBreakpoints(_) => MEM_ERR_HW_LIMIT,
82 BrkHookError::SetStateFailed => MEM_ERR_PROTECT,
83 BrkHookError::NotFound(_) => MEM_ERR_NOT_FOUND,
84 BrkHookError::InitFailed => MEM_ERR_GENERIC,
85 }
86}
87
88fn loader_err(e: &crate::memory::allocation::shellcode::LoaderError) -> i32 {
89 use crate::memory::allocation::shellcode::LoaderError;
90 match e {
91 LoaderError::AllocationFailed(_) => MEM_ERR_ALLOC,
92 LoaderError::SymbolNotFound(_) => MEM_ERR_SYMBOL,
93 LoaderError::WriteFailed(_) => MEM_ERR_PATCH,
94 LoaderError::InvalidSize(_) => MEM_ERR_EMPTY,
95 LoaderError::RelocationFailed(_) => MEM_ERR_RELOC,
96 }
97}
98
99static HOOK_REGISTRY: Lazy<Mutex<HashMap<u64, crate::memory::manipulation::hook::Hook>>> =
102 Lazy::new(|| Mutex::new(HashMap::new()));
103
104static PATCH_REGISTRY: Lazy<Mutex<HashMap<usize, crate::memory::manipulation::patch::Patch>>> =
105 Lazy::new(|| Mutex::new(HashMap::new()));
106
107#[cfg(target_os = "ios")]
108static BRK_REGISTRY: Lazy<Mutex<HashMap<u64, crate::memory::platform::breakpoint::Breakpoint>>> =
109 Lazy::new(|| Mutex::new(HashMap::new()));
110
111static SHELLCODE_REGISTRY: Lazy<
112 Mutex<HashMap<usize, crate::memory::allocation::shellcode::LoadedShellcode>>,
113> = Lazy::new(|| Mutex::new(HashMap::new()));
114
115static HANDLE_COUNTER: AtomicU64 = AtomicU64::new(1);
116
117fn next_handle() -> u64 {
118 HANDLE_COUNTER.fetch_add(1, Ordering::Relaxed)
119}
120
121unsafe fn cstr_to_str<'a>(ptr: *const c_char) -> Result<&'a str, i32> {
127 if ptr.is_null() {
128 return Err(MEM_ERR_NULL);
129 }
130 unsafe { CStr::from_ptr(ptr).to_str().map_err(|_| MEM_ERR_GENERIC) }
131}
132
133#[unsafe(no_mangle)]
143pub unsafe extern "C" fn mem_init(image_name: *const c_char, base_out: *mut usize) -> i32 {
144 let name = unsafe {
145 match cstr_to_str(image_name) {
146 Ok(s) => s,
147 Err(e) => return e,
148 }
149 };
150 crate::config::set_target_image_name(name);
151 if !base_out.is_null() {
152 match crate::memory::info::image::get_image_base(name) {
153 Ok(base) => unsafe { *base_out = base },
154 Err(_) => return MEM_ERR_NOT_FOUND,
155 }
156 }
157 MEM_OK
158}
159
160#[unsafe(no_mangle)]
168pub unsafe extern "C" fn mem_hook_install(
169 rva: usize,
170 replacement: usize,
171 trampoline_out: *mut usize,
172 handle_out: *mut u64,
173) -> i32 {
174 if handle_out.is_null() {
175 return MEM_ERR_NULL;
176 }
177 let hook = unsafe {
178 match crate::memory::manipulation::hook::install(rva, replacement) {
179 Ok(h) => h,
180 Err(ref e) => return hook_err(e),
181 }
182 };
183 let trampoline = hook.trampoline();
184 let handle = next_handle();
185 HOOK_REGISTRY.lock().insert(handle, hook);
186 if !trampoline_out.is_null() {
187 unsafe { *trampoline_out = trampoline };
188 }
189 unsafe { *handle_out = handle };
190 MEM_OK
191}
192
193#[unsafe(no_mangle)]
197pub unsafe extern "C" fn mem_hook_symbol(
198 symbol_name: *const c_char,
199 replacement: usize,
200 trampoline_out: *mut usize,
201 handle_out: *mut u64,
202) -> i32 {
203 if handle_out.is_null() {
204 return MEM_ERR_NULL;
205 }
206 let name = unsafe {
207 match cstr_to_str(symbol_name) {
208 Ok(s) => s,
209 Err(e) => return e,
210 }
211 };
212 let hook = unsafe {
213 match crate::memory::manipulation::hook::hook_symbol(name, replacement) {
214 Ok(h) => h,
215 Err(ref e) => return hook_err(e),
216 }
217 };
218 let trampoline = hook.trampoline();
219 let handle = next_handle();
220 HOOK_REGISTRY.lock().insert(handle, hook);
221 if !trampoline_out.is_null() {
222 unsafe { *trampoline_out = trampoline };
223 }
224 unsafe { *handle_out = handle };
225 MEM_OK
226}
227
228#[unsafe(no_mangle)]
233pub unsafe extern "C" fn mem_hook_install_at(
234 target: usize,
235 replacement: usize,
236 trampoline_out: *mut usize,
237) -> i32 {
238 let trampoline = unsafe {
239 match crate::memory::manipulation::hook::install_at_address(target, replacement) {
240 Ok(t) => t,
241 Err(ref e) => return hook_err(e),
242 }
243 };
244 if !trampoline_out.is_null() {
245 unsafe { *trampoline_out = trampoline };
246 }
247 MEM_OK
248}
249
250#[unsafe(no_mangle)]
254pub unsafe extern "C" fn mem_hook_install_cave(
255 rva: usize,
256 replacement: usize,
257 trampoline_out: *mut usize,
258 handle_out: *mut u64,
259) -> i32 {
260 if handle_out.is_null() {
261 return MEM_ERR_NULL;
262 }
263 let hook = unsafe {
264 match crate::memory::manipulation::hook::install_in_cave(rva, replacement) {
265 Ok(h) => h,
266 Err(ref e) => return hook_err(e),
267 }
268 };
269 let trampoline = hook.trampoline();
270 let handle = next_handle();
271 HOOK_REGISTRY.lock().insert(handle, hook);
272 if !trampoline_out.is_null() {
273 unsafe { *trampoline_out = trampoline };
274 }
275 unsafe { *handle_out = handle };
276 MEM_OK
277}
278
279#[unsafe(no_mangle)]
283pub unsafe extern "C" fn mem_hook_install_cave_at(
284 target: usize,
285 replacement: usize,
286 trampoline_out: *mut usize,
287 handle_out: *mut u64,
288) -> i32 {
289 if handle_out.is_null() {
290 return MEM_ERR_NULL;
291 }
292 let hook = unsafe {
293 match crate::memory::manipulation::hook::install_in_cave_at_address(target, replacement) {
294 Ok(h) => h,
295 Err(ref e) => return hook_err(e),
296 }
297 };
298 let trampoline = hook.trampoline();
299 let handle = next_handle();
300 HOOK_REGISTRY.lock().insert(handle, hook);
301 if !trampoline_out.is_null() {
302 unsafe { *trampoline_out = trampoline };
303 }
304 unsafe { *handle_out = handle };
305 MEM_OK
306}
307
308#[unsafe(no_mangle)]
311pub unsafe extern "C" fn mem_hook_remove(handle: u64) -> i32 {
312 let hook = match HOOK_REGISTRY.lock().remove(&handle) {
313 Some(h) => h,
314 None => return MEM_ERR_NOT_FOUND,
315 };
316 hook.remove();
317 MEM_OK
318}
319
320#[unsafe(no_mangle)]
322pub unsafe extern "C" fn mem_hook_remove_at(target: usize) -> i32 {
323 let removed = unsafe { crate::memory::manipulation::hook::remove_at_address(target) };
324 if removed { MEM_OK } else { MEM_ERR_NOT_FOUND }
325}
326
327#[unsafe(no_mangle)]
331pub unsafe extern "C" fn mem_hook_count() -> usize {
332 crate::memory::manipulation::hook::hook_count()
333}
334
335#[unsafe(no_mangle)]
337pub unsafe extern "C" fn mem_hook_is_hooked(target: usize) -> i32 {
338 if crate::memory::manipulation::hook::is_hooked(target) {
339 1
340 } else {
341 0
342 }
343}
344
345#[unsafe(no_mangle)]
349pub unsafe extern "C" fn mem_hook_list(buf: *mut usize, cap: usize, count_out: *mut usize) -> i32 {
350 if count_out.is_null() {
351 return MEM_ERR_NULL;
352 }
353 let hooks = crate::memory::manipulation::hook::list_hooks();
354 let total = hooks.len();
355 unsafe { *count_out = total };
356 if !buf.is_null() {
357 let to_copy = total.min(cap);
358 for (i, &addr) in hooks.iter().take(to_copy).enumerate() {
359 unsafe { *buf.add(i) = addr };
360 }
361 }
362 MEM_OK
363}
364
365#[unsafe(no_mangle)]
372pub unsafe extern "C" fn mem_patch_apply(
373 rva: usize,
374 hex_str: *const c_char,
375 address_out: *mut usize,
376) -> i32 {
377 let hex = unsafe {
378 match cstr_to_str(hex_str) {
379 Ok(s) => s,
380 Err(e) => return e,
381 }
382 };
383 let patch = match crate::memory::manipulation::patch::apply(rva, hex) {
384 Ok(p) => p,
385 Err(ref e) => return patch_err(e),
386 };
387 let addr = patch.address();
388 if !address_out.is_null() {
389 unsafe { *address_out = addr };
390 }
391 PATCH_REGISTRY.lock().insert(addr, patch);
392 MEM_OK
393}
394
395#[unsafe(no_mangle)]
399pub unsafe extern "C" fn mem_patch_apply_at(
400 address: usize,
401 data: *const u8,
402 len: usize,
403 address_out: *mut usize,
404) -> i32 {
405 if data.is_null() {
406 return MEM_ERR_NULL;
407 }
408 if len == 0 {
409 return MEM_ERR_EMPTY;
410 }
411 let slice = unsafe { std::slice::from_raw_parts(data, len) };
412 let patch = match crate::memory::manipulation::patch::apply_at_address(address, slice) {
413 Ok(p) => p,
414 Err(ref e) => return patch_err(e),
415 };
416 let addr = patch.address();
417 if !address_out.is_null() {
418 unsafe { *address_out = addr };
419 }
420 PATCH_REGISTRY.lock().insert(addr, patch);
421 MEM_OK
422}
423
424#[unsafe(no_mangle)]
428pub unsafe extern "C" fn mem_patch_apply_cave(
429 rva: usize,
430 hex_str: *const c_char,
431 address_out: *mut usize,
432) -> i32 {
433 let hex = unsafe {
434 match cstr_to_str(hex_str) {
435 Ok(s) => s,
436 Err(e) => return e,
437 }
438 };
439 let patch = match crate::memory::manipulation::patch::apply_in_cave(rva, hex) {
440 Ok(p) => p,
441 Err(ref e) => return patch_err(e),
442 };
443 let addr = patch.address();
444 if !address_out.is_null() {
445 unsafe { *address_out = addr };
446 }
447 PATCH_REGISTRY.lock().insert(addr, patch);
448 MEM_OK
449}
450
451#[unsafe(no_mangle)]
454pub unsafe extern "C" fn mem_patch_revert(address: usize) -> i32 {
455 let patch = match PATCH_REGISTRY.lock().remove(&address) {
456 Some(p) => p,
457 None => return MEM_ERR_NOT_FOUND,
458 };
459 patch.revert();
460 MEM_OK
461}
462
463#[unsafe(no_mangle)]
470pub unsafe extern "C" fn mem_read(address: usize, out: *mut u8, size: usize) -> i32 {
471 if out.is_null() {
472 return MEM_ERR_NULL;
473 }
474 if address == 0 {
475 return MEM_ERR_NULL;
476 }
477 if size == 0 {
478 return MEM_OK;
479 }
480 unsafe { std::ptr::copy_nonoverlapping(address as *const u8, out, size) };
481 MEM_OK
482}
483
484#[unsafe(no_mangle)]
486pub unsafe extern "C" fn mem_read_rva(rva: usize, out: *mut u8, size: usize) -> i32 {
487 if out.is_null() {
488 return MEM_ERR_NULL;
489 }
490 if size == 0 {
491 return MEM_OK;
492 }
493 let image_name = match crate::config::get_target_image_name() {
494 Some(n) => n,
495 None => return MEM_ERR_NOT_FOUND,
496 };
497 let base = match crate::memory::info::image::get_image_base(&image_name) {
498 Ok(b) => b,
499 Err(_) => return MEM_ERR_NOT_FOUND,
500 };
501 unsafe { std::ptr::copy_nonoverlapping((base + rva) as *const u8, out, size) };
502 MEM_OK
503}
504
505#[unsafe(no_mangle)]
508pub unsafe extern "C" fn mem_read_pointer_chain(
509 base: usize,
510 offsets: *const usize,
511 offset_count: usize,
512 result_out: *mut usize,
513) -> i32 {
514 if result_out.is_null() {
515 return MEM_ERR_NULL;
516 }
517 if offsets.is_null() && offset_count > 0 {
518 return MEM_ERR_NULL;
519 }
520 let slice = if offset_count == 0 {
521 &[] as &[usize]
522 } else {
523 unsafe { std::slice::from_raw_parts(offsets, offset_count) }
524 };
525 match unsafe { crate::memory::manipulation::rw::read_pointer_chain(base, slice) } {
526 Ok(v) => {
527 unsafe { *result_out = v };
528 MEM_OK
529 }
530 Err(ref e) => rw_err(e),
531 }
532}
533
534#[unsafe(no_mangle)]
539pub unsafe extern "C" fn mem_write(address: usize, value: *const u8, size: usize) -> i32 {
540 if value.is_null() {
541 return MEM_ERR_NULL;
542 }
543 if address == 0 {
544 return MEM_ERR_NULL;
545 }
546 if size == 0 {
547 return MEM_OK;
548 }
549 unsafe { std::ptr::copy_nonoverlapping(value, address as *mut u8, size) };
550 MEM_OK
551}
552
553#[unsafe(no_mangle)]
555pub unsafe extern "C" fn mem_write_rva(rva: usize, value: *const u8, size: usize) -> i32 {
556 if value.is_null() {
557 return MEM_ERR_NULL;
558 }
559 if size == 0 {
560 return MEM_OK;
561 }
562 let image_name = match crate::config::get_target_image_name() {
563 Some(n) => n,
564 None => return MEM_ERR_NOT_FOUND,
565 };
566 let base = match crate::memory::info::image::get_image_base(&image_name) {
567 Ok(b) => b,
568 Err(_) => return MEM_ERR_NOT_FOUND,
569 };
570 unsafe { std::ptr::copy_nonoverlapping(value, (base + rva) as *mut u8, size) };
571 MEM_OK
572}
573
574#[unsafe(no_mangle)]
577pub unsafe extern "C" fn mem_write_bytes(address: usize, data: *const u8, len: usize) -> i32 {
578 if data.is_null() {
579 return MEM_ERR_NULL;
580 }
581 if len == 0 {
582 return MEM_OK;
583 }
584 let slice = unsafe { std::slice::from_raw_parts(data, len) };
585 match unsafe { crate::memory::manipulation::rw::write_bytes(address, slice) } {
586 Ok(()) => MEM_OK,
587 Err(ref e) => rw_err(e),
588 }
589}
590
591#[unsafe(no_mangle)]
596pub unsafe extern "C" fn mem_get_image_base(
597 image_name: *const c_char,
598 base_out: *mut usize,
599) -> i32 {
600 if base_out.is_null() {
601 return MEM_ERR_NULL;
602 }
603 let name = unsafe {
604 match cstr_to_str(image_name) {
605 Ok(s) => s,
606 Err(e) => return e,
607 }
608 };
609 match crate::memory::info::image::get_image_base(name) {
610 Ok(base) => {
611 unsafe { *base_out = base };
612 MEM_OK
613 }
614 Err(_) => MEM_ERR_NOT_FOUND,
615 }
616}
617
618#[unsafe(no_mangle)]
621pub unsafe extern "C" fn mem_resolve_symbol(
622 symbol_name: *const c_char,
623 address_out: *mut usize,
624) -> i32 {
625 if address_out.is_null() {
626 return MEM_ERR_NULL;
627 }
628 let name = unsafe {
629 match cstr_to_str(symbol_name) {
630 Ok(s) => s,
631 Err(e) => return e,
632 }
633 };
634 match crate::memory::info::symbol::resolve_symbol(name) {
635 Ok(addr) => {
636 unsafe { *address_out = addr };
637 MEM_OK
638 }
639 Err(_) => MEM_ERR_SYMBOL,
640 }
641}
642
643#[unsafe(no_mangle)]
645pub unsafe extern "C" fn mem_cache_symbol(symbol_name: *const c_char, address: usize) {
646 let name = unsafe {
647 match cstr_to_str(symbol_name) {
648 Ok(s) => s,
649 Err(_) => return,
650 }
651 };
652 crate::memory::info::symbol::cache_symbol(name, address);
653}
654
655#[unsafe(no_mangle)]
657pub unsafe extern "C" fn mem_clear_symbol_cache() {
658 crate::memory::info::symbol::clear_cache();
659}
660
661#[cfg(target_os = "ios")]
666#[unsafe(no_mangle)]
667pub unsafe extern "C" fn mem_brk_install(
668 rva: usize,
669 replacement: usize,
670 handle_out: *mut u64,
671) -> i32 {
672 if handle_out.is_null() {
673 return MEM_ERR_NULL;
674 }
675 let bp = unsafe {
676 match crate::memory::platform::breakpoint::install(rva, replacement) {
677 Ok(b) => b,
678 Err(ref e) => return brk_err(e),
679 }
680 };
681 let handle = next_handle();
682 BRK_REGISTRY.lock().insert(handle, bp);
683 unsafe { *handle_out = handle };
684 MEM_OK
685}
686
687#[cfg(target_os = "ios")]
690#[unsafe(no_mangle)]
691pub unsafe extern "C" fn mem_brk_install_at(
692 target: usize,
693 replacement: usize,
694 handle_out: *mut u64,
695) -> i32 {
696 if handle_out.is_null() {
697 return MEM_ERR_NULL;
698 }
699 let bp = unsafe {
700 match crate::memory::platform::breakpoint::install_at_address(target, replacement) {
701 Ok(b) => b,
702 Err(ref e) => return brk_err(e),
703 }
704 };
705 let handle = next_handle();
706 BRK_REGISTRY.lock().insert(handle, bp);
707 unsafe { *handle_out = handle };
708 MEM_OK
709}
710
711#[cfg(target_os = "ios")]
713#[unsafe(no_mangle)]
714pub unsafe extern "C" fn mem_brk_remove(handle: u64) -> i32 {
715 let bp = match BRK_REGISTRY.lock().remove(&handle) {
716 Some(b) => b,
717 None => return MEM_ERR_NOT_FOUND,
718 };
719 match bp.remove() {
720 Ok(()) => MEM_OK,
721 Err(ref e) => brk_err(e),
722 }
723}
724
725#[cfg(target_os = "ios")]
727#[unsafe(no_mangle)]
728pub unsafe extern "C" fn mem_brk_remove_at(target: usize) -> i32 {
729 let mut registry = BRK_REGISTRY.lock();
730 let handle = match registry.iter().find_map(
732 |(&h, bp)| {
733 if bp.target() == target { Some(h) } else { None }
734 },
735 ) {
736 Some(h) => h,
737 None => return MEM_ERR_NOT_FOUND,
738 };
739 let bp = registry.remove(&handle).expect("handle was just found");
740 drop(registry);
741 match bp.remove() {
742 Ok(()) => MEM_OK,
743 Err(ref e) => brk_err(e),
744 }
745}
746
747#[cfg(target_os = "ios")]
749#[unsafe(no_mangle)]
750pub unsafe extern "C" fn mem_brk_active_count() -> i32 {
751 crate::memory::platform::breakpoint::active_count() as i32
752}
753
754#[cfg(target_os = "ios")]
756#[unsafe(no_mangle)]
757pub unsafe extern "C" fn mem_brk_max_breakpoints() -> i32 {
758 crate::memory::platform::breakpoint::max_breakpoints()
759}
760
761#[unsafe(no_mangle)]
776pub unsafe extern "C" fn mem_shellcode_load(
777 code: *const u8,
778 code_len: usize,
779 reloc_offsets: *const usize,
780 reloc_symbols: *const *const c_char,
781 reloc_count: usize,
782 near_address: usize,
783 _auto_free: i32,
784 address_out: *mut usize,
785) -> i32 {
786 if code.is_null() {
787 return MEM_ERR_NULL;
788 }
789 if code_len == 0 {
790 return MEM_ERR_EMPTY;
791 }
792 if address_out.is_null() {
793 return MEM_ERR_NULL;
794 }
795
796 let code_slice = unsafe { std::slice::from_raw_parts(code, code_len) };
797
798 let mut builder = crate::memory::allocation::shellcode::ShellcodeBuilder::new(code_slice);
799
800 if near_address != 0 {
801 builder = builder.near_address(near_address);
802 }
803
804 if reloc_count > 0 {
805 if reloc_offsets.is_null() || reloc_symbols.is_null() {
806 return MEM_ERR_NULL;
807 }
808 let offsets = unsafe { std::slice::from_raw_parts(reloc_offsets, reloc_count) };
809 let sym_ptrs = unsafe { std::slice::from_raw_parts(reloc_symbols, reloc_count) };
810 for i in 0..reloc_count {
811 let sym_name = unsafe {
812 match cstr_to_str(sym_ptrs[i]) {
813 Ok(s) => s,
814 Err(e) => return e,
815 }
816 };
817 builder = builder.with_symbol(offsets[i], sym_name);
818 }
819 }
820
821 builder = builder.no_auto_free();
825
826 let loaded = match builder.load() {
827 Ok(l) => l,
828 Err(ref e) => return loader_err(e),
829 };
830
831 let addr = loaded.address;
832 unsafe { *address_out = addr };
833 SHELLCODE_REGISTRY.lock().insert(addr, loaded);
834 MEM_OK
835}
836
837#[unsafe(no_mangle)]
840pub unsafe extern "C" fn mem_shellcode_free(address: usize) -> i32 {
841 match SHELLCODE_REGISTRY.lock().remove(&address) {
842 Some(loaded) => {
843 loaded.free();
847 MEM_OK
848 }
849 None => MEM_ERR_NOT_FOUND,
850 }
851}