Migrate bookmarks from 2.5 to 2.6
Purpose
We fixed an issue in Reven 2.6 leading to some changes in the transition number for QEMU scenarios.
This script is here to help you migrate your bookmarks if they are off after replaying your scenario with Reven 2.6.
How to use
Launch after updating the trace resource for your scenario to Reven 2.6+.
usage: migrate_bookmarks_2.5_to_2.6.py [-h] [--host HOST] [-p PORT]
optional arguments:
-h, --help show this help message and exit
--host HOST Reven host, as a string (default: "localhost")
-p PORT, --port PORT Reven port, as an int (default: 13370)
Known limitations
- It also does not attempt to determine whether the scenario needs to be upgraded or not. Applying the script when bookmarks don't need to be upgraded will actually put them at the wrong position. Apply only if you notice that the bookmarks have been put at the wrong position after updating.
Supported versions
Reven 2.6+
Supported perimeter
Reven scenarios recorded with QEMU.
Dependencies
None.
Source
#!/usr/bin/env python3
import argparse
import sys
import reven2
"""
# Migrate bookmarks from 2.5 to 2.6
## Purpose
We fixed an issue in Reven 2.6 leading to some changes in the transition number for QEMU scenarios.
This script is here to help you migrate your bookmarks if they are off after replaying your scenario with Reven 2.6.
## How to use
Launch after updating the trace resource for your scenario to Reven 2.6+.
```bash
usage: migrate_bookmarks_2.5_to_2.6.py [-h] [--host HOST] [-p PORT]
optional arguments:
-h, --help show this help message and exit
--host HOST Reven host, as a string (default: "localhost")
-p PORT, --port PORT Reven port, as an int (default: 13370)
```
## Known limitations
- It also does not attempt to determine whether the scenario needs to be upgraded or not.
Applying the script when bookmarks don't need to be upgraded will actually put them at the wrong position.
Apply only if you notice that the bookmarks have been put at the wrong position after updating.
## Supported versions
Reven 2.6+
## Supported perimeter
Reven scenarios recorded with QEMU.
## Dependencies
None.
"""
def migrate_bookmarks(reven_server):
offset_table = {}
def get_offset(transition_id):
lower_bound = None
for key in offset_table.keys():
if key <= transition_id and (lower_bound is None or lower_bound < key):
lower_bound = key
return offset_table[lower_bound] if lower_bound is not None else 0
print("Generating offset table...")
c = reven_server.trace.context_before(0)
counter = 0
while c is not None:
c = c.find_register_change(reven2.arch.x64.cr2)
if c is None:
continue
t_exception = c.transition_before()
t_before_exception = t_exception - 1
ctx_before = t_exception.context_before()
ctx_after = t_exception.context_after()
# We are looking for code pagefault, so CR2 will contains PC
cr2 = ctx_after.read(reven2.arch.x64.cr2)
if ctx_before.is64b():
if cr2 != ctx_before.read(reven2.arch.x64.rip):
continue
else:
if cr2 != ctx_before.read(reven2.arch.x64.eip):
continue
try:
# The issues occurred when the previous instruction was just doing some reads and not any write
# Warning: This could not work if the trace is desync with the memory
next(t_before_exception.memory_accesses(operation=reven2.memhist.MemoryAccessOperation.Write))
except StopIteration:
counter += 1
offset_table[t_exception.id - counter] = counter
print("Migrating bookmarks...")
for bookmark in list(reven_server.bookmarks.all()):
offset = get_offset(bookmark.transition.id)
print(
" id: %d | %60.60s | Transition #%d => #%d (+%d)"
% (bookmark.id, bookmark.description, bookmark.transition.id, bookmark.transition.id + offset, offset)
)
if offset == 0:
continue
reven_server.bookmarks.add(bookmark.transition + offset, bookmark.description)
reven_server.bookmarks.remove(bookmark)
if __name__ == "__main__":
parser = argparse.ArgumentParser()
parser.add_argument("--host", type=str, default="localhost", help='Reven host, as a string (default: "localhost")')
parser.add_argument("-p", "--port", type=int, default=13370, help="Reven port, as an int (default: 13370)")
args = parser.parse_args()
answer = ""
while answer not in ["y", "n"]:
answer = input(
"This script should be launched on a QEMU scenario with the trace generated with Reven 2.6 with bookmarks"
" that were added in Reven 2.5 or older. Do you want to continue [Y/N]? "
).lower()
if answer == "n":
print("Aborting")
sys.exit(0)
reven_server = reven2.RevenServer(args.host, args.port)
migrate_bookmarks(reven_server)
print("Bookmarks migrated!")