Git Product home page Git Product logo

zydis-rs's People

Contributors

athre0z avatar flobernd avatar jrmuizel avatar oberrich avatar sferrini avatar spinpx avatar tathanhdinh avatar th0rex avatar tnballo avatar williballenthin 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

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

zydis-rs's Issues

Enhance AccessedFlags struct

Hi, i've noticed some strange stuff. When printing with dbg!() macro i noticed that some AccessedFlags looks weird. They are always wrapped in an Option enum, even though when working with my binary it was always evaluating to Some. Also, in many places we can see the 0x0 instead of something like UNUSED. I think that AccessedFlags probably should not be wrapped inside an Option enum, but instead it's fields should be.

Here is an example:

add r9b, 0xA9
[src/deep_taint_run.rs:76] insn.cpu_flags = Some(
    AccessedFlags {
        tested: CpuFlag(
            0x0,
        ),
        modified: CpuFlag(
            CF | PF | AF | ZF | SF | OF,
        ),
        set_0: CpuFlag(
            0x0,
        ),
        set_1: CpuFlag(
            0x0,
        ),
        undefined: CpuFlag(
            0x0,
        ),
    },
)

P.s. Idk honestly how to process all this flags btw. (i.e. log reads/writes to specific flags, etc)

Userdata not correctly passed to formatted callback when LTO enabled

I believe there is probably a UB bug in the handling of userdata pointers passed from Formatter.format_instruction to formatter callbacks. This results in segfaults and unexpected unwrap failures in non-unsafe client code. So far, I've only been able to trigger this issue when optimizations and LTO are enabled.

The example repo https://github.com/williballenthin/zydis-rs-issue-29 contains minimal programs that demonstrate the issue. The issue is present when built in release mode (which has fat LTO enabled) but not in debug mode.

b.rs is the more minimal example and completely non-unsafe. Although Some(...) is passed to format_instruction, the formatter callback receives None as the userdata:

image

image

a.rs more closely represents the code in another project that led to this bug discovery. There's a bit more data provided in the userdata structure, and rather than receiving None, the callback ends up with some unexpected data and segfaults. (Note: there is a single line of unsafe in this binary; however, I believe its unrelated, as I think its a well defined and valid cast across Formatter representations.)

image
image

I suspect the behaviors shown by a.rs and b.rs both stem from the same bug.

Notably, these test cases only demonstrate the issue when fat LTO is enabled (see release profile in Cargo.toml). However, I'm not exactly sure what this means. Suspicions include:

  1. maybe the unsafe casting from user data to &mut dyn Any and back is not well defined, or
  2. there's a bug in optimizations enabled by LTO.

Given that LTO is fairly widely used and tested, I think (1) or similar is more likely than (2). Unfortunately, I have pretty much avoided unsafe Rust because I don't know the safety rules well enough, so I don't know how to triage further.

crash during instruction serialization

I believe that zydis-rs may crash in some cases when serializing instructions, either via serde_json or via debug format (println!("{:?}", insn)). This seems to be due to some operands being invalid. Without doing any research, I wonder if the underlying zydis library does not initialize the unused operands resulting in the serializer getting confused by unexpected enum values or something.

Short term fix: When I overwrite the operands from insn.operand_count..10 with a dummy zero operand, then serialization (edit: sometimes) works:

image

I apologize for not having a test case ready. Would you like me to provide one?

type mismatch for ZydisMnemonic and ZydisMnemonics

I'd like to inspect the mnemonic of decoded instructions in order to find specific instructions. This is not as easy as I'd like because of a type mismatch between the mnemonic constants and the mnemonic field.

A ZydisDecodedInstruction_ has a field mnemonic with type ZydisMnemonic:

image

ZydisMnemonic is an alias for u16:

image

The mnemonic constants exported have type ZydisMnemonics:

image

And, unfortunately, ZydisMnemonics is an alias for c_uint:

image

This prevents me from directly comparing the mnemonic field of a decoded instruction to a constant exported by Zydis:

image

image

Would you consider changing the type of ZydisMnemonic or ZydisMnemonics so that they are the same?

Version 0.0.4 not on crates.io

Hi,

I am trying to build a project with Zydis-rs. I am following the README and setting

[dependencies]
zydis = "0.0.4"

When I run cargo build I get the following error:

$ cargo build
    Updating registry `https://github.com/rust-lang/crates.io-index`
error: no matching version `^0.0.4` found for package `zydis`
location searched: registry `https://github.com/rust-lang/crates.io-index`
versions found: 0.0.3, 0.0.1
required by package `nopstats v0.1.0 ({file path})`

Could the new version be pushed to crates.io?

Thanks

Alex

zydis-rs fails to build on windows from github

Using the basic example shown in the readme on linux, zydis-rs builds and links just fine (with dependecy zydis = { git = "https://github.com/zyantific/zydis-rs"}):

image

However, on Windows/Visual Studio, the example fails:

image

image

I believe this is because on Windows, cmake builds the zydis-c static libraries in a subdirectory named after CMAKE_BUILD_TYPE, eg. Build. On linux, the static libraries are placed into the root build directory.

See this is the build root, and Zycore.lib is not found:

image

but is placed in ./Debug/:

image

and likewise for Zydis.lib.

As I'm still fairly new to rust and not familiar with the cmake crate, I'm not sure if this is common behavior. I'll make an attempt to update build.rs to autodetect Windows/Visual Studio and fix the build path; though, you may have better ideas for a fix.

Tracking: Webassembly support

Does zydis-rs already support one of the wasm targets? If not, what is the outlook for this?

I'll admit, I haven't researched this too thoroughly, so maybe the answer is obvious already. In any case, I'd like to express that I'm interested in using zydis-rs in a wasm project (probably some sort of binary analysis that runs in the browser). Therefore, if this has already been considered (and done?), then sample code or pointers to getting this working are appreciated.

lea, "(empty)" second operand "action"

hi! there is a bug in rust bindings(and potentially in zydis-c)
long short story

lea rax, [rsp+0x20]
DecodedOperand { id: 0, ty: REGISTER, visibility: EXPLICIT, **action: WRITE,** ... }
DecodedOperand { id: 1, ty: MEMORY, visibility: EXPLICIT, **action: (empty)**, ... }

lea eax, [esp+0x20]
DecodedOperand { id: 0, ty: REGISTER, visibility: EXPLICIT, **action: WRITE**, ... }
DecodedOperand { id: 1, ty: MEMORY, visibility: EXPLICIT, **action: (empty)**, ... }

code to reproduce bug

fn main() {
    use zydis::*;
    let data = [0x48, 0x8D, 0x44, 0x24, 0x20];

    let decoder = Decoder::new(MachineMode::LONG_64, AddressWidth::_64).unwrap();
    let instr = decoder.decode(&data).unwrap().unwrap();

    let formatter = Formatter::new(FormatterStyle::INTEL).unwrap();
    let mut buffer = [0u8; 200];
    let mut buffer = OutputBuffer::new(&mut buffer[..]);

    formatter
        .format_instruction(&instr, &mut buffer, None, None)
        .unwrap();
    println!("{}", format!("{}", buffer));

    for i in 0..instr.operand_count as usize {
        println!("{:?}", instr.operands[i]);
    }
    println!();

    let data = [0x8D, 0x44, 0x24, 0x20];

    let decoder = Decoder::new(MachineMode::LONG_COMPAT_32, AddressWidth::_32).unwrap();
    let instr = decoder.decode(&data).unwrap().unwrap();

    let formatter = Formatter::new(FormatterStyle::INTEL).unwrap();
    let mut buffer = [0u8; 200];
    let mut buffer = OutputBuffer::new(&mut buffer[..]);

    formatter
        .format_instruction(&instr, &mut buffer, None, None)
        .unwrap();
    println!("{}", format!("{}", buffer));

    for i in 0..instr.operand_count as usize {
        println!("{:?}", instr.operands[i]);
    }
}

Update to v2-beta

Hello all,
Is there any plan to support zydis v2-beta? I pulled the master branch for zydis-c, but zydis-rs doesn't compile. I have tried to fix it myself but it is beyond my current knowledge about Rust :(

InstructionAttributes not applied to FullInstruction

Take a look at this example:

use zydis::{self, Decoder, FullInstruction, InstructionAttributes};


