Skip to content

Commit 561d7d1

Browse files
committed
getaddrinfo and other important winapi implemented
1 parent fd1a30f commit 561d7d1

File tree

10 files changed

+468
-4
lines changed

10 files changed

+468
-4
lines changed

crates/libmwemu/src/regs64.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -614,6 +614,10 @@ impl Regs64 {
614614
self.rip &= mask;
615615
}
616616

617+
pub fn sanitize64(&mut self) {
618+
// nothing to do
619+
}
620+
617621
pub fn print<const B: usize>(&self) {
618622
log::info!("regs:");
619623

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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,9 @@ mod mscoree;
99
mod msvcrt;
1010
mod ntdll;
1111
mod oleaut32;
12+
mod shell32;
1213
mod shlwapi;
14+
mod urlmon;
1315
mod user32;
1416
mod wincrt;
1517
mod wininet;
@@ -32,7 +34,9 @@ pub fn gateway(addr: u32, name: &str, emu: &mut emu::Emu) {
3234
"dnsapi.text" => dnsapi::gateway(addr, emu),
3335
"mscoree.text" => mscoree::gateway(addr, emu),
3436
"msvcrt.text" => msvcrt::gateway(addr, emu),
37+
"shell32.text" => shell32::gateway(addr, emu),
3538
"shlwapi.text" => shlwapi::gateway(addr, emu),
39+
"urlmon.text" => urlmon::gateway(addr, emu),
3640
"oleaut32.text" => oleaut32::gateway(addr, emu),
3741
"kernelbase.text" => kernelbase::gateway(addr, emu),
3842
"iphlpapi.text" => iphlpapi::gateway(addr, emu),
Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
use crate::emu;
2+
use crate::serialization;
3+
use crate::winapi::winapi32::kernel32;
4+
5+
pub fn gateway(addr: u32, emu: &mut emu::Emu) -> String {
6+
let api = kernel32::guess_api_name(emu, addr);
7+
match api.as_str() {
8+
"ShellExecuteA" => ShellExecuteA(emu),
9+
"ShellExecuteW" => ShellExecuteW(emu),
10+
_ => {
11+
if emu.cfg.skip_unimplemented == false {
12+
if emu.cfg.dump_on_exit && emu.cfg.dump_filename.is_some() {
13+
serialization::Serialization::dump_to_file(
14+
&emu,
15+
emu.cfg.dump_filename.as_ref().unwrap(),
16+
);
17+
}
18+
19+
unimplemented!("atemmpt to call unimplemented API 0x{:x} {}", addr, api);
20+
}
21+
log::warn!(
22+
"calling unimplemented API 0x{:x} {} at 0x{:x}",
23+
addr,
24+
api,
25+
emu.regs().rip
26+
);
27+
return api;
28+
}
29+
}
30+
31+
String::new()
32+
}
33+
34+
fn ShellExecuteA(emu: &mut emu::Emu) {
35+
let hwnd = emu
36+
.maps
37+
.read_dword(emu.regs().get_esp())
38+
.expect("shell32!ShellExecuteA error reading hwnd") as u64;
39+
let lp_operation = emu
40+
.maps
41+
.read_dword(emu.regs().get_esp() + 4)
42+
.expect("shell32!ShellExecuteA error reading lp_operation") as u64;
43+
let lp_file = emu
44+
.maps
45+
.read_dword(emu.regs().get_esp() + 8)
46+
.expect("shell32!ShellExecuteA error reading lp_file") as u64;
47+
let lp_parameters = emu
48+
.maps
49+
.read_dword(emu.regs().get_esp() + 12)
50+
.expect("shell32!ShellExecuteA error reading lp_parameters") as u64;
51+
let lp_directory = emu
52+
.maps
53+
.read_dword(emu.regs().get_esp() + 16)
54+
.expect("shell32!ShellExecuteA error reading lp_directory") as u64;
55+
let n_show_cmd = emu
56+
.maps
57+
.read_dword(emu.regs().get_esp() + 20)
58+
.expect("shell32!ShellExecuteA error reading n_show_cmd") as u64;
59+
60+
let operation = if lp_operation != 0 {
61+
emu.maps.read_string(lp_operation)
62+
} else {
63+
"open".to_string()
64+
};
65+
let file = emu.maps.read_string(lp_file);
66+
let params = if lp_parameters != 0 {
67+
emu.maps.read_string(lp_parameters)
68+
} else {
69+
"".to_string()
70+
};
71+
72+
log_red!(
73+
emu,
74+
"shell32!ShellExecuteA op: {} file: {} params: {}",
75+
operation,
76+
file,
77+
params
78+
);
79+
80+
for _ in 0..6 {
81+
emu.stack_pop32(false);
82+
}
83+
84+
emu.regs_mut().rax = 42; // > 32 means success
85+
}
86+
87+
fn ShellExecuteW(emu: &mut emu::Emu) {
88+
let hwnd = emu
89+
.maps
90+
.read_dword(emu.regs().get_esp())
91+
.expect("shell32!ShellExecuteW error reading hwnd") as u64;
92+
let lp_operation = emu
93+
.maps
94+
.read_dword(emu.regs().get_esp() + 4)
95+
.expect("shell32!ShellExecuteW error reading lp_operation") as u64;
96+
let lp_file = emu
97+
.maps
98+
.read_dword(emu.regs().get_esp() + 8)
99+
.expect("shell32!ShellExecuteW error reading lp_file") as u64;
100+
let lp_parameters = emu
101+
.maps
102+
.read_dword(emu.regs().get_esp() + 12)
103+
.expect("shell32!ShellExecuteW error reading lp_parameters") as u64;
104+
let lp_directory = emu
105+
.maps
106+
.read_dword(emu.regs().get_esp() + 16)
107+
.expect("shell32!ShellExecuteW error reading lp_directory") as u64;
108+
let n_show_cmd = emu
109+
.maps
110+
.read_dword(emu.regs().get_esp() + 20)
111+
.expect("shell32!ShellExecuteW error reading n_show_cmd") as u64;
112+
113+
let operation = if lp_operation != 0 {
114+
emu.maps.read_wide_string(lp_operation)
115+
} else {
116+
"open".to_string()
117+
};
118+
let file = emu.maps.read_wide_string(lp_file);
119+
let params = if lp_parameters != 0 {
120+
emu.maps.read_wide_string(lp_parameters)
121+
} else {
122+
"".to_string()
123+
};
124+
125+
log_red!(
126+
emu,
127+
"shell32!ShellExecuteW op: {} file: {} params: {}",
128+
operation,
129+
file,
130+
params
131+
);
132+
133+
for _ in 0..6 {
134+
emu.stack_pop32(false);
135+
}
136+
137+
emu.regs_mut().rax = 42; // > 32 means success
138+
}

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

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ use crate::winapi::winapi32::kernel32;
77
pub fn gateway(addr: u32, emu: &mut emu::Emu) -> String {
88
let api = kernel32::guess_api_name(emu, addr);
99
match api.as_str() {
10+
"PathFileExistsA" => PathFileExistsA(emu),
11+
"PathFileExistsW" => PathFileExistsW(emu),
1012
_ => {
1113
if emu.cfg.skip_unimplemented == false {
1214
if emu.cfg.dump_on_exit && emu.cfg.dump_filename.is_some() {
@@ -27,4 +29,34 @@ pub fn gateway(addr: u32, emu: &mut emu::Emu) -> String {
2729
return api;
2830
}
2931
}
32+
33+
String::new()
34+
}
35+
36+
fn PathFileExistsA(emu: &mut emu::Emu) {
37+
let ptr_path = emu
38+
.maps
39+
.read_dword(emu.regs().get_esp())
40+
.expect("shlwapi!PathFileExistsA error reading path") as u64;
41+
42+
let path = emu.maps.read_string(ptr_path);
43+
44+
log_red!(emu, "shlwapi!PathFileExistsA path: {}", path);
45+
46+
emu.stack_pop32(false);
47+
emu.regs_mut().rax = 1; // True
48+
}
49+
50+
fn PathFileExistsW(emu: &mut emu::Emu) {
51+
let ptr_path = emu
52+
.maps
53+
.read_dword(emu.regs().get_esp())
54+
.expect("shlwapi!PathFileExistsW error reading path") as u64;
55+
56+
let path = emu.maps.read_wide_string(ptr_path);
57+
58+
log_red!(emu, "shlwapi!PathFileExistsW path: {}", path);
59+
60+
emu.stack_pop32(false);
61+
emu.regs_mut().rax = 1; // True
3062
}
Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
use crate::emu;
2+
use crate::serialization;
3+
use crate::winapi::winapi32::kernel32;
4+
5+
pub fn gateway(addr: u32, emu: &mut emu::Emu) -> String {
6+
let api = kernel32::guess_api_name(emu, addr);
7+
match api.as_str() {
8+
"URLDownloadToFileA" => URLDownloadToFileA(emu),
9+
"URLDownloadToFileW" => URLDownloadToFileW(emu),
10+
_ => {
11+
if emu.cfg.skip_unimplemented == false {
12+
if emu.cfg.dump_on_exit && emu.cfg.dump_filename.is_some() {
13+
serialization::Serialization::dump_to_file(
14+
&emu,
15+
emu.cfg.dump_filename.as_ref().unwrap(),
16+
);
17+
}
18+
19+
unimplemented!("atemmpt to call unimplemented API 0x{:x} {}", addr, api);
20+
}
21+
log::warn!(
22+
"calling unimplemented API 0x{:x} {} at 0x{:x}",
23+
addr,
24+
api,
25+
emu.regs().rip
26+
);
27+
return api;
28+
}
29+
}
30+
31+
String::new()
32+
}
33+
34+
fn URLDownloadToFileA(emu: &mut emu::Emu) {
35+
let pcaller = emu
36+
.maps
37+
.read_dword(emu.regs().get_esp())
38+
.expect("urlmon!URLDownloadToFileA error reading pcaller") as u64;
39+
let sz_url = emu
40+
.maps
41+
.read_dword(emu.regs().get_esp() + 4)
42+
.expect("urlmon!URLDownloadToFileA error reading sz_url") as u64;
43+
let sz_filename = emu
44+
.maps
45+
.read_dword(emu.regs().get_esp() + 8)
46+
.expect("urlmon!URLDownloadToFileA error reading sz_filename") as u64;
47+
let dw_reserved = emu
48+
.maps
49+
.read_dword(emu.regs().get_esp() + 12)
50+
.expect("urlmon!URLDownloadToFileA error reading dw_reserved") as u64;
51+
let lpfn_cb = emu
52+
.maps
53+
.read_dword(emu.regs().get_esp() + 16)
54+
.expect("urlmon!URLDownloadToFileA error reading lpfn_cb") as u64;
55+
56+
let url = emu.maps.read_string(sz_url);
57+
let filename = emu.maps.read_string(sz_filename);
58+
59+
log_red!(
60+
emu,
61+
"urlmon!URLDownloadToFileA url: {} filename: {}",
62+
url,
63+
filename
64+
);
65+
66+
for _ in 0..5 {
67+
emu.stack_pop32(false);
68+
}
69+
70+
emu.regs_mut().rax = 0; // S_OK
71+
}
72+
73+
fn URLDownloadToFileW(emu: &mut emu::Emu) {
74+
let pcaller = emu
75+
.maps
76+
.read_dword(emu.regs().get_esp())
77+
.expect("urlmon!URLDownloadToFileW error reading pcaller") as u64;
78+
let sz_url = emu
79+
.maps
80+
.read_dword(emu.regs().get_esp() + 4)
81+
.expect("urlmon!URLDownloadToFileW error reading sz_url") as u64;
82+
let sz_filename = emu
83+
.maps
84+
.read_dword(emu.regs().get_esp() + 8)
85+
.expect("urlmon!URLDownloadToFileW error reading sz_filename") as u64;
86+
let dw_reserved = emu
87+
.maps
88+
.read_dword(emu.regs().get_esp() + 12)
89+
.expect("urlmon!URLDownloadToFileW error reading dw_reserved") as u64;
90+
let lpfn_cb = emu
91+
.maps
92+
.read_dword(emu.regs().get_esp() + 16)
93+
.expect("urlmon!URLDownloadToFileW error reading lpfn_cb") as u64;
94+
95+
let url = emu.maps.read_wide_string(sz_url);
96+
let filename = emu.maps.read_wide_string(sz_filename);
97+
98+
log_red!(
99+
emu,
100+
"urlmon!URLDownloadToFileW url: {} filename: {}",
101+
url,
102+
filename
103+
);
104+
105+
for _ in 0..5 {
106+
emu.stack_pop32(false);
107+
}
108+
109+
emu.regs_mut().rax = 0; // S_OK
110+
}

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ pub fn gateway(addr: u32, emu: &mut emu::Emu) -> String {
2626
"setsockopt" => setsockopt(emu),
2727
"getsockopt" => getsockopt(emu),
2828
"WsaAccept" => WsaAccept(emu),
29+
"getaddrinfo" => getaddrinfo(emu),
2930

3031
/*
3132
0x774834b5 => sendto(emu),

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

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ mod ole32;
1111
mod oleaut32;
1212
mod shell32;
1313
mod shlwapi;
14+
mod urlmon;
1415
mod user32;
1516
mod uxtheme;
1617
mod wincrt;
@@ -21,6 +22,7 @@ mod ws2_32;
2122
use crate::emu;
2223

2324
pub fn gateway(addr: u64, name: &str, emu: &mut emu::Emu) {
25+
emu.regs_mut().sanitize64();
2426
match name {
2527
"kernel32.text" => kernel32::gateway(addr, emu),
2628
"kernel32.rdata" => kernel32::gateway(addr, emu),
@@ -35,18 +37,17 @@ pub fn gateway(addr: u64, name: &str, emu: &mut emu::Emu) {
3537
"comctl64.text" => comctl64::gateway(addr, emu),
3638
"shell32.text" => shell32::gateway(addr, emu),
3739
"shlwapi.text" => shlwapi::gateway(addr, emu),
40+
"urlmon.text" => urlmon::gateway(addr, emu),
3841
"kernelbase.text" => kernelbase::gateway(addr, emu),
3942
"oleaut32.text" => oleaut32::gateway(addr, emu),
4043
"uxtheme.text" => uxtheme::gateway(addr, emu),
4144
"gdi32.text" => gdi32::gateway(addr, emu),
4245
"ole32.text" => ole32::gateway(addr, emu),
4346
"msvcrt.text" => msvcrt::gateway(addr, emu),
44-
"api-ms-win-crt-runtime-l1-1-0.rdata" => wincrt::gateway(addr, emu),
45-
"api-ms-win-crt-stdio-l1-1-0.rdata" => wincrt::gateway(addr, emu),
46-
"api-ms-win-crt-heap-l1-1-0.rdata" => wincrt::gateway(addr, emu),
47+
"api-ms-win-crt-runtime-l1-1-0.text" => wincrt::gateway(addr, emu),
4748
"not_loaded" => {
4849
// TODO: banzai check?
49-
emu.pe64.as_ref().unwrap().import_addr_to_name(addr)
50+
emu.pe32.as_ref().unwrap().import_addr_to_name(addr as u32)
5051
}
5152
_ => panic!("/!\\ winapi64 gateway: trying to execute on {} at 0x{:x}", name, addr),
5253
};

0 commit comments

Comments
 (0)