Analysis of CVE-2013-3906 (TIFF)

This is just a demonstration of malware analysis with Profiler, I haven’t looked into previous literature on the topic. So, perhaps there’s nothing new here, but I hope it will be of help for our users.

We open the main DOCX file. The first embedded file we analyze is the TIFF image, which stands out because it’s the only image.

TIFF directories

Among the directories we have two which specify an embedded JPEG. So we just select the data area according to the offset and length value and load it as an embedded JPEG (it’s a good idea to do this automatically in the future: bear with us, TIFF support has been just introduced).

JPEG data

JPEG embedded

Now we can inspect the embedded JPEG.

JPEG meta

The JPEG looks strange. Even by looking at the format fields, it looks malformed. Given certain anomalies we can suppose that the TIFF might be used as some sort of vector for something. Let’s keep that in mind and let’s take a look at other files. Two of them stand out: they have a .bin extension and are CFBFs (same format as DOC files).

CFBF Foreign

We immediately notice various problems. Foreign data is abundant and the file looks malformed. More alarmingly lots of shellcode warnings are reported. Let’s look at a random one (they are all the same basically).

CFBF Shellcode

Let’s start with the analysis of this shellcode.

The start of the shellcode is just a decryption loop which xors every byte following the last call with 0xEE. So, that’s exactly what we’re going to do. We select 0x27E bytes after the last call, then we press Ctrl+T to open the filters view.

Decrypt shellcode

We use two filters: ‘misc/basic‘ to xor the bytes and ‘disasm/x86‘ to disassemble them.

At this point it’s useful to load the shellcode into a debugger. So let’s select the decrypted shellcode and press Ctrl+R and activate the ‘Shellcode to executable‘ action:

Shellcode to executable

The options dialog will pop up.

Shellcode to executable options

After pressing OK, the debugger will be executed. Depending on your debugger, put a break-point on the beginning of the shellcode and run the code.

The start of the shellcode resolves API addresses:

This code basically retrieves the base of ‘kernel32.dll‘ and then resolves API address by calling 0x120d for 0x12 times (which is the amount of APIs to be resolved).

This is the function which resolves API names hashes to addresses:

The API hashes are stored at the end of the shellcode. Here are the hashes and the resolved APIs:

We can actually close the debugger now. Once the API names are known, it’s easy to continue the analysis statically.

The next step in the shellcode is to suspend all other threads in the current process:

It then looks for the handle in the current process for the main DOCX file:

It reads the entire file (minus the first 0x24 bytes) into memory and looks for a certain signature:

It creates a new file in the temp directory:

Now comes the juicy part. It reads few parameters after the matched signature, including a size parameter, and uses these parameters to decrypt a region of data:

Let’s select in the hex view the same region (we find the start address by looking for the signature just as the shellcode does).

Encrypted payload

Then we press Ctrl+E to add an embedded file and we click on filters. Since the decryption routine is too complex to be expressed through a simple filter, we have finally a good reason to use a Lua filter, in particular the ‘lua/custom‘ one.

Lua custom filter

As you can see, a sample stub is already provided when clicking on the script value in the options. We have to modify it only slightly for our purposes.

By clicking on preview, we can see that the file start with a typical MZ header. Thus, we can specify a PE file when loading the payload.

PE payload

By inspecing the PE file we can see that it’s a DLL among other things. Now, before analyzing the DLL, let’s finish the shellcode analysis.

The payload is now decrypted. So the shellcode just writes it to the temporary file, loads the DLL, unloads it and then terminates the current thread.

That’s it. Now we can go back to the payload dll.

One of the resources embedded in the PE file is a DOCX.

Payload DOCX

Probably a sane document to re-open in a reader to avoid making the user suspicious of a document which didn’t open.

There’s another suspicious embedded resource, but before making hypotheisis about it, let’s do a complete analysis of the DLL, (don’t worry: it’s very small). For this purpose I used IDA Pro and the decompiler.

