Fix x64 and x86 SEH analysis (#6558)
This commit is contained in:
parent
84b2f31035
commit
3c02fa5618
10 changed files with 339 additions and 37 deletions
107
librz/arch/fcn.c
107
librz/arch/fcn.c
|
|
@ -583,6 +583,49 @@ static bool is_unknown_call_from_plt(RzAnalysis *analysis, ut64 op_address) {
|
||||||
RZ_STR_EQ(s->name, ".plt");
|
RZ_STR_EQ(s->name, ".plt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
typedef struct rz_analysis_trycatch_ctx_t {
|
||||||
|
RzAnalysis *analysis;
|
||||||
|
RzVector /*<RzAnalysisTaskItem>*/ *tasks;
|
||||||
|
RzAnalysisFunction *fcn;
|
||||||
|
RzStackAddr sp;
|
||||||
|
ut64 addr;
|
||||||
|
bool overlapped;
|
||||||
|
RzAnalysisBlock *bb;
|
||||||
|
} RzAnalysisTrycatchCtx;
|
||||||
|
|
||||||
|
static bool add_trycatch_handlers(RZ_NONNULL RzAnalysisTrycatchCtx *ctx) {
|
||||||
|
if (!ctx->analysis->binb.get_trycatch || !ctx->analysis->binb.bin) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
RzPVector *tcs = ctx->analysis->binb.get_trycatch(ctx->analysis->binb.bin);
|
||||||
|
if (!tcs) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool found = false;
|
||||||
|
void **it;
|
||||||
|
RzBinTrycatch *tc;
|
||||||
|
rz_pvector_foreach (tcs, it) {
|
||||||
|
tc = *it;
|
||||||
|
if (ctx->addr >= tc->from && ctx->addr < tc->to && tc->handler) {
|
||||||
|
if (!ctx->overlapped && !found && ctx->bb) {
|
||||||
|
ctx->bb->jump = tc->handler;
|
||||||
|
}
|
||||||
|
rz_analysis_task_item_new(ctx->analysis, ctx->tasks, ctx->fcn, NULL, tc->handler, ctx->sp);
|
||||||
|
found = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return found;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline bool is_x86_seh(RzAnalysis *analysis, bool is_x86, RzAnalysisOp *op, ut64 last_push_addr) {
|
||||||
|
return analysis->opt.trycatch && is_x86 && op->dst && op->dst->seg &&
|
||||||
|
RZ_STR_EQ(op->dst->seg->name, "fs") && op->dst->delta == 0 &&
|
||||||
|
op->dst->memref && last_push_addr != UT64_MAX &&
|
||||||
|
analysis->iob.is_valid_offset(analysis->iob.io, last_push_addr, 0);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Analyses the given task item \p item for branches.
|
* \brief Analyses the given task item \p item for branches.
|
||||||
*
|
*
|
||||||
|
|
@ -843,34 +886,21 @@ static RzAnalysisBBEndCause run_basic_block_analysis(RzAnalysisTaskItem *item, R
|
||||||
rz_analysis_block_set_size(bb, newbbsize);
|
rz_analysis_block_set_size(bb, newbbsize);
|
||||||
fcn->ninstr++;
|
fcn->ninstr++;
|
||||||
}
|
}
|
||||||
if (analysis->opt.trycatch) {
|
if (analysis->opt.trycatch && analysis->binb.get_trycatch) {
|
||||||
const char *name = analysis->coreb.getName(analysis->coreb.core, at);
|
RzPVector *tcs = analysis->binb.get_trycatch(analysis->binb.bin);
|
||||||
if (name) {
|
if (tcs) {
|
||||||
if (rz_str_startswith(name, "try.") && rz_str_endswith(name, ".from")) {
|
void **it;
|
||||||
char *handle = rz_str_dup(name);
|
RzBinTrycatch *tc;
|
||||||
// handle = rz_str_replace (handle, ".from", ".to", 0);
|
rz_pvector_foreach (tcs, it) {
|
||||||
ut64 from_addr = analysis->coreb.numGet(analysis->coreb.core, handle);
|
tc = *it;
|
||||||
handle = rz_str_replace(handle, ".from", ".catch", 0);
|
if (tc->from != at) {
|
||||||
ut64 handle_addr = analysis->coreb.numGet(analysis->coreb.core, handle);
|
continue;
|
||||||
handle = rz_str_replace(handle, ".catch", ".filter", 0);
|
|
||||||
ut64 filter_addr = analysis->coreb.numGet(analysis->coreb.core, handle);
|
|
||||||
if (filter_addr) {
|
|
||||||
rz_analysis_xrefs_set(analysis, op.addr, filter_addr, RZ_ANALYSIS_XREF_TYPE_CALL);
|
|
||||||
}
|
}
|
||||||
bb->jump = at + oplen;
|
if (tc->filter) {
|
||||||
if (from_addr != bb->addr) {
|
rz_analysis_xrefs_set(analysis, op.addr, tc->filter, RZ_ANALYSIS_XREF_TYPE_CALL);
|
||||||
bb->fail = handle_addr;
|
|
||||||
ret = analyze_function_locally(analysis, fcn, handle_addr);
|
|
||||||
if (bb->size == 0) {
|
|
||||||
rz_analysis_function_remove_block(fcn, bb);
|
|
||||||
}
|
|
||||||
rz_analysis_block_update_hash(bb);
|
|
||||||
rz_analysis_block_unref(bb);
|
|
||||||
bb = fcn_append_basic_block(analysis, fcn, bb->jump);
|
|
||||||
if (!bb) {
|
|
||||||
gotoBeach(RZ_ANALYSIS_RET_ERROR);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
rz_analysis_xrefs_set(analysis, op.addr, tc->handler, RZ_ANALYSIS_XREF_TYPE_CODE);
|
||||||
|
rz_analysis_task_item_new(analysis, tasks, fcn, NULL, tc->handler, sp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -992,6 +1022,11 @@ static RzAnalysisBBEndCause run_basic_block_analysis(RzAnalysisTaskItem *item, R
|
||||||
gotoBeach(RZ_ANALYSIS_RET_END);
|
gotoBeach(RZ_ANALYSIS_RET_END);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (is_x86_seh(analysis, is_x86, &op, last_push_addr)) {
|
||||||
|
rz_analysis_xrefs_set(analysis, op.addr, last_push_addr, RZ_ANALYSIS_XREF_TYPE_CODE);
|
||||||
|
rz_analysis_task_item_new(analysis, tasks, fcn, NULL, last_push_addr, sp);
|
||||||
|
last_push_addr = UT64_MAX;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case RZ_ANALYSIS_OP_TYPE_LEA:
|
case RZ_ANALYSIS_OP_TYPE_LEA:
|
||||||
last_is_reg_mov_lea = false;
|
last_is_reg_mov_lea = false;
|
||||||
|
|
@ -1121,6 +1156,12 @@ static RzAnalysisBBEndCause run_basic_block_analysis(RzAnalysisTaskItem *item, R
|
||||||
}
|
}
|
||||||
gotoBeach(RZ_ANALYSIS_RET_BRANCH);
|
gotoBeach(RZ_ANALYSIS_RET_BRANCH);
|
||||||
}
|
}
|
||||||
|
if (analysis->opt.trycatch) {
|
||||||
|
RzAnalysisTrycatchCtx ctx = { analysis, tasks, fcn, sp, at, overlapped, bb };
|
||||||
|
if (add_trycatch_handlers(&ctx)) {
|
||||||
|
gotoBeach(RZ_ANALYSIS_RET_BRANCH);
|
||||||
|
}
|
||||||
|
}
|
||||||
gotoBeach(RZ_ANALYSIS_RET_END);
|
gotoBeach(RZ_ANALYSIS_RET_END);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
|
|
@ -1273,6 +1314,7 @@ static RzAnalysisBBEndCause run_basic_block_analysis(RzAnalysisTaskItem *item, R
|
||||||
case RZ_ANALYSIS_OP_TYPE_RCALL:
|
case RZ_ANALYSIS_OP_TYPE_RCALL:
|
||||||
case RZ_ANALYSIS_OP_TYPE_ICALL:
|
case RZ_ANALYSIS_OP_TYPE_ICALL:
|
||||||
case RZ_ANALYSIS_OP_TYPE_IRCALL:
|
case RZ_ANALYSIS_OP_TYPE_IRCALL:
|
||||||
|
last_push_addr = UT64_MAX;
|
||||||
/* call [dst] */
|
/* call [dst] */
|
||||||
// XXX: this is TYPE_MCALL or indirect-call
|
// XXX: this is TYPE_MCALL or indirect-call
|
||||||
(void)rz_analysis_xrefs_set(analysis, op.addr, op.ptr, RZ_ANALYSIS_XREF_TYPE_CALL);
|
(void)rz_analysis_xrefs_set(analysis, op.addr, op.ptr, RZ_ANALYSIS_XREF_TYPE_CALL);
|
||||||
|
|
@ -1283,11 +1325,18 @@ static RzAnalysisBBEndCause run_basic_block_analysis(RzAnalysisTaskItem *item, R
|
||||||
if (f) {
|
if (f) {
|
||||||
f->is_noreturn = true;
|
f->is_noreturn = true;
|
||||||
}
|
}
|
||||||
|
if (analysis->opt.trycatch) {
|
||||||
|
RzAnalysisTrycatchCtx ctx = { analysis, tasks, fcn, sp, at, overlapped, bb };
|
||||||
|
if (add_trycatch_handlers(&ctx)) {
|
||||||
|
gotoBeach(RZ_ANALYSIS_RET_BRANCH);
|
||||||
|
}
|
||||||
|
}
|
||||||
gotoBeach(RZ_ANALYSIS_RET_END);
|
gotoBeach(RZ_ANALYSIS_RET_END);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case RZ_ANALYSIS_OP_TYPE_CCALL:
|
case RZ_ANALYSIS_OP_TYPE_CCALL:
|
||||||
case RZ_ANALYSIS_OP_TYPE_CALL:
|
case RZ_ANALYSIS_OP_TYPE_CALL:
|
||||||
|
last_push_addr = UT64_MAX;
|
||||||
/* call dst */
|
/* call dst */
|
||||||
(void)rz_analysis_xrefs_set(analysis, op.addr, op.jump, RZ_ANALYSIS_XREF_TYPE_CALL);
|
(void)rz_analysis_xrefs_set(analysis, op.addr, op.jump, RZ_ANALYSIS_XREF_TYPE_CALL);
|
||||||
|
|
||||||
|
|
@ -1296,6 +1345,12 @@ static RzAnalysisBBEndCause run_basic_block_analysis(RzAnalysisTaskItem *item, R
|
||||||
if (f) {
|
if (f) {
|
||||||
f->is_noreturn = true;
|
f->is_noreturn = true;
|
||||||
}
|
}
|
||||||
|
if (analysis->opt.trycatch) {
|
||||||
|
RzAnalysisTrycatchCtx ctx = { analysis, tasks, fcn, sp, at, overlapped, bb };
|
||||||
|
if (add_trycatch_handlers(&ctx)) {
|
||||||
|
gotoBeach(RZ_ANALYSIS_RET_BRANCH);
|
||||||
|
}
|
||||||
|
}
|
||||||
gotoBeach(RZ_ANALYSIS_RET_END);
|
gotoBeach(RZ_ANALYSIS_RET_END);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -583,12 +583,26 @@ RZ_API void rz_bin_class_free(RZ_NULLABLE RzBinClass *k) {
|
||||||
free(k);
|
free(k);
|
||||||
}
|
}
|
||||||
|
|
||||||
RZ_API RZ_OWN RzPVector /*<RzBinTrycatch *>*/ *rz_bin_file_get_trycatch(RZ_NONNULL RzBinFile *bf) {
|
/**
|
||||||
rz_return_val_if_fail(bf && bf->o && bf->o->plugin, NULL);
|
* \brief Get the trycatch information from the given binary file.
|
||||||
if (bf->o->plugin->trycatch) {
|
*
|
||||||
return bf->o->plugin->trycatch(bf);
|
* If the trycatch information has not been parsed yet, it will call the plugin's
|
||||||
|
* trycatch method to load it, if that fails then an empty vector will be returned.
|
||||||
|
*
|
||||||
|
* \param bf Binary file
|
||||||
|
* \return Borrowed vector of RzBinTrycatch pointers
|
||||||
|
*/
|
||||||
|
RZ_API RZ_BORROW RzPVector /*<RzBinTrycatch *>*/ *rz_bin_file_get_trycatch(RZ_NONNULL RzBinFile *bf) {
|
||||||
|
rz_return_val_if_fail(bf && bf->o, NULL);
|
||||||
|
if (!bf->o->trycatch) {
|
||||||
|
if (bf->o->plugin && bf->o->plugin->trycatch) {
|
||||||
|
bf->o->trycatch = bf->o->plugin->trycatch(bf);
|
||||||
|
}
|
||||||
|
if (!bf->o->trycatch) {
|
||||||
|
bf->o->trycatch = rz_pvector_new((RzPVectorFree)rz_bin_trycatch_free);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return NULL;
|
return bf->o->trycatch;
|
||||||
}
|
}
|
||||||
|
|
||||||
RZ_API RzPVector /*<RzBinSymbol *>*/ *rz_bin_file_get_symbols(RzBinFile *bf) {
|
RZ_API RzPVector /*<RzBinSymbol *>*/ *rz_bin_file_get_symbols(RzBinFile *bf) {
|
||||||
|
|
|
||||||
|
|
@ -978,6 +978,12 @@ static RzBinObject *bin_bind_get_bin_object(RzBin *bin) {
|
||||||
return bf ? bf->o : NULL;
|
return bf ? bf->o : NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static RzPVector /*<RzBinTrycatch *>*/ *bin_bind_get_trycatch(RzBin *bin) {
|
||||||
|
rz_return_val_if_fail(bin, NULL);
|
||||||
|
RzBinFile *bf = rz_bin_cur(bin);
|
||||||
|
return bf ? rz_bin_file_get_trycatch(bf) : NULL;
|
||||||
|
}
|
||||||
|
|
||||||
RZ_API void rz_bin_bind(RzBin *bin, RzBinBind *b) {
|
RZ_API void rz_bin_bind(RzBin *bin, RzBinBind *b) {
|
||||||
if (!b) {
|
if (!b) {
|
||||||
return;
|
return;
|
||||||
|
|
@ -990,6 +996,7 @@ RZ_API void rz_bin_bind(RzBin *bin, RzBinBind *b) {
|
||||||
b->get_vsect_at = bin_bind_get_vsection_at;
|
b->get_vsect_at = bin_bind_get_vsection_at;
|
||||||
b->demangle = rz_bin_demangle;
|
b->demangle = rz_bin_demangle;
|
||||||
b->get_bin_object = bin_bind_get_bin_object;
|
b->get_bin_object = bin_bind_get_bin_object;
|
||||||
|
b->get_trycatch = bin_bind_get_trycatch;
|
||||||
}
|
}
|
||||||
|
|
||||||
RZ_API RzBuffer *rz_bin_create(RzBin *bin, const char *p,
|
RZ_API RzBuffer *rz_bin_create(RzBin *bin, const char *p,
|
||||||
|
|
|
||||||
|
|
@ -207,6 +207,7 @@ RZ_IPI void rz_bin_object_free(RzBinObject *o) {
|
||||||
rz_pvector_free(o->mem);
|
rz_pvector_free(o->mem);
|
||||||
rz_pvector_free(o->sections);
|
rz_pvector_free(o->sections);
|
||||||
rz_pvector_free(o->symbols);
|
rz_pvector_free(o->symbols);
|
||||||
|
rz_pvector_free(o->trycatch);
|
||||||
rz_pvector_free(o->vfiles);
|
rz_pvector_free(o->vfiles);
|
||||||
rz_pvector_free(o->resources);
|
rz_pvector_free(o->resources);
|
||||||
for (ut32 i = 0; i < RZ_BIN_SPECIAL_SYMBOL_LAST; i++) {
|
for (ut32 i = 0; i < RZ_BIN_SPECIAL_SYMBOL_LAST; i++) {
|
||||||
|
|
|
||||||
|
|
@ -5654,8 +5654,6 @@ RZ_API bool rz_core_bin_trycatch_print(RZ_NONNULL RzCore *core, RZ_NONNULL RzBin
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
rz_pvector_free(trycatch);
|
|
||||||
|
|
||||||
rz_cmd_state_output_array_end(state);
|
rz_cmd_state_output_array_end(state);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3057,7 +3057,7 @@ RZ_API int rz_core_config_init(RzCore *core) {
|
||||||
SETCB("analysis.jmp.mid", "true", &cb_analysis_jmpmid, "Continue analysis after jump to middle of instruction (x86 only)");
|
SETCB("analysis.jmp.mid", "true", &cb_analysis_jmpmid, "Continue analysis after jump to middle of instruction (x86 only)");
|
||||||
|
|
||||||
SETCB("analysis.refstr", "false", &cb_analysis_searchstringrefs, "Search string references in data references");
|
SETCB("analysis.refstr", "false", &cb_analysis_searchstringrefs, "Search string references in data references");
|
||||||
SETCB("analysis.trycatch", "false", &cb_analysis_trycatch, "Honor try.X.Y.{from,to,catch} flags");
|
SETCB("analysis.trycatch", "true", &cb_analysis_trycatch, "Honor try.X.Y.{from,to,catch} flags");
|
||||||
SETCB("analysis.bb.maxsize", "63K", &cb_analysis_bb_max_size, "Maximum basic block size");
|
SETCB("analysis.bb.maxsize", "63K", &cb_analysis_bb_max_size, "Maximum basic block size");
|
||||||
SETCB("analysis.fcn_max_size", "256K", &cb_analysis_fcn_max_size, "Maximum function size (unspecified units)");
|
SETCB("analysis.fcn_max_size", "256K", &cb_analysis_fcn_max_size, "Maximum function size (unspecified units)");
|
||||||
SETCB("analysis.pushret", "false", &cb_analysis_pushret, "Analyze push+ret as jmp");
|
SETCB("analysis.pushret", "false", &cb_analysis_pushret, "Analyze push+ret as jmp");
|
||||||
|
|
|
||||||
|
|
@ -338,6 +338,7 @@ typedef struct rz_bin_object_t {
|
||||||
RzPVector /*<RzBinSection *>*/ *sections;
|
RzPVector /*<RzBinSection *>*/ *sections;
|
||||||
RzPVector /*<RzBinImport *>*/ *imports;
|
RzPVector /*<RzBinImport *>*/ *imports;
|
||||||
RzPVector /*<RzBinSymbol *>*/ *symbols;
|
RzPVector /*<RzBinSymbol *>*/ *symbols;
|
||||||
|
RzPVector /*<RzBinTrycatch *>*/ *trycatch;
|
||||||
RzPVector /*<RzBinResource *>*/ *resources;
|
RzPVector /*<RzBinResource *>*/ *resources;
|
||||||
/**
|
/**
|
||||||
* \brief Acceleration structure for fast access of the symbol for a given import.
|
* \brief Acceleration structure for fast access of the symbol for a given import.
|
||||||
|
|
@ -881,6 +882,7 @@ typedef const RzPVector *(*RzBinGetSections)(RzBinObject *obj);
|
||||||
typedef RzBinSection *(*RzBinGetSectionAt)(RzBin *bin, ut64 addr);
|
typedef RzBinSection *(*RzBinGetSectionAt)(RzBin *bin, ut64 addr);
|
||||||
typedef char *(*RzBinDemangle)(RzBin *bin, const char *language, const char *mangled);
|
typedef char *(*RzBinDemangle)(RzBin *bin, const char *language, const char *mangled);
|
||||||
typedef RzBinObject *(*RzBinGetObject)(RzBin *bin);
|
typedef RzBinObject *(*RzBinGetObject)(RzBin *bin);
|
||||||
|
typedef RzPVector /*<RzBinTrycatch *>*/ *(*RzBinGetTrycatch)(RzBin *bin);
|
||||||
|
|
||||||
typedef struct rz_bin_bind_t {
|
typedef struct rz_bin_bind_t {
|
||||||
RzBin *bin;
|
RzBin *bin;
|
||||||
|
|
@ -890,6 +892,7 @@ typedef struct rz_bin_bind_t {
|
||||||
RzBinGetSectionAt get_vsect_at;
|
RzBinGetSectionAt get_vsect_at;
|
||||||
RzBinDemangle demangle;
|
RzBinDemangle demangle;
|
||||||
RzBinGetObject get_bin_object;
|
RzBinGetObject get_bin_object;
|
||||||
|
RzBinGetTrycatch get_trycatch;
|
||||||
ut32 visibility;
|
ut32 visibility;
|
||||||
} RzBinBind;
|
} RzBinBind;
|
||||||
|
|
||||||
|
|
@ -1020,7 +1023,7 @@ RZ_API RZ_OWN RzPVector /*<RzBinString *>*/ *rz_bin_file_strings(RZ_NONNULL RzBi
|
||||||
|
|
||||||
// use RzBinFile instead
|
// use RzBinFile instead
|
||||||
RZ_DEPRECATE RZ_API int rz_bin_is_static(RZ_NONNULL RzBin *bin);
|
RZ_DEPRECATE RZ_API int rz_bin_is_static(RZ_NONNULL RzBin *bin);
|
||||||
RZ_API RZ_OWN RzPVector /*<RzBinTrycatch *>*/ *rz_bin_file_get_trycatch(RZ_NONNULL RzBinFile *bf);
|
RZ_API RZ_BORROW RzPVector /*<RzBinTrycatch *>*/ *rz_bin_file_get_trycatch(RZ_NONNULL RzBinFile *bf);
|
||||||
|
|
||||||
RZ_API RZ_BORROW const RzPVector /*<RzBinAddr *>*/ *rz_bin_object_get_entries(RZ_NONNULL RzBinObject *obj);
|
RZ_API RZ_BORROW const RzPVector /*<RzBinAddr *>*/ *rz_bin_object_get_entries(RZ_NONNULL RzBinObject *obj);
|
||||||
RZ_API const RzPVector /*<RzBinField *>*/ *rz_bin_object_get_fields(RZ_NONNULL RzBinObject *obj);
|
RZ_API const RzPVector /*<RzBinField *>*/ *rz_bin_object_get_fields(RZ_NONNULL RzBinObject *obj);
|
||||||
|
|
|
||||||
|
|
@ -44,7 +44,7 @@ EXPECT=<<EOF
|
||||||
arch x86
|
arch x86
|
||||||
machine AMD 64
|
machine AMD 64
|
||||||
0 * classes
|
0 * classes
|
||||||
86 * functions
|
87 * functions
|
||||||
38 * imports
|
38 * imports
|
||||||
0 * platform.ports
|
0 * platform.ports
|
||||||
80 * pointers
|
80 * pointers
|
||||||
|
|
|
||||||
|
|
@ -43,6 +43,7 @@ afl.
|
||||||
EOF
|
EOF
|
||||||
EXPECT=<<EOF
|
EXPECT=<<EOF
|
||||||
0x00401e80 fcn.00401e80
|
0x00401e80 fcn.00401e80
|
||||||
|
0x00401e80 fcn.00401e80
|
||||||
EOF
|
EOF
|
||||||
RUN
|
RUN
|
||||||
|
|
||||||
|
|
@ -530,7 +531,7 @@ s 0x401880
|
||||||
fd
|
fd
|
||||||
EOF
|
EOF
|
||||||
EXPECT=<<EOF
|
EXPECT=<<EOF
|
||||||
fcn.00401880
|
fcn.00401820 + 96
|
||||||
EOF
|
EOF
|
||||||
RUN
|
RUN
|
||||||
|
|
||||||
|
|
@ -4261,3 +4262,137 @@ EXPECT=<<EOF
|
||||||
\ |,=< 0x00401054 jmp fcn.0040dfd0
|
\ |,=< 0x00401054 jmp fcn.0040dfd0
|
||||||
EOF
|
EOF
|
||||||
RUN
|
RUN
|
||||||
|
|
||||||
|
NAME=x86 structured exception handling xframe
|
||||||
|
FILE=bins/pe/microsoft_seh_tests/x86/xframe_eh_exe.exe
|
||||||
|
CMDS=<<EOF
|
||||||
|
aaa
|
||||||
|
pdf @ main
|
||||||
|
EOF
|
||||||
|
EXPECT=<<EOF
|
||||||
|
; CALL XREF from entry0 @ 0x401d37
|
||||||
|
/ int main(int argc, char **argv, char **envp);
|
||||||
|
| 0x00401b10 call fcn.00401880
|
||||||
|
| 0x00401b15 call fcn.00401000
|
||||||
|
| 0x00401b1a call fcn.00401320
|
||||||
|
| 0x00401b1f push str.Caught_Exceptions_Test_PASSED. ; 0x4031b0 ; "Caught Exceptions Test PASSED." ; const char *s
|
||||||
|
| 0x00401b24 call dword [sym.imp.api_ms_win_crt_stdio_l1_1_0.dll_puts] ; 0x4030cc ; int puts(const char *s)
|
||||||
|
| 0x00401b2a call fcn.004019a0
|
||||||
|
| 0x00401b2f push str.Resumed_Exceptions_Test_PASSED. ; 0x4031d0 ; "Resumed Exceptions Test PASSED." ; const char *s
|
||||||
|
| 0x00401b34 call dword [sym.imp.api_ms_win_crt_stdio_l1_1_0.dll_puts] ; 0x4030cc ; int puts(const char *s)
|
||||||
|
| 0x00401b3a add esp, 0x08
|
||||||
|
| 0x00401b3d xor eax, eax
|
||||||
|
\ 0x00401b3f ret
|
||||||
|
EOF
|
||||||
|
RUN
|
||||||
|
|
||||||
|
NAME=x86 structured exception handling nested_collided
|
||||||
|
FILE=bins/pe/microsoft_seh_tests/x86/nested_collided.exe
|
||||||
|
CMDS=<<EOF
|
||||||
|
aaa
|
||||||
|
pdr @ main
|
||||||
|
EOF
|
||||||
|
EXPECT=<<EOF
|
||||||
|
; CALL XREF from entry0 @ 0x40160e
|
||||||
|
/ int main(int argc, char **argv, char **envp);
|
||||||
|
| ; var int32_t var_3ch @ stack - 0x3c
|
||||||
|
| ; var int32_t var_30h @ stack - 0x30
|
||||||
|
| ; var int32_t var_2ch @ stack - 0x2c
|
||||||
|
| ; var int32_t var_1ch @ stack - 0x1c
|
||||||
|
| ; var int32_t var_14h @ stack - 0x14
|
||||||
|
| ; var int32_t var_ch @ stack - 0xc
|
||||||
|
| 0x00401280 push ebp
|
||||||
|
| 0x00401281 mov ebp, esp
|
||||||
|
| 0x00401283 push 0xfffffffe ; 0xfe ; 254 ; int32_t var_20h
|
||||||
|
| 0x00401285 push data.00403618 ; 0x403618 ; ub"\U0000feff\xff\xff" ; int32_t var_1ch
|
||||||
|
| 0x0040128a push fcn.00401417 ; 0x401417 ; "U\x8b\xecV\x8bu\b\xff6\xe8\xf8\v" ; int32_t var_28h
|
||||||
|
| 0x0040128f mov eax, dword fs:[0x0]
|
||||||
|
| 0x00401295 push eax
|
||||||
|
| 0x00401296 sub esp, 0x08
|
||||||
|
| 0x00401299 push ebx
|
||||||
|
| 0x0040129a push esi
|
||||||
|
| 0x0040129b push edi
|
||||||
|
| 0x0040129c mov eax, dword [data.00404004] ; [0x404004:4]=0xbb40e64e ; "N\xe6@\xbb\xff\xff\xff\xff\U00000001"
|
||||||
|
| 0x004012a1 xor dword [var_ch], eax
|
||||||
|
| 0x004012a4 xor eax, ebp
|
||||||
|
| 0x004012a6 push eax ; int32_t arg_4h
|
||||||
|
| 0x004012a7 lea eax, dword [var_14h]
|
||||||
|
| 0x004012aa mov dword fs:[0x0], eax
|
||||||
|
| 0x004012b0 mov dword [var_1ch], esp
|
||||||
|
| 0x004012b3 push str.Collided_Unwind_test... ; 0x403108 ; "Collided Unwind test... " ; int32_t arg_8h
|
||||||
|
| 0x004012b8 call fcn.00401030
|
||||||
|
| 0x004012bd add esp, 0x04
|
||||||
|
| 0x004012c0 cmp byte [data.00404374], 0x00 ; [0x404374:1]=0
|
||||||
|
| 0x004012c7 jz 0x4012ca
|
||||||
|
| ----------- true: 0x004012ca false: 0x004012c9
|
||||||
|
| 0x004012c9 int3
|
||||||
|
|
||||||
|
| 0x004012ca mov dword [data.00404388], 0x01 ; [0x404388:4]=0
|
||||||
|
| 0x004012d4 mov dword [data.0040438c], 0x00 ; [0x40438c:4]=0
|
||||||
|
| 0x004012de mov dword [var_30h], 0x00
|
||||||
|
| 0x004012e5 call fcn.004011e0
|
||||||
|
| 0x004012ea jmp 0x401323
|
||||||
|
| ----------- true: 0x00401323
|
||||||
|
| ; CODE XREF from main @ 0x4012ea
|
||||||
|
| 0x00401323 mov dword [var_30h], 0xfffffffe ; 4294967294
|
||||||
|
| 0x0040132a cmp byte [data.00404374], 0x00 ; [0x404374:1]=0
|
||||||
|
| 0x00401331 jz 0x401334
|
||||||
|
| ----------- true: 0x00401334 false: 0x00401333
|
||||||
|
| 0x00401333 int3
|
||||||
|
|
||||||
|
| 0x00401334 cmp dword [data.00404388], 0x40bf ; [0x404388:4]=0
|
||||||
|
| 0x0040133e jnz 0x401349
|
||||||
|
| ----------- true: 0x00401349 false: 0x00401340
|
||||||
|
| 0x00401340 cmp dword [data.0040438c], 0x00 ; [0x40438c:4]=0
|
||||||
|
| 0x00401347 jz 0x40134a
|
||||||
|
| ----------- true: 0x0040134a false: 0x00401349
|
||||||
|
| 0x00401349 int3
|
||||||
|
|
||||||
|
| 0x0040134a push str.PASSED. ; 0x403124 ; "PASSED." ; int32_t arg_4h
|
||||||
|
| 0x0040134f mov esi, dword [sym.imp.api_ms_win_crt_stdio_l1_1_0.dll_puts] ; [0x4030b8:4]=0x3884
|
||||||
|
| 0x00401355 call esi
|
||||||
|
| 0x00401357 push str.Nested_Exception_test... ; 0x40312c ; "Nested Exception test... " ; int32_t arg_8h
|
||||||
|
| 0x0040135c call fcn.00401030
|
||||||
|
| 0x00401361 add esp, 0x08
|
||||||
|
| 0x00401364 cmp byte [data.00404374], 0x00 ; [0x404374:1]=0
|
||||||
|
| 0x0040136b jz 0x40136e
|
||||||
|
| ----------- true: 0x0040136e false: 0x0040136d
|
||||||
|
| 0x0040136d int3
|
||||||
|
|
||||||
|
| 0x0040136e mov dword [data.00404388], 0x01 ; [0x404388:4]=0
|
||||||
|
| 0x00401378 mov dword [data.0040438c], 0x00 ; [0x40438c:4]=0
|
||||||
|
| 0x00401382 mov dword [var_30h], 0x01
|
||||||
|
| 0x00401389 call fcn.00401140
|
||||||
|
| 0x0040138e mov dword [var_30h], 0xfffffffe ; 4294967294
|
||||||
|
| 0x00401395 jmp 0x4013d9
|
||||||
|
| ----------- true: 0x004013d9
|
||||||
|
| ; CODE XREF from main @ 0x401395
|
||||||
|
| 0x004013d9 cmp byte [data.00404374], 0x00 ; [0x404374:1]=0
|
||||||
|
| 0x004013e0 jz 0x4013e3
|
||||||
|
| ----------- true: 0x004013e3 false: 0x004013e2
|
||||||
|
| 0x004013e2 int3
|
||||||
|
|
||||||
|
| 0x004013e3 cmp dword [data.00404388], 0x368d ; [0x404388:4]=0
|
||||||
|
| 0x004013ed jnz 0x4013f8
|
||||||
|
| ----------- true: 0x004013f8 false: 0x004013ef
|
||||||
|
| 0x004013ef cmp dword [data.0040438c], 0x00 ; [0x40438c:4]=0
|
||||||
|
| 0x004013f6 jz 0x4013f9
|
||||||
|
| ----------- true: 0x004013f9 false: 0x004013f8
|
||||||
|
| 0x004013f8 int3
|
||||||
|
|
||||||
|
| 0x004013f9 push str.PASSED. ; 0x403124 ; "PASSED."
|
||||||
|
| 0x004013fe call esi
|
||||||
|
| 0x00401400 add esp, 0x04
|
||||||
|
| 0x00401403 xor eax, eax
|
||||||
|
| 0x00401405 mov ecx, dword [var_3ch]
|
||||||
|
| 0x00401408 mov dword fs:[0x0], ecx
|
||||||
|
| 0x0040140f pop ecx
|
||||||
|
| 0x00401410 pop edi
|
||||||
|
| 0x00401411 pop esi
|
||||||
|
| 0x00401412 pop ebx
|
||||||
|
| 0x00401413 mov esp, ebp
|
||||||
|
| 0x00401415 pop ebp
|
||||||
|
\ 0x00401416 ret
|
||||||
|
|
||||||
|
EOF
|
||||||
|
RUN
|
||||||
|
|
|
||||||
|
|
@ -4432,3 +4432,92 @@ global uint8_t [4] global_var @ 0x404050
|
||||||
global uint8_t [8] global_array @ 0x404058
|
global uint8_t [8] global_array @ 0x404058
|
||||||
EOF
|
EOF
|
||||||
RUN
|
RUN
|
||||||
|
|
||||||
|
NAME=x64 structured exception handling xframe
|
||||||
|
FILE=bins/pe/microsoft_seh_tests/x64/xframe_eh_exe.exe
|
||||||
|
CMDS=<<EOF
|
||||||
|
aaa
|
||||||
|
pdf @ main
|
||||||
|
EOF
|
||||||
|
EXPECT=<<EOF
|
||||||
|
; CALL XREF from entry0 @ 0x1400019cb
|
||||||
|
/ int main(int argc, char **argv, char **envp);
|
||||||
|
| 0x140001770 sub rsp, 0x28
|
||||||
|
| 0x140001774 call fcn.140001590
|
||||||
|
| 0x140001779 call fcn.140001000
|
||||||
|
| 0x14000177e call fcn.140001220
|
||||||
|
| 0x140001783 lea rcx, qword str.Caught_Exceptions_Test_PASSED. ; 0x140003320 ; "Caught Exceptions Test PASSED." ; const char *s
|
||||||
|
| 0x14000178a call qword [sym.imp.api_ms_win_crt_stdio_l1_1_0.dll_puts] ; [0x1400031a0:8]=0x3e22 ; "\">" ; int puts(const char *s)
|
||||||
|
| 0x140001790 call fcn.1400016a0
|
||||||
|
| 0x140001795 lea rcx, qword str.Resumed_Exceptions_Test_PASSED. ; 0x140003340 ; "Resumed Exceptions Test PASSED." ; const char *s
|
||||||
|
| 0x14000179c call qword [sym.imp.api_ms_win_crt_stdio_l1_1_0.dll_puts] ; [0x1400031a0:8]=0x3e22 ; "\">" ; int puts(const char *s)
|
||||||
|
| 0x1400017a2 xor eax, eax
|
||||||
|
| 0x1400017a4 add rsp, 0x28
|
||||||
|
\ 0x1400017a8 ret
|
||||||
|
EOF
|
||||||
|
RUN
|
||||||
|
|
||||||
|
NAME=x64 structured exception handling
|
||||||
|
FILE=bins/pe/seh_x64.exe
|
||||||
|
CMDS=<<EOF
|
||||||
|
aaa
|
||||||
|
pdf @ main
|
||||||
|
EOF
|
||||||
|
EXPECT=<<EOF
|
||||||
|
; CALL XREF from entry0 @ 0x140001433
|
||||||
|
/ int main(int argc, char **argv, char **envp);
|
||||||
|
| ; arg int argc @ rcx
|
||||||
|
| ; arg char **argv @ rdx
|
||||||
|
| ; var int64_t var_18h @ stack - 0x18
|
||||||
|
| ; var int64_t var_8h @ stack + 0x8
|
||||||
|
| 0x140001010 mov qword [var_8h], rbx
|
||||||
|
| 0x140001015 push rdi
|
||||||
|
| 0x140001016 sub rsp, 0x30
|
||||||
|
| 0x14000101a mov rbx, rdx ; argv
|
||||||
|
| 0x14000101d mov edi, 0xbadbeef
|
||||||
|
| 0x140001022 cmp ecx, 0x01 ; 1 ; argc
|
||||||
|
| ,=< 0x140001025 jle 0x140001048
|
||||||
|
| | 0x140001027 lea rcx, qword str.Writing_to_invalid_pointer. ; 0x140002330 ; "Writing to invalid pointer." ; const char *s
|
||||||
|
| | 0x14000102e call qword [sym.imp.api_ms_win_crt_stdio_l1_1_0.dll_puts] ; [0x140002180:8]=0x2cbe ; int puts(const char *s)
|
||||||
|
| | 0x140001034 mov rcx, qword [rbx+0x08] ; const char *str
|
||||||
|
| | 0x140001038 call qword [sym.imp.api_ms_win_crt_convert_l1_1_0.dll_atoi] ; [0x140002098:8]=0x2ca4 ; int atoi(const char *str)
|
||||||
|
| | 0x14000103e mov ebx, eax
|
||||||
|
| | 0x140001040 mov dword [var_18h], eax
|
||||||
|
| | 0x140001044 mov dword [rdi], eax
|
||||||
|
| ,==< 0x140001046 jmp 0x14000104c
|
||||||
|
| |`-> 0x140001048 mov ebx, dword [var_18h]
|
||||||
|
| | ; CODE XREF from main @ 0x140001046
|
||||||
|
| `--> 0x14000104c lea rcx, qword str.Try_dividing_by_zero. ; 0x140002350 ; "Try dividing by zero." ; const char *s
|
||||||
|
| 0x140001053 call qword [sym.imp.api_ms_win_crt_stdio_l1_1_0.dll_puts] ; [0x140002180:8]=0x2cbe ; int puts(const char *s)
|
||||||
|
| 0x140001059 mov eax, ebx
|
||||||
|
| 0x14000105b cdq
|
||||||
|
| 0x14000105c xor ecx, ecx
|
||||||
|
| 0x14000105e idiv ecx
|
||||||
|
| 0x140001060 mov dword [var_18h], eax
|
||||||
|
| ,=< 0x140001064 jmp 0x140001074
|
||||||
|
| | ; CODE XREF from main @ 0x14000104c
|
||||||
|
| | 0x140001066 lea rcx, qword str.Inside_nested_except_block ; 0x140002368 ; "Inside nested except block!" ; const char *s
|
||||||
|
| | 0x14000106d call qword [sym.imp.api_ms_win_crt_stdio_l1_1_0.dll_puts] ; [0x140002180:8]=0x2cbe ; int puts(const char *s)
|
||||||
|
| | 0x140001073 nop
|
||||||
|
| | ; CODE XREF from main @ 0x140001064
|
||||||
|
| ,`-> 0x140001074 jmp 0x1400010a2
|
||||||
|
| | ; CODE XREF from main @ 0x140001022
|
||||||
|
| | 0x140001076 lea rcx, qword str.Inside_exception_handler ; 0x140002388 ; "Inside exception handler!\n" ; const char *s
|
||||||
|
| | 0x14000107d call qword [sym.imp.api_ms_win_crt_stdio_l1_1_0.dll_puts] ; [0x140002180:8]=0x2cbe ; int puts(const char *s)
|
||||||
|
| | 0x140001083 nop
|
||||||
|
| | 0x140001084 mov edx, 0xbadbeef ; int64_t arg2
|
||||||
|
| | 0x140001089 mov ecx, dword [var_18h] ; int64_t arg1
|
||||||
|
| | 0x14000108d call fcn.140001170
|
||||||
|
| |,=< 0x140001092 jmp 0x1400010a2
|
||||||
|
| || ; CODE XREF from main @ 0x140001084
|
||||||
|
| || 0x140001094 lea rcx, qword str.Divide_by_zero_exception ; 0x1400023a8 ; "Divide by zero exception!" ; const char *s
|
||||||
|
| || 0x14000109b call qword [sym.imp.api_ms_win_crt_stdio_l1_1_0.dll_puts] ; [0x140002180:8]=0x2cbe ; int puts(const char *s)
|
||||||
|
| || 0x1400010a1 nop
|
||||||
|
| || ; CODE XREFS from main @ 0x140001074, 0x140001092
|
||||||
|
| ``-> 0x1400010a2 xor eax, eax
|
||||||
|
| 0x1400010a4 mov rbx, qword [var_8h]
|
||||||
|
| 0x1400010a9 add rsp, 0x30
|
||||||
|
| 0x1400010ad pop rdi
|
||||||
|
\ 0x1400010ae ret
|
||||||
|
EOF
|
||||||
|
RUN
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue