Skip to content

Commit

Permalink
[FEATURE] Added support for ARM binaries
Browse files Browse the repository at this point in the history
  • Loading branch information
hasherezade committed Jul 12, 2024
1 parent 267bd7e commit 0694071
Show file tree
Hide file tree
Showing 9 changed files with 86 additions and 36 deletions.
3 changes: 2 additions & 1 deletion disasm/Disasm.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ class Disasm
Disasm();
~Disasm();

virtual bool init(uint8_t* buf, size_t bufSize, size_t disasmSize, offset_t offset, Executable::exe_bits bitMode) = 0;
virtual bool init(uint8_t* buf, size_t bufSize, size_t disasmSize, offset_t offset, Executable::exe_arch arch, Executable::exe_bits bitMode) = 0;
virtual bool fillTable() = 0;
virtual bool clearTable() = 0;
virtual size_t getChunkSize(int index) const = 0;
Expand Down Expand Up @@ -101,6 +101,7 @@ class Disasm
bool is_init;

Executable::exe_bits m_bitMode;
Executable::exe_arch m_arch;

uint8_t* m_buf;
size_t m_bufSize;
Expand Down
11 changes: 8 additions & 3 deletions disasm/PeDisasm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,21 +12,26 @@ PeDisasm::PeDisasm(PEFile *pe, size_t _previewSize)
if (pe == NULL) throw CustomException("PE not initialized!");
}

bool PeDisasm::init(const offset_t offset, Executable::exe_bits bitMode)
bool PeDisasm::init(const offset_t offset, Executable::exe_arch arch, Executable::exe_bits bitMode)
{
this->isInit = false;
clearTable();
if (!m_PE) {
return false;
}

this->firstOffset = offset;
if (bitMode == Executable::UNKNOWN) {
this->isBitModeAuto = true;
this->m_bitMode = m_PE->getBitMode();
} else {
this->m_bitMode = bitMode;
}
if (arch == Executable::ARCH_UNKNOWN) {
//this->isBitModeAuto = true;
this->m_arch = m_PE->getArch();
} else {
this->m_arch = arch;
}
if (m_PE->getContentSize() < offset) {
return false;
}
Expand All @@ -37,7 +42,7 @@ bool PeDisasm::init(const offset_t offset, Executable::exe_bits bitMode)
if (!buf) {
return false;
}
const bool isOk = __disasm_super::init(buf, maxSize, disasmSize, offset, m_bitMode);
const bool isOk = __disasm_super::init(buf, maxSize, disasmSize, offset, m_arch, m_bitMode);
this->isInit = isOk;
return isOk;
}
Expand Down
2 changes: 1 addition & 1 deletion disasm/PeDisasm.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ class PeDisasm : public __disasm_super

public:
PeDisasm(PEFile *pe, size_t previewSize = DISASM_PREVIEW_SIZE);
bool init(const offset_t offset, Executable::exe_bits bitMode = Executable::UNKNOWN);
bool init(const offset_t offset, Executable::exe_arch arch, Executable::exe_bits bitMode);
bool fillTable();

bool isRvaContnuous(int index) const;
Expand Down
27 changes: 21 additions & 6 deletions disasm/cdis/CDisasm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,26 @@ cs_mode toCSmode(Executable::exe_bits bitMode)
return CS_MODE_32; //Default
}

bool CDisasm::init_capstone(Executable::exe_bits bitMode)
bool CDisasm::init_capstone(Executable::exe_arch arch, Executable::exe_bits bitMode)
{
cs_err err;
err = cs_open(CS_ARCH_X86, toCSmode(bitMode), &handle);
if (arch == Executable::ARCH_INTEL) {
err = cs_open(CS_ARCH_X86, toCSmode(bitMode), &handle);
} else if (arch == Executable::ARCH_ARM && bitMode == Executable::BITS_64) {
err = cs_open(CS_ARCH_ARM64, CS_MODE_LITTLE_ENDIAN, &handle);
} else if (arch == Executable::ARCH_ARM && bitMode == Executable::BITS_32) {
err = cs_open(CS_ARCH_ARM, CS_MODE_LITTLE_ENDIAN, &handle);
} else {
std::cout << "Unknown ARCH: " << std::hex << arch << "\n";
return false;
}

if (err) {
printf("Failed on cs_open() with error returned: %u\n", err);
if (err == CS_ERR_ARCH) {
std::cerr << "Failed on cs_open(): unsupported architecture supplied!\n";
} else {
std::cerr << "Failed on cs_open(), error: " << std::dec << err << std::endl;
}
return false;
}
cs_option(handle, CS_OPT_DETAIL, CS_OPT_ON);
Expand All @@ -46,7 +60,7 @@ bool CDisasm::init_capstone(Executable::exe_bits bitMode)
return true;
}

