Skip to content

Malware University

Class is in Session

  • About
    • Privacy Policy
  • Contact
  • Resources

Author: admin

TDL4 IDAPython Decryptor

Posted on September 14, 2021 - September 14, 2021 by admin

This is a script used to unpack a hidden area of the bootsector after a TDL4 infection. This is classic code but still useful is anyone needs it. Written by your humble admin many years ago.

import idaapi

# Simulate C-style for() loop.
def cfor(first, test, update):
    while test(first):
        yield first
        first = update(first)


# Bit-shifting operations.
#def ROR(x, n, bits = 32):
#    mask = (2L**n) - 1
#    mask_bits = x & mask
#    return (x >> n) | (mask_bits << (bits - n))

#def ROL(x, n, bits = 32):
#    return ROR(x, bits - n, bits)
def ROR(byte, count):
    while count > 0:
        byte = (byte >> 1 | byte << 7) & 0xFF
        count -= 1
    return byte


if __name__ == "__main__":
    print "TDL4 Decrypt"
    print "A script to unpack the contents hidden on the bootsector of a TDL4 infected host"
    print ""
    
    encryptedBytes = [None] * 311
    
    rorCount = 311  # 0x137 (CX)
    count = 0
    # target starts at 0x62A in memory
    for i in cfor(int('0x2A', 16), lambda i : i < (311 + i), lambda i : i + 1):
        cryptedByte = idaapi.get_byte(i)
        print "Byte[" + hex(i) + "]:    " + hex(cryptedByte)
        idaapi.patch_byte(i, ROR(cryptedByte, rorCount - count))
        count += 1
        if count == 311:
            break
Posted in UtilitiesTagged bootsector, decryptor, ida pro, idapython, malware, tdl4, windowsLeave a comment

Read (and infect) Windows MBR

Posted on September 14, 2021 - September 14, 2021 by admin

This code is useful for detecting the exact version of Windows you are using, and then choosing to infect (writing to PHYSICALDRIVE0) of the target machine. Windows 2012 Server and XP are supported in this snippet.

#include "stdafx.h"

#define BUFFER_SIZE		1000
#define SZ_WXP_MBR		382
#define SZ_W2K12_MBR	870 

// You can't include things like partition table, because they are probably unique to each machine.
unsigned char WXP_MBR[382] = {
    0x33, 0xC0, 0x8E, 0xD0, 0xBC, 0x00, 0x7C, 0xFB,
    0x50, 0x07, 0x50, 0x1F, 0xFC, 0xBE, 0x1B, 0x7C,
    0xBF, 0x1B, 0x06, 0x50, 0x57, 0xB9, 0xE5, 0x01,
    0xF3, 0xA4, 0xCB, 0xBD, 0xBE, 0x07, 0xB1, 0x04,
    0x38, 0x6E, 0x00, 0x7C, 0x09, 0x75, 0x13, 0x83,
    0xC5, 0x10, 0xE2, 0xF4, 0xCD, 0x18, 0x8B, 0xF5,
    0x83, 0xC6, 0x10, 0x49, 0x74, 0x19, 0x38, 0x2C,
    0x74, 0xF6, 0xA0, 0xB5, 0x07, 0xB4, 0x07, 0x8B,
    0xF0, 0xAC, 0x3C, 0x00, 0x74, 0xFC, 0xBB, 0x07,
    0x00, 0xB4, 0x0E, 0xCD, 0x10, 0xEB, 0xF2, 0x88,
    0x4E, 0x10, 0xE8, 0x46, 0x00, 0x73, 0x2A, 0xFE,
    0x46, 0x10, 0x80, 0x7E, 0x04, 0x0B, 0x74, 0x0B,
    0x80, 0x7E, 0x04, 0x0C, 0x74, 0x05, 0xA0, 0xB6,
    0x07, 0x75, 0xD2, 0x80, 0x46, 0x02, 0x06, 0x83,
    0x46, 0x08, 0x06, 0x83, 0x56, 0x0D, 0x0A, 0x00,
    0xE8, 0x21, 0x00, 0x73, 0x05, 0xA0, 0xB6, 0x07,
    0xEB, 0xBC, 0x81, 0x3E, 0xFE, 0x7D, 0x55, 0xAA,
    0x74, 0x0B, 0x80, 0x7E, 0x10, 0x00, 0x74, 0xC8,
    0xA0, 0xB7, 0x07, 0xEB, 0xA9, 0x8B, 0xFC, 0x1E,
    0x57, 0x8B, 0xF5, 0xCB, 0xBF, 0x05, 0x00, 0x8A,
    0x56, 0x00, 0xB4, 0x08, 0xCD, 0x13, 0x72, 0x23,
    0x8A, 0xC1, 0x24, 0x3F, 0x98, 0x8A, 0xDE, 0x8A,
    0xFC, 0x43, 0xF7, 0xE3, 0x8B, 0xD1, 0x86, 0xD6,
    0xB1, 0x06, 0xD2, 0xEE, 0x42, 0xF7, 0xE2, 0x39,
    0x56, 0x0D, 0x0A, 0x77, 0x23, 0x72, 0x05, 0x39,
    0x46, 0x08, 0x73, 0x1C, 0xB8, 0x01, 0x02, 0xBB,
    0x00, 0x7C, 0x8B, 0x4E, 0x02, 0x8B, 0x56, 0x00,
    0xCD, 0x13, 0x73, 0x51, 0x4F, 0x74, 0x4E, 0x32,
    0xE4, 0x8A, 0x56, 0x00, 0xCD, 0x13, 0xEB, 0xE4,
    0x8A, 0x56, 0x00, 0x60, 0xBB, 0xAA, 0x55, 0xB4,
    0x41, 0xCD, 0x13, 0x72, 0x36, 0x81, 0xFB, 0x55,
    0xAA, 0x75, 0x30, 0xF6, 0xC1, 0x01, 0x74, 0x2B,
    0x61, 0x60, 0x6A, 0x00, 0x6A, 0x00, 0xFF, 0x76,
    0x0D, 0x0A, 0xFF, 0x76, 0x08, 0x6A, 0x00, 0x68,
    0x00, 0x7C, 0x6A, 0x01, 0x6A, 0x10, 0xB4, 0x42,
    0x8B, 0xF4, 0xCD, 0x13, 0x61, 0x61, 0x73, 0x0E,
    0x4F, 0x74, 0x0B, 0x32, 0xE4, 0x8A, 0x56, 0x00,
    0xCD, 0x13, 0xEB, 0xD6, 0x61, 0xF9, 0xC3, 0x49,
    0x6E, 0x76, 0x61, 0x6C, 0x69, 0x64, 0x20, 0x70,
    0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6F, 0x6E,
    0x20, 0x74, 0x61, 0x62, 0x6C, 0x65, 0x00, 0x45,
    0x72, 0x72, 0x6F, 0x72, 0x20, 0x6C, 0x6F, 0x61,
    0x64, 0x69, 0x6E, 0x67, 0x20, 0x6F, 0x70, 0x65,
    0x72, 0x61, 0x74, 0x69, 0x6E, 0x67, 0x20, 0x73,
    0x79, 0x73, 0x74, 0x65, 0x6D, 0x00, 0x4D, 0x69,
    0x73, 0x73, 0x69, 0x6E, 0x67, 0x20, 0x6F, 0x70,
    0x65, 0x72, 0x61, 0x74, 0x69, 0x6E, 0x67, 0x20,
    0x73, 0x79, 0x73, 0x74, 0x65, 0x6D 
};

