Announcing REVEN version 2.6


Sep 15, 2020
by Louis and Marc
Categories: REVEN -
Tags: REVEN - Announcement - Releases -




Tetrane is pleased to announce that the release of REVEN 2.6 Enterprise and Professional is available.

REVEN is an automated Reverse Engineering Platform designed to go x10 faster & x10 deeper using Timeless Analysis. Technically, REVEN captures a time slice of a full system execution (CPU, Memory, Hardware events) to provide unique analysis features that speed up and scale your reverse engineering process.

Reverse Engineering can sometimes feel like trying to find a needle in the proverbial haystack. For REVEN version 2.6, we really wanted to provide new ways of finding the information you seek in your scenarios, faster. This translates to new key features and improvements for searching data in memory and following the data flow.

This article covers the most important changes introduced in the REVEN 2.6 release.

Search in memory throughout the entire trace

More often than not, users report, the needle is a pattern of bytes, and the haystack is the entirety of the memory. In REVEN, where the state of the memory is available during the billions of instructions a trace may contain, this is quite the large haystack…

Well, looking for specific patterns of bytes appearing or used in memory at any moment of the recorded system execution is now possible with REVEN 2.6.

This has many important applications, such as:

  • finding the aliases of a pointer in memory,
  • finding usages of cryptography by looking for cryptographic constants,
  • finding strings: while this use case is already covered by our dynamic string algorithm, the new algorithm allows to find strings outside the size parameters of the traditional strings algorithm, such as “MZ” (magic for Microsoft Windows executables) wich only contains 2 letters.
  • Identifying where/if a file is mapped in memory by looking for its content,
  • surely you can think of other use cases?

The new search in memory in whole trace feature is available in the Analysis API.


  • Search bytes in memory anywhere in the trace!

More Microsoft WinDbg integration

When your needle is more in the shape of a file handle, WinDbg can help you get more information about it. We already covered how REVEN synergizes with WinDbg. In REVEN 2.6, browsing the REVEN trace from WinDbg is made easier, as you can now use stepping commands and breakpoints.


  • Work from WinDbg while using the power of REVEN for data tainting, memory history, the API, and more!

Slicing

What if someone could chomp through that big pile of hay, made of the billions of instructions executed in your system during the recording, and reduce it to a handful of straws, together with your needle? This is the work that REVEN’s taint is doing for you.

Starting with REVEN 2.6, the taint now returns the instructions that use tainted data. With this new feature, you can now extract a shorter program, containing only the instructions that are relevant to the tainted data, allowing the taint to act as a slicer.

This feature was notably inspired by our discussions with Richard Johnson about triaging and bucketing crashes out of fuzzer (look at his next online training for more details). It is very useful to analyze algorithms by removing the fluff that is not directly linked to the data at hand.

This feature means that when tainting e.g. rax forward in the following code:

0: add rbx, rax
1: mov rcx, 0x2a
2: inc rbx
3: add rbx, rax
4: add rcx, rax

Only instructions 0 and 4 change the taint (notably, adding rbx and rcx to the taint) and would be reported when only the changes are reported, while in REVEN 2.6, you have the option of getting all instructions that use tainted data, which adds instructions 2 and 3 to the results (but rightfully still excludes instruction 1).

This gives you a better picture of what happens to rbx in this small example, and to your tainted data in general.

  • Extract sub-programs that are relevant to your tainted data!

“ltrace-like” tool

For several releases, we have been steadily adding scripts, API entries and features to make your life as an analyst easier, be it analyzing a system trace or automate the analysis process.

Parallel to this release, we are releasing on Github a new “ltrace-like” tool.

For a given binary in the trace, this tool finds all the calls to functions of other binaries, complete with their parameters and return types.

You can even add your own signatures to the system for more calls to be recognized!

The following invocation of REVEN’s ltrace:

python3 -m reven2_ltrace c:/users/reven/documents/tokio_simple_tcp/tokio_simple_tcp/target/release/chat_server.exe

