Commit 422f080b authored by swift_gan's avatar swift_gan Committed by swift_gan

[NativeHook]fix inst relocation when target address in move range

parent 60f5426c
......@@ -162,8 +162,12 @@ void AssemblerA64::Ldr(RegisterA64 &rt, const MemOperand &memOperand) {
}
}
void AssemblerA64::Ldr(RegisterA64 &rt, Label &label) {
Emit(reinterpret_cast<Unit<Base> *>(new INST_A64(LDR_LIT)(rt.isX() ? INST_A64(LDR_LIT)::LDR_X : INST_A64(LDR_LIT)::LDR_W, rt, label)));
void AssemblerA64::Ldr(RegisterA64 &rt, Label* label) {
Emit(reinterpret_cast<Unit<Base> *>(new INST_A64(LDR_LIT)(rt.isX() ? INST_A64(LDR_LIT)::LDR_X : INST_A64(LDR_LIT)::LDR_W, rt, *label)));
}
void AssemblerA64::Ldrsw(RegisterA64 &rt, Label* label) {
Emit(reinterpret_cast<Unit<Base> *>(new INST_A64(LDR_LIT)(INST_A64(LDR_LIT)::LDR_SW, rt, *label)));
}
void AssemblerA64::Ldrsw(XRegister &rt, const MemOperand& memOperand) {
......
......@@ -63,8 +63,9 @@ namespace SandHook {
void Str(RegisterA64& rt, const MemOperand& memOperand);
void Ldr(RegisterA64& rt, const MemOperand& memOperand);
void Ldr(RegisterA64& rt, Label& label);
void Ldr(RegisterA64& rt, Label* label);
void Ldrsw(RegisterA64 &rt, Label* label);
void Ldrsw(XRegister& rt, const MemOperand& memOperand);
void Pop(RegisterA64& rt);
......
......@@ -318,19 +318,20 @@ void A64_LDR_LIT::onOffsetApply(Off offset) {
}
void A64_LDR_LIT::decode(STRUCT_A64(LDR_LIT) *inst) {
op = OP(inst->op);
DECODE_OP;
offset = getImmPCOffset();
ENCODE_OFFSET(19, 2);
if (op == LDR_W) {
DECODE_RT(WReg);
} else {
DECODE_RT(XReg);
}
offset = getImmPCOffset();
}
void A64_LDR_LIT::assembler() {
SET_OPCODE(LDR_LIT);
get()->rt = rt->getCode();
get()->op = op;
ENCODE_OP;
ENCODE_RT;
ENCODE_OFFSET(19, 2);
}
......@@ -702,7 +703,7 @@ void A64_LDR_UIMM::assembler() {
valid = false;
return;
}
get()->imm12 = operand.offset >> get()->size;
get()->imm12 = static_cast<InstA64>(operand.offset >> get()->size);
}
......
......@@ -4,9 +4,11 @@
#include "code_relocate_a64.h"
#include "decoder_arm64.h"
#include "lock.h"
using namespace SandHook::RegistersA64;
using namespace SandHook::AsmA64;
using namespace SandHook::Utils;
#define __ assemblerA64->
......@@ -21,7 +23,17 @@ CodeRelocateA64::CodeRelocateA64(AssemblerA64 &assembler) : CodeRelocate(assembl
this->assemblerA64 = &assembler;
}
bool CodeRelocateA64::visit(Unit<Base> *unit, void *pc) {
relocate(reinterpret_cast<Instruction<Base> *>(unit), assemblerA64->getPC());
curOffset += unit->size();
return true;
}
void* CodeRelocateA64::relocate(void *startPc, Addr len, void *toPc = nullptr) throw(ErrorCodeException) {
AutoLock autoLock(relocateLock);
startAddr = reinterpret_cast<Addr>(startPc);
length = len;
curOffset = 0;
assemblerA64->allocBufferFirst(static_cast<U32>(len * 8));
void* curPc = assemblerA64->getPC();
Arm64Decoder decoder = Arm64Decoder();
......@@ -35,6 +47,10 @@ void* CodeRelocateA64::relocate(void *startPc, Addr len, void *toPc = nullptr) t
void* CodeRelocateA64::relocate(Instruction<Base> *instruction, void *toPc) throw(ErrorCodeException) {
void* curPc = assemblerA64->getPC();
//insert later bind labels
__ Emit(getLaterBindLabel(curOffset));
if (!instruction->pcRelate()) {
__ Emit(instruction);
return curPc;
......@@ -52,8 +68,38 @@ void* CodeRelocateA64::relocate(Instruction<Base> *instruction, void *toPc) thro
return curPc;
}
//in range of copy
bool CodeRelocateA64::inRelocateRange(Off targetOffset, Addr targetLen) {
Off startP = curOffset + targetOffset;
Off endP = startP + targetLen;
return startP >= 0 && endP <= length;
}
Label *CodeRelocateA64::getLaterBindLabel(Addr offset) {
Label* label_per_unit = nullptr;
std::map<Addr,Label*>::iterator it = laterBindlabels->find(offset);
if (it != laterBindlabels->end()) {
label_per_unit = it->second;
}
if (label_per_unit == nullptr) {
label_per_unit = new Label();
laterBindlabels->insert(std::map<Addr, Label*>::value_type(offset, label_per_unit));
}
return label_per_unit;
}
IMPL_RELOCATE(B_BL) {
Addr targetAddr = inst->getImmPCOffsetTarget();
if (inRelocateRange(inst->offset, sizeof(InstA64))) {
if (inst->op == inst->BL) {
__ Bl(getLaterBindLabel(inst->offset + curOffset));
} else {
__ B(getLaterBindLabel(inst->offset + curOffset));
}
return;
}
if (inst->op == inst->BL) {
__ Mov(LR, (Addr)inst->getPC() + inst->size());
}
......@@ -62,9 +108,13 @@ IMPL_RELOCATE(B_BL) {
}
IMPL_RELOCATE(B_COND) {
Addr targetAddr = inst->getImmPCOffsetTarget();
if (inRelocateRange(inst->offset, sizeof(InstA64))) {
__ B(inst->condition, getLaterBindLabel(inst->offset + curOffset));
return;
}
Label *true_label = new Label();
Label *false_label = new Label();
......@@ -82,6 +132,15 @@ IMPL_RELOCATE(TBZ_TBNZ) {
Addr targetAddr = inst->getImmPCOffsetTarget();
if (inRelocateRange(inst->offset, sizeof(InstA64))) {
if (inst->op == INST_A64(TBZ_TBNZ)::TBNZ) {
__ Tbnz(*inst->rt, inst->bit, getLaterBindLabel(inst->offset + curOffset));
} else {
__ Tbz(*inst->rt, inst->bit, getLaterBindLabel(inst->offset + curOffset));
}
return;
}
Label *true_label = new Label();
Label *false_label = new Label();
......@@ -102,6 +161,15 @@ IMPL_RELOCATE(TBZ_TBNZ) {
IMPL_RELOCATE(CBZ_CBNZ) {
Addr targetAddr = inst->getImmPCOffsetTarget();
if (inRelocateRange(inst->offset, sizeof(InstA64))) {
if (inst->op == INST_A64(CBZ_CBNZ)::CBNZ) {
__ Cbnz(*inst->rt, getLaterBindLabel(inst->offset + curOffset));
} else {
__ Cbz(*inst->rt, getLaterBindLabel(inst->offset + curOffset));
}
return;
}
Label *true_label = new Label();
Label *false_label = new Label();
......@@ -124,16 +192,40 @@ IMPL_RELOCATE(LDR_LIT) {
Addr targetAddr = inst->getImmPCOffsetTarget();
XRegister* rtX = XReg(inst->rt->getCode());
WRegister* rtW = WReg(inst->rt->getCode());
if (inRelocateRange(inst->offset, sizeof(Addr))) {
switch (inst->op) {
case INST_A64(LDR_LIT)::LDR_X:
__ Ldr(*rtX, getLaterBindLabel(inst->offset + curOffset));
break;
case INST_A64(LDR_LIT)::LDR_W:
__ Ldr(*rtW, getLaterBindLabel(inst->offset + curOffset));
break;
case INST_A64(LDR_LIT)::LDR_SW:
__ Ldrsw(*rtX, getLaterBindLabel(inst->offset + curOffset));
break;
case INST_A64(LDR_LIT)::LDR_PRFM:
__ Push(X0);
__ Mov(X0, targetAddr);
__ Ldrsw(X0, MemOperand(rtX, 0, Offset));
__ Pop(X0);
break;
}
return;
}
switch (inst->op) {
case INST_A64(LDR_LIT)::LDR_X:
__ Mov(*rtX, targetAddr);
__ Ldr(*rtW, MemOperand(rtX, 0, Offset));
__ Ldr(*rtX, MemOperand(rtX, 0, Offset));
break;
case INST_A64(LDR_LIT)::LDR_W:
__ Mov(*rtX, targetAddr);
__ Ldr(*rtX, MemOperand(rtX, 0, Offset));
__ Ldr(*rtW, MemOperand(rtX, 0, Offset));
break;
case INST_A64(LDR_LIT)::LDR_SW:
__ Mov(*rtX, targetAddr);
__ Ldrsw(*rtX, MemOperand(rtX, 0, Offset));
break;
case INST_A64(LDR_LIT)::LDR_PRFM:
__ Push(X0);
......@@ -147,8 +239,3 @@ IMPL_RELOCATE(LDR_LIT) {
IMPL_RELOCATE(ADR_ADRP) {
__ Mov(*inst->rd, inst->getImmPCOffsetTarget());
}
bool CodeRelocateA64::visit(Unit<Base> *unit, void *pc) {
relocate(reinterpret_cast<Instruction<Base> *>(unit), assemblerA64->getPC());
return true;
}
......@@ -5,6 +5,8 @@
#ifndef SANDHOOK_NH_CODE_RELOCATE_A64_H
#define SANDHOOK_NH_CODE_RELOCATE_A64_H
#include <mutex>
#include <map>
#include "code_relocate.h"
#include "assembler_a64.h"
......@@ -27,6 +29,10 @@ namespace SandHook {
bool visit(Unit<Base> *unit, void *pc) override;
bool inRelocateRange(Off targetOffset, Addr targetLen);
Label* getLaterBindLabel(Addr offset);
DEFINE_RELOCATE(B_BL)
DEFINE_RELOCATE(B_COND)
......@@ -40,8 +46,19 @@ namespace SandHook {
DEFINE_RELOCATE(ADR_ADRP)
~CodeRelocateA64() {
delete relocateLock;
delete laterBindlabels;
}
private:
AssemblerA64* assemblerA64;
std::mutex* relocateLock = new std::mutex();
std::map<Addr, Label*>* laterBindlabels = new std::map<Addr, Label*>();
Addr startAddr;
Addr length;
Addr curOffset;
};
}
......
......@@ -25,7 +25,6 @@ void *InlineHookArm64Android::inlineHook(void *origin, void *replace) {
void* backup = nullptr;
AssemblerA64 assemblerBackup(backupBuffer);
CodeContainer* codeContainerBackup = &assemblerBackup.codeContainer;
StaticCodeBuffer inlineBuffer = StaticCodeBuffer(reinterpret_cast<Addr>(origin));
AssemblerA64 assemblerInline(&inlineBuffer);
......@@ -34,10 +33,7 @@ void *InlineHookArm64Android::inlineHook(void *origin, void *replace) {
//build inline trampoline
#define __ assemblerInline.
Label* target_addr_label = new Label();
__ Push(X0);
__ Ldr(IP1, *target_addr_label);
__ Ldr(IP1, *target_addr_label);
__ Pop(X0);
__ Ldr(IP1, target_addr_label);
__ Br(IP1);
__ Emit(target_addr_label);
__ Emit(reinterpret_cast<Addr>(replace));
......@@ -48,7 +44,7 @@ void *InlineHookArm64Android::inlineHook(void *origin, void *replace) {
backup = relocate.relocate(origin, codeContainerInline->size(), nullptr);
#define __ assemblerBackup.
Label* origin_addr_label = new Label();
__ Ldr(IP1, *origin_addr_label);
__ Ldr(IP1, origin_addr_label);
__ Br(IP1);
__ Emit(origin_addr_label);
__ Emit(reinterpret_cast<Addr>(origin) + codeContainerInline->size());
......
......@@ -17,7 +17,7 @@ using namespace SandHook::AsmA64;
void (*dosth3Backup)(int, int) = nullptr;
void (*dosth4Backup)() = nullptr;
void (*dosth4Backup2)() = nullptr;
bool memUnprotect(Addr addr, Addr len) {
long pagesize = 4096;
......@@ -66,6 +66,14 @@ void do4replace() {
dosth4Backup();
}
void do4replace2() {
int a = 1 + 1;
int b = 1 + 1;
int c = 1 + 1;
int d = 1 + 1;
dosth4Backup2();
}
void do3replace(int x, int y) {
int a = 1 + 1;
int b = 1 + 1;
......@@ -132,6 +140,10 @@ Java_com_swift_sandhook_nativehook_NativeHook_test(JNIEnv *env, jclass jclass1)
reinterpret_cast<void *>(do4),
reinterpret_cast<void *>(do4replace)));
dosth4Backup2 = reinterpret_cast<void (*)()>(inlineHookArm64Android.inlineHook(
reinterpret_cast<void *>(do4),
reinterpret_cast<void *>(do4replace2)));
do4();
}
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment