Skip to content

Commit ddcc853

Browse files
committed
Adding support for some API
1 parent aaa9d0b commit ddcc853

File tree

6 files changed

+292
-1
lines changed

6 files changed

+292
-1
lines changed

crates/libmwemu/src/winapi/winapi32/kernel32/mod.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -345,6 +345,7 @@ pub use wide_char_to_multi_byte::*;
345345
pub use win_exec::*;
346346
pub use write_file::*;
347347
pub use write_process_memory::*;
348+
use crate::emu::Emu;
348349

349350
pub fn gateway(addr: u32, emu: &mut emu::Emu) -> String {
350351
let api = guess_api_name(emu, addr);
@@ -390,6 +391,7 @@ pub fn gateway(addr: u32, emu: &mut emu::Emu) -> String {
390391
"FreeLibrary" => FreeLibrary(emu),
391392
"FreeResource" => FreeResource(emu),
392393
"GetACP" => GetACP(emu),
394+
"GetThreadId" => GetThreadId(emu),
393395
"GetCommandLineA" => GetCommandLineA(emu),
394396
"GetCommandLineW" => GetCommandLineW(emu),
395397
"GetComputerNameA" => GetComputerNameA(emu),
@@ -545,6 +547,11 @@ pub fn gateway(addr: u32, emu: &mut emu::Emu) -> String {
545547
String::new()
546548
}
547549

550+
fn GetThreadId(emu: &mut Emu) {
551+
emu.stack_pop32(false);
552+
emu.regs_mut().rax = 0x2c2878;
553+
}
554+
548555
lazy_static! {
549556
static ref COUNT_READ: Mutex<u32> = Mutex::new(0);
550557
static ref COUNT_WRITE: Mutex<u32> = Mutex::new(0);

crates/libmwemu/src/winapi/winapi32/ntdll.rs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ use crate::winapi::winapi32::kernel32;
99

1010
use crate::maps::mem64::Permission;
1111
use scan_fmt::scan_fmt_some;
12+
use crate::emu::Emu;
13+
use crate::winapi::winapi64::kernel32::InitializeCriticalSection;
1214

1315
const PAGE_NOACCESS: u32 = 0x01;
1416
const PAGE_READONLY: u32 = 0x02;
@@ -36,6 +38,8 @@ pub fn gateway(addr: u32, emu: &mut emu::Emu) -> String {
3638
"NtQueryPerformanceCounter" => NtQueryPerformanceCounter(emu),
3739
"RtlGetProcessHeaps" => RtlGetProcessHeaps(emu),
3840
"RtlDosPathNameToNtPathName_U" => RtlDosPathNameToNtPathName_U(emu),
41+
"RtlInitializeCriticalSection" => InitializeCriticalSection(emu),
42+
"RtlZeroMemory" => RtlZeroMemory(emu),
3943
"NtCreateFile" => NtCreateFile(emu),
4044
"RtlFreeHeap" => RtlFreeHeap(emu),
4145
"NtQueryInformationFile" => NtQueryInformationFile(emu),
@@ -80,6 +84,26 @@ pub fn gateway(addr: u32, emu: &mut emu::Emu) -> String {
8084
String::new()
8185
}
8286

87+
fn RtlZeroMemory(emu: &mut Emu) {
88+
let dest = emu
89+
.maps
90+
.read_dword(emu.regs().get_esp() + 4)
91+
.expect("bad RtlZeroMemory address pointer parameter") as u64;
92+
let length = emu
93+
.maps
94+
.read_dword(emu.regs().get_esp() + 8)
95+
.expect("bad RtlZeroMemory address length parameter") as u64;
96+
97+
log_red!(
98+
emu,
99+
"ntdll!RtlZeroMemory dest: 0x{:x} length: {}",
100+
dest,
101+
length
102+
);
103+
104+
emu.maps.memset(dest, 0, length as usize);
105+
}
106+
83107
fn NtAllocateVirtualMemory(emu: &mut emu::Emu) {
84108
/*
85109
__kernel_entry NTSYSCALLAPI NTSTATUS NtAllocateVirtualMemory(

crates/libmwemu/src/winapi/winapi32/ws2_32.rs

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,119 @@ lazy_static! {
6363
static ref COUNT_RECV: Mutex<u32> = Mutex::new(0);
6464
}
6565

66+
fn getaddrinfo(emu: &mut emu::Emu) {
67+
let node_name_ptr = emu
68+
.maps
69+
.read_dword(emu.regs().get_esp() + 4)
70+
.expect("ws2_32!getaddrinfo cannot read node_name_ptr");
71+
let service_name_ptr = emu
72+
.maps
73+
.read_dword(emu.regs().get_esp() + 8)
74+
.expect("ws2_32!getaddrinfo cannot read service_name_ptr");
75+
let hints_ptr = emu
76+
.maps
77+
.read_dword(emu.regs().get_esp() + 12)
78+
.expect("ws2_32!getaddrinfo cannot read hints_ptr");
79+
let result_ptr_ptr = emu
80+
.maps
81+
.read_dword(emu.regs().get_esp() + 16)
82+
.expect("ws2_32!getaddrinfo cannot read result_ptr_ptr");
83+
84+
let node_name = if node_name_ptr != 0 {
85+
emu.maps.read_string(node_name_ptr)
86+
} else {
87+
"NULL".to_string()
88+
};
89+
90+
let service_name = if service_name_ptr != 0 {
91+
emu.maps.read_string(service_name_ptr)
92+
} else {
93+
"NULL".to_string()
94+
};
95+
96+
log_red!(emu, "ws2_32!getaddrinfo node: `{}` service: `{}`", node_name, service_name);
97+
98+
// Read hints if provided
99+
let mut hints_flags = 0;
100+
let mut hints_family = 0;
101+
let mut hints_socktype = 0;
102+
let mut hints_protocol = 0;
103+
104+
if hints_ptr != 0 {
105+
hints_flags = emu.maps.read_dword(hints_ptr).unwrap_or(0) as i32;
106+
hints_family = emu.maps.read_dword(hints_ptr + 4).unwrap_or(0) as i32;
107+
hints_socktype = emu.maps.read_dword(hints_ptr + 8).unwrap_or(0) as i32;
108+
hints_protocol = emu.maps.read_dword(hints_ptr + 12).unwrap_or(0) as i32;
109+
}
110+
111+
// Create a dummy ADDRINFO structure
112+
let addrinfo_size = 48; // Size of ADDRINFOA structure (approximate)
113+
let sockaddr_in_size = 16; // Size of sockaddr_in structure
114+
115+
// Allocate memory for the result
116+
let heap_management = emu.heap_management.as_mut().unwrap();
117+
let addrinfo_addr = heap_management.allocate((addrinfo_size + sockaddr_in_size + 100) as usize).unwrap();
118+
let sockaddr_addr = addrinfo_addr + addrinfo_size;
119+
let canonname_addr = sockaddr_addr + sockaddr_in_size;
120+
121+
// Create a dummy sockaddr_in (IPv4 address 127.0.0.1, port based on service)
122+
let ip_addr = 0x0100007f; // 127.0.0.1 in network byte order
123+
124+
// Determine port based on service name
125+
let port = if service_name == "http" || service_name == "80" {
126+
80u16
127+
} else if service_name == "https" || service_name == "443" {
128+
443u16
129+
} else if service_name == "ftp" || service_name == "21" {
130+
21u16
131+
} else if service_name == "ssh" || service_name == "22" {
132+
22u16
133+
} else if service_name == "smtp" || service_name == "25" {
134+
25u16
135+
} else if service_name == "dns" || service_name == "53" {
136+
53u16
137+
} else {
138+
service_name.parse().unwrap_or(80u16)
139+
};
140+
141+
// Write sockaddr_in structure
142+
emu.maps.write_word(sockaddr_addr, 2); // AF_INET = 2
143+
emu.maps.write_word(sockaddr_addr + 2, port.to_be()); // Port in network byte order
144+
emu.maps.write_dword(sockaddr_addr + 4, ip_addr); // IP address (127.0.0.1)
145+
emu.maps.memset(sockaddr_addr + 8, 0, 8); // Zero out the rest
146+
147+
// Write ADDRINFO structure
148+
emu.maps.write_dword(addrinfo_addr, hints_flags as u32); // ai_flags
149+
emu.maps.write_dword(addrinfo_addr + 4, if hints_family != 0 { hints_family as u32 } else { 2 }); // ai_family (AF_INET)
150+
emu.maps.write_dword(addrinfo_addr + 8, if hints_socktype != 0 { hints_socktype as u32 } else { 1 }); // ai_socktype (SOCK_STREAM)
151+
emu.maps.write_dword(addrinfo_addr + 12, if hints_protocol != 0 { hints_protocol as u32 } else { 6 }); // ai_protocol (IPPROTO_TCP)
152+
emu.maps.write_qword(addrinfo_addr + 16, sockaddr_in_size as u64); // ai_addrlen
153+
emu.maps.write_qword(addrinfo_addr + 24, canonname_addr); // ai_canonname
154+
emu.maps.write_qword(addrinfo_addr + 32, sockaddr_addr); // ai_addr
155+
156+
// Set ai_canonname to the node name or "localhost"
157+
let canon_name = if node_name == "NULL" || node_name.is_empty() || node_name == "localhost" {
158+
"localhost.localdomain".to_string()
159+
} else if node_name == "127.0.0.1" {
160+
"localhost".to_string()
161+
} else {
162+
format!("{}.localdomain", node_name)
163+
};
164+
emu.maps.write_string(canonname_addr, &canon_name);
165+
166+
// ai_next is NULL (end of list)
167+
emu.maps.write_qword(addrinfo_addr + 40, 0);
168+
169+
// Store the result pointer in the ppResult parameter
170+
emu.maps.write_qword(result_ptr_ptr, addrinfo_addr);
171+
172+
log::info!("\tcreated dummy ADDRINFO for {}:{} at 0x{:x}", node_name, service_name, addrinfo_addr);
173+
log::info!("\tsockaddr at 0x{:x}, canonname at 0x{:x}", sockaddr_addr, canonname_addr);
174+
175+
// Return 0 for success (WSA error code)
176+
emu.regs_mut().rax = 0;
177+
}
178+
66179
fn WsaStartup(emu: &mut emu::Emu) {
67180
log_red!(emu, "ws2_32!WsaStartup");
68181

crates/libmwemu/src/winapi/winapi64/kernel32/mod.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -354,7 +354,7 @@ pub use write_console_w::WriteConsoleW;
354354
pub use write_file::WriteFile;
355355
pub use write_process_memory::WriteProcessMemory;
356356
pub use local_free::LocalFree;
357-
357+
use crate::emu::Emu;
358358
// a in RCX, b in RDX, c in R8, d in R9, then e pushed on stack
359359

360360
pub fn clear_last_error(emu: &mut emu::Emu) {
@@ -447,6 +447,7 @@ pub fn gateway(addr: u64, emu: &mut emu::Emu) -> String {
447447
"GetStartupInfoA" => GetStartupInfoA(emu),
448448
"GetStartupInfoW" => GetStartupInfoW(emu),
449449
"GetStdHandle" => GetStdHandle(emu),
450+
"GetThreadId" => GetThreadId(emu),
450451
"GetSystemDirectoryA" => GetSystemDirectoryA(emu),
451452
"GetSystemDirectoryW" => GetSystemDirectoryW(emu),
452453
"GetSystemFirmwareTable" => GetSystemFirmwareTable(emu),
@@ -563,6 +564,11 @@ pub fn gateway(addr: u64, emu: &mut emu::Emu) -> String {
563564
String::new()
564565
}
565566

567+
fn GetThreadId(emu: &mut Emu) {
568+
let hThread = emu.regs().rcx;
569+
emu.regs_mut().rax = 0x2c2878;
570+
}
571+
566572
lazy_static! {
567573
pub static ref COUNT_READ: Mutex<u32> = Mutex::new(0);
568574
pub static ref COUNT_WRITE: Mutex<u32> = Mutex::new(0);

crates/libmwemu/src/winapi/winapi64/ntdll.rs

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,13 @@ use crate::console::Console;
77
use crate::constants;
88
use crate::context::context64::Context64;
99
use crate::emu;
10+
use crate::emu::Emu;
1011
use crate::maps::mem64::Permission;
1112
use crate::serialization;
1213
use crate::structures;
1314
use crate::winapi::helper;
1415
use crate::winapi::winapi64::kernel32;
16+
use crate::winapi::winapi64::kernel32::InitializeCriticalSection;
1517

1618
const PAGE_NOACCESS: u32 = 0x01;
1719
const PAGE_READONLY: u32 = 0x02;
@@ -44,6 +46,7 @@ pub fn gateway(addr: u64, emu: &mut emu::Emu) -> String {
4446
"NtQueryPerformanceCounter" => NtQueryPerformanceCounter(emu),
4547
"RtlGetProcessHeaps" => RtlGetProcessHeaps(emu),
4648
"RtlDosPathNameToNtPathName_U" => RtlDosPathNameToNtPathName_U(emu),
49+
"RtlInitializeCriticalSection" => InitializeCriticalSection(emu),
4750
"NtCreateFile" => NtCreateFile(emu),
4851
"RtlFreeHeap" => RtlFreeHeap(emu),
4952
"NtQueryInformationFile" => NtQueryInformationFile(emu),
@@ -65,6 +68,8 @@ pub fn gateway(addr: u64, emu: &mut emu::Emu) -> String {
6568
"NtTerminateThread" => NtTerminateThread(emu),
6669
"RtlAddFunctionTable" => RtlAddFunctionTable(emu),
6770
"RtlCaptureContext" => RtlCaptureContext(emu),
71+
"RtlMoveMemory" => RtlMoveMemory(emu),
72+
"RtlZeroMemory" => RtlZeroMemory(emu),
6873
"RtlLookupFunctionEntry" => RtlLookupFunctionEntry(emu),
6974
"strlen" => strlen(emu),
7075
"NtSetInformationThread" => NtSetInformationThread(emu),
@@ -91,6 +96,40 @@ pub fn gateway(addr: u64, emu: &mut emu::Emu) -> String {
9196

9297
String::new()
9398
}
99+
fn RtlZeroMemory(emu: &mut emu::Emu) {
100+
let dest = emu.regs().rcx;
101+
let length = emu.regs().rdx;
102+
103+
log_red!(
104+
emu,
105+
"ntdll!RtlZeroMemory dest: 0x{:x} length: {}",
106+
dest,
107+
length
108+
);
109+
110+
emu.maps.memset(dest, 0, length as usize);
111+
}
112+
113+
114+
fn RtlMoveMemory(emu: &mut emu::Emu) {
115+
let dst = emu.regs().rcx;
116+
let src = emu.regs().rdx;
117+
let sz = emu.regs().r8 as usize;
118+
119+
let result = emu.maps.memcpy(dst, src, sz);
120+
if result == false {
121+
panic!("RtlMoveMemory failed to copy");
122+
}
123+
124+
log_red!(
125+
emu,
126+
"** {} ntdll!RtlMoveMemory dst = {:x} src = {:x} sz = {}",
127+
emu.pos,
128+
dst,
129+
src,
130+
sz
131+
);
132+
}
94133

95134
fn NtAllocateVirtualMemory(emu: &mut emu::Emu) {
96135
/*

0 commit comments

Comments
 (0)