Skip to content

Commit

Permalink
label8 and replace some skip pointers with small variants
Browse files Browse the repository at this point in the history
  • Loading branch information
altalk23 committed Jan 19, 2025
1 parent 6346f7b commit 3220bf5
Show file tree
Hide file tree
Showing 7 changed files with 45 additions and 13 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ jobs:

- name: 'macOS'
id: mac
os: macos-12
os: macos-13
build_tests: true
extra_flags: "-DCMAKE_BUILD_TYPE=Debug"
out_paths: './build/src/libTulipHook.a'
Expand Down
1 change: 1 addition & 0 deletions src/Handler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

#include <algorithm>
#include <stack>
#include <iostream>

using namespace tulip::hook;

Expand Down
3 changes: 2 additions & 1 deletion src/assembler/X64Assembler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,8 @@ X64Assembler::~X64Assembler() {}

void X64Assembler::updateLabels() {
for (auto const& update : m_labelUpdates) {
this->rewrite32(update.m_address, m_labels[update.m_name] - update.m_address - 4);
if (update.m_size == 4) this->rewrite32(update.m_address, m_labels[update.m_name] - update.m_address - 4);
else if (update.m_size == 1) this->rewrite8(update.m_address, m_labels[update.m_name] - update.m_address - 1);
}
// absolute is not absolute in 64 bit
for (auto const& update : m_absoluteLabelUpdates) {
Expand Down
27 changes: 22 additions & 5 deletions src/assembler/X86Assembler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,11 @@ X86Assembler::X86Assembler(int64_t baseAddress) :

X86Assembler::~X86Assembler() {}

void X86Assembler::label8(std::string const& name) {
m_labelUpdates.push_back({this->currentAddress(), name, 1});
this->write8(0);
}

void X86Assembler::label32(std::string const& name) {
m_labelUpdates.push_back({this->currentAddress(), name, 4});
this->write32(0);
Expand All @@ -27,7 +32,8 @@ void X86Assembler::abslabel32(std::string const& name) {

void X86Assembler::updateLabels() {
for (auto const& update : m_labelUpdates) {
this->rewrite32(update.m_address, m_labels[update.m_name] - update.m_address - 4);
if (update.m_size == 4) this->rewrite32(update.m_address, m_labels[update.m_name] - update.m_address - 4);
else if (update.m_size == 1) this->rewrite8(update.m_address, m_labels[update.m_name] - update.m_address - 1);
}
for (auto const& update : m_absoluteLabelUpdates) {
this->rewrite32(update.m_address, m_labels[update.m_name]);
Expand Down Expand Up @@ -127,17 +133,28 @@ void X86Assembler::jmp(X86Register reg) {
}

void X86Assembler::jmp(int64_t address) {
this->write8(0xE9);
// typical formula is target - addr - 5,
// but add + 1 because we just wrote one byte
this->write32(address - this->currentAddress() - 5 + 1);
auto const difference = address - this->currentAddress();
if (difference - 2 >= -0x80 && difference - 2 <= 0x7f) {
this->write8(0xEB);
this->write8(difference - 2);
}
else {
// typical formula is target - addr - 5,
this->write8(0xE9);
this->write32(difference - 5);
}
}

void X86Assembler::jmp(std::string const& label) {
this->write8(0xE9);
this->label32(label);
}

void X86Assembler::jmp8(std::string const& label) {
this->write8(0xEB);
this->label8(label);
}

void X86Assembler::call(int64_t address) {
this->write8(0xE8);
// typical formula is target - addr - 5,
Expand Down
2 changes: 2 additions & 0 deletions src/assembler/X86Assembler.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ namespace tulip::hook {
X86Assembler(X86Assembler&&) = delete;
~X86Assembler();

void label8(std::string const& name);
void label32(std::string const& name);
void abslabel32(std::string const& name);
void updateLabels() override;
Expand All @@ -96,6 +97,7 @@ namespace tulip::hook {
void jmp(X86Register reg);
void jmp(int64_t address);
void jmp(std::string const& label);
void jmp8(std::string const& label);

void call(X86Register reg);
void call(int64_t value);
Expand Down
11 changes: 6 additions & 5 deletions src/generator/X64Generator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -360,7 +360,7 @@ geode::Result<> X64HandlerGenerator::relocateRIPInstruction(cs_insn* insn, uint8
}
else if (id == X86_INS_CALL && operand0.type == X86_OP_MEM) {
a.callip("absolute-pointer");
a.jmp("skip-pointer");
a.jmp8("skip-pointer");

a.label("absolute-pointer");
// it's bad but umm better than the alternative of double indirection
Expand Down Expand Up @@ -390,7 +390,7 @@ geode::Result<> X64HandlerGenerator::relocateRIPInstruction(cs_insn* insn, uint8
if (shouldPush) {
a.pop(RAX);
}
a.jmp("skip-pointer");
a.jmp8("skip-pointer");

a.label("absolute-pointer");
a.write64(absolute);
Expand Down Expand Up @@ -596,9 +596,10 @@ geode::Result<HandlerGenerator::TrampolineReturn> X64HandlerGenerator::generateT
}
else {
a.jmpip("handler");

a.jmp8("skip-pointer");
a.label("handler");
a.write64(reinterpret_cast<uint64_t>(m_address) + code.m_originalOffset);
a.label("skip-pointer");
}

a.updateLabels();
Expand Down Expand Up @@ -697,7 +698,7 @@ geode::Result<> X64HandlerGenerator::relocateBranchInstruction(cs_insn* insn, ui
using enum X64Register;

a.callip("absolute-pointer");
a.jmp("skip-pointer");
a.jmp8("skip-pointer");

a.label("absolute-pointer");
a.write64(targetAddress);
Expand Down Expand Up @@ -743,7 +744,7 @@ geode::Result<> X64HandlerGenerator::relocateBranchInstruction(cs_insn* insn, ui
}
a.label32("jmp-on-branch");

a.jmp("skip-branch");
a.jmp8("skip-branch");

a.label("jmp-on-branch");

Expand Down
12 changes: 11 additions & 1 deletion test/Assembler64.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,17 @@ TEST(X64AssemblerTest, Jmp) {
a.jmp(0xb00b5);
a.jmp(RCX);
a.jmp(R8);
EXPECT_EQ(a.buffer(), "\xE9\x8D\xFF\x0A\x00\xFF\xE1\x41\xFF\xE0"_bytes);
a.jmp(0x123);
EXPECT_EQ(a.buffer(), "\xE9\x8D\xFF\x0A\x00\xFF\xE1\x41\xFF\xE0\xEB\xF4"_bytes);
}

TEST(X64AssemblerTest, Jmp8) {
X64Assembler a(0x123);
a.jmp8("label");
a.write32(0x80085);
a.label("label");
a.updateLabels();
EXPECT_EQ(a.buffer(), "\xEB\x04\x85\x00\x08\x00"_bytes);
}

TEST(X64AssemblerTest, Call) {
Expand Down

0 comments on commit 3220bf5

Please sign in to comment.