utils_nostd/
lib.rs

1#![no_std]
2#![no_main]
3
4extern crate alloc;
5
6#[macro_use]
7extern crate litcrypt2;
8use_litcrypt!();
9
10use alloc::vec::Vec;
11use data_nostd::{CloseHandle, CreateFileW, GetProcessHeap, GetStdHandle, HeapAlloc, HeapFree, ReadFile, WriteConsoleW, FILE_ATTRIBUTE_NORMAL, FILE_GENERIC_READ, HANDLE, HEAP_ZERO_MEMORY, OPEN_EXISTING, STD_OUTPUT_HANDLE};
12use core::ptr::{self, copy_nonoverlapping, null_mut};
13use core::ffi::c_void;
14use alloc::string::String;
15
16
17/// Reads the contents of a file.
18///
19/// # Examples
20///
21/// ```
22/// let file_content = utils::read_file(r"c:\windows\system32\ntdll.dll")?;
23/// ```
24pub fn read_file(file_path: &str) -> Result<Vec<u8>, String> 
25{
26    unsafe 
27    {
28        let mut file_path: Vec<u16> = file_path.encode_utf16().collect();
29        file_path.push(0);
30    
31        let handle: HANDLE = CreateFileW(
32            file_path.as_mut_ptr(),
33            FILE_GENERIC_READ,
34            0,
35            null_mut(),
36            OPEN_EXISTING,
37            FILE_ATTRIBUTE_NORMAL,
38            HANDLE::default(),
39        );
40    
41        if handle.id == -1 {
42            return Err(lc!("[x] Error opening the file."));
43        }
44    
45        let mut buffer_size: usize = 4096;
46        let process_heap = GetProcessHeap();
47        let mut file_buffer = HeapAlloc(process_heap, HEAP_ZERO_MEMORY, buffer_size);
48    
49        if file_buffer.is_null() 
50        {
51            CloseHandle(handle);
52            return Err(lc!("[x] Heap allocation failed"));
53        }
54    
55        let mut bytes_read: u32 = 0;
56        let mut total_bytes_read: usize = 0;
57    
58        loop 
59        {
60            let result = ReadFile(
61                handle,
62                file_buffer.add(total_bytes_read),
63                4096,
64                &mut bytes_read,
65                null_mut(),
66            );
67    
68            if result && bytes_read > 0 
69            {
70                total_bytes_read += bytes_read as usize;
71    
72                if total_bytes_read + 4096 > buffer_size 
73                {
74                    let new_buffer_size = buffer_size * 2;
75                    let new_file_buffer = HeapAlloc(process_heap, HEAP_ZERO_MEMORY, new_buffer_size);
76    
77                    if new_file_buffer.is_null() 
78                    {
79                        HeapFree(process_heap, 0, file_buffer as *mut c_void); 
80                        CloseHandle(handle);
81                        return Err(lc!("[x] Heap allocation failed"));
82                    }
83    
84                    copy_nonoverlapping(file_buffer as *mut u8, new_file_buffer as *mut u8, total_bytes_read);
85    
86                    HeapFree(process_heap, 0, file_buffer);
87                    file_buffer = new_file_buffer;
88                    buffer_size = new_buffer_size;
89                }
90
91            } else {
92                break;
93            }
94        }
95    
96        CloseHandle(handle);
97    
98        if total_bytes_read == 0 {
99            return Err(lc!("[x] Error reading the file."));
100        }
101        
102        let new_file_buffer = HeapAlloc(process_heap, HEAP_ZERO_MEMORY, total_bytes_read);
103
104        if new_file_buffer.is_null() {
105            return Ok(Vec::from_raw_parts(file_buffer as *mut u8, total_bytes_read, total_bytes_read));
106        }
107
108        copy_nonoverlapping(file_buffer as *mut u8, new_file_buffer as *mut u8, total_bytes_read);
109        HeapFree(process_heap, 0, file_buffer);
110        
111        Ok(Vec::from_raw_parts(new_file_buffer as *mut u8, total_bytes_read, total_bytes_read))
112    }
113}
114
115
116/// This macro tries to reproduce the behavior of `std::println!()`.
117/// 
118/// The following lines should be added to use this macro:
119/// ```
120/// extern crate alloc;
121/// use core::fmt::Write;
122/// ```
123///
124/// # Examples
125///
126/// ```
127/// extern crate alloc;
128///
129/// utils::println!("Hello world!");
130/// utils::println!("Print hex value: {:x}", 2907isize);
131/// utils::println!("{}{}", "Concat", "Strings");
132/// ```
133#[macro_export]
134macro_rules!println {
135    ($($arg:tt)*) => {
136        let mut string = String::new();
137        let _ = write!(string, $($arg)*);  
138        let _ = write!(string, "\n");  
139        let mut utf16: alloc::vec::Vec<u16> = string.encode_utf16().collect();  
140        utf16.push(0);
141
142        $crate::print_string(utf16);
143    };
144}
145
146/// This function is not meant to be called directly, instead use `utils::println!()` macro.
147pub fn print_string(utf16_str: Vec<u16>) {
148    unsafe {
149        let h_stdout = GetStdHandle(STD_OUTPUT_HANDLE);
150        if !h_stdout.is_null() {
151            WriteConsoleW(
152                h_stdout,
153                utf16_str.as_ptr(),
154                utf16_str.len() as u32,
155                ptr::null_mut(),
156                ptr::null_mut(),
157            );
158        }
159    } 
160}