Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
C
cwe_checker
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
fact-depend
cwe_checker
Commits
008a45d2
Unverified
Commit
008a45d2
authored
Apr 29, 2022
by
Enkelmann
Committed by
GitHub
Apr 29, 2022
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Change non-returning extern calls to dead ends in the CFG (#319)
parent
242c5325
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
43 additions
and
3 deletions
+43
-3
project.rs
...we_checker_lib/src/intermediate_representation/project.rs
+43
-3
No files found.
src/cwe_checker_lib/src/intermediate_representation/project.rs
View file @
008a45d2
...
...
@@ -37,6 +37,7 @@ impl Project {
self
.calling_conventions
.get
(
"__stdcall"
)
.or_else
(||
self
.calling_conventions
.get
(
"__cdecl"
))
.or_else
(||
self
.calling_conventions
.get
(
"__thiscall"
))
// for x86_64 Microsoft Windows binaries.
}
/// Try to find a specific calling convention in the list of calling conventions in the project.
...
...
@@ -98,14 +99,49 @@ impl Project {
}
}
/// Replace the return-to TID of calls to extern symbols that are marked as non-returning (e.g. `exit(..)`)
/// with the provided TID of an artificial sink block.
///
/// Returns `true` if at least one return target has been replaced this way.
fn
retarget_calls_to_non_returning_symbols_to_artificial_sink
(
&
mut
self
,
dummy_blk_tid
:
&
Tid
,
)
->
bool
{
let
mut
has_at_least_one_jmp_been_retargeted
=
false
;
for
sub
in
self
.program.term.subs
.values_mut
()
{
for
block
in
sub
.term.blocks
.iter_mut
()
{
for
jmp
in
block
.term.jmps
.iter_mut
()
{
if
let
Jmp
::
Call
{
target
,
return_
:
Some
(
return_tid
),
}
=
&
mut
jmp
.term
{
if
let
Some
(
extern_symbol
)
=
self
.program.term.extern_symbols
.get
(
target
)
{
if
extern_symbol
.no_return
{
// Call to an extern symbol that does not return.
*
return_tid
=
dummy_blk_tid
.clone
();
has_at_least_one_jmp_been_retargeted
=
true
;
}
}
}
}
}
}
has_at_least_one_jmp_been_retargeted
}
/// Replace jumps to nonexisting TIDs with jumps to a dummy target
/// representing an artificial sink in the control flow graph.
/// Return a log message for each replaced jump target.
/// Also retarget the return address of extern symbol calls that are marked as non-returning to the artificial sink.
///
/// Nonexisting jump targets may be generated by the Ghidra backend
/// if the data at the target address is not a valid assembly instruction.
#[must_use]
fn
remove_references_to_nonexisting_tids
(
&
mut
self
)
->
Vec
<
LogMessage
>
{
fn
remove_references_to_nonexisting_tids_and_retarget_non_returning_calls
(
&
mut
self
,
)
->
Vec
<
LogMessage
>
{
// Gather all existing jump targets
let
mut
jump_target_tids
=
HashSet
::
new
();
for
sub
in
self
.program.term.subs
.values
()
{
...
...
@@ -139,8 +175,11 @@ impl Project {
}
}
}
// Also replace return targets of calls to non-returning extern symbols
let
dummy_blk_needs_to_be_added
=
self
.retarget_calls_to_non_returning_symbols_to_artificial_sink
(
&
dummy_blk_tid
);
// If at least one dummy jump was inserted, add the corresponding dummy sub and block to the program.
if
!
log_messages
.is_empty
()
{
if
dummy_blk_needs_to_be_added
||
!
log_messages
.is_empty
()
{
let
dummy_sub
:
Term
<
Sub
>
=
Term
{
tid
:
dummy_sub_tid
,
term
:
Sub
{
...
...
@@ -181,13 +220,14 @@ impl Project {
///
/// Passes:
/// - Replace jumps to nonexisting TIDs with jumps to artificial sink targets in the CFG.
/// Also replace return addresses of non-returning external symbols with artificial sink targets.
/// - Duplicate blocks so that if a block is contained in several functions, each function gets its own unique copy.
/// - Propagate input expressions along variable assignments.
/// - Replace trivial expressions like `a XOR a` with their result.
/// - Remove dead register assignments
#[must_use]
pub
fn
normalize
(
&
mut
self
)
->
Vec
<
LogMessage
>
{
let
logs
=
self
.remove_references_to_nonexisting_tids
();
let
logs
=
self
.remove_references_to_nonexisting_tids
_and_retarget_non_returning_calls
();
make_block_to_sub_mapping_unique
(
self
);
self
.propagate_input_expressions
();
self
.substitute_trivial_expressions
();
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment