lifting-bits / microx Goto Github PK
View Code? Open in Web Editor NEWSafely execute an arbitrary x86 instruction
License: Apache License 2.0
Safely execute an arbitrary x86 instruction
License: Apache License 2.0
We should publish microx to PyPI. Building it as a redistributable wheel shouldn't be too difficult, as long as we link XED statically.
pdoc
works well for us on other projects, we should use it here.
These should be recorded as a dev
extra in setup.py
, instead of being hardcoded in random places.
...and check them with mypy
.
REP MOVSB was not working correctly for me. It seems the source and destination registers are not in the modified register set and do not get updated by WriteRegisters.
Something like this fixes the bug for me:
@@ -802,6 +802,7 @@ static void UpdateFlagsSub(Flags &flags, uintptr_t lhs, uintptr_t rhs,
WriteGPR(dest_reg, \
static_cast<uint64_t>(static_cast<int64_t>(ReadGPR(dest_reg)) + \
stringop_inc)); \
+ gModifiedRegs.set(dest_reg); \
} while (false)
#define SCAS \
@@ -813,6 +814,7 @@ static void UpdateFlagsSub(Flags &flags, uintptr_t lhs, uintptr_t rhs,
WriteGPR(dest_reg, \
static_cast<uint64_t>(static_cast<int64_t>(ReadGPR(dest_reg)) + \
stringop_inc)); \
+ gModifiedRegs.set(dest_reg); \
} while (false)
#define LODS \
@@ -821,6 +823,7 @@ static void UpdateFlagsSub(Flags &flags, uintptr_t lhs, uintptr_t rhs,
WriteGPR(dest_reg, \
static_cast<uint64_t>(static_cast<int64_t>(ReadGPR(dest_reg)) + \
stringop_inc)); \
+ gModifiedRegs.set(dest_reg); \
} while (false)
#define MOVS \
@@ -832,6 +835,8 @@ static void UpdateFlagsSub(Flags &flags, uintptr_t lhs, uintptr_t rhs,
WriteGPR(dest_reg, \
static_cast<uint64_t>(static_cast<int64_t>(ReadGPR(dest_reg)) + \
stringop_inc)); \
+ gModifiedRegs.set(src_reg); \
+ gModifiedRegs.set(dest_reg); \
} while (false)
#define CMPS \
@@ -845,6 +850,8 @@ static void UpdateFlagsSub(Flags &flags, uintptr_t lhs, uintptr_t rhs,
WriteGPR(dest_reg, \
static_cast<uint64_t>(static_cast<int64_t>(ReadGPR(dest_reg)) + \
stringop_inc)); \
+ gModifiedRegs.set(src_reg); \
+ gModifiedRegs.set(dest_reg); \
} while (false)
#define REPNE(...) \
We should build both microx and its Python bindings in the CI.
I don't recall if we're actually saving/restoring enough. I think we're only saving xmm0 through xmm7. I'd need to think more about whether more is needed. I don't believe that we rewrite things like raw uses of xmm8
(in avx2) to be in that range, for instance.
Setting the memory map address bit size to 64 is not sufficient to run X64 code. It will constantly loop over one instruction because when microx updates the program counter it updates EIP instead of RIP.
pop rsp
currently returns result increased by 8
opposed to expected value. One possible explanation is that following happens:
new = *rsp
store(dst, new)
*rsp = *rsp + 8
instead of
new = *rsp
*rsp = *rsp + 8
store(dst, new)
For example BTS
does not work with greater immediates.
All of our PyPI-packaged projects should use trusted publishing, rather than a manually configured API token.
Example trusted publishing workflow:
https://github.com/trailofbits/blight/blob/master/.github/workflows/release.yml
Resources:
Thanks for the really cool project!
I am wondering if this is a related implementation of "Micro Execution" (https://patricegodefroid.github.io/public_psfiles/icse2014.pdf), which is not open-sourced?
Thanks.
While these are categorized as "system" instructions, they are also popular within userspace applications. While it is unlikely that microx can provide a "correct" implementation, it can at least provide a way for the user to provide an implementation.
Something like:
@@ -1347,6 +1421,18 @@ static bool Emulate(const Executor *executor, uintptr_t &next_pc,
WriteGPR(reg0, mem0);
return true;
+ case XED_IFORM_RDTSC:
+ case XED_IFORM_RDTSCP: {
+ Data tsc;
+ if (!executor->ReadTsc(tsc)) {
+ status = ExecutorStatus::kErrorReadTsc;
+ return false;
+ }
+ WriteGPR(reg0, *reinterpret_cast<uint32_t *>(&tsc.bytes[0]));
+ WriteGPR(reg1, *reinterpret_cast<uint32_t *>(&tsc.bytes[4]));
+ }
+ return true;
+
default:
return false;
}
@@ -1382,6 +1468,14 @@ static bool UsesUnsupportedAttributes(void) {
static bool UsesUnsupportedFeatures(const Executor *executor) {
switch (xed_decoded_inst_get_category(gXedd)) {
+ case XED_CATEGORY_SYSTEM:
+ switch (xed_decoded_inst_get_iform_enum(gXedd)) {
+ case XED_IFORM_RDTSC:
+ case XED_IFORM_RDTSCP:
+ return false;
+ default:
+ return true;
+ }
case XED_CATEGORY_3DNOW:
case XED_CATEGORY_MPX:
case XED_CATEGORY_AES:
DF
is not having a correct value after executing some instruction. Best seen with popf
and can crash program in other cases (by possibly not restoring properly?)
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.