2010
07.04
http://www.youtube.com/watch?v=g_dQ1xp7AfE

When talking about new concepts, its always best to demonstrate them on something everyone is familiar with. In our case that's of-course UPX with which we are fairly familiar. It almost feels like we write one UPX unpacker each week, doesn't it?

Today we are presenting an optimization concept that enables us to unpack everything in a single go. Now, when talking about file unpacking we always unpack everything in one go, but we never unpack both the main executable module and all of its packed dependencies in a single run. Normally, you wold do this by batching through individual files.  But from a speed perspective, the best optimization imaginable comes from unpacking the main module and all of its dependencies at once. Since TitanEngine wasn't really designed to do that out-of-the-box, it needs just a little bit of help to pull it off.

The problem is the existence of multiple relocation tables, and more importantly multiple import tables. Since TitanEngine was designed to unpack files one at the time, we must do some additional coding around these boundaries to achieve our goal. Compared to a traditional TitanEngine dynamic unpacker, the only difference is the need to collect import table data for modules in one place, and use that data for any module that has reached its entry point jump. The UPX is a special case because it always imports packed file dependencies through the import table. This is, of course, a static way of importing libraries but our approach must be flexible enough to cover both dynamic and static importing.

To achieve our goal we have to scan the main module and all loaded libraries and try to find  the appropriate patterns. Once the patterns are found, we set breakpoints and store info about them so we know which module triggered which callback event. Normally we have three callbacks for UPX unpackers (LoadLibrary, GetProcAddress and EP jump) but since we are doing transverse unpacking we need one more: the load library event custom handler, which determines whether the loaded dependencies are packed with UPX by trying to find the neccessary breakpoint patterns. Even though it is impossible to have more than one module loading at a time, we still need to store the import data because the import tables for the main executable and dependencies might overlap if the modules are loaded dynamically. Once stored, the import info for each module is retrieved when it hits its entry point callback. Relocations aren't really a problem since there is just one module loading at a time, so we can use our "snapshot and compare" model, provided that modules load on non-default image bases. This can be done in numerous ways - one of the easiest is to compile the sample files so that they do that by default (which is considered cheating in the unpacking game), alternatively, we can pre-allocate the memory so that the modules have no choice but to pick another base address. For the purpose of this blog we cheated, in a real world application of this approach you mustn't.

In the real world you will hardly ever see this kind of case but if you do, you now know how to get everything in one go. Until next week...

TitanEngine

ReversingLabs Corporation
RL!deUPX
(package contains the unpacker with source and the samples used)

VN:F [1.9.13_1145]
Rating: +2 (from 2 votes)
Share
2010
06.24

Security is notoriously disunited. Every year multiple tools and projects are released and never maintained. TitanMist is its inverse opposite. Built on top of TitanEngine, it provides automation and manages all known and good PEID signatures, unpacking scripts and other tools in one unified tool. TitanMist is the nicely packaged and open source catch-all tool that will become your first line of defense. The project goes beyond pure tool development. It builds a forum to share information and reverse-engineering experience built around the biggest online and collaborative knowledge base regarding software packers.

With the increase in packed and protected malicious payloads, collaboration and quick response among researchers has become critical. As new sample numbers are quickly approaching 40M samples per year, the solution to this problem has to come from reverse-engineers themselves, integrating their prior and current work. Huge databases of format identification data and unpacking scripts can be reused to maximize automation. Yet, where do we find a definite collection of functional tools, identification signatures and unpacking tools? And how do we integrate them in a meaningful and accurate way?

Come to this talk to hear how we plan to raise reversing collaboration to a whole new level with TitanMist. We will address today's and future challenges, source code, packaging and distribution, and define your role in making TitanMist the most powerful community tool for years to come.

This talk will be a BlackHat exclusive; a launch and demonstration of TitanMist, a new open-source project based on TitanEngine. All components will be available for distribution with the conference materials.

See you in Vegas...

VN:F [1.9.13_1145]
Rating: +6 (from 6 votes)
Share
2010
06.23

Reverse engineering self defense

http://www.youtube.com/watch?v=-3nwk9DPsN4

If you remember not so long ago we wrote about minor inconveniences we encountered while working with OllyDBG. Today we return to that subject with challenges we face when reversing modern software protectors. One such protection is SafeEngine or NoobyProtect, which uses a simple portable executable malformation in order to crash OllyDBG. Even though this crash is limited to old OllyDBG versions, it is interesting for us nevertheless. The crash itself wouldn't be interesting if, in fact, the application didn't then operate normally. But it does, which makes it even more sinister. This leads us to conclude that this portable executable malformation is either ignored by the system or irrelevant to the system loader ... but not to our debugger. So, where's the trick? What does it apply to?

If you look at the import table you will see that the first entry is rather unusual. Its name in LordPE is "kernel32...". Which could be fine since the trailing ".dll" is optional. If only it wasn't for those three little dots. Those dots represent multiple new lines after the name. In fact if we open the file with a hex editor we see that there are exactly 0x100 bytes following the first import library name. And in addition, there are 0x3000 bytes that follow the name of the first imported function in the first library trunk. These extra bytes seem to be too large for Olly to handle, overwriting some memory and ultimately making it crash. Since EIP is rewritten to 0x0d0a0d0a this could be an exploitable attack vector. Now we knew about this kind of attack for a while, having first seen it as an attack via too long names in the export table. But this is a bigger issue, since the import table is affected.

If we investigate further we find an even more interesting issue that arises because of the way Windows processes the import table. If the import address table pointer inside the image import descriptor isn't nil and if it points to a sequence of eight zero bytes, the import entry will be ignored completely. Also, if the import lookup table pointer is valid and it points to at least one valid import address pointer, tools such as LordPE will read that data and display a list of functions that never get imported. This means that Windows will ignore the image import descriptor entry completely, which makes the dynamic link library name irrelevant as it will never reach the loading stage. This enables anyone to craft a file that only looks like its importing a specified library which may or may not be present on the system. And that can create confusion about which library is actually needed and which isn't.

This isn't something that NoobyProtect does - but it could if it wanted to. Working around our crash problem is as easy as updating to OllyDBG 2.0 or patching the broken import table. Until next week...

sampleFile
(package contains a harmless sample file that imports a non existent DLL)

VN:F [1.9.13_1145]
Rating: +2 (from 2 votes)
Share
2010
06.13

Lets try something totally crazy. Lets try dynamic unpacking without total unpacking control, without breakpoints, without any kind of debugging whatsoever. Lets merge our unpacking process with the packer itself, binding them into one unique work-flow that collects information while the packer is executing. It's similar to what we do with debugging - just without the debugger. How do we do this? Can we for that matter?

We can, with a little help from TitanEngine's hooking library. The idea is to use our unpacker as a library which will be injected into the packed file during its execution. Such a library would place hooks inside the packer code, redirecting the control flow to our unpacker wherever data collection or execution handling is needed. Those places are usually spots where the packer processes the import table or relocations, jumps to the original entry point, or just switches execution from one layer to another.

What are the benefits of such an approach? Even though its slightly harder to create and test such unpackers, the most notable benefit of unpacking by hooking is total immunity to various anti-debugging tricks used to detect the unpacking process. The only detection applicable to this unpacking scenario is anti-hooking and memory checksumming. The first is hardly ever used in modern protections due to the large number of false positives it gives, which are triggered by the operating system itself, security software and various window skinning applications. The second one is rarely present, and when it is it only covers specific memory regions that correspond to a single protection layer. In conclusion this method of implementing the unpacking process should result in fewer things to worry about.

Implementing this kind of hooking requires building custom functions to process the hook events. This is necessary to maintain the packed program work flow, and is exactly why we preserve the register state with PUSHAD, and if there is a jump affected by our hook, even EFLAGS with PUSHFD. These ASM instructions are embedded in our C code and with the help of naked pre-processor instruction they become the prologue and epilogue of the function. To apply the hooks we use the DLL_PROCESS_ATTACH event. For example if we were to hook the UPX code which loads libraries the hook code flow would look like this:

Since our hooks are 5 bytes we need to "borrow" as many instructions as we need to insert the hook. In this case we are "borrowing" three instructions. These instructions will be executed right after our inserted function is called. This is done to preserve the packer work flow. As you can see from this diagram we are using hooks instead of breakpoints. Therefore these hooks will be placed on at least three places: when UPX calls LoadLibraryA, GetProcAddress and finally once it jumps to the entry point. The most basic sample UPX unpacker is limited to working on executables that don't import functions by ordinals and use the old jump to entry point method. It's quite limited, but it's enough for a proof-of-concept of our technique.

Debugging this kind of unpacker can be rather tricky. This video shows a quick and easy way to do it:

http://www.youtube.com/watch?v=Sub3huN18qI

Since we are creating a hook library unpacker, we also need a loader which will execute the unpacking target and inject the unpacker library in it. This can be done in number of ways but we decided to do it via the debug - detach method. Once both the unpacker hook library and the loader are made, our unpacker is complete. We hope you got the idea on how to use this technique to build your own hooking unpackers from our short blog. Until next week...

TitanEngine

ReversingLabs Corporation
upxHooks
(package contains the unpacker with source and the samples used)

VN:F [1.9.13_1145]
Rating: +4 (from 6 votes)
Share
2010
06.05

ReversingLabs at Source Boston

Recording of a panel discussion at Source Boston 2010
Mario Vuksan - President, ReversingLabs Corporation

VN:F [1.9.13_1145]
Rating: +3 (from 3 votes)
Share
2010
06.03

CARO Workshop Recap

We had a great time during this year's CARO Workshop Conference held in Helsinki last week.  Now it is the time to sort out our impressions.  First of all, thanks to all that have made it to our talk and asked us many intriguing questions. Slides for our talk are available here. The picture you see above is from the brilliant keynote held by Dr. Alan Solomon. We absolutely enjoyed the keynote and Dr. Solomon's remark regarding the perfect antivirus represented by his three batch files.

Our talk was focused on improving the file analysis metrics and on unpacking technology performance testing,  comparing different solutions. During the talk we have presented a new idea for unpacking optimization.  We proposed unpacking through "binary layering" which enables the reuse of unpacking technology as much as possible. Put simply binary layering enables scanning various parts of the binary object and attributing them to known packing formats. Since multiple segments of the same file can have different formats attached to them we recognize that files commonly don't have simple identities but instead their complex layout is viewed as file's complex identity. These complex identities give much more detailed picture about the file itself and enable easy file categorization and further analysis.

We also talked about optimization that can improve file analysis system's metrics.   In this regard, we have shown that binary layering can improve the unpacking speed when identified segments are processed in parallel. Most objects can take advantage of this kind of optimization, but with some exceptions.  Specifically, this applies to cases where binary object requires other objects to be present in predefined way prevents unpacking one file at the time.   Similarly, it also applies to cases where there are multiple one way unpacking layers with output of the previous layer serving as input for the next one.

To test our hypothesis we did a comparative test using our lab tools and Kaspersky Anti-virus, which incorporates both file unpacking and malicious payload detection.   For the test to be relevant enough and to avoid inclusion of  malware scanning into unpacking metrics we have performed the following:

  • Inspecting metrics for our internal lab unpacking tools
  • Inspecting metrics for KAV on the predefined set of packed files
  • Inspecting metrics for KAV on the set of unpacked files produced by our internal lab tools

It is necessary to perform these three steps together in order to obtain relevant results.  Third step excludes unpacking from scanning results and therefore gets a relatively good comparison for unpacking metrics.  For the purpose of our presentation we performed two distinct tests, one on packed portable executable files and one on installer packages.  The first test has employed one way unpacking while the second test has used non-parallel "binary layering" to detect and unpack files. Here are the results for the first test:

This first test was performed on 1627 portable executable files packed with 140 different packer families. It  demonstrated that our internal tool (referred here as the "BlackBox") has successfully unpacked 95% of the files in 530 seconds. Remaining 74 files we declared as invalid either for static or dynamic analysis, indicating that file recovery can not be applied to salvage corrupt data. This means that reported 1568 objects is the number of output files that were processed by this unpacking library. KAV processed the same amount of files in 534 seconds reporting 4533 objects and 249 events. To clarify, KAV counts all files it finds inside the packed content (every packing level is counted) and then reports the actual number of files detected by its signatures. Number of events refers to all additional operations KAV performs on scanned files such as malware detection, quarantine or deletion action. Finally, in the last step KAV scanned 1568 unpacked files that were produced by BlackBox. Third step eliminates the need for unpacking since all files are already unpacked. This part completed in 300 seconds and KAV reported2042 objects and 35 events. To take into the account the unpacking that was initially performed with BlackBox we have added its execution time to the scan time. Results: KAV performs its scan faster with fewer objects that need scanning. Additionally, there are less events indicating false positive detection on the packer formats themselves .  Granted a small amount of packers used in our test base should be blacklisted as their main use historically has been to hide malicious payload.

Its important to note that the unpacking methods used by BlackBox and KAV are completely different. While KAV mostly uses static unpacking to decompress data to memory, our BlackBox uses both dynamic and static unpacking  methods to decompress data to disk with multiple drive accesses. It is slowed down even further when unpacking dynamic link libraries due to snapshot comparison to repair relocation table. Optimizations can be performed to improve these unpacking results, but none were used. Hence we feel confidant that if all of these unpackers were done using TitanEngine, a significant unpacking speed increase would be gained.

