private void ProcessZipFileContents(byte[] rawBytes) { FriendlyName = "Variable: Zip file contents"; if (rawBytes[0x28] == 0x2f || rawBytes[0x24] == 0x4e && rawBytes[0x26] == 0x2f && rawBytes[0x28] == 0x41 || rawBytes[0x1c] == 0x2f || rawBytes[0x18] == 0x4e && rawBytes[0x1a] == 0x2f && rawBytes[0x1c] == 0x41) { //we have a good date var zip = new ShellBagZipContents(rawBytes); FriendlyName = zip.FriendlyName; LastAccessTime = zip.LastAccessTime; Value = zip.Value; } else { Value = "!!! Unable to determine Value !!!"; } }
private void ProcessPropertyViewDefault(byte[] rawBytes) { FriendlyName = "Variable: Users property view"; var index = 10; var shellPropertySheetListSize = BitConverter.ToInt16(rawBytes, index); index += 2; var identifiersize = BitConverter.ToInt16(rawBytes, index); index += 2; var identifierData = new byte[identifiersize]; Array.Copy(rawBytes, index, identifierData, 0, identifiersize); index += identifiersize; if (shellPropertySheetListSize > 0) { var propBytes = rawBytes.Skip(index).Take(shellPropertySheetListSize).ToArray(); var propStore = new PropertyStore(propBytes); PropertyStore = propStore; var p = propStore.Sheets.Where(t => t.PropertyNames.ContainsKey("32")); if (p.Any()) { //we can now look thru prop bytes for extension blocks //TODO this is a hack until we can process vectors natively var extOffsets = new List <int>(); try { var regexObj = new Regex("([0-9A-F]{2})-00-EF-BE", RegexOptions.IgnoreCase); var matchResult = regexObj.Match(BitConverter.ToString(propBytes)); while (matchResult.Success) { extOffsets.Add(matchResult.Index); matchResult = matchResult.NextMatch(); } foreach (var extOffset in extOffsets) { var binaryOffset = extOffset / 3 - 4; var exSize = BitConverter.ToInt16(propBytes, binaryOffset); var exBytes = propBytes.Skip(binaryOffset).Take(exSize).ToArray(); var signature1 = BitConverter.ToUInt32(exBytes, 4); var block1 = Utils.GetExtensionBlockFromBytes(signature1, exBytes); ExtensionBlocks.Add(block1); } } catch (ArgumentException ex) { throw ex; // Syntax error in the regular expression } } } else { if (rawBytes[0x28] == 0x2f || rawBytes[0x24] == 0x4e && rawBytes[0x26] == 0x2f && rawBytes[0x28] == 0x41) { //we have a good date var zip = new ShellBagZipContents(rawBytes); FriendlyName = zip.FriendlyName; // LastAccessTime = zip.LastAccessTime; Value = zip.Value; return; } } index += shellPropertySheetListSize; index += 2; //move past end of property sheet terminator var rawguid = Utils.ExtractGuidFromShellItem(rawBytes.Skip(index).Take(16).ToArray()); index += 16; rawguid = Utils.ExtractGuidFromShellItem(rawBytes.Skip(index).Take(16).ToArray()); index += 16; var name = Utils.GetFolderNameFromGuid(rawguid); Value = name; var extBlockSize = BitConverter.ToInt16(rawBytes, index); if (extBlockSize > 0) { //process extension blocks while (extBlockSize > 0) { var extBytes = rawBytes.Skip(index).Take(extBlockSize).ToArray(); index += extBlockSize; var signature1 = BitConverter.ToUInt32(extBytes, 4); var block1 = Utils.GetExtensionBlockFromBytes(signature1, extBytes); ExtensionBlocks.Add(block1); extBlockSize = BitConverter.ToInt16(rawBytes, index); } } int terminator = BitConverter.ToInt16(rawBytes, index); if (terminator > 0) { throw new Exception($"Expected terminator of 0, but got {terminator}"); } var valuestring = (from propertySheet in PropertyStore.Sheets from propertyName in propertySheet.PropertyNames where propertyName.Key == "10" select propertyName.Value).FirstOrDefault(); if (valuestring == null) { var namesList = (from propertySheet in PropertyStore.Sheets from propertyName in propertySheet.PropertyNames select propertyName.Value) .ToList(); valuestring = string.Join("::", namesList.ToArray()); } if (valuestring == "") { valuestring = "No Property sheet value found"; } Value = valuestring; }
public LnkFile(byte[] rawBytes, string sourceFile) { RawBytes = rawBytes; SourceFile = Path.GetFullPath(sourceFile); var headerBytes = new byte[76]; Buffer.BlockCopy(rawBytes, 0, headerBytes, 0, 76); Header = new Header(headerBytes); var fi = new FileInfo(sourceFile); SourceCreated = new DateTimeOffset(fi.CreationTimeUtc); SourceModified = new DateTimeOffset(fi.LastWriteTimeUtc); SourceAccessed = new DateTimeOffset(fi.LastAccessTimeUtc); if (SourceCreated.Value.Year == 1601) { SourceCreated = null; } if (SourceModified.Value.Year == 1601) { SourceModified = null; } if (SourceAccessed.Value.Year == 1601) { SourceAccessed = null; } var index = 76; TargetIDs = new List <ShellBag>(); if ((Header.DataFlags & Header.DataFlag.HasTargetIdList) == Header.DataFlag.HasTargetIdList) { //process shell items var shellItemSize = BitConverter.ToInt16(rawBytes, index); index += 2; var shellItemBytes = new byte[shellItemSize]; Buffer.BlockCopy(rawBytes, index, shellItemBytes, 0, shellItemSize); var shellItemsRaw = new List <byte[]>(); var shellItemIndex = 0; while (shellItemIndex < shellItemBytes.Length) { var shellSize = BitConverter.ToUInt16(shellItemBytes, shellItemIndex); if (shellSize == 0) { break; } var itemBytes = new byte[shellSize]; Buffer.BlockCopy(shellItemBytes, shellItemIndex, itemBytes, 0, shellSize); shellItemsRaw.Add(itemBytes); shellItemIndex += shellSize; } //TODO try catch and add placeholder for shellitem when exeption happens? or ? foreach (var shellItem in shellItemsRaw) { if (shellItem.Length >= 0x28) { var sig1 = BitConverter.ToInt64(shellItem, 0x8); var sig2 = BitConverter.ToInt64(shellItem, 0x18); if (sig1 == 0 && sig2 == 0 ) // if ((sig1 == zip1_0 && sig2 == zip2_0) || sig2 == zip2_1 || (sig1 == zip1_1 && sig2 == zip2_0)) { //double check if (shellItem[0x28] == 0x2f || shellItem[0x26] == 0x2f || shellItem[0x1a] == 0x2f || shellItem[0x1c] == 0x2f) // forward slash in date or N / A { //zip? var zz = new ShellBagZipContents(shellItem); TargetIDs.Add(zz); continue; } } } switch (shellItem[2]) { case 0x1f: var f = new ShellBag0X1F(shellItem); TargetIDs.Add(f); break; case 0x23: var two3 = new ShellBag0X23(shellItem); TargetIDs.Add(two3); break; case 0x2f: var ff = new ShellBag0X2F(shellItem); TargetIDs.Add(ff); break; case 0x2e: var ee = new ShellBag0X2E(shellItem); TargetIDs.Add(ee); break; case 0xb1: case 0x31: case 0x35: case 0x36: var d = new ShellBag0X31(shellItem); TargetIDs.Add(d); break; case 0x32: var d2 = new ShellBag0X32(shellItem); TargetIDs.Add(d2); break; case 0x00: var v0 = new ShellBag0X00(shellItem); TargetIDs.Add(v0); break; case 0x01: var one = new ShellBag0X01(shellItem); TargetIDs.Add(one); break; case 0x71: var sevenone = new ShellBag0X71(shellItem); TargetIDs.Add(sevenone); break; case 0x61: var sixone = new ShellBag0X61(shellItem); TargetIDs.Add(sixone); break; case 0xC3: var c3 = new ShellBag0Xc3(shellItem); TargetIDs.Add(c3); break; case 0x74: case 0x77: var sev = new ShellBag0X74(shellItem); TargetIDs.Add(sev); break; case 0xae: case 0xaa: case 0x79: var ae = new ShellBagZipContents(shellItem); TargetIDs.Add(ae); break; case 0x41: case 0x42: case 0x43: case 0x46: case 0x47: var forty = new ShellBag0X40(shellItem); TargetIDs.Add(forty); break; case 0x4C: var fc = new ShellBag0X4C(shellItem); TargetIDs.Add(fc); break; default: throw new Exception( $"Unknown shell item ID: 0x{shellItem[2]:X}. Please send to [email protected] so support can be added."); } } //TODO tie back extra block for SpecialFolderDataBlock and KnownFolderDataBlock?? index += shellItemSize; } if ((Header.DataFlags & Header.DataFlag.HasLinkInfo) == Header.DataFlag.HasLinkInfo) { var locationItemSize = BitConverter.ToInt32(rawBytes, index); var locationBytes = new byte[locationItemSize]; Buffer.BlockCopy(rawBytes, index, locationBytes, 0, locationItemSize); if (locationBytes.Length > 20) { var locationInfoHeaderSize = BitConverter.ToInt32(locationBytes, 4); LocationFlags = (LocationFlag)BitConverter.ToInt32(locationBytes, 8); var volOffset = BitConverter.ToInt32(locationBytes, 12); var vbyteSize = BitConverter.ToInt32(locationBytes, volOffset); var volBytes = new byte[vbyteSize]; Buffer.BlockCopy(locationBytes, volOffset, volBytes, 0, vbyteSize); if (volOffset > 0) { VolumeInfo = new VolumeInfo(volBytes); } var localPathOffset = BitConverter.ToInt32(locationBytes, 16); var networkShareOffset = BitConverter.ToInt32(locationBytes, 20); if ((LocationFlags & LocationFlag.VolumeIdAndLocalBasePath) == LocationFlag.VolumeIdAndLocalBasePath) { LocalPath = Encoding.GetEncoding(1252) .GetString(locationBytes, localPathOffset, locationBytes.Length - localPathOffset) .Split('\0') .First(); } if ((LocationFlags & LocationFlag.CommonNetworkRelativeLinkAndPathSuffix) == LocationFlag.CommonNetworkRelativeLinkAndPathSuffix) { var networkShareSize = BitConverter.ToInt32(locationBytes, networkShareOffset); var networkBytes = new byte[networkShareSize]; Buffer.BlockCopy(locationBytes, networkShareOffset, networkBytes, 0, networkShareSize); NetworkShareInfo = new NetworkShareInfo(networkBytes); } var commonPathOffset = BitConverter.ToInt32(locationBytes, 24); CommonPath = Encoding.GetEncoding(1252) .GetString(locationBytes, commonPathOffset, locationBytes.Length - commonPathOffset) .Split('\0') .First(); if (locationInfoHeaderSize > 28) { var uniLocalOffset = BitConverter.ToInt32(locationBytes, 28); var unicodeLocalPath = Encoding.Unicode .GetString(locationBytes, uniLocalOffset, locationBytes.Length - uniLocalOffset) .Split('\0') .First(); LocalPath = unicodeLocalPath; } if (locationInfoHeaderSize > 32) { var uniCommonOffset = BitConverter.ToInt32(locationBytes, 32); var unicodeCommonPath = Encoding.Unicode .GetString(locationBytes, uniCommonOffset, locationBytes.Length - uniCommonOffset) .Split('\0') .First(); CommonPath = unicodeCommonPath; } } index += locationItemSize; } if ((Header.DataFlags & Header.DataFlag.HasName) == Header.DataFlag.HasName) { var nameLen = BitConverter.ToInt16(rawBytes, index); index += 2; if ((Header.DataFlags & Header.DataFlag.IsUnicode) == Header.DataFlag.IsUnicode) { Name = Encoding.Unicode.GetString(rawBytes, index, nameLen * 2); index += nameLen; } else { Name = Encoding.GetEncoding(1252).GetString(rawBytes, index, nameLen); } index += nameLen; } if ((Header.DataFlags & Header.DataFlag.HasRelativePath) == Header.DataFlag.HasRelativePath) { var relLen = BitConverter.ToInt16(rawBytes, index); index += 2; if ((Header.DataFlags & Header.DataFlag.IsUnicode) == Header.DataFlag.IsUnicode) { RelativePath = Encoding.Unicode.GetString(rawBytes, index, relLen * 2); index += relLen; } else { RelativePath = Encoding.GetEncoding(1252).GetString(rawBytes, index, relLen); } index += relLen; } if ((Header.DataFlags & Header.DataFlag.HasWorkingDir) == Header.DataFlag.HasWorkingDir) { var workLen = BitConverter.ToInt16(rawBytes, index); index += 2; if ((Header.DataFlags & Header.DataFlag.IsUnicode) == Header.DataFlag.IsUnicode) { WorkingDirectory = Encoding.Unicode.GetString(rawBytes, index, workLen * 2); index += workLen; } else { WorkingDirectory = Encoding.GetEncoding(1252).GetString(rawBytes, index, workLen); } index += workLen; } if ((Header.DataFlags & Header.DataFlag.HasArguments) == Header.DataFlag.HasArguments) { var argLen = BitConverter.ToInt16(rawBytes, index); index += 2; if ((Header.DataFlags & Header.DataFlag.IsUnicode) == Header.DataFlag.IsUnicode) { Arguments = Encoding.Unicode.GetString(rawBytes, index, argLen * 2); index += argLen; } else { Arguments = Encoding.GetEncoding(1252).GetString(rawBytes, index, argLen); } index += argLen; } if ((Header.DataFlags & Header.DataFlag.HasIconLocation) == Header.DataFlag.HasIconLocation) { var icoLen = BitConverter.ToInt16(rawBytes, index); index += 2; if ((Header.DataFlags & Header.DataFlag.IsUnicode) == Header.DataFlag.IsUnicode) { IconLocation = Encoding.Unicode.GetString(rawBytes, index, icoLen * 2); index += icoLen; } else { IconLocation = Encoding.GetEncoding(1252).GetString(rawBytes, index, icoLen); } index += icoLen; } var extraByteBlocks = new List <byte[]>(); //extra blocks while (index < rawBytes.Length) { var extraSize = BitConverter.ToInt32(rawBytes, index); if (extraSize == 0) { break; } if (extraSize > rawBytes.Length - index) { extraSize = rawBytes.Length - index; } var extraBytes = new byte[extraSize]; Buffer.BlockCopy(rawBytes, index, extraBytes, 0, extraSize); extraByteBlocks.Add(extraBytes); index += extraSize; } ExtraBlocks = new List <ExtraDataBase>(); foreach (var extraBlock in extraByteBlocks) { try { var sig = (ExtraDataTypes)BitConverter.ToInt32(extraBlock, 4); switch (sig) { case ExtraDataTypes.TrackerDataBlock: var tb = new TrackerDataBaseBlock(extraBlock); ExtraBlocks.Add(tb); break; case ExtraDataTypes.ConsoleDataBlock: var cdb = new ConsoleDataBlock(extraBlock); ExtraBlocks.Add(cdb); break; case ExtraDataTypes.ConsoleFeDataBlock: var cfeb = new ConsoleFeDataBlock(extraBlock); ExtraBlocks.Add(cfeb); break; case ExtraDataTypes.DarwinDataBlock: var db = new DarwinDataBlock(extraBlock); ExtraBlocks.Add(db); break; case ExtraDataTypes.EnvironmentVariableDataBlock: var eb = new EnvironmentVariableDataBlock(extraBlock); ExtraBlocks.Add(eb); break; case ExtraDataTypes.IconEnvironmentDataBlock: var ib = new IconEnvironmentDataBlock(extraBlock); ExtraBlocks.Add(ib); break; case ExtraDataTypes.KnownFolderDataBlock: var kf = new KnownFolderDataBlock(extraBlock); ExtraBlocks.Add(kf); break; case ExtraDataTypes.PropertyStoreDataBlock: var ps = new PropertyStoreDataBlock(extraBlock); ExtraBlocks.Add(ps); break; case ExtraDataTypes.ShimDataBlock: var sd = new KnownFolderDataBlock(extraBlock); ExtraBlocks.Add(sd); break; case ExtraDataTypes.SpecialFolderDataBlock: var sf = new SpecialFolderDataBlock(extraBlock); ExtraBlocks.Add(sf); break; case ExtraDataTypes.VistaAndAboveIdListDataBlock: var vid = new VistaAndAboveIdListDataBlock(extraBlock); ExtraBlocks.Add(vid); break; default: throw new Exception( $"Unknown extra data block signature: 0x{sig:X}. Please send lnk file to [email protected] so support can be added"); } } catch (Exception e) { var dmg = new DamagedDataBlock(extraBlock, e.Message); ExtraBlocks.Add(dmg); } } }
private void ProcessPropertyViewDefault(byte[] rawBytes) { FriendlyName = "Variable: Users property view"; var index = 10; var shellPropertySheetListSize = BitConverter.ToInt16(rawBytes, index); index += 2; var identifiersize = BitConverter.ToInt16(rawBytes, index); index += 2; if (identifiersize > rawBytes.Length) { index = 0xc; var strs = CodePagesEncodingProvider.Instance.GetEncoding(1252).GetString(rawBytes, index, rawBytes.Length - index).Split('\0'); var p2 = string.Join(",", strs.Skip(1).ToList()); Value = $"{strs[0]} ({p2})"; return; } var identifierData = new byte[identifiersize]; Array.Copy(rawBytes, index, identifierData, 0, identifiersize); index += identifiersize; if (shellPropertySheetListSize > 0) { var propBytes = rawBytes.Skip(index).Take(shellPropertySheetListSize).ToArray(); var propStore = new PropertyStore(propBytes); PropertyStore = propStore; var p = propStore.Sheets.Where(t => t.PropertyNames.ContainsKey("32")); if (p.Any()) { //we can now look thry prop bytes for extension blocks //TODO this is a hack until we can process vectors natively var extOffsets = new List <int>(); try { var regexObj = new Regex("([0-9A-F]{2})-00-EF-BE", RegexOptions.IgnoreCase); var matchResult = regexObj.Match(BitConverter.ToString(propBytes)); while (matchResult.Success) { extOffsets.Add(matchResult.Index); matchResult = matchResult.NextMatch(); } foreach (var extOffset in extOffsets) { var binaryOffset = extOffset / 3 - 4; var exSize = BitConverter.ToInt16(propBytes, binaryOffset); var exBytes = propBytes.Skip(binaryOffset).Take(exSize).ToArray(); var signature1 = BitConverter.ToUInt32(exBytes, 4); //Debug.WriteLine(" 0x1f bag sig: " + signature1.ToString("X8")); var block1 = Utils.GetExtensionBlockFromBytes(signature1, exBytes); ExtensionBlocks.Add(block1); } } catch (ArgumentException ex) { throw ex; // Syntax error in the regular expression } // Debug.WriteLine("Found 32 key"); } } else { // Debug.Write("Oh no! No property sheets!"); // SiAuto.Main.LogWarning("Oh no! No property sheets!"); if (rawBytes[0x28] == 0x2f || rawBytes[0x24] == 0x4e && rawBytes[0x26] == 0x2f && rawBytes[0x28] == 0x41) { //we have a good date var zip = new ShellBagZipContents(rawBytes); FriendlyName = zip.FriendlyName; LastAccessTime = zip.LastAccessTime; Value = zip.Value; return; } //41-75-67-4D is AugM if (rawBytes[4] == 0x41 && rawBytes[5] == 0x75 && rawBytes[6] == 0x67 && rawBytes[7] == 0x4D) { var cdb = new ShellBagCDBurn(rawBytes); Value = cdb.Value; FriendlyName = cdb.FriendlyName; CreatedOnTime = cdb.CreatedOnTime; LastModificationTime = cdb.LastModificationTime; LastAccessTime = cdb.LastAccessTime; return; } Debug.Write("Oh no! No property sheets!"); Value = "!!! Unable to determine Value !!!"; } index += shellPropertySheetListSize; index += 2; //move past end of property sheet terminator if (shellPropertySheetListSize > 0 && index < rawBytes.Length) { var extBlockSize = BitConverter.ToInt16(rawBytes, index); if (extBlockSize > 0) { //process extension blocks while (extBlockSize > 0) { var extBytes = rawBytes.Skip(index).Take(extBlockSize).ToArray(); index += extBlockSize; var signature1 = BitConverter.ToUInt32(extBytes, 4); var block1 = Utils.GetExtensionBlockFromBytes(signature1, extBytes); ExtensionBlocks.Add(block1); if (index >= rawBytes.Length) { break; } extBlockSize = BitConverter.ToInt16(rawBytes, index); } } // int terminator = BitConverter.ToInt16(rawBytes, index); // // if (terminator > 0) // { // throw new Exception($"Expected terminator of 0, but got {terminator}"); // } } var valuestring = (from propertySheet in PropertyStore.Sheets from propertyName in propertySheet.PropertyNames where propertyName.Key == "10" select propertyName.Value).FirstOrDefault(); if (valuestring == null) { var namesList = (from propertySheet in PropertyStore.Sheets from propertyName in propertySheet.PropertyNames select propertyName.Value) .ToList(); valuestring = string.Join("::", namesList.ToArray()); } if (valuestring == "") { valuestring = "No Property sheet value found"; } Value = valuestring; }
public ShellBag0X32(byte[] rawBytes) { FriendlyName = "File"; ExtensionBlocks = new List <IExtensionBlock>(); ShortName = string.Empty; var index = 2; if (rawBytes.Length > 0x28 && (rawBytes[0x28] == 0x2f || rawBytes[0x24] == 0x4e && rawBytes[0x26] == 0x2f && rawBytes[0x28] == 0x41)) { //we have a good date if (rawBytes[0x28] == 0x2f || rawBytes[0x26] == 0x2f || rawBytes[0x1a] == 0x2f || rawBytes[0x1c] == 0x2f) // forward slash in date or N / A { //zip? try { var zip = new ShellBagZipContents(rawBytes); FriendlyName = zip.FriendlyName; LastAccessTime = zip.LastAccessTime; Value = zip.Value; if (Value.Contains("Unable to determine value") == false) { return; } } catch (Exception) { } } } index += 1; //skip unknown byte index += 1; var fileSize = BitConverter.ToUInt32(rawBytes, index); FileSize = (int)fileSize; index += 4; // skip file size since always 0 for directory var tempBytes = new byte[4]; Array.Copy(rawBytes, index, tempBytes, 0, 4); var lastmodifiedUtcRaw = tempBytes; LastModificationTime = Utils.ExtractDateTimeOffsetFromBytes(lastmodifiedUtcRaw); index += 4; index += 2; var len = 0; var beefPos = BitConverter.ToString(rawBytes).IndexOf("04-00-EF-BE", StringComparison.InvariantCulture) / 3; if (beefPos == 0) { var hackName = Encoding.GetEncoding(1255).GetString(rawBytes, index, rawBytes.Length - index); var segs = hackName.Split(new[] { '\0' }, StringSplitOptions.RemoveEmptyEntries); ShortName = string.Join("|", segs); Value = ShortName; return; } beefPos = beefPos - 4; //add header back for beef var strLen = beefPos - index; if (rawBytes[2] == 0x36) { len = strLen; } else { while (rawBytes[index + len] != 0x0) { len += 1; } } tempBytes = new byte[len]; Array.Copy(rawBytes, index, tempBytes, 0, len); var shortName = ""; if (rawBytes[2] == 0x36) { shortName = Encoding.Unicode.GetString(tempBytes); } else { shortName = CodePagesEncodingProvider.Instance.GetEncoding(1252).GetString(tempBytes); } ShortName = shortName; Value = shortName; index = beefPos; //we are at extension blocks, so cut them up and process // here is where we need to cut up the rest into extension blocks var chunks = new List <byte[]>(); while (index < rawBytes.Length) { var subshellitemdatasize = BitConverter.ToInt16(rawBytes, index); if (subshellitemdatasize <= 0) { break; } if (subshellitemdatasize == 1) { //some kind of separator index += 2; } else { chunks.Add(rawBytes.Skip(index).Take(subshellitemdatasize).ToArray()); index += subshellitemdatasize; } } foreach (var bytes in chunks) { index = 0; var extsize = BitConverter.ToInt16(bytes, index); var signature = BitConverter.ToUInt32(bytes, 0x04); //TODO does this need to check if its a 0xbeef?? regex? var block = Utils.GetExtensionBlockFromBytes(signature, bytes); ExtensionBlocks.Add(block); var beef0004 = block as Beef0004; if (beef0004 != null) { Value = beef0004.LongName; } index += extsize; } }
public ShellBag0X31(byte[] rawBytes) { FriendlyName = "Directory"; ExtensionBlocks = new List <IExtensionBlock>(); var index = 2; if (rawBytes.Length > 0x29 && (rawBytes[0x27] == 0x00 && rawBytes[0x28] == 0x2f && rawBytes[0x29] == 0x00 || rawBytes[0x24] == 0x4e && rawBytes[0x26] == 0x2f && rawBytes[0x28] == 0x41)) { //we have a good date if (rawBytes[0x28] == 0x2f || rawBytes[0x26] == 0x2f || rawBytes[0x1a] == 0x2f || rawBytes[0x1c] == 0x2f) // forward slash in date or N / A { //zip? try { var zip = new ShellBagZipContents(rawBytes); FriendlyName = zip.FriendlyName; LastAccessTime = zip.LastAccessTime; Value = zip.Value; if (Value.Contains("Unable to determine value") == false) { return; } } catch (Exception) { } } } index += 1; //skip unknown byte index += 1; index += 4; // skip file size since always 0 for directory LastModificationTime = Utils.ExtractDateTimeOffsetFromBytes(rawBytes.Skip(index).Take(4).ToArray()); index += 4; index += 2; var len = 0; var beefPos = BitConverter.ToString(rawBytes).IndexOf("04-00-EF-BE", StringComparison.InvariantCulture) / 3; beefPos = beefPos - 4; //add header back for beef var strLen = beefPos - index; if (rawBytes[2] == 0x35 || rawBytes[2] == 0x36) { len = strLen; } else { while (rawBytes[index + len] != 0x0) { len += 1; } } var tempBytes = new byte[len]; Array.Copy(rawBytes, index, tempBytes, 0, len); index += len; var shortName = ""; if (rawBytes[2] == 0x35 || rawBytes[2] == 0x36) { shortName = Encoding.Unicode.GetString(tempBytes); } else { shortName = CodePagesEncodingProvider.Instance.GetEncoding(1252).GetString(tempBytes); } ShortName = shortName; Value = shortName; if (rawBytes.Length == index) { return; } while (rawBytes[index] == 0x0) { index += 1; if (rawBytes.Length == index) { return; } } // here is where we need to cut up the rest into extension blocks var chunks = new List <byte[]>(); while (index < rawBytes.Length) { var subshellitemdatasize = BitConverter.ToInt16(rawBytes, index); if (subshellitemdatasize <= 0) { break; } if (subshellitemdatasize == 1) { //some kind of separator index += 2; } else { chunks.Add(rawBytes.Skip(index).Take(subshellitemdatasize).ToArray()); index += subshellitemdatasize; } } foreach (var bytes in chunks) { index = 0; var extsize = BitConverter.ToInt16(bytes, index); if (bytes.Length < 8) { return; } var signature = BitConverter.ToUInt32(bytes, 0x04); //TODO does this need to check if its a 0xbeef?? regex? var block = Utils.GetExtensionBlockFromBytes(signature, bytes); if (block.Signature.ToString("X").StartsWith("BEEF00")) { ExtensionBlocks.Add(block); } var beef0004 = block as Beef0004; if (beef0004 != null) { Value = beef0004.LongName; } var beef0005 = block as Beef0005; if (beef0005 != null) { //TODO Resolve this // foreach (var internalBag in beef0005.InternalBags) // { // ExtensionBlocks.Add(new BeefPlaceHolder(null)); // // // } } index += extsize; } }
public ShellBag0X74(byte[] rawBytes) { FriendlyName = "Users Files Folder"; ExtensionBlocks = new List <IExtensionBlock>(); var index = 2; index += 2; // move past type and an unknown var size = BitConverter.ToUInt16(rawBytes, index); index += 2; var sig74 = CodePagesEncodingProvider.Instance.GetEncoding(1252).GetString(rawBytes, index, 4); if (sig74 == "CF\0\0") { if (rawBytes[0x28] == 0x2f || rawBytes[0x24] == 0x4e && rawBytes[0x26] == 0x2f && rawBytes[0x28] == 0x41) { //we have a good date var zip = new ShellBagZipContents(rawBytes); FriendlyName = zip.FriendlyName; LastAccessTime = zip.LastAccessTime; Value = zip.Value; return; } } if (sig74 != "CFSF") { throw new Exception($"Invalid signature! Should be CFSF but was {sig74}"); } index += 4; var subShellSize = BitConverter.ToUInt16(rawBytes, index); index += 2; var subClasstype = rawBytes[index]; index += 1; index += 1; // skip unknown var filesize = BitConverter.ToUInt32(rawBytes, index); index += 4; FileSize = (int)filesize; var tempBytes = new byte[4]; Array.Copy(rawBytes, index, tempBytes, 0, 4); index += 4; LastModificationTime = Utils.ExtractDateTimeOffsetFromBytes(tempBytes); index += 2; //skip file attribute flag var len = 0; while (rawBytes[index + len] != 0x0) { len += 1; } tempBytes = new byte[len]; Array.Copy(rawBytes, index, tempBytes, 0, len); index += len; var primaryName = CodePagesEncodingProvider.Instance.GetEncoding(1252).GetString(tempBytes); while (rawBytes[index] == 0x0) { index += 1; } var delegateGuidRaw = new byte[16]; Array.Copy(rawBytes, index, delegateGuidRaw, 0, 16); var delegateGuid = Utils.ExtractGuidFromShellItem(delegateGuidRaw); if (delegateGuid != "5e591a74-df96-48d3-8d67-1733bcee28ba") { throw new Exception( $"Delegate guid not expected value of 5e591a74-df96-48d3-8d67-1733bcee28ba. Actual value: {delegateGuid}"); } index += 16; var itemIdentifierGuidRaw = new byte[16]; Array.Copy(rawBytes, index, itemIdentifierGuidRaw, 0, 16); var itemIdentifierGuid = Utils.ExtractGuidFromShellItem(itemIdentifierGuidRaw); var itemName = Utils.GetFolderNameFromGuid(itemIdentifierGuid); index += 16; //0xbeef0004 section //we are at extensnon blocks, so cut them up and process // here is where we need to cut up the rest into extension blocks var chunks = new List <byte[]>(); while (index < rawBytes.Length) { var subshellitemdatasize = BitConverter.ToInt16(rawBytes, index); if (subshellitemdatasize <= 0) { break; } if (subshellitemdatasize == 1) { //some kind of separator index += 2; } else { chunks.Add(rawBytes.Skip(index).Take(subshellitemdatasize).ToArray()); index += subshellitemdatasize; } } foreach (var bytes in chunks) { index = 0; var extsize = BitConverter.ToInt16(bytes, index); var signature = BitConverter.ToUInt32(bytes, 0x04); //TODO does this need to check if its a 0xbeef?? regex? var block = Utils.GetExtensionBlockFromBytes(signature, bytes); ExtensionBlocks.Add(block); var beef0004 = block as Beef0004; if (beef0004 != null) { Value = beef0004.LongName; } index += extsize; } }