summaryrefslogtreecommitdiff
path: root/src/windows/preamble_patcher.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/windows/preamble_patcher.cc')
-rw-r--r--src/windows/preamble_patcher.cc36
1 files changed, 36 insertions, 0 deletions
diff --git a/src/windows/preamble_patcher.cc b/src/windows/preamble_patcher.cc
index b27a95b..4163691 100644
--- a/src/windows/preamble_patcher.cc
+++ b/src/windows/preamble_patcher.cc
@@ -535,6 +535,12 @@ bool PreamblePatcher::IsShortConditionalJump(
return (*(target) & 0x70) == 0x70 && instruction_size == 2;
}
+bool PreamblePatcher::IsShortJump(
+ unsigned char* target,
+ unsigned int instruction_size) {
+ return target[0] == 0xeb && instruction_size == 2;
+}
+
bool PreamblePatcher::IsNearConditionalJump(
unsigned char* target,
unsigned int instruction_size) {
@@ -600,6 +606,36 @@ SideStepError PreamblePatcher::PatchShortConditionalJump(
return SIDESTEP_SUCCESS;
}
+SideStepError PreamblePatcher::PatchShortJump(
+ unsigned char* source,
+ unsigned int instruction_size,
+ unsigned char* target,
+ unsigned int* target_bytes,
+ unsigned int target_size) {
+ // note: rel8 offset is _signed_. Thus we need signed char here.
+ unsigned char* original_jump_dest = (source + 2) + static_cast<signed char>(source[1]);
+ unsigned char* stub_jump_from = target + 5;
+ __int64 fixup_jump_offset = original_jump_dest - stub_jump_from;
+ if (fixup_jump_offset > INT_MAX || fixup_jump_offset < INT_MIN) {
+ SIDESTEP_ASSERT(false &&
+ "Unable to fix up short jump because target"
+ " is too far away.");
+ return SIDESTEP_JUMP_INSTRUCTION;
+ }
+
+ *target_bytes = 5;
+ if (target_size > *target_bytes) {
+ // Convert the short jump to a near jump.
+ //
+ // e9 xx xx xx xx = jmp rel32off
+ target[0] = 0xe9;
+ memcpy(reinterpret_cast<void*>(target + 1),
+ reinterpret_cast<void*>(&fixup_jump_offset), 4);
+ }
+
+ return SIDESTEP_SUCCESS;
+}
+
SideStepError PreamblePatcher::PatchNearJumpOrCall(
unsigned char* source,
unsigned int instruction_size,