Package related to data tainting.
Data tainting allows to follow the flow of some data throughout the execution trace. This package exposes the taint algorithm available in REVEN v2 through an (experimental and simplified) API.
>>> # Spawning a taint with a tainter.simple_taint >>> tainter = reven2.preview.taint.Tainter(trace) >>> taint = tainter.simple_taint(tag0="[ds:0xffff88007cb95800 ; 27]", from_context=trace.context_before(0), ... to_context=trace.context_after(2968406), is_forward=False) >>> taint Taint Object (from_context=Context before #0, to_context=Context before #2968407, direction=Backward, granularity=Instruction)
>>> # Getting changes and states from a taint >>> print(next(taint.change().all())) Taint change at #2960185 rep movsb byte ptr [rdi], byte ptr [rsi] Tainted memories: [phy:0x77bcccb8; 3] : gained[tag0,] [phy:0x7cb95818; 3] : lost[tag0,] >>> print(taint.state_at(trace.context_before(0))) Taint state at Context before #0 Tainted memories: [phy:0x779fe80e; 19] : [tag0,] [phy:0x779fe828; 1] : [tag0,] [phy:0x779fe83b; 7] : [tag0,]
The taint produces three types of results:
TaintState: the state of the taint at some
Context, that indicates which data is currently tainted.
TaintChange: a change to the state of taint at some
Transition, that indicates which data is newly tainted and which data just lost the taint.
TaintWarning: a list of warning messages associated to a range of
Transitions, that indicate that something may be incorrect in the taint propagation. Users are encouraged to check manually the correctness of these range of
Transitions, especially if the range contains one or more
TaintChange, in which case it is likely to have had an effect on the taint.
When data is tainted, it means that it is marked with a taint marker. During the (forward) taint propagation, if some piece of data that has a taint marker influences another, it also transmits the taint marker to this other piece of data (in backward propagation, the relationship is "depends on another").
The taint algorithm in REVENv2 can operate with multiple taint
markers. This means each piece of data can be marked with zero, one or
several taint markers. A marker is defined by its name, and by an
integer handle (for efficiency reasons when manipulating
In the simplified API, only two predefined taint markers, "tag0" and "tag1" are available in taints, but we plan to allow taints with an arbitrary number of taint markers in the future.
Compared to the other objects available in the API, the
Taint object is
special in several ways:
The two next sections go in details over these points.
While the taint can be very fast (may traverse billions of instructions in a few seconds), sometimes the taint process can last for a long time (especially when there are a lot of changes to the taint state). It would be possible to wait for the taint to finish before accessing the results, but meanwhile, your script would not be able to advance. The current taint makes its results available as soon as they are computed. This means that is you query the results on a taint that is not finished, you will not get all the results of the taint, only those that are computed at the time of the query.
The API exposes various handles to address this problem:
Progressclass gives you the current status of the taint (whether it is still running or not), and the last taint state that was computed.
>>> # Fetching the progress of a Taint >>> taint.progress() TaintProgress(last_known_state_id=0, status=Finished)
TaintResultViewclass. This builds "views" of the queried results, where results can be fetched by polling repeatedly the available results with the
TaintResultView.availablemethod, or the user can wait for all results to be produced with the
>>> # Fetching results >>> changes = taint.changes().available() >>> for change in changes.available(): ... print(change.transition.id) 21 27 52 >>> for change in changes.available(): ... print(change.transition.id) 87 101 >>> for change in taint.changes().all(): ... print(change.transition.id) 21 27 52 87 101
As of today, the main limitation to the taint being a server-side
background process is that there can only be one taint processed
at the same time per server. Starting a second taint, be it in
Axion of through the API by using
immediately cancels and discards the results of the first taint.
NOTE: Currently, starting a new taint can confuse Axion and Python clients that were in the middle of requesting results from a previous taint, resulting in the clients mixing results from the previous and the new taint. To avoid this issue, always make sure that no client is in the middle of requesting results from a taint before starting another one.
|Class||ChangeMarkers||Models gained and lost markers for a
|Class||MarkerIterator||Models an iterator over taint markers.|
|Class||MarkerManager||Manages the taint markers defined in a taint.|
|Class||Progress||Represent the status of the taint at the point where it was requested.|
|Class||PropagationDirection||Enum describing the taint direction|
|Class||ResultGranularity||Enum describing the taint result granularity.|
|Class||Taint||Represent a started taint in the backend, allowing to retrieve the taint results.|
|Class||TaintChange||A change between two taint states, containing information about which data became tainted or lost the taint.|
|Class||TaintChangeView||A view of the
|Class||TaintResultStatus||Enum describing the various statuses of a
|Class||TaintResultView||TThe abstract class from which any result view is derived.|
|Class||TaintState||A taint state lists all data that is currently tainted at a given
|Class||TaintStateView||A view of the
|Class||TaintWarning||A taint warning is a collection of warning messages that occurred during the taint.|
|Class||TaintWarningView||A view of the
|Class||TaintedMemories||Models a range of memory|
|Class||TaintedRegisterSlice||Models a slice of an architecture register, e.g.
|Class||Tainter||Entry point object for tainting data.|