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) { ...@@ -162,8 +162,12 @@ void AssemblerA64::Ldr(RegisterA64 &rt, const MemOperand &memOperand) {
} }
} }
void AssemblerA64::Ldr(RegisterA64 &rt, Label &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))); 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) { void AssemblerA64::Ldrsw(XRegister &rt, const MemOperand& memOperand) {
......
...@@ -63,8 +63,9 @@ namespace SandHook { ...@@ -63,8 +63,9 @@ namespace SandHook {
void Str(RegisterA64& rt, const MemOperand& memOperand); void Str(RegisterA64& rt, const MemOperand& memOperand);
void Ldr(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 Ldrsw(XRegister& rt, const MemOperand& memOperand);
void Pop(RegisterA64& rt); void Pop(RegisterA64& rt);
......
...@@ -318,19 +318,20 @@ void A64_LDR_LIT::onOffsetApply(Off offset) { ...@@ -318,19 +318,20 @@ void A64_LDR_LIT::onOffsetApply(Off offset) {
} }
void A64_LDR_LIT::decode(STRUCT_A64(LDR_LIT) *inst) { 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) { if (op == LDR_W) {
DECODE_RT(WReg); DECODE_RT(WReg);
} else { } else {
DECODE_RT(XReg); DECODE_RT(XReg);
} }
offset = getImmPCOffset();
} }
void A64_LDR_LIT::assembler() { void A64_LDR_LIT::assembler() {
SET_OPCODE(LDR_LIT); SET_OPCODE(LDR_LIT);
get()->rt = rt->getCode(); ENCODE_OP;
get()->op = op; ENCODE_RT;
ENCODE_OFFSET(19, 2); ENCODE_OFFSET(19, 2);
} }
...@@ -702,7 +703,7 @@ void A64_LDR_UIMM::assembler() { ...@@ -702,7 +703,7 @@ void A64_LDR_UIMM::assembler() {
valid = false; valid = false;
return; return;
} }
get()->imm12 = operand.offset >> get()->size; get()->imm12 = static_cast<InstA64>(operand.offset >> get()->size);
} }
......
...@@ -4,9 +4,11 @@ ...@@ -4,9 +4,11 @@
#include "code_relocate_a64.h" #include "code_relocate_a64.h"
#include "decoder_arm64.h" #include "decoder_arm64.h"
#include "lock.h"
using namespace SandHook::RegistersA64; using namespace SandHook::RegistersA64;
using namespace SandHook::AsmA64; using namespace SandHook::AsmA64;
using namespace SandHook::Utils;
#define __ assemblerA64-> #define __ assemblerA64->
...@@ -21,7 +23,17 @@ CodeRelocateA64::CodeRelocateA64(AssemblerA64 &assembler) : CodeRelocate(assembl ...@@ -21,7 +23,17 @@ CodeRelocateA64::CodeRelocateA64(AssemblerA64 &assembler) : CodeRelocate(assembl
this->assemblerA64 = &assembler; 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) { 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)); assemblerA64->allocBufferFirst(static_cast<U32>(len * 8));
void* curPc = assemblerA64->getPC(); void* curPc = assemblerA64->getPC();
Arm64Decoder decoder = Arm64Decoder(); Arm64Decoder decoder = Arm64Decoder();
...@@ -35,6 +47,10 @@ void* CodeRelocateA64::relocate(void *startPc, Addr len, void *toPc = nullptr) t ...@@ -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* CodeRelocateA64::relocate(Instruction<Base> *instruction, void *toPc) throw(ErrorCodeException) {
void* curPc = assemblerA64->getPC(); void* curPc = assemblerA64->getPC();
//insert later bind labels
__ Emit(getLaterBindLabel(curOffset));
if (!instruction->pcRelate()) { if (!instruction->pcRelate()) {
__ Emit(instruction); __ Emit(instruction);
return curPc; return curPc;
...@@ -52,8 +68,38 @@ void* CodeRelocateA64::relocate(Instruction<Base> *instruction, void *toPc) thro ...@@ -52,8 +68,38 @@ void* CodeRelocateA64::relocate(Instruction<Base> *instruction, void *toPc) thro
return curPc; 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) { IMPL_RELOCATE(B_BL) {
Addr targetAddr = inst->getImmPCOffsetTarget(); 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) { if (inst->op == inst->BL) {
__ Mov(LR, (Addr)inst->getPC() + inst->size()); __ Mov(LR, (Addr)inst->getPC() + inst->size());
} }
...@@ -62,9 +108,13 @@ IMPL_RELOCATE(B_BL) { ...@@ -62,9 +108,13 @@ IMPL_RELOCATE(B_BL) {
} }
IMPL_RELOCATE(B_COND) { IMPL_RELOCATE(B_COND) {
Addr targetAddr = inst->getImmPCOffsetTarget(); Addr targetAddr = inst->getImmPCOffsetTarget();
if (inRelocateRange(inst->offset, sizeof(InstA64))) {
__ B(inst->condition, getLaterBindLabel(inst->offset + curOffset));
return;
}
Label *true_label = new Label(); Label *true_label = new Label();
Label *false_label = new Label(); Label *false_label = new Label();
...@@ -82,6 +132,15 @@ IMPL_RELOCATE(TBZ_TBNZ) { ...@@ -82,6 +132,15 @@ IMPL_RELOCATE(TBZ_TBNZ) {
Addr targetAddr = inst->getImmPCOffsetTarget(); 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 *true_label = new Label();
Label *false_label = new Label(); Label *false_label = new Label();
...@@ -102,6 +161,15 @@ IMPL_RELOCATE(TBZ_TBNZ) { ...@@ -102,6 +161,15 @@ IMPL_RELOCATE(TBZ_TBNZ) {
IMPL_RELOCATE(CBZ_CBNZ) { IMPL_RELOCATE(CBZ_CBNZ) {
Addr targetAddr = inst->getImmPCOffsetTarget(); 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 *true_label = new Label();
Label *false_label = new Label(); Label *false_label = new Label();
...@@ -124,16 +192,40 @@ IMPL_RELOCATE(LDR_LIT) { ...@@ -124,16 +192,40 @@ IMPL_RELOCATE(LDR_LIT) {
Addr targetAddr = inst->getImmPCOffsetTarget(); Addr targetAddr = inst->getImmPCOffsetTarget();
XRegister* rtX = XReg(inst->rt->getCode()); XRegister* rtX = XReg(inst->rt->getCode());
WRegister* rtW = WReg(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) { switch (inst->op) {
case INST_A64(LDR_LIT)::LDR_X: case INST_A64(LDR_LIT)::LDR_X:
__ Mov(*rtX, targetAddr); __ Mov(*rtX, targetAddr);
__ Ldr(*rtW, MemOperand(rtX, 0, Offset)); __ Ldr(*rtX, MemOperand(rtX, 0, Offset));
break; break;
case INST_A64(LDR_LIT)::LDR_W: case INST_A64(LDR_LIT)::LDR_W:
__ Mov(*rtX, targetAddr); __ Mov(*rtX, targetAddr);
__ Ldr(*rtX, MemOperand(rtX, 0, Offset)); __ Ldr(*rtW, MemOperand(rtX, 0, Offset));
break; break;
case INST_A64(LDR_LIT)::LDR_SW: case INST_A64(LDR_LIT)::LDR_SW:
__ Mov(*rtX, targetAddr);
__ Ldrsw(*rtX, MemOperand(rtX, 0, Offset));
break; break;
case INST_A64(LDR_LIT)::LDR_PRFM: case INST_A64(LDR_LIT)::LDR_PRFM:
__ Push(X0); __ Push(X0);
...@@ -147,8 +239,3 @@ IMPL_RELOCATE(LDR_LIT) { ...@@ -147,8 +239,3 @@ IMPL_RELOCATE(LDR_LIT) {
IMPL_RELOCATE(ADR_ADRP) { IMPL_RELOCATE(ADR_ADRP) {
__ Mov(*inst->rd, inst->getImmPCOffsetTarget()); __ 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 @@ ...@@ -5,6 +5,8 @@
#ifndef SANDHOOK_NH_CODE_RELOCATE_A64_H #ifndef SANDHOOK_NH_CODE_RELOCATE_A64_H
#define SANDHOOK_NH_CODE_RELOCATE_A64_H #define SANDHOOK_NH_CODE_RELOCATE_A64_H
#include <mutex>
#include <map>
#include "code_relocate.h" #include "code_relocate.h"
#include "assembler_a64.h" #include "assembler_a64.h"
...@@ -27,6 +29,10 @@ namespace SandHook { ...@@ -27,6 +29,10 @@ namespace SandHook {
bool visit(Unit<Base> *unit, void *pc) override; 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_BL)
DEFINE_RELOCATE(B_COND) DEFINE_RELOCATE(B_COND)
...@@ -40,8 +46,19 @@ namespace SandHook { ...@@ -40,8 +46,19 @@ namespace SandHook {
DEFINE_RELOCATE(ADR_ADRP) DEFINE_RELOCATE(ADR_ADRP)
~CodeRelocateA64() {
delete relocateLock;
delete laterBindlabels;
}
private: private:
AssemblerA64* assemblerA64; 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) { ...@@ -25,7 +25,6 @@ void *InlineHookArm64Android::inlineHook(void *origin, void *replace) {
void* backup = nullptr; void* backup = nullptr;
AssemblerA64 assemblerBackup(backupBuffer); AssemblerA64 assemblerBackup(backupBuffer);
CodeContainer* codeContainerBackup = &assemblerBackup.codeContainer;
StaticCodeBuffer inlineBuffer = StaticCodeBuffer(reinterpret_cast<Addr>(origin)); StaticCodeBuffer inlineBuffer = StaticCodeBuffer(reinterpret_cast<Addr>(origin));
AssemblerA64 assemblerInline(&inlineBuffer); AssemblerA64 assemblerInline(&inlineBuffer);
...@@ -34,10 +33,7 @@ void *InlineHookArm64Android::inlineHook(void *origin, void *replace) { ...@@ -34,10 +33,7 @@ void *InlineHookArm64Android::inlineHook(void *origin, void *replace) {
//build inline trampoline //build inline trampoline
#define __ assemblerInline. #define __ assemblerInline.
Label* target_addr_label = new Label(); Label* target_addr_label = new Label();
__ Push(X0); __ Ldr(IP1, target_addr_label);
__ Ldr(IP1, *target_addr_label);
__ Ldr(IP1, *target_addr_label);
__ Pop(X0);
__ Br(IP1); __ Br(IP1);
__ Emit(target_addr_label); __ Emit(target_addr_label);
__ Emit(reinterpret_cast<Addr>(replace)); __ Emit(reinterpret_cast<Addr>(replace));
...@@ -48,7 +44,7 @@ void *InlineHookArm64Android::inlineHook(void *origin, void *replace) { ...@@ -48,7 +44,7 @@ void *InlineHookArm64Android::inlineHook(void *origin, void *replace) {
backup = relocate.relocate(origin, codeContainerInline->size(), nullptr); backup = relocate.relocate(origin, codeContainerInline->size(), nullptr);
#define __ assemblerBackup. #define __ assemblerBackup.
Label* origin_addr_label = new Label(); Label* origin_addr_label = new Label();
__ Ldr(IP1, *origin_addr_label); __ Ldr(IP1, origin_addr_label);
__ Br(IP1); __ Br(IP1);
__ Emit(origin_addr_label); __ Emit(origin_addr_label);
__ Emit(reinterpret_cast<Addr>(origin) + codeContainerInline->size()); __ Emit(reinterpret_cast<Addr>(origin) + codeContainerInline->size());
......
...@@ -17,7 +17,7 @@ using namespace SandHook::AsmA64; ...@@ -17,7 +17,7 @@ using namespace SandHook::AsmA64;
void (*dosth3Backup)(int, int) = nullptr; void (*dosth3Backup)(int, int) = nullptr;
void (*dosth4Backup)() = nullptr; void (*dosth4Backup)() = nullptr;
void (*dosth4Backup2)() = nullptr;
bool memUnprotect(Addr addr, Addr len) { bool memUnprotect(Addr addr, Addr len) {
long pagesize = 4096; long pagesize = 4096;
...@@ -66,6 +66,14 @@ void do4replace() { ...@@ -66,6 +66,14 @@ void do4replace() {
dosth4Backup(); 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) { void do3replace(int x, int y) {
int a = 1 + 1; int a = 1 + 1;
int b = 1 + 1; int b = 1 + 1;
...@@ -132,6 +140,10 @@ Java_com_swift_sandhook_nativehook_NativeHook_test(JNIEnv *env, jclass jclass1) ...@@ -132,6 +140,10 @@ Java_com_swift_sandhook_nativehook_NativeHook_test(JNIEnv *env, jclass jclass1)
reinterpret_cast<void *>(do4), reinterpret_cast<void *>(do4),
reinterpret_cast<void *>(do4replace))); reinterpret_cast<void *>(do4replace)));
dosth4Backup2 = reinterpret_cast<void (*)()>(inlineHookArm64Android.inlineHook(
reinterpret_cast<void *>(do4),
reinterpret_cast<void *>(do4replace2)));
do4(); 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