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
2808701c
Unverified
Commit
2808701c
authored
May 05, 2022
by
van den Bosch
Committed by
GitHub
May 05, 2022
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Stack alignment analysis (#317)
parent
2c469338
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
184 additions
and
1 deletions
+184
-1
mod.rs
src/cwe_checker_lib/src/analysis/mod.rs
+1
-0
mod.rs
...cker_lib/src/analysis/stack_alignment_substitution/mod.rs
+175
-0
tests.rs
...er_lib/src/analysis/stack_alignment_substitution/tests.rs
+0
-0
blk.rs
src/cwe_checker_lib/src/intermediate_representation/blk.rs
+1
-0
project.rs
...we_checker_lib/src/intermediate_representation/project.rs
+7
-1
No files found.
src/cwe_checker_lib/src/analysis/mod.rs
View file @
2808701c
...
...
@@ -9,5 +9,6 @@ pub mod function_signature;
pub
mod
graph
;
pub
mod
interprocedural_fixpoint_generic
;
pub
mod
pointer_inference
;
pub
mod
stack_alignment_substitution
;
pub
mod
string_abstraction
;
pub
mod
vsa_results
;
src/cwe_checker_lib/src/analysis/stack_alignment_substitution/mod.rs
0 → 100644
View file @
2808701c
//! Substitutes stack pointer alignment operations utilising logical AND with an arithmetic SUB operation.
//!
//! The first basic block of every function is searched for a logical AND operation on the stack pointer.
//! By journaling changes to the stack pointer an offset is calculated which is going to be used to alter the operation
//! into a subtraction.
//!
//! # Log Messages
//! Following cases trigger log messages:
//! - alignment is untypical for the architecture
//! - the argument for the AND operation is not a constant
//! - an operation alters the stack pointer, which can not be journaled.
use
anyhow
::{
anyhow
,
Result
};
use
apint
::
ApInt
;
use
itertools
::
Itertools
;
use
crate
::{
intermediate_representation
::
*
,
utils
::
log
::
LogMessage
};
/// Substitutes AND operation by SUB operation with calculated constants.
/// Constants are derived by a journaled stackpointer value and the bitmask provided by the operation.
fn
substitute
(
exp
:
&
mut
Expression
,
expected_alignment
:
i64
,
journaled_sp
:
&
mut
i64
,
tid
:
Tid
,
)
->
Vec
<
LogMessage
>
{
let
mut
log
:
Vec
<
LogMessage
>
=
vec!
[];
if
let
Expression
::
BinOp
{
op
,
lhs
,
rhs
}
=
exp
{
match
(
&**
lhs
,
&**
rhs
)
{
(
Expression
::
Var
(
sp
),
Expression
::
Const
(
bitmask
))
|
(
Expression
::
Const
(
bitmask
),
Expression
::
Var
(
sp
))
=>
{
if
let
BinOpType
::
IntAnd
=
op
{
if
ApInt
::
try_to_i64
(
&
ApInt
::
into_negate
(
bitmask
.clone
()))
.unwrap
()
!=
expected_alignment
{
log
.push
(
LogMessage
::
new_info
(
"Unexpected alignment"
)
.location
(
tid
));
}
let
offset
=
*
journaled_sp
-
(
*
journaled_sp
&
bitmask
.clone
()
.try_to_i64
()
.unwrap
());
let
sp
=
sp
.clone
();
*
op
=
BinOpType
::
IntSub
;
*
rhs
=
Box
::
new
(
Expression
::
Const
(
(
ApInt
::
from_i64
(
offset
))
.into_resize_unsigned
(
bitmask
.bytesize
()),
));
*
lhs
=
Box
::
new
(
Expression
::
Var
(
sp
));
}
else
{
log
.push
(
LogMessage
::
new_info
(
"Unsubstitutable Operation on SP"
)
.location
(
tid
))
};
}
_
=>
log
.push
(
LogMessage
::
new_info
(
"Unsubstitutable Operation on SP. Operants are not register and constant."
,
)
.location
(
tid
),
),
}
}
else
{
log
.push
(
LogMessage
::
new_info
(
"Unsubstitutable Operation on SP"
)
.location
(
tid
))
}
log
}
/// Updates current stackpointer value by given Constant.
fn
journal_sp_value
(
journaled_sp
:
&
mut
i64
,
is_plus
:
bool
,
(
rhs
,
lhs
):
(
&
Expression
,
&
Expression
),
sp_register
:
&
Variable
,
)
->
Result
<
()
>
{
match
(
rhs
,
lhs
)
{
(
Expression
::
Var
(
sp
),
Expression
::
Const
(
constant
))
|
(
Expression
::
Const
(
constant
),
Expression
::
Var
(
sp
))
=>
{
if
sp
==
sp_register
{
match
is_plus
{
true
=>
*
journaled_sp
+=
constant
.try_to_i64
()
.unwrap
(),
false
=>
*
journaled_sp
-
=
constant
.try_to_i64
()
.unwrap
(),
}
Ok
(())
}
else
{
Err
(
anyhow!
(
"Input not stackpointer register and constant."
))
}
}
_
=>
Err
(
anyhow!
(
"Input not register and constant."
)),
}
}
/// Substitutes logical AND on the stackpointer register by SUB.
/// Expressions are changed to use constants w.r.t the provided bit mask.
pub
fn
substitute_and_on_stackpointer
(
project
:
&
mut
Project
)
->
Option
<
Vec
<
LogMessage
>>
{
// for sanity check
let
sp_alignment
=
match
project
.cpu_architecture
.as_str
()
{
"x86_32"
=>
16
,
"x86_64"
=>
16
,
"arm32"
=>
4
,
_
=>
0
,
};
let
mut
log
:
Vec
<
LogMessage
>
=
vec!
[];
'sub_loop
:
for
sub
in
project
.program.term.subs
.values_mut
()
{
let
journaled_sp
:
&
mut
i64
=
&
mut
0
;
// only for the first block SP can be reasonable tracked
if
let
Some
(
blk
)
=
sub
.term.blocks
.first_mut
()
{
for
def
in
blk
.term.defs
.iter_mut
()
{
if
let
Def
::
Assign
{
var
,
value
}
=
&
mut
def
.term
{
if
*
var
==
project
.stack_pointer_register
{
if
let
Expression
::
BinOp
{
op
,
lhs
,
rhs
}
=
value
{
match
op
{
BinOpType
::
IntAdd
=>
{
if
journal_sp_value
(
journaled_sp
,
true
,
(
lhs
,
rhs
),
&
project
.stack_pointer_register
,
)
.is_err
()
{
continue
'sub_loop
;
}
}
BinOpType
::
IntSub
=>
{
if
journal_sp_value
(
journaled_sp
,
false
,
(
lhs
,
rhs
),
&
project
.stack_pointer_register
,
)
.is_err
()
{
continue
'sub_loop
;
}
}
_
=>
{
let
mut
msg
=
substitute
(
value
,
sp_alignment
,
journaled_sp
,
def
.tid
.clone
(),
);
log
.append
(
&
mut
msg
);
if
!
log
.iter
()
.filter
(|
x
|
{
x
.text
.contains
(
"Unsubstitutable Operation on SP"
)
})
.collect_vec
()
.is_empty
()
{
// Lost track of SP
continue
'sub_loop
;
}
}
}
}
else
{
log
.push
(
LogMessage
::
new_info
(
"Unexpected assignment on SP"
)
.location
(
def
.tid
.clone
()),
);
continue
'sub_loop
;
}
}
}
}
}
}
if
log
.is_empty
()
{
return
None
;
}
Some
(
log
)
}
#[cfg(test)]
mod
tests
;
src/cwe_checker_lib/src/analysis/stack_alignment_substitution/tests.rs
0 → 100644
View file @
2808701c
This diff is collapsed.
Click to expand it.
src/cwe_checker_lib/src/intermediate_representation/blk.rs
View file @
2808701c
...
...
@@ -194,6 +194,7 @@ mod tests {
use
crate
::
intermediate_representation
::{
Def
,
Expression
,
Variable
};
impl
Blk
{
/// Creates empty block with tid "block".
pub
fn
mock
()
->
Term
<
Blk
>
{
Term
{
tid
:
Tid
::
new
(
"block"
),
...
...
src/cwe_checker_lib/src/intermediate_representation/project.rs
View file @
2808701c
...
...
@@ -227,11 +227,17 @@ impl Project {
/// - Remove dead register assignments
#[must_use]
pub
fn
normalize
(
&
mut
self
)
->
Vec
<
LogMessage
>
{
let
logs
=
self
.remove_references_to_nonexisting_tids_and_retarget_non_returning_calls
();
let
mut
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
();
crate
::
analysis
::
dead_variable_elimination
::
remove_dead_var_assignments
(
self
);
logs
.append
(
crate
::
analysis
::
stack_alignment_substitution
::
substitute_and_on_stackpointer
(
self
)
.unwrap_or_default
()
.as_mut
(),
);
logs
}
}
...
...
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