Didier Stevens

Sunday 12 July 2020

Quickpost: curl

Filed under: Networking,Quickpost — Didier Stevens @ 0:00

Since I learned that Windows 10 has curl pre-installed now, I notice I use it more often.

Here are some quick notes, mainly for myself:


Using Tor:

curl --socks5-hostname http://didierstevens.com

Option socks5-hostname uses SOCKS5 protocol and does name resolution of the hostname via the SOCKS5 protocol (and not local DNS)


Removing the User-Agent header:

curl --header "User-Agent:" http://didierstevens.com

Option –header (-H) can also be used to remove a header: provide the header name with colon, provide no header value.


Using a custom User-Agent header (-A –user-agent):

curl --user-agent "Mozilla/5.0 DidierStevens" http://didierstevens.com


Saving received data:

curl --dump-header 01.headers --output 01.bin.vir --trace 01.trace --trace-time http://didierstevens.com

Option —dump-header (-D) saves the headers, option –output (-o) saves the body, –trace creates a trace file and –trace-time adds timestamps to the trace file.


Option to ignore certificate errors: -k –insecure


Putting it all together:

curl --socks5-hostname --user-agent "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36" --insecure --dump-header 01.headers --output 01.data --trace 01.trace --trace-time https://didierstevens.com


Quickpost info

Monday 18 May 2020

Quickpost: curl And SSPI Proxy Authentication

Filed under: Networking,Quickpost — Didier Stevens @ 0:00

curl with SSPI feature supports integrated authentication to a proxy: you don’t need to provide credentials.

The command is the following:

curl –proxy proxyname:8080 –proxy-ntlm -U : https://www.didierstevens.com/index.html

This curl command uses a proxy (–proxy) and authenticates to the proxy (–proxy-ntlm) without providing explicit credentials (-U :).

curl will use an SSPI to perform integrated authentication to the proxy. This is explained on curl’s man page:

If you use a Windows SSPI-enabled curl binary and do either Negotiate or NTLM authentication then you can tell curl to select the user name and password from your environment by specifying a single colon with this option: “-U :”.

curl’s SSPI feature can also be used to authenticate to an internal IIS server.

Windows’ built-in curl version supports SSPI. You can use the version option to check if your version of curl supports SSPI:


Quickpost info

Saturday 9 May 2020

Quickpost: Go: Building For Multiple Operating Systems

Filed under: Quickpost — Didier Stevens @ 11:34

To compile a Go program for multiple operating systems on a single machine, set environment variables GOOS and GOARCH accordingly.

GOOS (Go Operating System):

  • set GOOS=windows
  • set GOOS=linux
  • set GOOS=darwin

GOARCH (Go Architecture):

  • set GOARCH=386
  • set GOARCH=amd64

More values here.

Example program:

package main

import "fmt"

