unicorn-rs / unicorn-rs Goto Github PK
View Code? Open in Web Editor NEWRust bindings for the unicorn CPU emulator
License: GNU General Public License v2.0
Rust bindings for the unicorn CPU emulator
License: GNU General Public License v2.0
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 :)
The protection bitfield doesn't yet get exported properly in the cargo version
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.
$ 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)
I believe variant ETCH_UNMAPPED
should be called FETCH_UNMAPPED
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:
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.
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.
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:
unicorn = "0.4.1"
as dependencycargo 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)
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.
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)));
}
I still do not understand why the struct
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.
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");
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(§ion).unwrap();
emu.mem_write(section_va, §ion_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)
To create a MIPS Big Endian emulator, I need to be able to pass the flags MODE_32
and BIG_ENDIAN
. Because Mode
is a rust enum, I can only pass one of these values. I can only pass Mode::MODE_32
.
Because the value of LITTLE_ENDIAN
is 0
, this effectively becomes MODE_32 | LITTLE_ENDIAN
.
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?
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)
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.
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.
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.
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
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.