96 lines
5.6 KiB
TypeScript
96 lines
5.6 KiB
TypeScript
import { deflateRawSync } from 'node:zlib';
|
|
|
|
function crc32(bytes: Uint8Array): number {
|
|
let value = 0xffffffff;
|
|
for (const byte of bytes) {
|
|
value ^= byte;
|
|
for (let bit = 0; bit < 8; bit += 1) value = (value >>> 1) ^ (0xedb88320 & -(value & 1));
|
|
}
|
|
return (value ^ 0xffffffff) >>> 0;
|
|
}
|
|
|
|
|
|
function syntheticRegistryPolicy(): Buffer {
|
|
const header = Buffer.alloc(8);
|
|
header.write('PReg', 0, 'ascii');
|
|
header.writeUInt32LE(1, 4);
|
|
const type = Buffer.alloc(4);
|
|
type.writeUInt32LE(4);
|
|
const size = Buffer.alloc(4);
|
|
size.writeUInt32LE(4);
|
|
const data = Buffer.alloc(4);
|
|
data.writeUInt32LE(1);
|
|
const unicode = (value: string) => Buffer.from(value, 'utf16le');
|
|
return Buffer.concat([
|
|
header,
|
|
unicode('['),
|
|
unicode('Software\\Policies\\Synthetic'), Buffer.alloc(2), unicode(';'),
|
|
unicode('Mode'), Buffer.alloc(2), unicode(';'),
|
|
type, unicode(';'),
|
|
size, unicode(';'),
|
|
data,
|
|
unicode(']')
|
|
]);
|
|
}
|
|
export function syntheticGpoBackupZip(securityTemplate?: string): Uint8Array {
|
|
const entries = [
|
|
{
|
|
path: 'synthetic/Backup.xml',
|
|
content: Buffer.from('<?xml version="1.0"?><BackupInst><ID>{22222222-2222-4222-8222-222222222222}</ID><GPOGuid>{11111111-1111-4111-8111-111111111111}</GPOGuid><GPODomain>synthetic.example</GPODomain><BackupTime>2026-07-20T10:00:00Z</BackupTime></BackupInst>')
|
|
},
|
|
{
|
|
path: 'synthetic/DomainSysvol/GPO/Machine/Registry.pol',
|
|
content: syntheticRegistryPolicy()
|
|
}, {
|
|
path: 'synthetic/DomainSysvol/GPO/Machine/Microsoft/Windows NT/SecEdit/GptTmpl.inf',
|
|
content: Buffer.from(securityTemplate ?? '[Unicode]\r\nUnicode=yes\r\n[System Access]\r\nMinimumPasswordLength=14\r\n[Version]\r\nsignature="$CHICAGO$"')
|
|
},
|
|
{
|
|
path: 'synthetic/DomainSysvol/GPO/Machine/Microsoft/Windows NT/Audit/audit.csv',
|
|
content: Buffer.from('Machine Name,Policy Target,Subcategory,Subcategory GUID,Inclusion Setting,Exclusion Setting,Setting Value\r\n,System,ignored,{0cce9210-69ae-11d9-bed3-505054503030},Success and Failure,,3')
|
|
},
|
|
{
|
|
path: 'synthetic/DomainSysvol/GPO/Machine/Preferences/Registry/Registry.xml',
|
|
content: Buffer.from('<?xml version="1.0"?><RegistrySettings clsid="{A3CCFC41-DFDB-43a5-8D26-0FE8B954DA51}" disabled="0"><Registry clsid="{9CD4B2F4-923D-47f5-A062-E897DD1DAD50}" uid="{33333333-3333-4333-8333-333333333333}"><Properties action="U" default="0" hive="HKEY_LOCAL_MACHINE" key="Software\Synthetic" name="Mode" type="REG_SZ" value="Strict"/></Registry></RegistrySettings>')
|
|
}, {
|
|
path: 'synthetic/DomainSysvol/GPO/Machine/Preferences/Groups/Groups.xml',
|
|
content: Buffer.from('<?xml version="1.0"?><Groups clsid="{3125E937-EB16-4b4c-9934-544FC6D24D26}" disabled="0"><User clsid="{DF5F1855-51E5-4d24-8B1A-D9BDE98BA1D1}" uid="{44444444-4444-4444-8444-444444444444}"><Properties action="U" userName="SyntheticOperator" cpassword="synthetic-cpassword-fixture" acctDisabled="1"/></User></Groups>')
|
|
},
|
|
{
|
|
path: 'synthetic/DomainSysvol/GPO/Machine/Preferences/Services/Services.xml',
|
|
content: Buffer.from('<?xml version="1.0"?><NTServices clsid="{2CFB484A-4E96-4b5d-A0B6-093D2F91E6AE}"><NTService clsid="{AB6F0B67-341F-4e51-92F9-005FBFBA1A43}" uid="{55555555-5555-4555-8555-555555555555}"><Properties serviceAction="RESTART_IF_REQUIRED" startupType="AUTOMATIC" serviceName="SyntheticService" accountName="Synthetic\\Service" cPassword="synthetic-service-cpassword-fixture" thirdFailure="RESTART" restartServiceDelay="900000"/></NTService></NTServices>')
|
|
}, {
|
|
path: 'synthetic/DomainSysvol/GPO/User/Preferences/Drives/Drives.xml',
|
|
content: Buffer.from('<?xml version="1.0"?><Drives clsid="{8FDDCC1A-0C3C-43cd-A6B4-71A6DF20DA8C}"><Drive clsid="{935D1B74-9CB8-4e3c-9914-7DD559B7A417}" uid="{66666666-6666-4666-8666-666666666666}"><Properties action="R" path="\\\\synthetic-server\\share" label="Synthetic Share" persistent="1" userName="SYNTHETIC\\DriveUser" cpassword="synthetic-drive-cpassword-fixture" useLetter="1" letter="S" thisDrive="SHOW" allDrives="NOCHANGE"/></Drive></Drives>')
|
|
},
|
|
{ path: 'synthetic/DomainSysvol/GPO/gpt.ini', content: Buffer.from('[General]') }
|
|
];
|
|
const localParts: Buffer[] = [];
|
|
const centralParts: Buffer[] = [];
|
|
let localOffset = 0;
|
|
for (const entry of entries) {
|
|
const name = Buffer.from(entry.path);
|
|
const compressed = deflateRawSync(entry.content);
|
|
const checksum = crc32(entry.content);
|
|
const local = Buffer.alloc(30 + name.length);
|
|
local.writeUInt32LE(0x04034b50, 0); local.writeUInt16LE(20, 4); local.writeUInt16LE(0x0800, 6); local.writeUInt16LE(8, 8);
|
|
local.writeUInt32LE(checksum, 14); local.writeUInt32LE(compressed.length, 18); local.writeUInt32LE(entry.content.length, 22);
|
|
local.writeUInt16LE(name.length, 26); name.copy(local, 30);
|
|
localParts.push(local, compressed);
|
|
const central = Buffer.alloc(46 + name.length);
|
|
central.writeUInt32LE(0x02014b50, 0); central.writeUInt16LE(20, 4); central.writeUInt16LE(20, 6);
|
|
central.writeUInt16LE(0x0800, 8); central.writeUInt16LE(8, 10); central.writeUInt32LE(checksum, 16);
|
|
central.writeUInt32LE(compressed.length, 20); central.writeUInt32LE(entry.content.length, 24); central.writeUInt16LE(name.length, 28);
|
|
central.writeUInt32LE(localOffset, 42); name.copy(central, 46);
|
|
centralParts.push(central);
|
|
localOffset += local.length + compressed.length;
|
|
}
|
|
const directory = Buffer.concat(centralParts);
|
|
const end = Buffer.alloc(22);
|
|
end.writeUInt32LE(0x06054b50, 0); end.writeUInt16LE(entries.length, 8); end.writeUInt16LE(entries.length, 10);
|
|
end.writeUInt32LE(directory.length, 12); end.writeUInt32LE(localOffset, 16);
|
|
return Buffer.concat([...localParts, directory, end]);
|
|
}
|
|
|
|
|