From 08f10e5d8fa4aab9f9c9b9b3952b4109d8ca8196 Mon Sep 17 00:00:00 2001 From: 3c7 <3c7@posteo.de> Date: Wed, 3 Jan 2024 12:04:04 +0100 Subject: [PATCH] ci: GitHub actions add windows-latest test build --- .github/workflows/test.yml | 76 ++++++++++++++++++++++++----- yari-sys/build.rs | 2 + yari-sys/src/lib.rs | 35 +++++++------ yari-sys/tests/common.rs | 7 +++ yari-sys/tests/tests_dump_module.rs | 4 ++ 5 files changed, 99 insertions(+), 25 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index aa46be1..6e11e27 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -20,15 +20,19 @@ jobs: - name: Install YARA deps run: sudo apt-get install -y automake libtool make gcc pkg-config libssl-dev libjansson-dev libmagic-dev - name: Build YARA - run: cd yari-sys/yara && ./bootstrap.sh && CFLAGS="-fPIC" ./configure --enable-debug --disable-shared --enable-static --enable-cuckoo --enable-magic --enable-dotnet --with-crypto && make + run: | + cd yari-sys/yara + ./bootstrap.sh + CFLAGS="-fPIC" ./configure --enable-debug --disable-shared --enable-static --enable-cuckoo --enable-magic --enable-dotnet --with-crypto + make - name: Build - run: cargo build --verbose + run: cargo build - name: Run Rust tests - run: cargo test --verbose + run: cargo test - name: Run tests with yari using bundled bindings run: | cargo clean - YARI_USE_BUNDLED_BINDINGS=1 cargo test --verbose + YARI_USE_BUNDLED_BINDINGS=1 cargo test - uses: actions/setup-python@v4 with: python-version: '3.10' @@ -48,19 +52,69 @@ jobs: uses: actions/checkout@v3 with: submodules: 'true' - - name: Install (Yara) Dependencies + - name: Install YARA deps run: brew install autoconf automake libtool pkg-config jansson libmagic openssl python@3.10 python@3.11 python@3.12 - name: Build Yara - run: cd yari-sys/yara && ./bootstrap.sh && CFLAGS="-fPIC -I$(brew --prefix)/include" LDFLAGS="-L$(brew --prefix)/lib $LDFLAGS" LIBRARY_PATH="$(brew --prefix)/lib:$LIBRARY_PATH" ./configure --enable-debug --disable-shared --enable-static --enable-cuckoo --enable-magic --enable-dotnet --with-crypto && make + run: | + cd yari-sys/yara + ./bootstrap.sh + CFLAGS="-fPIC -I$(brew --prefix)/include" LDFLAGS="-L$(brew --prefix)/lib $LDFLAGS" LIBRARY_PATH="$(brew --prefix)/lib:$LIBRARY_PATH" ./configure --enable-debug --disable-shared --enable-static --enable-cuckoo --enable-magic --enable-dotnet --with-crypto + make - name: Build Yari (yari-sys) run: cd yari-sys && CFLAGS="-I$(brew --prefix)/include" LDFLAGS="-L$(brew --prefix)/lib $LDFLAGS" LIBRARY_PATH="$(brew --prefix)/lib:$LIBRARY_PATH" cargo build --release - name: Build Yari (yari-cli) run: cd yari-cli && CFLAGS="-I$(brew --prefix)/include" LDFLAGS="-L$(brew --prefix)/lib $LDFLAGS" LIBRARY_PATH="$(brew --prefix)/lib:$LIBRARY_PATH" cargo build --release - - name: Build Yari (yari-py) - run: cd yari-py && python3.12 -mvenv .venv && .venv/bin/pip install maturin pytest && CFLAGS="-I$(brew --prefix)/include" LDFLAGS="-L$(brew --prefix)/lib $LDFLAGS" LIBRARY_PATH="$(brew --prefix)/lib:$LIBRARY_PATH" .venv/bin/maturin build --release -i python3.10 -i python3.11 -i python3.12 - name: Run Rust tests - run: CFLAGS="-I$(brew --prefix)/include" LDFLAGS="-L$(brew --prefix)/lib $LDFLAGS" LIBRARY_PATH="$(brew --prefix)/lib:$LIBRARY_PATH" cargo test --verbose + run: CFLAGS="-I$(brew --prefix)/include" LDFLAGS="-L$(brew --prefix)/lib $LDFLAGS" LIBRARY_PATH="$(brew --prefix)/lib:$LIBRARY_PATH" cargo test - name: Run Rust tests with bundled bindings - run: cargo clean && YARI_USE_BUNDLED_BINDINGS=1 CFLAGS="-I$(brew --prefix)/include" LDFLAGS="-L$(brew --prefix)/lib $LDFLAGS" LIBRARY_PATH="$(brew --prefix)/lib:$LIBRARY_PATH" cargo test --verbose + run: | + cargo clean + YARI_USE_BUNDLED_BINDINGS=1 CFLAGS="-I$(brew --prefix)/include" LDFLAGS="-L$(brew --prefix)/lib $LDFLAGS" LIBRARY_PATH="$(brew --prefix)/lib:$LIBRARY_PATH" cargo test - name: Run Python tests - run: cd yari-py && .venv/bin/maturin develop && .venv/bin/pytest + run: | + cd yari-py + python3.12 -m venv .venv + .venv/bin/pip install maturin pytest + CFLAGS="-I$(brew --prefix)/include" LDFLAGS="-L$(brew --prefix)/lib $LDFLAGS" LIBRARY_PATH="$(brew --prefix)/lib:$LIBRARY_PATH" .venv/bin/maturin build -i python3.10 -i python3.11 -i python3.12 + .venv/bin/maturin build + .venv/bin/maturin develop + .venv/bin/pytest + build-windows: + runs-on: windows-latest + defaults: + run: + shell: bash + steps: + - uses: actions/checkout@v3 + with: + submodules: 'recursive' + - uses: actions/setup-python@v3 + with: + python-version: '3.10' + - name: Setup Nuget.exe + uses: nuget/setup-nuget@v1 + with: + nuget-version: 'latest' + - name: Setup msbuild + uses: microsoft/setup-msbuild@v1.1 + - name: Install YARA Dependencies + run: nuget.exe restore windows/vs2017/yara.sln + working-directory: ./yari-sys/yara + - name: Build YARA + run: msbuild /m /p:Platform=x64 /p:Configuration=Release /p:PlatformToolset="v142" /p:WindowsTargetPlatformVersion="10.0.19041.0" windows/vs2017/yara.sln + working-directory: ./yari-sys/yara + shell: cmd + - name: Build yari-sys + run: | + cargo build + RUST_LOG=debug cargo test -- --nocapture --show-output --test-threads 1 + working-directory: ./yari-sys + - name: Build Python wheels + run: | + pip install --upgrade pip + python -m venv env + . env/Scripts/activate + pip install maturin pytest + maturin develop + pytest tests + working-directory: ./yari-py diff --git a/yari-sys/build.rs b/yari-sys/build.rs index 99cf767..ed7dbff 100644 --- a/yari-sys/build.rs +++ b/yari-sys/build.rs @@ -32,6 +32,8 @@ fn link_lib(name: &str) { #[cfg(target_os = "windows")] fn link_windows() { link_lib("libyara64"); + link_lib("crypt32"); + link_lib("user32"); } #[cfg(any(target_os = "linux", target_os = "macos"))] diff --git a/yari-sys/src/lib.rs b/yari-sys/src/lib.rs index d01eb1d..6498a9d 100644 --- a/yari-sys/src/lib.rs +++ b/yari-sys/src/lib.rs @@ -640,8 +640,7 @@ impl Context { &mut res.context.matches_notebook, ); - res.context.entry_point = - yr_get_entry_point_offset(data, (*block).size); + res.context.entry_point = yr_get_entry_point_offset(data, (*block).size); _yr_scanner_scan_mem_block(&mut **res.context, data, block); } } @@ -738,7 +737,11 @@ impl Context { debug!("Importing module {:?}", module); let module_name = CString::new(module.as_ref()).expect("Invalid string"); - let _res = unsafe { yr_modules_load(module_name.as_ptr(), &mut **self.context) }; + let res = unsafe { yr_modules_load(module_name.as_ptr(), &mut **self.context) }; + debug!("Loaded module {:?} with result {}", module, res); + if res != ERROR_SUCCESS as i32 { + return Err(YariError::UnknownModule(module.to_string())); + } let new_module: *mut YR_OBJECT_STRUCTURE = unsafe { yr_hash_table_lookup( @@ -748,9 +751,9 @@ impl Context { ) } .cast(); - + debug!("Module {:?} has pointer {:?}", module, new_module); if new_module.is_null() { - return Err(YariError::SymbolNotFound(module.to_string())); + return Err(YariError::UnknownModule(module.to_string())); } self.modules.insert(module, new_module); @@ -1336,6 +1339,7 @@ impl Context { } pub fn dump_module(&mut self, module: Module) -> Result<(), YariError> { + debug!("Dumping module {:?}", module); self.import_module(module)?; match self.modules.get(&module) { Some(module) => { @@ -1464,6 +1468,7 @@ impl Drop for Context { debug!("Dropping context"); unsafe { yr_modules_unload_all(&mut **self.context) }; + debug!("Unloaded modules"); let rules = self.context.rules; @@ -1471,34 +1476,36 @@ impl Drop for Context { unsafe { yr_notebook_destroy(self.context.matches_notebook); } + debug!("Destroyed matches notebook"); } // Drop all created filemaps (this should close all opened FDs) for file in self.yr_mapped_files.iter_mut() { unsafe { yr_filemap_unmap(file) }; } + debug!("Freed filemaps"); unsafe { yr_compiler_destroy(self.compiler) }; + debug!("Destroyed compiler"); if !self.fallback_scanner.is_null() { unsafe { yr_scanner_destroy(self.fallback_scanner) }; + debug!("Destroyed fallback scanner"); } - #[allow(clippy::if_same_then_else)] - if self.use_fallback_eval { - #[cfg(not(target_os = "windows"))] - unsafe { - yr_scanner_destroy(&mut **self.context) - }; - } else { - unsafe { yr_scanner_destroy(&mut **self.context) }; - } + #[cfg(not(target_os = "windows"))] + unsafe { + yr_scanner_destroy(&mut **self.context) + }; + debug!("Destroyed scanner"); if !rules.is_null() { unsafe { yr_rules_destroy(rules) }; + debug!("Destroyed rules"); } unsafe { yr_finalize() }; + debug!("DONE dropping context"); } } diff --git a/yari-sys/tests/common.rs b/yari-sys/tests/common.rs index 2a5cb27..76a5993 100644 --- a/yari-sys/tests/common.rs +++ b/yari-sys/tests/common.rs @@ -4,10 +4,12 @@ use yari_sys::Module; use yari_sys::{Context, ContextBuilder}; pub fn context() -> Context { + let _ = env_logger::builder().is_test(true).try_init(); ContextBuilder::default().build().unwrap() } pub fn context_with_cuckoo() -> Context { + let _ = env_logger::builder().is_test(true).try_init(); let test_root = Path::new(env!("CARGO_MANIFEST_DIR")); let cuckoo_report = test_root.join("tests/assets/cuckoo.json"); @@ -18,6 +20,7 @@ pub fn context_with_cuckoo() -> Context { } fn context_with_sample(path: &str, rule: Option<&str>) -> Context { + let _ = env_logger::builder().is_test(true).try_init(); let test_root = Path::new(env!("CARGO_MANIFEST_DIR")); let file = test_root.join(path); @@ -29,14 +32,17 @@ fn context_with_sample(path: &str, rule: Option<&str>) -> Context { } pub fn context_with_elf_sample() -> Context { + let _ = env_logger::builder().is_test(true).try_init(); context_with_sample("tests/assets/elf_hello_world", None) } pub fn context_with_pe_signed_sample() -> Context { + let _ = env_logger::builder().is_test(true).try_init(); context_with_sample("tests/assets/pe_signed", None) } pub fn context_with_pe_sample_and_rule() -> Context { + let _ = env_logger::builder().is_test(true).try_init(); context_with_sample( "tests/assets/pe_hello_world", Some( @@ -58,6 +64,7 @@ rule r { } pub fn context_with_elf_sample_and_rule() -> Context { + let _ = env_logger::builder().is_test(true).try_init(); context_with_sample( "tests/assets/elf_hello_world", Some( diff --git a/yari-sys/tests/tests_dump_module.rs b/yari-sys/tests/tests_dump_module.rs index 18e4c16..430f8ec 100644 --- a/yari-sys/tests/tests_dump_module.rs +++ b/yari-sys/tests/tests_dump_module.rs @@ -4,6 +4,7 @@ mod common; #[test] fn test_function_dump_plain() { + println!("test_function_dump_plain"); let mut context = common::context(); for module in MODULES { @@ -13,6 +14,7 @@ fn test_function_dump_plain() { #[test] fn test_function_dump_cuckoo() { + println!("test_function_dump_cuckoo"); let mut context = common::context_with_cuckoo(); for module in MODULES { @@ -22,6 +24,7 @@ fn test_function_dump_cuckoo() { #[test] fn test_function_dump_pe() { + println!("test_function_dump_pe"); let mut context = common::context_with_pe_sample_and_rule(); for module in MODULES { @@ -31,6 +34,7 @@ fn test_function_dump_pe() { #[test] fn test_function_dump_elf() { + println!("test_function_dump_elf"); let mut context = common::context_with_elf_sample(); for module in MODULES {