bool CDisasm::init(uint8_t* buf, size_t bufSize, size_t disasmSize, offset_t offset, Executable::exe_bits bitMode)
bool CDisasm::init(uint8_t* buf, size_t bufSize, size_t disasmSize, offset_t offset, Executable::exe_arch arch, Executable::exe_bits bitMode)
{
QMutexLocker locker(&m_disasmMutex);
is_init = false;
Expand All @@ -60,15 +74,16 @@ bool CDisasm::init(uint8_t* buf, size_t bufSize, size_t disasmSize, offset_t off
this->m_offset = 0;
this->startOffset = this->convertToVA(offset);
m_bitMode = bitMode;
m_arch = arch;

is_init = init_capstone(m_bitMode);
is_init = init_capstone(m_arch, m_bitMode);
return this->is_init;
}

size_t CDisasm::disasmNext()
{
if (!is_init && m_insn) {
printf("Cannot disasm next = NOT INIT!\n");
printf("Cannot disasm next = not initialized!\n");
return 0;
}
//--
Expand Down
4 changes: 2 additions & 2 deletions disasm/cdis/CDisasm.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ class CDisasm : public Disasm
CDisasm();
~CDisasm();

bool init(uint8_t* buf, size_t bufSize, size_t disasmSize, offset_t offset, Executable::exe_bits bitMode);
bool init(uint8_t* buf, size_t bufSize, size_t disasmSize, offset_t offset, Executable::exe_arch arch, Executable::exe_bits bitMode);
bool fillTable();
bool clearTable();
offset_t getRawAt(int index) const;
Expand Down Expand Up @@ -117,7 +117,7 @@ class CDisasm : public Disasm
minidis::mnem_type fetchMnemType(const cs_insn &insn) const;

size_t disasmNext();
bool init_capstone(Executable::exe_bits bitMode);
bool init_capstone(Executable::exe_arch arch, Executable::exe_bits bitMode);

//capstone stuff:
std::vector<cs_insn> m_table;
Expand Down
67 changes: 47 additions & 20 deletions pe-bear/DisasmView.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -363,34 +363,51 @@ void DisasmTreeView::initHeaderMenu()
/*Bitmode setting actions */
QActionGroup *group = new QActionGroup(this);
group->setExclusive(true);
QMenu* bitModeSubmenu = hdrSettings->addMenu(tr("&Bit mode"));
const int MODES_NUM = 4;
QAction *actions[MODES_NUM];
QMenu* archMenu = hdrSettings->addMenu(tr("Architectu&re"));

actions[0] = group->addAction(tr("Automatic"));
actions[0]->setData(0);
const int MODES_NUM = 6;
QAction *actionsI[MODES_NUM];

actionsI[0] = group->addAction(tr("Automatic"));
actionsI[0]->setData(0);

for (int i = 1; i < MODES_NUM; i++) {
int bitmode = 16<<(i-1);
actions[i] = group->addAction(QString::number(bitmode));
actions[i]->setData(bitmode);
if (i < 4) {
int bitmode = 16<<(i-1);
actionsI[i] = group->addAction(QString(tr("Intel")) + ": " + QString::number(bitmode) + tr("-bit"));
} else {
int val = i - 2;
int bitmode = 16<<(val-1);
actionsI[i] = group->addAction(QString(tr("ARM")) + ": " + QString::number(bitmode) + tr("-bit"));
}
actionsI[i]->setData(i);
}

for (int i = 0; i < MODES_NUM; i++) {
actions[i]->setCheckable(true);
bitModeSubmenu->addAction(actions[i]);
actionsI[i]->setCheckable(true);
archMenu->addAction(actionsI[i]);
}
actions[0]->setChecked(true);
actionsI[0]->setChecked(true);
connect(group, SIGNAL( triggered(QAction*) ), this, SLOT( setBitMode(QAction*) ));
}

void DisasmTreeView::setBitMode(QAction* action)
{
QVariant data = action->data();
int bit = data.toInt();
if (!myModel) return;

myModel->resetDisasmMode(bit);
int flags = data.toInt();
if (!myModel) {
return;
}
int bitmode = 0;
Executable::exe_arch arch = Executable::ARCH_UNKNOWN;
if (flags < 4) {
bitmode = 16<<(flags-1);
arch = Executable::ARCH_INTEL;
} else {
bitmode = 16<<((flags - 2)-1);
arch = Executable::ARCH_ARM;
}
myModel->resetDisasmMode(bitmode, arch);
reset();
}

Expand Down Expand Up @@ -656,7 +673,7 @@ void DisasmTreeView::initHeader()

DisasmModel::DisasmModel(PeHandler *peHndl, QObject *parent)
: HexDumpModel(peHndl, parent), startOff(0),
isBitModeAuto(true), myDisasm(peHndl->getPe())
isBitModeAuto(true), archAuto(true), myDisasm(peHndl->getPe())
{
addrType = Executable::RVA;
makeIcons(this->settings.getIconSize());
Expand All @@ -678,16 +695,19 @@ void DisasmModel::makeIcons(const QSize &vSize)

void DisasmModel::rebuildDisamTab()
{
if (this->isBitModeAuto)
if (this->isBitModeAuto) {
this->bitMode = (m_PE) ? m_PE->getBitMode() : 32;

myDisasm.init(startOff, (Executable::exe_bits) this->bitMode);
}
if (this->archAuto) {
this->arch = (m_PE) ? m_PE->getArch() : Executable::ARCH_INTEL;
}
myDisasm.init(startOff, this->arch, (Executable::exe_bits) this->bitMode);
myDisasm.fillTable();
reset();
emit modelUpdated();
}

void DisasmModel::resetDisasmMode(uint8_t bitMode)
void DisasmModel::resetDisasmMode(uint8_t bitMode, Executable::exe_arch arch)
{
if (!m_PE) return;
if (bitMode != 16 && bitMode != 32 && bitMode != 64) {
Expand All @@ -697,6 +717,13 @@ void DisasmModel::resetDisasmMode(uint8_t bitMode)
this->isBitModeAuto = false;
this->bitMode = bitMode;
}
if (arch == Executable::ARCH_UNKNOWN) {
this->archAuto = true;
this->arch = m_PE->getArch();
} else {
this->archAuto = false;
this->arch = arch;
}
rebuildDisamTab();
}

Expand Down
4 changes: 3 additions & 1 deletion pe-bear/DisasmView.h
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,7 @@ public slots:
void setStartingOffset(offset_t start) { startOff = start; rebuildDisamTab(); }
void setShownContent(offset_t start, bufsize_t size) { setStartingOffset(start); emit scrollReset(); }

void resetDisasmMode(uint8_t bitMode);
void resetDisasmMode(uint8_t bitMode, Executable::exe_arch arch);
void setShowImageBase(bool flag);
bool setComment(offset_t rva, const QString &comment)
{
Expand Down Expand Up @@ -247,7 +247,9 @@ public slots:
uint32_t startOff;

uint8_t bitMode;
Executable::exe_arch arch;
bool isBitModeAuto;
bool archAuto;
bool showImageBase;

QIcon tracerIcon, tracerUpIcon, tracerDownIcon, tracerSelf;
Expand Down
2 changes: 1 addition & 1 deletion pe-bear/base/PeHandler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1194,7 +1194,7 @@ bool PeHandler::exportDisasm(const QString &path, const offset_t startOff, const
}

pe_bear::PeDisasm myDisasm(pe, previewSize);
myDisasm.init(startOff, pe->getBitMode());
myDisasm.init(startOff, pe->getArch(), pe->getBitMode());
myDisasm.fillTable();

QTextStream disasmStream(&fOut);
Expand Down

0 comments on commit 0694071

Please sign in to comment.