timeline #15
Replies: 1 comment 1 reply
-
Hi,
Thank you, that's a great suggestion! We'll consider this for a future version.
Yes there should be! Since the API gives you access to the whole memory, you can fetch the current time of the system from memory. Assuming Windows, below is a small script to fetch the realtime at a context. import argparse
from datetime import datetime, timedelta
import reven2
# Cf https://www.geoffchappell.com/studies/windows/km/ntoskrnl/inc/api/ntexapi_x/kuser_shared_data/index.htm
kuser_shared_data_address_32 = 0xffdf0000
kuser_shared_data_address_64 = 0xfffff78000000000
system_time_offset = 0x14
timezone_bias_offset = 0x20
def get_system_time(ctx: reven2.trace.Context, mode: reven2.trace.Mode) -> datetime:
"""
Retrieves the system time at the given context and returns the corresponding datetime
Assumes Windows 7 or Windows 10, 32 or 64-bit.
"""
if mode == reven2.trace.Mode.X86_32:
system_time_address = kuser_shared_data_address_32 + system_time_offset
elif mode == reven2.trace.Mode.X86_64:
system_time_address = kuser_shared_data_address_64 + system_time_offset
else:
raise ValueError(f"Unsupported mode '{mode}'")
# The system time value is the number of "100ns periods" from January 1, 1601 (UTC)
system_time = ctx.read(
reven2.address.LinearAddress(system_time_address),
reven2.types.I64,
)
# To convert the system time to a valid timestamp we need to make it start at January 1, 1970
# for that we are substracting 116444736000000000 that is the number of "100ns periods" between
# January 1, 1601 and January 1, 1970
# As we have 10'000'000 "100ns periods" in a second, we need to divide the RTL system time by
# 10'000'000 to have the number of seconds since January 1, 1970
return datetime.fromtimestamp((system_time - 116444736000000000) / 10000000)
def get_local_time(ctx: reven2.trace.Context, mode: reven2.trace.Mode) -> datetime:
"""
Retrieves the local time at the given transition and returns the corresponding datetime
Assumes Windows 7 or Windows 10, 32 or 64-bit.
"""
if mode == reven2.trace.Mode.X86_32:
timezone_bias_address = kuser_shared_data_address_32 + timezone_bias_offset
elif mode == reven2.trace.Mode.X86_64:
timezone_bias_address = kuser_shared_data_address_64 + timezone_bias_offset
else:
raise ValueError(f"Unsupported mode '{mode}'")
# The timezone bias value is the number of "100ns periods" between the local time and the system time
timezone_bias = ctx.read(
reven2.address.LinearAddress(timezone_bias_address),
reven2.types.I64,
)
# To get the local time we need to get the system time and substract the bias between the local time and the system time
# For that we need to convert the bias in seconds with a division like we do in the system time
return get_system_time(ctx, mode) - timedelta(seconds=timezone_bias / 10000000)
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)",
)
parser.add_argument(
"--transition",
type=int,
required=True,
help="""Transition id. The context before this id will be searched.
Pass transition_count to get the time at the last context""",
)
parser.add_argument(
"--arch",
type=str,
choices=["win32", "win64"],
required=True,
help="The architecture for this scenario. This is currently required to know where to read the time."
)
args = parser.parse_args()
server = reven2.RevenServer(args.host, args.port)
if args.transition == server.trace.transition_count:
ctx = server.trace.context_after(args.transition)
else:
ctx = server.trace.context_before(args.transition)
if args.arch == "win32":
mode = reven2.trace.Mode.X86_32
elif args.arch == "win64":
mode = reven2.trace.Mode.X86_64
else:
raise ValueError(f"Unsupported architecture '{args.arch}'")
print(f"System time: {get_system_time(ctx, mode)}")
print(f"Local time: {get_local_time(ctx, mode)}") Here is the output on the script on a freshly recorded Win7 64b scenario: $ python get_system_time_final.py --transition 0 --arch win64 --port 44797
System time: 2021-12-20 08:53:59.716400
Local time: 2021-12-20 09:53:59.716400
$ python get_system_time_final.py --transition 90000000 --arch win64 --port 44797
System time: 2021-12-20 08:54:01.058000
Local time: 2021-12-20 09:54:01.058000 To compute the total execution time of the trace, you can use the script above in the following way: from get_system_time import get_system_time # assuming you saved the script as get_system_time.py
import reven2
server = reven2.RevenServer("localhost", 13370)
mode = reven2.trace.Mode.X86_64 # for 64b windows
end_time = get_system_time(server.trace.last_context, mode)
begin_time = get_system_time(server.trace.first_context, mode)
print(f"Total elapsed time: {end_time - begin_time}") Here is the sample output on my example scenario:
I guess this would make for a good entry in our API cookbook. Hope this will help! |
Beta Was this translation helpful? Give feedback.
-
Maybe it would be a good idea to add to the search widget a display of the real time of execution of the replay, it would be something like a timeline. I haven't found such a feature. I have a big replay and it would be much more convenient to be able to see how many real time it was executed and faster to search events, seeing the interval in real seconds between two transactions of the trace.
By the way, is there no way to get the value in seconds of execution of the whole trace using API?
And the value in seconds between two transactions?
Beta Was this translation helpful? Give feedback.
All reactions