Skip to content

Commit fc3be4a

Browse files
committed
rust: add validation of PE library loads
We now have library presence coverage for all supported architectures.
1 parent a1f9aa2 commit fc3be4a

File tree

1 file changed

+74
-3
lines changed

1 file changed

+74
-3
lines changed

src/main.rs

Lines changed: 74 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,57 @@ const ELF_ALLOWED_LIBRARIES: &[&str] = &[
3333
"libpython3.9.so.1.0",
3434
];
3535

36+
const PE_ALLOWED_LIBRARIES: &[&str] = &[
37+
"ADVAPI32.dll",
38+
"api-ms-win-core-path-l1-1-0.dll",
39+
"api-ms-win-crt-conio-l1-1-0.dll",
40+
"api-ms-win-crt-convert-l1-1-0.dll",
41+
"api-ms-win-crt-heap-l1-1-0.dll",
42+
"api-ms-win-crt-environment-l1-1-0.dll",
43+
"api-ms-win-crt-filesystem-l1-1-0.dll",
44+
"api-ms-win-crt-locale-l1-1-0.dll",
45+
"api-ms-win-crt-math-l1-1-0.dll",
46+
"api-ms-win-crt-process-l1-1-0.dll",
47+
"api-ms-win-crt-runtime-l1-1-0.dll",
48+
"api-ms-win-crt-stdio-l1-1-0.dll",
49+
"api-ms-win-crt-string-l1-1-0.dll",
50+
"api-ms-win-crt-time-l1-1-0.dll",
51+
"api-ms-win-crt-utility-l1-1-0.dll",
52+
"bcrypt.dll",
53+
"Cabinet.dll",
54+
"COMCTL32.dll",
55+
"COMDLG32.dll",
56+
"CRYPT32.dll",
57+
"GDI32.dll",
58+
"IMM32.dll",
59+
"IPHLPAPI.DLL",
60+
"KERNEL32.dll",
61+
"msi.dll",
62+
"NETAPI32.dll",
63+
"ole32.dll",
64+
"OLEAUT32.dll",
65+
"RPCRT4.dll",
66+
"SHELL32.dll",
67+
"SHLWAPI.dll",
68+
"USER32.dll",
69+
"USERENV.dll",
70+
"VERSION.dll",
71+
"VCRUNTIME140.dll",
72+
"WINMM.dll",
73+
"WS2_32.dll",
74+
// Our libraries.
75+
"libcrypto-1_1.dll",
76+
"libcrypto-1_1-x64.dll",
77+
"libffi-7.dll",
78+
"libssl-1_1.dll",
79+
"libssl-1_1-x64.dll",
80+
"python38.dll",
81+
"python39.dll",
82+
"sqlite3.dll",
83+
"tcl86t.dll",
84+
"tk86t.dll",
85+
];
86+
3687
lazy_static! {
3788
static ref MACHO_ALLOWED_DYLIBS: Vec<MachOAllowedDylib> = {
3889
[
@@ -170,11 +221,23 @@ fn validate_macho(path: &Path, macho: &goblin::mach::MachO, bytes: &[u8]) -> Res
170221
Ok(errors)
171222
}
172223

173-
fn validate_distribution(path: &Path) -> Result<Vec<String>> {
224+
fn validate_pe(path: &Path, pe: &goblin::pe::PE) -> Result<Vec<String>> {
225+
let mut errors = vec![];
226+
227+
for lib in &pe.libraries {
228+
if !PE_ALLOWED_LIBRARIES.contains(lib) {
229+
errors.push(format!("{} loads illegal library {}", path.display(), lib));
230+
}
231+
}
232+
233+
Ok(errors)
234+
}
235+
236+
fn validate_distribution(dist_path: &Path) -> Result<Vec<String>> {
174237
let mut errors = vec![];
175238

176-
let fh =
177-
std::fs::File::open(&path).with_context(|| format!("unable to open {}", path.display()))?;
239+
let fh = std::fs::File::open(&dist_path)
240+
.with_context(|| format!("unable to open {}", dist_path.display()))?;
178241

179242
let reader = std::io::BufReader::new(fh);
180243
let dctx = zstd::stream::Decoder::new(reader)?;
@@ -200,6 +263,14 @@ fn validate_distribution(path: &Path) -> Result<Vec<String>> {
200263
errors.push(format!("unexpected fat mach-o binary: {}", path.display()));
201264
}
202265
},
266+
goblin::Object::PE(pe) => {
267+
// We don't care about the wininst-*.exe distutils executables.
268+
if path.to_string_lossy().contains("wininst-") {
269+
continue;
270+
}
271+
272+
errors.extend(validate_pe(path.as_ref(), &pe)?);
273+
}
203274
_ => {}
204275
}
205276
}

0 commit comments

Comments
 (0)