func main() {
	fmt.Printf("hello, world\n")

Build command on Windows for Linux 32-bit ELF file:
set GOOS=linux
set GOARCH=386
c:\Go\bin\go.exe build -o program.exe program.go

Quickpost info

Monday 4 May 2020

Quickpost: Empty ZIP File

Filed under: Quickpost — Didier Stevens @ 0:00

As a reminder to myself, here is the hexdump of an empty ZIP file: 50 4B 05 06 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00

And here is the cut-bytes.py command to generate an empty ZIP file:

C:\Demo>cut-bytes.py -a : #e#’PK’+0x0506+repeat(0x12,0x00)
00000000: 50 4B 05 06 00 00 00 00 00 00 00 00 00 00 00 00 PK…………..
00000010: 00 00 00 00 00 00 ……

Quickpost info

Sunday 26 April 2020

Quickpost: My SpiderMonkey’s Cheat Sheet

Filed under: My Software,Quickpost — Didier Stevens @ 8:27

I have a modified version of SpiderMonkey, Mozilla’s (old) JavaScript parser, that helps me with JavaScript analysis.

Details here.

js.exe -e “document.output(‘x’);” sample.js
zipdump.py -s 1 -d sample.js.zip | js.exe -e “document.output(‘a’);” –
zipdump.py -s 1 -d sample.js.zip | js.exe -e “document.output(‘d’);” –
zipdump.py -s 1 -d sample.js.zip | js.exe -e “document.output(‘X’);” –
zipdump.py -s 1 -d sample.js.zip | js.exe -e “document.output(‘A’);” –
zipdump.py -s 1 -d sample.js.zip | js.exe -e “document.output(‘D’);” –
zipdump.py -s 1 -d sample.js.zip | js.exe -e “document.output(‘f’);” –
zipdump.py -s 1 -d sample.js.zip | js.exe –

Saturday 28 March 2020

Quickpost: Windows Domain Controllers Have No Local Accounts

Filed under: Quickpost — Didier Stevens @ 0:00

Windows domain controllers have no local accounts. I think I learned this back when I made my “Practice ntds.dit File Overview” series of blog posts.

Today I had to search for a Microsoft document covering this: Built-in and Account Domains.

Quickpost info

Monday 23 March 2020

Quickpost: User-Agent: Microsoft Office Excel 2014

Filed under: Networking,Quickpost — Didier Stevens @ 14:25

To start: there is no version 2014 of Microsoft Office.

That’s why I was intrigued when I saw User Agent String “Microsoft Office Excel 2014” appearing in Wireshark when I did some tests with Excel’s data importing features.

With Excel 2019, when I get data from a CSV file and provide an URL (in stead of a local filename) like this:

Excel will issue several OPTIONS and HEAD requests, with different User Agent Strings:

And finally, a GET request to download the file:

Xavier Mertens has mentioned User Agent String “Microsoft Office Excel 2014” in another context: “Microsoft Apps Diverted from Their Main Use“.

Quickpost info

Tuesday 29 October 2019

Quickpost: Running a Service DLL

Filed under: Quickpost — Didier Stevens @ 0:00

To install and run a service DLL compiled with MinGW on Kali, I execute following commands from a BAT file with an elevated command prompt:

copy SvcHostDemo.dll %SystemRoot%\System32\SvcHostDemo.dll
sc create SvcHostDemo binPath= ^%%SystemRoot^%%"\system32\svchost.exe -k mygroup" type= share start= demand
reg add HKLM\SYSTEM\CurrentControlSet\services\SvcHostDemo\Parameters /v ServiceDll /t REG_EXPAND_SZ /d ^%%SystemRoot^%%\System32\SvcHostDemo.dll /f
reg add "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Svchost" /v mygroup /t REG_MULTI_SZ /d SvcHostDemo /f

Line 1 copies the DLL to system32.

Line 2 creates a service with name SvcHostDemo, that will start svchost.exe with service host group “mygroup”. The service can run in a shared svchost process, and it needs to be started manually.

Line 3 creates the registry entry ServiceDll referring to SvcHostDemo.dll.

Line 4 creates the service host group “mygroup” under the key for svchost. This service host group contains the service SvcHostDemo.

These commands create the following registry entries:

On a 64-bit Windows system, system32\svchost.exe is a 64-bit application and thus the service DLL needs to be a 64-bit DLL.

On a 32-bit Windows system, system32\svchost.exe is a 32-bit application and thus the service DLL needs to be a 32-bit DLL.


To start the service from the command line, the following command can be issued from an elevated command prompt: sc start SvcHostDemo.

Since service SvcHostDemo is the only service of service host group mygroup, starting the service causes a svchost.exe process to be created and the DLL is loaded inside this new process.

To pause the service: sc pause SvcHostDemo.

To resume the service: sc continue SvcHostDemo.

To stop the service: sc stop SvcHostDemo.

And since service SvcHostDemo is the only service of service host group mygroup, stopping the service causes the svchost.exe process to be terminated.


The many debug messages generated by this demo service can be viewed with DebugView. Run dbgview.exe elevated and enable “Capture Global Win32”, otherwise debug messages from a service (running under the local system account) will no be captured and displayed.

This service can also run inside an existing service host group, like netsvcs. To achieve this, line 2 of the commands above needs to use service host group netsvcs in stead of mygroup. And line 4 is not needed, but the existing multistring netsvcs under key Svchost needs to be updated to include SvcHostDemo. This change requires a reboot of the Windows machine to become effective.

With these changes, starting the service results in loading of the DLL in the existing svchost.exe process for the netsvcs service host group.

Stopping the service does not result in termination of the svchost.exe process, as it is hosting many other Microsoft Windows services.

To unload the DLL from the svchost.exe process when the service is stopped, set registry value ServiceDllUnloadOnStop under Parameters to 1.

reg add HKLM\SYSTEM\CurrentControlSet\services\SvcHostDemo\Parameters /v ServiceDllUnloadOnStop /t REG_DWORD /d 1 /f


If the name of the service function is not ServiceMain, but another name like RunThisService for example, then registry value ServiceMain under Parameters can be set to RunThisService.

reg add HKLM\SYSTEM\CurrentControlSet\services\SvcHostDemo\Parameters /v ServiceMain /t REG_SZ /d RunThisService /f


I used Windows 7 to demo this, as shared services on Windows 10 behave differently. Starting with Windows 10 version 1703, a service host refactoring took place and on machines with more than 3.5 GB of RAM each service DLL has its own svchost process, regardless of service host groups. This resulted in a change in the ImagePath registry entries. On Windows 10 machines version 1703 and later, almost all ImagePath entries for “svchost.exe -k servicegroup” have an extra option “-p”, like this: “svchost.exe -k servicegroup -p”. One of the very few svchost services not having this -p option, is the BTAGService service.

I still need to figure out what this option -p means exactly.

Quickpost info

Monday 28 October 2019

Quickpost: Compiling Service DLLs with MinGW on Kali

Filed under: Quickpost — Didier Stevens @ 7:36

Compiling a service DLL (a Windows DLL implementing a service to be executed inside a shared svchost.exe process) with MinGW on Kali, is almost the same as compiling a DLL.

A service DLL implements a service and must export a ServiceMain function. To prevent name mangling of the exported function, the ServiceMain definition needs to be ‘extern “C”‘:

extern “C” VOID WINAPI ServiceMain(DWORD dwArgc, LPCWSTR* lpszArgv)

And we need a DEF file:


This DEF file can be passed as argument to the MinGW compiler.

To create a 32-bit DLL:

i686-w64-mingw32-gcc -shared -municode -o SvcHostDemo.dll SvcHostDemo.def SvcHostDemo.cpp

To create a 64-bit DLL:

x86_64-w64-mingw32-gcc -shared -municode -o SvcHostDemo.dll SvcHostDemo.def SvcHostDemo.cpp

Option -municode is needed because I use TCHARs and want to compile a UNICODE executable.

Here is the code of my service template:

#define _UNICODE

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

SERVICE_STATUS_HANDLE g_serviceStatusHandle = nullptr;
HANDLE g_hSvcStopEvent = NULL;


BOOL WINAPI DllMain(HMODULE hModule, DWORD dwReason, LPVOID lpReserved)
	switch (dwReason)
    return TRUE;

DWORD WINAPI HandlerEx(DWORD dwControl, DWORD dwEventType, LPVOID lpEventData, LPVOID lpContext)
	switch (dwControl)
			OutputDebugString(L"HandlerEx SERVICE_CONTROL_STOP");
			g_serviceStatus.dwCurrentState = SERVICE_STOPPED;
			OutputDebugString(L"HandlerEx SERVICE_CONTROL_SHUTDOWN");
			g_serviceStatus.dwCurrentState = SERVICE_STOPPED;
			OutputDebugString(L"HandlerEx SERVICE_CONTROL_PAUSE");
			g_serviceStatus.dwCurrentState = SERVICE_PAUSED;
			OutputDebugString(L"HandlerEx SERVICE_CONTROL_CONTINUE");
			g_serviceStatus.dwCurrentState = SERVICE_RUNNING;
			OutputDebugString(L"HandlerEx SERVICE_CONTROL_INTERROGATE");
			OutputDebugString(L"HandlerEx default");

	SetServiceStatus(g_serviceStatusHandle, &g_serviceStatus);

	return NO_ERROR;

	while (TRUE)
		if (g_serviceStatus.dwCurrentState == SERVICE_RUNNING)
			OutputDebugString(L"Working ...");

extern "C" VOID WINAPI ServiceMain(DWORD dwArgc, LPCWSTR* lpszArgv)
	TCHAR szOutput[256];
	DWORD dwIter;

	OutputDebugString(L"Begin ServiceMain");
	StringCchPrintf(szOutput, 256, L"dwArgc = %d", dwArgc);
	for (dwIter=0; dwIter<dwArgc; dwIter++)

	if (dwArgc > 0)
		g_serviceStatusHandle = RegisterServiceCtrlHandlerExW(lpszArgv[0], HandlerEx, nullptr);
		g_serviceStatusHandle = RegisterServiceCtrlHandlerExW(L"SvcHostDemo", HandlerEx, nullptr);
	if (!g_serviceStatusHandle)
		OutputDebugString(L"Error 1 ServiceMain");

	g_hSvcStopEvent = CreateEvent(NULL, TRUE, FALSE, NULL);

	if (g_hSvcStopEvent == NULL)
		OutputDebugString(L"Error 2 ServiceMain");

	g_serviceStatus.dwCurrentState = SERVICE_RUNNING;

	SetServiceStatus(g_serviceStatusHandle, &g_serviceStatus);

	OutputDebugString(L"Starting Worker ServiceMain");

	if (NULL == CreateThread(NULL, 0, Worker, NULL, 0, NULL))
		OutputDebugString(L"Error 3 ServiceMain");

	OutputDebugString(L"Waiting ServiceMain");

	WaitForSingleObject(g_hSvcStopEvent, INFINITE);

	OutputDebugString(L"End ServiceMain");

Quickpost info

Monday 21 October 2019

Quickpost: ExifTool, OLE Files and FlashPix Files

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

ExifTool can misidentify VBA macro files as FlashPix files.

The binary file format of Office documents (.doc, .xls) uses the Compound File Binary Format, what I like to refer as OLE files. These files can be analyzed with my tool oledump.py.

Starting with Office 2007, the default file format (.docx, .docm, .xlsx, …) is Office Open XML: OOXML. It’s in essence a ZIP container with XML files inside. However, VBA macros inside OOXML files (.docm, .xlsm) are not stored as XML files, they are still stored inside an OLE file: the ZIP container contains a file with name vbaProject.bin. That is an OLE file containing the VBA macros.

This can be observed with my zipdump.py tool:

oledump.py can look inside the ZIP container to analyze the embedded vbaProject.bin file:

And of course, it can handle an OLE file directly:

When ExifTool is given a vbaProject.bin file for analysis, it will misidentify it as a picture file: a FlashPix file.

That’s because when ExifTool doesn’t have enough metadata or an identifying extension to identify an OLE file, it will fall back to FlashPix file detection. That’s because FlashPix files are also based on the OLE file format, and AFAIK ExifTool started out as an image tool:

That is why on VirusTotal, vbaProject.bin files from OOXML files with macros, will be misidentified as FlashPix files:

When the extension of a vbaProject.bin file is changed to .doc, ExifTool will misidentify it as a Word document:

ExifTool is not designed to identify VBA macro files (vbaProject.bin). These files are not Office documents, neither pictures. But since they are also OLE files, ExifTool tries to guess what they are, based on the extension, and if that doesn’t help, it falls back to the FlashPix file format (based on OLE).

There’s no “bug” to fix, you just need to be aware of this particular behavior of ExifTool: it is a tool to extract information from media formats, when it analyses an OLE file and doesn’t have enough metadata/proper file extension, it will fall back to FlashPix identification.


Quickpost info

Next Page »

Blog at WordPress.com.