It starts with the DllMain:

The called function:

It basically retrieves both embedded resources and then performs some stuff with both of them. First we take a look at what it does with the DOCX resource:

As hypothized previously, it just launches a new instance of the current process with the sane DOCX this time.

Now let’s take a look at what it does with the resource we haven’t yet identified:

It dumps it to file (with a vbe extension) and then executes it with ‘cscript.exe‘. I actually didn’t know about VBE files: they’re just encoded VBS files. To decode it I used an online tool by GreyMagic.

VBE resource

The VBS code is quite easy to read and quite boring. The only interesting part in my opinion is the update mechanism.

It basically looks for certain comments in two YouTube pages with a regex. The url captured by the regex is then used to perform the update.

It sends back to the URL various information about the current machine:

As a final anecdote: the main part of the script just contains an enormous byte array which is dumped to file. The file is a PNG with a RAR file appended to it which in turn contains a VBE encoding executable. The script itself doesn’t seem to make use of this, so no idea why it’s there.

Appended RAR

That’s all. While it may seem a lot of work, writing the article took much longer than performing the actual analysis (~30 minutes, including screenshots).

We hope it may be of help or interest to someone.

News for version 1.1

And here it is.

added libmagic to the SDK
added preliminary ELF support
added TIFF support
– added GZ, BZ2 and LZMA file support
– exposed internal API for files and paths to Python
– hooks are now triggered even when loading embedded objects in the workspace
added magic info extension script
– exposed more DEX methods to Python
– remember manually enabled extensions
– capability to add individual files in the scan page
– some bug fixes

Enjoy.

TIFF Support

The upcoming 1.1 version of Profiler includes support for TIFF image files. This addition completes the list of most popular supported image formats (JPEG, PNG/APNG, GIF, BMP/DIB, TIFF). The support was actually already partially there, because the Exif format (which is just an embedded TIFF) inside of JPEG files was already supported since the first public version of Profiler, but somehow the actual TIFF support hadn’t yet been added.

Multi-page TIFF

In a few days the new version will be released.

libmagic Support

While Profiler offers an API to identify file formats, it does so only for those which are supported. The list of supported files is vast, but there will be always unrecognized formats.

It’s certainly a good idea to introduce a file signature identification API. This API might be useful for several purposes, not all foreseeable right away. That’s why the upcoming version introduces support for libmagic (it comes with the latest 5.11 version). The library is exposed to Python in the ‘Pro.magic’ module. Here are the functions:

Just as a note: magic_file just calls magic_buffer internally.

Let’s create a small hook to demonstrate the use of the library, although it’s quite intuitive. Here’s the cfg entry:

The Python code:

The addMetaDataString in ScanProvider adds a string in the individual file report, which is visible from the file stats page in the workspace.

So if we open a file in the workspace, we’ll get the following extra information:

libmagic

The script above will be included in the update.

ELF Support

The upcoming 1.1 version of Profiler introduces preliminary ELF support. I said preliminary as the support wasn’t originally scheduled for this version. Anyway, here are some screenshots…

Segments (called program headers in the official terminology):

Segments

Sections (object files for instance don’t contain segments):

Sections

Symbols:

Symbols

ELF was the last important executable file format missing from list of supported formats. All other formats are already supported, be they native (PE, Mach-O) or managed (.NET, Java, DEX, ActionScript2, ActionScript3).

Raw File System Analysis (FAT32 File Recovery)

This post isn’t about upcoming features, it’s about things you can already do with Profiler. What we’ll see is how to import structures used for file system analysis from C/C++ sources, use them to analyze raw hex data, create a script to do the layout work for us in the future and at the end we’ll see how to create a little utility to recover deleted files. The file system used for this demonstration is FAT32, which is simple enough to avoid making the post too long.

Note: Before starting you might want to update. The 1.0.1 version is out and contains few small fixes. Among them the ‘signed char’ type wasn’t recognized by the CFFStruct internal engine and the FAT32 structures I imported do use it. While ‘signed char’ may seem redundant, it does make sense, since C compilers can be instructed to treat char types as unsigned.

Import file system structures

Importing file system structures from C/C++ sources is easy thanks to the Header Manager tool. In fact, it took me less than 30 minutes to import the structures for the most common file systems from different code bases. Click here to download the archive with all the headers.

Here’s the list of headers I have created:

  • ext – ext2/3/4 imported from FreeBSD
  • ext2 – imported from Linux
  • ext3 – imported from Linux
  • ext4 – imported from Linux
  • fat – imported from FreeBSD
  • hfs – imported from Darwin
  • iso9660 – imported from FreeBSD
  • ntfs – imported from Linux
  • reiserfs – imported from Linux
  • squashfs – imported from Linux
  • udf – imported from FreeBSD

Copy the files to your user headers directory (e.g. “AppData\Roaming\CProfiler\headers”). It’s better to not put them in a sub-directory. Please note that apart from the FAT structures, none of the others have been tried out.

Note: Headers created from Linux sources contain many additional structures, this is due to the includes in the parsed source code. This is a bit ugly: in the future it would be a good idea to add an option to import only structures belonging to files in a certain path hierarchy and those referenced by them.

Since this post is about FAT, we’ll see how to import the structures for this particular file system. But the same steps apply for other file systems as well and not only for them. If you’ve never imported structures before, you might want to take a look at this previous post about dissecting an ELF and read the documentation about C++ types.

We open the Header Manager and configure some basic options like ‘OS’, ‘Language’ and ‘Standard’. In this particular case I imported the structures from FreeBSD, so I just set ‘freebsd’, ‘c’ and ‘c11’. Then we need to add the header paths, which in my case were the following:

Then in the import edit we insert the following code:

Now we can click on ‘Import’.

Import FAT structures

That’s it! We now have all the FAT structures we need in the ‘fat’ header file.

It should also be mentioned that I modified some fields of the direntry structure from the Header Manager, because they were declared as byte arrays, but should actually be shown as short and int values.

Parse the Master Boot Record

Before going on with the FAT analysis, we need to briefly talk about the MBR. FAT partitions are usually found in a larger container, like a partitioned device.

To perform my tests I created a virtual hard-disk in Windows 7 and formatted it with FAT32.

VHD MBR

As you might be able to spot, the VHD file begins with a MBR. In order to locate the partitions it is necessary to parse the MBR first. The format of the MBR is very simple and you can look it up on Wikipedia. In this case we’re only interested in the start and size of each partition.

Profiler doesn’t yet support the MBR format, although it might be added in the future. In any case, it’s easy to add the missing feature: I wrote a small hook which parses the MBR and adds the partitions as embedded objects.

Here’s the cfg data:

And here’s the Python script:

And now we can inspect the partitions directly (do not forget to enable the hook from the extensions).

VHD Partitions

Easy.

Analyze raw file system data

The basics of the FAT format are quite simple to describe. The data begins with the boot sector header and some additional fields for FAT32 over FAT16 and for FAT16 over FAT12. We’re only interested in FAT32, so to simplify the description I will only describe this particular variant. The boot sector header specifies essential information such as sector size, sectors in clusters, number of FATs, size of FAT etc. It also specifies the number of reserved sectors. These reserved sectors start with the boot sector and where they end the FAT begins.

The ‘FAT’ in this case is not just the name of the file system, but the File Allocation Table itself. The size of the FAT, as already mentioned, is specified in the boot sector header. Usually, for data-loss prevention, more than one FAT is present. Normally there are two FATs: the number is specified in the boot sector header. The backup FAT follows the first one and has the same size. The data after the FAT(s) and right until the end of the partition includes directory entries and file data. The cluster right after the FAT(s) usually starts with the Root Directory entry, but even this is specified in the boot sector header.

The FAT itself is just an array of 32-bit indexes pointing to clusters. The first 2 indexes are special: they specify the range of EOF values for indexes. It works like this: a directory entry for a file (directories and files share the same structure) specifies the first cluster of said file, if the file is bigger than one cluster, the FAT is looked up at the index representing the current cluster, this index specifies the next cluster belonging to the file. If the index contains one of the values in the EOF range, the file has no more clusters or perhaps contains a damaged cluster (0xFFFFFFF7). Indexes with a value of zero are marked as free. Cluster index are 2-based: cluster 2 is actually cluster 0 in the data region. This means that if the Root Directory is specified to be located at cluster 2, it is located right after the FATs.

Hence, the size of the FAT depends on the size of the partition, and it must be big enough to accommodate an array large enough to represent every cluster in the data area.

So, let’s perform our raw analysis by adding the boot sector header and the additional FAT32 fields:

Add struct

Note: When adding a structure make sure that it’s packed to 1, otherwise field alignment will be wrong.

Boot sector

Then we highlight the FATs.

FATs

And the Root Directory entry.

Root Directory

This last step was just for demonstration, as we’re currently not interested in the Root Directory. Anyway, now we have a basic layout of the FAT to inspect and this is useful.

Let’s now make our analysis applicable to future cases.

Automatically create an analysis layout

Manually analyzing a file is very useful and it’s the first step everyone of us has to do when studying an unfamiliar file format. However, chances are that we have to analyze files with the same format in the future.

That’s why we could write a small Python script to create the analysis layout for us. We’ve already seen how to do this in the post about dissecting an ELF.

Here’s the code:

We can create an action with this code or just run it on the fly with Ctrl+Alt+R.

Recover deleted files

Now that we know where the FAT is located and where the data region begins, we can try to recover deleted files. There’s more than one possible approach to this task (more on that later). What I chose to do is to scan the entire data region for file directory entries and to perform integrity checks on them, in order to establish that they really are what they seem to be.

Let’s take a look at the original direntry structure:

Every directory entry has to be aligned to 0x20. If the file has been deleted the first byte of the deName field will be set to SLOT_DELETED (0xE5). That’s the first thing to check. The directory name should also not contain certain values like 0x00. According to Wikipedia, the following values aren’t allowed:

  • ” * / : < > ? \ |
    Windows/MS-DOS has no shell escape character
  • + , . ; = [ ]
    They are allowed in long file names only.
  • Lower case letters a–z
    Stored as A–Z. Allowed in long file names.
  • Control characters 0–31
  • Value 127 (DEL)

We can use these rules to validate the short file name. Moreover, certain directory entries are used only to store long file names:

We can exclude these entries by making sure that the deAttributes/weAttributes isn’t ATTR_WIN95 (0xF).

Once we have confirmed the integrity of the file name and made sure it’s not a long file name entry, we can validate the deAttributes. It should definitely not contain the flags ATTR_DIRECTORY (0x10) and ATTR_VOLUME (8).

Finally we can make sure that deFileSize isn’t 0 and that deHighClust combined with deStartCluster contains a valid cluster index.

It’s easier to write the code than to talk about it. Here’s a small snippet which looks for deleted files and prints them to the output view:

This script is to be run on the fly with Ctrl+Alt+R. It’s not complete, otherwise I would have added a wait box, since like it’s now the script just blocks the UI for the entire execution. We’ll see later how to put everything together in a meaningful way.

The output of the script is the following:

We can see many false positives in the list. The results would be cleaner if we allowed only ascii characters in the name, but this wouldn’t be correct, because short names do allow values above 127. We could make this an extra option, generally speaking it’s probably better to have some false positives than missing valid entries. Among the false positives we can spot four real entries. What I did on the test disk was to copy many files from the System32 directory of Windows and then to delete four of them, exactly those four found by the script.

The next step is recovering the content of the deleted files. The theory here is that we retrieve the first cluster of the file from the directory entry and then use the FAT to retrieve more entries until the file size is satisfied. The cluster indexes in the FAT won’t contain the next cluster value and will be set to 0. We look for adjacent 0 indexes to find free clusters which may have belonged to the file. Another approach would be to dump the entire file size starting from the first cluster, but that approach is worse, because it doesn’t tolerate even a little bit of fragmentation in the FAT. Of course, heavy fragmentation drastically reduces the chances of a successful recovery.

However, there’s a gotcha which I wasn’t aware of and it wasn’t mentioned in my references. Let’s take a look at the deleted directory entry of ‘notepad.exe’.

Notepad directory entry

In FAT32 the index of the first cluster is obtained by combining the high-word deHighClust with the low-word deStartCluster in order to obtain a 32-bit index.

The problem is that the high-word has been zeroed. The actual value should be 0x0013. Seems this behavior is common on Microsoft operating systems as mentioned in this thread on Forensic Focus.

This means that only files with a cluster index equal or lower than 0xFFFF will be correctly pointed at. This makes another approach for FAT32 file recovery more appealing: instead of looking for deleted directly entries, one could directly look for cluster indexes with a value of 0 in the FAT and recognize the start of a file by matching signatures. Profiler offers an API to identify file signatures (although limited to the file formats it supports), so we could easily implement this logic. Another advantage of this approach is that it doesn’t require a deleted file directory entry to work, increasing the possibility to recover deleted files. However, even that approach has certain disadvantages:

  1. Files which have no signature (like text files) or are not identified won’t be recovered.
  2. The name of the files won’t be recovered at all, unless they contain it themselves, but that’s unlikely.

Disadvantages notwithstanding I think that if one had to choose between the two approaches the second one holds higher chances of success. So why then did I opt to do otherwise? Because I thought it would be nice to recover file names, even though only partially and delve a bit more in the format of FAT32. The blunt approach could be generalized more and requires less FAT knowledge.

However, the surely best approach is to combine both systems in order to maximize chances of recovery at the cost of duplicates. But this is just a demonstration, so let’s keep it relatively simple and let’s go back to the problem at hand: the incomplete start cluster index.

Recovering files only from lower parts of the disk isn’t really good enough. We could try to recover the high-word of the index from adjacent directory entries of existing files. For instance, let’s take a look at the deleted directory entry:

Deleted entry

As you can see, the directory entry above the deleted one represents a valid file entry and contains an intact high-word we could use to repair our index. Please remember that this technique is just something I came up with and offers no guarantee whatsoever. In fact, it only works under certain conditions:

  1. The cluster containing the deleted entry must also contain a valid file directory entry.
  2. The FAT can’t be heavily fragmented, otherwise the retrieved high-word might not be correct.

Still I think it’s interesting and while it might not always be successful in automatic mode, it can be helpful when trying a manual recovery.

This is how the code to recover partial cluster indexes might look like:

It tries to find a valid file directory entry before and after the deleted entry, remaining in the same cluster. Now we can write a small function to recover the file content.

All the pieces are there, it’s time to bring them together.

Create a recovery tool

With the recently introduced logic provider extensions, it’s possible to create every kind of easy-to-use custom utility. Until now we have seen useful pieces of code, but using them as provided is neither user-friendly nor practical. Wrapping them up in a nice graphical utility is much better.

Home view

What follows is the source code or at least part of it: I have omitted those parts which haven’t significantly changed. You can download the full source code from here.

Here’s the cfg entry:

And the Python code:

When the tool is activated it will ask for the disk file to be selected, then it will show an options dialog.

Options

In our case we can select the option ‘Ascii only names’ to exclude false positives.

The options dialog asks for a directory to save the recovered files. In the future it will be possible to save volatile files in the temporary directory created for the report, but since it’s not yet possible, it’s the responsibility of the user to delete the recovered files if he wants to.

The end results of the recovery operation:

Results

