Didier Stevens

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:

LIBRARY SvcHostDemo
EXPORTS
	ServiceMain

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;

SERVICE_STATUS g_serviceStatus = {SERVICE_WIN32_SHARE_PROCESS, SERVICE_START_PENDING, SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN | SERVICE_ACCEPT_PAUSE_CONTINUE};

BOOL WINAPI DllMain(HMODULE hModule, DWORD dwReason, LPVOID lpReserved)
{
	OutputDebugString(L"DllMain");
	switch (dwReason)
    {
	    case DLL_PROCESS_ATTACH:
					OutputDebugString(L"DLL_PROCESS_ATTACH");
	        break;
	    case DLL_THREAD_ATTACH:
					OutputDebugString(L"DLL_THREAD_ATTACH");
	        break;
	    case DLL_THREAD_DETACH:
					OutputDebugString(L"DLL_THREAD_DETACH");
	        break;
	    case DLL_PROCESS_DETACH:
					OutputDebugString(L"DLL_PROCESS_DETACH");
	        break;
    }
    return TRUE;
}

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

	SetServiceStatus(g_serviceStatusHandle, &g_serviceStatus);

	return NO_ERROR;
}

DWORD WINAPI Worker(LPVOID lpParam)
{
	while (TRUE)
	{
		if (g_serviceStatus.dwCurrentState == SERVICE_RUNNING)
			OutputDebugString(L"Working ...");
		Sleep(1000);
	}
}

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);
	OutputDebugString(szOutput);
	for (dwIter=0; dwIter<dwArgc; dwIter++)
		OutputDebugString(lpszArgv[dwIter]);

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

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

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

	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");
		return;
	}

	OutputDebugString(L"Waiting ServiceMain");

	WaitForSingleObject(g_hSvcStopEvent, INFINITE);

	OutputDebugString(L"End ServiceMain");
}

Quickpost info


Sunday 27 October 2019

Update: pecheck.py Version 0.7.8

Filed under: My Software,Update — Didier Stevens @ 10:37

This new version of pecheck.py, a tool to analyze PE files, comes with a small update to option -l.

The overview of embedded PE files produced with option -l P now reports the hash of the embedded PE file without overlay:

By default, this is an MD5 hash, but can be changed to your liking using environment variable DSS_DEFAULT_HASH_ALGORITHMS, like this:

I will introduce this environment variable to my other tools with new releases.

 

pecheck-v0_7_8.zip (https)
MD5: 616CD9159316FC2100BE3E87C5C26B2C
SHA256: F734EFFFA17E4EE6CA64A67D18340B3347B72C4B1C7522BAF1B7D720FABA2389

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


Sunday 20 October 2019

New Tool: simple_tcp_stats.py

Filed under: My Software,Networking — Didier Stevens @ 10:25

My new tool simple_tcp_stats.py is a Python program that reads pcap files and produces simple statistics for each TCP connection.

For the moment, it calculates the entropy of the data (without packet reassembling) of each TCP connection (both directions) and reports this with a CSV file:

ConnectionID;head;Size;Entropy
192.168.10.10:50236-96.126.103.196:80;’GET ‘;364;5.42858024035
192.168.10.10:50235-96.126.103.196:80;’GET ‘;426;5.46464090792
96.126.103.196:80-192.168.10.10:50235;’HTTP’;3308;6.06151478505
96.126.103.196:80-192.168.10.10:50236;’HTTP’;493;6.73520107812

 

simple_tcp_stats_V0_0_1.zip (https)
MD5: 606DB4208BBC5908D9F32A68DDF90AC6
SHA256: 68B275C58736AE450D23BEA82CC1592936E541E00726D8ED95F5CA8ACB02B7CE

Tuesday 15 October 2019

PowerShell, Add-Type & csc.exe

Filed under: .NET,Forensics — Didier Stevens @ 0:00

Have you ever noticed that some PowerShell scripts result in the execution of the C# compiler csc.exe?

This happens when a PowerShell script uses cmdlet Add-Type.

Like in this command:

powershell -Command “Add-Type -TypeDefinition \”public class Demo {public int a;}\””

This command just adds the definition of a class (Demo) with one member (a).

When this Add-Type cmdlet is executed, the C# compiler is invoked by PowerShell to compile this class definition (a C# program) into an assembly (DLL) with the .NET type to be used by the PowerShell script.

A temporary file (oj5zlfcy.cmdline in this example) is created inside folder %appdata%\local\temp with extension .cmdline. This is passed as argument to the invoked C# compiler csc.exe, and contains directions to compile a C# program (oj5zlfcy.0.cs):

/t:library /utf8output /R:”System.dll” /R:”C:\WINDOWS\Microsoft.Net\assembly\GAC_MSIL\System.Management.Automation\v4.0_3.0.0.0__31bf3856ad364e35\System.Management.Automation.dll” /R:”System.Core.dll” /out:”C:\Users\testuser1\AppData\Local\Temp\oj5zlfcy.dll” /debug- /optimize+ /warnaserror /optimize+ “C:\Users\testuser1\AppData\Local\Temp\oj5zlfcy.0.cs”

The C# program (oj5zlfcy.0.cs in this example) contains the class definition passed as argument to cmdlet Add-Type:

public class Demo {public int a;}

Both these files start with a UTF-8 BOM (EF BB BF).

The C# compiler (csc.exe) can invoke compilation tools when necessary, like the resource compiler cvtres.exe.

This results in the creation of several temporary files:

All these files are removed when cmdlet Add-Type terminates.

 

Wednesday 2 October 2019

Shark Jack Capture File

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

I have a new toy: a “Shark Jack“. It’s a small device sold by Hak5 that performs a nmap scan (-sP) when plugged into a network port (that’s the default “payload”).

In this blog post, I’m sharing the network capture of a scan performed in this “test environment”:

The device (small black box, almost square) between the Shark Jack (SJ) and the router is my “Packet Squirrel”: a simple network capture device.

A couple of observations:

  1. The SJ was tested with its original firmware (1.0.0)
  2. The SJ will randomize its MAC address
  3. The SJ performs 2 full DHCP handshakes prior to the nmap scan
  4. The SJ listens on port 53 (tcp and udp) using dnsmasq (observed while scanning)

Example of different MAC addresses after before and after reboot:

root@shark:~# ifconfig
eth0 Link encap:Ethernet HWaddr 2E:AF:43:F2:3E:22
inet addr:172.16.24.1 Bcast:172.16.24.255 Mask:255.255.255.0

 

root@shark:~# ifconfig
eth0 Link encap:Ethernet HWaddr 86:72:96:71:C3:3C
inet addr:172.16.24.1 Bcast:172.16.24.255 Mask:255.255.255.0

 

And it can get quite hot while charging, as can be observed in this thermal image:

shark_jack_capture.zip (https)
MD5: 9E5C1187D64A6EC7284C06464E791F01
SHA256: 5153F5C7B559BEC1539B0395F97C5852064D7ED9309B837F11A9381EA6ED4C88

Tuesday 1 October 2019

Overview of Content Published in September

Filed under: Announcement — Didier Stevens @ 0:00

Here is an overview of content I published in September:

Blog posts:

YouTube videos:

Videoblog posts:

SANS ISC Diary entries:

NVISO blog posts:

Blog at WordPress.com.