public static string HashExecutable(string path) { WindowsBinaryData r = ExecutableParser(path); byte[] selfHash; int checkSumIndex = r.checkSumPos; int tableIndex = r.CertificateTableSizePos - 4; int endIndex = 0; if (r.CertificateTableAddress != 0) { endIndex = r.CertificateTableAddress; } if (endIndex == 0) { // Hash the entire file except the .msh at the end if .msh is present int mshLen = GetMshLengthFromExecutable(path); if (mshLen > 0) { mshLen += 20; } using (SHA384 sha384 = SHA384Managed.Create()) { sha384.Initialize(); using (FileStream stream = File.OpenRead(path)) { hashPortionOfStream(sha384, stream, 0, (int)stream.Length - mshLen); // Start --> end - (mshLen + 20) sha384.TransformFinalBlock(new byte[0], 0, 0); selfHash = sha384.Hash; } } return(BitConverter.ToString(selfHash).Replace("-", string.Empty).ToLower()); } using (SHA384 sha384 = SHA384Managed.Create()) { sha384.Initialize(); using (FileStream stream = File.OpenRead(path)) { hashPortionOfStream(sha384, stream, 0, checkSumIndex); // Start --> checkSumIndex sha384.TransformBlock(new byte[4], 0, 4, null, 0); // 4 zero bytes hashPortionOfStream(sha384, stream, checkSumIndex + 4, tableIndex); // checkSumIndex + 4 --> tableIndex sha384.TransformBlock(new byte[8], 0, 8, null, 0); // 8 zero bytes hashPortionOfStream(sha384, stream, tableIndex + 8, endIndex); // tableIndex + 8 --> endIndex sha384.TransformFinalBlock(new byte[0], 0, 0); selfHash = sha384.Hash; } } return(BitConverter.ToString(selfHash).Replace("-", string.Empty).ToLower()); }
public static WindowsBinaryData ExecutableParser(string path) { WindowsBinaryData r = new WindowsBinaryData(); FileStream fs = File.Open(path, FileMode.Open, FileAccess.Read, FileShare.Read); if (fs.Length < 64) { fs.Close(); return(null); } // File too short fs.Seek(0, SeekOrigin.Begin); // Read DOS header byte[] dosHeader = new byte[64]; fs.Read(dosHeader, 0, 64); if ((dosHeader[0] != 0x4d) || (dosHeader[1] != 0x5a)) { return(null); } // Unrecognized binary format int ntHeaderPosition = BitConverter.ToInt32(dosHeader, 60); // Read NT header fs.Seek(ntHeaderPosition, SeekOrigin.Begin); byte[] ntHeader = new byte[24]; fs.Read(ntHeader, 0, ntHeader.Length); if ((ntHeader[0] != 0x50) || (ntHeader[1] != 0x45) || (ntHeader[2] != 0x00) || (ntHeader[3] != 0x00)) { return(null); } // Not a PE file int binaryType = BitConverter.ToInt16(ntHeader, 4); if (binaryType == 0x014C) { r.BinaryType = WindowsBinaryData.BinaryTypeEnum.x32bit; } // 32 bit else if (binaryType == 0x8664) { r.BinaryType = WindowsBinaryData.BinaryTypeEnum.x64bit; } // 64 bit // Read the optional header r.optionalHeaderSize = BitConverter.ToInt16(ntHeader, 20); r.optionalHeaderSizeAddress = BitConverter.ToInt16(dosHeader, 60) + 24; byte[] optHeader = new byte[r.optionalHeaderSize]; fs.Seek(r.optionalHeaderSizeAddress, SeekOrigin.Begin); fs.Read(optHeader, 0, optHeader.Length); // Set values r.checkSumPos = ntHeaderPosition + 24 + 64; r.sizeOfCode = BitConverter.ToInt32(optHeader, 4); r.sizeOfInitializedData = BitConverter.ToInt32(optHeader, 8); r.sizeOfUnInitializedData = BitConverter.ToInt32(optHeader, 12); int optionalMagic = BitConverter.ToInt16(optHeader, 0); switch (optionalMagic) { case 0x010B: // 32bit { r.rvaCount = BitConverter.ToInt32(optHeader, 92); r.CertificateTableAddress = BitConverter.ToInt32(optHeader, 128); r.CertificateTableSize = BitConverter.ToInt32(optHeader, 132); r.CertificateTableSizePos = r.optionalHeaderSizeAddress + 132; r.rvaStartAddress = r.optionalHeaderSizeAddress + 96; /* * if (ILibMemory_AllocateA_Size(optHeader) >= 132) * { * if (((unsigned int*)(optHeader + 128))[0] != 0) * { * endIndex = ((unsigned int*)(optHeader + 128))[0]; * } * tableIndex = NTHeaderIndex + 24 + 128; * retVal = 0; * } */ break; } case 0x020B: // 64bit { r.rvaCount = BitConverter.ToInt32(optHeader, 108); r.CertificateTableAddress = BitConverter.ToInt32(optHeader, 144); r.CertificateTableSize = BitConverter.ToInt32(optHeader, 148); r.CertificateTableSizePos = r.optionalHeaderSizeAddress + 148; r.rvaStartAddress = r.optionalHeaderSizeAddress + 112; break; } default: // Unknown Value found for Optional Magic { return(null); } } if (r.CertificateTableAddress > 0) { // Read the authenticode certificate, only one cert (only the first entry) byte[] hdr = new byte[8]; fs.Seek(r.CertificateTableAddress, SeekOrigin.Begin); fs.Read(hdr, 0, hdr.Length); int certLen = BitConverter.ToInt32(hdr, 0); r.certificate = new byte[certLen]; fs.Seek(r.CertificateTableAddress + hdr.Length, SeekOrigin.Begin); fs.Read(r.certificate, 0, r.certificate.Length); } return(r); }