All four deleted files have been successfully recovered.

Three executables are marked as risky because intrinsic risk is enabled and only ‘ntoskrnl.exe’ contains a valid digital certificate.

Conclusions

I’d like to remind you that this utility hasn’t been tested on disks other than on the one I’ve created for the post and, as already mentioned, it doesn’t even implement the best method to recover files from a FAT32, which is to use a signature based approach. It’s possible that in the future we’ll improve the script and include it in an update.

The purpose of this post was to show some of the many things which can be done with Profiler. I used only Profiler for the entire job: from analysis to code development (I even wrote the entire Python code with it). And finally to demonstrate how a utility with commercial value like the one presented could be written in under 300 lines of Python code (counting comments and new-lines).

The advantages of using the Profiler SDK are many. Among them:

  • It hugely simplifies the analysis of files. In fact, I used only two external Python functions: one to check the existence of a directory and one to normalize the path string.
  • It helps building a fast robust product.
  • It offers a graphical analysis experience to the user with none or little effort.
  • It gives the user the benefit of all the other features and extension offered by Profiler.

To better explain what is meant by the last point, let’s take the current example. Thanks to the huge amount of formats supported by Profiler, it will be easy for the user to validate the recovered files.

Validate recovered files

In the case of Portable Executables it’s extremely easy because of the presence of digital certificates, checksums and data structures. But even with other files it’s easy, because Profiler may detect errors in the format or unused ranges.

I hope you enjoyed this post!

P.S. You can download the complete source code and related files from here.

References

  1. File System Forensic Analysis – Brian Carrier
  2. Understanding FAT32 Filesystems – Paul Stoffregen
  3. Official documentation – Microsoft
  4. File Allocation Table – Wikipedia
  5. Master boot record – Wikipedia

News for version 1.0

The new 1.0 version of the Profiler is out with the following news:

introduced logic provider extensions
added SQLite3 support including free pages inspection
exposed internal database access to extensions
– fixed some issues when executing Python code from other threads
– made actions available in the context of the main window

The 1.0 version represents for its round number and intrinsic meaning a milestone in the development road-map. So how does the actual development stage compare to the original road-map envisioned for 1.0?

Many features we’d like to have included are not there yet. On the other hand an even bigger number of features not originally considered for this version have been added, like complete support for C/C++ types, a JavaScript debugger, an incredibly powerful Python SDK, Lua filters etc.

Talking about file formats, few important ones are still missing. For instance ELF support is yet to be added. The reason for this lies behind the original idea to add support first for Windows file types. That’s why there’s support for esoteric file types like LNK and not for ELF. This strategy has been abandoned already some time ago and as you can see in 0.9.6 we added support for Mach-O executables. Also the overall support for Android (APKs, DEX, Binary XML) is very good and that only makes the support for ELF more important. Apart from that we’re happy with the number of formats currently supported and hope to significantly increase the number next year.

Another important aspect is documentation and tutorials. While we take good care of the blog, we’re certainly guilty in this regard. Unfortunately all time spent documenting is time subtracted from creating new features. We tried to give some practical examples this year (including reversing of malware):

But even there we certainly could do more. The already existing feature set of the standard version would already need half a book to be covered, not counting explanations regarding file formats. Sooner or later an entire book will become necessary, I guess. Early adopters have the advantage of gradually following the development and easily keeping up-to-date with new features. But the term ‘early adopter’ is relative. Become one of our customers today and you’ll become an ‘early adopter’ in a year! 😉

Sorry for the sales pitch, I was saying… Yes, our product offer has increased. Few months ago we have released PE Insider, a free Portable Executable viewer for the community, based on the same code base as Profiler.

Also, we have recently announced an advanced (forensic oriented) edition of Profiler. While this does subtract some time from the standard version, it also drives development a lot and the standard version will greatly benefit from it. For instance, the newly introduced logic providers could’ve been added later were it not for the advanced version. And the benefits won’t come only as extensions to the core and internal components, but also as additional file support as we’re going to show soon.

