PE x64 SEH fixes (#2310)

* Fix missing SEH scopes in x64 PE
* Fix multiple exception scopes in same address not adding flags
* Also add flags for the exception filter if it exists
* Fix assertion in `rz_analysis_block_update_hash()`
* Add call reference for exception filter
* Update old block's hash when creating a new block in trycatch analysis
* Fix try-catch control flow analysis
* Fix test
This commit is contained in:
GustavoLCR 2022-02-13 10:32:40 -03:00 committed by GitHub
parent 76508ec798
commit 5eaea7a552
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 48 additions and 46 deletions

View file

@ -792,6 +792,11 @@ static RzAnalysisBBEndCause run_basic_block_analysis(RzAnalysisTaskItem *item, R
ut64 from_addr = analysis->coreb.numGet(analysis->coreb.core, handle);
handle = rz_str_replace(handle, ".from", ".catch", 0);
ut64 handle_addr = analysis->coreb.numGet(analysis->coreb.core, handle);
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_REF_TYPE_CALL);
}
bb->jump = at + oplen;
if (from_addr != bb->addr) {
bb->fail = handle_addr;
@ -799,8 +804,9 @@ static RzAnalysisBBEndCause run_basic_block_analysis(RzAnalysisTaskItem *item, R
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, addr);
bb = fcn_append_basic_block(analysis, fcn, bb->jump);
if (!bb) {
gotoBeach(RZ_ANALYSIS_RET_ERROR);
}
@ -1455,11 +1461,14 @@ static RzAnalysisBBEndCause run_basic_block_analysis(RzAnalysisTaskItem *item, R
beach:
rz_analysis_op_fini(&op);
RZ_FREE(last_reg_mov_lea_name);
if (bb && bb->size == 0) {
rz_analysis_function_remove_block(fcn, bb);
if (bb) {
if (bb->size) {
rz_analysis_block_update_hash(bb);
} else {
rz_analysis_function_remove_block(fcn, bb);
}
rz_analysis_block_unref(bb);
}
rz_analysis_block_update_hash(bb);
rz_analysis_block_unref(bb);
free(movbasereg);
return ret;
}

View file

@ -363,7 +363,6 @@ static RzList *trycatch(RzBinFile *bf) {
ut64 baseAddr = bf->o->opts.baseaddr;
int i;
ut64 offset;
ut32 c_handler = 0;
struct PE_(rz_bin_pe_obj_t) *bin = bf->o->bin_obj;
PE_(image_data_directory) *expdir = &bin->optional_header->DataDirectory[PE_IMAGE_DIRECTORY_ENTRY_EXCEPTION];
@ -434,22 +433,8 @@ static RzList *trycatch(RzBinFile *bf) {
if (!rz_io_read_at_mapped(io, exceptionDataOff, (ut8 *)&handler, sizeof(handler))) {
continue;
}
if (c_handler && c_handler != handler) {
continue;
}
exceptionDataOff += sizeof(ut32);
if (!c_handler) {
ut32 magic, rva_to_fcninfo;
if (rz_io_read_at_mapped(io, exceptionDataOff, (ut8 *)&rva_to_fcninfo, sizeof(rva_to_fcninfo)) &&
rz_io_read_at_mapped(io, baseAddr + rva_to_fcninfo, (ut8 *)&magic, sizeof(magic))) {
if (magic >= 0x19930520 && magic <= 0x19930522) {
// __CxxFrameHandler3 or __GSHandlerCheck_EH
continue;
}
}
}
PE64_SCOPE_TABLE tbl;
if (!rz_io_read_at_mapped(io, exceptionDataOff, (ut8 *)&tbl, sizeof(tbl))) {
continue;
@ -469,7 +454,8 @@ static RzList *trycatch(RzBinFile *bf) {
}
if (!scope.JumpTarget) {
// scope.HandlerAddress == __finally block
continue;
scope.JumpTarget = scope.HandlerAddress;
scope.HandlerAddress = 1;
}
ut64 handlerAddr = scope.HandlerAddress == 1 ? 0 : scope.HandlerAddress + baseAddr;
RzBinTrycatch *tc = rz_bin_trycatch_new(
@ -478,7 +464,6 @@ static RzList *trycatch(RzBinFile *bf) {
scope.EndAddress + baseAddr,
scope.JumpTarget + baseAddr,
handlerAddr);
c_handler = handler;
rz_list_append(tclist, tc);
scopeRecOff += sizeof(PE64_SCOPE_RECORD);
}

View file

@ -4039,9 +4039,12 @@ static int bin_trycatch(RzCore *core, PJ *pj, int mode) {
int idx = 0;
// FIXME: json mode
rz_list_foreach (trycatch, iter, tc) {
rz_cons_printf("f try.%d.%" PFMT64x ".from @ 0x%08" PFMT64x "\n", idx, tc->source, tc->from);
rz_cons_printf("f try.%d.%" PFMT64x ".to @ 0x%08" PFMT64x "\n", idx, tc->source, tc->to);
rz_cons_printf("f try.%d.%" PFMT64x ".catch @ 0x%08" PFMT64x "\n", idx, tc->source, tc->handler);
rz_cons_printf("f+ try.%d.%" PFMT64x ".from @ 0x%08" PFMT64x "\n", idx, tc->source, tc->from);
rz_cons_printf("f+ try.%d.%" PFMT64x ".to @ 0x%08" PFMT64x "\n", idx, tc->source, tc->to);
rz_cons_printf("f+ try.%d.%" PFMT64x ".catch @ 0x%08" PFMT64x "\n", idx, tc->source, tc->handler);
if (tc->filter) {
rz_cons_printf("f+ try.%d.%" PFMT64x ".filter @ 0x%08" PFMT64x "\n", idx, tc->source, tc->filter);
}
idx++;
}
return true;

View file

@ -9,26 +9,31 @@ NAME=PE: seh_x64.exe - Get trycatchs
FILE=bins/pe/seh_x64.exe
CMDS=iw
EXPECT=<<EOF
f try.0.140001010.from @ 0x14000104c
f try.0.140001010.to @ 0x140001066
f try.0.140001010.catch @ 0x140001066
f try.1.140001010.from @ 0x140001022
f try.1.140001010.to @ 0x140001076
f try.1.140001010.catch @ 0x140001076
f try.2.140001010.from @ 0x140001084
f try.2.140001010.to @ 0x140001094
f try.2.140001010.catch @ 0x140001094
f try.3.140001170.from @ 0x140001192
f try.3.140001170.to @ 0x1400011c6
f try.3.140001170.catch @ 0x1400011c6
f try.4.14000132c.from @ 0x140001355
f try.4.14000132c.to @ 0x14000145a
f try.4.14000132c.catch @ 0x14000145a
f try.5.14000132c.from @ 0x14000148e
f try.5.14000132c.to @ 0x1400014a0
f try.5.14000132c.catch @ 0x14000145a
f try.6.1400015d0.from @ 0x1400015d7
f try.6.1400015d0.to @ 0x140001661
f try.6.1400015d0.catch @ 0x140001661
f+ try.0.140001010.from @ 0x14000104c
f+ try.0.140001010.to @ 0x140001066
f+ try.0.140001010.catch @ 0x140001066
f+ try.1.140001010.from @ 0x140001022
f+ try.1.140001010.to @ 0x140001076
f+ try.1.140001010.catch @ 0x140001076
f+ try.2.140001010.from @ 0x140001084
f+ try.2.140001010.to @ 0x140001094
f+ try.2.140001010.catch @ 0x140001094
f+ try.2.140001010.filter @ 0x140001d30
f+ try.3.140001170.from @ 0x140001192
f+ try.3.140001170.to @ 0x1400011c6
f+ try.3.140001170.catch @ 0x1400011c6
f+ try.3.140001170.filter @ 0x140001d50
f+ try.4.14000132c.from @ 0x140001355
f+ try.4.14000132c.to @ 0x14000145a
f+ try.4.14000132c.catch @ 0x14000145a
f+ try.4.14000132c.filter @ 0x140001d6b
f+ try.5.14000132c.from @ 0x14000148e
f+ try.5.14000132c.to @ 0x1400014a0
f+ try.5.14000132c.catch @ 0x14000145a
f+ try.5.14000132c.filter @ 0x140001d6b
f+ try.6.1400015d0.from @ 0x1400015d7
f+ try.6.1400015d0.to @ 0x140001661
f+ try.6.1400015d0.catch @ 0x140001661
f+ try.6.1400015d0.filter @ 0x140001d89
EOF
RUN