unsigned char W2K12_MBR[870] = {
    0xFF, 0xFE, 0x33, 0x00, 0x14, 0x25, 0xC4, 0x00,
    0x68, 0x25, 0x5D, 0x25, 0x00, 0x00, 0x7C, 0x00,
    0xC4, 0x00, 0x14, 0x25, 0xC4, 0x00, 0x6A, 0x25,
    0x5B, 0x25, 0x00, 0x00, 0x7C, 0x00, 0x10, 0x25,
    0x00, 0x00, 0x06, 0x00, 0x63, 0x25, 0x00, 0x00,
    0x02, 0x00, 0x7F, 0x20, 0x64, 0x22, 0xF1, 0x00,
    0x50, 0x00, 0x68, 0x00, 0x1C, 0x00, 0x06, 0x00,
    0x66, 0x25, 0x1A, 0x22, 0x63, 0x25, 0x04, 0x00,
    0x00, 0x00, 0x5C, 0x25, 0x5B, 0x25, 0x07, 0x00,
    0xC7, 0x00, 0x7E, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x7C, 0x00, 0x0B, 0x00, 0x0F, 0x00, 0xE0, 0x00,
    0x0E, 0x00, 0x01, 0x00, 0xE2, 0x00, 0x3C, 0x25,
    0x10, 0x00, 0x93, 0x03, 0xB1, 0x00, 0x50, 0x25,
    0x18, 0x00, 0xEA, 0x00, 0x56, 0x00, 0x00, 0x00,
    0x55, 0x00, 0x5E, 0x25, 0x46, 0x00, 0x11, 0x00,
    0x05, 0x00, 0x5E, 0x25, 0x46, 0x00, 0x10, 0x00,
    0x00, 0x00, 0x24, 0x25, 0x41, 0x00, 0x57, 0x25,
    0xAC, 0x00, 0x55, 0x00, 0x50, 0x25, 0x13, 0x00,
    0x5D, 0x00, 0x72, 0x00, 0x0F, 0x00, 0xFC, 0x00,
    0x1A, 0x22, 0x55, 0x00, 0xAC, 0x00, 0x75, 0x00,
    0x09, 0x00, 0x48, 0x22, 0x34, 0x25, 0x01, 0x00,
    0x00, 0x00, 0x74, 0x00, 0x03, 0x00, 0xA0, 0x25,
    0x46, 0x00, 0x10, 0x00, 0x66, 0x00, 0x60, 0x00,
    0xC7, 0x00, 0x7E, 0x00, 0x10, 0x00, 0x00, 0x00,
    0x74, 0x00, 0x26, 0x00, 0x66, 0x00, 0x68, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x66, 0x00, 0xA0, 0x00, 0x76, 0x00, 0x08, 0x00,
    0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x68, 0x00,
    0x00, 0x00, 0x7C, 0x00, 0x68, 0x00, 0x01, 0x00,
    0x00, 0x00, 0x68, 0x00, 0x10, 0x00, 0x00, 0x00,
    0x24, 0x25, 0x42, 0x00, 0xE8, 0x00, 0x56, 0x00,
    0x00, 0x00, 0xEF, 0x00, 0x20, 0x23, 0x50, 0x25,
    0x13, 0x00, 0x92, 0x01, 0xE2, 0x00, 0x00, 0x25,
    0x10, 0x00, 0xA7, 0x20, 0xB4, 0x03, 0x14, 0x00,
    0x55, 0x25, 0x01, 0x00, 0x02, 0x00, 0x57, 0x25,
    0x00, 0x00, 0x7C, 0x00, 0xE8, 0x00, 0x56, 0x00,
    0x00, 0x00, 0xE8, 0x00, 0x76, 0x00, 0x01, 0x00,
    0xE8, 0x00, 0x4E, 0x00, 0x02, 0x00, 0xE8, 0x00,
    0x6E, 0x00, 0x03, 0x00, 0x50, 0x25, 0x13, 0x00,
    0x66, 0x00, 0x61, 0x00, 0x73, 0x00, 0x1C, 0x00,
    0xA0, 0x25, 0x4E, 0x00, 0x11, 0x00, 0x75, 0x00,
    0x0C, 0x00, 0xC7, 0x00, 0x7E, 0x00, 0x00, 0x00,
    0xC7, 0x00, 0x0F, 0x00, 0xE4, 0x00, 0xE8, 0x00,
    0x00, 0x00, 0x93, 0x25, 0xC7, 0x00, 0xB4, 0x03,
    0xE4, 0x00, 0x55, 0x00, 0x32, 0x00, 0xA3, 0x03,
    0xE8, 0x00, 0x56, 0x00, 0x00, 0x00, 0x50, 0x25,
    0x13, 0x00, 0x5D, 0x00, 0xB4, 0x03, 0xA7, 0x20,
    0xFC, 0x00, 0x3E, 0x00, 0xA0, 0x25, 0x7D, 0x00,
    0x55, 0x00, 0xAC, 0x00, 0x75, 0x00, 0x6E, 0x00,
    0xA0, 0x00, 0x76, 0x00, 0x00, 0x00, 0xA6, 0x03,
    0xEC, 0x00, 0x00, 0x00, 0x75, 0x00, 0x17, 0x00,
    0xB7, 0x00, 0x91, 0x25, 0x64, 0x25, 0xB5, 0x00,
    0x64, 0x00, 0xA6, 0x03, 0xE2, 0x00, 0x00, 0x00,
    0x91, 0x25, 0x80, 0x25, 0xB5, 0x00, 0x60, 0x00,
    0xA6, 0x03, 0x7C, 0x00, 0x00, 0x00, 0x91, 0x25,
    0xA0, 0x00, 0xB5, 0x00, 0x64, 0x00, 0xA6, 0x03,
    0x75, 0x00, 0x00, 0x00, 0x1A, 0x22, 0x55, 0x25,
    0x00, 0x00, 0x57, 0x25, 0x50, 0x25, 0x1A, 0x00,
    0x66, 0x00, 0x23, 0x00, 0x14, 0x25, 0x75, 0x00,
    0x3B, 0x00, 0x66, 0x00, 0xFC, 0x00, 0x1A, 0x22,
    0x54, 0x00, 0x43, 0x00, 0x50, 0x00, 0x41, 0x00,
    0x75, 0x00, 0x32, 0x00, 0xFC, 0x00, 0x19, 0x22,
    0x02, 0x00, 0x01, 0x00, 0x72, 0x00, 0x2C, 0x00,
    0x66, 0x00, 0x68, 0x00, 0x07, 0x00, 0x57, 0x25,
    0x00, 0x00, 0x00, 0x00, 0x66, 0x00, 0x68, 0x00,
    0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x66, 0x00, 0x68, 0x00, 0x08, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x66, 0x00, 0x53, 0x00,
    0x66, 0x00, 0x53, 0x00, 0x66, 0x00, 0x55, 0x00,
    0x66, 0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x66, 0x00, 0x68, 0x00,
    0x00, 0x00, 0x7C, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x66, 0x00, 0x61, 0x00, 0x68, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x07, 0x00, 0x50, 0x25, 0x1A, 0x00,
    0x5A, 0x00, 0x32, 0x00, 0xF7, 0x00, 0xA9, 0x03,
    0x00, 0x00, 0x7C, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x50, 0x25, 0x18, 0x00, 0xE1, 0x00, 0x56, 0x25,
    0x07, 0x00, 0xB4, 0x03, 0x08, 0x00, 0xE1, 0x00,
    0x62, 0x25, 0x07, 0x00, 0xB4, 0x03, 0x03, 0x00,
    0xE1, 0x00, 0x61, 0x25, 0x07, 0x00, 0x32, 0x00,
    0xA3, 0x03, 0x05, 0x00, 0x00, 0x00, 0x07, 0x00,
    0xEF, 0x00, 0x61, 0x22, 0xBC, 0x00, 0x3C, 0x00,
    0x00, 0x00, 0x74, 0x00, 0x09, 0x00, 0x57, 0x25,
    0x07, 0x00, 0x00, 0x00, 0x24, 0x25, 0x0E, 0x00,
    0x50, 0x25, 0x10, 0x00, 0xB4, 0x03, 0x65, 0x22,
    0x20, 0x23, 0xB4, 0x03, 0xB2, 0x00, 0x2B, 0x00,
    0x54, 0x25, 0xA3, 0x03, 0x64, 0x00, 0xB4, 0x03,
    0x00, 0x00, 0x24, 0x00, 0x02, 0x00, 0xB1, 0x03,
    0xB0, 0x00, 0x24, 0x00, 0x02, 0x00, 0x1C, 0x25,
    0x49, 0x00, 0x6E, 0x00, 0x76, 0x00, 0x61, 0x00,
    0x6C, 0x00, 0x69, 0x00, 0x64, 0x00, 0x20, 0x00,
    0x70, 0x00, 0x61, 0x00, 0x72, 0x00, 0x74, 0x00,
    0x69, 0x00, 0x74, 0x00, 0x69, 0x00, 0x6F, 0x00,
    0x6E, 0x00, 0x20, 0x00, 0x74, 0x00, 0x61, 0x00,
    0x62, 0x00, 0x6C, 0x00, 0x65, 0x00, 0x00, 0x00,
    0x45, 0x00, 0x72, 0x00, 0x72, 0x00, 0x6F, 0x00,
    0x72, 0x00, 0x20, 0x00, 0x6C, 0x00, 0x6F, 0x00,
    0x61, 0x00, 0x64, 0x00, 0x69, 0x00, 0x6E, 0x00,
    0x67, 0x00, 0x20, 0x00, 0x6F, 0x00, 0x70, 0x00,
    0x65, 0x00, 0x72, 0x00, 0x61, 0x00, 0x74, 0x00,
    0x69, 0x00, 0x6E, 0x00, 0x67, 0x00, 0x20, 0x00,
    0x73, 0x00, 0x79, 0x00, 0x73, 0x00, 0x74, 0x00,
    0x65, 0x00, 0x6D, 0x00, 0x00, 0x00, 0x4D, 0x00,
    0x69, 0x00, 0x73, 0x00, 0x73, 0x00, 0x69, 0x00,
    0x6E, 0x00, 0x67, 0x00, 0x20, 0x00, 0x6F, 0x00,
    0x70, 0x00, 0x65, 0x00, 0x72, 0x00, 0x61, 0x00,
    0x74, 0x00, 0x69, 0x00, 0x6E, 0x00, 0x67, 0x00,
    0x20, 0x00, 0x73, 0x00, 0x79, 0x00, 0x73, 0x00,
    0x74, 0x00, 0x65, 0x00, 0x6D, 0x00 
};




BOOL IsUserAdmin()
{
	BOOL b;
	SID_IDENTIFIER_AUTHORITY ntAuthority = SECURITY_NT_AUTHORITY;
	PSID administratorsGroup;

	b = AllocateAndInitializeSid(&ntAuthority,
		2,
		SECURITY_BUILTIN_DOMAIN_RID,
		DOMAIN_ALIAS_RID_ADMINS,
		0, 0, 0, 0, 0, 0,
		&administratorsGroup);
	if (b)
	{
		if (!CheckTokenMembership(NULL, administratorsGroup, &b))
			b = FALSE;
		FreeSid(administratorsGroup);
	}

	return b;
}

// We look for exact matches at the moment.

BOOL IsWindowsXP(char* mbr)
{
	for (int i = 0; i < SZ_WXP_MBR; i++)
		if (*(mbr + i) != *(WXP_MBR + i))
			return false;
	return true;
}

BOOL IsWindows2012(char* mbr)
{
	for (int i = 0; i < SZ_W2K12_MBR; i++)
		if (*(mbr + i) != *(W2K12_MBR + i))
			return false;
	return true;
}

void InfectMBR_XP()
{

}

void InfectMBR_2012()
{

}



int _tmain(int argc, _TCHAR* argv[])
{
	FILE*		dosDevice;
	FILE*		outputFile;
	char		buffer[BUFFER_SIZE];

	if (!IsUserAdmin())
	{
		fprintf(stderr, "You must be admin\n");

		return -1;
	}

	dosDevice = fopen("\\\\.\\PHYSICALDRIVE0", "rb");
	if (!dosDevice)
	{
		fprintf(stderr, "Unable to open MBR\n");

		return -2;
	}

	outputFile = fopen("output.img", "wb");
	if (!outputFile)
	{
		fprintf(stderr, "Unable to open output file\n");

		return -1;
	}

	fread(buffer, BUFFER_SIZE, sizeof(char), dosDevice);
	fclose(dosDevice);

	if (IsWindowsXP(buffer))
		fprintf(stdout, "Detected Windows XP MBR\n");
	else if (IsWindows2012(buffer))
		fprintf(stdout, "Detected Windows 2012 Server MBR\n");

	return 0;
}
Posted in Code Analysis, Malware Development, TechniquesTagged infector, mbr, windowsLeave a comment

Windows XP SP3 Bootsector Analysis: Part 2

Posted on September 14, 2021 - September 14, 2021 by admin

These are notes made while disassembling the Windows XP Service Pack 3 bootsector (x86 real mode) code.

; This is the "Volume Boot Record".
; Also called "Windows bootstrap loader"/"Windows partition boot sector"
; The section before this is the MBR of the hard disk, next is NTLDR.


.686p
.mmx
.model flat

; Segment type:	Pure code
BOOT_SECTOR segment byte public	'CODE' use16
assume cs:BOOT_SECTOR
;org 7C00h
assume es:nothing, ss:nothing, ds:nothing, fs:nothing, gs:nothing

; =============== S U B	R O U T	I N E =======================================

; DL = 0x82
; drive	number on Bochs	XP
; Attributes: noreturn

public start
start proc far				; CODE XREF: debug002:20101J
					; DATA XREF: BOOT_SECTOR:7CDEo
jmp	short near ptr sub_7C54	; jump over BPB to beginning of code
start endp

; ---------------------------------------------------------------------------
db 90h
db 4Eh,	54h					; 8-byte OEM ID or System Name ("NTFS    ")
db 46h
db 53h
db 20h
db 20h,	20h, 20h, 
; Start of NTFS BPB (Bios Parameter Block) (size 54h inclusive)
; REMEMBER THIS IS A MEMORY SNAPSHOT, THUS VALUES ARE IN LITTLE ENDIAN, whereas on disk 
; it's big endian
dw 0002h,					; Sector Size (in bytes) (512)
db 8,						; Sectors per Cluster
							; Number of sectors per allocation unit.
							; 512 * 8 = 4096 (4kb cluster size)
							; value is 4 if partition < 2GB
byte_7C0E dw 0000			; DATA XREF: sub_7C54+18w
							; Reserved Sectors (on disk)
							; After loading into memory:
							;	stores number of sectors of Boot Record read into memory
							;	begins with value of 0x10 (16) and counts down to zero
dword_7C10 dd 0				; DATA XREF: BOOT_SECTOR:loc_7CCBr
byte_7C14 db 0				; DATA XREF: sub_7CAA+18w
					; BOOT_SECTOR:7CEBr ...
db 0F8h 					; "Fixed Disk" Media Descriptor ID
dw 0000 					; Must be set to zero for NTFS volumes
							; Originally for FAT 12/16 "Sectors per FAT" value
dw 3F00h 					; Sectors per track (0x3F)
dw 0FF00h					; Number of Heads (sides) (0xFF)	
dword_7C1C dd 3Fh			; DATA XREF: BOOT_SECTOR:7CCFr
							; stored 3F 00 00 00 in memory
							; number of "Hidden (Reserved) Sectors" (cylinder = head = 0)
							; count of hidden sectors preceding partition that contains this volume
dword_7C20 dd 0				; DATA XREF: sub_7C54+51w
							; on disk:
							; 	not used in NTFS
							; 	Total Number of Sectors (FAT32)
							; in memory:
							;	stores Total Number of Sectors in the partition we're trying to boot
					; BOOT_SECTOR:7CD4r
byte_7C24 db 80h			; DATA XREF: sub_7C7Br	sub_7CAA+5r ...
							; First byte of four byte sequence indicates Drive Number (0x80)
							; NTFS OS always fills these bytes with "80 00 80 00"
			db 0
			db 80h
			db 0
db 89h						; Total Sectors (in the Volume)
db B6h						; 00000000007FB689 (long long word)
db 7Fh						; 1 sector less than total number to account for NTFS "Backup Sector"
db 0						; "Backup Sector" not considered part of NTFS volume
db 0
db 0
db 0
db 0
							; end of Total Sectors
	db 0					; Starting Cluster Number (for $MFT file in this partition)
	db 0					; 0000000000040000 (long long word)
	db 4
	db 0
	db 0
	db 0
	db 0
	db 0
							; end of Starting Cluster Number
db 68h						; Starting Cluster Number (for $MFTMirror file in this partition)
db 0FBh						; 000000000007FB68 (long long word)
db 7
db 0
db 0
db 0
db 0
db 0
							; end of Starting Cluster Number
