(order: &Order, folder: &Path)
| 239 | } |
| 240 | |
| 241 | fn apply_proxy(order: &Order, folder: &Path) { |
| 242 | let proxy_path = order.proxy_dll.as_ref().unwrap(); |
| 243 | let exports = pe_parser::parse_exports(proxy_path).unwrap_or_else(|e| { |
| 244 | eprintln!("[-] Failed to parse proxy DLL exports: {}", e); |
| 245 | exit(1); |
| 246 | }); |
| 247 | |
| 248 | if exports.is_empty() { |
| 249 | eprintln!("[-] Warning: proxy DLL has no exports"); |
| 250 | } |
| 251 | |
| 252 | let stem = pe_parser::dll_stem(proxy_path); |
| 253 | let proxy_output = dll_proxy::generate_proxy(&exports, &stem); |
| 254 | |
| 255 | let src_dir = folder.join("src"); |
| 256 | fs::write(src_dir.join("proxy.rs"), &proxy_output.proxy_source) |
| 257 | .expect("Failed to write proxy.rs"); |
| 258 | |
| 259 | let lib_rs_path = src_dir.join("lib.rs"); |
| 260 | let existing = fs::read_to_string(&lib_rs_path).expect("Failed to read lib.rs"); |
| 261 | |
| 262 | // Insert `mod proxy;` after inner attributes (#![...]) to avoid breaking them |
| 263 | let mut inner_attr_end = 0; |
| 264 | for line in existing.lines() { |
| 265 | let trimmed = line.trim(); |
| 266 | if trimmed.starts_with("#!") || trimmed.is_empty() { |
| 267 | inner_attr_end += line.len() + 1; // +1 for newline |
| 268 | } else { |
| 269 | break; |
| 270 | } |
| 271 | } |
| 272 | let updated = format!( |
| 273 | "{}\n#[allow(non_upper_case_globals, non_snake_case)]\nmod proxy;\n{}", |
| 274 | &existing[..inner_attr_end.min(existing.len())].trim_end(), |
| 275 | &existing[inner_attr_end.min(existing.len())..] |
| 276 | ); |
| 277 | fs::write(&lib_rs_path, updated).expect("Failed to update lib.rs with mod proxy"); |
| 278 | |
| 279 | println!( |
| 280 | "[+] DLL proxying: {} exports forwarded. Rename the original DLL to '{}'", |
| 281 | exports.len(), |
| 282 | proxy_output.original_dll_name |
| 283 | ); |
| 284 | } |
| 285 | |
| 286 | pub fn assemble(order: Order) -> PathBuf { |
| 287 | println!("[+] Assembling Rust code.."); |
no test coverage detected