Skip to content

Instantly share code, notes, and snippets.

@Wack0 Wack0/SbpParse.cs
Created Jan 13, 2017

Embed
What would you like to do?
Secure Boot Policy parser
using System;
using System.IO;
using LipingShare.LCLib.Asn1Processor;
using System.Runtime.InteropServices;
using System.Collections.Generic;
using System.Text;
using System.Security.Cryptography;
namespace SbpParse {
struct SignerValue {
public ushort Val1;
public uint Val2;
public SignerValue(byte[] BinaryData) {
Val1 = BitConverter.ToUInt16(BinaryData,6);
Val2 = BitConverter.ToUInt32(BinaryData,8);
}
}
class PolicyValue {
private int Type;
public object data;
public PolicyValue(byte[] BinaryData) {
Type = BinaryData[0] & 0x1f;
byte[] RawData;
switch (Type) {
case 0: // string
RawData = new byte[BitConverter.ToUInt16(BinaryData,2)];
Buffer.BlockCopy(BinaryData,4,RawData,0,RawData.Length);
data = Encoding.Unicode.GetString(RawData);
break;
case 1: // bool
ushort bval = BitConverter.ToUInt16(BinaryData,2);
bool val = (bval != 0);
data = val;
break;
case 2: // dword
data = BitConverter.ToUInt32(BinaryData,2);
break;
case 4: // SignerValue
data = new SignerValue(BinaryData);
break;
case 5: // qword
case 6:
case 7:
data = BitConverter.ToUInt64(BinaryData,2);
break;
case 8: // device
data = BitConverter.ToUInt16(BinaryData,2);
break;
case 10: // binary
RawData = new byte[BitConverter.ToUInt16(BinaryData,2)];
Buffer.BlockCopy(BinaryData,4,RawData,0,RawData.Length);
data = RawData;
break;
default:
throw new Exception("Unknown type "+Type);
}
}
public override string ToString() {
switch (Type) {
case 0:
return "string - "+(string)data;
case 1:
return "bool - "+( (bool)data ).ToString();
case 2:
return "dword - 0x"+( (uint)data ).ToString("X");
case 4:
var sv = (SignerValue)data;
return "signervalue - 0x"+sv.Val1.ToString("X")+" 0x"+sv.Val2.ToString("X");
case 5:
case 6:
case 7:
return "qword - 0x"+( (ulong)data ).ToString("X");
case 8:
return "device - 0x"+( (ushort)data).ToString("X");
case 10:
return "byte[] - "+BitConverter.ToString( (byte[])data ).Replace("-","");
default:
throw new Exception("Unknown type "+Type);
}
}
}
class SecureBootPolicy {
[StructLayout(LayoutKind.Sequential, Pack = 1)]
struct SBPHeader {
public ushort FormatVersion;
public uint PolicyVersion;
public Guid PolicyPublisher;
public ushort CanUpdateCount;
}
[StructLayout(LayoutKind.Sequential, Pack = 1)]
struct SBPFlags {
public uint OptionFlags;
public ushort BcdRulesCount;
public ushort RegistryRulesCount;
}
[StructLayout(LayoutKind.Sequential, Pack = 1)]
struct BcdRuleStruct {
public uint ObjectType;
public uint Element;
public uint ValueOffset;
}
class BcdRule {
uint ObjectType;
uint Element;
PolicyValue Value;
public BcdRule(BcdRuleStruct s,byte[] ValueTable) {
ObjectType = s.ObjectType;
Element = s.Element;
byte[] RawData = new byte[ValueTable.Length - s.ValueOffset];
Buffer.BlockCopy(ValueTable,(int)s.ValueOffset,RawData,0,RawData.Length);
Value = new PolicyValue(RawData);
}
public override string ToString() {
var sb = new StringBuilder();
sb.AppendLine(" ObjectType: 0x"+ObjectType.ToString("X"));
sb.AppendLine(" Element: 0x"+Element.ToString("X"));
sb.AppendLine(" Value: "+Value.ToString());
return sb.ToString();
}
}
[StructLayout(LayoutKind.Sequential, Pack = 1)]
struct RegistryRuleStruct {
public uint RootKey;
public uint SubkeyNameOffset;
public uint ValueNameOffset;
public uint ValueOffset;
}
class RegistryRule {
uint RootKey;
string SubkeyName;
string ValueName;
PolicyValue Value;
public RegistryRule(RegistryRuleStruct s,byte[] ValueTable) {
RootKey = s.RootKey;
byte[] RawData = new byte[BitConverter.ToUInt16(ValueTable,(int)s.SubkeyNameOffset)];
Buffer.BlockCopy(ValueTable,(int)s.SubkeyNameOffset + 2,RawData,0,RawData.Length);
SubkeyName = Encoding.Unicode.GetString(RawData);
RawData = new byte[BitConverter.ToUInt16(ValueTable,(int)s.ValueNameOffset)];
Buffer.BlockCopy(ValueTable,(int)s.ValueNameOffset + 2,RawData,0,RawData.Length);
ValueName = Encoding.Unicode.GetString(RawData);
RawData = new byte[ValueTable.Length - s.ValueOffset];
Buffer.BlockCopy(ValueTable,(int)s.ValueOffset,RawData,0,RawData.Length);
Value = new PolicyValue(RawData);
}
public override string ToString() {
var sb = new StringBuilder();
sb.AppendLine(" Path: 0x"+RootKey.ToString("X")+" "+SubkeyName+"\\"+ValueName);
sb.AppendLine(" Value: "+Value.ToString());
return sb.ToString();
}
}
private SBPHeader Header;
ushort FormatVersion { get { return Header.FormatVersion; } set { Header.FormatVersion = value; } }
uint PolicyVersion { get { return Header.PolicyVersion; } set { Header.PolicyVersion = value; } }
Guid PolicyPublisher { get { return Header.PolicyPublisher; } set { Header.PolicyPublisher = value; } }
List<Guid> CanUpdate;
private SBPFlags Flags;
uint OptionFlags { get { return Flags.OptionFlags; } set { Flags.OptionFlags = value; } }
List<BcdRule> BcdRules;
List<RegistryRule> RegistryRules;
byte[] Sha256Hash;
public SecureBootPolicy(string filename) {
byte[] RawPolicy;
try {
var Policy = new Asn1Parser();
Policy.LoadData(filename);
RawPolicy = Policy.GetNodeByPath("/1/0/2/1/0").Data;
} catch (Exception) {
RawPolicy = File.ReadAllBytes(filename);
}
Sha256Hash = new SHA256Managed().ComputeHash(RawPolicy);
int offset = 0;
Header = ByteArrayToStructure<SBPHeader>(RawPolicy,ref offset);
CanUpdate = new List<Guid>();
for (int i = 0; i < Header.CanUpdateCount; i++)
CanUpdate.Add(ByteArrayToStructure<Guid>(RawPolicy,ref offset));
Flags = ByteArrayToStructure<SBPFlags>(RawPolicy,ref offset);
var BcdRulesRaw = new List<BcdRuleStruct>();
for (int i = 0; i < Flags.BcdRulesCount; i++) {
BcdRulesRaw.Add(ByteArrayToStructure<BcdRuleStruct>(RawPolicy,ref offset));
}
var RegistryRulesRaw = new List<RegistryRuleStruct>();
for (int i = 0; i < Flags.RegistryRulesCount; i++)
RegistryRulesRaw.Add(ByteArrayToStructure<RegistryRuleStruct>(RawPolicy,ref offset));
byte[] ValueTable = new byte[(RawPolicy.Length - offset)];
Buffer.BlockCopy(RawPolicy,offset,ValueTable,0,ValueTable.Length);
BcdRules = new List<BcdRule>();
foreach (BcdRuleStruct BcdRaw in BcdRulesRaw)
BcdRules.Add(new BcdRule(BcdRaw,ValueTable));
RegistryRules = new List<RegistryRule>();
foreach (RegistryRuleStruct RegRaw in RegistryRulesRaw)
RegistryRules.Add(new RegistryRule(RegRaw,ValueTable));
}
public override string ToString() {
var sb = new StringBuilder();
sb.AppendLine("SHA256 hash: "+BitConverter.ToString(Sha256Hash).Replace("-",""));
sb.AppendLine("Format version: "+FormatVersion);
sb.AppendLine("Policy version: "+PolicyVersion);
sb.AppendLine("Policy publisher: "+PolicyPublisher.ToString());
sb.AppendLine("Option flags: 0x"+OptionFlags.ToString("X"));
sb.AppendLine("CanUpdate GUIDs: "+CanUpdate.Count);
foreach (Guid cu in CanUpdate)
sb.AppendLine(" "+cu.ToString());
sb.AppendLine("BCD rules: "+BcdRules.Count);
foreach (var Bcd in BcdRules)
sb.AppendLine(" "+Bcd.ToString());
sb.AppendLine("Registry rules: "+RegistryRules.Count);
foreach (var Reg in RegistryRules)
sb.AppendLine(" "+Reg.ToString());
return sb.ToString();
}
private T ByteArrayToStructure<T>(byte[] bytes,ref int position) where T: struct {
int length = Marshal.SizeOf(typeof(T));
IntPtr ptr = Marshal.AllocHGlobal(length);
Marshal.Copy(bytes, 0, ptr, length);
T stuff = (T)Marshal.PtrToStructure(Marshal.UnsafeAddrOfPinnedArrayElement(bytes, position), typeof(T));
position += length;
Marshal.FreeHGlobal(ptr);
return stuff;
}
}
class Cli {
public static void Main(string[] args) {
foreach (string arg in args) {
Console.WriteLine(new SecureBootPolicy(arg).ToString());
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.