db 0F6h						; Clusters (or bytes) per File Record Segment (FRS)
							; signed byte (-10 -> 1024 bytes)
							; Can be negative when cluster size (8) > MFT File Record Size
							; From MS:
							; "If this number is positive (up to 0x7F), it represents Clusters 
							; per MFT record. 
							; If the number is negative (0x80 to 0xFF), the size of the File Record 
							; is 2 raised to the absolute value of this number."
							; 2 ^ (|-10|) = 2 ^ 10 = 1024 bytes
db 0, 0, 0					; Unused by NTFS (3 bytes)
db 1						; Clusters per Index Buffer
							; signed byte
							; Size of each index buffer, used to allocate space for NTFS structures
							; such as directories
db 0, 0, 0					; Unused by NTFS (3 bytes)
db 0B8h, 0F8h, 0FBh			; NTFS Volume Serial Number
db 0B4h, 1Ah, 0FCh, 0B4h, 0D8h	; [B4 FB] F8 B8 
								; D8 [B4 FC] 1A (long long word)
								; the [] are different than thestarman's
dd 0						; Unused by NTFS

; =============== S U B	R O U T	I N E =======================================

; Attributes: noreturn

sub_7C54 proc far			; CODE XREF: startj

; FUNCTION CHUNK AT 026A SIZE 00000199 BYTES
; FUNCTION CHUNK AT 7C81 SIZE 00000029 BYTES

cli							; disable maskable interrupts
xor	ax, ax					; AX = 0
mov	ss, ax					; SS = 0
assume es:debug002, ss:debug002, ds:debug002 ; inaccurate and wtf is assume?
mov	sp, 7C00h				; SP = 0x7C00
sti							; enable interrupts
mov	ax, 7C0h				; AX = 0x07C0
mov	ds, ax					; DS = 0x07C0
assume ds:nothing
call	sub_7C7B			; drive	number (80)
							; stores total sectors of boot partition in BPB offset 20h
mov	ax, 0D00h				; 0000:7C65, AX = 0x0D00
mov	es, ax					; ES = 0x0D00
assume es:nothing
xor	bx, bx					; BX = 0
mov	byte ptr ds:0Eh, 10h	; *(BYTE *)07C0:000E (0x7C0E) = 0x10
call	loc_7CC7			; reads all boot sectors in memory beginning at 0D00:0000 and ending
							; at 0F00:0000
; ---------------------------------------------------------------------------
push	0D00h
push	26Ah
retf						; returns to 0D00:026A or 0xD26A
sub_7C54 endp ;	sp-analysis failed


; =============== S U B	R O U T	I N E =======================================

; drive	number (80)
; sub_7C7B is _CalculateTotalSectorsBootPartition
; Calculates total sectors in the boot partition using only CHS
sub_7C7B proc near			; CODE XREF: sub_7C54+Ep
mov	dl, ds:24h				; 07C0:0024 = 0x80 (DX = 0x0180)
							; DS:0000 is pointer to start of BPB
							; 0x80 is the first hard drive (offset 24h of BPB)
mov	ah, 8					; AX = 0x08C0
sub_7C7B endp ;	sp-analysis failed
; START	OF FUNCTION CHUNK FOR sub_7C54
int	13h				; DISK - DISK -	GET CURRENT DRIVE PARAMETERS (XT,AT,XT286,CONV,PS)
					; DL = drive number
					; Return: CF set on error, AH =	status code (0), BL	= drive	type (0)
					; DL = number of consecutive drives on the system (1)
					; DH = maximum head number (0xFE)
					; ES:DI -> drive parameter [ EB 52 90 4E 54 46 53 20 20 20 20 ]
					;		Disk Base Table
					; CX = 0x09BF
					; CH = low 8 bits of maximum cylinder number
					; CL (bits 7 - 6) = high 2 bits of maximum cylinder number
					; CL (bits 5 - 0) = maximum sector number
					; Returns CF = 0
jnb	short loc_7C8A	; jump if successful
mov	cx, 0FFFFh		; Not successful?  Set CX = 0xFFFF and DH = 0xFF
mov	dh, cl			; Results in count of 0x00FC0000 or 16515072 sectors being placed into
					; [0000:7C20] and following

loc_7C8A:				; CODE XREF: sub_7C54+2Fj
movzx	eax, dh		; EAX = 0x000000FE
inc	ax				; AX = 0x00FF (total heads)
movzx	edx, cl		; EDX = 0x000000BF (maximum sector number)
and	dl, 3Fh			; DX = 0x003F (0x3F is maximum number of heads)
mul	dx				; head number *	max number of sectors
					; 0x3F * 0xFF
					; DX = 0
					; AX = 0x3EC1
xchg	cl, ch		; CH = 0xBF
					; CL = 0x09 (low 8 bits of maximum cylinder number)
shr	ch, 6			; CX = 0x0209 (shift bits 7-6 of CH next to CL)
					; CX now equals the maximum cylinder number
inc	cx				; CX = 0x020A (total cylinders)
movzx	ecx, cx		; ECX = 0x0000020A
mul	ecx				; 20A *	3EC1
					; EDX = 0
					; EAX = 0x007FF58A (total number of sectors)
mov	ds:20h,	eax		; 07C0:0020 (7C20) = 8A F5 7F 00 (little endian)
					; stores total number of sectors in offset 20h of BPB
retn				; returns to 7C65 (07C0:0065)
; END OF FUNCTION CHUNK	FOR sub_7C54

; =============== S U B	R O U T	I N E =======================================

; sub_7CAA is _TestInt13Extensions
sub_7CAA proc near			; CODE XREF: BOOT_SECTOR:7CF4p
mov	ah, 41h			; function 0x41
mov	bx, 55AAh		; has to be 0x55AA for function
mov	dl, ds:24h
int	13h				; DISK - Check for INT 13h Extensions
					; BX = 55AAh, DL = drive number
					; Return: CF set if not	supported
					; AH = extensions version
					; BX = AA55h
					; CX = Interface support bit map
jb	short locret_7CC6 ; jump if failed
cmp	bx, 0AA55h
jnz	short locret_7CC6 ; jump if failed
test	cl, 1
jz	short locret_7CC6 ; test if "Device Access using the packet structure"
inc	byte ptr ds:14h	  ; increase high-byte of small sectors count for FAT12/16

locret_7CC6:				; CODE XREF: sub_7CAA+Bj sub_7CAA+11j	...
retn
sub_7CAA endp

; ---------------------------------------------------------------------------

; loc_7CC7 is _ReadAllBootSectors
; stores all boot sectors (16) into memory at 0D00:000
loc_7CC7:				; CODE XREF: sub_7C54+1Dp
pushad					; save all (double) general-purpose registers
push	ds				; *SP = 0x07C0 (pointer to BPB offset 0)
push	es				; *SP = 0x0D00 (pointer to RAM location)

loc_7CCB:				; CODE XREF: BOOT_SECTOR:7D58j
mov	eax, ds:10h			; EAX = 0x00000000 (for NTFS, always 0)
add	eax, ds:1Ch			; EAX = 0x0000003F (number of "Hidden Sectors")
cmp	eax, ds:20h			; 0x3F < 0x7FF58A (Logical Block Addressing)
						; This is making sure we have at least a full "track" (63 sectors).
						; We can't have more "Hidden Sectors" than the total number of sectors!
jb	loc_7D17			; jump on success
push	ds
push	large (offset start - offset start) ; DMA page register	74LS612:
					; Channel 7 (address bits 17-23)
push	eax
push	es
push	bx
push	large 10010h			; DMA page register 74LS612:
					; Channel 7 (address bits 17-23)
cmp	byte ptr ds:14h, 0	; Not used on NTFS/FAT32 (0), 
						; but it's the high-byte of the "small sectors count" for FAT12/16
jnz	loc_7D00
call	sub_7CAA		; check for extended Int13 code
cmp	byte ptr ds:14h, 0

loc_7CFC:
jz	loc_7D61			; jumps if extensions are NOT installed ("A disk read error")

loc_7D00:				; CODE XREF: BOOT_SECTOR:7CF0j
mov	ah, 42h	; 'B'
mov	dl, ds:24h
push	ss
pop	ds
assume ds:debug002
mov	si, sp
int	13h				; DISK - IBM/MS	Extension - EXTENDED READ (DL -	drive, DS:SI - disk address packet)
pop	eax
pop	bx
pop	es
assume es:nothing
pop	eax
pop	eax
pop	ds
assume ds:nothing
jmp	short loc_7D44
; ---------------------------------------------------------------------------

; This function will read in the first 16 sectors of the primary drive into RAM starting
; at 0D00:0000 to 0F00:0000 (exclusive).
; I believe what is read is the "Initial Program Loader."
; loc_7D17 is _ReadFirstSectorOfSecondHead
loc_7D17:				; CODE XREF: BOOT_SECTOR:7CD9j
xor	edx, edx			; EDX = 0
movzx	ecx, word ptr ds:18h	; ECX = 0x0000003F (sectors per track) offset 18h from BPB
div	ecx					; 0x3F (sectors per track) / 0x3F (number of "hidden sectors")
						; DX = 0x0000
						; AX = 0x0001
inc	dl					; DX = 0x0001
mov	cl, dl				; CX = 0x0001
mov	edx, eax			; EDX = 0x00000001
shr	edx, 10h			; EDX = 0x00000000 (align remainder on 512 boundary)
div	word ptr ds:1Ah		; 0x00FF (number of heads/sides) / 0x01
						; 1000000000b = 512 = 0x200
						; DX = 0x0001
						; AX = 0x0000 ?
xchg	dl, dh			; DH = 0x01 (head = 0x1)
						; DL = 0x00 (drive 0)
mov	dl, ds:24h			; DX = 0x0180 (80 is drive number)
mov	ch, al				; CX = 0x0001 (track = 0, sector = 1)
shl	ah, 6				; AX = 0
						; calculates the cube of AH, assuming AH <= 2 (10b)
or	cl, ah				; sets CL only if it is 1 (which it is)
mov	ax, 201h			; AX = 0x0201 (AH = function, AL = sectors to read)
int	13h				; DISK - READ SECTORS INTO MEMORY
					; AL = number of sectors to read (max 512 bytes (0x200)), CH = track, CL = sector
					; DH = head, DL	= drive, ES:BX -> buffer to fill (0D00:0000) (D000)
					; Return: CF set on error, AH =	status (0),	AL = number of sectors read (1)
					; Returns CF = 0

loc_7D44:				; CODE XREF: BOOT_SECTOR:7D15j
jb	loc_7D61		; jump if failed ("A disk read error")
mov	ax, es			; AX = 0x0D00
add	ax, 20h	; ' '	; AX = 0x0D20
					; adds 0x200 (512) bytes to (0D00:0000) or (0xD000) offset
mov	es, ax			; ES = 0x0D20	(0D20:xxxx) or (0xD200)
assume es:nothing
inc	dword ptr ds:10h; *(DWORD* ) 07C0:0010 (0x7C10) = 0x1
					; Field that apparently is used to count how many sectors were read
					; BPB offset 10h
dec	word ptr ds:0Eh ; *(WORD* ) 07C0:000E (0x7C0E) = 0x000F
					; BPB offset 0Eh is count of how many sectors are left to read
					; AF = 1, PF = 1
jnz	loc_7CCB		; jumps if 0x7C0E is not zero (now)
					; loops for 16 (0x10) times
pop	es				; restore original ES (0D00)
assume es:nothing
pop	ds				; restore original DS (07C0), wasn't modified
popad				; restore all (double) registers
retn				; return to 0000:7C74 (assuming everything just worked)
; ---------------------------------------------------------------------------

; loc_7D61 is _SomethingFailedRtn
loc_7D61:				; CODE XREF: BOOT_SECTOR:loc_7CFCj
					; BOOT_SECTOR:loc_7D44j
mov	al, ds:1F8h		; pointer value for message area ("A disk read error occurred")
call	sub_7D70
; ---------------------------------------------------------------------------
mov	al, ds:1FBh
call	sub_7D70
; ---------------------------------------------------------------------------
db 0FBh
; ---------------------------------------------------------------------------

loc_7D6E:				; CODE XREF: BOOT_SECTOR:loc_7D6Ej
jmp	short loc_7D6E		; endless loop

; =============== S U B	R O U T	I N E =======================================

; Attributes: noreturn

sub_7D70 proc near			; CODE XREF: BOOT_SECTOR:7D64p
					; BOOT_SECTOR:7D6Ap
mov	ah, 1

lodsb					; CODE XREF: BOOT_SECTOR:7D80j
cmp	al, 0				; check for NULL byte
jz	short locret_7D82	; jump if done printing message
mov	ah, 0Eh				; teletype output, one char at a time
mov	bx, 7
int	10h				; - VIDEO - WRITE CHARACTER AND	ADVANCE	CURSOR (TTY WRITE)
					; AL = character, BH = display page (alpha modes)
					; BL = foreground color	(graphics modes)
jmp	short loc_7D74		; continue printing while character exists
; ---------------------------------------------------------------------------

locret_7D82:				; CODE XREF: BOOT_SECTOR:7D77j
retn
; ---------------------------------------------------------------------------
aADiskReadErrorOccurred	db 0Dh,0Ah
db 'A disk read error occurred',0
aNtldrIsMissing	db 0Dh,0Ah
db 'NTLDR is missing',0
db 0Dh,	0Ah, 4Eh, 54h, 4Ch
dd 69205244h				; disk signature
aSCompressed db	's compressed',0
aPressCtrlAltDelToResta	db 0Dh,0Ah
db 'Press Ctrl+Alt+Del to restart',0Dh,0Ah,0
align 8
byte_7DF0 db 0,	0, 0, 0, 0, 0, 0, 0, 83h, 0A0h,	0B3h, 0C9h, 0, 0
word_7DFE dw 0AA55h			; DATA XREF: sub_61B:loc_681r
BOOT_SECTOR ends

; ===========================================================================

; Segment type:	Pure data
; Segment permissions: Read/Write
debug002 segment byte public 'DATA' use16
assume cs:debug002
;org 7E00h

; =============== S U B	R O U T	I N E =======================================

; F000:FFF0
; First	instruction on all BIOS	chips.
; Hard coded into all processors.
; Attributes: thunk

PowerOnResetVector proc	near
jmp	far ptr	loc_FE05B
PowerOnResetVector endp

; ---------------------------------------------------------------------------
db  30h	; 0
db  38h	; 8
db  2Fh	; /
db  32h	; 2
db  31h	; 1
db  2Fh	; /
db  31h	; 1
db  32h	; 2
db    0
db 0FCh	; �
db  80h	; �
BIOS ends

; ===========================================================================


Posted in Code AnalysisTagged bootsector, real mode, sp3, windows, windows xp, x86Leave a comment

Windows XP SP3 Bootsector Analysis: Part 1

Posted on September 14, 2021 - September 14, 2021 by admin

These are notes made while disassembling the Windows XP Service Pack 3 bootsector (x86 real mode) code.




; File Name   :	C:\Users\anonymous\Documents\windows_xpsp3_bootsector.img
; Format      :	Binary file
; Base Address:	0000h Range: 0000h - 0200h Loaded length: 0200h

		.686p
		.mmx
		.model flat

; ===========================================================================

; Segment type:	Pure code
seg000		segment	byte public 'CODE' use16
		assume cs:seg000
		assume es:nothing, ss:nothing, ds:nothing, fs:nothing, gs:nothing

; =============== S U B	R O U T	I N E =======================================


; ORIGin is 0x7C00
sub_0		proc far
		xor	ax, ax			; AX = 0
		mov	ss, ax			; SS = 0
		mov	sp, 7C00h		; SP = 0x7C00
		sti					; enable interrupts
		push	ax			; *SP = 0
		pop	es				; ES = *SP
		push	ax			; *SP = 0
		pop	ds				; DS = *SP
		cld					; clear direction (left to right)
		mov	si, 7C1Bh	; for (int i = 0; i < 0x1E5; i++)
					;    *((BYTE* ) 0x061B)	= *((BYTE* ) &0x7C1B);
		mov	di, 61Bh
		push	ax			; puts value of zero on top of stack
		push	di			; *SP = 0x061B
		mov	cx, 1E5h		; CX = 0x1E5 (number of elements to copy)
		rep movsb			; copy byte by byte
		retf				; 0000:061B
