Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Decluter InstructionInformation #42

Merged
merged 4 commits into from
Feb 20, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 13 additions & 26 deletions src/rp/arm.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,9 +43,6 @@ class ArmCapstone : public DisassEngineWrapper {
instr.virtual_address_in_memory = uintptr_t(vaddr);
instr.disassembly = mnemonic + ' ' + std::string(insn[0].op_str);
instr.size = insn[0].size;

instr.cap_is_branch = false;
instr.cap_is_valid_ending_instr = false;
ret = AllRight;

if (insn[0].detail == nullptr) {
Expand All @@ -54,28 +51,28 @@ class ArmCapstone : public DisassEngineWrapper {
}

if (cs_insn_group(m_handle, insn, ARM_GRP_JUMP)) {
instr.cap_is_branch = true;
instr.cap_is_valid_ending_instr =
instr.is_branch = true;
instr.is_valid_ending_instr =
insn[0].detail->arm.op_count == 1 &&
insn[0].detail->arm.operands[0].type != ARM_OP_IMM;
} else if (mnemonic == "b" || mnemonic == "bl" || mnemonic == "blx" ||
mnemonic == "cb" || mnemonic == "cbz") {
instr.cap_is_branch = true;
instr.is_branch = true;
} else if (mnemonic == "swi" || mnemonic == "svc") {
instr.cap_is_branch = true;
instr.cap_is_valid_ending_instr = true;
instr.is_branch = true;
instr.is_valid_ending_instr = true;
} else if (mnemonic == "mov" && insn[0].detail->arm.op_count >= 1 &&
insn[0].detail->arm.operands[0].type == ARM_OP_REG &&
insn[0].detail->arm.operands[0].reg == ARM_REG_PC) {
instr.cap_is_branch = true;
instr.cap_is_valid_ending_instr = true;
instr.is_branch = true;
instr.is_valid_ending_instr = true;
} else if (mnemonic == "bx") {
instr.cap_is_branch = true;
instr.cap_is_valid_ending_instr =
instr.is_branch = true;
instr.is_valid_ending_instr =
insn[0].detail->arm.operands[0].type == ARM_OP_REG;
} else if (mnemonic == "blx") {
instr.cap_is_branch = true;
instr.cap_is_valid_ending_instr = true;
instr.is_branch = true;
instr.is_valid_ending_instr = true;
} else if (mnemonic == "pop") {
bool has_pc = false;
for (size_t i = 0; i < insn[0].detail->arm.op_count; ++i) {
Expand All @@ -87,25 +84,15 @@ class ArmCapstone : public DisassEngineWrapper {
}

if (has_pc) {
instr.cap_is_branch = true;
instr.cap_is_valid_ending_instr = true;
instr.is_branch = true;
instr.is_valid_ending_instr = true;
}
}

cs_free(insn, count);
return instr;
}

bool is_valid_ending_instruction(
const InstructionInformation &instr) const override {
return instr.cap_is_valid_ending_instr;
}

bool
is_valid_instruction(const InstructionInformation &instr) const override {
return instr.cap_is_branch == false;
}

uint32_t get_size_biggest_instruction() const override { return 4; }

uint32_t get_alignement() const override {
Expand Down
17 changes: 2 additions & 15 deletions src/rp/arm64.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,6 @@ class Arm64Capstone : public DisassEngineWrapper {
instr.virtual_address_in_memory = uintptr_t(vaddr);
instr.disassembly = mnemonic + ' ' + std::string(insn[0].op_str);
instr.size = insn[0].size;

instr.cap_is_branch = false;
instr.cap_is_valid_ending_instr = false;
ret = AllRight;

if (insn[0].detail == nullptr) {
Expand All @@ -51,8 +48,8 @@ class Arm64Capstone : public DisassEngineWrapper {
const bool Call = cs_insn_group(m_handle, insn, ARM64_GRP_CALL);
const bool Ret = cs_insn_group(m_handle, insn, ARM64_GRP_RET);
const bool Int = cs_insn_group(m_handle, insn, ARM64_GRP_INT);
instr.cap_is_branch = Jump || Call || Ret || Int;
instr.cap_is_valid_ending_instr =
instr.is_branch = Jump || Call || Ret || Int;
instr.is_valid_ending_instr =
Ret || Int ||
((Jump || Call) && insn[0].detail->arm64.op_count == 1 &&
insn[0].detail->arm64.operands[0].type != ARM64_OP_IMM);
Expand All @@ -61,16 +58,6 @@ class Arm64Capstone : public DisassEngineWrapper {
return instr;
}

bool is_valid_ending_instruction(
const InstructionInformation &instr) const override {
return instr.cap_is_valid_ending_instr;
}

bool
is_valid_instruction(const InstructionInformation &instr) const override {
return instr.cap_is_branch == false;
}

uint32_t get_size_biggest_instruction() const override { return 4; }

uint32_t get_alignement() const override { return 4; }
Expand Down
16 changes: 2 additions & 14 deletions src/rp/disassenginewrapper.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,22 +6,14 @@
#include <vector>

struct InstructionInformation {
// Generic fields
std::string disassembly;
std::string mnemonic;
uint32_t size = 0;
uintptr_t address = 0;
uintptr_t virtual_address_in_memory = 0;
std::vector<uint8_t> bytes;

// Capstone field
bool cap_is_branch = false;
bool cap_is_valid_ending_instr = false;

// BeaEngine fields
uint32_t bea_branch_type = 0; // This is used by BeaEngine ; and this will
// hold DISASM.Instruction.BranchType
uint64_t bea_addr_value = 0; // This is used by BeaEngine, DISASM.Instruction
bool is_branch = false;
bool is_valid_ending_instr = false;
};

enum DisassEngineReturn { UnknownInstruction, OutOfBlock, AllRight };
Expand All @@ -39,10 +31,6 @@ class DisassEngineWrapper {
virtual InstructionInformation disass(const uint8_t *data, uint64_t len,
const uint64_t vaddr,
DisassEngineReturn &ret) = 0;
virtual bool
is_valid_ending_instruction(const InstructionInformation &instr) const = 0;
virtual bool
is_valid_instruction(const InstructionInformation &instr) const = 0;
virtual uint32_t get_size_biggest_instruction() const = 0;
virtual uint32_t get_alignement() const = 0;
};
40 changes: 12 additions & 28 deletions src/rp/gadget.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -142,34 +142,18 @@ class Gadget {
return true;
}

const auto &current_a_bytes = a.m_instructions[current_a_idx].bytes();
const size_t current_a_bytes_size = current_a_bytes.size();
const auto &current_b_bytes = b.m_instructions[current_b_idx].bytes();
const size_t current_b_bytes_size = current_b_bytes.size();
while (1) {
if (current_a_bytes_idx >= current_a_bytes_size) {
current_a_idx++;
current_a_bytes_idx = 0;
break;
}

if (current_b_bytes_idx >= current_b_bytes_size) {
current_b_idx++;
current_b_bytes_idx = 0;
break;
}

if (current_a_bytes[current_a_bytes_idx] !=
current_b_bytes[current_b_bytes_idx]) {
return current_a_bytes[current_a_bytes_idx] <
current_b_bytes[current_b_bytes_idx];
}

current_a_bytes_idx++;
current_b_bytes_idx++;
const auto &current_a_disass =
a.m_instructions[current_a_idx].get_disassembly();
const auto &current_b_disass =
b.m_instructions[current_b_idx].get_disassembly();
const int compare = current_a_disass.compare(current_b_disass);
if (compare != 0) {
return (compare < 0) ? true : false;
}

current_a_idx++;
current_b_idx++;
}
return false;
}
};

Expand All @@ -186,8 +170,8 @@ class Gadget {
uint32_t m_size; /*!< the size in byte of the gadget*/

std::vector<Instruction>
m_instructions; /*!< the list of the different instructions composing the
gadget*/
m_instructions; /*!< the list of the different instructions composing
the gadget*/

mutable std::vector<Info>
m_info_gadgets; /*!< the vector which stores where you can find the same
Expand Down
36 changes: 10 additions & 26 deletions src/rp/intelbeaengine.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,49 +44,33 @@ class IntelBeaEngine : public DisassEngineWrapper {
instr.disassembly = m_disasm.CompleteInstr;
instr.mnemonic = m_disasm.Instruction.Mnemonic;
instr.size = len_instr;
instr.bea_branch_type = m_disasm.Instruction.BranchType;
instr.bea_addr_value = m_disasm.Instruction.AddrValue;
return instr;
}

bool is_valid_ending_instruction(
const InstructionInformation &instr) const override {
const uint32_t branch_type = instr.bea_branch_type;
const uint64_t addr_value = instr.bea_addr_value;
const char *mnemonic_s = instr.mnemonic.c_str();
const auto branch_type = m_disasm.Instruction.BranchType;
const auto addr_value = m_disasm.Instruction.AddrValue;
const char *mnemonic_s = m_disasm.Instruction.Mnemonic;
const char *disass_s = instr.disassembly.c_str();

const std::string &disass = instr.disassembly;
const char *disass_s = disass.c_str();
instr.is_branch = branch_type != 0;

const bool is_good_branch_type =
// We accept all the ret type instructions (except retf/iret)
(branch_type == RetType && (strncmp(mnemonic_s, "retf", 4) != 0) &&
(strncmp(mnemonic_s, "iretd", 5) != 0)) ||

// call reg32 / call [reg32]
(branch_type == CallType && addr_value == 0) ||

// jmp reg32 / jmp [reg32]
(branch_type == JmpType && addr_value == 0) ||

// int 0x80 & int 0x2e
((strncmp(disass_s, "int 0x80", 8) == 0) ||
(strncmp(disass_s, "int 0x2e", 8) == 0) ||
(strncmp(disass_s, "syscall", 7) == 0));

return is_good_branch_type &&
// Yeah, we don't accept jmp far/call far
disass.find("far") == std::string::npos;
}
instr.is_valid_ending_instr =
is_good_branch_type &&
// Yeah, we don't accept jmp far/call far
instr.disassembly.find("far") == std::string::npos;

bool
is_valid_instruction(const InstructionInformation &instr) const override {
const Int32 branch_type = instr.bea_branch_type;
const uint64_t addr_value = instr.bea_addr_value;
return branch_type != RetType && branch_type != JmpType &&
((branch_type == CallType && addr_value == 0) ||
branch_type != CallType) &&
instr.disassembly.find("far") == std::string::npos;
return instr;
}

uint32_t get_size_biggest_instruction() const override { return 15; }
Expand Down
6 changes: 2 additions & 4 deletions src/rp/ropsearch_algorithm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,9 +46,7 @@ void find_all_gadget_from_ret(const std::vector<uint8_t> &memory,
InstructionInformation instr =
disass_engine.disass(EIP_, end_data - EIP_, VirtualAddr, ret);

const bool is_valid = g_opts.allow_branches
? true
: disass_engine.is_valid_instruction(instr);
const bool is_valid = g_opts.allow_branches || (!instr.is_branch);
// if the instruction isn't valid, ends this function
if (ret == UnknownInstruction || ret == OutOfBlock || !is_valid) {
break;
Expand Down Expand Up @@ -126,7 +124,7 @@ void find_rop_gadgets(const std::vector<uint8_t> &section, const uint64_t vaddr,
continue;
}

if (!disass_engine.is_valid_ending_instruction(ret_instr)) {
if (!ret_instr.is_valid_ending_instr) {
continue;
}

Expand Down