fn main() {
    let push_rax = [0x50];
    // Btw i get a hint to include zydis::ffi::Decoder. 
    // I dont think we need it. Need to check visibility of some funcs
    let decoder = Decoder::new64();
    let decoded: FullInstruction = decoder.decode_first(&push_rax).unwrap().unwrap();

    dbg!(decoded.operands());
    dbg!(decoded.attributes);
    assert!(decoded.attributes.contains(InstructionAttributes::HAS_SEGMENT_SS));
    
    // Also idk how decoded.segments() work
    
    // Offtop: I need a hint on how to detect conditional branches and conditional reads/writes
}
Click here to see output
[src/main.rs:11] decoded.operands() = [
    DecodedOperand {
        id: 0,
        visibility: EXPLICIT,
        action: OperandAction(
            READ,
        ),
        encoding: OPCODE,
        size: 64,
        element_type: INT,
        element_size: 64,
        element_count: 1,
        attributes: OperandAttributes(
            0x0,
        ),
        kind: Reg(
            RAX,
        ),
    },
    DecodedOperand {
        id: 1,
        visibility: HIDDEN,
        action: OperandAction(
            READ | WRITE,
        ),
        encoding: NONE,
        size: 64,
        element_type: INT,
        element_size: 64,
        element_count: 1,
        attributes: OperandAttributes(
            0x0,
        ),
        kind: Reg(
            RSP,
        ),
    },
    DecodedOperand {
        id: 2,
        visibility: HIDDEN,
        action: OperandAction(
            WRITE,
        ),
        encoding: NONE,
        size: 64,
        element_type: INT,
        element_size: 64,
        element_count: 1,
        attributes: OperandAttributes(
            0x0,
        ),
        kind: Mem(
            MemoryInfo {
                ty: MEM,
                segment: SS,
                base: RSP,
                index: NONE,
                scale: 0,
                disp: DisplacementInfo {
                    has_displacement: false,
                    displacement: 0,
                },
            },
        ),
    },
]
[src/main.rs:12] decoded.attributes = InstructionAttributes(
    0x0,
)
thread 'main' panicked at src/main.rs:13:5:
assertion failed: decoded.attributes.contains(InstructionAttributes::HAS_SEGMENT_SS)
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

As we can see, the InstructionAttributes is nonexistent and also lacks some pretty representation. I have tested it with lots of instructions and the issue is present in all of them.

mismatched types on arm

When cross compiling for armv7/aarch64 a crate that depends on zydis-rs, the compilation fails with a mismatched types error:

error[E0308]: mismatched types
   --> /root/.cargo/registry/src/github.com-1ecc6299db9ec823/zydis-3.1.1/src/ffi.rs:202:17
    |
202 |                 buffer as *mut i8,
    |                 ^^^^^^^^^^^^^^^^^ expected `u8`, found `i8`
    |
    = note: expected raw pointer `*mut u8`
               found raw pointer `*mut i8`


error[E0308]: mismatched types
   --> /root/.cargo/registry/src/github.com-1ecc6299db9ec823/zydis-3.1.1/src/ffi.rs:245:17
    |
245 |                 buffer.as_ptr() as *const i8,
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `u8`, found `i8`
    |
    = note: expected raw pointer `*const u8`
               found raw pointer `*const i8`


error: aborting due to 2 previous errors


For more information about this error, try `rustc --explain E0308`.

error: could not compile `zydis` due to 3 previous errors
warning: build failed, waiting for other jobs to finish...
error: build failed

https://github.com/williballenthin/lancelot/runs/4215259537?check_suite_focus=true

Line 202 is

zydis-rs/src/ffi.rs

Lines 200 to 204 in 2089243

check!(ZyanStringInitCustomBuffer(
string.as_mut_ptr(),
buffer as *mut i8,
capacity
))?;

We see the buffer parameters to ZyanStringInitCustomBuffer should be a *mut c_char:

zydis-rs/src/ffi.rs

Lines 1143 to 1147 in 2089243

pub fn ZyanStringInitCustomBuffer(
string: *mut ZyanString,
buffer: *mut c_char,
capacity: usize,
) -> Status;

and the buffer above is casted to a *mut i8. This is correct on x64 but not arm:

https://github.com/rust-lang/rust/blob/eab2d7519a3f1c11ddaff3d19f8b7727354c6362/library/std/src/os/raw/mod.rs#L48-L55

I think this can be fixed on lines 202 and 245 with a change like here:
https://github.com/jeaye/ncurses-rs/pull/100/files

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.