-
Notifications
You must be signed in to change notification settings - Fork 6
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Implemented very cool assemblers, dunno if they work
- Loading branch information
Showing
7 changed files
with
541 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
#include "BaseAssembler.hpp" | ||
|
||
using namespace tulip::hook; | ||
|
||
BaseAssembler::BaseAssembler(uint64_t baseAddress) : | ||
m_baseAddress(baseAddress) {} | ||
|
||
BaseAssembler::~BaseAssembler() {} | ||
|
||
void BaseAssembler::write8(uint8_t value) { | ||
m_buffer.push_back(value); | ||
} | ||
|
||
void BaseAssembler::write16(uint16_t value) { | ||
write8(value & 0xFF); | ||
write8((value >> 8) & 0xFF); | ||
} | ||
|
||
void BaseAssembler::write32(uint32_t value) { | ||
write16(value & 0xFFFF); | ||
write16((value >> 16) & 0xFFFF); | ||
} | ||
|
||
void BaseAssembler::write64(uint64_t value) { | ||
write32(value & 0xFFFFFFFF); | ||
write32((value >> 32) & 0xFFFFFFFF); | ||
} | ||
|
||
uint64_t BaseAssembler::currentAddress() const { | ||
return m_baseAddress + m_buffer.size(); | ||
} | ||
|
||
void BaseAssembler::rewrite8(uint64_t address, uint8_t value) { | ||
m_buffer[address - m_baseAddress] = value; | ||
} | ||
|
||
void BaseAssembler::rewrite16(uint64_t address, uint16_t value) { | ||
rewrite8(address, value & 0xFF); | ||
rewrite8(address + 1, (value >> 8) & 0xFF); | ||
} | ||
|
||
void BaseAssembler::rewrite32(uint64_t address, uint32_t value) { | ||
rewrite16(address, value & 0xFFFF); | ||
rewrite16(address + 2, (value >> 16) & 0xFFFF); | ||
} | ||
|
||
void BaseAssembler::rewrite64(uint64_t address, uint64_t value) { | ||
rewrite32(address, value & 0xFFFFFFFF); | ||
rewrite32(address + 4, (value >> 32) & 0xFFFFFFFF); | ||
} | ||
|
||
void BaseAssembler::label(std::string const& name) { | ||
m_labels[name] = this->currentAddress(); | ||
} | ||
|
||
void BaseAssembler::updateLabels() {} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
#pragma once | ||
|
||
#include <stdint.h> | ||
#include <string> | ||
#include <unordered_map> | ||
#include <vector> | ||
|
||
namespace tulip::hook { | ||
|
||
struct AssemblerLabelUpdates { | ||
uint64_t m_address; | ||
std::string m_name; | ||
uint8_t m_size; | ||
}; | ||
|
||
class BaseAssembler { | ||
public: | ||
uint64_t m_baseAddress; | ||
std::vector<uint8_t> m_buffer; | ||
std::unordered_map<std::string, uint64_t> m_labels; | ||
std::vector<AssemblerLabelUpdates> m_labelUpdates; | ||
|
||
BaseAssembler(uint64_t baseAddress); | ||
BaseAssembler(BaseAssembler const&) = delete; | ||
BaseAssembler(BaseAssembler&&) = delete; | ||
~BaseAssembler(); | ||
|
||
uint64_t currentAddress() const; | ||
|
||
void write8(uint8_t value); | ||
void write16(uint16_t value); | ||
void write32(uint32_t value); | ||
void write64(uint64_t value); | ||
|
||
void rewrite8(uint64_t address, uint8_t value); | ||
void rewrite16(uint64_t address, uint16_t value); | ||
void rewrite32(uint64_t address, uint32_t value); | ||
void rewrite64(uint64_t address, uint64_t value); | ||
|
||
void label(std::string const& name); | ||
|
||
virtual void updateLabels(); | ||
}; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,163 @@ | ||
#include "X64Assembler.hpp" | ||
|
||
using namespace tulip::hook; | ||
|
||
uint8_t regv(X64Register reg) { | ||
return static_cast<uint8_t>(reg); | ||
} | ||
|
||
uint8_t regv(X64Pointer ptr) { | ||
return regv(ptr.m_register); | ||
} | ||
|
||
uint8_t regl(X64Register reg) { | ||
return regv(reg) & 0x7; | ||
} | ||
|
||
uint8_t regl(X64Pointer ptr) { | ||
return regv(ptr) & 0x7; | ||
} | ||
|
||
uint8_t regx(X64Register reg) { | ||
return regv(reg) - 0x80; | ||
} | ||
|
||
bool espcheck(X64Pointer ptr) { | ||
return regl(ptr) == 0x4; | ||
} | ||
|
||
bool lowerreg(X64Register reg) { | ||
return regv(reg) < 0x8; | ||
} | ||
|
||
bool lowerreg(X64Pointer ptr) { | ||
return regv(ptr) < 0x8; | ||
} | ||
|
||
uint8_t lowerv(X64Register reg, uint8_t offset) { | ||
return lowerreg(reg) << offset; | ||
} | ||
|
||
uint8_t lowerv(X64Pointer ptr, uint8_t offset) { | ||
return lowerreg(ptr) << offset; | ||
} | ||
|
||
X64Assembler::X64Assembler(uint64_t baseAddress) : | ||
BaseAssembler(baseAddress) {} | ||
|
||
X64Assembler::~X64Assembler() {} | ||
|
||
void X64Assembler::label32(std::string const& name) { | ||
m_labelUpdates.push_back({this->currentAddress(), name, 4}); | ||
this->write32(0); | ||
} | ||
|
||
void X64Assembler::updateLabels() { | ||
for (auto const& update : m_labelUpdates) { | ||
this->rewrite32(update.m_address, m_labels[update.m_name] - update.m_address - 4); | ||
} | ||
} | ||
|
||
void X64Assembler::nop() { | ||
this->write8(0x90); | ||
} | ||
|
||
void X64Assembler::add(X64Register reg, uint32_t value) { | ||
this->write8(0x48 | lowerv(reg, 0)); | ||
this->write8(0x81); | ||
this->write8(0xC0 | regl(reg)); | ||
this->write32(value); | ||
} | ||
|
||
void X64Assembler::sub(X64Register reg, uint32_t value) { | ||
this->write8(0x48 | lowerv(reg, 0)); | ||
this->write8(0x81); | ||
this->write8(0xE8 | regl(reg)); | ||
this->write32(value); | ||
} | ||
|
||
void X64Assembler::jmp(X64Register reg) { | ||
this->write8(0x40 | lowerv(reg, 0)); | ||
this->write8(0xFF); | ||
this->write8(0xE0 | regl(reg)); | ||
} | ||
|
||
void X64Assembler::jmp(uint64_t address) { | ||
this->write8(0xE9); | ||
this->write32(address - this->currentAddress() - 4); | ||
} | ||
|
||
void X64Assembler::call(X64Register reg) { | ||
this->write8(0x40 | lowerv(reg, 0)); | ||
this->write8(0xFF); | ||
this->write8(0xD0 | regl(reg)); | ||
} | ||
|
||
void X64Assembler::lea(X64Register reg, std::string const& label) { | ||
this->write8(0x48 | lowerv(reg, 2)); | ||
this->write8(0x8D); | ||
this->write8(0x05 | regl(reg) * 8); | ||
this->label32(label); | ||
} | ||
|
||
void X64Assembler::movaps(X64Register reg, X64Pointer ptr) { | ||
this->write8(0x40 | lowerv(ptr, 0)); | ||
this->write8(0x0F); | ||
this->write8(0x28); | ||
this->write8(0x80 | regl(ptr) | regx(reg) * 8); | ||
if (espcheck(ptr)) { | ||
this->write8(0x24); | ||
} | ||
this->write32(ptr.m_offset); | ||
} | ||
|
||
void X64Assembler::movaps(X64Pointer ptr, X64Register reg) { | ||
this->write8(0x40 | lowerv(ptr, 0)); | ||
this->write8(0x0F); | ||
this->write8(0x29); | ||
this->write8(0x80 | regl(ptr) | regx(reg) * 8); | ||
if (espcheck(ptr)) { | ||
this->write8(0x24); | ||
} | ||
this->write32(ptr.m_offset); | ||
} | ||
|
||
void X64Assembler::mov(X64Register reg, uint32_t value) { | ||
this->write8(0x48 | lowerv(reg, 0)); | ||
this->write8(0xC7); | ||
this->write8(0xC0 | regl(reg)); | ||
this->write32(value); | ||
} | ||
|
||
void X64Assembler::mov(X64Register reg, X64Pointer ptr) { | ||
this->write8(0x48 | lowerv(ptr, 0) | lowerv(reg, 2)); | ||
this->write8(0x8B); | ||
this->write8(0x80 | regl(ptr) | regl(reg) * 8); | ||
if (espcheck(ptr)) { | ||
this->write8(0x24); | ||
} | ||
this->write32(ptr.m_offset); | ||
} | ||
|
||
void X64Assembler::mov(X64Pointer ptr, X64Register reg) { | ||
this->write8(0x48 | lowerv(ptr, 0) | lowerv(reg, 2)); | ||
this->write8(0x89); | ||
this->write8(0x80 | regl(ptr) | regl(reg) * 8); | ||
if (espcheck(ptr)) { | ||
this->write8(0x24); | ||
} | ||
this->write32(ptr.m_offset); | ||
} | ||
|
||
void X64Assembler::mov(X64Register reg, X64Register reg2) { | ||
this->write8(0x48 | lowerv(reg, 0) | lowerv(reg2, 2)); | ||
this->write8(0x89); | ||
this->write8(0xC0 | regl(reg) | regl(reg2) * 8); | ||
} | ||
|
||
void X64Assembler::mov(X64Register reg, std::string const& label) { | ||
this->write8(0x48 | lowerv(reg, 2)); | ||
this->write8(0x8B); | ||
this->write8(0x05 | regl(reg) * 8); | ||
this->label32(label); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
#pragma once | ||
|
||
#include "BaseAssembler.hpp" | ||
|
||
namespace tulip::hook { | ||
|
||
enum class X64Register : uint8_t { | ||
RAX = 0x0, | ||
RCX, | ||
RDX, | ||
RBX, | ||
RSP, | ||
RBP, | ||
RSI, | ||
RDI, | ||
R8, | ||
R9, | ||
R10, | ||
R11, | ||
R12, | ||
R13, | ||
R14, | ||
R15, | ||
RIP = 0x40, | ||
XMM0 = 0x80, | ||
XMM1, | ||
XMM2, | ||
XMM3, | ||
XMM4, | ||
XMM5, | ||
XMM6, | ||
XMM7 | ||
}; | ||
|
||
struct X64Pointer { | ||
X64Register m_register; | ||
int32_t m_offset = 0; | ||
}; | ||
|
||
class X64Assembler : public BaseAssembler { | ||
public: | ||
X64Assembler(uint64_t baseAddress); | ||
X64Assembler(X64Assembler const&) = delete; | ||
X64Assembler(X64Assembler&&) = delete; | ||
~X64Assembler(); | ||
|
||
void label32(std::string const& name); | ||
void updateLabels() override; | ||
|
||
void nop(); | ||
|
||
void add(X64Register reg, uint32_t value); | ||
void sub(X64Register reg, uint32_t value); | ||
|
||
void jmp(X64Register reg); | ||
void jmp(uint64_t address); | ||
|
||
void call(X64Register reg); | ||
|
||
void lea(X64Register reg, std::string const& label); | ||
|
||
void movaps(X64Register reg, X64Pointer ptr); | ||
void movaps(X64Pointer ptr, X64Register reg); | ||
|
||
void mov(X64Register reg, uint32_t value); | ||
void mov(X64Register reg, X64Pointer ptr); | ||
void mov(X64Pointer ptr, X64Register reg); | ||
void mov(X64Register reg, X64Register reg2); | ||
void mov(X64Register reg, std::string const& label); | ||
}; | ||
} |
Oops, something went wrong.