Yields the (edited for brevity) output below:

Generating LALR tables
Generating LALR tables
#6211337 ? ntdll!RtlAcquireSRWLockExclusive() = 0x7ffb6f38d760 at #6211349
#6211363 ? kernel32!TlsGetValueStub() = 0xc7aad0 at #6211372
#6211533 ? ntdll!RtlAcquireSRWLockExclusive() = 0x7ffb6f38d760 at #6211545
[...]
#6219611 ? kernel32!TlsGetValueStub() = 0xc7aad0 at #6219619
#6219713 int ws2_32!recv(SOCKET s=0x190, char * buf='' 0xc7e60d, int len=2035, int flags=0) = 4294967295 at #6221279
#6221283 int ws2_32!WSAGetLastError() = 10035 at #6221287
#6221291 int ws2_32!WSAGetLastError() = 10035 at #6221295
#6221477 int ws2_32!WSARecv(SOCKET s=0x190, LPWSABUF lpBuffers=0x29fe448, DWORD dwBufferCount=1, LPDWORD lpNumberOfBytesRecvd=44033088, LPDWORD lpFlags=44033092, LPWSAOVERLAPPED lpOverlapped=0xc8df50, LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine=0x0) = 4294967295 at #6223611
#6223615 int ws2_32!WSAGetLastError() = 997 at #6223619
#6223674 ? kernel32!TlsGetValueStub() = 0xc7aad0 at #6223683
#6223726 ? ntdll!RtlReleaseSRWLockExclusive() = 1 at #6223731
[...]
#6225025 ? ntdll!RtlEnterCriticalSection() = 0 at #6225033
#6225047 ? kernel32!TlsGetValueStub() = 0xc7aad0 at #6225055
#6225385 addr msvcrt!memcpy(addr arg1=0xc67760, string arg2='Received line () : \n' 0x5cbf2b, ulong arg3=15) = 0xc67760 at #6225439
#6225828 addr msvcrt!memcpy(addr arg1=0xc6776f, string arg2='b"' 0x5e04f8, ulong arg3=2) = 0xc6776f at #6225852
#6226302 addr msvcrt!memcpy(addr arg1=0xc67771, string arg2='B' 0x29fe3bc, ulong arg3=1) = 0xc67771 at #6226320
#6226773 addr msvcrt!memcpy(addr arg1=0xc67772, string arg2='o' 0x29fe3bc, ulong arg3=1) = 0xc67772 at #6226791
#6227244 addr msvcrt!memcpy(addr arg1=0xc67773, string arg2='b' 0x29fe3bc, ulong arg3=1) = 0xc67773 at #6227262
#6227610 addr msvcrt!memcpy(addr arg1=0xc67774, string arg2='"' 0x5e0630, ulong arg3=1) = 0xc67774 at #6227629
#6227910 addr msvcrt!memcpy(addr arg1=0xc67775, string arg2=') : \n' 0x5cbf3a, ulong arg3=4) = 0xc67775 at #6227944
#6228257 addr msvcrt!memcpy(addr arg1=0xc67779, string arg2='Some' 0x5cc2a0, ulong arg3=4) = 0xc67779 at #6228291
#6232980 addr msvcrt!memcpy(addr arg1=0xc6777d, string arg2='(),\n, {' 0x61f95c, ulong arg3=1) = 0xc6777d at #6232999
#6233399 addr msvcrt!memcpy(addr arg1=0xc6777e, string arg2='b"' 0x5e04f8, ulong arg3=2) = 0xc6777e at #6233423
#6233873 addr msvcrt!memcpy(addr arg1=0xc67780, string arg2='H' 0x29fe27c, ulong arg3=1) = 0xc67780 at #6233891
#6234344 addr msvcrt!memcpy(addr arg1=0xc67781, string arg2='e' 0x29fe27c, ulong arg3=1) = 0xc67781 at #6234362
#6234815 addr msvcrt!memcpy(addr arg1=0xc67782, string arg2='l' 0x29fe27c, ulong arg3=1) = 0xc67782 at #6234833
#6235286 addr msvcrt!memcpy(addr arg1=0xc67783, string arg2='l' 0x29fe27c, ulong arg3=1) = 0xc67783 at #6235304
#6235757 addr msvcrt!memcpy(addr arg1=0xc67784, string arg2='o' 0x29fe27c, ulong arg3=1) = 0xc67784 at #6235775
#6236229 addr msvcrt!memcpy(addr arg1=0xc67785, string arg2='!' 0x29fe27c, ulong arg3=1) = 0xc67785 at #6236247
#6236595 addr msvcrt!memcpy(addr arg1=0xc67786, string arg2='"' 0x5e0630, ulong arg3=1) = 0xc67786 at #6236614
#6236918 addr msvcrt!memcpy(addr arg1=0xc67787, string arg2='),\n, {' 0x61f95d, ulong arg3=1) = 0xc67787 at #6236937
#6237204 addr msvcrt!memcpy(addr arg1=0xc67788, string arg2='\n' 0x5cbf3e, ulong arg3=1) = 0xc67788 at #6237223
#6237289 ? kernel32!GetStdHandleStub() = 36 at #6237307
#6237317 BOOL kernel32!GetConsoleMode(HANDLE hConsoleHandle=0x24, LPDWORD lpMode=44032800) = true at #6250429
#6250621 ? kernel32!GetProcessHeapStub() = 0xc50000 at #6250625
#6250633 ? ntdll!RtlAllocateHeap() = 0xc8d490 at #6250886
#6251133 ? kernel32!GetProcessHeapStub() = 0xc50000 at #6251137
#6251146 ? ntdll!RtlReAllocateHeap() = 0xc7bb10 at #6251824
#6252066 ? kernel32!GetProcessHeapStub() = 0xc50000 at #6252070
#6252079 ? ntdll!RtlReAllocateHeap() = 0xc6a2d0 at #6252762
#6253143 BOOL kernel32!WriteConsole(HANDLE hConsoleOutput=0x24, const VOID * lpBuffer=0xc6a2d0, DWORD nNumberOfCharsToWrite=41, LPDWORD lpNumberOfCharsWritten=44032860, LPVOID lpReserved=0x0) = true at #6359213
#6359242 ? kernel32!GetProcessHeapStub() = 0xc50000 at #6359246
#6359254 ? kernel32!HeapFreeStub() = 1 at #6359412
#6359530 addr msvcrt!memcpy(addr arg1=0xc67760, string arg2='' 0x5cbf3f, ulong arg3=0) = 0xc67760 at #6359543
#6359635 ? kernel32!TlsGetValueStub() = 0xc7aad0 at #6359643
#6359671 ? ntdll!RtlLeaveCriticalSection() = 0 at #6359688
#6359754 addr msvcrt!memcpy(addr arg1=0x29fe929, string arg2='Bob\r\nHello!\r\n' 0xc7e600, ulong arg3=3) = 0x29fe929 at #6359783
#6359892 addr msvcrt!memcpy(addr arg1=0x29feb24, string arg2=': \r\nsrc\\bin\\chat_server.rs' 0x5cbff0, ulong arg3=2) = 0x29feb24 at #6359916
#6360043 addr msvcrt!memcpy(addr arg1=0x29feb26, string arg2='Hello!\r\n' 0xc7e605, ulong arg3=6) = 0x29feb26 at #6360087
#6360210 addr msvcrt!memcpy(addr arg1=0x29feb2c, string arg2='\r\nsrc\\bin\\chat_server.rs' 0x5cbff2, ulong arg3=2) = 0x29feb2c at #6360234
#6360284 ? ntdll!RtlAcquireSRWLockExclusive() = 0x7ffb6f38d760 at #6360296
#6360310 ? kernel32!TlsGetValueStub() = 0xc7aad0 at #6360318
[...]
#6366436 ? kernel32!GetProcessHeapStub() = 0xc50000 at #6366440
#6366448 ? kernel32!HeapFreeStub() = 1 at #6366606
#6366869 addr msvcrt!memcpy(addr arg1=0xc62359, string arg2='Bob: Hello!\r\n' 0x29fea21, ulong arg3=13) = 0xc62359 at #6366913
#6367096 ? ntdll!RtlAcquireSRWLockExclusive() = 0x7ffb6f38d760 at #6367108
#6367122 ? kernel32!TlsGetValueStub() = 0xc7aad0 at #6367130
#6367179 ? kernel32!TlsGetValueStub() = 0xc7aad0 at #6367187
#6367230 ? ntdll!RtlReleaseSRWLockExclusive() = 1 at #6367235

