Skip to content

Instantly share code, notes, and snippets.

@hfiref0x
Created April 29, 2023 01:33
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save hfiref0x/847c42c0d641c806483cb4a681068993 to your computer and use it in GitHub Desktop.
Save hfiref0x/847c42c0d641c806483cb4a681068993 to your computer and use it in GitHub Desktop.
F-Secure Blacklight fsbl.sys
Infamous "antirootkit" from F-Secure. Driver contains few potential CVE's.
With such "functionallity" under the hood it was unable to detect anything more advanced then few PoC's from old rootkit.com
main.c
RtlCopyUnicodeString(&g_DriverRegEntry, RegistryPath);
DriverObject->MajorFunction[2] = fsblIrpCloseHandler;
DriverObject->MajorFunction[0xE] = fsblDriverDispatch;
DriverObject->MajorFunction[0x12] = fsblIrpCleanupHandler;
DriverObject->MajorFunction[0] = fsblIrpCreateHandler;
DriverObject->DriverUnload = fsblDriverUnload;
RtlInitUnicodeString(&DestinationString, L"\\Device\\fsblstandaloneDevice");
if ( WdmlibIoCreateDeviceSecure(
DriverObject,
0x10u,
&DestinationString,
0x22u,
0x100u,
0,
&DefaultSDDLString,
&DeviceClassGuid,
&DeviceObject) < 0 )
goto Exit2;
DeviceExtension = DeviceObject->DeviceExtension;
*DeviceExtension = 0i64;
DeviceExtension[1] = 0i64;
*DeviceExtension = DeviceObject;
DeviceObject->Flags |= 0x10u;
RtlInitUnicodeString(&SymbolicLinkName, L"\\??\\fsblstandaloneDevice");
v6 = IoCreateSymbolicLink(&SymbolicLinkName, &DestinationString);
if ( v6 < 0 )
{
ExitDeleteDevice:
IoDeleteDevice(DeviceObject);
Exit2:
ExFreePoolWithTag(g_DriverRegEntry.Buffer, 'lbsf');
g_DriverRegEntry.Buffer = 0i64;
return 0xE0010001i64;
}
if ( !fsblGetPsPointers() )
{
IoDeleteSymbolicLink(&SymbolicLinkName);
goto ExitDeleteDevice;
}
fsblReferenceFSHS1Device();
dispatch.c
IoControlCode = CurrentStackLocation->Parameters.DeviceIoControl.IoControlCode;
InputBufferLength = CurrentStackLocation->Parameters.DeviceIoControl.InputBufferLength;
OutputBufferLength = CurrentStackLocation->Parameters.DeviceIoControl.OutputBufferLength;
switch ( IoControlCode )
{
case 0x80002014:
SystemBuffer = Irp->AssociatedIrp.MasterIrp;
v18 = fsblValidateInputAndRunCallback(
SystemBuffer,
InputBufferLength,
SystemBuffer,
OutputBufferLength,
&v20,
fsblReadDriverObjectIRPHandlerCode);
ntStatus = v18;
if ( v18 >= 0 )
{
v19 = v20;
Irp->IoStatus.Status = v18;
Irp->IoStatus.Information = v19;
goto LABEL_26;
}
goto LABEL_24;
case 0x80002018:
SystemBuffer = Irp->AssociatedIrp.MasterIrp;
v16 = fsblValidateInputAndRunCallback(
SystemBuffer,
InputBufferLength,
SystemBuffer,
OutputBufferLength,
&v20,
fsblReadDriverObjectIRPHandler);
ntStatus = v16;
if ( v16 >= 0 )
{
v17 = v20;
Irp->IoStatus.Status = v16;
Irp->IoStatus.Information = v17;
goto LABEL_26;
}
goto LABEL_24;
case 0x8000201C:
SystemBuffer = Irp->AssociatedIrp.MasterIrp;
v14 = fsblValidateInputAndRunCallback(
SystemBuffer,
InputBufferLength,
SystemBuffer,
OutputBufferLength,
&v20,
fsblModifyDriverObjectIRPHandler);
ntStatus = v14;
if ( v14 >= 0 )
{
v15 = v20;
Irp->IoStatus.Status = v14;
Irp->IoStatus.Information = v15;
goto LABEL_26;
}
goto LABEL_24;
case 0x80006010:
SystemBuffer = Irp->AssociatedIrp.SystemBuffer;
if ( !SystemBuffer || !fsblCallDriver )
{
LODWORD(v20) = 0;
ntStatus = 0xC000000D;
goto LABEL_24;
}
if ( OutputBufferLength <= 8 )
{
v12 = 0i64;
ntStatus = 0xC0000023;
LODWORD(v20) = 0;
goto LABEL_13;
}
if ( (OutputBufferLength & 7) != 0 )
{
v12 = 0i64;
ntStatus = 0xE0010002;
LODWORD(v20) = 0;
goto LABEL_13;
}
memset(Irp->AssociatedIrp.SystemBuffer, 0, OutputBufferLength);
ntStatus = fsblCallDriver((SystemBuffer + 8), OutputBufferLength - 8, &v20);
if ( ntStatus < 0 )
goto LABEL_22;
*SystemBuffer = 0x12345678;
*(SystemBuffer + 4) = v20;
v13 = 8 - ((v20 + 8) & 7) + v20 + 8;
LODWORD(v20) = v13;
if ( v13 > OutputBufferLength - 8 )
{
v12 = 0i64;
ntStatus = 0xC0000023;
LODWORD(v20) = 0;
goto LABEL_13;
}
if ( fsblEncryptOutputBuffer(g_CurrentProcessId, SystemBuffer, v13) )
{
v12 = 0i64;
ntStatus = 0xE0010004;
LODWORD(v20) = 0;
}
else
{
LABEL_22:
v12 = v20;
}
LABEL_13:
if ( ntStatus >= 0 )
{
Irp->IoStatus.Information = v12;
LABEL_25:
Irp->IoStatus.Status = ntStatus;
goto LABEL_26;
}
LABEL_24:
memset(SystemBuffer, 0, OutputBufferLength);
Irp->IoStatus.Information = 0i64;
goto LABEL_25;
}
if ( IoControlCode != 0x8000E00C )
{
Irp->IoStatus.Status = 0xC0000010;
IofCompleteRequest(Irp, 0);
return 0xC0000010i64;
}
SystemBuffer = Irp->AssociatedIrp.MasterIrp;
v9 = fsblValidateInputAndRunCallback(
SystemBuffer,
InputBufferLength,
SystemBuffer,
OutputBufferLength,
&v20,
fsblOpenProcessForReadVmByProcessId);
ntStatus = v9;
if ( v9 < 0 )
goto LABEL_24;
v11 = v20;
Irp->IoStatus.Status = v9;
Irp->IoStatus.Information = v11;
LABEL_26:
IofCompleteRequest(Irp, 0);
return ntStatus;
}
stringxor.c
__int64 fsblDecodeString(_BYTE *InputBuffer, __int64 InputBufferLength, char *Key)
{
char v3;
v3 = *Key;
if ( !InputBuffer )
return 1001i64;
if ( !InputBufferLength || (InputBufferLength & 1) != 0 )
return 1002i64;
InputBufferLength = InputBufferLength;
do
{
*InputBuffer ^= v3;
v3 += Key[1];
++InputBuffer;
--InputBufferLength;
}
while ( InputBufferLength );
return 0i64;
}
fsblGetPsPointers
if ( fsblDecodeString(SourceString, 0x36i64, v1) )
return 0;
RtlInitUnicodeString(&routineName, SourceString);
PsLookupProcessByProcessId = MmGetSystemRoutineAddress(&routineName);
if ( !PsLookupProcessByProcessId || fsblDecodeString(v3, 0x1Ci64, v1) )
return 0;
RtlInitUnicodeString(&routineName, v3);
PsProcessType = MmGetSystemRoutineAddress(&routineName);
return PsProcessType != 0i64;
fsblOpenProcessForReadVmByProcessId
__int64 fsblOpenProcessForReadVmByProcessId(
unsigned int *ProcessId,
unsigned int InputBufferLength,
void **OutputBuffer,
unsigned int OutputBufferLength,
_DWORD *a5)
{
_DWORD *v5;
char v8;
NTSTATUS ntStatus;
LUID AccessMode;
__int64 result;
void *Handle;
struct _SECURITY_SUBJECT_CONTEXT SubjectContext;
PVOID Object;
v5 = a5;
v8 = UserMode;
if ( !ProcessId || !InputBufferLength || !OutputBuffer || !OutputBufferLength || !a5 )
goto LABEL_20;
if ( !PsProcessType || !PsLookupProcessByProcessId )
{
result = 0xE001000Ai64;
LABEL_21:
*a5 = 0;
return result;
}
if ( InputBufferLength < 4 )
{
LABEL_20:
result = 0xC000000Di64;
goto LABEL_21;
}
ntStatus = PsLookupProcessByProcessId(*ProcessId, &Object);
if ( ntStatus < 0 || !Object )
goto LABEL_17;
memset(&SubjectContext, 0, sizeof(SubjectContext));
AccessMode = SeExports->SeDebugPrivilege;
SeCaptureSubjectContext(&SubjectContext);
LOBYTE(AccessMode.LowPart) = SeSinglePrivilegeCheck(AccessMode, UserMode) == 0;
SeReleaseSubjectContext(&SubjectContext);
ntStatus = ObOpenObjectByPointer(Object, 0, 0i64, 0x410u, *PsProcessType, AccessMode.LowPart, &Handle);// PROCESS_QUERY_INFORMATION | PROCESS_VM_READ
if ( ntStatus >= 0 )
{
*v5 = 8;
if ( OutputBufferLength < 8 )
ntStatus = 0xC0000023;
else
*OutputBuffer = Handle;
v8 = 0;
}
ObfDereferenceObject(Object);
if ( v8 )
LABEL_17:
*v5 = 0;
return ntStatus;
}
create.c
__int64 fsblIrpCreateHandler(DEVICE_OBJECT *a1, IRP *a2)
{
volatile signed __int32 *DeviceExtension;
DeviceExtension = a1->DeviceExtension;
if ( _InterlockedIncrement(DeviceExtension + 2) <= 1 )
{
LODWORD(g_CurrentProcessId) = PsGetCurrentProcessId();
a2->IoStatus.Information = 0i64;
a2->IoStatus.Status = 0;
IofCompleteRequest(a2, 0);
return 0i64;
}
else
{
_InterlockedDecrement(DeviceExtension + 2);
a2->IoStatus.Status = 0xC0000043;
a2->IoStatus.Information = 0i64;
IofCompleteRequest(a2, 0);
return 3221225539i64;
}
}
Input/Output buffers are encrypted (and decrypted via versa)
1. id = GetCurrentProcessId()
2. hash = Sha1(id)
3. *Buffer[0] = 0x12345678
4. Buffer = RC2(Buffer, sizeof(Buffer), hash)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment