Compare commits
5 Commits
727c87ecc4
...
ba14104087
Author | SHA1 | Date |
---|---|---|
Anichitei Ionel-Cristinel | ba14104087 | 3 months ago |
Andrei KISARI | 698686ab14 | 3 months ago |
Anichitei Ionel-Cristinel | fbe5c1375d | 3 months ago |
Anichitei Ionel-Cristinel | 570fa2bb62 | 3 months ago |
Andrei Vlad LUTAS | fad9c7e35c | 3 months ago |
@ -0,0 +1,54 @@
|
||||
# Changelog
|
||||
|
||||
All notable (user-facing) changes to this project will be documented in this file.
|
||||
|
||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
||||
|
||||
|
||||
|
||||
## [2.1.0] - 2024-02-20
|
||||
|
||||
### Added
|
||||
- Support in bddisasm for Intel REX2 prefix.
|
||||
- Support in bddisasm for Intel APX extensions.
|
||||
- Support in bddisasm for Intel USERMSR extensions.
|
||||
- Support in bddisasm for prefix activation fields inside `INSTRUX` - these fields can be consulted to determine whether a particular prefix is present, accepted & active.
|
||||
- New feature in bdshemu: `SHEMU_OPT_DIRECT_MAPPED_SHELL` - allows emulation with a smaller `IntBuff` at the cost of not having `WRITE_SELF` detections. The shellcode can be provided directly from its original location, without the need to allocate it in a dedicated memory region.
|
||||
- New feature in bdshemu: `SHEMU_OPT_TRACK_LOOPS` - loops can now be tracked by bdshemu. `SHEMU_OPT_TRACE_LOOPS` can be used to log loop information.
|
||||
- Support in bdshemu for APX instructions (both REX2 and EVEX encoded instructions) - the new `SHEMU_OPT_SUPPORT_APX` must be set in order to enable APX emulation.
|
||||
|
||||
### Changed
|
||||
- Reduced the size of the `INSTRUX` structure from 856 bytes to 488 bytes (almost -43%!).
|
||||
- Increased decoding performance from average 300 clocks/instruction to average 235 clocks/instruction (almost +20%!).
|
||||
- New decode options - do not decode implicit operands - this further increases performance from average 235 clocks/instruction to 200 clocks/instruction (almost +15%!).
|
||||
- Re-worked the Python scripts - both `disasmlib.py` and `generate_tables.py` have been significantly reworked, improving readability, and making them more efficient.
|
||||
- `disasmtool` builds on Linux.
|
||||
|
||||
### Removed
|
||||
- Support for Cyrix & VIA instructions - only current Intel & AMD instructions remain supported.
|
||||
- disasmtool_lix has been removed. `disasmtool` is available on Linux as well.
|
||||
|
||||
### Breaking changes
|
||||
|
||||
#### Inside INSTRUX
|
||||
- Removed `Iclass` field - it was aliased over `Instruction` field, which must be used from now on.
|
||||
- Removed `OperandsEncodingMap` field - one can consult the `Encoding` field in each operand to determine the encoding.
|
||||
- Removed `ExceptionClass` field - only `ExceptionType` remains, which contains an enum with all the exception types.
|
||||
- Removed `Predicate` field - only `Condition` remains, which was aliased over `Predicate`.
|
||||
- Removed `HasImm3`, `Immediate3`, `Imm3Length` and `Imm3Offset` fields, as they were not used/needed.
|
||||
- Removed `Bhint`, `SseCondition`, `SignDisp` fields, as they were not used.
|
||||
- Moved `FlagsAccess.RegAccess` outside and renamed it to `RflAccess`, to save more space.
|
||||
- Switched from `char Mnemonic[32]` to `const char *Mnemonic` - this decreases INSTRUX size by almost 32 bytes, and increases perf.
|
||||
|
||||
#### Inside ND_OPERAND
|
||||
- Removed `RawSize` - in most cases, `Size` and `RawSize` are identical; the only case where they might differ is for `Immediate` and `RelativeOffset` operands - in that case, one can consult the `RawSize` field in `Immediate` or `RelativeOffset`.
|
||||
|
||||
#### Inside ND_OPERAND_DECORATOR
|
||||
- Removed `Broadcast` field, moved it inside `ND_OPDESC_MEMORY`.
|
||||
- Removed `HasSae`, `HasEr` - they are per instruction, not per operand, and can be consulted directly inside `INSTRUX`.
|
||||
- Moved `Msk` one level up, inside the `ND_OPERAND_DECORATOR` structure.
|
||||
|
||||
#### Defines & constants
|
||||
- Removed `ND_PRED_*` defines - search & replace them with `ND_COND_*`.
|
||||
- Removed `ND_HAS_PREDICATE` - use `ND_HAS_CONDITION` instead.
|
||||
- Removed `ND_VEND_GEODE` and `ND_VEND_CYRIX`.
|
@ -0,0 +1,118 @@
|
||||
FROM ubuntu:22.04 as build
|
||||
|
||||
WORKDIR /bddfuzz
|
||||
|
||||
# Install everything we need to build AFL++ and honggfuzz and bdshemu
|
||||
# We install both clang-13 and clang-15 because honggfuzz does not support newer versions of clang, but AFL++ wants
|
||||
# the latest version so it is what it is
|
||||
RUN apt-get update && apt-get install -y \
|
||||
cmake make git \
|
||||
binutils-dev \
|
||||
libunwind-dev \
|
||||
libblocksruntime-dev \
|
||||
clang-13 \
|
||||
clang-15 \
|
||||
llvm-15 llvm-15-dev llvm-15-linker-tools llvm-15-runtime llvm-15-tools lld-15
|
||||
|
||||
# Cleanup
|
||||
RUN apt-get clean && rm -rf /var/lib/apt/lists/*
|
||||
|
||||
RUN mkdir /bddfuzz/fuzzers
|
||||
|
||||
# Build and install AFL++
|
||||
RUN cd /bddfuzz/fuzzers && git clone https://github.com/AFLplusplus/AFLplusplus.git
|
||||
RUN cd /bddfuzz/fuzzers/AFLplusplus && \
|
||||
CC=clang-15 CXX=clang++-15 make source-only install LLVM_CONFIG=llvm-config-15 NO_NYX=1
|
||||
|
||||
# Build and install honggfuzz
|
||||
RUN cd /bddfuzz/fuzzers && git clone --depth 1 --branch 2.5 https://github.com/google/honggfuzz.git
|
||||
RUN cd /bddfuzz/fuzzers/honggfuzz && make install
|
||||
|
||||
# Remove the fuzzer source files as we no longer need them
|
||||
RUN cd /bddfuzz/fuzzers/AFLplusplus && git clean -dxf && git clean -dXf && rm -rf /bddfuzz/fuzzers/AFLplusplus
|
||||
RUN rm -rf /bddfuzz/fuzzers/honggfuzz
|
||||
RUN rm -rf /bddfuzz/fuzzers/
|
||||
|
||||
ENV SRC /bddfuzz/src/
|
||||
|
||||
# Copy the relevant bddisasm sources
|
||||
RUN mkdir "${SRC}"
|
||||
|
||||
COPY CMakeLists.txt "${SRC}"/CMakeLists.txt
|
||||
COPY bddisasm.pc.in "${SRC}"/bddisasm.pc.in
|
||||
COPY bddisasmConfig.cmake "${SRC}"/bddisasmConfig.cmake
|
||||
COPY bddisasm "${SRC}"/bddisasm
|
||||
COPY bdshemu "${SRC}"/bdshemu
|
||||
COPY bdshemu_fuzz "${SRC}"/bdshemu_fuzz
|
||||
COPY inc "${SRC}"/inc
|
||||
|
||||
# Now build all the variants
|
||||
RUN mkdir build
|
||||
|
||||
# Build for AFL++ with afl-clang-lto
|
||||
RUN mkdir /bddfuzz/build/afllto && cd /bddfuzz/build/afllto && \
|
||||
cmake "${SRC}" -DCMAKE_C_COMPILER=afl-clang-lto -DCMAKE_CXX_COMPILER=afl-clang-lto++ \
|
||||
-DCMAKE_BUILD_TYPE=Releaase \
|
||||
-DBDD_INCLUDE_TOOL=OFF -DBDD_INCLUDE_ISAGENERATOR_X86=OFF \
|
||||
-DBDD_INCLUDE_FUZZERS=ON && \
|
||||
make shfuzz
|
||||
|
||||
# Build for honggfuzz
|
||||
RUN mkdir /bddfuzz/build/hfuzz && cd /bddfuzz/build/hfuzz && \
|
||||
cmake "${SRC}" -DCMAKE_C_COMPILER=hfuzz-clang -DCMAKE_CXX_COMPILER=hfuzz-clang++ \
|
||||
-DCMAKE_BUILD_TYPE=Releaase \
|
||||
-DBDD_INCLUDE_TOOL=OFF -DBDD_INCLUDE_ISAGENERATOR_X86=OFF \
|
||||
-DBDD_INCLUDE_FUZZERS=ON && \
|
||||
make shfuzz
|
||||
|
||||
# Build for libfuzzer with ASAN and UBSAN
|
||||
RUN mkdir /bddfuzz/build/san && cd /bddfuzz/build/san && \
|
||||
cmake "${SRC}" -DCMAKE_C_COMPILER=clang-15 -DCMAKE_CXX_COMPILER=clang-15++ \
|
||||
-DCMAKE_BUILD_TYPE=Releaase \
|
||||
-DBDD_INCLUDE_TOOL=OFF -DBDD_INCLUDE_ISAGENERATOR_X86=OFF \
|
||||
-DBDD_INCLUDE_FUZZERS=ON -DBDD_FUZZ_WITH_LOGS=ON \
|
||||
-DBDD_ASAN=ON -DBDD_UBSAN=ON && \
|
||||
make shfuzz
|
||||
|
||||
RUN rm -rf "${SRC}"
|
||||
|
||||
# Save the fuzzers
|
||||
RUN mkdir /bddfuzz/shf && cd /bddfuzz/shf && \
|
||||
for d in /bddfuzz/build/*; do \
|
||||
mkdir ./`basename "${d}"` && \
|
||||
cp -v "${d}"/bdshemu_fuzz/shfuzz* ./`basename "${d}"`; \
|
||||
done
|
||||
|
||||
# Remove the build directory
|
||||
RUN rm -rf build
|
||||
|
||||
FROM ubuntu:22.04 as run
|
||||
|
||||
WORKDIR /bddfuzz
|
||||
|
||||
# Copy the fuzzers from the build stage
|
||||
COPY --from=build /bddfuzz/shf /bddfuzz/shf
|
||||
|
||||
# Copy AFL++ and honggfuzz binaries
|
||||
COPY --from=build /usr/local/bin/afl-* /usr/local/bin/
|
||||
COPY --from=build /usr/local/bin/hfuzz-* /usr/local/bin/
|
||||
COPY --from=build /usr/local/bin/honggfuzz /usr/local/bin/
|
||||
|
||||
RUN mkdir /bddfuzz/inputs
|
||||
COPY bdshemu_fuzz/in-32 /bddfuzz/inputs/in-32
|
||||
COPY bdshemu_fuzz/in-64 /bddfuzz/inputs/in-64
|
||||
|
||||
# Runtime dependencies for honggfuzz
|
||||
RUN apt-get update && apt-get install -y binutils-dev libunwind-dev libblocksruntime-dev
|
||||
|
||||
# Cleanup
|
||||
RUN apt-get clean && rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# So we can share files between the host and the container (we don't want to loose the results when we stop the
|
||||
# container).
|
||||
ENV SHARE_DIR share
|
||||
|
||||
COPY bdshemu_fuzz/fuzzing_image_entrypoint.sh /bddfuzz/fuzzing_image_entrypoint.sh
|
||||
RUN chmod +x /bddfuzz/fuzzing_image_entrypoint.sh
|
||||
|
||||
ENTRYPOINT ["/bddfuzz/fuzzing_image_entrypoint.sh"]
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Binary file not shown.
@ -0,0 +1,224 @@
|
||||
0000000000000000 626c7808fc1e AADD dword ptr [r22], r27d
|
||||
DSIZE: 32, ASIZE: 64, VLEN: -
|
||||
ISA Set: APX_F, Ins cat: RAO-INT, CET tracked: no
|
||||
CPUID leaf: 0x00000007, sub-leaf: 0x00000001, reg: edx, bit: 21
|
||||
EVEX Tuple Type: None
|
||||
Exception class: APX, exception type: APX-EVEX-RAO-INT
|
||||
Valid modes
|
||||
R0: yes, R1: yes, R2: yes, R3: yes
|
||||
Real: no, V8086: no, Prot: yes, Compat: yes, Long: yes
|
||||
SMM on: yes, SMM off: yes, SGX on: yes, SGX off: yes, TSX on: yes, TSX off: yes
|
||||
VMXRoot: yes, VMXNonRoot: yes, VMXRoot SEAM: yes, VMXNonRoot SEAM: yes, VMX off: yes
|
||||
Valid prefixes
|
||||
REP: no, REPcc: no, LOCK: no
|
||||
HLE: no, XACQUIRE only: no, XRELEASE only: no
|
||||
BND: no, BHINT: no, DNT: no
|
||||
Operand: 0, Acc: RW, Type: Memory, Size: 4, RawSize: 4, Encoding: M,
|
||||
Segment: 3, Base: 22,
|
||||
Operand: 1, Acc: R-, Type: Register, Size: 4, RawSize: 4, Encoding: R, RegType: General Purpose, RegSize: 4, RegId: 27, RegCount: 1
|
||||
|
||||
0000000000000006 626cf808fc1e AADD qword ptr [r22], r27
|
||||
DSIZE: 64, ASIZE: 64, VLEN: -
|
||||
ISA Set: APX_F, Ins cat: RAO-INT, CET tracked: no
|
||||
CPUID leaf: 0x00000007, sub-leaf: 0x00000001, reg: edx, bit: 21
|
||||
EVEX Tuple Type: None
|
||||
Exception class: APX, exception type: APX-EVEX-RAO-INT
|
||||
Valid modes
|
||||
R0: yes, R1: yes, R2: yes, R3: yes
|
||||
Real: no, V8086: no, Prot: yes, Compat: yes, Long: yes
|
||||
SMM on: yes, SMM off: yes, SGX on: yes, SGX off: yes, TSX on: yes, TSX off: yes
|
||||
VMXRoot: yes, VMXNonRoot: yes, VMXRoot SEAM: yes, VMXNonRoot SEAM: yes, VMX off: yes
|
||||
Valid prefixes
|
||||
REP: no, REPcc: no, LOCK: no
|
||||
HLE: no, XACQUIRE only: no, XRELEASE only: no
|
||||
BND: no, BHINT: no, DNT: no
|
||||
Operand: 0, Acc: RW, Type: Memory, Size: 8, RawSize: 8, Encoding: M,
|
||||
Segment: 3, Base: 22,
|
||||
Operand: 1, Acc: R-, Type: Register, Size: 8, RawSize: 8, Encoding: R, RegType: General Purpose, RegSize: 8, RegId: 27, RegCount: 1
|
||||
|
||||
000000000000000C 626c7908fc1e AAND dword ptr [r22], r27d
|
||||
DSIZE: 32, ASIZE: 64, VLEN: -
|
||||
ISA Set: APX_F, Ins cat: RAO-INT, CET tracked: no
|
||||
CPUID leaf: 0x00000007, sub-leaf: 0x00000001, reg: edx, bit: 21
|
||||
EVEX Tuple Type: None
|
||||
Exception class: APX, exception type: APX-EVEX-RAO-INT
|
||||
Valid modes
|
||||
R0: yes, R1: yes, R2: yes, R3: yes
|
||||
Real: no, V8086: no, Prot: yes, Compat: yes, Long: yes
|
||||
SMM on: yes, SMM off: yes, SGX on: yes, SGX off: yes, TSX on: yes, TSX off: yes
|
||||
VMXRoot: yes, VMXNonRoot: yes, VMXRoot SEAM: yes, VMXNonRoot SEAM: yes, VMX off: yes
|
||||
Valid prefixes
|
||||
REP: no, REPcc: no, LOCK: no
|
||||
HLE: no, XACQUIRE only: no, XRELEASE only: no
|
||||
BND: no, BHINT: no, DNT: no
|
||||
Operand: 0, Acc: RW, Type: Memory, Size: 4, RawSize: 4, Encoding: M,
|
||||
Segment: 3, Base: 22,
|
||||
Operand: 1, Acc: R-, Type: Register, Size: 4, RawSize: 4, Encoding: R, RegType: General Purpose, RegSize: 4, RegId: 27, RegCount: 1
|
||||
|
||||
0000000000000012 626cf908fc1e AAND qword ptr [r22], r27
|
||||
DSIZE: 64, ASIZE: 64, VLEN: -
|
||||
ISA Set: APX_F, Ins cat: RAO-INT, CET tracked: no
|
||||
CPUID leaf: 0x00000007, sub-leaf: 0x00000001, reg: edx, bit: 21
|
||||
EVEX Tuple Type: None
|
||||
Exception class: APX, exception type: APX-EVEX-RAO-INT
|
||||
Valid modes
|
||||
R0: yes, R1: yes, R2: yes, R3: yes
|
||||
Real: no, V8086: no, Prot: yes, Compat: yes, Long: yes
|
||||
SMM on: yes, SMM off: yes, SGX on: yes, SGX off: yes, TSX on: yes, TSX off: yes
|
||||
VMXRoot: yes, VMXNonRoot: yes, VMXRoot SEAM: yes, VMXNonRoot SEAM: yes, VMX off: yes
|
||||
Valid prefixes
|
||||
REP: no, REPcc: no, LOCK: no
|
||||
HLE: no, XACQUIRE only: no, XRELEASE only: no
|
||||
BND: no, BHINT: no, DNT: no
|
||||
Operand: 0, Acc: RW, Type: Memory, Size: 8, RawSize: 8, Encoding: M,
|
||||
Segment: 3, Base: 22,
|
||||
Operand: 1, Acc: R-, Type: Register, Size: 8, RawSize: 8, Encoding: R, RegType: General Purpose, RegSize: 8, RegId: 27, RegCount: 1
|
||||
|
||||
0000000000000018 626c7b08fc1e AOR dword ptr [r22], r27d
|
||||
DSIZE: 32, ASIZE: 64, VLEN: -
|
||||
ISA Set: APX_F, Ins cat: RAO-INT, CET tracked: no
|
||||
CPUID leaf: 0x00000007, sub-leaf: 0x00000001, reg: edx, bit: 21
|
||||
EVEX Tuple Type: None
|
||||
Exception class: APX, exception type: APX-EVEX-RAO-INT
|
||||
Valid modes
|
||||
R0: yes, R1: yes, R2: yes, R3: yes
|
||||
Real: no, V8086: no, Prot: yes, Compat: yes, Long: yes
|
||||
SMM on: yes, SMM off: yes, SGX on: yes, SGX off: yes, TSX on: yes, TSX off: yes
|
||||
VMXRoot: yes, VMXNonRoot: yes, VMXRoot SEAM: yes, VMXNonRoot SEAM: yes, VMX off: yes
|
||||
Valid prefixes
|
||||
REP: no, REPcc: no, LOCK: no
|
||||
HLE: no, XACQUIRE only: no, XRELEASE only: no
|
||||
BND: no, BHINT: no, DNT: no
|
||||
Operand: 0, Acc: RW, Type: Memory, Size: 4, RawSize: 4, Encoding: M,
|
||||
Segment: 3, Base: 22,
|
||||
Operand: 1, Acc: R-, Type: Register, Size: 4, RawSize: 4, Encoding: R, RegType: General Purpose, RegSize: 4, RegId: 27, RegCount: 1
|
||||
|
||||
000000000000001E 626cfb08fc1e AOR qword ptr [r22], r27
|
||||
DSIZE: 64, ASIZE: 64, VLEN: -
|
||||
ISA Set: APX_F, Ins cat: RAO-INT, CET tracked: no
|
||||
CPUID leaf: 0x00000007, sub-leaf: 0x00000001, reg: edx, bit: 21
|
||||
EVEX Tuple Type: None
|
||||
Exception class: APX, exception type: APX-EVEX-RAO-INT
|
||||
Valid modes
|
||||
R0: yes, R1: yes, R2: yes, R3: yes
|
||||
Real: no, V8086: no, Prot: yes, Compat: yes, Long: yes
|
||||
SMM on: yes, SMM off: yes, SGX on: yes, SGX off: yes, TSX on: yes, TSX off: yes
|
||||
VMXRoot: yes, VMXNonRoot: yes, VMXRoot SEAM: yes, VMXNonRoot SEAM: yes, VMX off: yes
|
||||
Valid prefixes
|
||||
REP: no, REPcc: no, LOCK: no
|
||||
HLE: no, XACQUIRE only: no, XRELEASE only: no
|
||||
BND: no, BHINT: no, DNT: no
|
||||
Operand: 0, Acc: RW, Type: Memory, Size: 8, RawSize: 8, Encoding: M,
|
||||
Segment: 3, Base: 22,
|
||||
Operand: 1, Acc: R-, Type: Register, Size: 8, RawSize: 8, Encoding: R, RegType: General Purpose, RegSize: 8, RegId: 27, RegCount: 1
|
||||
|
||||
0000000000000024 626c7a08fc1e AXOR dword ptr [r22], r27d
|
||||
DSIZE: 32, ASIZE: 64, VLEN: -
|
||||
ISA Set: APX_F, Ins cat: RAO-INT, CET tracked: no
|
||||
CPUID leaf: 0x00000007, sub-leaf: 0x00000001, reg: edx, bit: 21
|
||||
EVEX Tuple Type: None
|
||||
Exception class: APX, exception type: APX-EVEX-RAO-INT
|
||||
Valid modes
|
||||
R0: yes, R1: yes, R2: yes, R3: yes
|
||||
Real: no, V8086: no, Prot: yes, Compat: yes, Long: yes
|
||||
SMM on: yes, SMM off: yes, SGX on: yes, SGX off: yes, TSX on: yes, TSX off: yes
|
||||
VMXRoot: yes, VMXNonRoot: yes, VMXRoot SEAM: yes, VMXNonRoot SEAM: yes, VMX off: yes
|
||||
Valid prefixes
|
||||
REP: no, REPcc: no, LOCK: no
|
||||
HLE: no, XACQUIRE only: no, XRELEASE only: no
|
||||
BND: no, BHINT: no, DNT: no
|
||||
Operand: 0, Acc: RW, Type: Memory, Size: 4, RawSize: 4, Encoding: M,
|
||||
Segment: 3, Base: 22,
|
||||
Operand: 1, Acc: R-, Type: Register, Size: 4, RawSize: 4, Encoding: R, RegType: General Purpose, RegSize: 4, RegId: 27, RegCount: 1
|
||||
|
||||
000000000000002A 626cfa08fc1e AXOR qword ptr [r22], r27
|
||||
DSIZE: 64, ASIZE: 64, VLEN: -
|
||||
ISA Set: APX_F, Ins cat: RAO-INT, CET tracked: no
|
||||
CPUID leaf: 0x00000007, sub-leaf: 0x00000001, reg: edx, bit: 21
|
||||
EVEX Tuple Type: None
|
||||
Exception class: APX, exception type: APX-EVEX-RAO-INT
|
||||
Valid modes
|
||||
R0: yes, R1: yes, R2: yes, R3: yes
|
||||
Real: no, V8086: no, Prot: yes, Compat: yes, Long: yes
|
||||
SMM on: yes, SMM off: yes, SGX on: yes, SGX off: yes, TSX on: yes, TSX off: yes
|
||||
VMXRoot: yes, VMXNonRoot: yes, VMXRoot SEAM: yes, VMXNonRoot SEAM: yes, VMX off: yes
|
||||
Valid prefixes
|
||||
REP: no, REPcc: no, LOCK: no
|
||||
HLE: no, XACQUIRE only: no, XRELEASE only: no
|
||||
BND: no, BHINT: no, DNT: no
|
||||
Operand: 0, Acc: RW, Type: Memory, Size: 8, RawSize: 8, Encoding: M,
|
||||
Segment: 3, Base: 22,
|
||||
Operand: 1, Acc: R-, Type: Register, Size: 8, RawSize: 8, Encoding: R, RegType: General Purpose, RegSize: 8, RegId: 27, RegCount: 1
|
||||
|
||||
0000000000000030 626c7b08f8de URDMSR r22, r27
|
||||
DSIZE: 32, ASIZE: 64, VLEN: -
|
||||
ISA Set: APX_F, Ins cat: USER_MSR, CET tracked: no
|
||||
CPUID leaf: 0x00000007, sub-leaf: 0x00000001, reg: edx, bit: 21
|
||||
EVEX Tuple Type: None
|
||||
Exception class: APX, exception type: APX-EVEX-USER-MSR
|
||||
Valid modes
|
||||
R0: yes, R1: yes, R2: yes, R3: yes
|
||||
Real: no, V8086: no, Prot: yes, Compat: yes, Long: yes
|
||||
SMM on: yes, SMM off: yes, SGX on: yes, SGX off: yes, TSX on: yes, TSX off: yes
|
||||
VMXRoot: yes, VMXNonRoot: yes, VMXRoot SEAM: yes, VMXNonRoot SEAM: yes, VMX off: yes
|
||||
Valid prefixes
|
||||
REP: no, REPcc: no, LOCK: no
|
||||
HLE: no, XACQUIRE only: no, XRELEASE only: no
|
||||
BND: no, BHINT: no, DNT: no
|
||||
Operand: 0, Acc: -W, Type: Register, Size: 8, RawSize: 8, Encoding: M, RegType: General Purpose, RegSize: 8, RegId: 22, RegCount: 1
|
||||
Operand: 1, Acc: R-, Type: Register, Size: 8, RawSize: 8, Encoding: R, RegType: General Purpose, RegSize: 8, RegId: 27, RegCount: 1
|
||||
|
||||
0000000000000036 62ff7b08f8c6bdbdbdbd URDMSR r22, 0xbdbdbdbd
|
||||
DSIZE: 32, ASIZE: 64, VLEN: -
|
||||
ISA Set: APX_F, Ins cat: USER_MSR, CET tracked: no
|
||||
CPUID leaf: 0x00000007, sub-leaf: 0x00000001, reg: edx, bit: 21
|
||||
EVEX Tuple Type: None
|
||||
Valid modes
|
||||
R0: yes, R1: yes, R2: yes, R3: yes
|
||||
Real: no, V8086: no, Prot: no, Compat: no, Long: yes
|
||||
SMM on: yes, SMM off: yes, SGX on: yes, SGX off: yes, TSX on: yes, TSX off: yes
|
||||
VMXRoot: yes, VMXNonRoot: yes, VMXRoot SEAM: yes, VMXNonRoot SEAM: yes, VMX off: yes
|
||||
Valid prefixes
|
||||
REP: no, REPcc: no, LOCK: no
|
||||
HLE: no, XACQUIRE only: no, XRELEASE only: no
|
||||
BND: no, BHINT: no, DNT: no
|
||||
Operand: 0, Acc: -W, Type: Register, Size: 8, RawSize: 8, Encoding: M, RegType: General Purpose, RegSize: 8, RegId: 22, RegCount: 1
|
||||
Operand: 1, Acc: R-, Type: Immediate, Size: 4, RawSize: 4, Encoding: I
|
||||
Operand: 2, Acc: R-, Type: Register, Size: 8, RawSize: 8, Encoding: E, RegType: Model Specific, RegSize: 8, RegId: 0xffffffff, RegCount: 1
|
||||
|
||||
0000000000000040 626c7a08f8de UWRMSR r27, r22
|
||||
DSIZE: 32, ASIZE: 64, VLEN: -
|
||||
ISA Set: APX_F, Ins cat: USER_MSR, CET tracked: no
|
||||
CPUID leaf: 0x00000007, sub-leaf: 0x00000001, reg: edx, bit: 21
|
||||
EVEX Tuple Type: None
|
||||
Exception class: APX, exception type: APX-EVEX-USER-MSR
|
||||
Valid modes
|
||||
R0: yes, R1: yes, R2: yes, R3: yes
|
||||
Real: no, V8086: no, Prot: yes, Compat: yes, Long: yes
|
||||
SMM on: yes, SMM off: yes, SGX on: yes, SGX off: yes, TSX on: yes, TSX off: yes
|
||||
VMXRoot: yes, VMXNonRoot: yes, VMXRoot SEAM: yes, VMXNonRoot SEAM: yes, VMX off: yes
|
||||
Valid prefixes
|
||||
REP: no, REPcc: no, LOCK: no
|
||||
HLE: no, XACQUIRE only: no, XRELEASE only: no
|
||||
BND: no, BHINT: no, DNT: no
|
||||
Operand: 0, Acc: R-, Type: Register, Size: 8, RawSize: 8, Encoding: R, RegType: General Purpose, RegSize: 8, RegId: 27, RegCount: 1
|
||||
Operand: 1, Acc: R-, Type: Register, Size: 8, RawSize: 8, Encoding: M, RegType: General Purpose, RegSize: 8, RegId: 22, RegCount: 1
|
||||
|
||||
0000000000000046 62ff7a08f8c6bdbdbdbd UWRMSR 0xbdbdbdbd, r22
|
||||
DSIZE: 32, ASIZE: 64, VLEN: -
|
||||
ISA Set: APX_F, Ins cat: USER_MSR, CET tracked: no
|
||||
CPUID leaf: 0x00000007, sub-leaf: 0x00000001, reg: edx, bit: 21
|
||||
EVEX Tuple Type: None
|
||||
Valid modes
|
||||
R0: yes, R1: yes, R2: yes, R3: yes
|
||||
Real: no, V8086: no, Prot: no, Compat: no, Long: yes
|
||||
SMM on: yes, SMM off: yes, SGX on: yes, SGX off: yes, TSX on: yes, TSX off: yes
|
||||
VMXRoot: yes, VMXNonRoot: yes, VMXRoot SEAM: yes, VMXNonRoot SEAM: yes, VMX off: yes
|
||||
Valid prefixes
|
||||
REP: no, REPcc: no, LOCK: no
|
||||
HLE: no, XACQUIRE only: no, XRELEASE only: no
|
||||
BND: no, BHINT: no, DNT: no
|
||||
Operand: 0, Acc: R-, Type: Immediate, Size: 4, RawSize: 4, Encoding: I
|
||||
Operand: 1, Acc: R-, Type: Register, Size: 8, RawSize: 8, Encoding: M, RegType: General Purpose, RegSize: 8, RegId: 22, RegCount: 1
|
||||
Operand: 2, Acc: -W, Type: Register, Size: 8, RawSize: 8, Encoding: E, RegType: Model Specific, RegSize: 8, RegId: 0xffffffff, RegCount: 1
|
||||
|
@ -0,0 +1,16 @@
|
||||
bits 64
|
||||
|
||||
; NF not supported.
|
||||
db 0x62, 0x6C, 0x78, 0x0C, 0x10, 0x1E, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,
|
||||
; V' set.
|
||||
db 0x62, 0x6C, 0x78, 0x00, 0x10, 0x1E, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,
|
||||
; VVVV set.
|
||||
db 0x62, 0x6C, 0x38, 0x08, 0x10, 0x1E, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,
|
||||
; Reserved bits set.
|
||||
db 0x62, 0x6C, 0x78, 0x09, 0x10, 0x1E, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,
|
||||
db 0x62, 0x6C, 0x78, 0x88, 0x10, 0x1E, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,
|
||||
; Invalid PUSH2 register (RSP).
|
||||
db 0x62, 0x6C, 0x58, 0x18, 0xFF, 0xF4, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,
|
||||
; Invalid POP2 registers (same dest register, RAX).
|
||||
db 0x62, 0x64, 0x78, 0x18, 0x8F, 0xC0, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,
|
||||
|
@ -0,0 +1,7 @@
|
||||
0000000000000000 62 db 0x62 (0x80000002)
|
||||
0000000000000010 62 db 0x62 (0x80000040)
|
||||
0000000000000020 62 db 0x62 (0x80000032)
|
||||
0000000000000030 62 db 0x62 (0x80000045)
|
||||
0000000000000040 62 db 0x62 (0x80000045)
|
||||
0000000000000050 62 db 0x62 (0x80000044)
|
||||
0000000000000060 62 db 0x62 (0x80000044)
|
Binary file not shown.
@ -0,0 +1,25 @@
|
||||
bits 64
|
||||
|
||||
; REX2 with REX
|
||||
db 0x48, 0xD5, 0x00, 0x33, 0xC0, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90
|
||||
; REX with REX2
|
||||
db 0xD5, 0x00, 0x48, 0x33, 0xC0, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90
|
||||
; REX2 with EVEX
|
||||
db 0xD5, 0x00, 0x62, 0x6C, 0x78, 0x08, 0x10, 0x1E, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90
|
||||
; JMPABS with prefixes
|
||||
db 0x66, 0xD5, 0x00, 0xA1, 0xBD, 0xBD, 0xBD, 0xBD, 0xBD, 0xBD, 0xBD, 0xBD, 0x90, 0x90, 0x90, 0x90
|
||||
db 0x67, 0xD5, 0x00, 0xA1, 0xBD, 0xBD, 0xBD, 0xBD, 0xBD, 0xBD, 0xBD, 0xBD, 0x90, 0x90, 0x90, 0x90
|
||||
db 0xF2, 0xD5, 0x00, 0xA1, 0xBD, 0xBD, 0xBD, 0xBD, 0xBD, 0xBD, 0xBD, 0xBD, 0x90, 0x90, 0x90, 0x90
|
||||
db 0xF3, 0xD5, 0x00, 0xA1, 0xBD, 0xBD, 0xBD, 0xBD, 0xBD, 0xBD, 0xBD, 0xBD, 0x90, 0x90, 0x90, 0x90
|
||||
; REX2 with unssuported instruction
|
||||
db 0xD5, 0x00, 0x70, 0xBD, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90
|
||||
db 0xD5, 0x80, 0x80, 0xBD, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90
|
||||
; REX2 inside legacy map 0x38 & 0x3A
|
||||
db 0xD5, 0x80, 0x38, 0xFC, 0x00, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90
|
||||
db 0xD5, 0x80, 0x3A, 0xCC, 0x00, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90
|
||||
; REX2 with extension opcode.
|
||||
db 0xD5, 0x7F, 0x0F, 0xD1, 0xC0, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90
|
||||
db 0xD5, 0x7F, 0x0F, 0x38, 0x00, 0xC0, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90
|
||||
db 0xD5, 0xFF, 0x38, 0x00, 0xC0, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90
|
||||
|
||||
|
@ -0,0 +1,14 @@
|
||||
0000000000000000 48 db 0x48 (0x80000004)
|
||||
0000000000000010 d5 db 0xd5 (0x80000009)
|
||||
0000000000000020 d5 db 0xd5 (0x80000009)
|
||||
0000000000000030 66 db 0x66 (0x80000002)
|
||||
0000000000000040 67 db 0x67 (0x80000002)
|
||||
0000000000000050 f2 db 0xf2 (0x80000002)
|
||||
0000000000000060 f3 db 0xf3 (0x80000002)
|
||||
0000000000000070 d5 db 0xd5 (0x80000002)
|
||||
0000000000000080 d5 db 0xd5 (0x80000002)
|
||||
0000000000000090 d5 db 0xd5 (0x80000002)
|
||||
00000000000000A0 d5 db 0xd5 (0x80000002)
|
||||
00000000000000B0 d5 db 0xd5 (0x80000002)
|
||||
00000000000000C0 d5 db 0xd5 (0x80000002)
|
||||
00000000000000D0 d5 db 0xd5 (0x80000002)
|
Binary file not shown.
@ -0,0 +1,32 @@
|
||||
bits 64
|
||||
|
||||
; REX2 0
|
||||
db 0xD5, 0x00, 0x33, 0xC0
|
||||
; REX2.W = 1
|
||||
db 0xD5, 0x08, 0x33, 0xC0
|
||||
; REX2.B3 & REX2.B4 set
|
||||
db 0xD5, 0x19, 0x33, 0xC0
|
||||
; REX2.R3 & REX2.R4 set
|
||||
db 0xD5, 0x4C, 0x33, 0xC0
|
||||
; REX2.X3 & REX2.X4 set, no memory
|
||||
db 0xD5, 0x2A, 0x33, 0xC0
|
||||
; REX2.X3 & REX2.X4 set, SIB access
|
||||
db 0xD5, 0x2A, 0x33, 0x04, 0x33
|
||||
; JMPABS
|
||||
db 0xD5, 0x00, 0xA1, 0xBD, 0xBD, 0xBD, 0xBD, 0xBD, 0xBD, 0xBD, 0xBD
|
||||
; PUSHP/POPP
|
||||
db 0xD5, 0x08, 0x50
|
||||
db 0xD5, 0x08, 0x58
|
||||
db 0xD5, 0x18, 0x50
|
||||
db 0xD5, 0x18, 0x58
|
||||
; PUSH/POP
|
||||
db 0xD5, 0x00, 0x50
|
||||
db 0xD5, 0x00, 0x58
|
||||
db 0xD5, 0x10, 0x50
|
||||
db 0xD5, 0x10, 0x58
|
||||
; NOP
|
||||
db 0xD5, 0x00, 0x90
|
||||
; XCHG r16, rax
|
||||
db 0xD5, 0x18, 0x90
|
||||
; RDFSBASE r31
|
||||
db 0xF3, 0xD5, 0x99, 0xAE, 0xC7
|
@ -0,0 +1,301 @@
|
||||
0000000000000000 d50033c0 XOR eax, eax
|
||||
DSIZE: 32, ASIZE: 64, VLEN: -
|
||||
ISA Set: I86, Ins cat: LOGIC, CET tracked: no
|
||||
FLAGS access
|
||||
CF: 0, PF: m, AF: u, ZF: m, SF: m, OF: 0,
|
||||
Valid modes
|
||||
R0: yes, R1: yes, R2: yes, R3: yes
|
||||
Real: yes, V8086: yes, Prot: yes, Compat: yes, Long: yes
|
||||
SMM on: yes, SMM off: yes, SGX on: yes, SGX off: yes, TSX on: yes, TSX off: yes
|
||||
VMXRoot: yes, VMXNonRoot: yes, VMXRoot SEAM: yes, VMXNonRoot SEAM: yes, VMX off: yes
|
||||
Valid prefixes
|
||||
REP: no, REPcc: no, LOCK: no
|
||||
HLE: no, XACQUIRE only: no, XRELEASE only: no
|
||||
BND: no, BHINT: no, DNT: no
|
||||
Operand: 0, Acc: RW, Type: Register, Size: 4, RawSize: 4, Encoding: R, RegType: General Purpose, RegSize: 4, RegId: 0, RegCount: 1
|
||||
Operand: 1, Acc: R-, Type: Register, Size: 4, RawSize: 4, Encoding: M, RegType: General Purpose, RegSize: 4, RegId: 0, RegCount: 1
|
||||
Operand: 2, Acc: -W, Type: Register, Size: 4, RawSize: 4, Encoding: S, RegType: Flags, RegSize: 4, RegId: 0, RegCount: 1
|
||||
|
||||
0000000000000004 d50833c0 XOR rax, rax
|
||||
DSIZE: 64, ASIZE: 64, VLEN: -
|
||||
ISA Set: I86, Ins cat: LOGIC, CET tracked: no
|
||||
FLAGS access
|
||||
CF: 0, PF: m, AF: u, ZF: m, SF: m, OF: 0,
|
||||
Valid modes
|
||||
R0: yes, R1: yes, R2: yes, R3: yes
|
||||
Real: yes, V8086: yes, Prot: yes, Compat: yes, Long: yes
|
||||
SMM on: yes, SMM off: yes, SGX on: yes, SGX off: yes, TSX on: yes, TSX off: yes
|
||||
VMXRoot: yes, VMXNonRoot: yes, VMXRoot SEAM: yes, VMXNonRoot SEAM: yes, VMX off: yes
|
||||
Valid prefixes
|
||||
REP: no, REPcc: no, LOCK: no
|
||||
HLE: no, XACQUIRE only: no, XRELEASE only: no
|
||||
BND: no, BHINT: no, DNT: no
|
||||
Operand: 0, Acc: RW, Type: Register, Size: 8, RawSize: 8, Encoding: R, RegType: General Purpose, RegSize: 8, RegId: 0, RegCount: 1
|
||||
Operand: 1, Acc: R-, Type: Register, Size: 8, RawSize: 8, Encoding: M, RegType: General Purpose, RegSize: 8, RegId: 0, RegCount: 1
|
||||
Operand: 2, Acc: -W, Type: Register, Size: 8, RawSize: 8, Encoding: S, RegType: Flags, RegSize: 8, RegId: 0, RegCount: 1
|
||||
|
||||
0000000000000008 d51933c0 XOR rax, r24
|
||||
DSIZE: 64, ASIZE: 64, VLEN: -
|
||||
ISA Set: I86, Ins cat: LOGIC, CET tracked: no
|
||||
FLAGS access
|
||||
CF: 0, PF: m, AF: u, ZF: m, SF: m, OF: 0,
|
||||
Valid modes
|
||||
R0: yes, R1: yes, R2: yes, R3: yes
|
||||
Real: yes, V8086: yes, Prot: yes, Compat: yes, Long: yes
|
||||
SMM on: yes, SMM off: yes, SGX on: yes, SGX off: yes, TSX on: yes, TSX off: yes
|
||||
VMXRoot: yes, VMXNonRoot: yes, VMXRoot SEAM: yes, VMXNonRoot SEAM: yes, VMX off: yes
|
||||
Valid prefixes
|
||||
REP: no, REPcc: no, LOCK: no
|
||||
HLE: no, XACQUIRE only: no, XRELEASE only: no
|
||||
BND: no, BHINT: no, DNT: no
|
||||
Operand: 0, Acc: RW, Type: Register, Size: 8, RawSize: 8, Encoding: R, RegType: General Purpose, RegSize: 8, RegId: 0, RegCount: 1
|
||||
Operand: 1, Acc: R-, Type: Register, Size: 8, RawSize: 8, Encoding: M, RegType: General Purpose, RegSize: 8, RegId: 24, RegCount: 1
|
||||
Operand: 2, Acc: -W, Type: Register, Size: 8, RawSize: 8, Encoding: S, RegType: Flags, RegSize: 8, RegId: 0, RegCount: 1
|
||||
|
||||
000000000000000C d54c33c0 XOR r24, rax
|
||||
DSIZE: 64, ASIZE: 64, VLEN: -
|
||||
ISA Set: I86, Ins cat: LOGIC, CET tracked: no
|
||||
FLAGS access
|
||||
CF: 0, PF: m, AF: u, ZF: m, SF: m, OF: 0,
|
||||
Valid modes
|
||||
R0: yes, R1: yes, R2: yes, R3: yes
|
||||
Real: yes, V8086: yes, Prot: yes, Compat: yes, Long: yes
|
||||
SMM on: yes, SMM off: yes, SGX on: yes, SGX off: yes, TSX on: yes, TSX off: yes
|
||||
VMXRoot: yes, VMXNonRoot: yes, VMXRoot SEAM: yes, VMXNonRoot SEAM: yes, VMX off: yes
|
||||
Valid prefixes
|
||||
REP: no, REPcc: no, LOCK: no
|
||||
HLE: no, XACQUIRE only: no, XRELEASE only: no
|
||||
BND: no, BHINT: no, DNT: no
|
||||
Operand: 0, Acc: RW, Type: Register, Size: 8, RawSize: 8, Encoding: R, RegType: General Purpose, RegSize: 8, RegId: 24, RegCount: 1
|
||||
Operand: 1, Acc: R-, Type: Register, Size: 8, RawSize: 8, Encoding: M, RegType: General Purpose, RegSize: 8, RegId: 0, RegCount: 1
|
||||
Operand: 2, Acc: -W, Type: Register, Size: 8, RawSize: 8, Encoding: S, RegType: Flags, RegSize: 8, RegId: 0, RegCount: 1
|
||||
|
||||
0000000000000010 d52a33c0 XOR rax, rax
|
||||
DSIZE: 64, ASIZE: 64, VLEN: -
|
||||
ISA Set: I86, Ins cat: LOGIC, CET tracked: no
|
||||
FLAGS access
|
||||
CF: 0, PF: m, AF: u, ZF: m, SF: m, OF: 0,
|
||||
Valid modes
|
||||
R0: yes, R1: yes, R2: yes, R3: yes
|
||||
Real: yes, V8086: yes, Prot: yes, Compat: yes, Long: yes
|
||||
SMM on: yes, SMM off: yes, SGX on: yes, SGX off: yes, TSX on: yes, TSX off: yes
|
||||
VMXRoot: yes, VMXNonRoot: yes, VMXRoot SEAM: yes, VMXNonRoot SEAM: yes, VMX off: yes
|
||||
Valid prefixes
|
||||
REP: no, REPcc: no, LOCK: no
|
||||
HLE: no, XACQUIRE only: no, XRELEASE only: no
|
||||
BND: no, BHINT: no, DNT: no
|
||||
Operand: 0, Acc: RW, Type: Register, Size: 8, RawSize: 8, Encoding: R, RegType: General Purpose, RegSize: 8, RegId: 0, RegCount: 1
|
||||
Operand: 1, Acc: R-, Type: Register, Size: 8, RawSize: 8, Encoding: M, RegType: General Purpose, RegSize: 8, RegId: 0, RegCount: 1
|
||||
Operand: 2, Acc: -W, Type: Register, Size: 8, RawSize: 8, Encoding: S, RegType: Flags, RegSize: 8, RegId: 0, RegCount: 1
|
||||
|
||||
0000000000000014 d52a330433 XOR rax, qword ptr [rbx+r30]
|
||||
DSIZE: 64, ASIZE: 64, VLEN: -
|
||||
ISA Set: I86, Ins cat: LOGIC, CET tracked: no
|
||||
FLAGS access
|
||||
CF: 0, PF: m, AF: u, ZF: m, SF: m, OF: 0,
|
||||
Valid modes
|
||||
R0: yes, R1: yes, R2: yes, R3: yes
|
||||
Real: yes, V8086: yes, Prot: yes, Compat: yes, Long: yes
|
||||
SMM on: yes, SMM off: yes, SGX on: yes, SGX off: yes, TSX on: yes, TSX off: yes
|
||||
VMXRoot: yes, VMXNonRoot: yes, VMXRoot SEAM: yes, VMXNonRoot SEAM: yes, VMX off: yes
|
||||
Valid prefixes
|
||||
REP: no, REPcc: no, LOCK: no
|
||||
HLE: no, XACQUIRE only: no, XRELEASE only: no
|
||||
BND: no, BHINT: no, DNT: no
|
||||
Operand: 0, Acc: RW, Type: Register, Size: 8, RawSize: 8, Encoding: R, RegType: General Purpose, RegSize: 8, RegId: 0, RegCount: 1
|
||||
Operand: 1, Acc: R-, Type: Memory, Size: 8, RawSize: 8, Encoding: M,
|
||||
Segment: 3, Base: 3, Index: 30 * 1,
|
||||
Operand: 2, Acc: -W, Type: Register, Size: 8, RawSize: 8, Encoding: S, RegType: Flags, RegSize: 8, RegId: 0, RegCount: 1
|
||||
|
||||
0000000000000019 d500a1bdbdbdbdbdbdbdbd JMPABS 0xbdbdbdbdbdbdbdbd
|
||||
DSIZE: 32, ASIZE: 64, VLEN: -
|
||||
ISA Set: APX_F, Ins cat: UNCOND_BR, CET tracked: no
|
||||
CPUID leaf: 0x00000007, sub-leaf: 0x00000001, reg: edx, bit: 21
|
||||
Valid modes
|
||||
R0: yes, R1: yes, R2: yes, R3: yes
|
||||
Real: yes, V8086: yes, Prot: yes, Compat: yes, Long: yes
|
||||
SMM on: yes, SMM off: yes, SGX on: yes, SGX off: yes, TSX on: yes, TSX off: yes
|
||||
VMXRoot: yes, VMXNonRoot: yes, VMXRoot SEAM: yes, VMXNonRoot SEAM: yes, VMX off: yes
|
||||
Valid prefixes
|
||||
REP: no, REPcc: no, LOCK: no
|
||||
HLE: no, XACQUIRE only: no, XRELEASE only: no
|
||||
BND: no, BHINT: no, DNT: no
|
||||
Operand: 0, Acc: R-, Type: Address, Size: 8, RawSize: 8, Encoding: D
|
||||
Operand: 1, Acc: -W, Type: Register, Size: 4, RawSize: 4, Encoding: S, RegType: IP, RegSize: 4, RegId: 0, RegCount: 1
|
||||
|
||||
0000000000000024 d50850 PUSHP rax
|
||||
DSIZE: 64, ASIZE: 64, VLEN: -
|
||||
ISA Set: APX_F, Ins cat: PUSH, CET tracked: no
|
||||
CPUID leaf: 0x00000007, sub-leaf: 0x00000001, reg: edx, bit: 21
|
||||
Valid modes
|
||||
R0: yes, R1: yes, R2: yes, R3: yes
|
||||
Real: yes, V8086: yes, Prot: yes, Compat: yes, Long: yes
|
||||
SMM on: yes, SMM off: yes, SGX on: yes, SGX off: yes, TSX on: yes, TSX off: yes
|
||||
VMXRoot: yes, VMXNonRoot: yes, VMXRoot SEAM: yes, VMXNonRoot SEAM: yes, VMX off: yes
|
||||
Valid prefixes
|
||||
REP: no, REPcc: no, LOCK: no
|
||||
HLE: no, XACQUIRE only: no, XRELEASE only: no
|
||||
BND: no, BHINT: no, DNT: no
|
||||
Operand: 0, Acc: R-, Type: Register, Size: 8, RawSize: 8, Encoding: O, RegType: General Purpose, RegSize: 8, RegId: 0, RegCount: 1
|
||||
Operand: 1, Acc: -W, Type: Memory, Size: 8, RawSize: 8, Encoding: S, Stack: yes,
|
||||
Segment: 2, Base: 4,
|
||||
|
||||
0000000000000027 d50858 POPP rax
|
||||
DSIZE: 64, ASIZE: 64, VLEN: -
|
||||
ISA Set: APX_F, Ins cat: POP, CET tracked: no
|
||||
CPUID leaf: 0x00000007, sub-leaf: 0x00000001, reg: edx, bit: 21
|
||||
Valid modes
|
||||
R0: yes, R1: yes, R2: yes, R3: yes
|
||||
Real: yes, V8086: yes, Prot: yes, Compat: yes, Long: yes
|
||||
SMM on: yes, SMM off: yes, SGX on: yes, SGX off: yes, TSX on: yes, TSX off: yes
|
||||
VMXRoot: yes, VMXNonRoot: yes, VMXRoot SEAM: yes, VMXNonRoot SEAM: yes, VMX off: yes
|
||||
Valid prefixes
|
||||
REP: no, REPcc: no, LOCK: no
|
||||
HLE: no, XACQUIRE only: no, XRELEASE only: no
|
||||
BND: no, BHINT: no, DNT: no
|
||||
Operand: 0, Acc: -W, Type: Register, Size: 8, RawSize: 8, Encoding: O, RegType: General Purpose, RegSize: 8, RegId: 0, RegCount: 1
|
||||
Operand: 1, Acc: R-, Type: Memory, Size: 8, RawSize: 8, Encoding: S, Stack: yes,
|
||||
Segment: 2, Base: 4,
|
||||
|
||||
000000000000002A d51850 PUSHP r16
|
||||
DSIZE: 64, ASIZE: 64, VLEN: -
|
||||
ISA Set: APX_F, Ins cat: PUSH, CET tracked: no
|
||||
CPUID leaf: 0x00000007, sub-leaf: 0x00000001, reg: edx, bit: 21
|
||||
Valid modes
|
||||
R0: yes, R1: yes, R2: yes, R3: yes
|
||||
Real: yes, V8086: yes, Prot: yes, Compat: yes, Long: yes
|
||||
SMM on: yes, SMM off: yes, SGX on: yes, SGX off: yes, TSX on: yes, TSX off: yes
|
||||
VMXRoot: yes, VMXNonRoot: yes, VMXRoot SEAM: yes, VMXNonRoot SEAM: yes, VMX off: yes
|
||||
Valid prefixes
|
||||
REP: no, REPcc: no, LOCK: no
|
||||
HLE: no, XACQUIRE only: no, XRELEASE only: no
|
||||
BND: no, BHINT: no, DNT: no
|
||||
Operand: 0, Acc: R-, Type: Register, Size: 8, RawSize: 8, Encoding: O, RegType: General Purpose, RegSize: 8, RegId: 16, RegCount: 1
|
||||
Operand: 1, Acc: -W, Type: Memory, Size: 8, RawSize: 8, Encoding: S, Stack: yes,
|
||||
Segment: 2, Base: 4,
|
||||
|
||||
000000000000002D d51858 POPP r16
|
||||
DSIZE: 64, ASIZE: 64, VLEN: -
|
||||
ISA Set: APX_F, Ins cat: POP, CET tracked: no
|
||||
CPUID leaf: 0x00000007, sub-leaf: 0x00000001, reg: edx, bit: 21
|
||||
Valid modes
|
||||
R0: yes, R1: yes, R2: yes, R3: yes
|
||||
Real: yes, V8086: yes, Prot: yes, Compat: yes, Long: yes
|
||||
SMM on: yes, SMM off: yes, SGX on: yes, SGX off: yes, TSX on: yes, TSX off: yes
|
||||
VMXRoot: yes, VMXNonRoot: yes, VMXRoot SEAM: yes, VMXNonRoot SEAM: yes, VMX off: yes
|
||||
Valid prefixes
|
||||
REP: no, REPcc: no, LOCK: no
|
||||
HLE: no, XACQUIRE only: no, XRELEASE only: no
|
||||
BND: no, BHINT: no, DNT: no
|
||||
Operand: 0, Acc: -W, Type: Register, Size: 8, RawSize: 8, Encoding: O, RegType: General Purpose, RegSize: 8, RegId: 16, RegCount: 1
|
||||
Operand: 1, Acc: R-, Type: Memory, Size: 8, RawSize: 8, Encoding: S, Stack: yes,
|
||||
Segment: 2, Base: 4,
|
||||
|
||||
0000000000000030 d50050 PUSH rax
|
||||
DSIZE: 64, ASIZE: 64, VLEN: -
|
||||
ISA Set: I86, Ins cat: PUSH, CET tracked: no
|
||||
Valid modes
|
||||
R0: yes, R1: yes, R2: yes, R3: yes
|
||||
Real: yes, V8086: yes, Prot: yes, Compat: yes, Long: yes
|
||||
SMM on: yes, SMM off: yes, SGX on: yes, SGX off: yes, TSX on: yes, TSX off: yes
|
||||
VMXRoot: yes, VMXNonRoot: yes, VMXRoot SEAM: yes, VMXNonRoot SEAM: yes, VMX off: yes
|
||||
Valid prefixes
|
||||
REP: no, REPcc: no, LOCK: no
|
||||
HLE: no, XACQUIRE only: no, XRELEASE only: no
|
||||
BND: no, BHINT: no, DNT: no
|
||||
Operand: 0, Acc: R-, Type: Register, Size: 8, RawSize: 8, Encoding: O, RegType: General Purpose, RegSize: 8, RegId: 0, RegCount: 1
|
||||
Operand: 1, Acc: -W, Type: Memory, Size: 8, RawSize: 8, Encoding: S, Stack: yes,
|
||||
Segment: 2, Base: 4,
|
||||
|
||||
0000000000000033 d50058 POP rax
|
||||
DSIZE: 64, ASIZE: 64, VLEN: -
|
||||
ISA Set: I86, Ins cat: POP, CET tracked: no
|
||||
Valid modes
|
||||
R0: yes, R1: yes, R2: yes, R3: yes
|
||||
Real: yes, V8086: yes, Prot: yes, Compat: yes, Long: yes
|
||||
SMM on: yes, SMM off: yes, SGX on: yes, SGX off: yes, TSX on: yes, TSX off: yes
|
||||
VMXRoot: yes, VMXNonRoot: yes, VMXRoot SEAM: yes, VMXNonRoot SEAM: yes, VMX off: yes
|
||||
Valid prefixes
|
||||
REP: no, REPcc: no, LOCK: no
|
||||
HLE: no, XACQUIRE only: no, XRELEASE only: no
|
||||
BND: no, BHINT: no, DNT: no
|
||||
Operand: 0, Acc: -W, Type: Register, Size: 8, RawSize: 8, Encoding: O, RegType: General Purpose, RegSize: 8, RegId: 0, RegCount: 1
|
||||
Operand: 1, Acc: R-, Type: Memory, Size: 8, RawSize: 8, Encoding: S, Stack: yes,
|
||||
Segment: 2, Base: 4,
|
||||
|
||||
0000000000000036 d51050 PUSH r16
|
||||
DSIZE: 64, ASIZE: 64, VLEN: -
|
||||
ISA Set: I86, Ins cat: PUSH, CET tracked: no
|
||||
Valid modes
|
||||
R0: yes, R1: yes, R2: yes, R3: yes
|
||||
Real: yes, V8086: yes, Prot: yes, Compat: yes, Long: yes
|
||||
SMM on: yes, SMM off: yes, SGX on: yes, SGX off: yes, TSX on: yes, TSX off: yes
|
||||
VMXRoot: yes, VMXNonRoot: yes, VMXRoot SEAM: yes, VMXNonRoot SEAM: yes, VMX off: yes
|
||||
Valid prefixes
|
||||
REP: no, REPcc: no, LOCK: no
|
||||
HLE: no, XACQUIRE only: no, XRELEASE only: no
|
||||
BND: no, BHINT: no, DNT: no
|
||||
Operand: 0, Acc: R-, Type: Register, Size: 8, RawSize: 8, Encoding: O, RegType: General Purpose, RegSize: 8, RegId: 16, RegCount: 1
|
||||
Operand: 1, Acc: -W, Type: Memory, Size: 8, RawSize: 8, Encoding: S, Stack: yes,
|
||||
Segment: 2, Base: 4,
|
||||
|
||||
0000000000000039 d51058 POP r16
|
||||
DSIZE: 64, ASIZE: 64, VLEN: -
|
||||
ISA Set: I86, Ins cat: POP, CET tracked: no
|
||||
Valid modes
|
||||
R0: yes, R1: yes, R2: yes, R3: yes
|
||||
Real: yes, V8086: yes, Prot: yes, Compat: yes, Long: yes
|
||||
SMM on: yes, SMM off: yes, SGX on: yes, SGX off: yes, TSX on: yes, TSX off: yes
|
||||
VMXRoot: yes, VMXNonRoot: yes, VMXRoot SEAM: yes, VMXNonRoot SEAM: yes, VMX off: yes
|
||||
Valid prefixes
|
||||
REP: no, REPcc: no, LOCK: no
|
||||
HLE: no, XACQUIRE only: no, XRELEASE only: no
|
||||
BND: no, BHINT: no, DNT: no
|
||||
Operand: 0, Acc: -W, Type: Register, Size: 8, RawSize: 8, Encoding: O, RegType: General Purpose, RegSize: 8, RegId: 16, RegCount: 1
|
||||
Operand: 1, Acc: R-, Type: Memory, Size: 8, RawSize: 8, Encoding: S, Stack: yes,
|
||||
Segment: 2, Base: 4,
|
||||
|
||||
000000000000003C d50090 NOP
|
||||
DSIZE: 32, ASIZE: 64, VLEN: -
|
||||
ISA Set: I86, Ins cat: NOP, CET tracked: no
|
||||
Valid modes
|
||||
R0: yes, R1: yes, R2: yes, R3: yes
|
||||
Real: yes, V8086: yes, Prot: yes, Compat: yes, Long: yes
|
||||
SMM on: yes, SMM off: yes, SGX on: yes, SGX off: yes, TSX on: yes, TSX off: yes
|
||||
VMXRoot: yes, VMXNonRoot: yes, VMXRoot SEAM: yes, VMXNonRoot SEAM: yes, VMX off: yes
|
||||
Valid prefixes
|
||||
REP: no, REPcc: no, LOCK: no
|
||||
HLE: no, XACQUIRE only: no, XRELEASE only: no
|
||||
BND: no, BHINT: no, DNT: no
|
||||
|
||||
000000000000003F d51890 XCHG r16, rax
|
||||
DSIZE: 64, ASIZE: 64, VLEN: -
|
||||
ISA Set: I86, Ins cat: DATAXFER, CET tracked: no
|
||||
Valid modes
|
||||
R0: yes, R1: yes, R2: yes, R3: yes
|
||||
Real: yes, V8086: yes, Prot: yes, Compat: yes, Long: yes
|
||||
SMM on: yes, SMM off: yes, SGX on: yes, SGX off: yes, TSX on: yes, TSX off: yes
|
||||
VMXRoot: yes, VMXNonRoot: yes, VMXRoot SEAM: yes, VMXNonRoot SEAM: yes, VMX off: yes
|
||||
Valid prefixes
|
||||
REP: no, REPcc: no, LOCK: no
|
||||
HLE: no, XACQUIRE only: no, XRELEASE only: no
|
||||
BND: no, BHINT: no, DNT: no
|
||||
Operand: 0, Acc: RW, Type: Register, Size: 8, RawSize: 8, Encoding: O, RegType: General Purpose, RegSize: 8, RegId: 16, RegCount: 1
|
||||
Operand: 1, Acc: RW, Type: Register, Size: 8, RawSize: 8, Encoding: S, RegType: General Purpose, RegSize: 8, RegId: 0, RegCount: 1
|
||||
|
||||
0000000000000042 f3d599aec7 RDFSBASE r31
|
||||
DSIZE: 64, ASIZE: 64, VLEN: -
|
||||
ISA Set: RDWRFSGS, Ins cat: RDWRFSGS, CET tracked: no
|
||||
CPUID leaf: 0x00000007, sub-leaf: 0x00000000, reg: ebx, bit: 0
|
||||
Valid modes
|
||||
R0: yes, R1: yes, R2: yes, R3: yes
|
||||
Real: no, V8086: no, Prot: no, Compat: no, Long: yes
|
||||
SMM on: yes, SMM off: yes, SGX on: yes, SGX off: yes, TSX on: yes, TSX off: yes
|
||||
VMXRoot: yes, VMXNonRoot: yes, VMXRoot SEAM: yes, VMXNonRoot SEAM: yes, VMX off: yes
|
||||
Valid prefixes
|
||||
REP: no, REPcc: no, LOCK: no
|
||||
HLE: no, XACQUIRE only: no, XRELEASE only: no
|
||||
BND: no, BHINT: no, DNT: no
|
||||
Operand: 0, Acc: -W, Type: Register, Size: 8, RawSize: 8, Encoding: M, RegType: General Purpose, RegSize: 8, RegId: 31, RegCount: 1
|
||||
Operand: 1, Acc: R-, Type: Register, Size: 8, RawSize: 8, Encoding: S, RegType: Model Specific, RegSize: 8, RegId: 0xc0000100, RegCount: 1
|
||||
|
Binary file not shown.
@ -0,0 +1,11 @@
|
||||
bits 64
|
||||
|
||||
; UWRMSR 0x44332211, rax
|
||||
db 0xC4, 0xE7, 0x7A, 0xF8, 0xC0, 0x11, 0x22, 0x33, 0x44
|
||||
; URDMSR rax, 0x44332211
|
||||
db 0xC4, 0xE7, 0x7B, 0xF8, 0xC0, 0x11, 0x22, 0x33, 0x44
|
||||
; UWRMSR rcx, rax
|
||||
db 0xF3, 0x0F, 0x38, 0xF8, 0xC1
|
||||
; URDMSR rax, rcx
|
||||
db 0xF2, 0x0F, 0x38, 0xF8, 0xC1
|
||||
|
@ -0,0 +1,68 @@
|
||||
0000000000000000 c4e77af8c011223344 UWRMSR 0x44332211, rax
|
||||
DSIZE: 32, ASIZE: 64, VLEN: -
|
||||
ISA Set: USER_MSR, Ins cat: USER_MSR, CET tracked: no
|
||||
CPUID leaf: 0x00000007, sub-leaf: 0x00000001, reg: edx, bit: 15
|
||||
Valid modes
|
||||
R0: yes, R1: yes, R2: yes, R3: yes
|
||||
Real: no, V8086: no, Prot: no, Compat: no, Long: yes
|
||||
SMM on: yes, SMM off: yes, SGX on: yes, SGX off: yes, TSX on: yes, TSX off: yes
|
||||
VMXRoot: yes, VMXNonRoot: yes, VMXRoot SEAM: yes, VMXNonRoot SEAM: yes, VMX off: yes
|
||||
Valid prefixes
|
||||
REP: no, REPcc: no, LOCK: no
|
||||
HLE: no, XACQUIRE only: no, XRELEASE only: no
|
||||
BND: no, BHINT: no, DNT: no
|
||||
Operand: 0, Acc: R-, Type: Immediate, Size: 4, RawSize: 4, Encoding: I
|
||||
Operand: 1, Acc: R-, Type: Register, Size: 8, RawSize: 8, Encoding: M, RegType: General Purpose, RegSize: 8, RegId: 0, RegCount: 1
|
||||
Operand: 2, Acc: -W, Type: Register, Size: 8, RawSize: 8, Encoding: E, RegType: Model Specific, RegSize: 8, RegId: 0xffffffff, RegCount: 1
|
||||
|
||||
0000000000000009 c4e77bf8c011223344 URDMSR rax, 0x44332211
|
||||
DSIZE: 32, ASIZE: 64, VLEN: -
|
||||
ISA Set: USER_MSR, Ins cat: USER_MSR, CET tracked: no
|
||||
CPUID leaf: 0x00000007, sub-leaf: 0x00000001, reg: edx, bit: 15
|
||||
Valid modes
|
||||
R0: yes, R1: yes, R2: yes, R3: yes
|
||||
Real: no, V8086: no, Prot: no, Compat: no, Long: yes
|
||||
SMM on: yes, SMM off: yes, SGX on: yes, SGX off: yes, TSX on: yes, TSX off: yes
|
||||
VMXRoot: yes, VMXNonRoot: yes, VMXRoot SEAM: yes, VMXNonRoot SEAM: yes, VMX off: yes
|
||||
Valid prefixes
|
||||
REP: no, REPcc: no, LOCK: no
|
||||
HLE: no, XACQUIRE only: no, XRELEASE only: no
|
||||
BND: no, BHINT: no, DNT: no
|
||||
Operand: 0, Acc: -W, Type: Register, Size: 8, RawSize: 8, Encoding: M, RegType: General Purpose, RegSize: 8, RegId: 0, RegCount: 1
|
||||
Operand: 1, Acc: R-, Type: Immediate, Size: 4, RawSize: 4, Encoding: I
|
||||
Operand: 2, Acc: R-, Type: Register, Size: 8, RawSize: 8, Encoding: E, RegType: Model Specific, RegSize: 8, RegId: 0xffffffff, RegCount: 1
|
||||
|
||||
0000000000000012 f30f38f8c1 UWRMSR rax, rcx
|
||||
DSIZE: 32, ASIZE: 64, VLEN: -
|
||||
ISA Set: USER_MSR, Ins cat: USER_MSR, CET tracked: no
|
||||
CPUID leaf: 0x00000007, sub-leaf: 0x00000001, reg: edx, bit: 15
|
||||
Valid modes
|
||||
R0: yes, R1: yes, R2: yes, R3: yes
|
||||
Real: no, V8086: no, Prot: no, Compat: no, Long: yes
|
||||
SMM on: yes, SMM off: yes, SGX on: yes, SGX off: yes, TSX on: yes, TSX off: yes
|
||||
VMXRoot: yes, VMXNonRoot: yes, VMXRoot SEAM: yes, VMXNonRoot SEAM: yes, VMX off: yes
|
||||
Valid prefixes
|
||||
REP: no, REPcc: no, LOCK: no
|
||||
HLE: no, XACQUIRE only: no, XRELEASE only: no
|
||||
BND: no, BHINT: no, DNT: no
|
||||
Operand: 0, Acc: R-, Type: Register, Size: 8, RawSize: 8, Encoding: R, RegType: General Purpose, RegSize: 8, RegId: 0, RegCount: 1
|
||||
Operand: 1, Acc: R-, Type: Register, Size: 8, RawSize: 8, Encoding: M, RegType: General Purpose, RegSize: 8, RegId: 1, RegCount: 1
|
||||
Operand: 2, Acc: -W, Type: Register, Size: 8, RawSize: 8, Encoding: E, RegType: Model Specific, RegSize: 8, RegId: 0xffffffff, RegCount: 1
|
||||
|
||||
0000000000000017 f20f38f8c1 URDMSR rcx, rax
|
||||
DSIZE: 32, ASIZE: 64, VLEN: -
|
||||
ISA Set: USER_MSR, Ins cat: USER_MSR, CET tracked: no
|
||||
CPUID leaf: 0x00000007, sub-leaf: 0x00000001, reg: edx, bit: 15
|
||||
Valid modes
|
||||
R0: yes, R1: yes, R2: yes, R3: yes
|
||||
Real: no, V8086: no, Prot: no, Compat: no, Long: yes
|
||||
SMM on: yes, SMM off: yes, SGX on: yes, SGX off: yes, TSX on: yes, TSX off: yes
|
||||
VMXRoot: yes, VMXNonRoot: yes, VMXRoot SEAM: yes, VMXNonRoot SEAM: yes, VMX off: yes
|
||||
Valid prefixes
|
||||
REP: no, REPcc: no, LOCK: no
|
||||
HLE: no, XACQUIRE only: no, XRELEASE only: no
|
||||
BND: no, BHINT: no, DNT: no
|
||||
Operand: 0, Acc: -W, Type: Register, Size: 8, RawSize: 8, Encoding: M, RegType: General Purpose, RegSize: 8, RegId: 1, RegCount: 1
|
||||
Operand: 1, Acc: R-, Type: Register, Size: 8, RawSize: 8, Encoding: R, RegType: General Purpose, RegSize: 8, RegId: 0, RegCount: 1
|
||||
Operand: 2, Acc: R-, Type: Register, Size: 8, RawSize: 8, Encoding: E, RegType: Model Specific, RegSize: 8, RegId: 0xffffffff, RegCount: 1
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,172 @@
|
||||
/*
|
||||
* Copyright (c) 2020 Bitdefender
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#ifndef BDSHEMU_COMMON_H_
|
||||
#define BDSHEMU_COMMON_H_
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#include <sal.h>
|
||||
#else
|
||||
#define _Analysis_assume_(x)
|
||||
#endif
|
||||
|
||||
|
||||
// The SHELLBMP and STACKBMP are two bitmaps which hold the state of each shellcode byte and each stack byte.
|
||||
// Inside SHELLBMP, we store whether a shellcode byte has been fetched for execution or not, and whether it was
|
||||
// modified or not.
|
||||
// Inside STACKBMP, we store whether a stack byte is part of a previously saved RIP value or not.
|
||||
#define STACKBMP(ctx) ((ctx)->Intbuf)
|
||||
#define STACKBMP_SIZE(ctx) ((ctx)->StackSize)
|
||||
#define SHELLBMP(ctx) (!((ctx)->Options & SHEMU_OPT_DIRECT_MAPPED_SHELL) ? (ctx)->Intbuf + (ctx)->StackSize : ND_NULL)
|
||||
#define SHELLBMP_SIZE(ctx) (!((ctx)->Options & SHEMU_OPT_DIRECT_MAPPED_SHELL) ? (ctx)->ShellcodeSize : 0)
|
||||
#define MAX(a, b) ((a) < (b) ? (b) : (a))
|
||||
#define MIN(a, b) ((a) > (b) ? (b) : (a))
|
||||
|
||||
|
||||
// Flags used for the shellcode. These are set inside SHELLBMP. Each byte at index X inside SHELLBMP indicates the state
|
||||
// of the shellcode byte at index X.
|
||||
#define SHELL_BYTE_DIRTY (0x01) // The location inside the shellcode has been written.
|
||||
#define SHELL_BYTE_FETCHED (0x02) // The location inside the shellcode has been fetched for execution.
|
||||
#define SHELL_BYTE_IBYTES (0x04) // The location inside the shellcode represents executed instruction
|
||||
// bytes. Does not include the first instruction byte, which is marked
|
||||
// using the SHELL_BYTE_FETCHED flag.
|
||||
|
||||
// Flags used for the stack. These are set inside STACKBMP. Each byte at index X inside STACKBMP indicates the state
|
||||
// of the stack byte at index X.
|
||||
#define STACK_BYTE_RIP (0x01) // The location inside the stack contains a RIP portion.
|
||||
|
||||
// Flags used for the GPR tracking mechanism. Each byte X inside the GPR tracker array indicates the state of said GPR.
|
||||
#define GPR_TRACK_READ (0x01) // The GPR has been read, by any instruction (including RMW).
|
||||
#define GPR_TRACK_DIRTY (0x02) // The GPR has been modified.
|
||||
|
||||
|
||||
#define GET_BITS(val, start, stop) (((val) >> (start)) & ((1ULL << ((stop) - (start) + 1)) - 1))
|
||||
|
||||
#define ShemuShellBmpStateSet(Context, Start, Count, Flags) \
|
||||
ShemuBmpStateUpdate(SHELLBMP(Context), SHELLBMP_SIZE(Context), Start, Count, Flags, ND_FALSE)
|
||||
|
||||
#define ShemuShellBmpStateClear(Context, Start, Count, Flags) \
|
||||
ShemuBmpStateUpdate(SHELLBMP(Context), SHELLBMP_SIZE(Context), Start, Count, Flags, ND_TRUE)
|
||||
|
||||
#define ShemuShellBmpStateCheck(Context, Start, Count, Flags) \
|
||||
ShemuBmpStateCheck(SHELLBMP(Context), SHELLBMP_SIZE(Context), Start, Count, Flags)
|
||||
|
||||
#define ShemuStackBmpStateSet(Contxt, Start, Count, Flags) \
|
||||
ShemuBmpStateUpdate(STACKBMP(Context), STACKBMP_SIZE(Context), Start, Count, Flags, ND_FALSE)
|
||||
|
||||
#define ShemuStackBmpStateClear(Context, Start, Count, Flags) \
|
||||
ShemuBmpStateUpdate(STACKBMP(Context), STACKBMP_SIZE(Context), Start, Count, Flags, ND_TRUE)
|
||||
|
||||
#define ShemuStackBmpStateCheck(Context, Start, Count, Flags) \
|
||||
ShemuBmpStateCheck(STACKBMP(Context), STACKBMP_SIZE(Context), Start, Count, Flags)
|
||||
|
||||
|
||||
|
||||
|
||||
void
|
||||
shemu_printf(
|
||||
SHEMU_CONTEXT *Context,
|
||||
char *formatstring,
|
||||
...
|
||||
);
|
||||
|
||||
void *
|
||||
shemu_memcpy(
|
||||
void *Dest,
|
||||
const void *Source,
|
||||
ND_SIZET Size
|
||||
);
|
||||
|
||||
void
|
||||
ShemuHexlify(
|
||||
ND_UINT8 *Value,
|
||||
ND_UINT64 ValueSize,
|
||||
char *Hex,
|
||||
ND_UINT64 HexSize
|
||||
);
|
||||
|
||||
void
|
||||
ShemuBmpStateUpdate(
|
||||
ND_UINT8 *Bitmap,
|
||||
ND_UINT64 Size,
|
||||
ND_UINT64 Start,
|
||||
ND_UINT64 Count,
|
||||
ND_UINT8 Flags,
|
||||
ND_BOOL Clear
|
||||
);
|
||||
|
||||
ND_BOOL
|
||||
ShemuBmpStateCheck(
|
||||
ND_UINT8 *Bitmap,
|
||||
ND_UINT64 Size,
|
||||
ND_UINT64 Start,
|
||||
ND_UINT64 Count,
|
||||
ND_UINT8 Flags
|
||||
);
|
||||
|
||||
ND_BOOL
|
||||
ShemuIsShellcodePtr(
|
||||
SHEMU_CONTEXT *Context,
|
||||
ND_UINT64 Gla,
|
||||
ND_UINT64 Size
|
||||
);
|
||||
|
||||
ND_BOOL
|
||||
ShemuIsStackPtr(
|
||||
SHEMU_CONTEXT *Context,
|
||||
ND_UINT64 Gla,
|
||||
ND_UINT64 Size
|
||||
);
|
||||
|
||||
ND_BOOL
|
||||
ShemuIsIcachePtr(
|
||||
SHEMU_CONTEXT *Context,
|
||||
ND_UINT64 Gla,
|
||||
ND_UINT64 Size
|
||||
);
|
||||
|
||||
SHEMU_STATUS
|
||||
ShemuMemLoad(
|
||||
SHEMU_CONTEXT *Context,
|
||||
ND_UINT64 Gla,
|
||||
ND_UINT64 Size,
|
||||
ND_UINT8 *Value
|
||||
);
|
||||
|
||||
SHEMU_STATUS
|
||||
ShemuMemStore(
|
||||
SHEMU_CONTEXT *Context,
|
||||
ND_UINT64 Gla,
|
||||
ND_UINT64 Size,
|
||||
ND_UINT8 *Value
|
||||
);
|
||||
|
||||
SHEMU_STATUS
|
||||
ShemuMemFetch(
|
||||
SHEMU_CONTEXT *Context,
|
||||
ND_UINT64 Gla,
|
||||
ND_UINT64 Size,
|
||||
ND_UINT8 *Bytes
|
||||
);
|
||||
|
||||
void
|
||||
ShemuFlushIcache(
|
||||
SHEMU_CONTEXT *Context
|
||||
);
|
||||
|
||||
void
|
||||
ShemuDisplayMemValue(
|
||||
SHEMU_CONTEXT *Context,
|
||||
ND_UINT64 Gla,
|
||||
ND_UINT64 Size,
|
||||
ND_UINT8 *Value,
|
||||
ND_BOOL Load
|
||||
);
|
||||
|
||||
ND_BOOL
|
||||
ShemuIsImmMetasploitHash(
|
||||
ND_UINT64 Value
|
||||
);
|
||||
|
||||
#endif // BDSHEMU_COMMON_H_
|
@ -1,49 +0,0 @@
|
||||
# Bitdefender Shellocde Emulator Fuzzer
|
||||
|
||||
This assumes that you have [AFL](https://github.com/google/AFL) in your path.
|
||||
|
||||
It collects the `bddisasm` and `bdshemu` sources into a single executable, built with AFL instrumentation.
|
||||
|
||||
## Getting started
|
||||
|
||||
Build it with `make shfuzz`.
|
||||
|
||||
Start fuzzing with `make fuzz32` (for 32-bit mode samples) or `make fuzz64` (for 64-bit mode samples).
|
||||
|
||||
If you're in a hurry you can fuzz in the quick and dirty mode with `DIRTY=y`: `make fuzz32 DIRTY=y` or `make fuzz64 DIRTY=y`.
|
||||
|
||||
Activate support for [address sanitizer](https://github.com/google/sanitizers/wiki/AddressSanitizer) with `AFL_USE_ASAN=1 make shfuzz`. This can uncover more bugs, but it is a lot slower and requires more memory.
|
||||
|
||||
Input files are in the `in-32` and `in-64` directories, crashes will be in `out-32/crashes` or `out-64/crashes`, hangs will be in `out-32/hangs` or `out-64/hangs`.
|
||||
|
||||
## Details
|
||||
|
||||
If the `AFL_COMPILER` variable is not set, the build process looks for `afl-clang-fast` and if it is available, the tool is compiled with that. If not, it tries to choose between `afl-clang` and `afl-gcc`.
|
||||
If you want to use a certain compiler simply set `AFL_COMPILER` before invoking make: `AFL_COMPILER=afl-gcc make`.
|
||||
Note that `afl-clang-fast` is not compiled by default when compiling AFL. See [llvm mode](https://github.com/google/AFL/tree/master/llvm_mode) in the AFL repository.
|
||||
|
||||
Run the fuzzer in 32-bit mode with `make fuzz32`, or in 64-bit mode with `make fuzz64`.
|
||||
|
||||
If you want to take advantage of multiple cores see [parallel fuzzing](https://github.com/google/AFL/blob/master/docs/parallel_fuzzing.txt).
|
||||
|
||||
If `afl-clang-fast` is used, we try to use AFL in persistent mode, which should provide better performance.
|
||||
|
||||
Note that both `fuzz32` and `fuzz64` assume that the tool was compiled with `afl-clang-fast`, `afl-clang`, or `afl-gcc`.
|
||||
|
||||
ASAN builds will have increased memory requirements. You may need to tweak the `-m` parameter (or set `AFL_MEMORY`) for `afl-fuzz` (see [notes for ASAN](https://github.com/google/AFL/blob/master/docs/notes_for_asan.txt)).
|
||||
|
||||
By default, all logging is disabled, as it is already not visible while AFL is running. Compile with `LOG=y` in order to enable some minimal logging.
|
||||
|
||||
## Using the tool
|
||||
|
||||
The `shfuzz` tool is a simplified version of `disasmtool`. It takes 3 positional arguments:
|
||||
|
||||
```bash
|
||||
shfuzz file mode use_logging
|
||||
```
|
||||
|
||||
- file - the path to a input file that contains instructions to be disassembled and emulated;
|
||||
- mode - the mode in which to run: `32` for 32-bit instructions, `64` for 64-bit instruction;
|
||||
- use_logging - if present, will actually log everything that `bdshemu` wants to log; even if absent, the `ShemuLog` implementation will still try to access every character in the string it should normally print, so if you want to find bugs related to logging you can still do, but it is a lot faster when the strings don't get printed. This is ignored if you compile `shfuzz` without `LOG=y`.
|
||||
|
||||
Any errors encountered while parsing the arguments, trying to open the input file, or allocate memory are handled by calling `abort()`. This makes it easier to detect these problems.
|
@ -0,0 +1,21 @@
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
# Check if the -it flag is provided
|
||||
if [ -t 0 ] && [ -t 1 ]; then
|
||||
echo "Running in interactive mode"
|
||||
else
|
||||
echo "Error: This container requires an interactive shell (-it flag)."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Check if the volume directory is present
|
||||
if [ ! -d "${SHARE_DIR}" ]; then
|
||||
echo "Warning: Volume directory '${SHARE_DIR}' is missing."
|
||||
echo "Please use the -v flag to specify a host directory."
|
||||
echo "For example 'podman run -v /host/path:${SHARE_DIR}'"
|
||||
echo "You will need to manually copy fuzzing inputs/outputs from/to the host"
|
||||
fi
|
||||
|
||||
# Continue with the original command
|
||||
exec "$@"
|
Binary file not shown.
Binary file not shown.
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,198 @@
|
||||
import os
|
||||
import subprocess
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
from git import Repo
|
||||
|
||||
repo = Repo(search_parent_directories=True)
|
||||
root = Path(repo.working_tree_dir)
|
||||
|
||||
print(f"Repo root: {root}")
|
||||
|
||||
hdr_dirs = root / "inc"
|
||||
x86_constants = hdr_dirs / "bdx86_constants.h"
|
||||
|
||||
print(f"Looking for enums in {x86_constants}")
|
||||
|
||||
with open(x86_constants, "r") as data:
|
||||
nd_ins = []
|
||||
nd_ins_set = []
|
||||
nd_ins_type = []
|
||||
|
||||
for line in data:
|
||||
if "INVALID" in line:
|
||||
continue
|
||||
|
||||
if line.startswith(" ND_CAT_"):
|
||||
token = line.replace(',', '').strip()
|
||||
nd_ins_type.append(token)
|
||||
continue
|
||||
|
||||
if line.startswith(" ND_SET_"):
|
||||
token = line.replace(',', '').strip()
|
||||
nd_ins_set.append(token)
|
||||
continue
|
||||
|
||||
if line.startswith(" ND_INS_"):
|
||||
token = line.replace(',', '').strip()
|
||||
nd_ins.append(token)
|
||||
continue
|
||||
|
||||
print(f"ND_INS_: {len(nd_ins)} ND_SET_: {len(nd_ins_set)} ND_CAT_: {len(nd_ins_type)}")
|
||||
|
||||
bindings = root / "bindings/rsbddisasm/bddisasm/src"
|
||||
mnemonic = bindings / "mnemonic.rs"
|
||||
ins_cat = bindings / "instruction_category.rs"
|
||||
isa_set = bindings / "isa_set.rs"
|
||||
|
||||
license_header = """
|
||||
/*
|
||||
* Copyright (c) 2021 Bitdefender
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
"""
|
||||
|
||||
print(f"Generating {mnemonic}")
|
||||
|
||||
with open(mnemonic, "w") as fmnemonic:
|
||||
fmnemonic.write(license_header)
|
||||
fmnemonic.write("//! Mnemonics.\n")
|
||||
fmnemonic.write("\n")
|
||||
fmnemonic.write("use super::decode_error::DecodeError;\n")
|
||||
fmnemonic.write("use core::convert::TryFrom;\n")
|
||||
|
||||
mnemonic_enum_def = """
|
||||
/// Uniquely identifies an instruction.
|
||||
#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
|
||||
#[allow(non_camel_case_types)]
|
||||
pub enum Mnemonic {
|
||||
"""
|
||||
fmnemonic.write(mnemonic_enum_def)
|
||||
for ins in nd_ins:
|
||||
line = ins.replace("ND_INS_", "")
|
||||
fmnemonic.write(f"{line},\n")
|
||||
|
||||
fmnemonic.write("}\n")
|
||||
|
||||
try_from = """
|
||||
#[doc(hidden)]
|
||||
impl TryFrom<ffi::ND_INS_CLASS> for Mnemonic {
|
||||
type Error = DecodeError;
|
||||
|
||||
#[allow(clippy::too_many_lines)]
|
||||
fn try_from(value: ffi::ND_INS_CLASS) -> Result<Self, Self::Error> {
|
||||
match value {
|
||||
ffi::_ND_INS_CLASS::ND_INS_INVALID => Err(DecodeError::InternalError(value as u64)),
|
||||
"""
|
||||
fmnemonic.write(try_from)
|
||||
for ins in nd_ins:
|
||||
line = f"ffi::_ND_INS_CLASS::{ins} => Ok(Mnemonic::{ins.replace('ND_INS_', '')}),\n"
|
||||
fmnemonic.write(line)
|
||||
|
||||
end = """
|
||||
}
|
||||
}
|
||||
}
|
||||
"""
|
||||
fmnemonic.write(end)
|
||||
|
||||
print(f"Generating {ins_cat}")
|
||||
|
||||
with open(ins_cat, "w") as finscat:
|
||||
finscat.write(license_header)
|
||||
finscat.write("//! Instruction categories.\n")
|
||||
finscat.write("\n")
|
||||
finscat.write("use super::decode_error::DecodeError;\n")
|
||||
finscat.write("use core::convert::TryFrom;\n")
|
||||
|
||||
ins_cat_enum_def = """
|
||||
/// Instruction category.
|
||||
#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
|
||||
#[allow(non_camel_case_types)]
|
||||
pub enum Category {
|
||||
"""
|
||||
finscat.write(ins_cat_enum_def)
|
||||
for ins in nd_ins_type:
|
||||
line = ins.replace("ND_CAT_", "")
|
||||
if line[0].isdigit():
|
||||
line = f"I{line}"
|
||||
finscat.write(f"{line},\n")
|
||||
|
||||
finscat.write("}\n")
|
||||
|
||||
try_from = """
|
||||
#[doc(hidden)]
|
||||
impl TryFrom<ffi::ND_INS_CATEGORY> for Category {
|
||||
type Error = DecodeError;
|
||||
|
||||
#[allow(clippy::too_many_lines)]
|
||||
fn try_from(value: ffi::ND_INS_CATEGORY) -> Result<Self, Self::Error> {
|
||||
match value {
|
||||
ffi::_ND_INS_TYPE::ND_CAT_INVALID => Err(DecodeError::InternalError(value as u64)),
|
||||
"""
|
||||
finscat.write(try_from)
|
||||
for ins in nd_ins_type:
|
||||
ok = ins.replace('ND_CAT_', '')
|
||||
if ok[0].isdigit():
|
||||
ok = f"I{ok}"
|
||||
line = f"ffi::_ND_INS_TYPE::{ins} => Ok(Category::{ok}),\n"
|
||||
finscat.write(line)
|
||||
|
||||
end = """
|
||||
}
|
||||
}
|
||||
}
|
||||
"""
|
||||
finscat.write(end)
|
||||
|
||||
print(f"Generating {isa_set}")
|
||||
|
||||
with open(isa_set, "w") as fset:
|
||||
fset.write(license_header)
|
||||
fset.write("//! Instruction sets.\n")
|
||||
fset.write("\n")
|
||||
fset.write("use super::decode_error::DecodeError;\n")
|
||||
fset.write("use core::convert::TryFrom;\n")
|
||||
|
||||
ins_set_enum_def = """
|
||||
/// ISA set.
|
||||
#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
|
||||
#[allow(non_camel_case_types)]
|
||||
pub enum IsaSet {
|
||||
"""
|
||||
fset.write(ins_set_enum_def)
|
||||
for ins in nd_ins_set:
|
||||
line = ins.replace("ND_SET_", "")
|
||||
if line[0].isdigit():
|
||||
line = f"I{line}"
|
||||
fset.write(f"{line},\n")
|
||||
|
||||
fset.write("}\n")
|
||||
|
||||
try_from = """
|
||||
#[doc(hidden)]
|
||||
impl TryFrom<ffi::ND_INS_SET> for IsaSet {
|
||||
type Error = DecodeError;
|
||||
|
||||
#[allow(clippy::too_many_lines)]
|
||||
fn try_from(value: ffi::ND_INS_SET) -> Result<Self, Self::Error> {
|
||||
match value {
|
||||
ffi::_ND_INS_SET::ND_SET_INVALID => Err(DecodeError::InternalError(value as u64)),
|
||||
"""
|
||||
fset.write(try_from)
|
||||
for ins in nd_ins_set:
|
||||
ok = ins.replace('ND_SET_', '')
|
||||
if ok[0].isdigit():
|
||||
ok = f"I{ok}"
|
||||
line = f"ffi::_ND_INS_SET::{ins} => Ok(IsaSet::{ok}),\n"
|
||||
fset.write(line)
|
||||
|
||||
end = """
|
||||
}
|
||||
}
|
||||
}
|
||||
"""
|
||||
fset.write(end)
|
||||
|
||||
subprocess.check_output(["cargo", "fmt"])
|
File diff suppressed because it is too large
Load Diff
@ -1,65 +0,0 @@
|
||||
cmake_minimum_required(VERSION 3.16)
|
||||
|
||||
project(disasmtool LANGUAGES CXX)
|
||||
|
||||
# Use Release as the build type if no build type was specified and we're not using a multi-config generator .
|
||||
if (NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
|
||||
message(STATUS "No build type given. Will use 'Release'")
|
||||
set(CMAKE_BUILD_TYPE
|
||||
"Release"
|
||||
CACHE STRING "Choose the type of build." FORCE)
|
||||
# Set the possible values of build type for cmake-gui.
|
||||
set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS "Debug" "Release")
|
||||
endif ()
|
||||
|
||||
add_executable(disasmtool disasmtool.cpp dumpers.cpp rapidjson.cpp)
|
||||
|
||||
target_compile_options(
|
||||
disasmtool
|
||||
PRIVATE "$<$<CONFIG:Release>:-U_FORTIFY_SOURCE>"
|
||||
"$<$<CONFIG:Release>:-D_FORTIFY_SOURCE=2>"
|
||||
-Wall
|
||||
-Wextra
|
||||
-Wshadow
|
||||
-Wformat-security
|
||||
-Wstrict-overflow=2
|
||||
-Wno-unused-function
|
||||
-Wno-multichar
|
||||
-Werror=format-security
|
||||
-pipe
|
||||
-fpie
|
||||
-fwrapv
|
||||
-fno-strict-aliasing
|
||||
-fstack-protector-strong
|
||||
-ffunction-sections
|
||||
-fdata-sections
|
||||
-g3
|
||||
-gdwarf-4
|
||||
-grecord-gcc-switches
|
||||
-march=nehalem
|
||||
-fno-omit-frame-pointer)
|
||||
|
||||
if (NOT TARGET bddisasm)
|
||||
find_package(bddisasm REQUIRED)
|
||||
endif ()
|
||||
|
||||
find_package(RapidJSON QUIET REQUIRED)
|
||||
|
||||
target_link_libraries(disasmtool PRIVATE bddisasm::bddisasm bddisasm::bdshemu)
|
||||
# :( https://github.com/satishbabariya/modern-cmake#good-boys-export-their-targets
|
||||
target_include_directories(disasmtool PRIVATE ${RapidJSON_INCLUDE_DIRS})
|
||||
|
||||
if ("${CMAKE_BUILD_TYPE}" STREQUAL "Release")
|
||||
include(CheckIPOSupported)
|
||||
check_ipo_supported(RESULT USE_IPO)
|
||||
if (USE_IPO)
|
||||
set_target_properties(disasmtool PROPERTIES INTERPROCEDURAL_OPTIMIZATION True)
|
||||
endif ()
|
||||
endif ()
|
||||
|
||||
set_target_properties(
|
||||
disasmtool
|
||||
PROPERTIES POSITION_INDEPENDENT_CODE ON
|
||||
CXX_STANDARD 17
|
||||
CXX_STANDARD_REQUIRED ON
|
||||
CXX_EXTENSIONS ON)
|
@ -1,39 +0,0 @@
|
||||
.PHONY: all last_build debug release
|
||||
|
||||
CMAKE_BUILD_DIR = build
|
||||
|
||||
CPUCOUNT := $(shell grep -c "^processor" /proc/cpuinfo)
|
||||
|
||||
ifneq (,$(CPUCOUNT))
|
||||
EXTRA_MAKE_ARGS := -j$(CPUCOUNT)
|
||||
endif
|
||||
|
||||
# NINJA := $(shell which ninja 2>/dev/null)
|
||||
|
||||
ifneq (,$(NINJA))
|
||||
GENERATOR := "Ninja"
|
||||
else
|
||||
GENERATOR := "Unix Makefiles"
|
||||
endif
|
||||
|
||||
$(shell if [ ! -d $(CMAKE_BUILD_DIR) ]; then mkdir $(CMAKE_BUILD_DIR); fi)
|
||||
|
||||
all: last_build
|
||||
|
||||
last_build:
|
||||
@cmake -H. -G$(GENERATOR) -B$(CMAKE_BUILD_DIR) -DCMAKE_EXPORT_COMPILE_COMMANDS=ON
|
||||
@cmake --build $(CMAKE_BUILD_DIR) -- $(EXTRA_MAKE_ARGS)
|
||||
|
||||
debug: CMAKE_BUILD_TYPE := Debug
|
||||
debug: build
|
||||
|
||||
release: CMAKE_BUILD_TYPE := Release
|
||||
release: build
|
||||
|
||||
clean:
|
||||
@if [ -d $(CMAKE_BUILD_DIR) ]; then cmake --build $(CMAKE_BUILD_DIR) --target clean; fi
|
||||
|
||||
reset:
|
||||
@if [ -d $(CMAKE_BUILD_DIR) ]; then rm -r $(CMAKE_BUILD_DIR); fi
|
||||
|
||||
|
@ -1,66 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2020 Bitdefender
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <ctime>
|
||||
#include <cstdint>
|
||||
|
||||
#include <rapidjson/stringbuffer.h>
|
||||
using StringBuffer = rapidjson::StringBuffer;
|
||||
|
||||
|
||||
extern "C"
|
||||
{
|
||||
|
||||
// On windows, simply include Windows.h
|
||||
#ifndef _WIN32
|
||||
typedef void VOID, *PVOID;
|
||||
typedef unsigned char BOOLEAN, *PBOOLEAN;
|
||||
typedef char CHAR, *PCHAR;
|
||||
typedef unsigned char BYTE, *PBYTE;
|
||||
typedef unsigned short WORD, *PWORD;
|
||||
typedef unsigned int DWORD, *PDWORD;
|
||||
typedef unsigned long long QWORD, *PQWORD;
|
||||
typedef size_t SIZE_T;
|
||||
#endif
|
||||
|
||||
#ifndef FALSE
|
||||
#define FALSE 0
|
||||
#endif
|
||||
|
||||
#ifndef TRUE
|
||||
#define TRUE 1
|
||||
#endif
|
||||
|
||||
#ifndef MAX_PATH
|
||||
#define MAX_PATH 255
|
||||
#endif
|
||||
|
||||
// Main disasm header file.
|
||||
#include "bdshemu.h"
|
||||
#include "bddisasm.h"
|
||||
|
||||
#include <unistd.h>
|
||||
#include <time.h>
|
||||
}
|
||||
|
||||
|
||||
#include <string>
|
||||
|
||||
|
||||
std::string enc_mode_to_str(const uint8_t enc_mode);
|
||||
std::string op_type_to_str(const ND_OPERAND_TYPE type);
|
||||
std::string op_enc_to_str(const ND_OPERAND_ENCODING Encoding);
|
||||
std::string ins_class_to_str(const ND_INS_CLASS cls);
|
||||
std::string ins_cat_to_str(ND_INS_CATEGORY category);
|
||||
std::string ins_set_to_str(ND_INS_SET ins_set);
|
||||
std::string reg_to_str(const int reg, const ND_REG_TYPE type);
|
||||
std::string reg_type_to_str(const ND_REG_TYPE type);
|
||||
|
||||
StringBuffer instrux_to_json(INSTRUX *instrux, size_t rip, bool text_only = false);
|
||||
StringBuffer byte_to_json(uint8_t byte, size_t rip);
|
||||
StringBuffer disassemble_one(uint8_t *bytes, size_t size, size_t rip, uint8_t bits, uint8_t vendor = ND_VEND_INTEL);
|
||||
|
||||
bool regs_from_json(const std::string &str, SHEMU_GPR_REGS ®s, bool &update_rsp);
|
@ -1,927 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2020 Bitdefender
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <memory>
|
||||
#include <limits>
|
||||
#include <cmath>
|
||||
#include <cpuid.h>
|
||||
|
||||
#include "external/argparse.h"
|
||||
|
||||
#include "disasm.hpp"
|
||||
|
||||
#define STACK_SIZE 0x2000
|
||||
#define PAGE_MASK 0xFFFFFFFFFFFFF000
|
||||
|
||||
static const long NSEC_PER_SEC = (1000ULL * 1000ULL * 1000ULL);
|
||||
|
||||
static const char *gSpaces[16] =
|
||||
{
|
||||
"",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
};
|
||||
|
||||
|
||||
struct options {
|
||||
size_t rip;
|
||||
size_t offset;
|
||||
size_t size;
|
||||
size_t count;
|
||||
|
||||
uint8_t bits;
|
||||
|
||||
uint8_t vendor;
|
||||
bool no_color;
|
||||
bool verbose;
|
||||
bool dump_stats;
|
||||
bool interactive;
|
||||
bool comm;
|
||||
bool json_output;
|
||||
bool extended;
|
||||
|
||||
bool shemu;
|
||||
std::string shctx;
|
||||
bool kernel;
|
||||
|
||||
std::string in_file;
|
||||
std::string hex_string;
|
||||
std::string hex_file;
|
||||
std::string shctx_file;
|
||||
std::string shdec_file;
|
||||
|
||||
// From here on, these are set internally
|
||||
std::unique_ptr<uint8_t[]> bytes;
|
||||
size_t actual_size;
|
||||
int address_size;
|
||||
|
||||
bool output_redirected;
|
||||
};
|
||||
|
||||
|
||||
extern "C"
|
||||
{
|
||||
#if !defined(BDDISASM_HAS_VSNPRINTF)
|
||||
int nd_vsnprintf_s(char *buffer, size_t sizeOfBuffer, [[maybe_unused]] size_t count, const char *format, va_list argptr)
|
||||
{
|
||||
return vsnprintf(buffer, sizeOfBuffer, format, argptr);
|
||||
}
|
||||
#endif // !defined(BDDISASM_HAS_VSNPRINTF)
|
||||
|
||||
#if !defined(BDDISASM_HAS_MEMSET)
|
||||
void *
|
||||
nd_memset(void *s, int c, size_t n)
|
||||
{
|
||||
return memset(s, c, n);
|
||||
}
|
||||
#endif // !defined(BDDISASM_HAS_MEMSET)
|
||||
}
|
||||
|
||||
static bool _hexstring_to_bytes(options &opts)
|
||||
{
|
||||
if (!opts.hex_file.empty()) {
|
||||
auto f = std::ifstream(opts.hex_file, std::ios::in);
|
||||
|
||||
if (!f.is_open()) {
|
||||
std::cerr << "Failed to open file " << opts.hex_file << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
f.seekg(0, std::ios::end);
|
||||
opts.hex_string.reserve(f.tellg());
|
||||
f.seekg(0, std::ios::beg);
|
||||
|
||||
opts.hex_string.assign((std::istreambuf_iterator<char>(f)), std::istreambuf_iterator<char>());
|
||||
}
|
||||
|
||||
if (opts.hex_string.empty())
|
||||
return false;
|
||||
|
||||
opts.actual_size = 0;
|
||||
opts.hex_string.erase(std::remove_if(opts.hex_string.begin(), opts.hex_string.end(), isspace), opts.hex_string.end());
|
||||
|
||||
// This is the maximum size, not the actual size
|
||||
auto initial_size = opts.hex_string.length() / 2 + 1;
|
||||
|
||||
opts.bytes = std::make_unique<uint8_t[]>(initial_size);
|
||||
auto bytes = opts.bytes.get();
|
||||
|
||||
for (size_t i = 0; i < opts.hex_string.length(); i += 2) {
|
||||
auto pair = opts.hex_string.substr(i, 2);
|
||||
char *end_ptr;
|
||||
|
||||
if (pair == "0x" || pair == "0X" || pair == "\\x")
|
||||
continue;
|
||||
|
||||
auto b = static_cast<uint8_t>(std::strtoul(pair.c_str(), &end_ptr, 16));
|
||||
|
||||
size_t conv_size = static_cast<size_t>(end_ptr - pair.c_str());
|
||||
|
||||
if (conv_size != pair.length()) {
|
||||
std::cerr << "Trying to convert invalid hex number: " << pair << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
bytes[opts.actual_size++] = b;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool _load_shctx(options &opts)
|
||||
{
|
||||
if (opts.shctx_file.empty())
|
||||
return false;
|
||||
|
||||
auto f = std::ifstream(opts.shctx_file, std::ios::in);
|
||||
if (!f.is_open()) {
|
||||
std::cout << "Failed to open file " << opts.shctx_file << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
f.seekg(0, std::ios::end);
|
||||
opts.shctx.reserve(f.tellg());
|
||||
f.seekg(0, std::ios::beg);
|
||||
|
||||
opts.shctx.assign((std::istreambuf_iterator<char>(f)), std::istreambuf_iterator<char>());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool _file_to_bytes(options &opts)
|
||||
{
|
||||
auto f = std::ifstream(opts.in_file, std::ios::in | std::ios::binary);
|
||||
|
||||
if (!f.is_open()) {
|
||||
std::cerr << "Failed to open file " << opts.in_file << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
f.seekg(0, std::ios::end);
|
||||
|
||||
opts.actual_size = f.tellg();
|
||||
|
||||
if (opts.offset >= opts.actual_size) {
|
||||
std::cerr << "Offset bigger than file size" << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
f.seekg(0, std::ios::beg);
|
||||
|
||||
opts.bytes = std::make_unique<uint8_t[]>(opts.actual_size);
|
||||
|
||||
f.read(reinterpret_cast<char*>(opts.bytes.get()), opts.actual_size);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Don't change the order (on linux these values are color codes)
|
||||
enum Colors {
|
||||
Reset = 0,
|
||||
#if defined(_WIN32)
|
||||
Red = FOREGROUND_INTENSITY | FOREGROUND_RED,
|
||||
Green = FOREGROUND_INTENSITY | FOREGROUND_GREEN,
|
||||
Yellow = FOREGROUND_INTENSITY | FOREGROUND_RED | FOREGROUND_GREEN,
|
||||
Blue = FOREGROUND_INTENSITY | FOREGROUND_BLUE,
|
||||
Magenta = FOREGROUND_INTENSITY | FOREGROUND_BLUE | FOREGROUND_RED,
|
||||
Cyan = FOREGROUND_INTENSITY | FOREGROUND_BLUE | FOREGROUND_GREEN,
|
||||
White = FOREGROUND_INTENSITY | FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED,
|
||||
#elif defined(__unix__)
|
||||
Red,
|
||||
Green,
|
||||
Yellow,
|
||||
Blue,
|
||||
Magenta,
|
||||
Cyan,
|
||||
White,
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
static void _set_text_color(Colors color)
|
||||
{
|
||||
#if defined(_WIN32)
|
||||
static WORD old_attrs = -1;
|
||||
|
||||
if (old_attrs == -1) {
|
||||
CONSOLE_SCREEN_BUFFER_INFO buffer_info;
|
||||
GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &buffer_info);
|
||||
old_attrs = buffer_info.wAttributes;
|
||||
}
|
||||
|
||||
if (color == Reset)
|
||||
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), old_attrs);
|
||||
else
|
||||
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), color);
|
||||
#elif defined(__unix__)
|
||||
if (color == Reset)
|
||||
std::cout << "\033[m";
|
||||
else
|
||||
std::cout << "\033[0;3" << color << "m";
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
static struct timespec diff_time(struct timespec const &end, struct timespec const &start)
|
||||
{
|
||||
struct timespec result;
|
||||
|
||||
if (end.tv_nsec > start.tv_nsec) {
|
||||
result.tv_sec = end.tv_sec - start.tv_sec;
|
||||
result.tv_nsec = end.tv_nsec - start.tv_nsec;
|
||||
} else {
|
||||
result.tv_sec = end.tv_sec - start.tv_sec - 1;
|
||||
result.tv_nsec = NSEC_PER_SEC + end.tv_nsec - start.tv_nsec;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
void print_instruction(const size_t rip, INSTRUX *instrux, const options &opts)
|
||||
{
|
||||
char instruxText[ND_MIN_BUF_SIZE];
|
||||
uint32_t k = 0;
|
||||
|
||||
printf("%*zx ", opts.address_size, rip);
|
||||
|
||||
if (!opts.no_color)
|
||||
{
|
||||
_set_text_color(Magenta);
|
||||
for (uint32_t idx = 0; idx < instrux->PrefLength; idx++, k++)
|
||||
{
|
||||
printf("%02x", instrux->InstructionBytes[k]);
|
||||
}
|
||||
|
||||
_set_text_color(Green);
|
||||
for (uint32_t idx = 0; idx < (DWORD)(ND_IS_3DNOW(instrux) ? instrux->OpLength - 1 : instrux->OpLength); idx++, k++)
|
||||
{
|
||||
printf("%02x", instrux->InstructionBytes[k]);
|
||||
}
|
||||
|
||||
_set_text_color(Yellow);
|
||||
for (uint32_t idx = 0; idx < (DWORD)(instrux->HasModRm + instrux->HasSib); idx++, k++)
|
||||
{
|
||||
printf("%02x", instrux->InstructionBytes[k]);
|
||||
}
|
||||
|
||||
_set_text_color(Blue);
|
||||
for (uint32_t idx = 0; idx < (DWORD)(instrux->DispLength); idx++, k++)
|
||||
{
|
||||
printf("%02x", instrux->InstructionBytes[k]);
|
||||
}
|
||||
|
||||
_set_text_color(Red);
|
||||
for (uint32_t idx = 0; idx < (DWORD)(instrux->Imm1Length + instrux->Imm2Length +
|
||||
instrux->RelOffsLength + instrux->MoffsetLength +
|
||||
instrux->HasSseImm + instrux->AddrLength); idx++, k++)
|
||||
{
|
||||
printf("%02x", instrux->InstructionBytes[k]);
|
||||
}
|
||||
|
||||
if (ND_IS_3DNOW(instrux))
|
||||
{
|
||||
_set_text_color(Green);
|
||||
for (; k < instrux->Length; k++)
|
||||
{
|
||||
printf("%02x", instrux->InstructionBytes[k]);
|
||||
}
|
||||
}
|
||||
|
||||
_set_text_color(Reset);
|
||||
}
|
||||
|
||||
for (; k < instrux->Length; k++)
|
||||
{
|
||||
printf("%02x", instrux->InstructionBytes[k]);
|
||||
}
|
||||
|
||||
std::cout << gSpaces[16 - instrux->Length];
|
||||
|
||||
NdToText(instrux, rip, sizeof(instruxText), instruxText);
|
||||
|
||||
std::cout << instruxText << std::endl;
|
||||
|
||||
if (opts.extended) {
|
||||
const uint8_t opsize[3] = { 2, 4, 8 };
|
||||
const uint8_t adsize[3] = { 2, 4, 8 };
|
||||
const uint8_t veclen[3] = { 16, 32, 64 };
|
||||
|
||||
printf(" DSIZE: %2d, ASIZE: %2d, VLEN: ",
|
||||
opsize[instrux->EfOpMode] * 8, adsize[instrux->AddrMode] * 8);
|
||||
|
||||
if (ND_HAS_VECTOR(instrux)) {
|
||||
printf("%2d\n", veclen[instrux->VecMode] * 8);
|
||||
} else {
|
||||
printf("-\n");
|
||||
}
|
||||
|
||||
printf(" ISA Set: %s, Ins cat: %s, Ins class: %d, CET tracked: %s\n",
|
||||
ins_set_to_str(instrux->IsaSet).c_str(), ins_cat_to_str(instrux->Category).c_str(), instrux->Instruction,
|
||||
instrux->IsCetTracked ? "yes" : "no");
|
||||
|
||||
if (0 != instrux->CpuidFlag.Flag) {
|
||||
const char *regs[4] = { "eax", "ecx", "edx", "ebx" };
|
||||
|
||||
printf(" CPUID leaf: 0x%08x", instrux->CpuidFlag.Leaf);
|
||||
|
||||
if (instrux->CpuidFlag.SubLeaf != ND_CFF_NO_SUBLEAF)
|
||||
{
|
||||
printf(", sub-leaf: 0x%08x", instrux->CpuidFlag.SubLeaf);
|
||||
}
|
||||
|
||||
printf(", reg: %s, bit %u\n", regs[instrux->CpuidFlag.Reg], instrux->CpuidFlag.Bit);
|
||||
}
|
||||
|
||||
printf(" FLAGS access: ");
|
||||
|
||||
uint32_t all = instrux->FlagsAccess.Tested.Raw | instrux->FlagsAccess.Modified.Raw | instrux->FlagsAccess.Set.Raw
|
||||
| instrux->FlagsAccess.Cleared.Raw | instrux->FlagsAccess.Undefined.Raw;
|
||||
const char *flags[22] = { "CF", nullptr, "PF", nullptr, "AF", nullptr, "ZF", "SF", "TF", "IF", "DF", "OF", "IOPL", nullptr, "NT", nullptr, "RF", "VM", "AC", "VIF", "VIP", "ID" };
|
||||
|
||||
for (uint32_t fidx = 0; fidx < 21; fidx++) {
|
||||
if (flags[fidx] != nullptr) {
|
||||
if (0 == (all & (1ULL << fidx))) {
|
||||
continue;
|
||||
}
|
||||
|
||||
printf("%s: ", flags[fidx]);
|
||||
|
||||
if (instrux->FlagsAccess.Tested.Raw & (1ULL << fidx)) {
|
||||
printf("t");
|
||||
}
|
||||
|
||||
if (instrux->FlagsAccess.Modified.Raw & (1ULL << fidx)) {
|
||||
printf("m");
|
||||
}
|
||||
|
||||
if (instrux->FlagsAccess.Set.Raw & (1ULL << fidx)) {
|
||||
printf("1");
|
||||
}
|
||||
|
||||
if (instrux->FlagsAccess.Cleared.Raw & (1ULL << fidx)) {
|
||||
printf("0");
|
||||
}
|
||||
|
||||
if (instrux->FlagsAccess.Undefined.Raw & (1ULL << fidx)) {
|
||||
printf("u");
|
||||
}
|
||||
|
||||
printf("; ");
|
||||
}
|
||||
}
|
||||
|
||||
printf("\n");
|
||||
|
||||
printf(" Valid modes: R0: %s, R1: %s, R2: %s, R3: %s, Real: %s, V8086: %s, Prot: %s, Compat: %s, Long: %s, SMM: %s, SGX: %s, TSX: %s, VMXRoot: %s, VMXNonRoot: %s\n",
|
||||
instrux->ValidModes.Ring0 ? "yes" : "no",
|
||||
instrux->ValidModes.Ring1 ? "yes" : "no",
|
||||
instrux->ValidModes.Ring2 ? "yes" : "no",
|
||||
instrux->ValidModes.Ring3 ? "yes" : "no",
|
||||
instrux->ValidModes.Real ? "yes" : "no",
|
||||
instrux->ValidModes.V8086 ? "yes" : "no",
|
||||
instrux->ValidModes.Protected ? "yes" : "no",
|
||||
instrux->ValidModes.Compat ? "yes" : "no",
|
||||
instrux->ValidModes.Long ? "yes" : "no",
|
||||
instrux->ValidModes.Smm ? "yes" : "no",
|
||||
instrux->ValidModes.Sgx ? "yes" : "no",
|
||||
instrux->ValidModes.Tsx ? "yes" : "no",
|
||||
instrux->ValidModes.VmxRoot ? "yes" : "no",
|
||||
instrux->ValidModes.VmxNonRoot ? "yes" : "no");
|
||||
|
||||
for (uint8_t i = 0; i < instrux->OperandsCount; i++) {
|
||||
printf(" Operand %d %s Type: %10s, Size: %2d, RawSize: %2d, Encoding: %s", i,
|
||||
instrux->Operands[i].Access.Read && instrux->Operands[i].Access.Write ? "RW" :
|
||||
instrux->Operands[i].Access.Write ? "-W" : instrux->Operands[i].Access.Read ? "R-" : "--",
|
||||
op_type_to_str(instrux->Operands[i].Type).c_str(), (int)instrux->Operands[i].Size,
|
||||
(int)instrux->Operands[i].RawSize, op_enc_to_str(instrux->Operands[i].Encoding).c_str());
|
||||
|
||||
if (ND_OP_MEM == instrux->Operands[i].Type) {
|
||||
printf(", ");
|
||||
|
||||
if (instrux->Operands[i].Info.Memory.IsAG) {
|
||||
printf("Address Generator, ");
|
||||
}
|
||||
|
||||
if (instrux->Operands[i].Info.Memory.IsBitbase) {
|
||||
printf("Bitbase Addressing, ");
|
||||
}
|
||||
|
||||
if (instrux->Operands[i].Info.Memory.IsMib) {
|
||||
printf("MIB Addressing, ");
|
||||
}
|
||||
|
||||
if (instrux->Operands[i].Info.Memory.IsVsib) {
|
||||
printf("VSIB Addressing, ");
|
||||
}
|
||||
|
||||
if (instrux->Operands[i].Info.Memory.IsStack) {
|
||||
printf("Stack, ");
|
||||
}
|
||||
|
||||
if (instrux->Operands[i].Info.Memory.IsShadowStack) {
|
||||
printf("Shadow Stack, ");
|
||||
}
|
||||
}
|
||||
|
||||
if (ND_OP_REG == instrux->Operands[i].Type) {
|
||||
printf(", RegType: %16s, RegSize: %2u, ",
|
||||
reg_type_to_str(instrux->Operands[i].Info.Register.Type).c_str(),
|
||||
instrux->Operands[i].Info.Register.Size);
|
||||
if (instrux->Operands[i].Info.Register.Type == ND_REG_MSR)
|
||||
{
|
||||
printf("RegId: 0x%08x, RegCount: %u\n",
|
||||
instrux->Operands[i].Info.Register.Reg,
|
||||
instrux->Operands[i].Info.Register.Count);
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("RegId: %u, RegCount: %u\n",
|
||||
instrux->Operands[i].Info.Register.Reg,
|
||||
instrux->Operands[i].Info.Register.Count);
|
||||
}
|
||||
}
|
||||
|
||||
printf("\n");
|
||||
|
||||
if (instrux->Operands[i].Decorator.HasBroadcast) {
|
||||
printf(" Decorator: Broadcast %d bytes element %d times\n",
|
||||
instrux->Operands[i].Decorator.Broadcast.Size,
|
||||
instrux->Operands[i].Decorator.Broadcast.Count);
|
||||
}
|
||||
|
||||
if (instrux->Operands[i].Decorator.HasMask) {
|
||||
printf(" Decorator: Mask k%d\n", instrux->Operands[i].Decorator.Mask.Msk);
|
||||
}
|
||||
|
||||
if (instrux->Operands[i].Decorator.HasZero) {
|
||||
printf(" Decorator: Zero (no merging)\n");
|
||||
}
|
||||
}
|
||||
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
StringBuffer disassemble_one(uint8_t *bytes, size_t size, size_t rip, uint8_t bits, uint8_t vendor /* = ND_VEND_INTEL */)
|
||||
{
|
||||
INSTRUX instrux;
|
||||
|
||||
auto status = NdDecodeEx2(&instrux, bytes, size, bits, bits, bits, vendor);
|
||||
if (!ND_SUCCESS(status))
|
||||
return byte_to_json(bytes[0], rip);
|
||||
else
|
||||
return instrux_to_json(&instrux, rip);
|
||||
}
|
||||
|
||||
void shemu_log(PCHAR msg)
|
||||
{
|
||||
printf("%s", msg);
|
||||
}
|
||||
|
||||
ND_BOOL shemu_access_mem(void * /* Ctx */, uint64_t /* Gla */, size_t Size, uint8_t *Buffer, ND_BOOL Store)
|
||||
{
|
||||
if (!Store)
|
||||
{
|
||||
memset(Buffer, 0, Size);
|
||||
}
|
||||
|
||||
return ND_TRUE;
|
||||
}
|
||||
|
||||
void shemu(options &opts)
|
||||
{
|
||||
SHEMU_CONTEXT ctx = { };
|
||||
SHEMU_STATUS shstatus;
|
||||
|
||||
auto stack = std::make_unique<uint8_t[]>(STACK_SIZE);
|
||||
auto intbuf = std::make_unique<uint8_t[]>(opts.actual_size + STACK_SIZE);
|
||||
auto shellcode = std::make_unique<uint8_t[]>(opts.actual_size);
|
||||
|
||||
ctx.Stack = stack.get();
|
||||
memset(ctx.Stack, 0, STACK_SIZE);
|
||||
|
||||
ctx.Intbuf = intbuf.get();
|
||||
memset(ctx.Intbuf, 0, opts.actual_size + STACK_SIZE);
|
||||
|
||||
ctx.Shellcode = shellcode.get();
|
||||
memcpy(ctx.Shellcode, opts.bytes.get(), opts.actual_size);
|
||||
|
||||
ctx.ShellcodeSize = opts.actual_size;
|
||||
ctx.StackSize = STACK_SIZE;
|
||||
ctx.Registers.RegRsp = 0x101000;
|
||||
ctx.IntbufSize = opts.actual_size + STACK_SIZE;
|
||||
|
||||
ctx.Registers.RegFlags = NDR_RFLAG_IF | 2;
|
||||
ctx.Registers.RegRip = opts.rip ? opts.rip : 0x200000;
|
||||
ctx.Segments.Cs.Selector = 0x10;
|
||||
ctx.Segments.Ds.Selector = 0x28;
|
||||
ctx.Segments.Es.Selector = 0x28;
|
||||
ctx.Segments.Ss.Selector = 0x28;
|
||||
ctx.Segments.Fs.Selector = 0x30;
|
||||
ctx.Segments.Fs.Base = 0x7FFF0000;
|
||||
ctx.Segments.Gs.Selector = 0x30;
|
||||
ctx.Segments.Gs.Base = 0x7FFF0000;
|
||||
|
||||
// Dummy values, to resemble regular CR0/CR4 values.
|
||||
ctx.Registers.RegCr0 = 0x0000000080050031;
|
||||
ctx.Registers.RegCr4 = 0x0000000000170678;
|
||||
|
||||
ctx.Mode = opts.bits;
|
||||
ctx.Ring = opts.kernel ? 0 : 3;
|
||||
ctx.TibBase = (opts.bits == ND_DATA_32 ? ctx.Segments.Fs.Base : ctx.Segments.Gs.Base);
|
||||
ctx.MaxInstructionsCount = 4096;
|
||||
ctx.Options = SHEMU_OPT_TRACE_EMULATION;
|
||||
ctx.Log = shemu_log;
|
||||
ctx.AccessMemory = shemu_access_mem;
|
||||
|
||||
uint32_t eax, ebx, ecx, edx;
|
||||
|
||||
eax = ebx = ecx = edx = 0;
|
||||
|
||||
__get_cpuid(1, &eax, &ebx, &ecx, &edx);
|
||||
|
||||
if (!!(ecx & (1UL << 25)))
|
||||
{
|
||||
ctx.Options |= SHEMU_OPT_SUPPORT_AES;
|
||||
}
|
||||
|
||||
// Configurable thresholds.
|
||||
ctx.NopThreshold = SHEMU_DEFAULT_NOP_THRESHOLD;
|
||||
ctx.StrThreshold = SHEMU_DEFAULT_STR_THRESHOLD;
|
||||
ctx.MemThreshold = SHEMU_DEFAULT_MEM_THRESHOLD;
|
||||
|
||||
bool update_rsp = false;
|
||||
|
||||
if (!opts.shctx.empty() && !regs_from_json(opts.shctx, ctx.Registers, update_rsp)) {
|
||||
std::cerr << "Failed to parse context file." << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
// Consider the stack base at least with a page before the current RSP. In case of pushes or operations
|
||||
// which decrease the RSP, we will always give SHEMU_ABORT_BRANCH_OUTSIDE otherwise.
|
||||
ctx.StackBase = ctx.Registers.RegRsp - 0x1000;
|
||||
ctx.ShellcodeBase = (ctx.Registers.RegRip ? ctx.Registers.RegRip & PAGE_MASK : 0x200000);
|
||||
|
||||
shstatus = ShemuEmulate(&ctx);
|
||||
|
||||
printf("Emulation terminated with status 0x%08x, flags: 0x%llx, %u NOPs\n",
|
||||
shstatus, (unsigned long long)ctx.Flags, ctx.NopCount);
|
||||
if (ctx.Flags & SHEMU_FLAG_NOP_SLED)
|
||||
{
|
||||
printf(" SHEMU_FLAG_NOP_SLED\n");
|
||||
}
|
||||
if (ctx.Flags & SHEMU_FLAG_LOAD_RIP)
|
||||
{
|
||||
printf(" SHEMU_FLAG_LOAD_RIP\n");
|
||||
}
|
||||
if (ctx.Flags & SHEMU_FLAG_WRITE_SELF)
|
||||
{
|
||||
printf(" SHEMU_FLAG_WRITE_SELF\n");
|
||||
}
|
||||
if (ctx.Flags & SHEMU_FLAG_TIB_ACCESS)
|
||||
{
|
||||
printf(" SHEMU_FLAG_TIB_ACCESS\n");
|
||||
}
|
||||
if (ctx.Flags & SHEMU_FLAG_SYSCALL)
|
||||
{
|
||||
printf(" SHEMU_FLAG_SYSCALL\n");
|
||||
}
|
||||
if (ctx.Flags & SHEMU_FLAG_STACK_STR)
|
||||
{
|
||||
printf(" SHEMU_FLAG_STACK_STR\n");
|
||||
}
|
||||
if (ctx.Flags & SHEMU_FLAG_KPCR_ACCESS)
|
||||
{
|
||||
printf(" SHEMU_FLAG_KPCR_ACCESS\n");
|
||||
}
|
||||
if (ctx.Flags & SHEMU_FLAG_SWAPGS)
|
||||
{
|
||||
printf(" SHEMU_FLAG_SWAPGS\n");
|
||||
}
|
||||
if (ctx.Flags & SHEMU_FLAG_SYSCALL_MSR_READ)
|
||||
{
|
||||
printf(" SHEMU_FLAG_SYSCALL_MSR_READ\n");
|
||||
}
|
||||
if (ctx.Flags & SHEMU_FLAG_SYSCALL_MSR_WRITE)
|
||||
{
|
||||
printf(" SHEMU_FLAG_SYSCALL_MSR_WRITE\n");
|
||||
}
|
||||
|
||||
if (!opts.shdec_file.empty()) {
|
||||
auto f = std::ofstream(opts.shdec_file, std::ios::out | std::ios::binary);
|
||||
|
||||
if (!f.is_open())
|
||||
std::cerr << "Failed to open file " << opts.shdec_file<< std::endl;
|
||||
else
|
||||
f.write(reinterpret_cast<char*>(ctx.Shellcode), ctx.ShellcodeSize);
|
||||
}
|
||||
}
|
||||
|
||||
size_t disassemble(options &opts)
|
||||
{
|
||||
struct timespec start;
|
||||
clock_gettime(CLOCK_THREAD_CPUTIME_ID, &start);
|
||||
|
||||
size_t icount = 0, miss_count = 0, ibytes = 0;
|
||||
size_t rel_rip = opts.offset;
|
||||
size_t total_disasm = 0;
|
||||
auto bytes = opts.bytes.get();
|
||||
auto disasm_size = std::min(opts.actual_size - opts.offset, opts.size);
|
||||
|
||||
opts.address_size = int(std::ceil(((8 * sizeof(opts.actual_size)) - __builtin_clzll(opts.actual_size)) / 4.0));
|
||||
|
||||
while ((total_disasm < disasm_size) && (icount < opts.count)) {
|
||||
INSTRUX instrux;
|
||||
|
||||
auto status = NdDecodeEx2(&instrux,
|
||||
&bytes[rel_rip],
|
||||
opts.actual_size - rel_rip,
|
||||
opts.bits,
|
||||
opts.bits,
|
||||
opts.bits,
|
||||
opts.vendor);
|
||||
|
||||
if (!ND_SUCCESS(status)) {
|
||||
if (!opts.dump_stats) {
|
||||
|
||||
if (opts.json_output) {
|
||||
auto j = byte_to_json(bytes[rel_rip], rel_rip + opts.rip);
|
||||
std::cout << j.GetString() << std::endl;
|
||||
} else {
|
||||
printf("%*zx ", opts.address_size, rel_rip + opts.rip);
|
||||
printf("%02x", bytes[rel_rip]);
|
||||
printf("%s", gSpaces[16 - opts.address_size]);
|
||||
printf("db 0x%02x\n", bytes[rel_rip]);
|
||||
}
|
||||
}
|
||||
|
||||
rel_rip++;
|
||||
total_disasm++;
|
||||
|
||||
miss_count++;
|
||||
} else {
|
||||
icount++;
|
||||
ibytes += instrux.Length;
|
||||
|
||||
if (!opts.dump_stats) {
|
||||
if (opts.json_output) {
|
||||
auto j = instrux_to_json(&instrux, rel_rip + opts.rip);
|
||||
std::cout << j.GetString() << std::endl;
|
||||
} else
|
||||
print_instruction(rel_rip + opts.rip, &instrux, opts);
|
||||
} else if (opts.json_output)
|
||||
instrux_to_json(&instrux, rel_rip + opts.rip);
|
||||
|
||||
rel_rip += instrux.Length;
|
||||
total_disasm += instrux.Length;
|
||||
}
|
||||
}
|
||||
|
||||
struct timespec end;
|
||||
clock_gettime(CLOCK_THREAD_CPUTIME_ID, &end);
|
||||
|
||||
if (opts.dump_stats)
|
||||
{
|
||||
auto result = diff_time(end, start);
|
||||
|
||||
long total_ns = result.tv_sec * NSEC_PER_SEC + result.tv_nsec;
|
||||
|
||||
printf("Disassembled %zu instructions took %ld.%09ld seconds, %lu ns / instr.\n",
|
||||
icount, result.tv_sec, result.tv_nsec, total_ns / icount);
|
||||
printf("Invalid: %zu/%zu (%.2f) bytes\n", miss_count, ibytes,
|
||||
(static_cast<double>(miss_count) / static_cast<double>(disasm_size)) * 100.0);
|
||||
}
|
||||
|
||||
opts.rip += rel_rip;
|
||||
|
||||
return icount;
|
||||
}
|
||||
|
||||
|
||||
static bool _validate_and_fix_args(options& opts)
|
||||
{
|
||||
if (!opts.interactive && !opts.comm) {
|
||||
int total = 0;
|
||||
|
||||
if (!opts.hex_string.empty())
|
||||
total++;
|
||||
|
||||
if (!opts.hex_file.empty())
|
||||
total++;
|
||||
|
||||
if (!opts.in_file.empty())
|
||||
total++;
|
||||
|
||||
if (total == 0) {
|
||||
std::cerr << "Give hex, file or hex-file..." << std::endl;
|
||||
return false;
|
||||
} else if (total > 1) {
|
||||
std::cerr << "Only one of hex, file or hex-file can be present..." << std::endl;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (opts.interactive || opts.comm) {
|
||||
if (!opts.in_file.empty() || !opts.hex_string.empty() || !opts.hex_file.empty()) {
|
||||
std::cerr << "Interactive mode doesn't work with file, hex-string or hex-file" << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (opts.size || opts.count || opts.offset) {
|
||||
std::cerr << "Interactive mode doesn't work with size, count or offset" << std::endl;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
switch (opts.bits) {
|
||||
case 64:
|
||||
opts.bits = ND_DATA_64;
|
||||
break;
|
||||
|
||||
case 32:
|
||||
opts.bits = ND_DATA_32;
|
||||
break;
|
||||
|
||||
case 16:
|
||||
opts.bits = ND_DATA_16;
|
||||
break;
|
||||
|
||||
default:
|
||||
std::cerr << "Please give --bits [64,32,16]" << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (0 == opts.size)
|
||||
opts.size = std::numeric_limits<std::size_t>::max();
|
||||
|
||||
if (0 == opts.count)
|
||||
opts.count = std::numeric_limits<std::size_t>::max();
|
||||
|
||||
if (!isatty(fileno(stdout)))
|
||||
opts.output_redirected = true;
|
||||
|
||||
if (!opts.hex_file.empty())
|
||||
opts.shdec_file = opts.hex_file + "_decoded.bin";
|
||||
else if (!opts.in_file.empty())
|
||||
opts.shdec_file = opts.in_file + "_decoded.bin";
|
||||
else
|
||||
opts.shdec_file = "hex_string_decoded.bin";
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
static size_t _get_hex_opt(argparse::ArgumentParser &parser, const std::string &field)
|
||||
{
|
||||
return std::strtoul(parser.get<std::string>(field).c_str(), nullptr, 0);
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, const char **argv)
|
||||
{
|
||||
auto opts = options{};
|
||||
|
||||
auto parser = argparse::ArgumentParser(argv[0], "Disassembler tool for Linux");
|
||||
|
||||
parser.add_argument("-i", "--interactive", "Interactive mode", false);
|
||||
parser.add_argument("-c", "--comm", "Comm mode", false);
|
||||
parser.add_argument("-r", "--rip", "Use this rip to disassemble", false);
|
||||
parser.add_argument("-f", "--file", "Use this input file", false);
|
||||
parser.add_argument("-x", "--hex", "Use this hex-string", false);
|
||||
parser.add_argument("--hexfile", "Use this input file as a hex-string", false);
|
||||
parser.add_argument("--no-color", "Don't use colors", false);
|
||||
parser.add_argument("--offset", "Use this offset in file/hex-string", false);
|
||||
parser.add_argument("--size", "Only disasemble this size from file/hex-string", false);
|
||||
parser.add_argument("--count", "Only disasemble this many instructions", false);
|
||||
parser.add_argument("--stats", "Dump statistics (time, count, etc.)", false);
|
||||
parser.add_argument("-b", "--bits", "Use the arch [16, 32, 64]", false);
|
||||
parser.add_argument("--verbose", "Verbose mode", false);
|
||||
parser.add_argument("--json", "Output to json", false);
|
||||
parser.add_argument("--extended", "Extended instruction info", false);
|
||||
parser.add_argument("--shemu", "Emulate the input hexfile", false);
|
||||
parser.add_argument("--kernel", "Kernel mode for shemu context", false);
|
||||
parser.add_argument("--shctx", "Shemu context file. Must be a JSON file.", false);
|
||||
|
||||
parser.enable_help();
|
||||
|
||||
auto err = parser.parse(argc, argv);
|
||||
if (err) {
|
||||
std::cout << err << std::endl;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (parser.exists("help")) {
|
||||
parser.print_help();
|
||||
return 0;
|
||||
}
|
||||
|
||||
opts.bits = parser.get<uint64_t>("bits");
|
||||
opts.interactive = parser.exists("interactive");
|
||||
opts.comm = parser.exists("comm");
|
||||
opts.offset = _get_hex_opt(parser, "offset");
|
||||
opts.size = _get_hex_opt(parser, "size");
|
||||
opts.count = _get_hex_opt(parser, "count");
|
||||
opts.rip = _get_hex_opt(parser, "rip");
|
||||
opts.in_file = parser.get<std::string>("file");
|
||||
opts.hex_string = parser.get<std::string>("hex");
|
||||
opts.hex_file = parser.get<std::string>("hexfile");
|
||||
opts.no_color = parser.exists("no-color");
|
||||
opts.dump_stats = parser.exists("stats");
|
||||
opts.verbose = parser.exists("verbose");
|
||||
opts.json_output = parser.exists("json");
|
||||
opts.extended = parser.exists("extended");
|
||||
opts.shemu = parser.exists("shemu");
|
||||
opts.kernel = parser.exists("kernel");
|
||||
opts.shctx_file = parser.get<std::string>("shctx");
|
||||
|
||||
if (opts.verbose) {
|
||||
std::cout << "interactive: " << opts.interactive << std::endl;
|
||||
std::cout << "comm: " << opts.comm << std::endl;
|
||||
std::cout << "rip: " << opts.rip << std::endl;
|
||||
std::cout << "bits: " << static_cast<uint16_t>(opts.bits) << std::endl;
|
||||
std::cout << "offset: " << opts.offset << std::endl;
|
||||
std::cout << "size: " << opts.offset << std::endl;
|
||||
std::cout << "count: " << opts.count << std::endl;
|
||||
std::cout << "in_file: " << opts.in_file << std::endl;
|
||||
std::cout << "no-color: " << opts.no_color << std::endl;
|
||||
std::cout << "stats: " << opts.dump_stats << std::endl;
|
||||
std::cout << "hex: " << opts.hex_string << std::endl;
|
||||
std::cout << "json: " << opts.json_output << std::endl;
|
||||
std::cout << "extended: " << opts.extended << std::endl;
|
||||
std::cout << "shemu:" << opts.shemu << std::endl;
|
||||
std::cout << "kernel:" << opts.kernel << std::endl;
|
||||
std::cout << "shctx:" << opts.shctx_file << std::endl;
|
||||
}
|
||||
|
||||
if (!_validate_and_fix_args(opts)) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!opts.interactive && !opts.comm) {
|
||||
if (!opts.hex_string.empty() || !opts.hex_file.empty()) {
|
||||
if (!_hexstring_to_bytes(opts))
|
||||
return 1;
|
||||
} else if (!opts.in_file.empty()) {
|
||||
if (!_file_to_bytes(opts))
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (opts.offset >= opts.actual_size)
|
||||
return 1;
|
||||
|
||||
if (!opts.shemu) {
|
||||
disassemble(opts);
|
||||
}
|
||||
else {
|
||||
_load_shctx(opts);
|
||||
shemu(opts);
|
||||
}
|
||||
|
||||
} else {
|
||||
while (true) {
|
||||
opts.hex_string.clear();
|
||||
|
||||
if (!opts.comm)
|
||||
std::cout << ">> ";
|
||||
|
||||
std::getline(std::cin, opts.hex_string);
|
||||
|
||||
if (opts.hex_string == "q"
|
||||
|| opts.hex_string == "quit"
|
||||
|| opts.hex_string == "exit"
|
||||
|| opts.hex_string.empty()) {
|
||||
|
||||
if (!opts.comm)
|
||||
std::cout << "Bye!" << std::endl;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
_hexstring_to_bytes(opts);
|
||||
|
||||
disassemble(opts);
|
||||
|
||||
std::cout.flush();
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -1,566 +0,0 @@
|
||||
/**
|
||||
* License: Apache 2.0 with LLVM Exception or GPL v3
|
||||
*
|
||||
* Author: Jesse Laning
|
||||
*/
|
||||
|
||||
#ifndef ARGPARSE_H
|
||||
#define ARGPARSE_H
|
||||
|
||||
#include <algorithm>
|
||||
#include <cctype>
|
||||
#include <cstring>
|
||||
#include <iomanip>
|
||||
#include <iostream>
|
||||
#include <locale>
|
||||
#include <map>
|
||||
#include <numeric>
|
||||
#include <sstream>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
namespace argparse {
|
||||
namespace detail {
|
||||
static inline bool _not_space(int ch) { return !std::isspace(ch); }
|
||||
static inline void _ltrim(std::string &s, bool (*f)(int) = _not_space) {
|
||||
s.erase(s.begin(), std::find_if(s.begin(), s.end(), f));
|
||||
}
|
||||
static inline void _rtrim(std::string &s, bool (*f)(int) = _not_space) {
|
||||
s.erase(std::find_if(s.rbegin(), s.rend(), f).base(), s.end());
|
||||
}
|
||||
static inline void _trim(std::string &s, bool (*f)(int) = _not_space) {
|
||||
_ltrim(s, f);
|
||||
_rtrim(s, f);
|
||||
}
|
||||
static inline std::string _ltrim_copy(std::string s,
|
||||
bool (*f)(int) = _not_space) {
|
||||
_ltrim(s, f);
|
||||
return s;
|
||||
}
|
||||
static inline std::string _rtrim_copy(std::string s,
|
||||
bool (*f)(int) = _not_space) {
|
||||
_rtrim(s, f);
|
||||
return s;
|
||||
}
|
||||
static inline std::string _trim_copy(std::string s,
|
||||
bool (*f)(int) = _not_space) {
|
||||
_trim(s, f);
|
||||
return s;
|
||||
}
|
||||
template <typename InputIt>
|
||||
static inline std::string _join(InputIt begin, InputIt end,
|
||||
const std::string &separator = " ") {
|
||||
std::ostringstream ss;
|
||||
if (begin != end) {
|
||||
ss << *begin++;
|
||||
}
|
||||
while (begin != end) {
|
||||
ss << separator;
|
||||
ss << *begin++;
|
||||
}
|
||||
return ss.str();
|
||||
}
|
||||
static inline bool _is_number(const std::string &arg) {
|
||||
std::istringstream iss(arg);
|
||||
float f;
|
||||
iss >> std::noskipws >> f;
|
||||
return iss.eof() && !iss.fail();
|
||||
}
|
||||
|
||||
static inline int _find_equal(const std::string &s) {
|
||||
for (size_t i = 0; i < s.length(); ++i) {
|
||||
// if find graph symbol before equal, end search
|
||||
// i.e. don't accept --asd)f=0 arguments
|
||||
// but allow --asd_f and --asd-f arguments
|
||||
if (std::ispunct(static_cast<int>(s[i]))) {
|
||||
if (s[i] == '=') {
|
||||
return static_cast<int>(i);
|
||||
} else if (s[i] == '_' || s[i] == '-') {
|
||||
continue;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static inline size_t _find_name_end(const std::string &s) {
|
||||
size_t i;
|
||||
for (i = 0; i < s.length(); ++i) {
|
||||
if (std::ispunct(static_cast<int>(s[i]))) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
namespace is_vector_impl {
|
||||
template <typename T>
|
||||
struct is_vector : std::false_type {};
|
||||
template <typename... Args>
|
||||
struct is_vector<std::vector<Args...>> : std::true_type {};
|
||||
} // namespace is_vector_impl
|
||||
|
||||
// type trait to utilize the implementation type traits as well as decay the
|
||||
// type
|
||||
template <typename T>
|
||||
struct is_vector {
|
||||
static constexpr bool const value =
|
||||
is_vector_impl::is_vector<typename std::decay<T>::type>::value;
|
||||
};
|
||||
} // namespace detail
|
||||
|
||||
class ArgumentParser {
|
||||
private:
|
||||
public:
|
||||
class Argument;
|
||||
|
||||
class Result {
|
||||
public:
|
||||
Result() {}
|
||||
Result(std::string err) noexcept : _error(true), _what(err) {}
|
||||
|
||||
operator bool() const { return _error; }
|
||||
|
||||
friend std::ostream &operator<<(std::ostream &os, const Result &dt);
|
||||
|
||||
const std::string &what() const { return _what; }
|
||||
|
||||
private:
|
||||
bool _error{false};
|
||||
std::string _what{};
|
||||
};
|
||||
|
||||
class Argument {
|
||||
public:
|
||||
enum Position : int { LAST = -1, DONT_CARE = -2 };
|
||||
enum Count : int { ANY = -1 };
|
||||
|
||||
Argument &name(const std::string &name) {
|
||||
_names.push_back(name);
|
||||
return *this;
|
||||
}
|
||||
|
||||
Argument &names(std::vector<std::string> names) {
|
||||
_names.insert(_names.end(), names.begin(), names.end());
|
||||
return *this;
|
||||
}
|
||||
|
||||
Argument &description(const std::string &description) {
|
||||
_desc = description;
|
||||
return *this;
|
||||
}
|
||||
|
||||
Argument &required(bool req) {
|
||||
_required = req;
|
||||
return *this;
|
||||
}
|
||||
|
||||
Argument &position(int position) {
|
||||
if (position != Position::LAST) {
|
||||
// position + 1 because technically argument zero is the name of the
|
||||
// executable
|
||||
_position = position + 1;
|
||||
} else {
|
||||
_position = position;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
Argument &count(int count) {
|
||||
_count = count;
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool found() const { return _found; }
|
||||
|
||||
template <typename T>
|
||||
typename std::enable_if<detail::is_vector<T>::value, T>::type get() {
|
||||
T t = T();
|
||||
typename T::value_type vt;
|
||||
for (auto &s : _values) {
|
||||
std::istringstream in(s);
|
||||
in >> vt;
|
||||
t.push_back(vt);
|
||||
}
|
||||
return t;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
typename std::enable_if<!detail::is_vector<T>::value, T>::type get() {
|
||||
std::istringstream in(get<std::string>());
|
||||
T t = T();
|
||||
in >> t >> std::ws;
|
||||
return t;
|
||||
}
|
||||
|
||||
private:
|
||||
Argument(const std::string &name, const std::string &desc,
|
||||
bool required = false)
|
||||
: _desc(desc), _required(required) {
|
||||
_names.push_back(name);
|
||||
}
|
||||
|
||||
Argument() {}
|
||||
|
||||
friend class ArgumentParser;
|
||||
int _position{Position::DONT_CARE};
|
||||
int _count{Count::ANY};
|
||||
std::vector<std::string> _names{};
|
||||
std::string _desc{};
|
||||
bool _found{false};
|
||||
bool _required{false};
|
||||
int _index{-1};
|
||||
|
||||
std::vector<std::string> _values{};
|
||||
};
|
||||
|
||||
ArgumentParser(const std::string &bin, const std::string &desc)
|
||||
: _bin(bin), _desc(desc) {}
|
||||
|
||||
Argument &add_argument() {
|
||||
_arguments.push_back({});
|
||||
_arguments.back()._index = static_cast<int>(_arguments.size()) - 1;
|
||||
return _arguments.back();
|
||||
}
|
||||
|
||||
Argument &add_argument(const std::string &name, const std::string &long_name,
|
||||
const std::string &desc, const bool required = false) {
|
||||
_arguments.push_back(Argument(name, desc, required));
|
||||
_arguments.back()._names.push_back(long_name);
|
||||
_arguments.back()._index = static_cast<int>(_arguments.size()) - 1;
|
||||
return _arguments.back();
|
||||
}
|
||||
|
||||
Argument &add_argument(const std::string &name, const std::string &desc,
|
||||
const bool required = false) {
|
||||
_arguments.push_back(Argument(name, desc, required));
|
||||
_arguments.back()._index = static_cast<int>(_arguments.size()) - 1;
|
||||
return _arguments.back();
|
||||
}
|
||||
|
||||
void print_help(size_t count = 0, size_t page = 0) {
|
||||
if (page * count > _arguments.size()) {
|
||||
return;
|
||||
}
|
||||
if (page == 0) {
|
||||
std::cout << "Usage: " << _bin;
|
||||
if (_positional_arguments.empty()) {
|
||||
std::cout << " [options...]" << std::endl;
|
||||
} else {
|
||||
int current = 1;
|
||||
for (auto &v : _positional_arguments) {
|
||||
if (v.first != Argument::Position::LAST) {
|
||||
for (; current < v.first; current++) {
|
||||
std::cout << " [" << current << "]";
|
||||
}
|
||||
std::cout
|
||||
<< " ["
|
||||
<< detail::_ltrim_copy(
|
||||
_arguments[static_cast<size_t>(v.second)]._names[0],
|
||||
[](int c) -> bool { return c != static_cast<int>('-'); })
|
||||
<< "]";
|
||||
}
|
||||
}
|
||||
auto it = _positional_arguments.find(Argument::Position::LAST);
|
||||
if (it == _positional_arguments.end()) {
|
||||
std::cout << " [options...]";
|
||||
} else {
|
||||
std::cout
|
||||
<< " [options...] ["
|
||||
<< detail::_ltrim_copy(
|
||||
_arguments[static_cast<size_t>(it->second)]._names[0],
|
||||
[](int c) -> bool { return c != static_cast<int>('-'); })
|
||||
<< "]";
|
||||
}
|
||||
std::cout << std::endl;
|
||||
}
|
||||
std::cout << "Options:" << std::endl;
|
||||
}
|
||||
if (count == 0) {
|
||||
page = 0;
|
||||
count = _arguments.size();
|
||||
}
|
||||
for (size_t i = page * count;
|
||||
i < std::min<size_t>(page * count + count, _arguments.size()); i++) {
|
||||
Argument &a = _arguments[i];
|
||||
std::string name = a._names[0];
|
||||
for (size_t n = 1; n < a._names.size(); ++n) {
|
||||
name.append(", " + a._names[n]);
|
||||
}
|
||||
std::cout << " " << std::setw(23) << std::left << name << std::setw(23)
|
||||
<< a._desc;
|
||||
if (a._required) {
|
||||
std::cout << " (Required)";
|
||||
}
|
||||
std::cout << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
Result parse(int argc, const char *argv[]) {
|
||||
Result err;
|
||||
if (argc > 1) {
|
||||
// build name map
|
||||
for (auto &a : _arguments) {
|
||||
for (auto &n : a._names) {
|
||||
std::string name = detail::_ltrim_copy(
|
||||
n, [](int c) -> bool { return c != static_cast<int>('-'); });
|
||||
if (_name_map.find(name) != _name_map.end()) {
|
||||
return Result("Duplicate of argument name: " + n);
|
||||
}
|
||||
_name_map[name] = a._index;
|
||||
}
|
||||
if (a._position >= 0 || a._position == Argument::Position::LAST) {
|
||||
_positional_arguments[a._position] = a._index;
|
||||
}
|
||||
}
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
|
||||
// parse
|
||||
std::string current_arg;
|
||||
size_t arg_len;
|
||||
for (int argv_index = 1; argv_index < argc; ++argv_index) {
|
||||
current_arg = std::string(argv[argv_index]);
|
||||
arg_len = current_arg.length();
|
||||
if (arg_len == 0) {
|
||||
continue;
|
||||
}
|
||||
if (_help_enabled && (current_arg == "-h" || current_arg == "--help")) {
|
||||
_arguments[static_cast<size_t>(_name_map["help"])]._found = true;
|
||||
} else if (argv_index == argc - 1 &&
|
||||
_positional_arguments.find(Argument::Position::LAST) !=
|
||||
_positional_arguments.end()) {
|
||||
err = _end_argument();
|
||||
Result b = err;
|
||||
err = _add_value(current_arg, Argument::Position::LAST);
|
||||
if (b) {
|
||||
return b;
|
||||
}
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
} else if (arg_len >= 2 &&
|
||||
!detail::_is_number(current_arg)) { // ignores the case if
|
||||
// the arg is just a -
|
||||
// look for -a (short) or --arg (long) args
|
||||
if (current_arg[0] == '-') {
|
||||
err = _end_argument();
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
// look for --arg (long) args
|
||||
if (current_arg[1] == '-') {
|
||||
err = _begin_argument(current_arg.substr(2), true, argv_index);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
} else { // short args
|
||||
err = _begin_argument(current_arg.substr(1), false, argv_index);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
}
|
||||
} else { // argument value
|
||||
err = _add_value(current_arg, argv_index);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
}
|
||||
} else { // argument value
|
||||
err = _add_value(current_arg, argv_index);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (_help_enabled && exists("help")) {
|
||||
return Result();
|
||||
}
|
||||
err = _end_argument();
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
for (auto &p : _positional_arguments) {
|
||||
Argument &a = _arguments[static_cast<size_t>(p.second)];
|
||||
if (a._values.size() > 0 && a._values[0][0] == '-') {
|
||||
std::string name = detail::_ltrim_copy(a._values[0], [](int c) -> bool {
|
||||
return c != static_cast<int>('-');
|
||||
});
|
||||
if (_name_map.find(name) != _name_map.end()) {
|
||||
if (a._position == Argument::Position::LAST) {
|
||||
return Result(
|
||||
"Poisitional argument expected at the end, but argument " +
|
||||
a._values[0] + " found instead");
|
||||
} else {
|
||||
return Result("Poisitional argument expected in position " +
|
||||
std::to_string(a._position) + ", but argument " +
|
||||
a._values[0] + " found instead");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
for (auto &a : _arguments) {
|
||||
if (a._required && !a._found) {
|
||||
return Result("Required argument not found: " + a._names[0]);
|
||||
}
|
||||
if (a._position >= 0 && argc >= a._position && !a._found) {
|
||||
return Result("Argument " + a._names[0] + " expected in position " +
|
||||
std::to_string(a._position));
|
||||
}
|
||||
}
|
||||
return Result();
|
||||
}
|
||||
|
||||
void enable_help() {
|
||||
add_argument("-h", "--help", "Shows this page", false);
|
||||
_help_enabled = true;
|
||||
}
|
||||
|
||||
bool exists(const std::string &name) const {
|
||||
std::string n = detail::_ltrim_copy(
|
||||
name, [](int c) -> bool { return c != static_cast<int>('-'); });
|
||||
auto it = _name_map.find(n);
|
||||
if (it != _name_map.end()) {
|
||||
return _arguments[static_cast<size_t>(it->second)]._found;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
T get(const std::string &name) {
|
||||
auto t = _name_map.find(name);
|
||||
if (t != _name_map.end()) {
|
||||
return _arguments[static_cast<size_t>(t->second)].get<T>();
|
||||
}
|
||||
return T();
|
||||
}
|
||||
|
||||
private:
|
||||
Result _begin_argument(const std::string &arg, bool longarg, int position) {
|
||||
auto it = _positional_arguments.find(position);
|
||||
if (it != _positional_arguments.end()) {
|
||||
Result err = _end_argument();
|
||||
Argument &a = _arguments[static_cast<size_t>(it->second)];
|
||||
a._values.push_back((longarg ? "--" : "-") + arg);
|
||||
a._found = true;
|
||||
return err;
|
||||
}
|
||||
if (_current != -1) {
|
||||
return Result("Current argument left open");
|
||||
}
|
||||
size_t name_end = detail::_find_name_end(arg);
|
||||
std::string arg_name = arg.substr(0, name_end);
|
||||
if (longarg) {
|
||||
int equal_pos = detail::_find_equal(arg);
|
||||
auto nmf = _name_map.find(arg_name);
|
||||
if (nmf == _name_map.end()) {
|
||||
return Result("Unrecognized command line option '" + arg_name + "'");
|
||||
}
|
||||
_current = nmf->second;
|
||||
_arguments[static_cast<size_t>(nmf->second)]._found = true;
|
||||
if (equal_pos == 0 ||
|
||||
(equal_pos < 0 &&
|
||||
arg_name.length() < arg.length())) { // malformed argument
|
||||
return Result("Malformed argument: " + arg);
|
||||
} else if (equal_pos > 0) {
|
||||
std::string arg_value = arg.substr(name_end + 1);
|
||||
_add_value(arg_value, position);
|
||||
}
|
||||
} else {
|
||||
Result r;
|
||||
if (arg_name.length() == 1) {
|
||||
return _begin_argument(arg, true, position);
|
||||
} else {
|
||||
for (char &c : arg_name) {
|
||||
r = _begin_argument(std::string(1, c), true, position);
|
||||
if (r) {
|
||||
return r;
|
||||
}
|
||||
r = _end_argument();
|
||||
if (r) {
|
||||
return r;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return Result();
|
||||
}
|
||||
|
||||
Result _add_value(const std::string &value, int location) {
|
||||
if (_current >= 0) {
|
||||
Result err;
|
||||
Argument &a = _arguments[static_cast<size_t>(_current)];
|
||||
if (a._count >= 0 && static_cast<int>(a._values.size()) >= a._count) {
|
||||
err = _end_argument();
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
goto unnamed;
|
||||
}
|
||||
a._values.push_back(value);
|
||||
if (a._count >= 0 && static_cast<int>(a._values.size()) >= a._count) {
|
||||
err = _end_argument();
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
}
|
||||
return Result();
|
||||
} else {
|
||||
unnamed:
|
||||
auto it = _positional_arguments.find(location);
|
||||
if (it != _positional_arguments.end()) {
|
||||
Argument &a = _arguments[static_cast<size_t>(it->second)];
|
||||
a._values.push_back(value);
|
||||
a._found = true;
|
||||
}
|
||||
// TODO
|
||||
return Result();
|
||||
}
|
||||
}
|
||||
|
||||
Result _end_argument() {
|
||||
if (_current >= 0) {
|
||||
Argument &a = _arguments[static_cast<size_t>(_current)];
|
||||
_current = -1;
|
||||
if (static_cast<int>(a._values.size()) < a._count) {
|
||||
return Result("Too few arguments given for " + a._names[0]);
|
||||
}
|
||||
if (a._count >= 0) {
|
||||
if (static_cast<int>(a._values.size()) > a._count) {
|
||||
return Result("Too many arguments given for " + a._names[0]);
|
||||
}
|
||||
}
|
||||
}
|
||||
return Result();
|
||||
}
|
||||
|
||||
bool _help_enabled{false};
|
||||
int _current{-1};
|
||||
std::string _bin{};
|
||||
std::string _desc{};
|
||||
std::vector<Argument> _arguments{};
|
||||
std::map<int, int> _positional_arguments{};
|
||||
std::map<std::string, int> _name_map{};
|
||||
};
|
||||
|
||||
std::ostream &operator<<(std::ostream &os, const ArgumentParser::Result &r) {
|
||||
os << r.what();
|
||||
return os;
|
||||
}
|
||||
template <>
|
||||
inline std::string ArgumentParser::Argument::get<std::string>() {
|
||||
return detail::_join(_values.begin(), _values.end());
|
||||
}
|
||||
template <>
|
||||
inline std::vector<std::string>
|
||||
ArgumentParser::Argument::get<std::vector<std::string>>() {
|
||||
return _values;
|
||||
}
|
||||
|
||||
} // namespace argparse
|
||||
#endif
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,16 @@
|
||||
/*
|
||||
* Copyright (c) 2020 Bitdefender
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#ifndef BDDISASM_VERSION_H
|
||||
#define BDDISASM_VERSION_H
|
||||
|
||||
#define DISASM_VERSION_MAJOR 2
|
||||
#define DISASM_VERSION_MINOR 1
|
||||
#define DISASM_VERSION_REVISION 0
|
||||
|
||||
#define SHEMU_VERSION_MAJOR DISASM_VERSION_MAJOR
|
||||
#define SHEMU_VERSION_MINOR DISASM_VERSION_MINOR
|
||||
#define SHEMU_VERSION_REVISION DISASM_VERSION_REVISION
|
||||
|
||||
#endif // BDDISASM_VERSION_H
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue