Didier Stevens

Sunday 26 September 2021

Patching A Java .class File

Filed under: 010 Editor,Forensics,Hacking,Malware — Didier Stevens @ 0:00

010 Editor is one of few commercial applications that I use daily. It’s a powerful binary editor with scripting and templates.

I recently had to patch a Java .class file: extend a string inside that class. Before going the route of decompiling / editing / recompiling, I tried with 010 Editor.

Here is the file opened inside the editor:

When opening the file, 010 Editor recognized the .class extension and installed and ran the template for .class files. That’s what I wanted to know: is there a template for .class files? Yes, there is!

Here is how you can apply a template manually, in case the file extension is not the original extension:

And this is how the template results look like:

Under the hex/ascii dump, the template results are displayed: a set of nested fields that match the internal structure of .class file. For example, the first field I selected here, u4 magic, is the magic header of a .class file: CAFEBABE.

The string I want to extend is this one:

I need to extend string “1.2 (20210922)”. Into something like “1.2 (20210922a)”.

Doing so will make the string longer, thus I need to add a byte to the file (trivial), but I also need to make sure that the binary structure of .java files remain valid: for example, if there is something in that structure like a field length, I need to change the field length too.

I’m not familiar with the internal structure of .class files, that why I’m using 010 Editor’s .class template, hoping that the template will make it clear to me what needs to be changed.

To find the template result field I need to modify, I position my cursor on the string I want to modify inside the ASCII dump, I right-click and select “Jump To Template Variable”:

Which selects the corresponding template variable:

So my cursor was on the 10th byte (bytes[9]) of the string, which is part of template variable cp_info constant_pool[27]. From that I gather that the string I want to modify is inside a pool of constants.

I can select that template variable:

And here I can see which bytes inside the .class file were selected. It’s not only the string, but also bytes that represent the tag and length. The length is 14, that’s indeed the length of the string I want to extend. Since I want to add 1 character, I change the length from 14 to 15: I can do that inside the template results by double-clicking the value 14, I don’t need to make that change inside the hexdump:

Next I need to add a character to the string. I can do that in the ASCII dump:

I have to make sure that the editor is in insert mode (INS), so that when I type characters, they are inserted at the cursor, in stead of overwriting existing bytes:

And then I can type my extra character:

So I have changed the constant string I wanted to change. Maybe there are more changes to make to the internal structure of this .class file, like other length fields … I don’t know. But what I do as an extra check is: save the modified file and run the template again. It runs without errors, and the result looks good.

So I guess there are no more changes to make, and I decide to tryout my modified .class file and see what happens: it works, so there are no other changes to make.

Monday 26 April 2021

Quickpost: Decrypting Cobalt Strike Traffic

Filed under: Encryption,Malware,My Software,Quickpost — Didier Stevens @ 0:00

I have been looking at several samples of Cobalt Strike beacons used in malware attacks. Although work is still ongoing, I already want to share my findings.

Cobalt Strike beacons communicating over HTTP encrypt their data with AES (unless a trial version is used). I found code to decrypt/encrypt such data in the PyBeacon and Geacon Github repositories.

This code works if you know the AES key: which is not a problem in the use cases of the code above, as it is developed to simulate a beacon. Beacons generate their own AES key, and thus these beacon simulations also generate their own AES key.

But what if you’re analyzing real beacons used in malware attacks? How do you obtain the AES key?

I found a way to extract the keys (AES and HMAC) from process memory of a running beacon.

I use the following procdump command to prepare process memory dumps:

procdump -mp -w -s 1 -n 5 malware.exe

Then I start the beacon malware.exe in a malware analysis virtual machine while capturing traffic with Wireshark.

My new tool cs-extract-key.py looks in the dumped process memory for the unencrypted (RSA encryption) metadata that a beacon sends to the C2. This metadata contains the AES en HMAC keys.

Example:

This method does not always work: the metadata is overwritten after some time, so the process dump needs to be taken quickly after the beacon is started. And there are also cases were this metadata can not be found (I suspect this is version bound).

For those cases, my tool has another way of obtaining the keys. I extract the encrypted data of the first post of the beacon to the C2 (this is called a callback in the PyBeacon code):

And then I provide this to my tool, together with the process dump. My tool will then proceed with a dictionary attack: extract all possible AES and HMAC keys from the process dump, and try do authenticate and decrypt the callback. If this works, the keys have been found:

And once I have obtained the keys, I can pass them to my traffic decoding program that I have updated to include decryption (and that I have renamed to cs-parse-http-traffic.py):


Quickpost info


Friday 12 February 2021

Quickpost: oledump.py plugin_biff.py: Remove Sheet Protection From Spreadsheets

Filed under: Malware,My Software,Quickpost — Didier Stevens @ 0:00

My new version of plugin_biff.py has a new option: –hexrecord.

Here I’ll show how I use this to remove the sheet protection from malicious spreadsheets.

If you want to open a malicious spreadsheet (for example with Excel 4 macros) in a sandbox, to inspect its content with Excel, chances are that it is protected.

I’m not talking about encryption (this is something that can be handled with my tool msoffcrypto-crack.py), but about sheet protection.

Enabling sheet protection can be done in Excel as follows:

Although you have to provide a password, that password is not used to derive an encryption key. An .xls file with sheet protection is not encrypted.

If you use my tool oledump.py together with plugin_biff.py, you can select all BIFF records that have the string “protect” in their name or description (-O protect). This will give you different records that govern sheet protection.

First, let’s take a look at an empty, unprotected (and unencrypted) .xls spreadsheet. With option -O protect I select the appropriate records, and with option -a I get an hex/ascii dump of the record data:

We can see that there are several records, and that their data is all NULL (0x00) bytes.

When we do the same for a spreadsheet with sheet protection, we get a different view:

First of all we have 4 extra records, and their data isn’t zero: the flags are set to 1 (01 00 little-endian) and the Protection Password data is AB94. That is the hash of the password (P@ssw0rd) we typed to create this sheet.

To remove this sheet protection, we just need to set all data to 0x00. This is something that can be done with an hex editor.

First use option -R instead of option -a:

This will give you the complete records (type, length and data) in hexadecimal. Next you can search for each record using this hexadecimal data with an hex editor and set the data bytes to 0x00.

Searching for the first record 120002000100:

Setting the data to 0x00: 0100 -> 0000

Do this for the 4 records, and then save the spreadsheet under a different name (keep the original intact).

Now you can open the spreadsheet, and the sheet protection is gone. You can now unhide hidden sheets for example.


Quickpost info


Thursday 28 January 2021

Update: XORSelection.1sc Version 6.0

Filed under: 010 Editor,Encryption,Malware,My Software — Didier Stevens @ 0:00

I released an update to my 010 Editor script XORSelection.1sc.

010 is a binary editor with a scripting engine. XORSelection.1sc is a script I wrote years ago, that will XOR-encode a (partial) file open in the editor.

The first version just accepted a printable, arbitrary-length string as XOR-key. Later versions accepted an hexadecimal key too, and introduced various options.

With version 6.0, I add support for a dynamic XOR-key. That is a key that changes while it is being used. It can change, one byte at-a-time, before or after each XOR operation at byte-level is executed.

Hence option cb means change before, and ca means change after. Watch this video to understand exactly how the key changes (if you want to skip the part explaining my script XORSelection, you can jump directly to the dynamic XOR-key explanation).

 

I made this update to my XORSelection script, because I had to “manually” decode a Cobalt Strike beacon that was XOR-encoded with a changing XOR key (it is part of a WebLogic server attack). Later I included this decoding in my Cobalt Strike beacon analysis tool 1768.py.

The decoding shellcode is in the first 62 bytes (0x3E) of the file:

After the shellcode comes the XOR-key, the size and the beacon:

We can decode the beacon size, that is XOR-encoded with key 0x3F0882FB, as follows. First we select the bytes to be decoded:

Then we launch 010 Editor script XORSelection.1sc:

Provide the XOR key (prefix 0x is to indicate that the key is provide as hexadecimal byte values):

And then, after pressing OK, the bytes that contain the beacon size are decoded by XOR-ing them with the provided key:

This beacon size (bytes 00 14 04 00) is a little-endian, 32-bit integer: 0x041400.

To decode the beacon, we select the encoded beacon and launch script XORSelection.1sc again:

This time, we need to provide an option to change the XOR-decoding process. We press OK without entering a value, this will make the next prompt appear, where we can provide options:

The option we need to use to decode this Cobalt Strike beacon, is cb: change before.

In the next prompt, we can provide the XOR-key:

And we end up with the decoded beacon (you can see parts of the PE file that is the beacon):

Remark that you can enter “h” at the option prompt, to get a help screen:

I made this video explaining how to use this new option, and also explaining how the XOR key is changed exactly when using option change before (cb) or change after (ca).

If you want to skip the part explaining my script XORSelection, you can jump directly to the dynamic XOR-key explanation.

XORSelection_V6_0.zip (https)
MD5: C1872C275B59E236906D38B2302F3F4B
SHA256: 1970A506299878FAC2DDD193F9CE230FD717854AC1C85554610DDD95E04DE9E9

 

Tuesday 19 January 2021

Video: Maldoc Analysis With CyberChef

Filed under: maldoc,Malware,video — Didier Stevens @ 0:00

In this video, I show how to analyze a .doc malicious document using CyberChef only. This is possible, because the payload is a very long string that can be extracted without having to parse the structure of the .doc file with a tool like oledump.py.

I pasted the recipe on pastebin here.

Friday 22 May 2020

Update: oledump.py Version 0.0.50

Filed under: maldoc,Malware,My Software,Update — Didier Stevens @ 0:00

This new version brings updates to plugin plugin_biff.py.

This plugin can now produce a CSV list of cell values and formulas (option -c) or a JSON file of values and formulas (option -j).

Cell references are in RC format (row-column), but can also be produced in letters-numbers format (LN, option -r LN).

CSV or JSON output can be piped into my ad-hoc decoding programs.


oledump_V0_0_50.zip (https)
MD5: 30EB6A0E0924E72350B268ADDE4E4EC7
SHA256: 870167AE5576B169EB52572788D04F1FFCEC5C8AFDEBCC59FE3B8B01CBDE6CD9

Wednesday 1 April 2020

April 1st 2020: FlashPix File With VBA Code

Filed under: Hacking,Malware — Didier Stevens @ 0:00

Last year, there was some misunderstanding regarding Office Documents with VBA code mistakenly identified as FlashPix picture files.

The FlashPix picture format is an old format, based on the Compound File Binary Format (what I like to call OLE files). It has no support for VBA code at all (it doesn’t support any embedded scripting).

However, since it is an ole file, it’s technically possible to add storages and streams containing VBA code. This code can never execute, because the FlashPix specifications does not support it, and hence there are no image viewers that would recognize and execute this code.

So I took a FlashPix image (3d996a887c4a1b5b5ce70528f6bb4508). Here you can see the streams it contains:

And then I took a malicious AutoCAD drawing, and copied the VBA streams and storages into the FlashPix file:

Giving me this file 5040ef90824371a0bd0acaa36263553b.When I submitted this file to VirusTotal a couple of months ago, the AV detection ratio was 29/59. Which is far better than the other “AV-alert pictures” that I created.

If you are in need of a benign file that will trigger anti-virus, I shared this FlashPix PoC on the new malware sharing service Malware Bazaar.

Monday 30 March 2020

mimikatz Is My New EICAR

Filed under: Malware — Didier Stevens @ 0:00

I helped a friend creating picture files to be detected by anti-virus. They are not malicious: they don’t execute code neither trigger a vulnerability.

The EICAR test file is detected by many anti-virus programs, except when it is appended to arbitrary files (this is according to specs).

Starting with a one-pixel JPEG and PNG file, I append the EICAR test file. And with a JPEG file, I can also insert the EICAR file as a comment:

The detection scores on VirusTotal show that these files are not detected by many anti-virus programs:

  • JPEG + EICAR: 6/55
  • PNG + EICAR: 7/58
  • JPEG + EICAR comment: 2/57

That wasn’t good enough for my friend, she needed something with a higher detection score.

Since several years now, there is a Windows program that triggers many anti-virus programs: mimikatz.

When I try mimikatz with picture files, I get better detection scores than for the EICAR test file (as I expected):

  • JPEG + MIMIMATZ.EXE: 19/58
  • PNG + MIMIMATZ.EXE: 15/57
  • JPEG + MIMIMATZ.DLL: 12/57

 

And I have a picture file with even higher detection scores, but you’ll have to wait until April Fools day for the details 😉 .

Monday 6 January 2020

Analysis Of Unusual ZIP Files

Filed under: Malware,My Software — Didier Stevens @ 0:00

Intrigued by a blog post from SpiderLabs on a special ZIP file they found, I took a closer look myself.

That special ZIP file is a concatenation of 2 ZIP files, the first containing a single PNG file (with extension .jpg) and the second a single EXE file (malware). Various archive managers and security products handle this file differently, some “seeing” only the PNG file, others only the EXE file.

My zipdump.py tool reports the following for this special ZIP file:

zipdump.py is essentially a wrapper for Python’s zipfile module, and this module parses ZIP files “starting from the end of the file”. That’s why it finds the second ZIP file (appended to the first ZIP file), containing the malicious EXE file.

To help with the analysis of such special/malformed ZIP files, I added an option (-f –find) to zipdump. This option scans the content of the provided file looking for ZIP records. ZIP records start with ASCII string PK followed by 2 bytes to indicate the record type (byte values less than 16).

Here I use option “-f list” to list all PK records found in a ZIP file containing a single text file:

This is how a normal ZIP file containing a single file looks on the inside.

The file starts with a “local file header”, a PK record that starts with ASCII characters PK followed by bytes 0x03 and 0x04 (that’s 50 4B 03 04 in hexadecimal). In zipdump’s report, such a PK record is identified with PK0304. This header is followed by the contained file (usually compressed).

Then there is a “central directory header”, a PK record that starts with ASCII characters PK followed by bytes 0x01 and 0x02 (that’s 50 4B 01 02 in hexadecimal). In zipdump’s report, such a PK record is identified with PK0102. This header contains an offset pointing to the corresponding PK0304 record.

And at the end of the ZIP file, there is a “end of central directory”, a PK record that starts with ASCII characters PK followed by bytes 0x05 and 0x06 (that’s 50 4B 05 06 in hexadecimal). In zipdump’s report, such a PK record is identified with PK0506. This header contains an offset pointing to the first PK0102 record.

A ZIP file containing 2 files looks like this, when scanned with zipdump’s option -f list:

Starting with 2 PK0304 records (one for each contained file), followed by 2 PK0102 records, and 1 PK0506 record.

Armed with this knowledge, we take a look at our malicious ZIP file:

We see 2 PK0506 records, and this is unusual.

We see the following sequence of records twice: PK0304, PK0102, PK0506.

From our previous examples, we can now understand that this sample contains 2 ZIP files.

Remark that zipdump assigned an index to both PK0506 records: 1 and 2. This index can be used to select one of the 2 ZIP files for further analysis. Like in this example, where I select the first ZIP file:

Using option “-f 1” (in stead of “-f list”) selects the first ZIP file in the provide sample, and lists its content.

It can then be further analyzed with zipdump like usual, for example, selecting the first file (order.jpg) inside the first ZIP file for an hex/ascii dump:

Likewise, “-f 2” will select the second ZIP file found inside the sample:

-f is a new option that I added for special/malformed ZIP files, but this is a work in progress, as there are many ways to malform ZIP files.

For example, I created a PoC malformed ZIP file that contains a single file, with reversed PK record order. Here is the output for the normal and “reversed” zip files (malformed, e.g. PK records order reversed):

This file can be opened with Windows Explorer, but there are tools and libraries than can not handle it. Like Python’s zipfile module:

I will further develop zipdump to handle malformed ZIP files as best as possible.

The current version (zipdump 0.0.16) is just a start:

  • it parses only 3 PK record types (PK0304, PK0102 and PK0506), other types are ignored
  • it does minimal parsing of these records: for example, there is no parsing/checking of offsets in this version

And finally, I also created a video showing how to use this new feature:

Monday 16 December 2019

Analyzing .DWG Files With Embedded VBA Macros

Filed under: maldoc,Malware — Didier Stevens @ 0:00

AutoCAD’s drawing files (.dwg) can contain VBA macros. The .dwg format is a proprietary file format. There is some documentation, for example here.

When VBA macros are stored inside a .dwg file, an OLE file is embedded inside the .dwg file. There’s a quick-and-dirty way to find this embedded file inside the .dwg file: search for magic sequence D0CF11E0.

My tool cut-bytes.py can be used to search for the first occurrence of byte sequence D0CF11E0 and extract all bytes starting from this sequence until the end of the .dwg file. This can be done with cut-expression [D0CF11E0]: and pipe the result into oledump.py, like this:

Next, oledump can be used to conduct the analysis as usual, for example by extracting the VBA macro source code:

There is also a more structured approach to locate the embedded OLE file inside a .dwg file. When one looks at a .dwg file with a hexadecimal editor, the following can be seen:

First there is a magic sequence identifying this as a .dwg file: AC1032. This sequence varies with the file format version, but since many, many years, it starts with AC10. You can find more details regarding this magic sequence here and here.

At position 0x24 (36 decimal), there is a 32-bit little-endian integer. This is a pointer to the embedded OLE file (this pointer is NULL when no OLE file with VBA macros is embedded).

In our example, this pointer value is 0x00008080. And here is what can be found at this position inside the .dwg file:

First there is a 16-byte long header. At position 8 inside this header, there is a 32-bit little-endian integer that represents the length of the embedded file. 0x00001C00 in our example. And after the header one can find the embedded OLE file (notice magic sequence D0CF11E0).

This information can then be used to extract the OLE file from the .dwg like, like this:

Achieving exactly he same result as the quick-and-dirty method. The reason we don’t have to figure out the length of embedded OLE the file using the quick-and-dirty method, is that oledump ignores all bytes appended to an OLE file.

I will adapt my oledump.py tool to extract macros directly from .dwg files, without the need of a tool like cut-bytes.py, but I will probably implement something like the quick-and-dirty method, as this method would potentially work for other file formats with embedded OLE files, not only .dwg files.

 

Next Page »

Blog at WordPress.com.