#6367336 ? ntdll!RtlAcquireSRWLockExclusive() = 0x7ffb6f38d760 at #6367348
#6367362 ? kernel32!TlsGetValueStub() = 0xc7aad0 at #6367370
[...]
#6370834 ? ntdll!RtlReleaseSRWLockExclusive() = 1 at #6370839
#6370896 addr msvcrt!memcpy(addr arg1=0xc8d470, string arg2='Bob: Hello!\r\n' 0xc62359, ulong arg3=13) = 0xc8d470 at #6370940
#6371080 int ws2_32!WSASend(SOCKET s=0x18c, LPWSABUF lpBuffers=0x29fe648, DWORD dwBufferCount=1, LPDWORD lpNumberOfBytesSent=44033604, DWORD dwFlags=0, LPWSAOVERLAPPED lpOverlapped=0xc54f08, LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine=0x0) = 0 at #6389588
#6389730 ? kernel32!GetProcessHeapStub() = 0xc50000 at #6389734
#6389742 ? kernel32!HeapFreeStub() = 1 at #6389900
#6389931 ? kernel32!TlsGetValueStub() = 0xc7aad0 at #6389939
#6389983 ? ntdll!RtlReleaseSRWLockExclusive() = 1 at #6389988
#6390338 ? kernel32!TlsGetValueStub() = 0xc5be80 at #6390346
[...]
#6775659 ? kernel32!SwitchToThreadStub() = 1 at #6782940
[...]
#6787011 ? kernel32!QueryPerformanceCounterStub() = 1 at #6787234
WAR: No ret point found for `#6787309 jmp qword ptr [rip + 0xb07a2]`
#6787309 ? kernel32!GetQueuedCompletionStatusExStub() = ? at #unknown
  • Retrace the life of a binary by tracing its calls to external binaries, from within REVEN!

Automatic recording of binaries

Recording a binary execution is simpler than ever from the Project Manager (Enterprise Edition). Just pick the binary and everything else is automated (uploading your binary and files to the VM, starting the VM, etc.). The record starts when the binary execution starts, and then automatically stops when the binary exits. It works even if the binary or the VM crashes! Once the VM has been recorded, the record is ready to be replayed in REVEN so you can analyze it.


Note: The program used in the example, hors, is a funny little CLI tool that takes a code question as input and attempts to output an answer extracted from StackOverflow.

  • Fast recording process that produces smaller traces focused on what you are interested in, for a faster replaying process and an easier analysis.

And More

  • REVEN can now be used when behind a proxy
  • Symbols are now displayed in the Bookmark widget, and the Backtrace widget is more reactive
  • Made several UX improvements to the Hexdump widget

The full list of improvements and fixes is available in the release notes.

Want to try REVEN? An extensive set of learning scenarios is available online, so just pick one from our demo catalog! Tutorials are available in most demos.

Interested in REVEN? Compare the features of REVEN Professional and REVEN Enterprise.

Next post: Buffer overflow exploitation in Quick Player 1.3 (unicode & SEH)
Previous post: Interactive write-ups with REVEN and Jupyter