Now, lets move to our second, more interesting test.  Here are the results:

Our second test was performed on 20 selected non-malicious installer packages. We used another internally developed tool, here referred to as "Core", to produce 4275 files in 95 seconds.  In comparison, KAV scanned these same input packages in 300 seconds, reporting 9174 found files. In our last step, we have performed the scan on unpacked files produced by Core.  In that case KAV reported 12175 files with the unpacking finishing in 360 seconds (this is with the added time for file unpacking done by Core). Number of events reported is two and they refer to scan start and scan finish. No malicious objects were detected. Results: This test shows that when performing unpacking on files  that have been already unpacked by Core, KAV is able to scan 3000 more files in the time that is very close to the time needed to scan the packed content.  Further optimizations could certainly apply that would reduce this number even further.

In conclusion, our initial "binary layering" experiment has performed great in comparison to existing solutions., while our first test has demonstrated the value of diligent support for various packing formats.  As these were only lab experiments, much space is left for further optimization and implementation improvements. Until next week...

We had a great time during this year's CARO Workshop Conference held in Helsinki last week.  Now it is the time to sort out our impressions.  First of all, thanks to all that have made it to our talk and asked us many intriguing questions. Slides for our talk are available here. The picture you see above is from the brilliant keynote held by Dr. Alan Solomon. We absolutely enjoyed the keynote and Dr. Solomon's remark regarding the perfect antivirus represented by his three batch files.

VN:F [1.9.13_1145]
Rating: +1 (from 1 vote)
Share
2010
05.23

Being the huge file analysis geeks (you must be shocked by this, we know) that we are, we couldn't help solving the more than interesting #decodeme challenge from Sophos at this years AusCert. The challenge itself was printed on a T-Shirt and the puzzle looked exactly like this:

%~~~~~~~~~~~~~~~~~~~~~~~~%
|H4sIAAAAAAACA3P3dLOwTOxh|
|YGF4zsBg7tHJMApGwYgE////|
|V/zJwsjF8I9BB8QH5QkGjhYG|
|xj/MD'              gULH|
|JrY'                BbVi|
|Tlx|   Y4NgmoOxWoxH4yL5d|
|VDR|   oTseHh8f6WK359lQU|
|qJy\              \YJOGt|
|xhN5I\              \dlr|
|qoJvnIznRDXvHjPWZ   |SY7|
|Lz31nKtYPklkV0F6w   |AKr|
|1E17                ,Vk5|
|afng              ,hp63R|
|VsvNzy8u9qpU670lon11hvnS|
|KNWuSS+vrvNf3HV05beU0NXB|
|p71kJQQYrAFt8kQCpwMAAA==|
%~~~~~~~~~~~~~~~~~~~~~~~~%
  D  E  C  O  D  E  M  E

We are pretty sure that "S" stands for Sophos not Superman. Now, the first thing that comes to mind when you look at the "picture" is that the data around the "S" is important. And if we look at the last two letters we see the base64 trademark signature. Which means that all that data is an encoded message or a file. To decode it, we must strip that "S" to form a proper base64 data chain. Once done, the data looks like this:

H4sIAAAAAAACA3P3dLOwTOxhYGF4zsBg7tHJMApGwYgE////V/zJwsj
F8I9BB8QH5QkGjhYGxj/MDgULHJrYBbViTlxY4NgmoOxWoxH4yL5dVD
RoTseHh8f6WK359lQUqJyYJOGtxhN5IdlrqoJvnIznRDXvHjPWZSY7L
z31nKtYPklkV0F6wAKr1E17Vk5afnghp63RVsvNzy8u9qpU670lon11
hvnSKNWuSS+vrvNf3HV05beU0NXBp71kJQQYrAFt8kQCpwMAAA==

That data must be reverted to either text or binary to continue. First, we tried  an online base64 decoder but it returns a very strange string. So then, we decoded the data to a binary file and opened that with a hex editor, where we see the well known 0x1F 0x8B signature, which indicates that the decoded data is in fact a GZIP file. Now, we know GZip files may or may not store a file name, so when we decompress the packed data we do another hex data inspection to discover that the decompressed file is a GIF file. It's an image showing us this: Not quite readable, but once you zoom in on it, and lower-case it, it points to: http://www.sophos.com/anz/sofarsogood.html which holds the last piece of the puzzle.