sub_0		endp


; =============== S U B	R O U T	I N E =======================================
; THIS CODE IS COPIED TO 0x061B FOR 0x1E5 BYTES (see above)
; This area is 0000:061B to 0000:0800 in RAM

sub_1B		proc far
		mov	bp, 7BEh		; BP points to partition table
		mov	cl, 4			; sets counter to 4 (max number active partitions)

; loc_20 is _FindActivePartition
loc_20:					; CODE XREF: sub_1B+Fj
		cmp	[bp+0],	ch		; *(BP + 0) = 0x80 (drive number)
		jl	short loc_2E	; jumps ((signed int)(0x0 - 0x80) < 0)
		jnz	short loc_3A	; jump if Active flag was negative (0xF0 to 0xFF, inclusive)
		add	bp, 10h			; only gets here if Active flag was zero (0x00)
		loop	loc_20		; loop a maximum of four times, trying to find active partition
							; reboot/pause if active partition not found after four attempts
		int	18h		; TRANSFER TO ROM BASIC
					; causes transfer to ROM-based BASIC (IBM-PC)
					; often	reboots	a compatible; often has	no effect at all

; loc_2E is _SuccessFoundActivePartition
loc_2E:					; CODE XREF: sub_1B+8j
		mov	si, bp		; if we made it here, we found the partition

loc_30:					; CODE XREF: sub_1B+1Dj
		add	si, 10h		; point to next partition entry
		dec	cx			; decrease counter
		jz	short loc_4F; jump if parsed all four partition table entries
		cmp	[si], ch	; check to see if active flag in next entry is NULL
		jz	short loc_30; check next partition entry, if we have any left (four possible)

; loc_3A is _PrintInvalidPartitionTable
loc_3A:					; CODE XREF: sub_1B+Aj
		mov	al, ds:7B5h	; AL = *(0x07B5) [2C] 

loc_3D:					; CODE XREF: sub_1B+4Ej sub_1B+64j ...
		mov	ah, 7		; AH = 0x07
		mov	si, ax		; DATA XREF: sub_1B+30r (0x072C)
						; 0x072C = "Invalid partition table"

; loc_41 is _LoadNextErrorChar
loc_41:					; CODE XREF: sub_1B+32j
		lodsb			; load character at ((BYTE* ) 0x072C++)

; loc_42 is _PrintErrorThenInfiniteLoop
loc_42:					; CODE XREF: sub_1B+29j
		cmp	al, 0		; until the byte is NULL (infinite loop!)
		jz	short loc_42
		mov	bx, 7		; BX = 0x7
		mov	ah, 0Eh		; AH = 0xE
		int	10h		; DATA XREF: sub_9B+8r	sub_9B+3Br ...
					; - VIDEO - WRITE CHARACTER AND	ADVANCE	CURSOR (TTY WRITE)
					; AL = character, BH = display page (alpha modes)
					; BL = foreground color	(graphics modes)
		jmp	short loc_41; load next character
; ---------------------------------------------------------------------------
; loc_4F is _PartitionTableParsed
loc_4F:					; CODE XREF: sub_1B+19j
		mov	[bp+10h], cl; set next partition entry to inactive (why?)
		call	sub_9B
		jnb	short loc_81

loc_57:					; CODE XREF: sub_1B+72j
		inc	byte ptr [bp+10h]
		cmp	byte ptr [bp+4], 0Bh
		jz	short loc_6B

loc_60:					; DATA XREF: sub_1B+11r
		cmp	byte ptr [bp+4], 0Ch
		jz	short loc_6B
		mov	al, ds:7B6h
		jnz	short loc_3D

loc_6B:					; CODE XREF: sub_1B+43j sub_1B+49j
		add	byte ptr [bp+2], 6
		add	word ptr [bp+8], 6
		adc	word ptr [bp+0Ah], 0
		call	sub_9B
		jnb	short loc_81
		mov	al, ds:7B6h
		jmp	short loc_3D
; ---------------------------------------------------------------------------
; loc_81 is _CheckPartitionMagic
loc_81:					; CODE XREF: sub_1B+3Aj sub_1B+5Fj
		cmp	word ptr ds:7DFEh, 0AA55h
		jz	short loc_94
		cmp	byte ptr [bp+10h], 0
		jz	short loc_57
		mov	al, ds:7B7h
		jmp	short loc_3D
; ---------------------------------------------------------------------------
; loc_94 is _LegitimatePartitionMagic
loc_94:					; CODE XREF: sub_1B+6Cj
		mov	di, sp		; DI = 0x7C00
		push	ds		; *(SP) = 0
		push	di		; *(SP) = 0x7C00
		mov	si, bp		; SI = 0x07BE (pointer to partition table entry)
		retf			; returns to 0000:7C00
						; END OF CURRENT ANALYSIS
						; GO TO PART 2 !!!!!!!!!!!!!!!!
						; GO TO PART 2 !!!!!!!!!!!!!!!!
						; GO TO PART 2 !!!!!!!!!!!!!!!!
						
						
						
						
						
						
						
sub_1B		endp ; sp-analysis failed


; =============== S U B	R O U T	I N E =======================================