To mark the current milestone, starting from this version we’ll change the progression of versions. Every new release will increase the minor version (rather than the last number which will be reserved for bug fixes).

We hope you will accompany us in our journey towards 2.0!

Logic Providers

The main feature of the 1.0.0 version of the Profiler is ready and thus it won’t take long for the new version to be released. This post serves as introduction to the topic of logic providers and can in no way cover all the ground.

Logic providers are a new type of extension quite similar to hooks: the callbacks are named the same. Their purpose however is different. Hooks are very powerful, but their purpose is to modify the behavior of generic scans. Logic providers, on the other hand, tell the scan engine which folders to scan, which files, etc.

Let’s take a look at a small logic provider. The ‘logicp.cfg’ entry:

And the ‘missingsecflags.py’ file:

Let’s now take a look at the home view in the Profiler.

Logic provider scan button

As you can see, there’s an additional scan button which belongs to the logic provider we’ve just added. The icon can be customized from the cfg file by specifying an ‘icon’ field (the path is relative to the media folder).

So let’s take a closer look at the code above. When the user clicks the scan button, the init function of our logic provider will be called.

The init function calls getSystem (which returns a CommonSystem base class). This class can be used to initialize the scan engine. By default the system will be initialized to LocalSystem. A logic provider can even create its own system class and then set it with setSystem. As introduction it’s not useful to inspect all the methods in CommonSystem and every possible use, we leave that for future posts. In this simple case it’s not necessary to implement anything complex, we are performing a scan on the local system and so it’s enough to call the addPath method on the default class returned by getSystem.

The function then returns the True value. It can also return False and abort the scan operation. Any other value will be passed as user argument to other callbacks such as: scanning, scanned and end.

That’s a small difference between hooks and logic providers: the init function in hooks can’t abort a scan operation. Another difference is that while hooks don’t have mandatory callbacks, the init function is mandatory for logic providers, since, without it, nothing gets done. Logic providers start their own scanning operations, while hooks just attach to existing operations (even those created by logic providers).

The scanned function has the same syntax as in hooks and doesn’t require an additional explanation. The only thing worth mentioning is that hooks can be selectively called based on the file format (see formats field). This isn’t true for logic providers: their scanning/scanned callbacks will be called for every file. The logic providers API is recent and not written in stone, so it might very well be that in the future a filtering mechanism for formats will be provided for them as well.

As for the content of the scanned function, it just checks two security related flags inside of a Portable Executable and includes in the final report only those files which miss one or both flags.

Logic provider results

The scan could be made more useful to check for specific things like COM modules which miss the ASRL flag and things like that.

Also the extension doesn’t really fully benefit from the advantages brought by logic providers: it could as well be implemented as a hook, perhaps it would be even better. In this case the only advantage it provides is a shortcut in the home view for the user.

An important aspect of logic providers is that the Profiler remembers which logic providers have been used to create a report and calls their rload callback when loading that report. The rload callback exists even for hooks, but for them it’s called in any case provided the hook is enabled. It’s important to remember that the identifying name for logic providers is the value contained between brackets in the cfg file. If it’s changed, the Profiler won’t be able to identify the logic provider and print an error message in the output view.

Since this version of the Profiler also exposes its internal SQLite implementation, it’s now possible to access the internal database (main.db):

Another useful method exposed by the Report class is retrieveFile:

The retrieveFile method retrieves a file based on its name either from the project or from the disk.

Using all these features in conjunction a typical scenario for a logic provider would be:

  • The init callback is called and initializes the scan engine.
  • Information is collected either from the scanning or scanned callback, depending on the needs.
  • The end callback stores the collected data in the main database via the provided SQLite API.
  • The rload callback retrieves the collected data from the main database and creates one or more views to display it to the user.

As already mentioned this post covers only the basics and we’ll try to provide more useful examples in the future.