Sadly last piece of the puzzle has nothing to do with file analysis whatsoever. Its a crypto challenge requiring you to play with letter substitution crypto algorithms. And this isn't something we are really interested in. You are however more than welcome to fiddle with it if you like. For some help on solving it check this out. Until next week...

VN:F [1.9.13_1145]
Rating: +2 (from 2 votes)
Share
2010
05.18

We are going to start today's blog with a short apology about the TitanEngine 2.0.3 availability during last week. Issue was that during certain amount of time during last week the old TitanEngine 2.0.2 was distributed instead of the fresh new version. This happened mainly because we were moving our hosting to a new server and mixed-up the TitanEngine packages.  We apologize for any inconvenience this might have caused and urge the users to update to current engine version. With that out of the way we can focus on the task at hand.

We have already talked about fixing the damaged, broken or missing files in several occasions. Based on what we know we created the Nexus TitanEngine plugin to deal with cases of missing dependencies and damaged files. Implementing the basic TitanEngine features to correct file abnormalities does however change the file checksum since modifications  needed to correct detected problems modify file and memory content. And that doesn't go well with software protections that check the file integrity during execution. One of those software protectors is tELock, and that is the starting point for today's blog. That and a question "How can we work around checksums when file repairing is necessary?".

Luckily for us most software protections only check the file integrity on disk while the memory integrity checks are only limited to protected data and the protection itself. Therefore we only need to worry about the integrity of the file on disk. To be able to fool any software protection integrity check in a generic way we need to know how these checks are performed. Usually is as simple as opening a file, reading its content in a buffer, hashing it with a custom hashing algorithm and checking if the hash is different then the one stored during file protection. So the logical place to catch the integrity checks is by hooking functions used open the file. Most commonly that involves hooking CreateFile API since all protections use it to gain access to protected file.

Hooking an API in a remote process is easy but not very practical since it involves injecting a DLL into the unpacking process and that isn't something we want to do. Other option is to set a breakpoint at the selected API and filter the information returned to the protection. In order to fool the checksum checks we do the following:

  • Detect if the file is broken (Nexus already did this)
  • Correct the damaged file and produce a backup file (Nexus already did this)
  • Catch all calls to CreateFileW API to determine when the integrity check is performed
  • Open a handle to backup file (which is valid for execution since its checksum is unaltered)
  • Pass the open handle back to protector so that backup file is hashed and its checksum is confirmed

Since we only place a breakpoint on CreateFileW API we need to filter the information somehow to make the program open the backup file which is unaltered and therefore has the correct checksum. We can alter the parameter string and possibly corrupt the memory or we can pass the correct handle back to the protection. To do that we open a handle to backup file inside the context of the debugger and duplicate it inside the context of the unpacking process. That new handle is then used by the software protection to read the data from the backup file which successfully fools any integrity check regardless of the checksum algorithm used. We do this handle switch only if the file which the protected file is trying to open is the file we are currently unpacking. Since this method is generic we can use it for any software protection, not just tELock.

To test out theory we intentionally damage the sample file by modifying a single non relevant byte. This damaged file is now named damaged.exe and the backup file which is the original one is named damaged.exe.bak. If we try to unpack damaged.exe file the unpacker will unpack the file correctly regardless of the damage done to the file. This process effectively simulates the scenario in which the Nexus plugin automatically corrects the damaged file. Until next week...

TitanEngine

ReversingLabs Corporation

NexusCheckSum
(package contains the plugin with source and the samples used)

VN:F [1.9.13_1145]
Rating: +1 (from 1 vote)
Share
2010
05.11

Its been a really long time since we made an unpacker for... well anything. Sure we did a format converter and some archive format unpacker but our last PE unpacker was (checks the blog) in February. So, lets get back to the basics and create a dynamic unpacker for PackMan. We already have an unpacker for PackMan? Its in the TitanEngine package already, you say? Well we do, but what's stopping us from having a little fun with unpacker optimizations?

There are a lot of optimizations one can do with the TitanEngine to make it work even faster then lightning. During the related unpacker execution timing research for our upcoming CARO Workshop talk we measured the impact that certain operations inside the engine itself have on the total unpacking time. We realized that there is significant space for performance improvement in certain unpacking areas which is especially important when we are processing large file volumes. Now, when unpacking files with unpackers built around the TitanEngine you get unpacker execution times quite similar to the sample execution time, except for cases where dynamic link library unpacking requires snapshots to correct the relocation table. in those cases we see a significant unpacking execution time increase. To counter this we can either do memory snapshots to memory or optimize relocation processing and avoid using snapshots at all.