sub_9B		proc near		; CODE XREF: sub_1B+37p sub_1B+5Cp
		mov	di, 5	; DI = 5 (write drive parameter to 0000:0005)
		mov	dl, [bp+0]	; DL = drive number (0x80)
		mov	ah, 8
		int	13h		; DISK - DISK -	GET CURRENT DRIVE PARAMETERS (XT,AT,XT286,CONV,PS)
					; DL = drive number (0x80)
					; Return: CF set on error, AH =	status code (0x8), BL = drive type (0)
					; DL = number of consecutive drives (0x1)
					; DH = maximum value for head number (0xFE), ES:DI -> drive parameter (0000:0005)
					; 0000:0005 points to Disk Base Table (http://stanislavs.org/helppc/dbt.html)
					;	value is : 0xFF 0x00 0xF0 0x53 0xFF 0x00 0xF0 0x53 0xFF 0x00 0xF0
					; returns CF = 0
		jb	short loc_CA	; jumps if failed
		mov	al, cl			; AL = 0xBF
		and	al, 3Fh			; AL = 0x3F	(why?)
		cbw					; AX = 0x003F
		mov	bl, dh			; BL = 0xFE
		mov	bh, ah			; BH = 0
		inc	bx				; BX = 0x00FF
		mul	bx				; 0xFF * 0x3F = 0x3EC1
							; AX = 0x3EC1
		mov	dx, cx			; DX = 0x09BF
		xchg	dl, dh		; DL = 0x09
							; DH = 0xBF
		mov	cl, 6			; CX = 0x0906
		shr	dh, cl			; DX = 0x0209
		inc	dx				; DX = 0x020A
		mul	dx				; 0x020A * 0x3EC1 = 0x7FF58A (Logical Block Addressing)
							; DX = 0x7F
							; AX = 0xF58A
		cmp	[bp+0Ah], dx	; 0 < 0x7F
		ja	short loc_E6	; definitely not
		jb	short loc_CA	; yes
		cmp	[bp+8],	ax		; 0x003F < 0xF58A (doesn't get here normally)
		jnb	short loc_E6	; jumps if something is messed up? has to check for INT 13 extensions

; loc_CA is _GetCurrentDriveParametersError
loc_CA:					; CODE XREF: sub_9B+Aj	sub_9B+28j ...
		mov	ax, 201h		; AX = 0x0201
		mov	bx, 7C00h		; BX = 0x7C00
		mov	cx, [bp+2]		; CX = 0x00 (track) 01 (sector)
		mov	dx, [bp+0]		; DX = 0x01 (head) 80 (drive)
		int	13h		; DISK - READ SECTORS INTO MEMORY
					; AL = number of sectors to read, CH = track, CL = sector
					; DH = head, DL	= drive, ES:BX -> buffer to fill (0000:7C00)
					; Return: CF set on error, AH =	status,	AL = number of sectors read
					; Returns CF = 0
		jnb	short locret_12B	; jumps on successful read (ours)
		dec	di
		jz	short locret_12B
		xor	ah, ah
		mov	dl, [bp+0]
		int	13h		; DISK - RESET DISK SYSTEM
					; DL = drive (if bit 7 is set both hard	disks and floppy disks reset)
		jmp	short loc_CA
; ---------------------------------------------------------------------------

loc_E6:					; CODE XREF: sub_9B+26j sub_9B+2Dj
		mov	dl, [bp+0]
		pusha
		mov	bx, 55AAh
		mov	ah, 41h	; 'A'
		int	13h		; DISK - Check for INT 13h Extensions
					; BX = 55AAh, DL = drive number
					; Return: CF set if not	supported
					; AH = extensions version
					; BX = AA55h
					; CX = Interface support bit map
		jb	short loc_129
		cmp	bx, 0AA55h
		jnz	short loc_129
		test	cl, 1
		jz	short loc_129
		popa

loc_FF:					; CODE XREF: sub_9B+8Cj
		pusha
		push	0
		push	0
		push	word ptr [bp+0Ah]
		push	word ptr [bp+8]
		push	0
		push	7C00h
		push	1
		push	10h
		mov	ah, 42h	; 'B'
		mov	si, sp
		int	13h		; DISK - IBM/MS	Extension - EXTENDED READ (DL -	drive, DS:SI - disk address packet)
		popa
		popa
		jnb	short locret_12B
		dec	di
		jz	short locret_12B
		xor	ah, ah
		mov	dl, [bp+0]
		int	13h		; DISK - RESET DISK SYSTEM
					; DL = drive (if bit 7 is set both hard	disks and floppy disks reset)
		jmp	short loc_FF
; ---------------------------------------------------------------------------

loc_129:				; CODE XREF: sub_9B+56j sub_9B+5Cj ...
		popa
		stc

locret_12B:				; CODE XREF: sub_9B+3Dj sub_9B+40j ...
		retn			; returns to 0000:0655 (loc_55)
sub_9B		endp

; ---------------------------------------------------------------------------
		db  49h	; I
		db  6Eh	; n
		db  76h	; v
		db  61h	; a
		db  6Ch	; l
		db  69h	; i
		db  64h	; d
		db  20h
		db  70h	; p
		db  61h	; a
		db  72h	; r
		db  74h	; t
		db  69h	; i
		db  74h	; t
		db  69h	; i
		db  6Fh	; o
		db  6Eh	; n
		db  20h
		db  74h	; t
		db  61h	; a
		db  62h	; b
		db  6Ch	; l
		db  65h	; e
		db    0
		db  45h	; E
		db  72h	; r
		db  72h	; r
		db  6Fh	; o
		db  72h	; r
		db  20h
		db  6Ch	; l
		db  6Fh	; o
		db  61h	; a
		db  64h	; d
		db  69h	; i
		db  6Eh	; n
		db  67h	; g
		db  20h
		db  6Fh	; o
		db  70h	; p
		db  65h	; e
		db  72h	; r
		db  61h	; a
		db  74h	; t
		db  69h	; i
		db  6Eh	; n
		db  67h	; g
		db  20h
		db  73h	; s
		db  79h	; y
		db  73h	; s
		db  74h	; t
		db  65h	; e
		db  6Dh	; m
		db    0
		db  4Dh	; M
		db  69h	; i
		db  73h	; s
		db  73h	; s
		db  69h	; i
		db  6Eh	; n
		db  67h	; g
		db  20h
		db  6Fh	; o
		db  70h	; p
		db  65h	; e
		db  72h	; r
		db  61h	; a
		db  74h	; t
		db  69h	; i
		db  6Eh	; n
		db  67h	; g
		db  20h
		db  73h	; s
		db  79h	; y
		db  73h	; s
		db  74h	; t
		db  65h	; e
		db  6Dh	; m
		db    0
		db    0
		db    0
		db    0
		db    0
		db    0
		db    0
		db    0
		db    0
		db    0
		db    0
		db    0
		db    0
		db    0
		db    0
		db    0
		db    0
		db    0
		db    0
		db    0
		db    0
		db    0
		db    0
		db    0
		db    0
		db    0
		db    0
		db    0
		db    0
		db    0
		db    0
		db    0
		db    0
		db    0
		db    0
		db    0
		db    0
		db    0
		db    0
		db    0
		db    0
		db    0
		db    0
		db    0
		db    0
		db    0
		db    0
		db    0
		db    0
		db    0
		db    0
		db    0
		db    0
		db    0
		db    0
		db    0
		db    0
		db    0
		db  2Ch	; ,
		db  44h	; D
		db  63h	; c
		db 0AAh	; �
		db  0Ah
		db 0AAh	; �
		db  0Ah
		db    0
		db    0
		db  80h	; �
		db    1
		db    1
		db    0
		db    7
		db 0FEh	; �
		db 0FFh
		db 0FFh
		db  3Fh	; ?
		db    0
		db    0
		db    0
		db 0D9h	; �
		db 0A6h	; �
		db  3Fh	; ?
		db    1
		db    0
		db    0
		db    0
		db    0
		db    0
		db    0
		db    0
		db    0
		db    0
		db    0
		db    0
		db    0
		db    0
		db    0
		db    0
		db    0
		db    0
		db    0
		db    0
		db    0
		db    0
		db    0
		db    0
		db    0
		db    0
		db    0
		db    0
		db    0
		db    0
		db    0
		db    0
		db    0
		db    0
		db    0
		db    0
		db    0
		db    0
		db    0
		db    0
		db    0
		db    0
		db    0
		db    0
		db    0
		db    0
		db    0
		db    0
		db    0
		db  55h	; U
		db 0AAh	; �
seg000		ends


		end
Posted in Code AnalysisTagged bootsector, real mode, sp3, windows, windows xp, x86Leave a comment

Atlassian Bug CyberCom

Posted on September 8, 2021 - September 8, 2021 by admin

Atlassian has raised a storm with CyberCom (US Cyber Command) due to a critical flaw discovered in Confluence Server and Confluence Data Center. “Mass exploitation of Atlassian Confluence CVE-2021-26084 is ongoing and expected to accelerate. Please patch immediately if you haven’t already—this cannot wait until after the weekend,” said the official CyberCom Twitter account.

On August 25, 2021, Atlassian did issue a patch for this vulnerability, in which the developer stated arbitrary code execution could be reached by an unauthenticated user on a Confluence server or datacenter instance.

Jenkins, the popular CI/CD platform, was hit by attackers exploiting this new flaw. Attackers decided to deploy a Monero cryptominer on the company’s Confluence server. The service immediately took the server offline and rotated all passwords.

Researchers at Kaspersky stated the flaw is only possible to leverage from unauthenticated users if the “Allow people to sign up to create their account” option is enabled by administrators.

Please note Confluence Cloud is not affected.

Posted in Current EventsTagged 0day, atlassian, cve-2021-26084, RCE, unauthenticatedLeave a comment

Chainsaw

Posted on September 8, 2021 - September 8, 2021 by admin

A new tool called Chainsaw was released on August 14, 2021. It helps blue teams find potential threats in Windows event logs. It was originally made for environments without an endpoint detection and response (EDR) solution was not available during a compromise.

Windows event logs store system activity such as application activity and logins. Such information is vital to defenders and investigators in incident response scenarios. Manually combing through the raw logs is time consuming due to the potentially large volume of information.

Chainsaw is written in the Rust programming language. It parses the event logs to find suspicious strings or entries of interest indicating a possible threat. The Sigma signature format to allow analysts or outside contributors to describe log events in patterns which may be useful for finding potential malicious activity.

Posted in UtilitiesTagged blue teaming, chainsaw, EDR, incident response, sigma, threat detection, threat huntingLeave a comment

TMobile Hack

Posted on August 23, 2021 - August 23, 2021 by admin

On Saturday, August 21, 2021, TMobile revised their number of customers affected by the recent attack was an addition five million, bringing the total to over 50 million people.

Names, drivers licenses, birth dates, addresses, and social security numbers were among the data stolen in a “highly sophisticated cyberattack”.

The company now faces a class-action lawsuit due to the breach.

This is at least the fourth known hack since 2015 on TMobile. A seller on an underground forum offered six BTC for all the data, which is how the company was made aware of the infiltration.

Does TMobile suffer from a bad organizational structure, the wrong people in security, lack of investment in security, all of the above? Countless other firms will remain wounded sheep so long as the legal and regulatory environment does not incentivize security understanding and investment.

Posted in Current EventsTagged data exfiltration, owned and exposed, TMobileLeave a comment

Cobalt Strike MS Office Macro Shellcode Decoder/Dumper

Posted on July 28, 2021 - July 28, 2021 by admin

One of the more popular Cobalt Strike attacks involves building an Office VBA payload. Unsophisticated attackers will not likely modify the generated payloads from the framework. This gives a defender an easier opportunity to find CS payloads and easily dump/analyze them.

The following tool (Python3) will help an analyst or security system to discover functionality of the embedded payload. Once extracted, you can use an online disassembler like ODA to analyze the x86 shellcode. Keep in mind it has both code and data embedded. Hence we leave possible decoded ASCII in a separate view.

#!/usr/bin/env python3
# (@) - Extracts shellcode from Array() in VBA Macro attack
#       Also prints possible ASCII values embedded in payload
#
import sys
import re

content_file=sys.argv[1]
contents = ''

try:
    with open(content_file, 'r') as f:
        contents = f.read()
except Exception as e:
    print(str(e))
    print('Usage:  python3 ' + sys.argv[0] + ' <generated_vba_file>')
    raise

start_location = contents.find('myArray = Array(')
end_location = contents.index('If Len(Environ("ProgramW6432"')

what_we_want = contents[start_location:end_location - 1]
what_we_want = re.sub(r'^.*?\(', ' ', what_we_want)
what_we_want = what_we_want.replace(' _', '')
what_we_want = what_we_want.replace(")", "")
what_we_want = what_we_want.replace(',', ' ')

disasm_this = ''
text_this = ''
for element in what_we_want.split(' '):
    if not element:
        continue
    new_number = int(element)
    asm_num = format(new_number & 0xff, "02X")
    disasm_this += asm_num + ' '
    if new_number < 0:
        continue
    text_this += bytes.fromhex(asm_num).decode('ascii')
print('x86 payload:')
print(disasm_this)
print('\n\n')
print('Possible ASCII data found:')
print(text_this)
Posted in UtilitiesTagged automation, blue team, CND, cobalt strike, macro, malware analysis, office, vbaLeave a comment

Kaseya Bullseye

Posted on July 12, 2021 - July 12, 2021 by admin

Hackers attributed to the REvil group recently exploited an (internally) known 0day in Kaseya software to demand ransom worth 70,000,000 USD affecting at least 1000 businesses.

On Friday, July 2, 2021, the incident response team from Kaseya became aware of a security incident related to their VSA software. Hackers used the software to deploy the REvil ransomware into many victims’ environment. The malicious code is side-loaded by a fake Windows Defender app, encrypting files in return for ransom. “Kaseya VSA Agent Hot-fix” is the distributed name of the malware, which was also seen attempting to disable Microsoft Defender Real-Time Monitoring via Powershell.

The group sent out a message on July 2:

“On Friday (02.07.2021) we launched an attack on MSP providers. More than a million systems were infected. If anyone wants to negotiate about universal decryptor – our price is 70,000,000$ in BTC and we will publish publicly decryptor that decrypts files of all victims, so everyone will be able to recover from attack in less than an hour."

How did the REvil group know a patch was forthcoming? Did they? It’s improbable this is a coincidence.

Assuming it is not, how were they alerted to a forthcoming patch which likely spurred an immediate decrease in their attack timeline? Insider alerting them? Prior compromise and a great analysis team?

Anything is possible when tens of millions of dollars, or more, are at stake. The most expensive 0days ($1,000,000+) are a drop in the bucket for groups eyes to rake in millions from one successful operation.

Former employees raised several software security concerns from 2017 through 2020 to company leaders. These concerns were not fully addressed, as sales were the focus of the business at the expense of other priorities. One employee sent a 40-page memo detailing many security concerns related to the software leading to his firing two weeks later. Customer passwords were stored in clear text on third-party platforms, among other bad habits.

Shame on Kaseya. Likely one of many professional software firms and IT management companies which fail to adhere to even basic security and administration best practices.

Posted in Campaign Analysis, Current EventsTagged 0day, kaseya, ransomwareLeave a comment

Ransomware, Insurance, Negligence, and Insiders

Posted on June 6, 2021 - June 6, 2021 by admin

Ransomware is taking the world by storm since the lockdowns of 2020. With record unemployment due to forced halting of economies and movement around the globe, without doubt some programmers with notable skill were negatively affected. Surely some have found homes in the rising number of groups engaging in ransoming of data and service.

Recent cases such as the Colonial Pipeline and Norsk Hydro hacks, with payouts of $4.4 million and $71 million respectively, show how lucrative such operations are. IT security operations are usually underfunded and notoriously understaffed, if not in headcount then certainly in talent. Such teams are classically seen as “cost centers” to financial types. Even in good times, corporate boards are unwilling to spend the necessary cash to find or develop talent necessary to handle such threats.

As explained by a close contact high up in the financial industry, “Why would we pay millions for talent when it’s cheaper for us to have an adequate insurance policy? It’s not like business leaders are under any threat to themselves [legally] or their companies from a hack.” Risk is calculated by actuaries. So long as their risk is perceived as covered, IT security remains a distant concern only insomuch as governance mandates.

Cyber liability insurance is starting to price in the risk of ransomware by utilizing “sub-limits”. For example, such stipulations may only pay out $25,000 for ransomware incidents, despite the insurance having potentially multi-million dollar limits for other cyber incidents. Without such initiatives companies may never have incentive to practice security measures which could prevent such incidents.

Governing bodies, such as the state of New York, may move to ban municipalities from paying out ransom demands, opting for initiatives such as a “Cyber Security Enhancement Fund” which limits ransom payouts to instead focus on upgrading security posture. The US Department of Treasury has warned companies that facilitate ransomware payments as a third party may face future economic sanctions for encouraging crime and future ransomware payment demands.

The astute reader may wonder how mature organizations are still being crippled by having mainline systems disrupted by ransomware, as data backup policies and procedures were well-defined and put in place since at least the 1990s. The current predicament proves the point that many (most?) organizations, even cyber-conscious ones, are failing to adequately cover basic system administration and networking practices. With the “cloud” now opening up perimeters worldwide, the effort for corralling systems and assets are more difficult.

History has cooled worries of executives about negligence and responsibility for data breaches and hacks. Equifax, one of the largest credit bureaus in the USA, received a mere slap on the wrist after hundreds of millions of peoples’ records were stolen. SolarWinds executives blamed a lowly intern for mismanagement of their server credentials. With no incentive for improvement for improvements sake and no pain for neglecting to secure infrastructure digitally, expectations of improved security posture for most organizations seem dire.

How many employees are bribed by outside forces to simply “run a program or command” from their work machines? Russian Egor Kriuchkov was found guilty of bribing a Tesla employee for $1,000,000 to place ransomware in the company’s battery plant network in Nevada. With such large ransoms being paid and the relative ease of insider threat attack models, expect threat actors to increasingly lean on this method in the future.

Posted in Current EventsTagged backups, colonial, extortion, pipeline, ransomware, solarwinds, teslaLeave a comment

Posts navigation

Older posts
Newer posts

Recent Posts

  • Manual Scraping
  • Nitter Replacement
  • MFA Abuse in Splunk
  • Virtualbox Automation
  • Repository Poisoning

Recent Comments

    Archives

    • August 2024
    • July 2023
    • August 2022
    • March 2022
    • November 2021
    • October 2021
    • September 2021
    • August 2021
    • July 2021
    • June 2021
    • February 2021
    • December 2020
    • October 2020
    • September 2020
    • April 2020
    • March 2020
    • January 2020
    • July 2019
    • June 2019

    Categories

    • Campaign Analysis
    • Campaign Management
    • Code Analysis
    • Current Events
    • Malware Development
    • Techniques
    • Uncategorized
    • Utilities

    Meta

    • Log in
    • Entries feed
    • Comments feed
    • WordPress.org
    Proudly powered by WordPress | Theme: micro, developed by DevriX.