update
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
#include "stack_tracker.h"
|
||||
|
||||
auto StackTracker::rpm(uintptr_t address, size_t readSize)
|
||||
-> std::vector<char> {
|
||||
size_t NumOfRead = 0;
|
||||
@@ -12,8 +13,7 @@ auto StackTracker::rpm(uintptr_t address, size_t readSize)
|
||||
return buffer;
|
||||
}
|
||||
auto StackTracker::LookslikeValidEntry(cs_insn* insn, size_t count) -> bool {
|
||||
if (insn == nullptr || count == 0)
|
||||
return false;
|
||||
if (insn == nullptr || count == 0) return false;
|
||||
|
||||
int threshold_score = 2;
|
||||
int score = 0;
|
||||
@@ -25,39 +25,36 @@ auto StackTracker::LookslikeValidEntry(cs_insn* insn, size_t count) -> bool {
|
||||
const cs_insn& inst = insn[i];
|
||||
|
||||
switch (inst.id) {
|
||||
case X86_INS_PUSH:
|
||||
if (strcmp(inst.mnemonic, "push") == 0)
|
||||
case X86_INS_PUSH:
|
||||
if (strcmp(inst.mnemonic, "push") == 0) score++;
|
||||
break;
|
||||
case X86_INS_MOV:
|
||||
if (strstr(inst.op_str, "rbp") != nullptr ||
|
||||
strstr(inst.op_str, "rsp") != nullptr)
|
||||
score++;
|
||||
break;
|
||||
case X86_INS_SUB:
|
||||
case X86_INS_ADD:
|
||||
if (strstr(inst.op_str, "rsp") != nullptr) score++;
|
||||
break;
|
||||
case X86_INS_CALL:
|
||||
score += 1;
|
||||
break;
|
||||
case X86_INS_LEA:
|
||||
if (strstr(inst.op_str, "rip") != nullptr) score++;
|
||||
break;
|
||||
case X86_INS_TEST:
|
||||
case X86_INS_CMP:
|
||||
case X86_INS_JE:
|
||||
case X86_INS_JNE:
|
||||
case X86_INS_JMP:
|
||||
score++;
|
||||
break;
|
||||
case X86_INS_MOV:
|
||||
if (strstr(inst.op_str, "rbp") != nullptr || strstr(inst.op_str, "rsp") != nullptr)
|
||||
score++;
|
||||
break;
|
||||
case X86_INS_SUB:
|
||||
case X86_INS_ADD:
|
||||
if (strstr(inst.op_str, "rsp") != nullptr)
|
||||
score++;
|
||||
break;
|
||||
case X86_INS_CALL:
|
||||
score += 1;
|
||||
break;
|
||||
case X86_INS_LEA:
|
||||
if (strstr(inst.op_str, "rip") != nullptr)
|
||||
score++;
|
||||
break;
|
||||
case X86_INS_TEST:
|
||||
case X86_INS_CMP:
|
||||
case X86_INS_JE:
|
||||
case X86_INS_JNE:
|
||||
case X86_INS_JMP:
|
||||
score++;
|
||||
break;
|
||||
case X86_INS_NOP:
|
||||
break; // 忽略
|
||||
default:
|
||||
if (score == 0)
|
||||
score -= 1; //杂指令降低一点分数
|
||||
break;
|
||||
break;
|
||||
case X86_INS_NOP:
|
||||
break; // 忽略
|
||||
default:
|
||||
if (score == 0) score -= 1; // 杂指令降低一点分数
|
||||
break;
|
||||
}
|
||||
|
||||
if (score >= threshold_score) {
|
||||
@@ -66,24 +63,31 @@ auto StackTracker::LookslikeValidEntry(cs_insn* insn, size_t count) -> bool {
|
||||
}
|
||||
return score >= threshold_score;
|
||||
}
|
||||
auto StackTracker::TryFindValidDisasm(uint64_t baseAddr, size_t maxOffset) -> bool {
|
||||
auto StackTracker::TryFindValidDisasm(uint64_t baseAddr, size_t maxOffset)
|
||||
-> bool {
|
||||
for (size_t i = 0; i < maxOffset; ++i) {
|
||||
auto buf = this->rpm(baseAddr + i, this->trackSize);
|
||||
if (buf.size() != this->trackSize) continue;
|
||||
cs_insn* testInsn = nullptr;
|
||||
auto cnt = cs_disasm(this->capstoneHandle,
|
||||
reinterpret_cast<const uint8_t*>(buf.data()),
|
||||
this->trackSize, baseAddr + i, 0, &testInsn);
|
||||
if (cnt > 0 && LookslikeValidEntry(testInsn, cnt)) {
|
||||
this->disasmCount = cs_disasm(this->capstoneHandle,
|
||||
reinterpret_cast<const uint8_t*>(buf.data()),
|
||||
this->trackSize, baseAddr + i, 0, &testInsn);
|
||||
// this->PrintAsm(testInsn);
|
||||
if (this->disasmCount > 0) {
|
||||
this->insn = testInsn;
|
||||
}
|
||||
if (this->disasmCount > 0 && LookslikeValidEntry(testInsn, this->disasmCount)) {
|
||||
this->baseAddr += i;
|
||||
if (this->insn != nullptr) {
|
||||
cs_free(this->insn, this->disasmCount);
|
||||
}
|
||||
this->insn = testInsn;
|
||||
this->disasmCount = cnt;
|
||||
for (size_t j = 0; j < cnt; ++j) {
|
||||
this->insList.push_back(std::make_shared<cs_insn>(this->insn[j]));
|
||||
for (size_t j = 0; j < this->disasmCount; ++j) {
|
||||
// this->PrintAsm(&this->insn[j]);
|
||||
|
||||
this->insList.push_back(
|
||||
std::make_shared<cs_insn>(this->insn[j]));
|
||||
}
|
||||
this->SuccessReadedBuffer = buf;
|
||||
this->readSuccess = true;
|
||||
return true;
|
||||
}
|
||||
@@ -104,10 +108,14 @@ StackTracker::StackTracker(HANDLE hProcess, uint64_t StartAddress,
|
||||
cs_option(capstoneHandle, CS_OPT_SKIPDATA, CS_OPT_ON);
|
||||
/*
|
||||
do {
|
||||
// 1.读取
|
||||
auto bufferArrays = this->rpm(StartAddress, trackSize);
|
||||
if (bufferArrays.size() != trackSize) {
|
||||
break;
|
||||
}
|
||||
// 2. 反过来
|
||||
std::reverse(bufferArrays.begin(), bufferArrays.end());
|
||||
// 3. 这里就是向上的了.指令是对的上的
|
||||
disasmCount =
|
||||
cs_disasm(capstoneHandle,
|
||||
reinterpret_cast<const uint8_t*>(bufferArrays.data()),
|
||||
@@ -115,8 +123,10 @@ StackTracker::StackTracker(HANDLE hProcess, uint64_t StartAddress,
|
||||
if (disasmCount == 0) {
|
||||
break;
|
||||
}
|
||||
for (size_t index = 0; index < disasmCount; index++) {
|
||||
// 4. 再反过来
|
||||
for (size_t index = disasmCount; index > 0; index--) {
|
||||
const auto code = insn[index];
|
||||
this->PrintAsm(&code);
|
||||
this->insList.push_back(std::make_shared<cs_insn>(code));
|
||||
}
|
||||
this->readSuccess = true;
|
||||
@@ -135,7 +145,7 @@ auto StackTracker::getNextIns() -> std::shared_ptr<cs_insn> {
|
||||
}
|
||||
StackTracker::~StackTracker() {
|
||||
if (insn) {
|
||||
cs_free(insn, disasmCount);
|
||||
//cs_free(insn, disasmCount);
|
||||
cs_close(&capstoneHandle);
|
||||
}
|
||||
}
|
||||
@@ -168,16 +178,26 @@ auto StackTracker::matchCode(
|
||||
inline auto StackTracker::is_call(cs_insn* ins) -> bool {
|
||||
return ins->id == X86_INS_CALL;
|
||||
}
|
||||
auto StackTracker::PrintAsm() -> void {
|
||||
for (size_t j = 0; j < this->disasmCount; ++j) {
|
||||
for (int x = 0; x < this->insn[j].size; x++) {
|
||||
printf("%02X ", this->insn[j].bytes[x]);
|
||||
}
|
||||
printf("0x%llx :\t\t%s\t%s\t\n", this->insn[j].address,
|
||||
this->insn[j].mnemonic, this->insn[j].op_str);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
auto StackTracker::CalcNextJmpAddress() -> std::pair<bool, uint64_t> {
|
||||
if (this->readSuccess == false) {
|
||||
return {false , 0};
|
||||
return {false, 0};
|
||||
}
|
||||
this->feature = _features::kNonCallOnly;
|
||||
|
||||
uint64_t callAddress = 0;
|
||||
auto isMatchCall = matchCode(
|
||||
[&](cs_insn* instruction) {
|
||||
|
||||
if (instruction->id != X86_INS_CALL) {
|
||||
if (instruction->id == X86_INS_SYSCALL) {
|
||||
this->feature = _features::kSyscall;
|
||||
@@ -192,35 +212,39 @@ auto StackTracker::CalcNextJmpAddress() -> std::pair<bool, uint64_t> {
|
||||
callAddress =
|
||||
instruction->address + instruction->size + operand.imm;
|
||||
return true;
|
||||
}
|
||||
else if (operand.type == X86_OP_MEM) {
|
||||
} else if (operand.type == X86_OP_MEM) {
|
||||
const x86_op_mem& mem = operand.mem;
|
||||
// 我们只处理可以静态计算的 RIP 相对寻址
|
||||
if (mem.base == X86_REG_RIP) {
|
||||
uint64_t pointerAddress = instruction->address + instruction->size + mem.disp;
|
||||
uint64_t pointerAddress =
|
||||
instruction->address + instruction->size + mem.disp;
|
||||
size_t pointerSize = this->isWow64 ? 4 : 8;
|
||||
std::vector<char> pointerBuffer = this->rpm(pointerAddress, pointerSize);
|
||||
std::vector<char> pointerBuffer =
|
||||
this->rpm(pointerAddress, pointerSize);
|
||||
if (pointerBuffer.empty()) {
|
||||
std::cerr << "Failed to read pointer at 0x" << std::hex << pointerAddress << std::endl;
|
||||
std::cerr << "Failed to read pointer at 0x" << std::hex
|
||||
<< pointerAddress << std::endl;
|
||||
return false;
|
||||
}
|
||||
if (pointerSize == 8) {
|
||||
callAddress = *reinterpret_cast<uint64_t*>(pointerBuffer.data());
|
||||
}
|
||||
else { // 32位
|
||||
callAddress = *reinterpret_cast<uint32_t*>(pointerBuffer.data());
|
||||
callAddress =
|
||||
*reinterpret_cast<uint64_t*>(pointerBuffer.data());
|
||||
} else { // 32位
|
||||
callAddress =
|
||||
*reinterpret_cast<uint32_t*>(pointerBuffer.data());
|
||||
}
|
||||
|
||||
//std::cout << "Found RIP-relative call at 0x" << std::hex << instruction->address
|
||||
// << ". Pointer at 0x" << pointerAddress
|
||||
// << ". Final Target: 0x" << callAddress << std::endl;
|
||||
// std::cout << "Found RIP-relative call at 0x" << std::hex
|
||||
// << instruction->address
|
||||
// << ". Pointer at 0x" << pointerAddress
|
||||
// << ". Final Target: 0x" << callAddress << std::endl;
|
||||
return true;
|
||||
}
|
||||
//std::cout << "Skipping non-RIP-relative memory call at 0x" << std::hex << instruction->address << std::endl;
|
||||
// std::cout << "Skipping non-RIP-relative memory call at 0x" <<
|
||||
// std::hex << instruction->address << std::endl;
|
||||
this->feature = _features::kCallRip;
|
||||
return false;
|
||||
}
|
||||
else if (operand.type == X86_OP_REG) {
|
||||
} else if (operand.type == X86_OP_REG) {
|
||||
this->feature = _features::kCallReg;
|
||||
return false;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user