Generally when talking about fixing relocation table we refer to the easy snap-and-compare method. However there is another way of making the unpacked dynamic link library valid for loading on non default base. We can use RelocaterGrabRelocationTableEx function for cases when the packer uses non modified relocation table, defined as it is in the PECOFF document. Relocation data is still compressed and can only be accessed just before the file is relocated, which is why we need a function to inspect the memory and determine the relocation table size. And that is exactly what RelocaterGrabRelocationTableEx does. It determines the size of the relocation table at the provided address and copies it to the engine for later exporting. If we look at the following PackMan code snippet which does the image relocation:

  OR ECX,ECX
  JE L018
  MOV EDI,DWORD PTR DS:[EBX+24]
  JMP L013
L004:
  XOR EAX,EAX
  LODS WORD PTR DS:[ESI]
  OR EAX,EAX
  JE L011
  AND AH,0F
  ADD EAX,DWORD PTR DS:[EBX]
  ADD DWORD PTR DS:[EDX+EAX],ECX
L011:
  CMP ESI,EDI
  JNZ L004
L013:
  MOV EDX,DWORD PTR DS:[EDI]
  LEA ESI,DWORD PTR DS:[EDI+8]
  ADD EDI,DWORD PTR DS:[EDI+4]
  TEST EDX,EDX
  JNZ L011
L018:
  POPAD
 

We can see that the relocation table is stored at EBX+0x24 address. Therefore by reading that memory pointer before the actual relocation occurs we have all the parameters we need to fix the relocation table. Passing that parameter to the RelocaterGrabRelocationTableEx will result in the engine reading the relocation table and estimating its size. Therefore we can just use the pointer we read at the EBX+0x24 address and the return from RelocaterEstimatedSize to correct the PE header for the unpacked file. However RelocaterEstimatedSize doesn't return the accurate size due to the system design. It must be reduced by 8 to be correct for all cases.

Since we are only updating the PE header data we can free the relocation table stored inside the engine with RelocaterCleanup. Once we dump the process relocation table fixing is as easy as updating the PE header fields. By doing the relocation table fixing this way we optimize the speed of execution by a significant percent. No actual data needs to be written to the file on the disk since it is already there and in the correct format. Furthermore you can start the debugging without the previously necessary DLL loading on the address other then default. If you choose to use that optimization as well packer execution time will be shorter since the file might not be relocated at all thus saving CPU cycles. Until next week...

TitanEngine

ReversingLabs Corporation

RL!dePackMan
(package contains the unpacker with source and the samples used)

VN:F [1.9.13_1145]
Rating: +2 (from 2 votes)
Share
2010
05.03

After few months of intense work and code polishing we are proud to present the next major update for the TitanEngine project. Latest update we labeled as TitanEngine 2.0.3. Even though the version incrementation is small the number of changes and the pure size of the code is vast. That is why we dedicate today's blog for listing all additions and changes done to the engine. So, what is new?

This update can be declared as a script update as we were driven by the idea that the TitanEngine should be as easy to use as and as widespread as possible. That is why we have extended the programming language support to LUA and Python, two very popular script languages. Traditionally these script languages execute in a console window with little to no graphical user interface which is why for this update we have integrated easy to use unpacker interface. This interface can be customized to fit your unpacker project and still enables you to use the TitanEngine with any supported script language without the need to make your unpacker a console project. But we didn't stop there, we realized that with more than 400 functions TitanEngine can be overwhelming at first glance. That is why we tried to simplify writing the most basic dynamic unpackers, lowering the knowledge barrier to learning only 5 engine's functions.

In addition to this we introduced a way to set any breakpoint type, be it INT3 single or double byte or UD2 breakpoints. This option was present as a global setting in the engine making it possible to set only one breakpoint type at the time. Now you can set different breakpoints for any byte pattern you choose within the same existing breakpoint manipulation functions.

Release without bug fixes is unimaginable. In this release we fixed all bugs that we are aware of. Thank you for all your reports, you keep TitanEngine with as bugs free as possible.

*Note: If you downloaded the old TitanEngine 2.0.2 instead of the new one please re-download the package as there was a small mix-up with the files while moving hosting servers. We apologize for the inconvenience.

TitanEngine 2.0.3 in numbers

  • 405 functions
  • 28,000+ lines of code
  • 44 usage samples
  • 6 supported programming languages
  • 390 pages of documentation
  • 1 download waiting to happen...

VN:F [1.9.13_1145]
Rating: +9 (from 9 votes)
Share