1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
use crate::emu;
use crate::emu::object_handle::file_handle::INVALID_HANDLE_VALUE;
pub fn ReadFile(emu: &mut emu::Emu) {
let h_file = emu.regs().rcx as usize; // Handle to the file
let lp_buffer = emu.regs().rdx; // Buffer to receive dat
let n_number_of_bytes_to_read = emu.regs().r8 as u32; // Number of bytes to read
let lp_number_of_bytes_read = emu.regs().r9; // Pointer to store bytes read
let lp_overlapped = emu
.maps
.read_qword(emu.regs().rsp + 0x20)
.expect("kernel32!ReadFile cannot read the overlapped");
log_red!(emu, "** {} kernel32!ReadFile hFile: 0x{:x} lpBuffer: 0x{:x} nNumberOfBytesToRead: {} lpNumberOfBytesRead: 0x{:x} lpOverlapped: 0x{:x}",
emu.pos, h_file, lp_buffer, n_number_of_bytes_to_read, lp_number_of_bytes_read, lp_overlapped);
// Check if handle is valid (not INVALID_HANDLE_VALUE)
if h_file == INVALID_HANDLE_VALUE {
log_red!(
emu,
"** {} kernel32!ReadFile ERROR: Invalid handle (INVALID_HANDLE_VALUE)",
emu.pos
);
emu.last_error = 6; // ERROR_INVALID_HANDLE
emu.regs_mut().rax = 0; // FALSE
return;
}
// Get the file handle from the handle management system
let file_handle_ref = match emu.handle_management.get_mut_file_handle(h_file as u32) {
Some(fh) => fh,
None => {
log_red!(
emu,
"** {} kernel32!ReadFile ERROR: Handle 0x{:x} not found in handle table",
emu.pos,
h_file
);
emu.last_error = 6; // ERROR_INVALID_HANDLE
emu.regs_mut().rax = 0; // FALSE
return;
}
};
// Check if the handle is valid and not a directory
if !file_handle_ref.is_valid() {
log_red!(
emu,
"** {} kernel32!ReadFile ERROR: Handle 0x{:x} is invalid",
emu.pos,
h_file
);
emu.last_error = 6; // ERROR_INVALID_HANDLE
emu.regs_mut().rax = 0; // FALSE
return;
}
if file_handle_ref.is_dir() {
log_red!(
emu,
"** {} kernel32!ReadFile ERROR: Cannot read from directory handle",
emu.pos
);
emu.last_error = 87; // ERROR_INVALID_PARAMETER
emu.regs_mut().rax = 0; // FALSE
return;
}
// Check if buffer pointer is valid
if lp_buffer == 0 && n_number_of_bytes_to_read > 0 {
log_red!(
emu,
"** {} kernel32!ReadFile ERROR: Invalid buffer pointer",
emu.pos
);
emu.last_error = 87; // ERROR_INVALID_PARAMETER
emu.regs_mut().rax = 0; // FALSE
return;
}
// Prepare buffer for reading
let mut buffer = vec![0u8; n_number_of_bytes_to_read as usize];
// Read from the file handle
let bytes_read_result = file_handle_ref.read(&mut buffer);
let bytes_read = match bytes_read_result {
Ok(bytes) => {
log_red!(
emu,
"** {} kernel32!ReadFile SUCCESS: Read {} bytes",
emu.pos,
bytes
);
// Write the data back to the emulator's memory
if bytes > 0 {
if !emu.maps.write_bytes(lp_buffer, &buffer) {
log_red!(
emu,
"** {} kernel32!ReadFile ERROR: Failed to write data to buffer at 0x{:x}",
emu.pos,
lp_buffer
);
emu.last_error = 14; // ERROR_OUTOFMEMORY
emu.regs_mut().rax = 0; // FALSE
return;
}
}
bytes
}
Err(e) => {
let error_code = match e.kind() {
std::io::ErrorKind::NotFound => 2, // ERROR_FILE_NOT_FOUND
std::io::ErrorKind::PermissionDenied => 5, // ERROR_ACCESS_DENIED
std::io::ErrorKind::InvalidInput => 87, // ERROR_INVALID_PARAMETER
std::io::ErrorKind::UnexpectedEof => 0, // EOF - not an error
_ => 1, // ERROR_INVALID_FUNCTION
};
log_red!(
emu,
"** {} kernel32!ReadFile ERROR: Read failed - {}",
emu.pos,
e
);
emu.last_error = error_code;
// If it's EOF, we still return success but with 0 bytes read
if e.kind() == std::io::ErrorKind::UnexpectedEof {
0
} else {
emu.regs_mut().rax = 0; // FALSE
return;
}
}
};
// Write the number of bytes read to the output parameter
if lp_number_of_bytes_read != 0 {
if !emu
.maps
.write_dword(lp_number_of_bytes_read, bytes_read as u32)
{
log_red!(
emu,
"** {} kernel32!ReadFile ERROR: Failed to write bytes read count to 0x{:x}",
emu.pos,
lp_number_of_bytes_read
);
emu.last_error = 14; // ERROR_OUTOFMEMORY
emu.regs_mut().rax = 0; // FALSE
return;
}
}
// Success!
emu.last_error = 0; // NO_ERROR
emu.regs_mut().rax = 1; // TRUE
}