GithubHelp home page GithubHelp logo

unicorn-rs's Introduction

unicorn-rs

THIS PACKAGE IS DEPRECATED AND NO LONGER MAINTAINED.

Rust bindings are now included with unicorn and will be maintained there from now on.

https://github.com/unicorn-engine/unicorn/tree/next/bindings/rust

Summary

Cargo Documentation Build Status

Rust bindings for the unicorn CPU emulator.

use unicorn::{Cpu, CpuX86};

fn main() {
    let x86_code32: Vec<u8> = vec![0x41, 0x4a]; // INC ecx; DEC edx

    let emu = CpuX86::new(unicorn::Mode::MODE_32).expect("failed to instantiate emulator");
    let _ = emu.mem_map(0x1000, 0x4000, unicorn::Protection::ALL);
    let _ = emu.mem_write(0x1000, &x86_code32);
    let _ = emu.reg_write_i32(unicorn::RegisterX86::ECX, -10);
    let _ = emu.reg_write_i32(unicorn::RegisterX86::EDX, -50);

    let _ = emu.emu_start(0x1000, (0x1000 + x86_code32.len()) as u64, 10 * unicorn::SECOND_SCALE, 1000);
    assert_eq!(emu.reg_read_i32(unicorn::RegisterX86::ECX), Ok(-9));
    assert_eq!(emu.reg_read_i32(unicorn::RegisterX86::EDX), Ok(-51));
}

Installation

This project has been tested on Linux, OS X and Windows. The bindings are built for version 1.0 of unicorn.

This package attempts to build unicorn if it is not already installed on the system. To build unicorn on Linux and OS X, the following tools are needed : gcc, make, git, python 2.7. Visual Studio is needed on Windows.

To use unicorn-rs, simply add it as dependency to the Cargo.toml of your program.

[dependencies]
unicorn = "0.8.0"

Changelog

0.9

Error now implements the Error trait (thanks to @tathanhdinh), the RESOURCE and EXCEPTION error cases are now supported (thanks to @endeav0r). The CPU context can now be saved and restored (thanks to @oblivia-simplex). You can find an example use in the test x86_context_save_and_restore, in tests/unicorn.rs. The ffi bindings crate unicorn-sys is now no_std by default (thanks to @strake). Finally the crate was migrated to Rust edition 2018.

Thank you again to all the contributors, your help is always appreciated.

0.8.0

Added support for mem_map_ptr.

0.7.0

Windows is now supported (thanks to kichristensen).

0.6.0

We now check if unicorn is installed on the system via pkg-tool and use that version if available. Otherwise unicorn is compiled when building the package.

0.4.0

unicorn is now compiled as part of the build process of unicorn-rs.

0.3.0

The handling of callbacks has been modified, callbacks should be implemented using closures. See the tests for examples.

  • added support for interrupt, in/out and sysenter callbacks

Contributing

Contributions to this project are super appreciated. Pull requests, bug reports, code review, tests, documentation or feedback on your use of the bindings, nothing is too small. Don't hesitate to open an issue if you have questions.

Contributors:

  • Sébastien Duquette (@ekse)
  • Israel Hallé (@isra17) for redesigning the callbacks API
  • Richo Healey (@richo)
  • Kim Christensen (@kichristensen) for the Windows support
  • petevine for reviewing the project and adding tests
  • jschievink for his help with the API design
  • m4b for the build.rs script
  • TA Thanh Dinh
  • Lucca Fraser (@oblivia-simplex)
  • Matthew Farkas-Dyck (@strake)
  • endeav0r

unicorn-rs's People

Contributors

ekse avatar endeav0r avatar evanrichter avatar felberj avatar gunyarakun avatar isra17 avatar kichristensen avatar m4b avatar mthiesen avatar oblivia-simplex avatar quadrupleslap avatar richo avatar sduquette-devolutions avatar strake avatar tathanhdinh avatar tesuji avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

unicorn-rs's Issues

Potential unsafe in boxed hooks

Hello all,

Beside of "natural" unsafe on FFI boundary, there are still some "potential" unsafe, IMHO. For example, in add_code_hook https://github.com/ekse/unicorn-rs/blob/6aca2c329c4d221c655f111e06a71720b778b8e5/src/lib.rs#L715-L718

In boxing self (by remove it's lifetime using raw pointer), there is a "potential" unsafe because self can be moved (and then possibly reallocated). But in the current binding, we forbid the reallocation by using boxed Unicorn everywhere (so self is never reallocated by moving)
https://github.com/ekse/unicorn-rs/blob/6aca2c329c4d221c655f111e06a71720b778b8e5/src/lib.rs#L443-L452

The consequence is that we cannot have a stack-allocated Unicorn: any Unicorn is a pinned object.

Since the raw Unicorn handle is a movable raw pointer, IMHO it's possible to have a "non-box" binding, but it may break the current design.

Many thanks for any comment.

Benchmarking the bindings

I remember @lunixbochs mention his go bindings were posting a 20x speedup compared to python (quoting from memory) so recreating the benchmark in unicorn-rs should make for an interesting comparison and provide some more testing.

If the benchmark is to be found somewhere, that is :)

Fork for UnicornAFL / Autogenerate bindings?

I just wanted to point out I have taken your code and started to integrate the bindings into my AFL fork of unicorn.
To keep overhead low (and my sanity), I moved the bindings into the main repo.
https://github.com/domenukk/unicorn/tree/rust/bindings/rust
The changes itself can be found here
master...domenukk:unicornafl
Specifically, I have added rust to ./const_generator.py as I constantly (heh) add consts, see:
https://github.com/domenukk/unicorn/blob/rust/bindings/const_generator.py
Maybe auto generating constants could be interesting for this project, too.

A thing I changed to be able to autogenerate them is to add aliases for ENUM types that are used more than once, see
https://github.com/domenukk/unicorn-rs/blob/15e2e00a46bead6c8fea7137ad53f2a9755fa110/libunicorn-sys/src/mips_const.rs#L205

I'm open to discussions of all sorts. :)
Keep up the good work.

fix vswhere problem

please use follow arguments to run vswhere, or libunicorn-sys will not build when only install Visual Studio BuildTools

libunicorn-sys-0.9.1, build.rs, ln 11
let vswhere_output = Command::new(r"build_tools\vswhere.exe")
.args(&[
"-latest",
"-products",
"*",
"-property",
"installationPath"])
.output()
.expect("failed to execute vswhere.exe");

Test fails on ARM

$ RUST_BACKTRACE=1  target/debug/examples/test 
version : 1.0
Support for:
         x86: true
         arm: true
         mips: true
page size : 4096
thread '<main>' panicked at 'failed to query hardware mode: ARG', src/libcore/result.rs:746
stack backtrace:
   1: 0xb6f70eff - std::sys::backtrace::tracing::imp::write::hf68f1a220b61702c
                at src/libstd/sys/unix/backtrace/tracing/gcc_s.rs:40
   2: 0xb6f74443 - std::panicking::default_hook::_$u7b$$u7b$closure$u7d$$u7d$::hb638acea7c29901b
                at src/libstd/panicking.rs:178
   3: 0xb6f73b13 - std::panicking::default_hook::h508c3dab3df347d6
                at src/libstd/panicking.rs:193
   4: 0xb6f6d84b - std::panicking::on_panic::h3a6e649f33b132c3
                at src/libstd/panicking.rs:227
   5: 0xb6f4fd6b - std::sys_common::unwind::begin_unwind_inner::h17f9e42de6d55309
                at src/libstd/sys/common/unwind/mod.rs:237
   6: 0xb6f526bb - std::sys_common::unwind::begin_unwind_fmt::h039d18bd8498e1d0
                at src/libstd/sys/common/unwind/mod.rs:202
   7: 0xb6f6d21b - rust_begin_unwind
                at src/libstd/sys/common/unwind/mod.rs:179
   8: 0xb6f814a7 - core::panicking::panic_fmt::h813eaa27a5810609
                at src/libcore/panicking.rs:69
   9: 0xb6f46fa7 - core::result::unwrap_failed::h419bc270f6772dcb
                at src/libcore/macros.rs:29
  10: 0xb6f47117 - _<std..result..Result<T, E>>::expect::he67c7df582d2e1e0
                at src/libcore/result.rs:708
  11: 0xb6f4673f - test::main::h1ef728500ff2f89b
                at examples/test.rs:17
  12: 0xb6f73323 - fn()::fn_pointer_shim.32839::ha52fbbed76ed0ca0
  13: 0xb6f73127 - std::panic::recover::_$u7b$$u7b$closure$u7d$$u7d$::he74338885f2bd0e2
                at src/libstd/panic.rs:318
  14: 0xb6f730f7 - std::sys_common::unwind::try::try_fn::h0f540c0db5f980f7
                at src/libstd/sys/common/unwind/mod.rs:127

rustc 1.9.0-dev (470ca1c3f 2016-04-07)

error: could not find native static library `unicorn`, perhaps an -L flag is missing?

Referencing the unicorn crate as follows:

# Cargo.toml
# ...
[dependencies]
unicorn = { version = "0.9" }

Then attempting to build on Linux/amd64:

$ PYTHON=python2 cargo build --verbose

Fails as follows:

...
rustc --edition=2018 --crate-name libunicorn_sys .../.cargo/registry/src/github.com-1ecc6299db9ec823/libunicorn-sys-0.9.0/src/lib.rs --color always --crate-type lib --emit=dep-info,link -C debuginfo=2 -C metadata=3e5e84d63b293298 -C extra-filename=-3e5e84d63b293298 --out-dir .../target/debug/deps -L dependency=.../target/debug/deps --extern bitflags=.../target/debug/deps/libbitflags-f4c5ccff822b82c9.rlib --extern libc=.../target/debug/deps/liblibc-e1ff536ab604bb39.rlib --cap-lints allow -L native=.../target/debug/build/libunicorn-sys-f7184211e440bd6d/out -l static=unicorn`
error: could not find native static library `unicorn`, perhaps an -L flag is missing?

error: aborting due to previous error

error: Could not compile `libunicorn-sys`.

Caused by:
  process didn't exit successfully: `rustc --edition=2018 --crate-name libunicorn_sys .../.cargo/registry/src/github.com-1ecc6299db9ec823/libunicorn-sys-0.9.0/src/lib.rs --color always --crate-type lib --emit=dep-info,link -C debuginfo=2 -C metadata=3e5e84d63b293298 -C extra-filename=-3e5e84d63b293298 --out-dir .../target/debug/deps -L dependency=.../target/debug/deps --extern bitflags=.../target/debug/deps/libbitflags-f4c5ccff822b82c9.rlib --extern libc=.../target/debug/deps/liblibc-e1ff536ab604bb39.rlib --cap-lints allow -L native=.../target/debug/build/libunicorn-sys-f7184211e440bd6d/out -l static=unicorn` (exit code: 1)

Where

cargo 1.32.0 (8610973aa 2019-01-02)
rustc 1.32.0 (9fda7c223 2019-01-16)

Tracing/logging?

use std::path::Path;
use pelite::{FileMap};
use pelite::pe64::{Pe, PeFile};
use unicorn::{Cpu, CpuX86};

fn round_to_multiple(numToRound: u64, multiple: u64) -> u64 {
    if (multiple == 0) {
        return numToRound;
    }
    let remainder = numToRound % multiple;
    if (remainder == 0) {
        return numToRound;
    }
    return numToRound + multiple - remainder;
}

fn main() {
  // emulator
  let mut emu = CpuX86::new(unicorn::Mode::MODE_64).unwrap();
  // parse PE
  let mut args = std::env::args();
  let filename = args.nth(1).unwrap();
  let path = Path::new(&filename);
  let map = FileMap::open(path).unwrap();
  let file = PeFile::from_bytes(&map).unwrap();
  let optional_header = file.optional_header();
  println!("{:02x?}", optional_header);
  let image_base = optional_header.ImageBase;
  for section in file.section_headers() {
    let section_va = image_base + section.VirtualAddress as u64;
    println!("{:02x?}", section);
    println!("{:08x}", section_va);
    let rounded_virtual_size = round_to_multiple(section.VirtualSize as u64, 4096);
    emu.mem_map(section_va, rounded_virtual_size as usize, unicorn::Protection::ALL).unwrap();
    if (section.SizeOfRawData > 0) {
      let section_bytes = file.get_section_bytes(&section).unwrap();
      emu.mem_write(section_va, &section_bytes).unwrap();
    }
  }
  let imports = file.imports().unwrap();
  for desc in imports {
    let iat = desc.iat().unwrap();
    let int = desc.int().unwrap();
    for (va, import) in Iterator::zip(iat, int) {
      println!("{:?} {:02x?} {:?}", desc, va, import);
    }
  }
  let va_entry = optional_header.ImageBase + optional_header.AddressOfEntryPoint as u64;
  emu.emu_start(
    va_entry,
    optional_header.ImageBase + (optional_header.AddressOfEntryPoint as u64) + 4,
    0,
    0
  ).unwrap();
}
IMAGE_OPTIONAL_HEADER64 { Magic: 20b, LinkerVersion: "14.0", SizeOfCode: a09a00, SizeOfInitializedData: 2081c00, SizeOfUninitializedData: 00, AddressOfEntryPoint: 4901722, BaseOfCode: 1000, ImageBase: 14000
0000, SectionAlignment: 1000, FileAlignment: 200, OperatingSystemVersion: "6.0", ImageVersion: "0.0", SubsystemVersion: "6.0", Win32VersionValue: 00, SizeOfImage: 50a4000, SizeOfHeaders: 400, CheckSum: 00, 
Subsystem: 02, DllCharacteristics: 8120, SizeOfStackReserve: 100000, SizeOfStackCommit: 1000, SizeOfHeapReserve: 100000, SizeOfHeapCommit: 1000, LoaderFlags: 00, NumberOfRvaAndSizes: 10, DataDirectory: [] }
SectionHeader { Name: ".text", VirtualAddress: 0x1000, VirtualSize: 0xa098b6, PointerToRawData: 0x0, SizeOfRawData: 0x0, Characteristics: 0x60000020 }
140001000
SectionHeader { Name: ".rdata", VirtualAddress: 0xa0b000, VirtualSize: 0x1f60058, PointerToRawData: 0x0, SizeOfRawData: 0x0, Characteristics: 0x40000040 }
140a0b000
SectionHeader { Name: ".data", VirtualAddress: 0x296c000, VirtualSize: 0x5aae4, PointerToRawData: 0x0, SizeOfRawData: 0x0, Characteristics: 0xc0000040 }
14296c000
SectionHeader { Name: ".pdata", VirtualAddress: 0x29c7000, VirtualSize: 0x38da8, PointerToRawData: 0x0, SizeOfRawData: 0x0, Characteristics: 0x40000040 }
1429c7000
SectionHeader { Name: ".qtmetad", VirtualAddress: 0x2a00000, VirtualSize: 0x536, PointerToRawData: 0x0, SizeOfRawData: 0x0, Characteristics: 0x40000040 }
142a00000
SectionHeader { Name: ".qtmimed", VirtualAddress: 0x2a01000, VirtualSize: 0x4ece5, PointerToRawData: 0x0, SizeOfRawData: 0x0, Characteristics: 0x40000040 }
142a01000
SectionHeader { Name: ".tls", VirtualAddress: 0x2a50000, VirtualSize: 0x18, PointerToRawData: 0x0, SizeOfRawData: 0x0, Characteristics: 0xc0000040 }
142a50000
SectionHeader { Name: ".jPc0", VirtualAddress: 0x2a51000, VirtualSize: 0x524792, PointerToRawData: 0x0, SizeOfRawData: 0x0, Characteristics: 0x60000020 }
142a51000
SectionHeader { Name: ".jPc1", VirtualAddress: 0x2f76000, VirtualSize: 0x1938, PointerToRawData: 0x400, SizeOfRawData: 0x1a00, Characteristics: 0xc0000040 }
142f76000
SectionHeader { Name: ".jPc2", VirtualAddress: 0x2f78000, VirtualSize: 0x20e804c, PointerToRawData: 0x1e00, SizeOfRawData: 0x20e8200, Characteristics: 0x68000060 }
142f78000
SectionHeader { Name: ".rsrc", VirtualAddress: 0x5061000, VirtualSize: 0x42bd8, PointerToRawData: 0x20ea000, SizeOfRawData: 0x42c00, Characteristics: 0x40000040 }
145061000
Imports { dll_name: Ok("KERNEL32.dll"), iat.len: Ok(1), int.len: Ok(1) } 3336408 Ok(ByName { hint: 0, name: "AcquireSRWLockExclusive" })
Imports { dll_name: Ok("api-ms-win-crt-heap-l1-1-0.dll"), iat.len: Ok(1), int.len: Ok(1) } 334fa7c Ok(ByName { hint: 0, name: "_aligned_free" })
Imports { dll_name: Ok("api-ms-win-crt-private-l1-1-0.dll"), iat.len: Ok(1), int.len: Ok(1) } 4e46904 Ok(ByName { hint: 0, name: "__intrinsic_setjmpex" })
Imports { dll_name: Ok("api-ms-win-crt-runtime-l1-1-0.dll"), iat.len: Ok(1), int.len: Ok(1) } 4941db6 Ok(ByName { hint: 0, name: "__p___argc" })
Imports { dll_name: Ok("api-ms-win-crt-stdio-l1-1-0.dll"), iat.len: Ok(1), int.len: Ok(1) } 492ac0e Ok(ByName { hint: 0, name: "__acrt_iob_func" })
Imports { dll_name: Ok("api-ms-win-crt-string-l1-1-0.dll"), iat.len: Ok(1), int.len: Ok(1) } 4e594cc Ok(ByName { hint: 0, name: "_isctype_l" })
Imports { dll_name: Ok("USER32.dll"), iat.len: Ok(1), int.len: Ok(1) } 48f1170 Ok(ByName { hint: 0, name: "AdjustWindowRectEx" })
Imports { dll_name: Ok("api-ms-win-crt-environment-l1-1-0.dll"), iat.len: Ok(1), int.len: Ok(1) } 48f6ac0 Ok(ByName { hint: 0, name: "__p__environ" })
Imports { dll_name: Ok("SHELL32.dll"), iat.len: Ok(1), int.len: Ok(1) } 48915e8 Ok(ByName { hint: 0, name: "CommandLineToArgvW" })
Imports { dll_name: Ok("ole32.dll"), iat.len: Ok(1), int.len: Ok(1) } 48e2d20 Ok(ByName { hint: 0, name: "CoCreateGuid" })
Imports { dll_name: Ok("api-ms-win-crt-math-l1-1-0.dll"), iat.len: Ok(1), int.len: Ok(1) } 490faa2 Ok(ByName { hint: 0, name: "__setusermatherr" })
Imports { dll_name: Ok("api-ms-win-crt-convert-l1-1-0.dll"), iat.len: Ok(1), int.len: Ok(1) } 335579a Ok(ByName { hint: 0, name: "_strtod_l" })
Imports { dll_name: Ok("api-ms-win-crt-time-l1-1-0.dll"), iat.len: Ok(1), int.len: Ok(1) } 3356172 Ok(ByName { hint: 0, name: "__daylight" })
Imports { dll_name: Ok("UxTheme.dll"), iat.len: Ok(1), int.len: Ok(1) } 49757a0 Ok(ByName { hint: 0, name: "CloseThemeData" })
Imports { dll_name: Ok("ADVAPI32.dll"), iat.len: Ok(1), int.len: Ok(1) } 33563a8 Ok(ByName { hint: 0, name: "AccessCheck" })
Imports { dll_name: Ok("NETAPI32.dll"), iat.len: Ok(1), int.len: Ok(1) } 4e582fe Ok(ByName { hint: 0, name: "NetApiBufferFree" })
Imports { dll_name: Ok("api-ms-win-crt-filesystem-l1-1-0.dll"), iat.len: Ok(1), int.len: Ok(1) } 49a4fac Ok(ByName { hint: 0, name: "_lock_file" })
Imports { dll_name: Ok("USERENV.dll"), iat.len: Ok(1), int.len: Ok(1) } 49812da Ok(ByName { hint: 0, name: "GetUserProfileDirectoryW" })
Imports { dll_name: Ok("api-ms-win-crt-utility-l1-1-0.dll"), iat.len: Ok(1), int.len: Ok(1) } 4e3a80a Ok(ByName { hint: 0, name: "bsearch" })
Imports { dll_name: Ok("VERSION.dll"), iat.len: Ok(1), int.len: Ok(1) } 48a76be Ok(ByName { hint: 0, name: "GetFileVersionInfoSizeW" })
Imports { dll_name: Ok("api-ms-win-crt-locale-l1-1-0.dll"), iat.len: Ok(1), int.len: Ok(1) } 4eadaf2 Ok(ByName { hint: 0, name: "___lc_codepage_func" })
Imports { dll_name: Ok("GDI32.dll"), iat.len: Ok(1), int.len: Ok(1) } 4e54c3e Ok(ByName { hint: 0, name: "AddFontMemResourceEx" })
Imports { dll_name: Ok("WS2_32.dll"), iat.len: Ok(1), int.len: Ok(1) } 48f2c4e Ok(ByName { hint: 0, name: "WSAAsyncSelect" })
Imports { dll_name: Ok("WINMM.dll"), iat.len: Ok(1), int.len: Ok(1) } 4e44ff2 Ok(ByName { hint: 0, name: "PlaySoundW" })
Imports { dll_name: Ok("WTSAPI32.dll"), iat.len: Ok(1), int.len: Ok(1) } 4906e6e Ok(ByName { hint: 0, name: "WTSFreeMemory" })
Imports { dll_name: Ok("IMM32.dll"), iat.len: Ok(1), int.len: Ok(1) } 4e2c998 Ok(ByName { hint: 0, name: "ImmAssociateContext" })
Imports { dll_name: Ok("dwmapi.dll"), iat.len: Ok(1), int.len: Ok(1) } 4e4086a Ok(ByName { hint: 0, name: "DwmEnableBlurBehindWindow" })
Imports { dll_name: Ok("api-ms-win-crt-multibyte-l1-1-0.dll"), iat.len: Ok(1), int.len: Ok(1) } 49863aa Ok(ByName { hint: 0, name: "_mbtowc_l" })
Imports { dll_name: Ok("OLEAUT32.dll"), iat.len: Ok(1), int.len: Ok(1) } 48f08aa Ok(ByName { hint: 0, name: "SafeArrayCreateVector" })
Imports { dll_name: Ok("KERNEL32.dll"), iat.len: Ok(1), int.len: Ok(1) } 4e595ca Ok(ByName { hint: 0, name: "GetSystemTimeAsFileTime" })
Imports { dll_name: Ok("USER32.dll"), iat.len: Ok(1), int.len: Ok(1) } 499c918 Ok(ByName { hint: 0, name: "CharUpperBuffW" })
Imports { dll_name: Ok("KERNEL32.dll"), iat.len: Ok(11), int.len: Ok(11) } 48ec4b0 Ok(ByName { hint: 0, name: "LocalAlloc" })
Imports { dll_name: Ok("KERNEL32.dll"), iat.len: Ok(11), int.len: Ok(11) } 494c6f6 Ok(ByName { hint: 0, name: "LocalFree" })
Imports { dll_name: Ok("KERNEL32.dll"), iat.len: Ok(11), int.len: Ok(11) } 333f566 Ok(ByName { hint: 0, name: "GetModuleFileNameW" })
Imports { dll_name: Ok("KERNEL32.dll"), iat.len: Ok(11), int.len: Ok(11) } 333cb80 Ok(ByName { hint: 0, name: "GetProcessAffinityMask" })
Imports { dll_name: Ok("KERNEL32.dll"), iat.len: Ok(11), int.len: Ok(11) } 48e52d4 Ok(ByName { hint: 0, name: "SetProcessAffinityMask" })
Imports { dll_name: Ok("KERNEL32.dll"), iat.len: Ok(11), int.len: Ok(11) } 495fd82 Ok(ByName { hint: 0, name: "SetThreadAffinityMask" })
Imports { dll_name: Ok("KERNEL32.dll"), iat.len: Ok(11), int.len: Ok(11) } 3341d1e Ok(ByName { hint: 0, name: "Sleep" })
Imports { dll_name: Ok("KERNEL32.dll"), iat.len: Ok(11), int.len: Ok(11) } 2f7f7c8 Ok(ByName { hint: 0, name: "ExitProcess" })
Imports { dll_name: Ok("KERNEL32.dll"), iat.len: Ok(11), int.len: Ok(11) } 333a9c2 Ok(ByName { hint: 0, name: "LoadLibraryA" })
Imports { dll_name: Ok("KERNEL32.dll"), iat.len: Ok(11), int.len: Ok(11) } 4e433ec Ok(ByName { hint: 0, name: "GetModuleHandleA" })
Imports { dll_name: Ok("KERNEL32.dll"), iat.len: Ok(11), int.len: Ok(11) } 495cd40 Ok(ByName { hint: 0, name: "GetProcAddress" })
thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: WRITE_UNMAPPED', src\main.rs:63:5
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
error: process didn't exit successfully: `target\debug\pe32-emulator.exe C:\Users\Brandon\Desktop\foo.exe` (exit code: 101)

"improper_ctypes" Build warning

Complete warning:

src/ffi.rs:37:36: 37:59 warning: found non-foreign-function-safe member in struct marked #[repr(C)]: found struct without foreign-function-safe representation annotation in foreign module, consider adding a #[repr(C)] attribute to the type, #[warn(improper_ctypes)] on by default
src/ffi.rs:37                           regions: *const *const MemRegion,
                                                 ^~~~~~~~~~~~~~~~~~~~~~~

Seems to come from the Protection bitflags that doesn't take the #[repr(C)] attribute as expected. I've got isra17@3eae40b that you might want to cherry-pick.

Can't build unicorn on Linux

After commit 1bdbb75, I can't build unicorn on Linux. I have installed unicorn library in my system, which is the one unicorn-rs uses before that commit. But after that change, when I try to build it, it fails. Here you have some information:

$ cargo build --verbose   # Just after that commit...
    Updating registry `https://github.com/rust-lang/crates.io-index`
   Compiling gcc v0.3.43
   Compiling libc v0.2.20
   Compiling bitflags v0.6.0
     Running `rustc /home/jmi2k/.cargo/registry/src/github.com-1ecc6299db9ec823/gcc-0.3.43/src/lib.rs --crate-name gcc --crate-type lib -g -C metadata=be7b7587fd240ec9 -C extra-filename=-be7b7587fd240ec9 --out-dir /home/jmi2k/tmp/unicorn-rs/target/debug/deps --emit=dep-info,link -L dependency=/home/jmi2k/tmp/unicorn-rs/target/debug/deps --cap-lints allow`
     Running `rustc /home/jmi2k/.cargo/registry/src/github.com-1ecc6299db9ec823/libc-0.2.20/src/lib.rs --crate-name libc --crate-type lib -g --cfg feature=\"use_std\" --cfg feature=\"default\" -C metadata=29ef97a68464c2b7 -C extra-filename=-29ef97a68464c2b7 --out-dir /home/jmi2k/tmp/unicorn-rs/target/debug/deps --emit=dep-info,link -L dependency=/home/jmi2k/tmp/unicorn-rs/target/debug/deps --cap-lints allow`
     Running `rustc /home/jmi2k/.cargo/registry/src/github.com-1ecc6299db9ec823/bitflags-0.6.0/src/lib.rs --crate-name bitflags --crate-type lib -g -C metadata=b8c7fb7df9b2bc2e -C extra-filename=-b8c7fb7df9b2bc2e --out-dir /home/jmi2k/tmp/unicorn-rs/target/debug/deps --emit=dep-info,link -L dependency=/home/jmi2k/tmp/unicorn-rs/target/debug/deps --cap-lints allow`
   Compiling libunicorn-sys v0.4.0 (file:///home/jmi2k/tmp/unicorn-rs/libunicorn-sys)
     Running `rustc libunicorn-sys/build.rs --crate-name build_script_build --crate-type bin -g -C metadata=1b1fea3559201b39 --out-dir /home/jmi2k/tmp/unicorn-rs/target/debug/build/libunicorn-sys-1b1fea3559201b39 --emit=dep-info,link -L dependency=/home/jmi2k/tmp/unicorn-rs/target/debug/deps --extern gcc=/home/jmi2k/tmp/unicorn-rs/target/debug/deps/libgcc-be7b7587fd240ec9.rlib`
     Running `/home/jmi2k/tmp/unicorn-rs/target/debug/build/libunicorn-sys-1b1fea3559201b39/build-script-build`
     Running `rustc libunicorn-sys/src/lib.rs --crate-name libunicorn_sys --crate-type lib -g -C metadata=1b1fea3559201b39 --out-dir /home/jmi2k/tmp/unicorn-rs/target/debug/deps --emit=dep-info,link -L dependency=/home/jmi2k/tmp/unicorn-rs/target/debug/deps --extern bitflags=/home/jmi2k/tmp/unicorn-rs/target/debug/deps/libbitflags-b8c7fb7df9b2bc2e.rlib --extern libc=/home/jmi2k/tmp/unicorn-rs/target/debug/deps/liblibc-29ef97a68464c2b7.rlib -L native=/home/jmi2k/tmp/unicorn-rs/target/debug/build/libunicorn-sys-1b1fea3559201b39/out -l static=unicorn`
error: could not find native static library `unicorn`, perhaps an -L flag is missing?

error: Could not compile `libunicorn-sys`.

Caused by:
  process didn't exit successfully: `rustc libunicorn-sys/src/lib.rs --crate-name libunicorn_sys --crate-type lib -g -C metadata=1b1fea3559201b39 --out-dir /home/jmi2k/tmp/unicorn-rs/target/debug/deps --emit=dep-info,link -L dependency=/home/jmi2k/tmp/unicorn-rs/target/debug/deps --extern bitflags=/home/jmi2k/tmp/unicorn-rs/target/debug/deps/libbitflags-b8c7fb7df9b2bc2e.rlib --extern libc=/home/jmi2k/tmp/unicorn-rs/target/debug/deps/liblibc-29ef97a68464c2b7.rlib -L native=/home/jmi2k/tmp/unicorn-rs/target/debug/build/libunicorn-sys-1b1fea3559201b39/out -l static=unicorn` (exit code: 101)

More details:

  • cargo version 0.15.0
  • rustc version 1.14.0
  • unicorn version 0.9

My system is pretty exotic, but I tried in an Arch chroot and it still happens. If you need more details, I can test it in a VM next week.

Broken documentation

The example should probably look more like this (renamings etc - never mind the main vs. test):

    use unicorn::{Unicorn, Arch, Mode, Protection, RegisterX86, SECOND_SCALE};
    #[test]
    fn it_works() {
        let x86_code32 : Vec<u8> = vec![0x41, 0x4a]; // INC ecx; DEC edx

        let mut emu = Unicorn::new(Arch::X86, Mode::MODE_32).expect("failed to instantiate emulator");
        emu.mem_map(0x1000, 0x4000, Protection::PROT_ALL); 
        emu.mem_write(0x1000, &x86_code32); 
        emu.reg_write_i32(RegisterX86::ECX as i32, -10);
        emu.reg_write_i32(RegisterX86::EDX as i32, -50);

        emu.emu_start(0x1000, (0x1000 + x86_code32.len()) as u64, 10 * SECOND_SCALE, 1000);
        assert_eq!(emu.reg_read_i32(RegisterX86::ECX as i32), Ok((-9)));
        assert_eq!(emu.reg_read_i32(RegisterX86::EDX as i32), Ok((-51)));
    }

unable to install it on osx

Hi there,

I know this project is only tested on linux but as everything should work on OSX, I gave it a try. Unfortunately it did not compile and people on users.rust.com were unable to help me so before I dig deep into the rust code, I wanted to know whether you can image what the problem is. So here is what I did:

  1. I addunicorn = "0.4.1" as dependency
  2. I run cargo run --verbose but I get the following error:
$ cargo run --verbose
       Fresh libc v0.2.20
       Fresh bitflags v0.6.0
       Fresh gcc v0.3.41
       Fresh byteorder v1.0.0
   Compiling libunicorn-sys v0.4.0
     Running `rustc /Users/$username/.cargo/registry/src/github.com-1ecc6299db9ec823/libunicorn-sys-0.4.0/lib.rs --crate-name libunicorn_sys \
--crate-type lib -g -C metadata=271778d4aa553e9c -C extra-filename=-271778d4aa553e9c --out-dir \
/Users/$username/dev/$project/target/debug/deps --emit=dep-info,link -L \
dependency=/Users/$username/dev/$project/target/debug/deps --extern \
libc=/Users/$username/dev/$project/target/debug/deps/liblibc-29ef97a68464c2b7.rlib --extern \
bitflags=/Users/$username/dev/$project/target/debug/deps/libbitflags-b8c7fb7df9b2bc2e.rlib --cap-lints allow -L \
native=/Users/$username/dev/$project/target/debug/build/libunicorn-sys-fe33b86568c508cb/out -l static=unicorn`

error: failed to add native library /Users/$user/dev/$project/target/debug/build/libunicorn-sys-fe33b86568c508cb/out/libunicorn.a: failed to open archive

error: Could not compile `libunicorn-sys`.

Caused by:
  process didn't exit successfully: `rustc /Users/$user/.cargo/registry/src/github.com-1ecc6299db9ec823/libunicorn-sys-0.4.0/lib.rs --crate-name libunicorn_sys --crate-type lib -g -C metadata=271778d4aa553e9c -C extra-filename=-271778d4aa553e9c --out-dir /Users/$user/dev/$project/target/debug/deps --emit=dep-info,link -L dependency=/Users/$user/dev/$project/target/debug/deps --extern libc=/Users/$user/dev/$project/target/debug/deps/liblibc-29ef97a68464c2b7.rlib --extern bitflags=/Users/$user/dev/$project/target/debug/deps/libbitflags-b8c7fb7df9b2bc2e.rlib --cap-lints allow -L native=/Users/$user/dev/$project/target/debug/build/libunicorn-sys-fe33b86568c508cb/out -l static=unicorn` (exit code: 101)
  1. The file libunicorn.a exists and file reveals the following:
$ file /Users/$username/dev/$project/target/debug/build/libunicorn-sys-fe33b86568c508cb/out/libunicorn.a
/Users/$username/dev/$project/target/debug/build/libunicorn-sys-fe33b86568c508cb/out/libunicorn.a: Mach-O universal binary with 2 architectures: [x86_64: current ar archive random library] [i386]
/Users/$username/dev/$project/target/debug/build/libunicorn-sys-fe33b86568c508cb/out/libunicorn.a (for architecture x86_64):	current ar archive random library
/Users/$username/dev/$project/target/debug/build/libunicorn-sys-fe33b86568c508cb/out/libunicorn.a (for architecture i386):	current ar archive random library

I assume the error gets thrown here but if possible I would like to avoid digging there. RUST_BACKTRACE=1 does not reveal more information.
4. my versions:

$ rustc --version
rustc 1.14.0
$ cargo --version
cargo 0.15.0-dev (298a012 2016-12-20)

By looking at your files, it does not look like that you are doing any linux specific things, but maybe I did not see it. One thing I suspect is that rustc expects a linux .a and not an osx .a, but according to the documentation, rustc should also work on osx. I am happy to fix this bug and file a merge request afterwards, but I do not know where to start.

ARM Mode

Hey, thanks for doing this. It's a really useful project.
Is there a reason why UC_MODE_ARM isn't available as a Mode argument? It looks like it's been commented out in the enum listing. There seems to be a workaround -- just use LITTLE_ENDIAN as the mode argument -- but this seems unnecessarily convoluted. Maybe it would be better to just have modes as integer values, identified by global, static variables? Or strings that are translated by a hashtable into the integer/C-enum arguments needed by the engine?

I want to find a maintainer

Hi @ekse , I would like to find another maintainer. In the meantime, you could
handle the ownership of this crate to me. At least I could merge the bug fix PR
if there are any.

If you want direct conversation, look for me on Rust Discord (@lzutao).

Thinner wrapper for Unicorn

I still do not understand why the struct

https://github.com/ekse/unicorn-rs/blob/4814a4f41db825c8123905006e71ffa2761a34d5/src/lib.rs#L380-L389

needs to store callbacks. Indeed, I've removed them, the code still compiles but tests fail :(

Are there reasons for the existence of these callback maps? I think that they might help to keep the lifetime of callback closures? (if "yes", why isn't the compiler able to detect the problem when I remove them)

Many thanks for any response.

Accessing the CPU in hooks

disclaimer: I'm a rust noob. I may be missing something essential, here.

Is there an intended way to access the Unicorn engine's CPU context from a code hook? The following (which more or less follows the pattern in the test routines) compiles without complaint, but then causes the emulation to hang for several seconds, until it crashes with an exit code of 1.

 53     if _DEBUG {                                                                                                                              
 54       let callback_c =                                                                                                                       
 55         move |u: &unicorn::Unicorn, addr: u64, _: u32| {                                                                                     
 56           println!("[{:08x}] SP: {:08x}", addr, u.reg_read(RegisterARM::SP.to_i32()).expect("Error reading SP"));                            
 57         };                                                                                                                                   
 58       // add some hooks if in debugging mode                                                                                                 
 59       uc.add_code_hook(CodeHookType::CODE,                                                                                                   
 60                        BASE_ADDR,                                                                                                            
 61                        BASE_ADDR+(MEM_SIZE as u64),                                                                                          
 62                        callback_c)                                                                                                           
 63         .expect("Error adding code hook");                                                                                                   
 64     }                                                                                                                                        
 65                                                                                                                                              
 66     uc                                                                                                                                       
 67   }         

edit: what I'm trying to do here is access the internal unicorn handle's reg_read() method, in lieu of the usual CPU reg_read wrapper (which takes an enum arg instead of an i32), since the Unicorn handle is all that the callback signature seems to give us to work with. This same hook works fine if I leave out the u.reg_read bit, and just print the addr value.

update: No worries. Turned out to be a scoping/lifetime issue after all, which, for reasons still unclear to me, the compiler wasn't picking up on. I moved the hook-adding routine to a separate function -- outside of the function that creates and initializes the engine -- and then called that function from the function that calls the first, initializing function, and now everything appears to be working fine. This partially makes sense to me, given what I grasp of rust's memory management system, and the rest I suppose will become clearer as I become less noobish. Closing the issue. Thanks for letting me rubber-duck debug here.

Possible to bind uc_mem_map_ptr?

Is it possible to bind uc_mem_map_ptr, thereby allowing the user to provide their own memory? Maybe this isn't reasonably to do with Rust, I don't know it well enough.

consider FnMut for hooks

in writing a program that uses unicorn, i ran into a problem where i wanted to initialize variables in the main function and capture them in the closure for the interrupt hook to act as sort of local static variables for the closure. i encountered a problem though, which is that add_intr_hook accepts a Fn and not a FnMut as an argument, which required me to wrap all the variables in mutexes in order to pass them in as mutable.

i was just wondering if it is a matter of limitation on the library (it would be unsafe to use FnMut) or if it was an oversight in the bindings and could be changed to allow more flexibility

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.