diff --git a/bindings/python/Cargo.toml b/bindings/python/Cargo.toml index 804726f..536258d 100644 --- a/bindings/python/Cargo.toml +++ b/bindings/python/Cargo.toml @@ -13,6 +13,7 @@ classifier = [ [dependencies] sleighcraft = { path = "../../sleighcraft" } +num_enum = "0.5.1" [dependencies.pyo3] version = "0.13.2" diff --git a/bindings/python/bincraft/__init__.py b/bindings/python/bincraft/__init__.py index b100b81..a8539e9 100644 --- a/bindings/python/bincraft/__init__.py +++ b/bindings/python/bincraft/__init__.py @@ -13,4 +13,237 @@ # See the License for the specific language governing permissions and # limitations under the License. # -from .bincraft import * \ No newline at end of file +from .bincraft import * + +__all__ = [ + 'Sleigh', + 'ARCH_6502', + 'ARCH_6805', + 'ARCH_6809', + 'ARCH_8048', + 'ARCH_8051', + 'ARCH_8085', + 'ARCH_68020', + 'ARCH_68030', + 'ARCH_68040', + 'ARCH_80251', + 'ARCH_80390', + 'ARCH_AARCH64', + 'ARCH_AARCH64BE', + 'ARCH_ARM4_BE', + 'ARCH_ARM4_LE', + 'ARCH_ARM4T_BE', + 'ARCH_ARM4T_LE', + 'ARCH_ARM5_BE', + 'ARCH_ARM5_LE', + 'ARCH_ARM5T_BE', + 'ARCH_ARM5T_LE', + 'ARCH_ARM6_BE', + 'ARCH_ARM6_LE', + 'ARCH_ARM7_BE', + 'ARCH_ARM7_LE', + 'ARCH_ARM8_BE', + 'ARCH_ARM8_LE', + 'ARCH_AVR8', + 'ARCH_AVR8E', + 'ARCH_AVR8EIND', + 'ARCH_AVR8XMEGA', + 'ARCH_AVR32A', + 'ARCH_COLDFIRE', + 'ARCH_CP1600', + 'ARCH_CR16B', + 'ARCH_CR16C', + 'ARCH_DALVIK', + 'ARCH_DATA_BE_64', + 'ARCH_DATA_LE_64', + 'ARCH_DSPIC30F', + 'ARCH_DSPIC33C', + 'ARCH_DSPIC33E', + 'ARCH_DSPIC33F', + 'ARCH_HC05', + 'ARCH_HC08', + 'ARCH_HCS08', + 'ARCH_HCS12', + 'ARCH_JVM', + 'ARCH_M8C', + 'ARCH_MCS96', + 'ARCH_MIPS32BE', + 'ARCH_MIPS32LE', + 'ARCH_MIPS32R6BE', + 'ARCH_MIPS32R6LE', + 'ARCH_MIPS64BE', + 'ARCH_MIPS64LE', + 'ARCH_MX51', + 'ARCH_PA_RISC32BE', + 'ARCH_PIC12C5XX', + 'ARCH_PIC16', + 'ARCH_PIC16C5X', + 'ARCH_PIC16F', + 'ARCH_PIC17C7XX', + 'ARCH_PIC18', + 'ARCH_PIC24E', + 'ARCH_PIC24F', + 'ARCH_PIC24H', + 'ARCH_PPC_32_4XX_BE', + 'ARCH_PPC_32_4XX_LE', + 'ARCH_PPC_32_BE', + 'ARCH_PPC_32_LE', + 'ARCH_PPC_32_QUICCIII_BE', + 'ARCH_PPC_32_QUICCIII_LE', + 'ARCH_PPC_64_BE', + 'ARCH_PPC_64_ISA_ALTIVEC_BE', + 'ARCH_PPC_64_ISA_ALTIVEC_LE', + 'ARCH_PPC_64_ISA_ALTIVEC_VLE_BE', + 'ARCH_PPC_64_ISA_BE', + 'ARCH_PPC_64_ISA_LE', + 'ARCH_PPC_64_ISA_VLE_BE', + 'ARCH_PPC_64_LE', + 'ARCH_RISCV', + 'ARCH_SH_1', + 'ARCH_SH_2', + 'ARCH_SH_2A', + 'ARCH_SPARCV9_32', + 'ARCH_SPARCV9_64', + 'ARCH_SUPERH4_BE', + 'ARCH_SUPERH4_LE', + 'ARCH_TI_MSP430', + 'ARCH_TI_MSP430X', + 'ARCH_TOY_BE_POSSTACK', + 'ARCH_TOY_BE', + 'ARCH_TOY_BUILDER_BE_ALIGN2', + 'ARCH_TOY_BUILDER_BE', + 'ARCH_TOY_BUILDER_LE_ALIGN2', + 'ARCH_TOY_BUILDER_LE', + 'ARCH_TOY_LE', + 'ARCH_TOY_WSZ_BE', + 'ARCH_TOY_WSZ_LE', + 'ARCH_TOY64_BE_HARVARD', + 'ARCH_TOY64_BE', + 'ARCH_TOY64_LE', + 'ARCH_TRICORE', + 'ARCH_V850', + 'ARCH_X86_64', + 'ARCH_X86', + 'ARCH_Z80', + 'ARCH_Z180', + 'MODE_16', + 'MODE_32', + 'MODE_64', +] + +# arch +ARCH_6502 = "6502" +ARCH_6805 = "6805" +ARCH_6809 = "6809" +ARCH_8048 = "8048" +ARCH_8051 = "8051" +ARCH_8085 = "8085" +ARCH_68020 = "68020" +ARCH_68030 = "68030" +ARCH_68040 = "68040" +ARCH_80251 = "80251" +ARCH_80390 = "80390" +ARCH_AARCH64 = "AARCH64" +ARCH_AARCH64BE = "AARCH64BE" +ARCH_ARM4_BE = "ARM4_be" +ARCH_ARM4_LE = "ARM4_le" +ARCH_ARM4T_BE = "ARM4t_be" +ARCH_ARM4T_LE = "ARM4t_le" +ARCH_ARM5_BE = "ARM5_be" +ARCH_ARM5_LE = "ARM5_le" +ARCH_ARM5T_BE = "ARM5t_be" +ARCH_ARM5T_LE = "ARM5t_le" +ARCH_ARM6_BE = "ARM6_be" +ARCH_ARM6_LE = "ARM6_le" +ARCH_ARM7_BE = "ARM7_be" +ARCH_ARM7_LE = "ARM7_le" +ARCH_ARM8_BE = "ARM8_be" +ARCH_ARM8_LE = "ARM8_le" +ARCH_AVR8 = "avr8" +ARCH_AVR8E = "avr8e" +ARCH_AVR8EIND = "avr8eind" +ARCH_AVR8XMEGA = "avr8xmega" +ARCH_AVR32A = "avr32a" +ARCH_COLDFIRE = "coldfire" +ARCH_CP1600 = "CP1600" +ARCH_CR16B = "CR16B" +ARCH_CR16C = "CR16C" +ARCH_DALVIK = "Dalvik" +ARCH_DATA_BE_64 = "data-be-64" +ARCH_DATA_LE_64 = "data-le-64" +ARCH_DSPIC30F = "dsPIC30F" +ARCH_DSPIC33C = "dsPIC33C" +ARCH_DSPIC33E = "dsPIC33E" +ARCH_DSPIC33F = "dsPIC33F" +ARCH_HC05 = "HC05" +ARCH_HC08 = "HC08" +ARCH_HCS08 = "HCS08" +ARCH_HCS12 = "HCS12" +ARCH_JVM = "JVM" +ARCH_M8C = "m8c" +ARCH_MCS96 = "MCS96" +ARCH_MIPS32BE = "mips32be" +ARCH_MIPS32LE = "mips32le" +ARCH_MIPS32R6BE = "mips32R6be" +ARCH_MIPS32R6LE = "mips32R6le" +ARCH_MIPS64BE = "mips64be" +ARCH_MIPS64LE = "mips64le" +ARCH_MX51 = "mx51" +ARCH_PA_RISC32BE = "pa-risc32be" +ARCH_PIC12C5XX = "pic12c5xx" +ARCH_PIC16 = "pic16" +ARCH_PIC16C5X = "pic16c5x" +ARCH_PIC16F = "pic16f" +ARCH_PIC17C7XX = "pic17c7xx" +ARCH_PIC18 = "pic18" +ARCH_PIC24E = "PIC24E" +ARCH_PIC24F = "PIC24F" +ARCH_PIC24H = "PIC24H" +ARCH_PPC_32_4XX_BE = "ppc_32_4xx_be" +ARCH_PPC_32_4XX_LE = "ppc_32_4xx_le" +ARCH_PPC_32_BE = "ppc_32_be" +ARCH_PPC_32_LE = "ppc_32_le" +ARCH_PPC_32_QUICCIII_BE = "ppc_32_quicciii_be" +ARCH_PPC_32_QUICCIII_LE = "ppc_32_quicciii_le" +ARCH_PPC_64_BE = "ppc_64_be" +ARCH_PPC_64_ISA_ALTIVEC_BE = "ppc_64_isa_altivec_be" +ARCH_PPC_64_ISA_ALTIVEC_LE = "ppc_64_isa_altivec_le" +ARCH_PPC_64_ISA_ALTIVEC_VLE_BE = "ppc_64_isa_altivec_vle_be" +ARCH_PPC_64_ISA_BE = "ppc_64_isa_be" +ARCH_PPC_64_ISA_LE = "ppc_64_isa_le" +ARCH_PPC_64_ISA_VLE_BE = "ppc_64_isa_vle_be" +ARCH_PPC_64_LE = "ppc_64_le" +ARCH_RISCV = "riscv" +ARCH_SH_1 = "sh-1" +ARCH_SH_2 = "sh-2" +ARCH_SH_2A = "sh-2a" +ARCH_SPARCV9_32 = "SparcV9_32" +ARCH_SPARCV9_64 = "SparcV9_64" +ARCH_SUPERH4_BE = "SuperH4_be" +ARCH_SUPERH4_LE = "SuperH4_le" +ARCH_TI_MSP430 = "TI_MSP430" +ARCH_TI_MSP430X = "TI_MSP430X" +ARCH_TOY_BE_POSSTACK = "toy_be_posStack" +ARCH_TOY_BE = "toy_be" +ARCH_TOY_BUILDER_BE_ALIGN2 = "toy_builder_be_align2" +ARCH_TOY_BUILDER_BE = "toy_builder_be" +ARCH_TOY_BUILDER_LE_ALIGN2 = "toy_builder_le_align2" +ARCH_TOY_BUILDER_LE = "toy_builder_le" +ARCH_TOY_LE = "toy_le" +ARCH_TOY_WSZ_BE = "toy_wsz_be" +ARCH_TOY_WSZ_LE = "toy_wsz_le" +ARCH_TOY64_BE_HARVARD = "toy64_be_harvard" +ARCH_TOY64_BE = "toy64_be" +ARCH_TOY64_LE = "toy64_le" +ARCH_TRICORE = "tricore" +ARCH_V850 = "V850" +ARCH_X86_64 = "x86-64" +ARCH_X86 = "x86" +ARCH_Z80 = "z80" +ARCH_Z180 = "z180" + +# disasm mode +MODE_16 = 0 +MODE_32 = 1 +MODE_64 = 2 + diff --git a/bindings/python/src/lib.rs b/bindings/python/src/lib.rs index bca001c..5735c4a 100644 --- a/bindings/python/src/lib.rs +++ b/bindings/python/src/lib.rs @@ -1,12 +1,12 @@ // // Copyright 2021 StarCrossTech -// +// // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -17,10 +17,9 @@ use pyo3::class::basic::PyObjectProtocol; use pyo3::prelude::*; use pyo3::types::{PyList, PyLong, PyUnicode}; use sleighcraft::error::Error; -use sleighcraft::{ - arch, CollectingAssemblyEmit, CollectingPcodeEmit, PlainLoadImage, SleighBuilder, -}; +use sleighcraft::{arch, CollectingAssemblyEmit, CollectingPcodeEmit, PlainLoadImage, SleighBuilder, Mode}; use sleighcraft::{Address, Instruction, PcodeInstruction, PcodeVarnodeData}; +use std::convert::TryFrom; #[pyclass] #[derive(Clone, PartialEq, Eq)] @@ -263,18 +262,24 @@ impl PyInstruction { pub struct Sleigh { spec: Option, code: Option>, + mode: Option } #[pymethods] impl Sleigh { #[new] - pub fn new(spec: &PyUnicode, code: &PyList) -> Self { + #[args(mode = "0")] + pub fn new(spec: &PyUnicode, code: &PyList, mode: i32) -> Self { let sp: &str = spec.extract().unwrap(); let spec = arch(sp); let codes: Vec = code.extract().unwrap(); let spec = Option::from(spec.unwrap().to_string()); + let mode = { + let mode =Mode::try_from(mode); + mode.ok() + }; let code = Option::from(codes); - Sleigh { spec, code } + Sleigh { spec, code, mode} } #[text_signature = "($self, start, cnt)"] @@ -285,6 +290,7 @@ impl Sleigh { let mut loader = PlainLoadImage::from_buf(self.code.as_ref().unwrap().as_ref(), start); sleigh_builder.loader(&mut loader); sleigh_builder.spec(self.spec.as_ref().unwrap().as_str()); + sleigh_builder.mode(self.mode.unwrap()); let mut asm_emit = CollectingAssemblyEmit::default(); let mut pcode_emit = CollectingPcodeEmit::default(); diff --git a/sleighcraft/Cargo.toml b/sleighcraft/Cargo.toml index 72157ac..3d7e8a5 100644 --- a/sleighcraft/Cargo.toml +++ b/sleighcraft/Cargo.toml @@ -13,6 +13,7 @@ repository = "https://github.com/ret2lab/bincraft/" [dependencies] cxx = "1.0" once_cell = "1.6.0" +num_enum = "0.5.1" [dependencies.pyo3] version = "0.13.2" diff --git a/sleighcraft/src/cpp/bridge/disasm.cpp b/sleighcraft/src/cpp/bridge/disasm.cpp index 51b1f77..ff45fc1 100644 --- a/sleighcraft/src/cpp/bridge/disasm.cpp +++ b/sleighcraft/src/cpp/bridge/disasm.cpp @@ -18,7 +18,7 @@ #include #include "proxies/address_proxy.hh" -void SleighProxy::set_spec(const rust::Str spec_content) { +void SleighProxy::set_spec(const rust::Str spec_content, int mode) { stringstream ss; ss << spec_content; @@ -26,14 +26,20 @@ void SleighProxy::set_spec(const rust::Str spec_content) { storage.registerTag(root); translator.initialize(storage); + + this->ctx.setVariableDefault("addrsize",mode); + this->ctx.setVariableDefault("opsize",mode); } -void SleighProxy::setSpecFromPath(const rust::Str path) { +void SleighProxy::setSpecFromPath(const rust::Str path,int mode) { string cxxpath = string(path); Element *root = storage.openDocument(cxxpath)->getRoot(); storage.registerTag(root); translator.initialize(storage); + + this->ctx.setVariableDefault("addrsize",mode); // Address size is 32-bit + this->ctx.setVariableDefault("opsize",mode); // Operand size is 32-bit } unique_ptr new_sleigh_proxy(RustLoadImage &ld) { diff --git a/sleighcraft/src/cpp/bridge/disasm.h b/sleighcraft/src/cpp/bridge/disasm.h index dc89ee9..3ed173e 100644 --- a/sleighcraft/src/cpp/bridge/disasm.h +++ b/sleighcraft/src/cpp/bridge/disasm.h @@ -96,8 +96,8 @@ class SleighProxy { public: SleighProxy(RustLoadImage &ld): loader(ld), translator(&loader, &this->ctx) {} - void setSpecFromPath(const rust::Str path); - void set_spec(const rust::Str spec_content); + void setSpecFromPath(const rust::Str path, int mode); + void set_spec(const rust::Str spec_content, int mode); void decode_with(RustAssemblyEmit& asm_emit, RustPcodeEmit& pcode_emit, uint64_t start); private: diff --git a/sleighcraft/src/sleigh.rs b/sleighcraft/src/sleigh.rs index 831605b..6b25ce2 100644 --- a/sleighcraft/src/sleigh.rs +++ b/sleighcraft/src/sleigh.rs @@ -1,12 +1,12 @@ // // Copyright 2021 StarCrossTech -// +// // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -388,7 +388,7 @@ pub mod ffi { // fn get_body(self: &InstructionProxy) -> &CxxString; type SleighProxy; - fn set_spec(self: Pin<&mut SleighProxy>, spec_content: &str); + fn set_spec(self: Pin<&mut SleighProxy>, spec_content: &str, mode: i32); fn new_sleigh_proxy(ld: &mut RustLoadImage) -> UniquePtr; fn decode_with( self: Pin<&mut SleighProxy>, @@ -402,6 +402,8 @@ pub mod ffi { use ffi::*; use std::borrow::BorrowMut; use std::pin::Pin; +use num_enum::TryFromPrimitive; +use crate::Mode::MODE16; impl ToString for PcodeOpCode { fn to_string(&self) -> String { @@ -483,6 +485,17 @@ impl ToString for PcodeOpCode { } } +#[derive(TryFromPrimitive,Copy, Clone)] +#[repr(i32)] +pub enum Mode { + // Default Address size is 16-bit + MODE16 = 0, + // Address size is 32-bit + MODE32 = 1, + // Address size is 32-bit + MODE64 = 2, +} + pub trait AssemblyEmit { fn dump(&mut self, addr: &AddressProxy, mnem: &str, body: &str); } @@ -673,7 +686,6 @@ impl LoadImage for PlainLoadImage { let size = ptr.len(); let max = self.start + (self.buf.len() as u64 - 1); - for i in 0..size { let cur_off = start_off + i as u64; if self.start <= cur_off && max >= cur_off { @@ -876,6 +888,7 @@ pub struct SleighBuilder<'a> { pcode_emit: Option>, load_image: Option>, spec: Option, + mode: Option, } impl<'a> SleighBuilder<'a> { // TODO: add from_arch(arch_name: &str) -> Self helper function. @@ -890,6 +903,11 @@ impl<'a> SleighBuilder<'a> { self } + pub fn mode(&mut self, mode: Mode) -> &mut Self { + self.mode = Some(mode); + self + } + pub fn spec(&mut self, spec: &str) -> &mut Self { // self.load_image = unsafe{Some(Box::from_raw(loader))}; self.spec = Some(spec.to_string()); @@ -901,7 +919,7 @@ impl<'a> SleighBuilder<'a> { self } - pub fn try_build(self) -> Result> { + pub fn try_build(mut self) -> Result> { let load_image = self .load_image .ok_or(Error::MissingArg("load_image".to_string()))?; @@ -909,7 +927,14 @@ impl<'a> SleighBuilder<'a> { let mut sleigh_proxy = new_sleigh_proxy(&mut load_image); let spec = self.spec.ok_or(Error::MissingArg("spec".to_string()))?; - sleigh_proxy.as_mut().unwrap().set_spec(spec.as_str()); + if self.mode.is_none() { + // Set default address and Operand size + self.mode = Some(MODE16); + }; + sleigh_proxy + .as_mut() + .unwrap() + .set_spec(spec.as_str(), self.mode.unwrap() as i32); let asm_emit = self .asm_emit diff --git a/sleighcraft/tests/mod.rs b/sleighcraft/tests/mod.rs index 4ff6a1d..01b5869 100644 --- a/sleighcraft/tests/mod.rs +++ b/sleighcraft/tests/mod.rs @@ -1,4 +1,5 @@ use sleighcraft::prelude::*; +use sleighcraft::Mode::{MODE32, MODE64}; // #[test] // fn test_custom_spec() { @@ -48,3 +49,45 @@ fn test_x86_case_ignoring() { println!("{:?}", asm_emit.asms); println!("{:?}", pcode_emit.pcode_asms); } + +#[test] +fn test_x86_32_bit() { + let mut sleigh_builder = SleighBuilder::default(); + let spec = arch("x86").unwrap(); + let buf = [0x90, 0x32, 0x31]; + let mut loader = PlainLoadImage::from_buf(&buf, 0); + sleigh_builder.loader(&mut loader); + sleigh_builder.spec(spec); + sleigh_builder.mode(MODE32); + let mut asm_emit = CollectingAssemblyEmit::default(); + let mut pcode_emit = CollectingPcodeEmit::default(); + sleigh_builder.asm_emit(&mut asm_emit); + sleigh_builder.pcode_emit(&mut pcode_emit); + let mut sleigh = sleigh_builder.try_build().unwrap(); + + sleigh.decode(0).unwrap(); + + println!("{:?}", asm_emit.asms); + println!("{:?}", pcode_emit.pcode_asms); +} + +#[test] +fn test_x86_64_bit() { + let mut sleigh_builder = SleighBuilder::default(); + let spec = arch("x86-64").unwrap(); + let buf = [72, 49, 192]; + let mut loader = PlainLoadImage::from_buf(&buf, 0); + sleigh_builder.loader(&mut loader); + sleigh_builder.spec(spec); + sleigh_builder.mode(MODE64); + let mut asm_emit = CollectingAssemblyEmit::default(); + let mut pcode_emit = CollectingPcodeEmit::default(); + sleigh_builder.asm_emit(&mut asm_emit); + sleigh_builder.pcode_emit(&mut pcode_emit); + let mut sleigh = sleigh_builder.try_build().unwrap(); + + sleigh.decode(0).unwrap(); + + println!("{:?}", asm_emit.asms); + println!("{:?}", pcode_emit.pcode_asms); +}