2017-04-18 08:33:35 +00:00
|
|
|
#include <QJsonArray>
|
|
|
|
#include <QJsonObject>
|
2017-12-13 14:30:00 +00:00
|
|
|
#include <utils/TempConfig.h>
|
2017-10-14 09:35:49 +00:00
|
|
|
#include "utils/Configuration.h"
|
2018-03-04 17:42:02 +00:00
|
|
|
#include "Cutter.h"
|
2017-09-25 12:55:41 +00:00
|
|
|
#include "sdb.h"
|
|
|
|
|
2017-10-09 18:08:35 +00:00
|
|
|
Q_GLOBAL_STATIC(ccClass, uniqueInstance)
|
2017-04-18 08:33:35 +00:00
|
|
|
|
2017-04-09 17:12:36 +00:00
|
|
|
RCoreLocked::RCoreLocked(RCore *core)
|
|
|
|
: core(core)
|
|
|
|
{
|
|
|
|
r_th_lock_enter(core->lock);
|
|
|
|
}
|
|
|
|
|
2017-04-09 19:55:06 +00:00
|
|
|
RCoreLocked::RCoreLocked(RCoreLocked &&o)
|
2017-04-09 18:42:45 +00:00
|
|
|
: core(o.core)
|
2017-04-09 17:12:36 +00:00
|
|
|
{
|
2017-04-09 18:42:45 +00:00
|
|
|
o.core = nullptr;
|
2017-04-09 17:12:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
RCoreLocked::~RCoreLocked()
|
|
|
|
{
|
|
|
|
r_th_lock_leave(core->lock);
|
|
|
|
}
|
|
|
|
|
2017-04-09 19:55:06 +00:00
|
|
|
RCoreLocked::operator RCore *() const
|
2017-04-09 17:12:36 +00:00
|
|
|
{
|
|
|
|
return core;
|
|
|
|
}
|
|
|
|
|
2017-04-09 19:55:06 +00:00
|
|
|
RCore *RCoreLocked::operator->() const
|
2017-04-09 17:12:36 +00:00
|
|
|
{
|
|
|
|
return core;
|
|
|
|
}
|
|
|
|
|
2017-09-25 12:55:41 +00:00
|
|
|
RCoreLocked CutterCore::core() const
|
2017-04-09 17:12:36 +00:00
|
|
|
{
|
|
|
|
return RCoreLocked(this->core_);
|
|
|
|
}
|
|
|
|
|
|
|
|
#define CORE_LOCK() RCoreLocked core_lock__(this->core_)
|
|
|
|
|
2017-09-25 12:55:41 +00:00
|
|
|
CutterCore::CutterCore(QObject *parent) :
|
2017-03-29 10:18:37 +00:00
|
|
|
QObject(parent)
|
|
|
|
{
|
2017-04-09 19:55:06 +00:00
|
|
|
r_cons_new(); // initialize console
|
|
|
|
this->core_ = r_core_new();
|
|
|
|
r_core_loadlibs(this->core_, R_CORE_LOADLIBS_ALL, NULL);
|
2017-04-09 17:12:36 +00:00
|
|
|
// IMPLICIT r_bin_iobind (core_->bin, core_->io);
|
2017-03-29 10:18:37 +00:00
|
|
|
|
2017-09-25 17:51:49 +00:00
|
|
|
// Otherwise r2 may ask the user for input and Cutter would freeze
|
2017-10-01 14:36:40 +00:00
|
|
|
setConfig("scr.interactive", false);
|
2017-03-29 10:18:37 +00:00
|
|
|
|
2017-05-03 09:09:57 +00:00
|
|
|
default_bits = 0;
|
2017-03-29 10:18:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-10-09 18:08:35 +00:00
|
|
|
CutterCore *CutterCore::getInstance()
|
|
|
|
{
|
|
|
|
return uniqueInstance;
|
|
|
|
}
|
|
|
|
|
2017-09-25 12:55:41 +00:00
|
|
|
QList<QString> CutterCore::sdbList(QString path)
|
2017-04-09 19:55:06 +00:00
|
|
|
{
|
2017-04-09 17:12:36 +00:00
|
|
|
CORE_LOCK();
|
2017-03-29 10:18:37 +00:00
|
|
|
QList<QString> list = QList<QString>();
|
2017-04-09 19:55:06 +00:00
|
|
|
Sdb *root = sdb_ns_path(core_->sdb, path.toUtf8().constData(), 0);
|
|
|
|
if (root)
|
|
|
|
{
|
2017-03-29 10:18:37 +00:00
|
|
|
void *vsi;
|
|
|
|
ls_iter_t *iter;
|
2017-04-09 19:55:06 +00:00
|
|
|
ls_foreach(root->ns, iter, vsi)
|
|
|
|
{
|
|
|
|
SdbNs *nsi = (SdbNs *)vsi;
|
2017-03-30 21:49:51 +00:00
|
|
|
list << nsi->name;
|
2017-03-29 10:18:37 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return list;
|
|
|
|
}
|
|
|
|
|
2017-09-25 12:55:41 +00:00
|
|
|
QList<QString> CutterCore::sdbListKeys(QString path)
|
2017-04-09 19:55:06 +00:00
|
|
|
{
|
2017-04-09 17:12:36 +00:00
|
|
|
CORE_LOCK();
|
2017-03-29 10:18:37 +00:00
|
|
|
QList<QString> list = QList<QString>();
|
2017-04-09 19:55:06 +00:00
|
|
|
Sdb *root = sdb_ns_path(core_->sdb, path.toUtf8().constData(), 0);
|
|
|
|
if (root)
|
|
|
|
{
|
2017-03-29 10:18:37 +00:00
|
|
|
void *vsi;
|
|
|
|
ls_iter_t *iter;
|
|
|
|
SdbList *l = sdb_foreach_list(root, false);
|
2017-04-09 19:55:06 +00:00
|
|
|
ls_foreach(l, iter, vsi)
|
|
|
|
{
|
|
|
|
SdbKv *nsi = (SdbKv *)vsi;
|
2017-03-30 21:49:51 +00:00
|
|
|
list << nsi->key;
|
2017-03-29 10:18:37 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return list;
|
|
|
|
}
|
|
|
|
|
2017-09-25 12:55:41 +00:00
|
|
|
QString CutterCore::sdbGet(QString path, QString key)
|
2017-04-09 19:55:06 +00:00
|
|
|
{
|
2017-04-09 17:12:36 +00:00
|
|
|
CORE_LOCK();
|
2017-04-09 19:55:06 +00:00
|
|
|
Sdb *db = sdb_ns_path(core_->sdb, path.toUtf8().constData(), 0);
|
|
|
|
if (db)
|
|
|
|
{
|
2017-03-30 21:49:51 +00:00
|
|
|
const char *val = sdb_const_get(db, key.toUtf8().constData(), 0);
|
2017-03-29 10:18:37 +00:00
|
|
|
if (val && *val)
|
2017-03-30 21:49:51 +00:00
|
|
|
return val;
|
2017-03-29 10:18:37 +00:00
|
|
|
}
|
2017-04-09 19:55:06 +00:00
|
|
|
return QString("");
|
2017-03-29 10:18:37 +00:00
|
|
|
}
|
|
|
|
|
2017-09-25 12:55:41 +00:00
|
|
|
bool CutterCore::sdbSet(QString path, QString key, QString val)
|
2017-04-09 19:55:06 +00:00
|
|
|
{
|
2017-04-09 17:12:36 +00:00
|
|
|
CORE_LOCK();
|
2017-04-09 19:55:06 +00:00
|
|
|
Sdb *db = sdb_ns_path(core_->sdb, path.toUtf8().constData(), 1);
|
2017-03-29 10:18:37 +00:00
|
|
|
if (!db) return false;
|
2017-04-09 19:55:06 +00:00
|
|
|
return sdb_set(db, key.toUtf8().constData(), val.toUtf8().constData(), 0);
|
2017-03-29 10:18:37 +00:00
|
|
|
}
|
|
|
|
|
2017-09-25 12:55:41 +00:00
|
|
|
CutterCore::~CutterCore()
|
2017-04-09 19:55:06 +00:00
|
|
|
{
|
2017-04-09 17:12:36 +00:00
|
|
|
r_core_free(this->core_);
|
|
|
|
r_cons_free();
|
2017-03-29 10:18:37 +00:00
|
|
|
}
|
|
|
|
|
2017-09-25 12:55:41 +00:00
|
|
|
QString CutterCore::sanitizeStringForCommand(QString s)
|
2017-07-11 11:05:42 +00:00
|
|
|
{
|
|
|
|
static const QRegExp regexp(";|@");
|
|
|
|
return s.replace(regexp, "_");
|
|
|
|
}
|
|
|
|
|
2018-01-27 13:11:30 +00:00
|
|
|
/**
|
|
|
|
* @brief CutterCore::cmd send a command to radare2
|
|
|
|
* @param str the command you want to execute
|
|
|
|
* Note that if you want to seek to an address, you should use CutterCore::seek
|
|
|
|
* @return command output
|
|
|
|
*/
|
2017-09-25 12:55:41 +00:00
|
|
|
QString CutterCore::cmd(const QString &str)
|
2017-04-09 19:55:06 +00:00
|
|
|
{
|
2017-04-09 17:12:36 +00:00
|
|
|
CORE_LOCK();
|
2017-05-13 18:09:36 +00:00
|
|
|
|
2017-10-09 18:08:35 +00:00
|
|
|
RVA offset = core_->offset;
|
2017-03-30 21:49:51 +00:00
|
|
|
QByteArray cmd = str.toUtf8();
|
2017-04-09 19:55:06 +00:00
|
|
|
char *res = r_core_cmd_str(this->core_, cmd.constData());
|
2017-03-30 21:49:51 +00:00
|
|
|
QString o = QString(res ? res : "");
|
2017-03-30 03:07:34 +00:00
|
|
|
r_mem_free(res);
|
2017-11-03 17:22:54 +00:00
|
|
|
if (offset != core_->offset)
|
|
|
|
{
|
2017-10-09 18:08:35 +00:00
|
|
|
emit seekChanged(core_->offset);
|
2017-11-28 10:34:47 +00:00
|
|
|
|
2018-01-27 10:40:26 +00:00
|
|
|
// Switch from graph to disassembly if there is no function
|
2017-11-28 11:03:36 +00:00
|
|
|
if (this->cmd("afi.").trimmed().isEmpty() && memoryWidgetPriority == MemoryWidgetType::Graph)
|
2017-11-28 10:34:47 +00:00
|
|
|
{
|
|
|
|
memoryWidgetPriority = MemoryWidgetType::Disassembly;
|
|
|
|
}
|
|
|
|
|
2017-11-04 11:46:29 +00:00
|
|
|
triggerRaisePrioritizedMemoryWidget();
|
2017-10-09 18:08:35 +00:00
|
|
|
}
|
2017-03-29 10:18:37 +00:00
|
|
|
return o;
|
|
|
|
}
|
|
|
|
|
2017-12-20 22:50:26 +00:00
|
|
|
QString CutterCore::cmdRaw(const QString &str)
|
|
|
|
{
|
|
|
|
QString cmdStr = str;
|
|
|
|
cmdStr.replace('\"', "\\\"");
|
|
|
|
return cmd("\"" + cmdStr + "\"");
|
|
|
|
}
|
|
|
|
|
2017-09-25 12:55:41 +00:00
|
|
|
QJsonDocument CutterCore::cmdj(const QString &str)
|
2017-04-18 08:33:35 +00:00
|
|
|
{
|
|
|
|
CORE_LOCK();
|
|
|
|
QByteArray cmd = str.toUtf8();
|
2017-04-28 13:09:40 +00:00
|
|
|
|
2017-04-18 08:33:35 +00:00
|
|
|
char *res = r_core_cmd_str(this->core_, cmd.constData());
|
2017-04-28 13:09:40 +00:00
|
|
|
|
|
|
|
QString resString = QString(res);
|
|
|
|
|
2017-11-25 14:15:58 +00:00
|
|
|
if (resString.isEmpty())
|
|
|
|
{
|
|
|
|
r_mem_free(res);
|
|
|
|
return QJsonDocument();
|
|
|
|
}
|
|
|
|
|
2017-04-28 13:09:40 +00:00
|
|
|
QJsonParseError jsonError;
|
|
|
|
QJsonDocument doc = res ? QJsonDocument::fromJson(resString.toUtf8(), &jsonError) : QJsonDocument();
|
|
|
|
|
2017-04-28 13:38:01 +00:00
|
|
|
if (jsonError.error != QJsonParseError::NoError)
|
2017-04-28 13:09:40 +00:00
|
|
|
{
|
2017-12-24 14:08:54 +00:00
|
|
|
eprintf("Failed to parse JSON for command \"%s\": %s\n", str.toLocal8Bit().constData(), jsonError.errorString().toLocal8Bit().constData());
|
2017-04-28 13:09:40 +00:00
|
|
|
eprintf("%s\n", resString.toLocal8Bit().constData());
|
|
|
|
}
|
|
|
|
|
2017-04-18 08:33:35 +00:00
|
|
|
r_mem_free(res);
|
|
|
|
return doc;
|
|
|
|
}
|
|
|
|
|
2018-02-27 10:20:48 +00:00
|
|
|
bool CutterCore::loadFile(QString path, uint64_t loadaddr, uint64_t mapaddr, int perms, int va, int idx, bool loadbin, const QString &forceBinPlugin)
|
2017-04-09 19:55:06 +00:00
|
|
|
{
|
2017-10-01 18:08:12 +00:00
|
|
|
Q_UNUSED(loadaddr);
|
|
|
|
Q_UNUSED(idx);
|
2017-04-09 17:09:35 +00:00
|
|
|
|
2017-04-09 17:12:36 +00:00
|
|
|
CORE_LOCK();
|
2017-03-29 10:18:37 +00:00
|
|
|
RCoreFile *f;
|
2017-04-09 19:55:06 +00:00
|
|
|
if (va == 0 || va == 2)
|
|
|
|
r_config_set_i(core_->config, "io.va", va);
|
2017-11-25 13:21:01 +00:00
|
|
|
|
2018-02-27 10:20:48 +00:00
|
|
|
f = r_core_file_open(core_, path.toUtf8().constData(), perms, mapaddr);
|
2017-04-09 19:55:06 +00:00
|
|
|
if (!f)
|
|
|
|
{
|
|
|
|
eprintf("r_core_file_open failed\n");
|
2017-03-29 10:18:37 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2017-09-29 11:32:53 +00:00
|
|
|
if (!forceBinPlugin.isNull())
|
|
|
|
{
|
|
|
|
r_bin_force_plugin(r_core_get_bin(core_), forceBinPlugin.toUtf8().constData());
|
|
|
|
}
|
|
|
|
|
2017-04-09 19:55:06 +00:00
|
|
|
if (loadbin)
|
|
|
|
{
|
|
|
|
if (va == 1)
|
|
|
|
{
|
2017-11-25 14:17:44 +00:00
|
|
|
if (!r_core_bin_load(core_, path.toUtf8().constData(), UT64_MAX))
|
2017-04-09 19:55:06 +00:00
|
|
|
{
|
|
|
|
eprintf("CANNOT GET RBIN INFO\n");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2017-11-25 14:17:44 +00:00
|
|
|
if (!r_core_bin_load(core_, path.toUtf8().constData(), UT64_MAX))
|
2017-04-09 19:55:06 +00:00
|
|
|
{
|
|
|
|
eprintf("CANNOT GET RBIN INFO\n");
|
2017-03-29 10:18:37 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#if HAVE_MULTIPLE_RBIN_FILES_INSIDE_SELECT_WHICH_ONE
|
2017-04-13 15:01:18 +00:00
|
|
|
if (!r_core_file_open(core, path.toUtf8(), R_IO_READ | (rw ? R_IO_WRITE : 0, mapaddr)))
|
2017-04-09 19:55:06 +00:00
|
|
|
{
|
|
|
|
eprintf("Cannot open file\n");
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2017-03-29 10:18:37 +00:00
|
|
|
// load RBin information
|
|
|
|
// XXX only for sub-bins
|
2017-04-09 19:55:06 +00:00
|
|
|
r_core_bin_load(core, path.toUtf8(), loadaddr);
|
|
|
|
r_bin_select_idx(core_->bin, NULL, idx);
|
2017-03-29 10:18:37 +00:00
|
|
|
}
|
|
|
|
#endif
|
2017-04-09 19:55:06 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2017-03-29 10:18:37 +00:00
|
|
|
// Not loading RBin info coz va = false
|
|
|
|
}
|
2017-05-03 09:09:57 +00:00
|
|
|
|
2018-03-01 12:16:23 +00:00
|
|
|
auto iod = core_->io ? core_->io->desc : NULL;
|
|
|
|
auto debug = core_->file && iod && (core_->file->fd == iod->fd) && iod->plugin && \
|
|
|
|
iod->plugin->isdbg;
|
|
|
|
|
|
|
|
if (!debug && r_flag_get (core_->flags, "entry0")) {
|
|
|
|
r_core_cmd0 (core_, "s entry0");
|
|
|
|
}
|
|
|
|
|
|
|
|
if (perms & R_IO_WRITE) {
|
|
|
|
r_core_cmd0 (core_, "omfg+w");
|
|
|
|
}
|
|
|
|
|
2017-05-03 09:09:57 +00:00
|
|
|
setDefaultCPU();
|
|
|
|
|
2017-04-09 17:12:36 +00:00
|
|
|
r_core_hash_load(core_, path.toUtf8().constData());
|
2017-04-09 19:55:06 +00:00
|
|
|
fflush(stdout);
|
2017-03-29 10:18:37 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2017-09-25 12:55:41 +00:00
|
|
|
void CutterCore::analyze(int level, QList<QString> advanced)
|
2017-04-09 19:55:06 +00:00
|
|
|
{
|
2017-04-09 17:12:36 +00:00
|
|
|
CORE_LOCK();
|
2017-04-09 19:55:06 +00:00
|
|
|
/*
|
|
|
|
* Levels
|
2018-01-27 10:40:26 +00:00
|
|
|
* Level 1: aaa
|
|
|
|
* Level 2: aaaa
|
2017-04-09 19:55:06 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
if (level == 1)
|
|
|
|
{
|
2017-07-24 11:05:28 +00:00
|
|
|
r_core_cmd0(core_, "aaa");
|
2017-04-09 19:55:06 +00:00
|
|
|
}
|
|
|
|
else if (level == 2)
|
|
|
|
{
|
2017-07-24 11:05:28 +00:00
|
|
|
r_core_cmd0(core_, "aaaa");
|
2017-04-09 19:55:06 +00:00
|
|
|
}
|
|
|
|
else if (level == 3)
|
|
|
|
{
|
2017-09-27 20:23:18 +00:00
|
|
|
foreach (QString option, advanced)
|
|
|
|
{
|
2017-07-24 11:05:28 +00:00
|
|
|
r_core_cmd0(core_, option.toStdString().c_str());
|
|
|
|
}
|
2017-03-29 10:18:37 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-12-20 22:50:26 +00:00
|
|
|
void CutterCore::renameFunction(const QString &oldName, const QString &newName)
|
2017-04-09 19:55:06 +00:00
|
|
|
{
|
2017-12-20 22:50:26 +00:00
|
|
|
cmdRaw("afn " + newName + " " + oldName);
|
|
|
|
emit functionRenamed(oldName, newName);
|
2017-11-27 08:22:52 +00:00
|
|
|
}
|
|
|
|
|
2017-12-11 13:07:12 +00:00
|
|
|
void CutterCore::delFunction(RVA addr)
|
|
|
|
{
|
|
|
|
cmd("af- " + RAddressString(addr));
|
|
|
|
emit functionsChanged();
|
|
|
|
}
|
|
|
|
|
2017-11-27 08:22:52 +00:00
|
|
|
void CutterCore::renameFlag(QString old_name, QString new_name)
|
|
|
|
{
|
2017-12-20 22:50:26 +00:00
|
|
|
cmdRaw("fr " + old_name + " " + new_name);
|
2017-12-03 20:23:02 +00:00
|
|
|
emit flagsChanged();
|
2017-04-28 13:09:40 +00:00
|
|
|
}
|
|
|
|
|
2017-12-11 13:07:12 +00:00
|
|
|
void CutterCore::delFlag(RVA addr)
|
|
|
|
{
|
|
|
|
cmd("f-@" + RAddressString(addr));
|
|
|
|
emit flagsChanged();
|
|
|
|
}
|
|
|
|
|
2018-02-12 20:12:13 +00:00
|
|
|
void CutterCore::editInstruction(RVA addr, const QString &inst)
|
|
|
|
{
|
2018-02-27 10:20:48 +00:00
|
|
|
cmd("wa " + inst + " @ " + RAddressString(addr));
|
2018-02-12 20:12:13 +00:00
|
|
|
emit instructionChanged(addr);
|
|
|
|
}
|
|
|
|
|
2018-03-05 14:20:55 +00:00
|
|
|
void CutterCore::nopInstruction(RVA addr)
|
|
|
|
{
|
|
|
|
cmd("wao nop @ " + RAddressString(addr));
|
|
|
|
emit instructionChanged(addr);
|
|
|
|
}
|
|
|
|
|
2018-02-12 20:12:13 +00:00
|
|
|
void CutterCore::editBytes(RVA addr, const QString &bytes)
|
|
|
|
{
|
2018-02-27 10:20:48 +00:00
|
|
|
cmd("wx " + bytes + " @ " + RAddressString(addr));
|
2018-02-12 20:12:13 +00:00
|
|
|
emit instructionChanged(addr);
|
|
|
|
}
|
|
|
|
|
2017-12-01 10:46:13 +00:00
|
|
|
void CutterCore::setComment(RVA addr, const QString &cmt)
|
2017-04-28 13:09:40 +00:00
|
|
|
{
|
2017-11-08 09:18:07 +00:00
|
|
|
cmd("CCu base64:" + cmt.toLocal8Bit().toBase64() + " @ " + QString::number(addr));
|
2017-07-11 11:05:42 +00:00
|
|
|
emit commentsChanged();
|
2017-03-29 10:18:37 +00:00
|
|
|
}
|
|
|
|
|
2017-12-11 13:07:12 +00:00
|
|
|
void CutterCore::delComment(RVA addr)
|
2017-04-09 19:55:06 +00:00
|
|
|
{
|
2017-11-02 06:48:32 +00:00
|
|
|
cmd("CC- @ " + QString::number(addr));
|
|
|
|
emit commentsChanged();
|
2017-03-29 10:18:37 +00:00
|
|
|
}
|
|
|
|
|
2017-11-28 13:13:22 +00:00
|
|
|
void CutterCore::setImmediateBase(const QString &r2BaseName, RVA offset)
|
|
|
|
{
|
|
|
|
if (offset == RVA_INVALID)
|
|
|
|
{
|
|
|
|
offset = getOffset();
|
|
|
|
}
|
|
|
|
|
|
|
|
this->cmd("ahi " + r2BaseName + " @ " + QString::number(offset));
|
|
|
|
emit instructionChanged(offset);
|
|
|
|
}
|
|
|
|
|
2018-02-12 09:48:06 +00:00
|
|
|
void CutterCore::setCurrentBits(int bits, RVA offset)
|
|
|
|
{
|
|
|
|
if (offset == RVA_INVALID)
|
|
|
|
{
|
|
|
|
offset = getOffset();
|
|
|
|
}
|
|
|
|
|
|
|
|
this->cmd("ahb " + QString::number(bits) + " @ " + QString::number(offset));
|
|
|
|
emit instructionChanged(offset);
|
|
|
|
}
|
|
|
|
|
2018-01-27 13:11:30 +00:00
|
|
|
void CutterCore::seek(ut64 offset)
|
2017-04-09 19:55:06 +00:00
|
|
|
{
|
2017-10-16 19:00:47 +00:00
|
|
|
// Slower than using the API, but the API is not complete
|
|
|
|
// which means we either have to duplicate code from radare2
|
|
|
|
// here, or refactor radare2 API.
|
|
|
|
CORE_LOCK();
|
2018-01-27 13:11:30 +00:00
|
|
|
if (offset == RVA_INVALID)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
cmd(QString("s %1").arg(offset));
|
2017-11-02 06:48:32 +00:00
|
|
|
// cmd already does emit seekChanged(core_->offset);
|
2017-03-29 10:18:37 +00:00
|
|
|
}
|
|
|
|
|
2018-01-27 13:11:30 +00:00
|
|
|
void CutterCore::seek(QString offset)
|
2017-04-09 19:55:06 +00:00
|
|
|
{
|
2018-02-02 15:56:39 +00:00
|
|
|
bool converted;
|
|
|
|
auto s = offset.toULongLong(&converted, 16);
|
|
|
|
if (!converted)
|
|
|
|
s = offset.toULongLong();
|
|
|
|
seek(s);
|
2017-03-29 10:18:37 +00:00
|
|
|
}
|
|
|
|
|
2017-10-16 19:00:47 +00:00
|
|
|
void CutterCore::seekPrev()
|
2017-10-12 19:55:15 +00:00
|
|
|
{
|
2017-10-16 19:00:47 +00:00
|
|
|
cmd("s-");
|
2017-10-12 19:55:15 +00:00
|
|
|
}
|
|
|
|
|
2017-10-16 19:00:47 +00:00
|
|
|
void CutterCore::seekNext()
|
|
|
|
{
|
|
|
|
cmd("s+");
|
|
|
|
}
|
2017-10-12 19:55:15 +00:00
|
|
|
|
2017-11-02 06:48:32 +00:00
|
|
|
RVA CutterCore::prevOpAddr(RVA startAddr, int count)
|
|
|
|
{
|
|
|
|
CORE_LOCK();
|
2017-12-17 09:58:25 +00:00
|
|
|
bool ok;
|
|
|
|
RVA offset = cmd("/O " + QString::number(count) + " @ " + QString::number(startAddr)).toULongLong(&ok, 16);
|
|
|
|
return ok ? offset : startAddr - count;
|
2017-11-02 06:48:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
RVA CutterCore::nextOpAddr(RVA startAddr, int count)
|
|
|
|
{
|
|
|
|
CORE_LOCK();
|
|
|
|
|
2017-12-16 13:01:58 +00:00
|
|
|
QJsonArray array = Core()->cmdj("pdj " + QString::number(count+1) + "@" + QString::number(startAddr)).array();
|
2017-11-02 06:48:32 +00:00
|
|
|
if (array.isEmpty())
|
|
|
|
{
|
|
|
|
return startAddr + 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
QJsonValue instValue = array.last();
|
|
|
|
if (!instValue.isObject())
|
|
|
|
{
|
|
|
|
return startAddr + 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool ok;
|
|
|
|
RVA offset = instValue.toObject()["offset"].toVariant().toULongLong(&ok);
|
|
|
|
if (!ok)
|
|
|
|
{
|
|
|
|
return startAddr + 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return offset;
|
|
|
|
}
|
|
|
|
|
2017-10-16 19:00:47 +00:00
|
|
|
RVA CutterCore::getOffset()
|
|
|
|
{
|
|
|
|
return core_->offset;
|
|
|
|
}
|
2017-09-27 20:23:18 +00:00
|
|
|
|
2017-09-25 12:55:41 +00:00
|
|
|
bool CutterCore::tryFile(QString path, bool rw)
|
2017-04-09 19:55:06 +00:00
|
|
|
{
|
2017-04-09 17:12:36 +00:00
|
|
|
CORE_LOCK();
|
2017-03-29 10:18:37 +00:00
|
|
|
RCoreFile *cf;
|
|
|
|
int flags = R_IO_READ;
|
|
|
|
if (rw) flags |= R_IO_WRITE;
|
2017-04-09 19:55:06 +00:00
|
|
|
cf = r_core_file_open(this->core_, path.toUtf8().constData(), flags, 0LL);
|
|
|
|
if (!cf)
|
|
|
|
{
|
2017-03-29 10:18:37 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2017-11-25 13:21:01 +00:00
|
|
|
r_core_file_close (this->core_, cf);
|
2017-03-29 10:18:37 +00:00
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2017-09-25 12:55:41 +00:00
|
|
|
ut64 CutterCore::math(const QString &expr)
|
2017-04-09 19:55:06 +00:00
|
|
|
{
|
2017-04-09 17:12:36 +00:00
|
|
|
CORE_LOCK();
|
2017-04-09 19:55:06 +00:00
|
|
|
return r_num_math(this->core_ ? this->core_->num : NULL, expr.toUtf8().constData());
|
2017-03-29 10:18:37 +00:00
|
|
|
}
|
|
|
|
|
2017-09-25 12:55:41 +00:00
|
|
|
QString CutterCore::itoa(ut64 num, int rdx)
|
2017-04-09 19:55:06 +00:00
|
|
|
{
|
2017-03-29 10:18:37 +00:00
|
|
|
return QString::number(num, rdx);
|
|
|
|
}
|
|
|
|
|
2017-10-01 14:36:40 +00:00
|
|
|
void CutterCore::setConfig(const QString &k, const QString &v)
|
2017-04-09 19:55:06 +00:00
|
|
|
{
|
2017-04-09 17:12:36 +00:00
|
|
|
CORE_LOCK();
|
2017-10-01 14:36:40 +00:00
|
|
|
r_config_set(core_->config, k.toUtf8().constData(), v.toUtf8().constData());
|
2017-03-29 10:18:37 +00:00
|
|
|
}
|
|
|
|
|
2017-10-01 14:36:40 +00:00
|
|
|
void CutterCore::setConfig(const QString &k, int v)
|
2017-04-09 19:55:06 +00:00
|
|
|
{
|
2017-04-09 17:12:36 +00:00
|
|
|
CORE_LOCK();
|
2017-10-01 14:36:40 +00:00
|
|
|
r_config_set_i(core_->config, k.toUtf8().constData(), static_cast<const unsigned long long int>(v));
|
|
|
|
}
|
|
|
|
|
|
|
|
void CutterCore::setConfig(const QString &k, bool v)
|
|
|
|
{
|
|
|
|
CORE_LOCK();
|
|
|
|
r_config_set_i(core_->config, k.toUtf8().constData(), v ? 1 : 0);
|
2017-03-29 10:18:37 +00:00
|
|
|
}
|
|
|
|
|
2017-09-25 12:55:41 +00:00
|
|
|
int CutterCore::getConfigi(const QString &k)
|
2017-08-31 17:43:46 +00:00
|
|
|
{
|
|
|
|
CORE_LOCK();
|
|
|
|
QByteArray key = k.toUtf8();
|
2017-10-01 14:36:40 +00:00
|
|
|
return static_cast<int>(r_config_get_i(core_->config, key.constData()));
|
|
|
|
}
|
|
|
|
|
|
|
|
bool CutterCore::getConfigb(const QString &k)
|
|
|
|
{
|
|
|
|
CORE_LOCK();
|
|
|
|
return r_config_get_i(core_->config, k.toUtf8().constData()) != 0;
|
|
|
|
}
|
|
|
|
|
2017-11-19 12:56:10 +00:00
|
|
|
void CutterCore::triggerRefreshAll()
|
|
|
|
{
|
|
|
|
emit refreshAll();
|
|
|
|
}
|
|
|
|
|
2017-10-01 14:36:40 +00:00
|
|
|
void CutterCore::triggerAsmOptionsChanged()
|
|
|
|
{
|
|
|
|
emit asmOptionsChanged();
|
|
|
|
}
|
|
|
|
|
2017-12-19 16:13:44 +00:00
|
|
|
void CutterCore::triggerGraphOptionsChanged()
|
|
|
|
{
|
|
|
|
emit graphOptionsChanged();
|
|
|
|
}
|
|
|
|
|
2017-10-01 14:36:40 +00:00
|
|
|
void CutterCore::resetDefaultAsmOptions()
|
|
|
|
{
|
2017-10-16 19:00:47 +00:00
|
|
|
// TODO Merge with Configuration.cpp
|
2017-10-14 09:35:49 +00:00
|
|
|
setConfig("asm.esil", Config()->getAsmESIL());
|
|
|
|
setConfig("asm.pseudo", Config()->getAsmPseudo());
|
|
|
|
setConfig("asm.offset", Config()->getAsmOffset());
|
|
|
|
setConfig("asm.describe", Config()->getAsmDescribe());
|
|
|
|
setConfig("asm.stackptr", Config()->getAsmStackPointer());
|
2018-01-31 08:01:16 +00:00
|
|
|
setConfig("asm.slow", Config()->getAsmSlow());
|
2018-01-28 22:28:25 +00:00
|
|
|
setConfig("asm.lines", Config()->getAsmLines());
|
2018-02-04 19:34:52 +00:00
|
|
|
setConfig("asm.fcnlines", Config()->getAsmFcnLines());
|
2018-01-31 08:01:16 +00:00
|
|
|
setConfig("asm.emu", Config()->getAsmEmu());
|
2018-02-27 22:04:06 +00:00
|
|
|
setConfig("asm.cmt.right", Config()->getAsmCmtRight());
|
2018-01-31 08:01:16 +00:00
|
|
|
setConfig("asm.varsum", Config()->getAsmVarSum());
|
2017-10-14 09:35:49 +00:00
|
|
|
setConfig("asm.bytes", Config()->getAsmBytes());
|
2018-03-10 06:26:58 +00:00
|
|
|
setConfig("asm.size", Config()->getAsmSize());
|
2017-10-14 09:35:49 +00:00
|
|
|
setConfig("asm.bytespace", Config()->getAsmBytespace());
|
|
|
|
setConfig("asm.lbytes", Config()->getAsmLBytes());
|
2018-02-01 09:01:09 +00:00
|
|
|
setConfig("asm.nbytes", Config()->getAsmNBytes());
|
2017-10-14 09:35:49 +00:00
|
|
|
setConfig("asm.syntax", Config()->getAsmSyntax());
|
|
|
|
setConfig("asm.ucase", Config()->getAsmUppercase());
|
|
|
|
setConfig("asm.bbline", Config()->getAsmBBLine());
|
|
|
|
setConfig("asm.capitalize", Config()->getAsmCapitalize());
|
|
|
|
setConfig("asm.varsub", Config()->getAsmVarsub());
|
|
|
|
setConfig("asm.varsub_only", Config()->getAsmVarsubOnly());
|
2017-10-01 14:36:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void CutterCore::saveDefaultAsmOptions()
|
|
|
|
{
|
2017-10-14 09:35:49 +00:00
|
|
|
Config()->setAsmESIL(getConfigb("asm.esil"));
|
|
|
|
Config()->setAsmPseudo(getConfigb("asm.pseudo"));
|
|
|
|
Config()->setAsmOffset(getConfigb("asm.offset"));
|
|
|
|
Config()->setAsmDescribe(getConfigb("asm.describe"));
|
|
|
|
Config()->setAsmStackPointer(getConfigb("asm.stackptr"));
|
2018-01-31 08:01:16 +00:00
|
|
|
Config()->setAsmSlow(getConfigb("asm.slow"));
|
2018-01-28 22:28:25 +00:00
|
|
|
Config()->setAsmLines(getConfigb("asm.lines"));
|
2018-02-04 19:34:52 +00:00
|
|
|
Config()->setAsmFcnLines(getConfigb("asm.fcnlines"));
|
2018-01-31 08:01:16 +00:00
|
|
|
Config()->setAsmEmu(getConfigb("asm.emu"));
|
2018-02-27 22:04:06 +00:00
|
|
|
Config()->setAsmCmtRight(getConfigb("asm.cmt.right"));
|
2018-01-31 08:01:16 +00:00
|
|
|
Config()->setAsmVarSum(getConfigb("asm.varsum"));
|
2017-10-14 09:35:49 +00:00
|
|
|
Config()->setAsmBytes(getConfigb("asm.bytes"));
|
2018-03-10 06:26:58 +00:00
|
|
|
Config()->setAsmSize(getConfigb("asm.size"));
|
2017-10-14 09:35:49 +00:00
|
|
|
Config()->setAsmBytespace(getConfigb("asm.bytespace"));
|
|
|
|
Config()->setAsmLBytes(getConfigb("asm.lbytes"));
|
2018-02-01 09:01:09 +00:00
|
|
|
Config()->setAsmNBytes(getConfigi("asm.nbytes"));
|
2017-10-14 09:35:49 +00:00
|
|
|
Config()->setAsmSyntax(getConfig("asm.syntax"));
|
|
|
|
Config()->setAsmUppercase(getConfigb("asm.ucase"));
|
|
|
|
Config()->setAsmBBLine(getConfigb("asm.bbline"));
|
|
|
|
Config()->setAsmCapitalize(getConfigb("asm.capitalize"));
|
|
|
|
Config()->setAsmVarsub(getConfigb("asm.varsub"));
|
|
|
|
Config()->setAsmVarsubOnly(getConfigb("asm.varsub_only"));
|
2018-01-31 08:01:16 +00:00
|
|
|
Config()->setAsmTabs(getConfigi("asm.tabs"));
|
2017-08-31 17:43:46 +00:00
|
|
|
}
|
|
|
|
|
2017-09-25 12:55:41 +00:00
|
|
|
QString CutterCore::getConfig(const QString &k)
|
2017-09-02 08:17:48 +00:00
|
|
|
{
|
|
|
|
CORE_LOCK();
|
|
|
|
QByteArray key = k.toUtf8();
|
|
|
|
return QString(r_config_get(core_->config, key.constData()));
|
|
|
|
}
|
|
|
|
|
2017-09-25 12:55:41 +00:00
|
|
|
void CutterCore::setCPU(QString arch, QString cpu, int bits, bool temporary)
|
2017-04-09 19:55:06 +00:00
|
|
|
{
|
2017-10-01 14:36:40 +00:00
|
|
|
setConfig("asm.arch", arch);
|
|
|
|
setConfig("asm.cpu", cpu);
|
|
|
|
setConfig("asm.bits", bits);
|
2017-04-09 19:55:06 +00:00
|
|
|
if (!temporary)
|
|
|
|
{
|
2017-03-29 10:18:37 +00:00
|
|
|
default_arch = arch;
|
|
|
|
default_cpu = cpu;
|
|
|
|
default_bits = bits;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-01-20 10:35:31 +00:00
|
|
|
void CutterCore::setEndianness(bool big)
|
|
|
|
{
|
|
|
|
setConfig("cfg.bigendian", big);
|
|
|
|
}
|
|
|
|
|
2018-03-07 12:02:39 +00:00
|
|
|
void CutterCore::setBBSize(int size)
|
|
|
|
{
|
|
|
|
setConfig("anal.bb.maxsize", size);
|
|
|
|
}
|
|
|
|
|
2017-09-25 12:55:41 +00:00
|
|
|
void CutterCore::setDefaultCPU()
|
2017-04-09 19:55:06 +00:00
|
|
|
{
|
2017-05-03 09:09:57 +00:00
|
|
|
if (!default_arch.isEmpty())
|
2017-10-01 14:36:40 +00:00
|
|
|
setConfig("asm.arch", default_arch);
|
2017-05-03 09:09:57 +00:00
|
|
|
if (!default_cpu.isEmpty())
|
2017-10-01 14:36:40 +00:00
|
|
|
setConfig("asm.cpu", default_cpu);
|
2017-05-03 09:09:57 +00:00
|
|
|
if (default_bits)
|
2017-10-01 14:36:40 +00:00
|
|
|
setConfig("asm.bits", QString::number(default_bits));
|
2017-03-29 10:18:37 +00:00
|
|
|
}
|
|
|
|
|
2017-09-25 12:55:41 +00:00
|
|
|
QString CutterCore::assemble(const QString &code)
|
2017-04-09 19:55:06 +00:00
|
|
|
{
|
2017-04-09 17:12:36 +00:00
|
|
|
CORE_LOCK();
|
2017-04-09 19:55:06 +00:00
|
|
|
RAsmCode *ac = r_asm_massemble(core_->assembler, code.toUtf8().constData());
|
2017-04-09 02:49:16 +00:00
|
|
|
QString hex(ac != nullptr ? ac->buf_hex : "");
|
2017-04-09 19:55:06 +00:00
|
|
|
r_asm_code_free(ac);
|
2017-03-29 10:18:37 +00:00
|
|
|
return hex;
|
|
|
|
}
|
|
|
|
|
2017-09-25 12:55:41 +00:00
|
|
|
QString CutterCore::disassemble(const QString &hex)
|
2017-04-09 19:55:06 +00:00
|
|
|
{
|
2017-04-09 17:12:36 +00:00
|
|
|
CORE_LOCK();
|
|
|
|
RAsmCode *ac = r_asm_mdisassemble_hexstr(core_->assembler, hex.toUtf8().constData());
|
2017-04-09 19:55:06 +00:00
|
|
|
QString code = QString(ac != nullptr ? ac->buf_asm : "");
|
|
|
|
r_asm_code_free(ac);
|
2017-03-29 10:18:37 +00:00
|
|
|
return code;
|
|
|
|
}
|
|
|
|
|
2017-09-25 12:55:41 +00:00
|
|
|
QString CutterCore::disassembleSingleInstruction(RVA addr)
|
2017-06-07 15:48:36 +00:00
|
|
|
{
|
|
|
|
return cmd("pi 1@" + QString::number(addr)).simplified();
|
|
|
|
}
|
|
|
|
|
2017-09-25 12:55:41 +00:00
|
|
|
RAnalFunction *CutterCore::functionAt(ut64 addr)
|
2017-04-09 19:55:06 +00:00
|
|
|
{
|
2017-04-09 17:12:36 +00:00
|
|
|
CORE_LOCK();
|
|
|
|
//return r_anal_fcn_find (core_->anal, addr, addr);
|
2017-04-09 19:55:06 +00:00
|
|
|
return r_anal_get_fcn_in(core_->anal, addr, 0);
|
2017-03-29 10:18:37 +00:00
|
|
|
}
|
|
|
|
|
2017-09-25 12:55:41 +00:00
|
|
|
QString CutterCore::cmdFunctionAt(QString addr)
|
2017-04-09 19:55:06 +00:00
|
|
|
{
|
2017-03-29 10:18:37 +00:00
|
|
|
QString ret;
|
|
|
|
//afi~name:1[1] @ 0x08048e44
|
|
|
|
//ret = cmd("afi~name[1] @ " + addr);
|
2017-04-28 13:09:40 +00:00
|
|
|
ret = cmd(QString("fd @ ") + addr + "~[0]");
|
2017-03-29 10:18:37 +00:00
|
|
|
return ret.trimmed();
|
|
|
|
}
|
|
|
|
|
2017-09-25 12:55:41 +00:00
|
|
|
QString CutterCore::cmdFunctionAt(RVA addr)
|
2017-04-28 13:09:40 +00:00
|
|
|
{
|
|
|
|
return cmdFunctionAt(QString::number(addr));
|
|
|
|
}
|
|
|
|
|
2017-12-10 20:40:15 +00:00
|
|
|
QString CutterCore::createFunctionAt(RVA addr, QString name)
|
|
|
|
{
|
|
|
|
name.remove(QRegExp("[^a-zA-Z0-9_]"));
|
|
|
|
QString command = "af " + name + " " + RAddressString(addr);
|
|
|
|
QString ret = cmd(command);
|
2017-12-11 13:07:12 +00:00
|
|
|
emit functionsChanged();
|
2017-12-10 20:40:15 +00:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
void CutterCore::markString(RVA addr)
|
|
|
|
{
|
|
|
|
cmd("Cs @" + RAddressString(addr));
|
|
|
|
}
|
|
|
|
|
2017-09-25 12:55:41 +00:00
|
|
|
int CutterCore::get_size()
|
2017-03-29 10:18:37 +00:00
|
|
|
{
|
2017-04-09 17:12:36 +00:00
|
|
|
CORE_LOCK();
|
|
|
|
RBinObject *obj = r_bin_get_object(core_->bin);
|
2017-03-29 10:18:37 +00:00
|
|
|
//return obj->size;
|
2017-04-09 02:49:16 +00:00
|
|
|
return obj != nullptr ? obj->obj_size : 0;
|
2017-03-29 10:18:37 +00:00
|
|
|
}
|
|
|
|
|
2017-09-25 12:55:41 +00:00
|
|
|
ulong CutterCore::get_baddr()
|
2017-03-29 10:18:37 +00:00
|
|
|
{
|
2017-04-09 17:12:36 +00:00
|
|
|
CORE_LOCK();
|
|
|
|
ulong baddr = r_bin_get_baddr(core_->bin);
|
2017-03-29 10:18:37 +00:00
|
|
|
return baddr;
|
|
|
|
}
|
|
|
|
|
2017-09-25 12:55:41 +00:00
|
|
|
QList<QList<QString>> CutterCore::get_exec_sections()
|
2017-03-29 10:18:37 +00:00
|
|
|
{
|
2017-04-09 19:55:06 +00:00
|
|
|
QList<QList<QString>> ret;
|
2017-03-29 10:18:37 +00:00
|
|
|
|
2017-04-09 19:55:06 +00:00
|
|
|
QString text = cmd("S*~^S");
|
|
|
|
for (QString line : text.split("\n"))
|
|
|
|
{
|
2017-03-29 10:18:37 +00:00
|
|
|
QStringList fields = line.split(" ");
|
2017-04-09 19:55:06 +00:00
|
|
|
if (fields.length() == 7)
|
|
|
|
{
|
|
|
|
if (fields[6].contains("x"))
|
|
|
|
{
|
2017-03-29 10:18:37 +00:00
|
|
|
QList<QString> tmp = QList<QString>();
|
|
|
|
tmp << fields[2];
|
|
|
|
tmp << fields[3];
|
|
|
|
tmp << fields[5];
|
|
|
|
ret << tmp;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2017-09-25 12:55:41 +00:00
|
|
|
QString CutterCore::getOffsetInfo(QString addr)
|
2017-04-09 19:55:06 +00:00
|
|
|
{
|
2017-03-29 10:18:37 +00:00
|
|
|
return cmd("ao @ " + addr);
|
|
|
|
}
|
|
|
|
|
2017-11-28 11:56:38 +00:00
|
|
|
RVA CutterCore::getOffsetJump(RVA addr)
|
2017-04-09 19:55:06 +00:00
|
|
|
{
|
2017-11-28 11:56:38 +00:00
|
|
|
bool ok;
|
|
|
|
RVA value = cmdj("aoj @" + QString::number(addr)).array().first().toObject().value("jump").toVariant().toULongLong(&ok);
|
|
|
|
|
|
|
|
if (!ok)
|
|
|
|
{
|
|
|
|
return RVA_INVALID;
|
|
|
|
}
|
|
|
|
|
|
|
|
return value;
|
2017-03-29 10:18:37 +00:00
|
|
|
}
|
|
|
|
|
2017-12-06 23:19:14 +00:00
|
|
|
QString CutterCore::getDecompiledCode(RVA addr)
|
|
|
|
{
|
|
|
|
return cmd("pdc @ " + QString::number(addr));
|
|
|
|
}
|
|
|
|
|
2017-09-25 12:55:41 +00:00
|
|
|
QString CutterCore::getDecompiledCode(QString addr)
|
2017-04-09 19:55:06 +00:00
|
|
|
{
|
2017-03-29 10:18:37 +00:00
|
|
|
return cmd("pdc @ " + addr);
|
|
|
|
}
|
|
|
|
|
2018-02-10 22:31:15 +00:00
|
|
|
QJsonDocument CutterCore::getFileInfo()
|
2017-04-09 19:55:06 +00:00
|
|
|
{
|
2018-02-10 22:31:15 +00:00
|
|
|
return cmdj("ij");
|
2017-03-29 10:18:37 +00:00
|
|
|
}
|
|
|
|
|
2017-09-25 12:55:41 +00:00
|
|
|
QStringList CutterCore::getStats()
|
2017-04-09 19:55:06 +00:00
|
|
|
{
|
2017-03-29 10:18:37 +00:00
|
|
|
QStringList stats;
|
|
|
|
cmd("fs functions");
|
|
|
|
stats << cmd("f~?").trimmed();
|
|
|
|
|
|
|
|
QString imps = cmd("ii~?").trimmed();
|
|
|
|
stats << imps;
|
|
|
|
|
|
|
|
cmd("fs symbols");
|
|
|
|
stats << cmd("f~?").trimmed();
|
|
|
|
cmd("fs strings");
|
|
|
|
stats << cmd("f~?").trimmed();
|
|
|
|
cmd("fs relocs");
|
|
|
|
stats << cmd("f~?").trimmed();
|
|
|
|
cmd("fs sections");
|
|
|
|
stats << cmd("f~?").trimmed();
|
|
|
|
cmd("fs *");
|
|
|
|
stats << cmd("f~?").trimmed();
|
|
|
|
|
|
|
|
return stats;
|
|
|
|
}
|
|
|
|
|
2017-09-25 12:55:41 +00:00
|
|
|
QString CutterCore::getSimpleGraph(QString function)
|
2017-04-09 19:55:06 +00:00
|
|
|
{
|
2017-03-29 10:18:37 +00:00
|
|
|
// New styles
|
|
|
|
QString graph = "graph [bgcolor=invis, splines=polyline];";
|
|
|
|
QString node = "node [style=\"filled\" fillcolor=\"#4183D7\" shape=box fontname=\"Courier\" fontsize=\"8\" color=\"#4183D7\" fontcolor=\"white\"];";
|
|
|
|
QString arrow = "edge [arrowhead=\"normal\";]";
|
|
|
|
|
|
|
|
// Old styles
|
|
|
|
QString old_graph = "graph [bgcolor=white fontsize=8 fontname=\"Courier\"];";
|
|
|
|
//QString old_node = "node [color=lightgray, style=filled shape=box];";
|
|
|
|
QString old_node = "node [fillcolor=gray style=filled shape=box];";
|
|
|
|
QString old_arrow = "edge [arrowhead=\"vee\"];";
|
|
|
|
|
|
|
|
QString dot = cmd("aga @ " + function).trimmed();
|
|
|
|
dot.replace(old_graph, graph);
|
|
|
|
dot.replace(old_node, node);
|
|
|
|
dot.replace(old_arrow, arrow);
|
|
|
|
dot.replace("fillcolor=blue", "fillcolor=\"#EC644B\", color=\"#EC644B\"");
|
|
|
|
|
|
|
|
return dot;
|
|
|
|
}
|
|
|
|
|
2017-09-25 12:55:41 +00:00
|
|
|
void CutterCore::getOpcodes()
|
2017-04-09 19:55:06 +00:00
|
|
|
{
|
2017-03-29 10:18:37 +00:00
|
|
|
QString opcodes = cmd("?O");
|
|
|
|
this->opcodes = opcodes.split("\n");
|
|
|
|
// Remove the last empty element
|
|
|
|
this->opcodes.removeLast();
|
|
|
|
QString registers = cmd("drp~[1]");
|
|
|
|
this->regs = registers.split("\n");
|
|
|
|
this->regs.removeLast();
|
|
|
|
}
|
2017-03-30 16:47:50 +00:00
|
|
|
|
2017-09-25 12:55:41 +00:00
|
|
|
void CutterCore::setSettings()
|
2017-04-09 19:55:06 +00:00
|
|
|
{
|
2017-10-01 14:36:40 +00:00
|
|
|
setConfig("scr.interactive", false);
|
2018-02-02 10:56:07 +00:00
|
|
|
|
2017-10-01 14:36:40 +00:00
|
|
|
setConfig("hex.pairs", false);
|
|
|
|
setConfig("asm.cmtcol", 70);
|
|
|
|
setConfig("asm.xrefs", false);
|
|
|
|
|
|
|
|
setConfig("asm.tabsonce", true);
|
|
|
|
setConfig("asm.tabsoff", 5);
|
|
|
|
setConfig("asm.midflags", 2);
|
2017-11-28 13:24:35 +00:00
|
|
|
|
2018-03-07 07:52:13 +00:00
|
|
|
setConfig("anal.hasnext", false);
|
2017-10-01 14:36:40 +00:00
|
|
|
setConfig("asm.lines.call", false);
|
|
|
|
setConfig("asm.flgoff", true);
|
|
|
|
setConfig("anal.autoname", true);
|
2017-08-31 17:43:46 +00:00
|
|
|
|
2017-03-30 16:47:50 +00:00
|
|
|
// Fucking pancake xD
|
2017-10-01 14:36:40 +00:00
|
|
|
setConfig("cfg.fortunes.tts", false);
|
2017-03-30 16:47:50 +00:00
|
|
|
|
|
|
|
// Used by the HTML5 graph
|
2017-10-01 14:36:40 +00:00
|
|
|
setConfig("http.cors", true);
|
|
|
|
setConfig("http.sandbox", false);
|
2017-03-30 16:47:50 +00:00
|
|
|
|
2017-10-22 10:21:44 +00:00
|
|
|
// Colors
|
2018-02-26 22:25:23 +00:00
|
|
|
setConfig("scr.color", COLOR_MODE_DISABLED);
|
2018-03-08 13:02:34 +00:00
|
|
|
|
|
|
|
// Don't show hits
|
|
|
|
setConfig("search.flags", false);
|
2017-03-30 16:47:50 +00:00
|
|
|
}
|
2017-04-28 13:09:40 +00:00
|
|
|
|
2017-09-25 12:55:41 +00:00
|
|
|
QList<RVA> CutterCore::getSeekHistory()
|
2017-04-28 13:09:40 +00:00
|
|
|
{
|
|
|
|
CORE_LOCK();
|
|
|
|
QList<RVA> ret;
|
|
|
|
|
|
|
|
QJsonArray jsonArray = cmdj("sj").array();
|
2017-04-28 13:38:01 +00:00
|
|
|
foreach (QJsonValue value, jsonArray)
|
2017-04-28 13:09:40 +00:00
|
|
|
ret << value.toVariant().toULongLong();
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2017-09-25 12:55:41 +00:00
|
|
|
QStringList CutterCore::getAsmPluginNames()
|
2017-05-03 09:09:57 +00:00
|
|
|
{
|
|
|
|
CORE_LOCK();
|
|
|
|
RListIter *it;
|
|
|
|
QStringList ret;
|
|
|
|
|
|
|
|
RAsmPlugin *ap;
|
2017-09-25 17:51:49 +00:00
|
|
|
CutterRListForeach(core_->assembler->plugins, it, RAsmPlugin, ap)
|
2017-05-03 09:09:57 +00:00
|
|
|
{
|
|
|
|
ret << ap->name;
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2017-09-25 12:55:41 +00:00
|
|
|
QStringList CutterCore::getAnalPluginNames()
|
2017-05-03 09:09:57 +00:00
|
|
|
{
|
|
|
|
CORE_LOCK();
|
|
|
|
RListIter *it;
|
|
|
|
QStringList ret;
|
|
|
|
|
|
|
|
RAnalPlugin *ap;
|
2017-09-25 17:51:49 +00:00
|
|
|
CutterRListForeach(core_->anal->plugins, it, RAnalPlugin, ap)
|
2017-05-03 09:09:57 +00:00
|
|
|
{
|
|
|
|
ret << ap->name;
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2017-09-25 12:55:41 +00:00
|
|
|
QStringList CutterCore::getProjectNames()
|
2017-05-13 18:09:36 +00:00
|
|
|
{
|
|
|
|
CORE_LOCK();
|
|
|
|
QStringList ret;
|
|
|
|
|
|
|
|
QJsonArray jsonArray = cmdj("Plj").array();
|
2017-06-03 12:27:23 +00:00
|
|
|
for (QJsonValue value : jsonArray)
|
2017-05-13 18:09:36 +00:00
|
|
|
ret.append(value.toString());
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2017-09-29 11:32:53 +00:00
|
|
|
QList<RBinPluginDescription> CutterCore::getRBinPluginDescriptions(const QString &type)
|
|
|
|
{
|
|
|
|
QList<RBinPluginDescription> ret;
|
|
|
|
|
|
|
|
QJsonObject jsonRoot = cmdj("iLj").object();
|
|
|
|
for (const QString &key : jsonRoot.keys())
|
|
|
|
{
|
|
|
|
if (!type.isNull() && key != type)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
QJsonArray pluginArray = jsonRoot[key].toArray();
|
|
|
|
|
|
|
|
for (const auto &pluginValue : pluginArray)
|
|
|
|
{
|
|
|
|
QJsonObject pluginObject = pluginValue.toObject();
|
|
|
|
RBinPluginDescription desc;
|
|
|
|
desc.name = pluginObject["name"].toString();
|
|
|
|
desc.description = pluginObject["description"].toString();
|
|
|
|
desc.license = pluginObject["license"].toString();
|
|
|
|
desc.type = key;
|
|
|
|
ret.append(desc);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2018-03-09 15:05:40 +00:00
|
|
|
QList<RIOPluginDescription> CutterCore::getRIOPluginDescriptions()
|
|
|
|
{
|
|
|
|
QList<RIOPluginDescription> ret;
|
|
|
|
|
|
|
|
QJsonArray plugins = cmdj("oLj").object()["IO_Plugins"].toArray();
|
|
|
|
for(QJsonValueRef pluginValue : plugins)
|
|
|
|
{
|
|
|
|
QJsonObject pluginObject = pluginValue.toObject();
|
|
|
|
RIOPluginDescription plugin;
|
|
|
|
|
|
|
|
plugin.name = pluginObject["Name"].toString();
|
|
|
|
plugin.description = pluginObject["Description"].toString();
|
|
|
|
plugin.license = pluginObject["License"].toString();
|
|
|
|
plugin.permissions = pluginObject["Permissions"].toString();
|
|
|
|
|
|
|
|
ret << plugin;
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
QList<RCorePluginDescription> CutterCore::getRCorePluginDescriptions()
|
|
|
|
{
|
|
|
|
QList<RCorePluginDescription> ret;
|
|
|
|
|
|
|
|
QJsonArray plugins = cmdj("Lsj").array();
|
|
|
|
for(QJsonValueRef pluginValue : plugins)
|
|
|
|
{
|
|
|
|
QJsonObject pluginObject = pluginValue.toObject();
|
|
|
|
RCorePluginDescription plugin;
|
|
|
|
|
|
|
|
plugin.name = pluginObject["Name"].toString();
|
|
|
|
plugin.description = pluginObject["Description"].toString();
|
|
|
|
|
|
|
|
ret << plugin;
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
QStringList CutterCore::getRAsmPlugins()
|
|
|
|
{
|
|
|
|
QStringList ret;
|
|
|
|
|
|
|
|
QJsonArray plugins = cmdj("evj asm.arch").array()[0].toObject()["options"].toArray();
|
|
|
|
for(QJsonValueRef pluginValue : plugins)
|
|
|
|
ret << pluginValue.toString();
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2017-09-25 12:55:41 +00:00
|
|
|
QList<FunctionDescription> CutterCore::getAllFunctions()
|
2017-04-28 13:09:40 +00:00
|
|
|
{
|
|
|
|
CORE_LOCK();
|
|
|
|
QList<FunctionDescription> ret;
|
|
|
|
|
|
|
|
QJsonArray jsonArray = cmdj("aflj").array();
|
|
|
|
|
2017-04-28 13:38:01 +00:00
|
|
|
foreach (QJsonValue value, jsonArray)
|
2017-04-28 13:09:40 +00:00
|
|
|
{
|
|
|
|
QJsonObject jsonObject = value.toObject();
|
|
|
|
|
|
|
|
FunctionDescription function;
|
|
|
|
|
|
|
|
function.offset = (RVA)jsonObject["offset"].toVariant().toULongLong();
|
|
|
|
function.size = (RVA)jsonObject["size"].toVariant().toULongLong();
|
|
|
|
function.name = jsonObject["name"].toString();
|
|
|
|
|
|
|
|
ret << function;
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2017-09-25 12:55:41 +00:00
|
|
|
QList<ImportDescription> CutterCore::getAllImports()
|
2017-04-28 13:09:40 +00:00
|
|
|
{
|
|
|
|
CORE_LOCK();
|
|
|
|
QList<ImportDescription> ret;
|
|
|
|
|
|
|
|
QJsonArray importsArray = cmdj("iij").array();
|
|
|
|
|
2017-04-28 13:38:01 +00:00
|
|
|
foreach (QJsonValue value, importsArray)
|
2017-04-28 13:09:40 +00:00
|
|
|
{
|
|
|
|
QJsonObject importObject = value.toObject();
|
|
|
|
|
|
|
|
ImportDescription import;
|
|
|
|
|
|
|
|
import.plt = importObject["plt"].toVariant().toULongLong();
|
|
|
|
import.ordinal = importObject["ordinal"].toInt();
|
|
|
|
import.bind = importObject["bind"].toString();
|
|
|
|
import.type = importObject["type"].toString();
|
|
|
|
import.name = importObject["name"].toString();
|
|
|
|
|
|
|
|
ret << import;
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2017-09-25 12:55:41 +00:00
|
|
|
QList<ExportDescription> CutterCore::getAllExports()
|
2017-05-19 07:45:26 +00:00
|
|
|
{
|
|
|
|
CORE_LOCK();
|
|
|
|
QList<ExportDescription> ret;
|
|
|
|
|
|
|
|
QJsonArray importsArray = cmdj("iEj").array();
|
|
|
|
|
|
|
|
foreach (QJsonValue value, importsArray)
|
|
|
|
{
|
|
|
|
QJsonObject importObject = value.toObject();
|
|
|
|
|
|
|
|
ExportDescription exp;
|
|
|
|
|
|
|
|
exp.vaddr = importObject["vaddr"].toVariant().toULongLong();
|
|
|
|
exp.paddr = importObject["paddr"].toVariant().toULongLong();
|
|
|
|
exp.size = importObject["size"].toVariant().toULongLong();
|
|
|
|
exp.type = importObject["type"].toString();
|
|
|
|
exp.name = importObject["name"].toString();
|
|
|
|
exp.flag_name = importObject["flagname"].toString();
|
|
|
|
|
|
|
|
ret << exp;
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2017-09-25 12:55:41 +00:00
|
|
|
QList<SymbolDescription> CutterCore::getAllSymbols()
|
2017-04-28 13:09:40 +00:00
|
|
|
{
|
|
|
|
CORE_LOCK();
|
|
|
|
RListIter *it;
|
|
|
|
|
|
|
|
QList<SymbolDescription> ret;
|
|
|
|
|
|
|
|
RBinSymbol *bs;
|
|
|
|
if (core_ && core_->bin && core_->bin->cur && core_->bin->cur->o)
|
|
|
|
{
|
2017-09-25 17:51:49 +00:00
|
|
|
CutterRListForeach(core_->bin->cur->o->symbols, it, RBinSymbol, bs)
|
2017-04-28 13:09:40 +00:00
|
|
|
{
|
|
|
|
QString type = QString(bs->bind) + " " + QString(bs->type);
|
|
|
|
SymbolDescription symbol;
|
|
|
|
symbol.vaddr = bs->vaddr;
|
|
|
|
symbol.name = QString(bs->name);
|
|
|
|
symbol.bind = QString(bs->bind);
|
|
|
|
symbol.type = QString(bs->type);
|
|
|
|
ret << symbol;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* list entrypoints as symbols too */
|
|
|
|
int n = 0;
|
|
|
|
RBinAddr *entry;
|
2017-09-25 17:51:49 +00:00
|
|
|
CutterRListForeach(core_->bin->cur->o->entries, it, RBinAddr, entry)
|
2017-04-28 13:09:40 +00:00
|
|
|
{
|
|
|
|
SymbolDescription symbol;
|
|
|
|
symbol.vaddr = entry->vaddr;
|
|
|
|
symbol.name = QString("entry") + QString::number(n++);
|
|
|
|
symbol.bind = "";
|
|
|
|
symbol.type = "entry";
|
|
|
|
ret << symbol;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2017-09-25 12:55:41 +00:00
|
|
|
QList<CommentDescription> CutterCore::getAllComments(const QString &filterType)
|
2017-04-28 13:09:40 +00:00
|
|
|
{
|
|
|
|
CORE_LOCK();
|
|
|
|
QList<CommentDescription> ret;
|
|
|
|
|
|
|
|
QJsonArray commentsArray = cmdj("CCj").array();
|
2017-04-28 13:38:01 +00:00
|
|
|
for (QJsonValue value : commentsArray)
|
2017-04-28 13:09:40 +00:00
|
|
|
{
|
|
|
|
QJsonObject commentObject = value.toObject();
|
|
|
|
|
|
|
|
QString type = commentObject["type"].toString();
|
2017-04-28 13:38:01 +00:00
|
|
|
if (type != filterType)
|
2017-04-28 13:09:40 +00:00
|
|
|
continue;
|
|
|
|
|
|
|
|
CommentDescription comment;
|
|
|
|
comment.offset = commentObject["offset"].toVariant().toULongLong();
|
|
|
|
comment.name = commentObject["name"].toString();
|
|
|
|
|
|
|
|
ret << comment;
|
|
|
|
}
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2017-09-25 12:55:41 +00:00
|
|
|
QList<RelocDescription> CutterCore::getAllRelocs()
|
2017-04-28 13:09:40 +00:00
|
|
|
{
|
|
|
|
CORE_LOCK();
|
|
|
|
RListIter *it;
|
|
|
|
QList<RelocDescription> ret;
|
|
|
|
|
|
|
|
RBinReloc *br;
|
|
|
|
if (core_ && core_->bin && core_->bin->cur && core_->bin->cur->o)
|
|
|
|
{
|
2017-09-25 17:51:49 +00:00
|
|
|
CutterRListForeach(core_->bin->cur->o->relocs, it, RBinReloc, br)
|
2017-04-28 13:09:40 +00:00
|
|
|
{
|
|
|
|
RelocDescription reloc;
|
|
|
|
|
|
|
|
reloc.vaddr = br->vaddr;
|
|
|
|
reloc.paddr = br->paddr;
|
|
|
|
reloc.type = (br->additive ? "ADD_" : "SET_") + QString::number(br->type);
|
|
|
|
|
|
|
|
if (br->import)
|
|
|
|
reloc.name = br->import->name;
|
|
|
|
else
|
|
|
|
reloc.name = QString("reloc_%1").arg(QString::number(br->vaddr, 16));
|
|
|
|
|
|
|
|
ret << reloc;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2017-09-25 12:55:41 +00:00
|
|
|
QList<StringDescription> CutterCore::getAllStrings()
|
2017-04-28 13:09:40 +00:00
|
|
|
{
|
|
|
|
CORE_LOCK();
|
|
|
|
QList<StringDescription> ret;
|
2018-02-10 18:03:16 +00:00
|
|
|
QJsonDocument stringsDoc = cmdj("izzj");
|
2018-02-10 18:11:09 +00:00
|
|
|
QJsonObject stringsObj = stringsDoc.object();
|
|
|
|
QJsonArray stringsArray = stringsObj["strings"].toArray();
|
2018-02-10 17:50:00 +00:00
|
|
|
for (QJsonValue value : stringsArray)
|
2017-04-28 13:09:40 +00:00
|
|
|
{
|
2018-02-10 17:50:00 +00:00
|
|
|
QJsonObject stringObject = value.toObject();
|
|
|
|
|
|
|
|
StringDescription string;
|
|
|
|
string.string = QString(QByteArray::fromBase64(stringObject["string"].toVariant().toByteArray()));
|
|
|
|
string.vaddr = stringObject["vaddr"].toVariant().toULongLong();
|
|
|
|
string.type = stringObject["type"].toString();
|
|
|
|
string.size = stringObject["size"].toVariant().toUInt();
|
|
|
|
string.length = stringObject["length"].toVariant().toUInt();
|
|
|
|
|
|
|
|
ret << string;
|
2017-04-28 13:09:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
2017-04-28 13:38:01 +00:00
|
|
|
}
|
2017-05-03 09:09:57 +00:00
|
|
|
|
2017-09-25 12:55:41 +00:00
|
|
|
QList<FlagspaceDescription> CutterCore::getAllFlagspaces()
|
2017-05-03 09:09:57 +00:00
|
|
|
{
|
|
|
|
CORE_LOCK();
|
|
|
|
QList<FlagspaceDescription> ret;
|
|
|
|
|
|
|
|
QJsonArray flagspacesArray = cmdj("fsj").array();
|
|
|
|
for (QJsonValue value : flagspacesArray)
|
|
|
|
{
|
|
|
|
QJsonObject flagspaceObject = value.toObject();
|
|
|
|
|
|
|
|
FlagspaceDescription flagspace;
|
|
|
|
flagspace.name = flagspaceObject["name"].toString();
|
|
|
|
|
|
|
|
ret << flagspace;
|
|
|
|
}
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2017-09-25 12:55:41 +00:00
|
|
|
QList<FlagDescription> CutterCore::getAllFlags(QString flagspace)
|
2017-05-03 09:09:57 +00:00
|
|
|
{
|
|
|
|
CORE_LOCK();
|
|
|
|
QList<FlagDescription> ret;
|
|
|
|
|
|
|
|
if (!flagspace.isEmpty())
|
|
|
|
cmd("fs " + flagspace);
|
|
|
|
else
|
|
|
|
cmd("fs *");
|
|
|
|
|
|
|
|
QJsonArray flagsArray = cmdj("fj").array();
|
|
|
|
for (QJsonValue value : flagsArray)
|
|
|
|
{
|
|
|
|
QJsonObject flagObject = value.toObject();
|
|
|
|
|
|
|
|
FlagDescription flag;
|
|
|
|
flag.offset = flagObject["offset"].toVariant().toULongLong();
|
|
|
|
flag.size = flagObject["size"].toVariant().toULongLong();
|
|
|
|
flag.name = flagObject["name"].toString();
|
|
|
|
|
|
|
|
ret << flag;
|
|
|
|
}
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2017-09-25 12:55:41 +00:00
|
|
|
QList<SectionDescription> CutterCore::getAllSections()
|
2017-05-03 09:09:57 +00:00
|
|
|
{
|
|
|
|
CORE_LOCK();
|
|
|
|
QList<SectionDescription> ret;
|
|
|
|
|
|
|
|
QJsonArray sectionsArray = cmdj("Sj").array();
|
|
|
|
for (QJsonValue value : sectionsArray)
|
|
|
|
{
|
|
|
|
QJsonObject sectionObject = value.toObject();
|
|
|
|
|
|
|
|
QString name = sectionObject["name"].toString();
|
|
|
|
if (name.isEmpty())
|
|
|
|
continue;
|
|
|
|
|
|
|
|
SectionDescription section;
|
|
|
|
section.name = name;
|
|
|
|
section.vaddr = sectionObject["vaddr"].toVariant().toULongLong();
|
|
|
|
section.vsize = sectionObject["vsize"].toVariant().toULongLong();
|
|
|
|
section.paddr = sectionObject["paddr"].toVariant().toULongLong();
|
|
|
|
section.size = sectionObject["size"].toVariant().toULongLong();
|
|
|
|
section.flags = sectionObject["flags"].toString();
|
|
|
|
|
|
|
|
ret << section;
|
|
|
|
}
|
|
|
|
return ret;
|
2017-05-13 18:09:36 +00:00
|
|
|
}
|
2017-06-07 10:56:55 +00:00
|
|
|
|
2017-09-25 12:55:41 +00:00
|
|
|
QList<EntrypointDescription> CutterCore::getAllEntrypoint()
|
2017-07-13 18:49:12 +00:00
|
|
|
{
|
|
|
|
CORE_LOCK();
|
|
|
|
QList<EntrypointDescription> ret;
|
|
|
|
|
|
|
|
QJsonArray entrypointsArray = cmdj("iej").array();
|
|
|
|
for (QJsonValue value : entrypointsArray)
|
|
|
|
{
|
|
|
|
QJsonObject entrypointObject = value.toObject();
|
|
|
|
|
|
|
|
EntrypointDescription entrypoint;
|
|
|
|
entrypoint.vaddr = entrypointObject["vaddr"].toVariant().toULongLong();
|
|
|
|
entrypoint.paddr = entrypointObject["paddr"].toVariant().toULongLong();
|
|
|
|
entrypoint.baddr = entrypointObject["baddr"].toVariant().toULongLong();
|
|
|
|
entrypoint.laddr = entrypointObject["laddr"].toVariant().toULongLong();
|
|
|
|
entrypoint.haddr = entrypointObject["haddr"].toVariant().toULongLong();
|
|
|
|
entrypoint.type = entrypointObject["type"].toString();
|
|
|
|
|
|
|
|
ret << entrypoint;
|
|
|
|
}
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2017-12-23 16:42:42 +00:00
|
|
|
QList<ClassDescription> CutterCore::getAllClasses()
|
|
|
|
{
|
|
|
|
CORE_LOCK();
|
|
|
|
QList<ClassDescription> ret;
|
|
|
|
|
|
|
|
QJsonArray classesArray = cmdj("icj").array();
|
|
|
|
for (QJsonValueRef value : classesArray)
|
|
|
|
{
|
|
|
|
QJsonObject classObject = value.toObject();
|
|
|
|
|
|
|
|
ClassDescription cls;
|
|
|
|
cls.name = classObject["classname"].toString();
|
|
|
|
cls.addr = classObject["addr"].toVariant().toULongLong();
|
|
|
|
cls.index = classObject["index"].toVariant().toULongLong();
|
|
|
|
|
|
|
|
for(QJsonValueRef value2 : classObject["methods"].toArray())
|
|
|
|
{
|
|
|
|
QJsonObject methObject = value2.toObject();
|
|
|
|
|
|
|
|
ClassMethodDescription meth;
|
|
|
|
meth.name = methObject["name"].toString();
|
|
|
|
meth.addr = methObject["addr"].toVariant().toULongLong();
|
|
|
|
cls.methods << meth;
|
|
|
|
}
|
|
|
|
|
|
|
|
for(QJsonValueRef value2 : classObject["fields"].toArray())
|
|
|
|
{
|
|
|
|
QJsonObject fieldObject = value2.toObject();
|
|
|
|
|
|
|
|
ClassFieldDescription field;
|
|
|
|
field.name = fieldObject["name"].toString();
|
|
|
|
field.addr = fieldObject["addr"].toVariant().toULongLong();
|
|
|
|
cls.fields << field;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret << cls;
|
|
|
|
}
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2018-02-04 14:32:18 +00:00
|
|
|
QList<ResourcesDescription> CutterCore::getAllResources()
|
|
|
|
{
|
|
|
|
CORE_LOCK();
|
|
|
|
QList<ResourcesDescription> ret;
|
|
|
|
|
|
|
|
QJsonArray resourcesArray = cmdj("iRj").array();
|
|
|
|
for (QJsonValueRef value : resourcesArray)
|
|
|
|
{
|
|
|
|
QJsonObject resourceObject = value.toObject();
|
|
|
|
|
|
|
|
ResourcesDescription res;
|
2018-02-09 13:19:36 +00:00
|
|
|
res.name = resourceObject["name"].toInt();
|
2018-02-04 14:32:18 +00:00
|
|
|
res.vaddr = resourceObject["vaddr"].toVariant().toULongLong();
|
|
|
|
res.index = resourceObject["index"].toVariant().toULongLong();
|
|
|
|
res.type = resourceObject["type"].toString();
|
|
|
|
res.size = resourceObject["size"].toVariant().toULongLong();
|
|
|
|
res.lang = resourceObject["lang"].toString();
|
|
|
|
|
|
|
|
ret << res;
|
|
|
|
}
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2018-02-26 22:26:18 +00:00
|
|
|
QList<VTableDescription> CutterCore::getAllVTables()
|
|
|
|
{
|
|
|
|
CORE_LOCK();
|
|
|
|
QList<VTableDescription> ret;
|
|
|
|
|
|
|
|
QJsonArray vTablesArray = cmdj("avj").array();
|
|
|
|
for(QJsonValueRef vTableValue : vTablesArray)
|
|
|
|
{
|
|
|
|
QJsonObject vTableObject = vTableValue.toObject();
|
|
|
|
|
|
|
|
VTableDescription res;
|
|
|
|
res.addr = vTableObject["offset"].toVariant().toULongLong();
|
|
|
|
QJsonArray methodArray = vTableObject["methods"].toArray();
|
|
|
|
|
|
|
|
for(QJsonValueRef methodValue : methodArray)
|
|
|
|
{
|
|
|
|
QJsonObject methodObject = methodValue.toObject();
|
|
|
|
|
|
|
|
ClassMethodDescription method;
|
|
|
|
method.addr = methodObject["offset"].toVariant().toULongLong();
|
|
|
|
method.name = methodObject["name"].toString();
|
|
|
|
|
|
|
|
res.methods << method;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret << res;
|
|
|
|
}
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2018-03-06 17:21:48 +00:00
|
|
|
QList<TypeDescription> CutterCore::getAllTypes()
|
|
|
|
{
|
|
|
|
CORE_LOCK();
|
|
|
|
QList<TypeDescription> ret;
|
|
|
|
|
|
|
|
QJsonArray typesArray = cmdj("tj").array();
|
|
|
|
|
|
|
|
foreach (QJsonValue value, typesArray)
|
|
|
|
{
|
|
|
|
QJsonObject typeObject = value.toObject();
|
|
|
|
|
|
|
|
TypeDescription exp;
|
|
|
|
|
|
|
|
exp.type = typeObject["type"].toString();
|
|
|
|
exp.size = typeObject["size"].toVariant().toULongLong();
|
|
|
|
exp.format = typeObject["format"].toString();
|
|
|
|
|
|
|
|
ret << exp;
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2018-03-08 12:24:15 +00:00
|
|
|
QList<SearchDescription> CutterCore::getAllSearch(QString search_for, QString space)
|
|
|
|
{
|
|
|
|
CORE_LOCK();
|
|
|
|
QList<SearchDescription> ret;
|
|
|
|
|
|
|
|
QJsonArray searchArray = cmdj(space + QString(" ") + search_for).array();
|
|
|
|
|
|
|
|
foreach (QJsonValue value, searchArray)
|
|
|
|
{
|
|
|
|
QJsonObject searchObject = value.toObject();
|
|
|
|
|
|
|
|
SearchDescription exp;
|
|
|
|
|
|
|
|
exp.offset = searchObject["offset"].toVariant().toULongLong();
|
|
|
|
exp.size = searchObject["len"].toVariant().toULongLong();
|
|
|
|
exp.code = searchObject["code"].toString();
|
|
|
|
exp.data = searchObject["data"].toString();
|
|
|
|
|
|
|
|
ret << exp;
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2017-09-25 12:55:41 +00:00
|
|
|
QList<XrefDescription> CutterCore::getXRefs(RVA addr, bool to, bool whole_function, const QString &filterType)
|
2017-06-07 10:56:55 +00:00
|
|
|
{
|
2017-06-07 19:35:38 +00:00
|
|
|
QList<XrefDescription> ret = QList<XrefDescription>();
|
2017-06-07 10:56:55 +00:00
|
|
|
|
|
|
|
QJsonArray xrefsArray;
|
|
|
|
|
|
|
|
if (to)
|
|
|
|
xrefsArray = cmdj("axtj@" + QString::number(addr)).array();
|
|
|
|
else
|
|
|
|
xrefsArray = cmdj("axfj@" + QString::number(addr)).array();
|
|
|
|
|
|
|
|
for (QJsonValue value : xrefsArray)
|
|
|
|
{
|
|
|
|
QJsonObject xrefObject = value.toObject();
|
|
|
|
|
2017-06-07 19:35:38 +00:00
|
|
|
XrefDescription xref;
|
2017-06-07 10:56:55 +00:00
|
|
|
xref.type = xrefObject["type"].toString();
|
|
|
|
|
|
|
|
if (!filterType.isNull() && filterType != xref.type)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
xref.from = xrefObject["from"].toVariant().toULongLong();
|
2017-11-27 16:05:10 +00:00
|
|
|
xref.from_str = Core()->cmd("fd " + xrefObject["from"].toString()).trimmed();
|
2017-06-07 10:56:55 +00:00
|
|
|
|
2017-06-08 22:40:43 +00:00
|
|
|
if (!whole_function && !to && xref.from != addr)
|
|
|
|
continue;
|
|
|
|
|
2017-06-07 10:56:55 +00:00
|
|
|
if (to && !xrefObject.contains("to"))
|
|
|
|
xref.to = addr;
|
|
|
|
else
|
|
|
|
xref.to = xrefObject["to"].toVariant().toULongLong();
|
2017-11-27 16:05:10 +00:00
|
|
|
xref.to_str = Core()->cmd("fd " + xrefObject["to"].toString()).trimmed();
|
2017-06-07 10:56:55 +00:00
|
|
|
|
|
|
|
ret << xref;
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
2017-07-11 11:05:42 +00:00
|
|
|
}
|
|
|
|
|
2017-09-25 12:55:41 +00:00
|
|
|
void CutterCore::addFlag(RVA offset, QString name, RVA size)
|
2017-07-11 11:05:42 +00:00
|
|
|
{
|
|
|
|
name = sanitizeStringForCommand(name);
|
|
|
|
cmd(QString("f %1 %2 @ %3").arg(name).arg(size).arg(offset));
|
|
|
|
emit flagsChanged();
|
2017-07-13 18:49:12 +00:00
|
|
|
}
|
2017-09-27 20:23:18 +00:00
|
|
|
|
2017-11-30 21:30:51 +00:00
|
|
|
void CutterCore::triggerFlagsChanged()
|
|
|
|
{
|
|
|
|
emit flagsChanged();
|
|
|
|
}
|
|
|
|
|
|
|
|
void CutterCore::triggerVarsChanged()
|
|
|
|
{
|
|
|
|
emit varsChanged();
|
|
|
|
}
|
|
|
|
|
|
|
|
void CutterCore::triggerFunctionRenamed(const QString &prevName, const QString &newName)
|
|
|
|
{
|
|
|
|
emit functionRenamed(prevName, newName);
|
|
|
|
}
|
|
|
|
|
2017-09-27 20:23:18 +00:00
|
|
|
void CutterCore::loadPDB(const QString &file)
|
|
|
|
{
|
|
|
|
cmd("idp " + sanitizeStringForCommand(file));
|
|
|
|
}
|
2017-10-21 19:20:10 +00:00
|
|
|
|
|
|
|
void CutterCore::openProject(const QString &name)
|
|
|
|
{
|
|
|
|
cmd("Po " + name);
|
|
|
|
|
|
|
|
QString notes = QString::fromUtf8(QByteArray::fromBase64(cmd("Pnj").toUtf8()));
|
|
|
|
}
|
|
|
|
|
|
|
|
void CutterCore::saveProject(const QString &name)
|
|
|
|
{
|
|
|
|
cmd("Ps " + name);
|
|
|
|
cmd("Pnj " + notes.toUtf8().toBase64());
|
|
|
|
emit projectSaved(name);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool CutterCore::isProjectNameValid(const QString &name)
|
|
|
|
{
|
|
|
|
// see is_valid_project_name() in libr/core/project.c
|
|
|
|
static const QRegExp regexp(R"(^[a-zA-Z0-9\\\._:-]{1,}$)");
|
|
|
|
return regexp.exactMatch(name) && !name.endsWith(".zip") ;
|
|
|
|
}
|
|
|
|
|
2017-12-13 14:30:00 +00:00
|
|
|
QList<DisassemblyLine> CutterCore::disassembleLines(RVA offset, int lines)
|
|
|
|
{
|
|
|
|
QJsonArray array = cmdj(QString("pdJ ") + QString::number(lines) + QString(" @ ") + QString::number(offset)).array();
|
|
|
|
QList<DisassemblyLine> r;
|
|
|
|
|
|
|
|
for (QJsonValue value : array)
|
|
|
|
{
|
|
|
|
QJsonObject object = value.toObject();
|
|
|
|
|
|
|
|
DisassemblyLine line;
|
|
|
|
line.offset = object["offset"].toVariant().toULongLong();
|
|
|
|
line.text = object["text"].toString();
|
|
|
|
|
|
|
|
r << line;
|
|
|
|
}
|
|
|
|
|
|
|
|
return r;
|
|
|
|
}
|
2017-12-14 12:45:03 +00:00
|
|
|
|
|
|
|
void CutterCore::loadScript(const QString &scriptname)
|
|
|
|
{
|
|
|
|
r_core_cmd_file(core_, scriptname.toStdString().data());
|
|
|
|
}
|
2017-12-15 16:09:04 +00:00
|
|
|
|
|
|
|
QString CutterCore::getVersionInformation()
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
QString ret;
|
|
|
|
struct vcs_t {
|
|
|
|
const char *name;
|
|
|
|
const char *(*callback)();
|
|
|
|
} vcs[] = {
|
|
|
|
{ "r_anal", &r_anal_version },
|
|
|
|
{ "r_lib", &r_lib_version },
|
|
|
|
{ "r_egg", &r_egg_version },
|
|
|
|
{ "r_asm", &r_asm_version },
|
|
|
|
{ "r_bin", &r_bin_version },
|
|
|
|
{ "r_cons", &r_cons_version },
|
|
|
|
{ "r_flag", &r_flag_version },
|
|
|
|
{ "r_core", &r_core_version },
|
|
|
|
{ "r_crypto", &r_crypto_version },
|
|
|
|
{ "r_bp", &r_bp_version },
|
|
|
|
{ "r_debug", &r_debug_version },
|
|
|
|
{ "r_hash", &r_hash_version },
|
|
|
|
{ "r_fs", &r_fs_version },
|
|
|
|
{ "r_io", &r_io_version },
|
|
|
|
{ "r_magic", &r_magic_version },
|
|
|
|
{ "r_parse", &r_parse_version },
|
|
|
|
{ "r_reg", &r_reg_version },
|
|
|
|
{ "r_sign", &r_sign_version },
|
|
|
|
{ "r_search", &r_search_version },
|
|
|
|
{ "r_syscall", &r_syscall_version },
|
|
|
|
{ "r_util", &r_util_version },
|
|
|
|
/* ... */
|
|
|
|
{NULL,NULL}
|
|
|
|
};
|
|
|
|
ret.append(QString("%1 r2\n").arg(R2_GITTAP));
|
|
|
|
for (i = 0; vcs[i].name; i++) {
|
|
|
|
struct vcs_t *v = &vcs[i];
|
|
|
|
const char *name = v->callback ();
|
|
|
|
ret.append(QString("%1 %2\n").arg(name, v->name));
|
|
|
|
}
|
|
|
|
return ret;
|
|
|
|
}
|
2018-01-27 10:40:26 +00:00
|
|
|
|
|
|
|
QJsonArray CutterCore::getOpenedFiles()
|
|
|
|
{
|
|
|
|
QJsonDocument files = cmdj("oj");
|
|
|
|
return files.array();
|
|
|
|
}
|
2018-02-26 22:25:23 +00:00
|
|
|
|
|
|
|
QList<QString> CutterCore::getColorThemes()
|
|
|
|
{
|
|
|
|
QList<QString> r;
|
|
|
|
QJsonDocument themes = cmdj("ecoj");
|
|
|
|
for (auto s : themes.array())
|
|
|
|
r << s.toString();
|
|
|
|
return r;
|
|
|
|
}
|