diff --git a/README.md b/README.md new file mode 100644 index 0000000..175fc7b --- /dev/null +++ b/README.md @@ -0,0 +1,63 @@ +# SecurityAccessQuery + +Interact with Vector security DLLs that are used to generate Security Access Keys in a ECU challenge/response ("seed key"). + +![Header image](https://raw.github.com/jglim/SecurityAccessQuery/main/docs/resources/SAQ_Header.png) + +## Usage + +SAQ requires .NET 4.6 or newer. You will also need to bring your own security DLLs. + +### Set up + +- Download SAQ from the [Releases page](https://github.com/jglim/SecurityAccessQuery/releases). +- Unzip the archive, including the empty Library folder. +- Add your DLLs into the Library folder. **No DLLs are provided by default.** +- Run SAQ. + +### Generate Seed Key + +- Under `File`, click `Select DLL (Filtered)` +- Select the DLL file that matches your ECU (double-click) +- In the text field, insert your seed value from Monaco or Vediamo +- The key will be automatically generated (shown beside `Access Key`) +- Select the cell and copy from it (`CTRL + C`) +- The key can now be pasted back into Monaco or Vediamo + +## Testing + +A set of tests are available here. As I do not own a C4, I used seed requests and generated keys that are shown in public screenshots and videos to verify that the generated values are correct. + +## Issues + +Please note: SAQ does not perform the actual key generation. It is only an interface to a target DLL. + +### Obtaining DLL files + +The DLL files are typically packaged with vendor tools like DTS Monaco, and several automotive forums typically share these files. As they are proprietary blobs, they **cannot** be included directly in this repository for legal reasons. Please **do not** share or request for them here. + +### Incorrect keys + +The keys are generated by the DLL. If the key is not accepted, it may indicate that the wrong or mismatched DLL was used. The challenges (seed) are also refreshed on reset or disconnection so they cannot be reused. + +--- + +# Technical notes + +Some modern ECU systems offer a layer of security that prevents normal users from making changes without completing a seed-key challenge. An authorized client will typically have a DLL or JAR file that takes in a seed challenge, and generates a key. Vector has a well-written application note (AN-IDG-1-017) available [here](https://assets.vector.com/cms/content/know-how/_application-notes/AN-IDG-1-017_SecurityAccess.pdf), that describes this verification process. + +At its essence, SAQ is simply a wrapper to call a target security DLL's key generation function — namely `GenerateKeyEx` or `GenerateKeyExOpt`. + +In my limited understanding, the DLLs are usually packaged in a container format, and only extracted by the vendor tools when they are required. For example, in the `MED40.smr-d` ODB file, the security DLLs are present as `med40_abgleich_00_00_01.dll` , `med40_flash_12_39_00.dll` and `med40_sec_00_00_01.dll`. + +![DB diff screenshot](https://raw.github.com/jglim/SecurityAccessQuery/main/docs/resources/diff.png) + +Recent ECUs seem to prefer JARs instead of DLLs, which should offer much better cross-platform support and disassembly quality. + +--- + +## License + +MIT + +Icon from [http://www.famfamfam.com/lab/icons/silk/](http://www.famfamfam.com/lab/icons/silk/) \ No newline at end of file diff --git a/SecurityAccessQuery/SecurityAccessQuery.sln b/SecurityAccessQuery/SecurityAccessQuery.sln new file mode 100644 index 0000000..c0f655a --- /dev/null +++ b/SecurityAccessQuery/SecurityAccessQuery.sln @@ -0,0 +1,25 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.30309.148 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SecurityAccessQuery", "SecurityAccessQuery\SecurityAccessQuery.csproj", "{67781F09-398D-4EA7-9087-938C7FBD9D98}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {67781F09-398D-4EA7-9087-938C7FBD9D98}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {67781F09-398D-4EA7-9087-938C7FBD9D98}.Debug|Any CPU.Build.0 = Debug|Any CPU + {67781F09-398D-4EA7-9087-938C7FBD9D98}.Release|Any CPU.ActiveCfg = Release|Any CPU + {67781F09-398D-4EA7-9087-938C7FBD9D98}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {25950996-1E60-42CA-8DFC-943E60EEE528} + EndGlobalSection +EndGlobal diff --git a/SecurityAccessQuery/SecurityAccessQuery/App.config b/SecurityAccessQuery/SecurityAccessQuery/App.config new file mode 100644 index 0000000..8324aa6 --- /dev/null +++ b/SecurityAccessQuery/SecurityAccessQuery/App.config @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/SecurityAccessQuery/SecurityAccessQuery/BitUtility.cs b/SecurityAccessQuery/SecurityAccessQuery/BitUtility.cs new file mode 100644 index 0000000..54aa01d --- /dev/null +++ b/SecurityAccessQuery/SecurityAccessQuery/BitUtility.cs @@ -0,0 +1,82 @@ +using System; + +namespace SecurityAccessQuery +{ + /// + /// Utilities for bit and byte operations. + /// (Frequently copied-and-pasted across my projects) + /// + class BitUtility + { + /// + /// Sets all values in an array of bytes to a specific value + /// + /// Value to set byte array to + /// Target byte array buffer + public static void Memset(byte value, byte[] buf) + { + for (int i = 0; i < buf.Length; i++) + { + buf[i] = value; + } + } + // Internally used by BytesFromHex + private static byte[] StringToByteArrayFastest(string hex) + { + // see https://stackoverflow.com/questions/321370/how-can-i-convert-a-hex-string-to-a-byte-array + if (hex.Length % 2 == 1) + { + throw new Exception("The binary key cannot have an odd number of digits"); + } + byte[] arr = new byte[hex.Length >> 1]; + for (int i = 0; i < hex.Length >> 1; ++i) + { + arr[i] = (byte)((GetHexValue(hex[i << 1]) << 4) + (GetHexValue(hex[(i << 1) + 1]))); + } + return arr; + } + // Internally used by StringToByteArrayFastest + private static int GetHexValue(char hex) + { + int val = (int)hex; + return val - (val < 58 ? 48 : 55); + } + /// + /// Converts an array of bytes into its hex-string equivalent + /// + /// Input byte array + /// Option to add spaces between individual bytes + /// Hex-string based on the input byte array + public static string BytesToHex(byte[] inBytes, bool spacedOut = false) + { + return BitConverter.ToString(inBytes).Replace("-", spacedOut ? " " : ""); + } + + /// + /// Converts an array of bytes into a printable hex-string + /// + /// Input hex-string to convert into a byte array + /// Byte array based on the input hex-string + public static byte[] BytesFromHex(string hexString) + { + return StringToByteArrayFastest(hexString.Replace(" ", "")); + } + + /// + /// Resize a smaller array of bytes to a larger array. The padding bytes will be 0. + /// + /// Input byte array + /// New size for the input array + /// Resized byte array + public static byte[] PadBytes(byte[] inData, int finalSize) + { + if (inData.Length > finalSize) + { + return inData; + } + byte[] result = new byte[finalSize]; + Buffer.BlockCopy(inData, 0, result, 0, inData.Length); + return result; + } + } +} diff --git a/SecurityAccessQuery/SecurityAccessQuery/DllContext.cs b/SecurityAccessQuery/SecurityAccessQuery/DllContext.cs new file mode 100644 index 0000000..be5456e --- /dev/null +++ b/SecurityAccessQuery/SecurityAccessQuery/DllContext.cs @@ -0,0 +1,226 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.IO; +using System.Security.Cryptography; +using System.Diagnostics; +using System.Runtime.InteropServices; + +namespace SecurityAccessQuery +{ + /// + /// High level interface to access a Vector DLL + /// + public class DllContext + { + private IntPtr dllHandle = IntPtr.Zero; + public List DllExports = new List(); + private Dictionary dllAddressMappings = new Dictionary(); + + public string SHA1Hash = ""; + public string FileDescription = ""; + public string FileName = ""; + public string DLLPath = ""; + public string ECUName = ""; + public string Comment = ""; + public bool KeyGenerationCapability = false; + public bool ModeSpecified = false; + public List> AccessLevels = new List>(); + + public DllContext(string filePath, bool runHash = true) + { + DLLPath = filePath; + if (!File.Exists(DLLPath)) + { + Console.WriteLine($"{DLLPath}: File does not exist"); + return; + } + FileName = Path.GetFileName(filePath); + + // Compute and store the file hash + if (runHash) + { + using (var cryptoProvider = new SHA1CryptoServiceProvider()) + { + SHA1Hash = BitConverter.ToString(cryptoProvider.ComputeHash(File.ReadAllBytes(filePath))).Replace("-", ""); + } + } + + // Get the module's exports + DllExports = UnmanagedUtility.GetExports(DLLPath); + + if (DllExports.Count == 0) + { + Console.WriteLine($"{DLLPath}: No exports, possibly an invalid DLL"); + return; + } + + // Try to load the library into our process space + dllHandle = UnmanagedUtility.LoadLibrary(filePath); + if (dllHandle == IntPtr.Zero) + { + Console.WriteLine($"{DLLPath}: LoadLibrary failed"); + return; + } + + // Try to load addresses of all known exports + dllAddressMappings = new Dictionary(); + foreach (string knownExport in ExportDefinition.KnownExportedFunctions) + { + if (DllExports.Contains(knownExport)) + { + dllAddressMappings.Add(knownExport, UnmanagedUtility.GetProcAddress(dllHandle, knownExport)); + } + else + { + dllAddressMappings.Add(knownExport, IntPtr.Zero); + } + } + + // Set capabilities + KeyGenerationCapability = DllExports.Contains("GenerateKeyEx") || DllExports.Contains("GenerateKeyExOpt"); + ModeSpecified = DllExports.Contains("GetKeyLength") && DllExports.Contains("GetSeedLength") && DllExports.Contains("GetConfiguredAccessTypes"); + + // Store additional metadata + FileDescription = FileVersionInfo.GetVersionInfo(DLLPath).FileDescription; + + LoadAdditionalDataFromDllCalls(); + } + + public void LoadAdditionalDataFromDllCalls() + { + ECUName = GetECUName(); + Comment = GetComment(); + + if (!ModeSpecified) + { + return; + } + + // Access level, key size, seed size + AccessLevels = new List>(); + foreach (uint accessLevel in GetConfiguredAccessTypes()) + { + AccessLevels.Add(new Tuple(accessLevel, GetKeyLength(accessLevel), GetSeedLength(accessLevel))); + } + } + + // Automatically selects and invokes the correct key generation function. Prefers the "opt" variant + public string GenerateKeyAuto(uint securityLevel, byte[] seed) + { + if (DllExports.Contains("GenerateKeyExOpt")) + { + return BitUtility.BytesToHex(GenerateKey(seed, securityLevel, true, out ExportDefinition.VKeyGenResultEx result), true); + } + else if (DllExports.Contains("GenerateKeyEx")) + { + return BitUtility.BytesToHex(GenerateKey(seed, securityLevel, false, out ExportDefinition.VKeyGenResultEx result), true); + } + else + { + return ""; + } + } + + public string GetECUName() + { + IntPtr procAddress = dllAddressMappings["GetECUName"]; + if (procAddress == IntPtr.Zero) + { + return "(unavailable)"; + } + var fn = (ExportDefinition.GetECUName)Marshal.GetDelegateForFunctionPointer(procAddress, typeof(ExportDefinition.GetECUName)); + IntPtr resultPtr = fn(); + return Marshal.PtrToStringAnsi(resultPtr); + } + public string GetComment() + { + IntPtr procAddress = dllAddressMappings["GetComment"]; + if (procAddress == IntPtr.Zero) + { + return "(unavailable)"; + } + var fn = (ExportDefinition.GetComment)Marshal.GetDelegateForFunctionPointer(procAddress, typeof(ExportDefinition.GetComment)); + IntPtr resultPtr = fn(); + return Marshal.PtrToStringAnsi(resultPtr); + } + public List GetConfiguredAccessTypes() + { + IntPtr procAddress = dllAddressMappings["GetConfiguredAccessTypes"]; + if (procAddress == IntPtr.Zero) + { + return new List(); + } + uint[] accessTypes = new uint[1000]; + var fn = (ExportDefinition.GetConfiguredAccessTypes)Marshal.GetDelegateForFunctionPointer(procAddress, typeof(ExportDefinition.GetConfiguredAccessTypes)); + int accessTypesCount = fn(accessTypes); + return accessTypes.Take(accessTypesCount).ToList(); + } + public int GetSeedLength(uint securityLevel) + { + IntPtr procAddress = dllAddressMappings["GetSeedLength"]; + if (procAddress == IntPtr.Zero) + { + return 0; + } + var fn = (ExportDefinition.GetSeedLength)Marshal.GetDelegateForFunctionPointer(procAddress, typeof(ExportDefinition.GetSeedLength)); + return fn(securityLevel); + } + public int GetKeyLength(uint securityLevel) + { + IntPtr procAddress = dllAddressMappings["GetKeyLength"]; + if (procAddress == IntPtr.Zero) + { + return 0; + } + var fn = (ExportDefinition.GetKeyLength)Marshal.GetDelegateForFunctionPointer(procAddress, typeof(ExportDefinition.GetKeyLength)); + return fn(securityLevel); + } + + private byte[] GenerateKey(byte[] seed, uint securityLevel, bool addOptionParameter, out ExportDefinition.VKeyGenResultEx returnError) + { + returnError = ExportDefinition.VKeyGenResultEx.UnknownError; + + IntPtr procAddress = dllAddressMappings[addOptionParameter ? "GenerateKeyExOpt" : "GenerateKeyEx"]; + if ((!KeyGenerationCapability) || procAddress == IntPtr.Zero) + { + return new byte[] { }; + } + byte[] keyResult = new byte[0x1000]; + uint actualkeySize; + int keygenResult = (int)returnError; + + if (addOptionParameter) + { + var fn = (ExportDefinition.GenerateKeyExOpt)Marshal.GetDelegateForFunctionPointer(procAddress, typeof(ExportDefinition.GenerateKeyExOpt)); + keygenResult = fn(seed, (uint)seed.Length, securityLevel, null, null, keyResult, (uint)keyResult.Length, out actualkeySize); + } + else + { + var fn = (ExportDefinition.GenerateKeyEx)Marshal.GetDelegateForFunctionPointer(procAddress, typeof(ExportDefinition.GenerateKeyEx)); + keygenResult = fn(seed, (uint)seed.Length, securityLevel, null, keyResult, (uint)keyResult.Length, out actualkeySize); + } + returnError = (ExportDefinition.VKeyGenResultEx)keygenResult; + + keyResult = keyResult.Take((int)actualkeySize).ToArray(); + return keyResult; + } + + public void UnloadLibrary() + { + // WARNING: the instance will no longer be able to access native functions after this is called + // This is a workaround if many DLLs have to be enumerated for their metadata -- Windows has a limit on the number of DLLs that can be loaded simultaneously + UnmanagedUtility.FreeLibrary(dllHandle); + } + + ~DllContext() + { + if (dllHandle != IntPtr.Zero) + { + UnmanagedUtility.FreeLibrary(dllHandle); + } + } + } +} diff --git a/SecurityAccessQuery/SecurityAccessQuery/ExportDefinition.cs b/SecurityAccessQuery/SecurityAccessQuery/ExportDefinition.cs new file mode 100644 index 0000000..32f707d --- /dev/null +++ b/SecurityAccessQuery/SecurityAccessQuery/ExportDefinition.cs @@ -0,0 +1,160 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Runtime.InteropServices; +using System.Text; +using System.Threading.Tasks; + +namespace SecurityAccessQuery +{ + class ExportDefinition + { + /* + Diagnostics function to enumerate all DLLs and get unique exported functions so that the signatures can be built + + This is what I have so far: + + GenerateKeyExOpt + GetECUName + GetConfiguredAccessTypes + GetSeedLength + GetKeyLength + GenerateKeyEx + + GetComment + + VectorCompressInit + VectorCompress + VectorCompressExit + */ + + public static void DumpUniqueExportsToConsole(string breakOnSpecificFunction = "") + { + HashSet uniqueExports = new HashSet(); + foreach (string filePath in Program.GetLibraryFiles()) + { + List exportsForFile = UnmanagedUtility.GetExports(filePath); + foreach (string exportName in exportsForFile) + { + if (exportName == breakOnSpecificFunction) + { + Console.WriteLine($"BREAK: {breakOnSpecificFunction} for {Path.GetFileName(filePath)}"); + Console.ReadLine(); + } + uniqueExports.Add(exportName); + } + Console.WriteLine(filePath); + } + foreach (string uniqueExportName in uniqueExports) + { + Console.WriteLine(uniqueExportName); + } + } + + /* + Compression - no public definitions : nothing found on https://kb.vector.com/ + + VectorCompressInit + VectorCompress + VectorCompressExit + + // Compression libraries: + CPC_NG_CompressAlgo1.dll + CRR1_CompressAlgo1.dll + DCB167_Compress.dll + DCDC48_222_CompressAlgo1.dll + DRVU_NG_CompressAlgo1.dll + ESP213_CompressAlgo1.dll + FCW177_Compress.dll + FCW205_Compress.dll + IC213_CompressAlgo1.dll + IC222_CompressAlgo1.dll + IC447KIG2_CompressAlgo1.dll + IDC213_CompressAlgo1.dll + ISG48V1_CompressAlgo1.dll + LIB48_222_CompressAlgo1.dll + RSG48V1_CompressAlgo1.dll + UDCM_CompressAlgo1.dll + VGSNAG3_CompressAlgo1.dll + */ + + + /* + GetComment : present in IC_204_* libraries such as IC_204_IC_204_01_51_11_00.dll + Content is something like "Generiert fuer Hr Merz" + */ + + + /* + Standard functions: + + GenerateKeyExOpt + GenerateKeyEx + + GetSeedLength + GetKeyLength + GetConfiguredAccessTypes + GetECUName + */ + + /* + GenerateKeyExOpt + From Vector's official docs @ https://assets.vector.com/cms/content/know-how/_application-notes/AN-IDG-1-017_SecurityAccess.pdf + + VKeyGenResultEx GenerateKeyExOpt + ( + const unsigned char* ipSeedArray, + unsigned int iSeedArraySize, + const unsigned int iSecurityLevel, + const char* ipVariant, + const char* ipOptions, + unsigned char* iopKeyArray, + unsigned int iMaxKeyArraySize, + unsigned int& oActualKeyArraySize + ); + Parameter description + > [in] ipSeedArray: the seed queried by the ECU (as byte raw data) + > [in] iSeedArraySize: The size of the array + > [in] iSecurityLevel: the security level to be change to + > [in] ipVariant: the ECU variant’s qualifier + > [in] ipOptions: the option string (free text) + > [out] iopKeyArray: the calculated key on return (as byte raw data) + > [in] iMaxKeyArraySize: maximum number of key bytes available + > [out] oActualKeyArraySize: the number of key bytes calculated + + */ + + public static string[] KnownExportedFunctions = new string[] { "GetECUName", "GetComment", "GetKeyLength", "GetSeedLength", "GetConfiguredAccessTypes", "GenerateKeyExOpt", "GenerateKeyEx" }; + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + public delegate IntPtr GetECUName(); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + public delegate IntPtr GetComment(); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + public delegate int GetKeyLength(uint iSecurityLevel); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + public delegate int GetSeedLength(uint iSecurityLevel); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + public delegate int GetConfiguredAccessTypes(uint[] iSecurityLevels); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + public delegate int GenerateKeyExOpt(byte[] ipSeedArray, uint iSeedArraySize, uint iSecurityLevel, byte[] ipVariant, byte[] ipOptions, byte[] iopKeyArray, uint iMaxKeyArraySize, out uint oActualKeyArraySize); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + public delegate int GenerateKeyEx(byte[] ipSeedArray, uint iSeedArraySize, uint iSecurityLevel, byte[] ipVariant, byte[] iopKeyArray, uint iMaxKeyArraySize, out uint oActualKeyArraySize); + + public enum VKeyGenResultEx + { + OK = 0, + BufferTooSmall = 1, + SecurityLevelInvalid = 2, + VariantInvalid = 3, + UnknownError = 4 + } + } +} diff --git a/SecurityAccessQuery/SecurityAccessQuery/LibrarySelector.Designer.cs b/SecurityAccessQuery/SecurityAccessQuery/LibrarySelector.Designer.cs new file mode 100644 index 0000000..8ef5fc0 --- /dev/null +++ b/SecurityAccessQuery/SecurityAccessQuery/LibrarySelector.Designer.cs @@ -0,0 +1,150 @@ +namespace SecurityAccessQuery +{ + partial class LibrarySelector + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(LibrarySelector)); + this.dgvResponse = new System.Windows.Forms.DataGridView(); + this.txtFilter = new System.Windows.Forms.TextBox(); + this.cbHasValidModes = new System.Windows.Forms.CheckBox(); + this.cbHasGenerationFn = new System.Windows.Forms.CheckBox(); + this.btnOpen = new System.Windows.Forms.Button(); + this.btnCancel = new System.Windows.Forms.Button(); + ((System.ComponentModel.ISupportInitialize)(this.dgvResponse)).BeginInit(); + this.SuspendLayout(); + // + // dgvResponse + // + this.dgvResponse.AllowUserToAddRows = false; + this.dgvResponse.AllowUserToDeleteRows = false; + this.dgvResponse.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.dgvResponse.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize; + this.dgvResponse.Location = new System.Drawing.Point(12, 12); + this.dgvResponse.Name = "dgvResponse"; + this.dgvResponse.ReadOnly = true; + this.dgvResponse.SelectionMode = System.Windows.Forms.DataGridViewSelectionMode.FullRowSelect; + this.dgvResponse.Size = new System.Drawing.Size(776, 393); + this.dgvResponse.TabIndex = 2; + this.dgvResponse.DoubleClick += new System.EventHandler(this.dgvResponse_DoubleClick); + this.dgvResponse.KeyDown += new System.Windows.Forms.KeyEventHandler(this.dgvResponse_KeyDown); + // + // txtFilter + // + this.txtFilter.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.txtFilter.Location = new System.Drawing.Point(12, 418); + this.txtFilter.Name = "txtFilter"; + this.txtFilter.Size = new System.Drawing.Size(296, 20); + this.txtFilter.TabIndex = 3; + this.txtFilter.TextChanged += new System.EventHandler(this.txtFilter_TextChanged); + this.txtFilter.KeyDown += new System.Windows.Forms.KeyEventHandler(this.txtFilter_KeyDown); + // + // cbHasValidModes + // + this.cbHasValidModes.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); + this.cbHasValidModes.AutoSize = true; + this.cbHasValidModes.Checked = true; + this.cbHasValidModes.CheckState = System.Windows.Forms.CheckState.Checked; + this.cbHasValidModes.Location = new System.Drawing.Point(325, 420); + this.cbHasValidModes.Name = "cbHasValidModes"; + this.cbHasValidModes.Size = new System.Drawing.Size(112, 17); + this.cbHasValidModes.TabIndex = 4; + this.cbHasValidModes.Text = "Filter: Valid Modes"; + this.cbHasValidModes.UseVisualStyleBackColor = true; + this.cbHasValidModes.CheckedChanged += new System.EventHandler(this.cbHasValidModes_CheckedChanged); + // + // cbHasGenerationFn + // + this.cbHasGenerationFn.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); + this.cbHasGenerationFn.AutoSize = true; + this.cbHasGenerationFn.Checked = true; + this.cbHasGenerationFn.CheckState = System.Windows.Forms.CheckState.Checked; + this.cbHasGenerationFn.Location = new System.Drawing.Point(443, 420); + this.cbHasGenerationFn.Name = "cbHasGenerationFn"; + this.cbHasGenerationFn.Size = new System.Drawing.Size(183, 17); + this.cbHasGenerationFn.TabIndex = 5; + this.cbHasGenerationFn.Text = "Filter: Exports generation function"; + this.cbHasGenerationFn.UseVisualStyleBackColor = true; + this.cbHasGenerationFn.CheckedChanged += new System.EventHandler(this.cbHasGenerationFn_CheckedChanged); + // + // btnOpen + // + this.btnOpen.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); + this.btnOpen.Location = new System.Drawing.Point(632, 416); + this.btnOpen.Name = "btnOpen"; + this.btnOpen.Size = new System.Drawing.Size(75, 23); + this.btnOpen.TabIndex = 6; + this.btnOpen.Text = "Open"; + this.btnOpen.UseVisualStyleBackColor = true; + this.btnOpen.Click += new System.EventHandler(this.btnOpen_Click); + // + // btnCancel + // + this.btnCancel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); + this.btnCancel.Location = new System.Drawing.Point(713, 416); + this.btnCancel.Name = "btnCancel"; + this.btnCancel.Size = new System.Drawing.Size(75, 23); + this.btnCancel.TabIndex = 7; + this.btnCancel.Text = "Cancel"; + this.btnCancel.UseVisualStyleBackColor = true; + this.btnCancel.Click += new System.EventHandler(this.btnCancel_Click); + // + // LibrarySelector + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(800, 450); + this.Controls.Add(this.btnCancel); + this.Controls.Add(this.btnOpen); + this.Controls.Add(this.cbHasGenerationFn); + this.Controls.Add(this.cbHasValidModes); + this.Controls.Add(this.txtFilter); + this.Controls.Add(this.dgvResponse); + this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon"))); + this.Name = "LibrarySelector"; + this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen; + this.Text = "Library Selector"; + this.Load += new System.EventHandler(this.LibrarySelector_Load); + ((System.ComponentModel.ISupportInitialize)(this.dgvResponse)).EndInit(); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.DataGridView dgvResponse; + private System.Windows.Forms.TextBox txtFilter; + private System.Windows.Forms.CheckBox cbHasValidModes; + private System.Windows.Forms.CheckBox cbHasGenerationFn; + private System.Windows.Forms.Button btnOpen; + private System.Windows.Forms.Button btnCancel; + } +} \ No newline at end of file diff --git a/SecurityAccessQuery/SecurityAccessQuery/LibrarySelector.cs b/SecurityAccessQuery/SecurityAccessQuery/LibrarySelector.cs new file mode 100644 index 0000000..9c15411 --- /dev/null +++ b/SecurityAccessQuery/SecurityAccessQuery/LibrarySelector.cs @@ -0,0 +1,159 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.IO; +using System.Linq; +using System.Reflection; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; + +namespace SecurityAccessQuery +{ + public partial class LibrarySelector : Form + { + public string SelectedFile { get; set; } + + public List LoadedDlls = new List(); + private Keys[] directionalKeys = new Keys[] { Keys.Up, Keys.Down, Keys.Left, Keys.Right }; + + public LibrarySelector() + { + InitializeComponent(); + } + + private void LibrarySelector_Load(object sender, EventArgs e) + { + UnmanagedUtility.SendMessage(txtFilter.Handle, UnmanagedUtility.EM_SETCUEBANNER, 0, "Filter library by file name or ECU name.."); + EnableDoubleBuffer(dgvResponse, true); + DrawDatagrid(); + } + + public static void EnableDoubleBuffer(DataGridView dgv, bool setting) + { + Type dgvType = dgv.GetType(); + PropertyInfo pi = dgvType.GetProperty("DoubleBuffered", BindingFlags.Instance | BindingFlags.NonPublic); + pi.SetValue(dgv, setting, null); + } + + private void DrawDatagrid() + { + DataTable dt = new DataTable(); + + dt.Columns.Add("Name"); + dt.Columns.Add("Target ECU"); + dt.Columns.Add("Available Levels"); + + foreach (DllContext dll in LoadedDlls) + { + if (cbHasGenerationFn.Checked) + { + if (!dll.KeyGenerationCapability) + { + continue; + } + } + if (cbHasValidModes.Checked) + { + if (dll.AccessLevels.Count == 0) + { + continue; + } + } + string filter = txtFilter.Text.ToLower(); + if (dll.FileName.ToLower().Contains(filter) || dll.FileName.ToLower().Contains(filter)) + { + string accessLevels = string.Join(", ", dll.AccessLevels.Select(t => $"{t.Item1}")); + dt.Rows.Add(new string[] { dll.FileName, dll.ECUName, $"[{accessLevels}]" }); + } + } + + dgvResponse.DataSource = dt; + dgvResponse.Columns[0].AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill; + dgvResponse.Columns[1].AutoSizeMode = DataGridViewAutoSizeColumnMode.DisplayedCells; + dgvResponse.Columns[2].AutoSizeMode = DataGridViewAutoSizeColumnMode.DisplayedCells; + } + + + private void cbHasGenerationFn_CheckedChanged(object sender, EventArgs e) + { + DrawDatagrid(); + } + + private void cbHasValidModes_CheckedChanged(object sender, EventArgs e) + { + DrawDatagrid(); + } + + private void txtFilter_TextChanged(object sender, EventArgs e) + { + DrawDatagrid(); + } + + private bool TryReturnSelectedItem() + { + if (dgvResponse.SelectedRows.Count > 0) + { + SelectedFile = Program.GetLibraryPath() + dgvResponse.SelectedRows[0].Cells[0].Value.ToString(); + this.DialogResult = DialogResult.OK; + this.Close(); + return true; + } + return false; + } + + private void dgvResponse_DoubleClick(object sender, EventArgs e) + { + TryReturnSelectedItem(); + } + + private void btnCancel_Click(object sender, EventArgs e) + { + this.DialogResult = DialogResult.Cancel; + this.Close(); + } + + private void btnOpen_Click(object sender, EventArgs e) + { + if (!TryReturnSelectedItem()) + { + MessageBox.Show("Please select a DLL file first", "No file selected"); + } + } + + private void dgvResponse_KeyDown(object sender, KeyEventArgs e) + { + if (e.KeyCode == Keys.Enter) + { + TryReturnSelectedItem(); + return; + } + + if (directionalKeys.Contains(e.KeyCode)) + { + return; + } + else + { + // send unrecognized keystrokes into the textbox if the user decides to type into the datagridview + txtFilter.Focus(); + } + } + + private void txtFilter_KeyDown(object sender, KeyEventArgs e) + { + if (e.KeyCode == Keys.Enter) + { + TryReturnSelectedItem(); + return; + } + // navigation keys go back to the datagridview + if (directionalKeys.Contains(e.KeyCode)) + { + dgvResponse.Focus(); + } + } + } +} diff --git a/SecurityAccessQuery/SecurityAccessQuery/LibrarySelector.resx b/SecurityAccessQuery/SecurityAccessQuery/LibrarySelector.resx new file mode 100644 index 0000000..5b3fbaa --- /dev/null +++ b/SecurityAccessQuery/SecurityAccessQuery/LibrarySelector.resx @@ -0,0 +1,145 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + + AAABAAEAEBAAAAEAIABoBAAAFgAAACgAAAAQAAAAIAAAAAEAIAAAAAAAQAQAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAlGE+nJRgPf+TYDz/kl87/5JeOv9gdoT/S5nH/0SHuf9rX1z/j1o2/45aNf+OWTWxAAAAAAAA + AAAAAAAAAAAAAJViP+HMq4X/0a+J/9KwiP/RrYX/Za3O/4bp+f9N2fX/QZPI/46Ihf/HmXH/k2E+/040 + IaEAAAAAAAAAAAAAAACWY0DhyqmF/6N4VP/Gmmf/xJhi/1+nyP+h5vj/ONLy/0fW9v9AlMj/iYSD/41h + Rf9SPjHjAAAAAAAAAAAAAAAAlmRB4cusiP+mflf/yZ9u/8edaf+QmZD/VJ3F/5ni9v9T3PX/Rtn2/z2R + yP8+gML/OX7D/yBep1MAAAAAAAAAAJdlQ+HOsI7/qoVb/8ukdf/KonH/yJ5r/6eaf/9gpsf/X7PU/17Z + 8v9O2/b/W933/1XY9f8ugM33IFiiWQAAAACYZkTh0LSS/6+LYP/OqXz/zKZ3/8ujdP/JoG7/x51q/3mZ + o/+J3fT/auD2/3Pi9/9f3/b/Vdr2/zh/zfMAAAAAmWdF4dK3lv+0kmX/0a6D/8+rf//NqHr/y6V2/8qi + cf9noLr/qe75/37m+P+a6Pj/ftHw/4Di9v8/mNnwAAAAAJloRuHVu5v/uJpp/9Sziv/Sr4f/0K2C/8+q + ff/Npnj/jJ6c/17B6f+j8Pv/gNTw/37H7P9Qo931IW62WQAAAACaaUfh17+f/72fb//UtZD/y62I/8eo + gf/GpX3/xKF6/8Whdv+EnaT/b8ns/8nz+/9Xsdr/JYXNSAAAAAAAAAAAm2pI4dnCpP/BpHL/0riU//Xt + 5P/07OL/9Ozh//Tr4P/z6t//yqmA/32nu/9XnsL/RmBu/wAAAAAAAAAAAAAAAJtqSeHbxab/xqd2/9m/ + m//Rt5P/y7CO/8quiv/Iq4f/y6uD/9Gwh//Yu5v/mWpI/1c+Kv8AAAAAAAAAAAAAAACca0rh3cip/9S9 + lf/m1Ln/5tG2/+TQtf/jzrP/4suw/+DJrf/fx6n/2r+g/5prSv9XPir/AAAAAAAAAAAAAAAAnGxL4NnC + pf+1kXD/q4Bf/6l+Xv+pfl7/qH1c/6h8W/+ne1r/pnlZ/5xrSf+WZEH/Vz4q/wAAAAAAAAAAAAAAAJ1t + S8+6l3j/2MW5/+je1//n3db/5tzW/+Tb1P/j2tP/4tjR/+HX0P/r5+X/7+/v/1c+Kv8AAAAAAAAAAAAA + AACdbUyRnW1L/ruXeP+sgmL/rIFh/6uAYP+rf1//qn9e/6h+Xf+ofFz/nW1M/5dmQ/+IXDz/AAAAAAAA + AAAAAAAAnm5NK51tTNadbUvFnWxL/5xsSv+ca0n/m2pJ/5tqSP+aaUf/mWhG/5hnRf+TZEP/hF0+3gAA + AAAAAAAAgAcAAIADAACAAwAAgAEAAIAAAACAAAAAgAAAAIAAAACAAQAAgAMAAIADAACAAwAAgAMAAIAD + AACAAwAAgAMAAA== + + + \ No newline at end of file diff --git a/SecurityAccessQuery/SecurityAccessQuery/MainForm.Designer.cs b/SecurityAccessQuery/SecurityAccessQuery/MainForm.Designer.cs new file mode 100644 index 0000000..9c03494 --- /dev/null +++ b/SecurityAccessQuery/SecurityAccessQuery/MainForm.Designer.cs @@ -0,0 +1,188 @@ +namespace SecurityAccessQuery +{ + partial class MainForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(MainForm)); + this.txtChallenge = new System.Windows.Forms.TextBox(); + this.dgvResponse = new System.Windows.Forms.DataGridView(); + this.menuStrip1 = new System.Windows.Forms.MenuStrip(); + this.fileToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.selectDLLToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.selectDLLFilteredToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripSeparator1 = new System.Windows.Forms.ToolStripSeparator(); + this.exitToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.btnGenerate = new System.Windows.Forms.Button(); + this.diagnosticsDumpDLLReportToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripSeparator2 = new System.Windows.Forms.ToolStripSeparator(); + ((System.ComponentModel.ISupportInitialize)(this.dgvResponse)).BeginInit(); + this.menuStrip1.SuspendLayout(); + this.SuspendLayout(); + // + // txtChallenge + // + this.txtChallenge.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.txtChallenge.BackColor = System.Drawing.SystemColors.Window; + this.txtChallenge.Location = new System.Drawing.Point(12, 29); + this.txtChallenge.Name = "txtChallenge"; + this.txtChallenge.Size = new System.Drawing.Size(667, 20); + this.txtChallenge.TabIndex = 0; + this.txtChallenge.TextChanged += new System.EventHandler(this.txtChallenge_TextChanged); + this.txtChallenge.KeyDown += new System.Windows.Forms.KeyEventHandler(this.txtChallenge_KeyDown); + // + // dgvResponse + // + this.dgvResponse.AllowUserToAddRows = false; + this.dgvResponse.AllowUserToDeleteRows = false; + this.dgvResponse.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.dgvResponse.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize; + this.dgvResponse.Location = new System.Drawing.Point(12, 53); + this.dgvResponse.Name = "dgvResponse"; + this.dgvResponse.ReadOnly = true; + this.dgvResponse.Size = new System.Drawing.Size(748, 378); + this.dgvResponse.TabIndex = 1; + // + // menuStrip1 + // + this.menuStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.fileToolStripMenuItem}); + this.menuStrip1.Location = new System.Drawing.Point(0, 0); + this.menuStrip1.Name = "menuStrip1"; + this.menuStrip1.RenderMode = System.Windows.Forms.ToolStripRenderMode.System; + this.menuStrip1.Size = new System.Drawing.Size(772, 24); + this.menuStrip1.TabIndex = 2; + this.menuStrip1.Text = "menuStrip1"; + // + // fileToolStripMenuItem + // + this.fileToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.selectDLLToolStripMenuItem, + this.selectDLLFilteredToolStripMenuItem, + this.toolStripSeparator2, + this.diagnosticsDumpDLLReportToolStripMenuItem, + this.toolStripSeparator1, + this.exitToolStripMenuItem}); + this.fileToolStripMenuItem.Name = "fileToolStripMenuItem"; + this.fileToolStripMenuItem.Size = new System.Drawing.Size(37, 20); + this.fileToolStripMenuItem.Text = "File"; + // + // selectDLLToolStripMenuItem + // + this.selectDLLToolStripMenuItem.Name = "selectDLLToolStripMenuItem"; + this.selectDLLToolStripMenuItem.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.O))); + this.selectDLLToolStripMenuItem.Size = new System.Drawing.Size(253, 22); + this.selectDLLToolStripMenuItem.Text = "Select DLL"; + this.selectDLLToolStripMenuItem.Click += new System.EventHandler(this.selectDLLToolStripMenuItem_Click); + // + // selectDLLFilteredToolStripMenuItem + // + this.selectDLLFilteredToolStripMenuItem.Name = "selectDLLFilteredToolStripMenuItem"; + this.selectDLLFilteredToolStripMenuItem.ShortcutKeys = ((System.Windows.Forms.Keys)(((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.Shift) + | System.Windows.Forms.Keys.O))); + this.selectDLLFilteredToolStripMenuItem.Size = new System.Drawing.Size(253, 22); + this.selectDLLFilteredToolStripMenuItem.Text = "Select DLL (Filtered)"; + this.selectDLLFilteredToolStripMenuItem.Click += new System.EventHandler(this.selectDLLFilteredToolStripMenuItem_Click); + // + // toolStripSeparator1 + // + this.toolStripSeparator1.Name = "toolStripSeparator1"; + this.toolStripSeparator1.Size = new System.Drawing.Size(250, 6); + // + // exitToolStripMenuItem + // + this.exitToolStripMenuItem.Name = "exitToolStripMenuItem"; + this.exitToolStripMenuItem.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.Q))); + this.exitToolStripMenuItem.Size = new System.Drawing.Size(253, 22); + this.exitToolStripMenuItem.Text = "Exit"; + this.exitToolStripMenuItem.Click += new System.EventHandler(this.exitToolStripMenuItem_Click); + // + // btnGenerate + // + this.btnGenerate.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.btnGenerate.Location = new System.Drawing.Point(685, 27); + this.btnGenerate.Name = "btnGenerate"; + this.btnGenerate.Size = new System.Drawing.Size(75, 23); + this.btnGenerate.TabIndex = 3; + this.btnGenerate.Text = "Generate"; + this.btnGenerate.UseVisualStyleBackColor = true; + this.btnGenerate.Click += new System.EventHandler(this.btnGenerate_Click); + // + // diagnosticsDumpDLLReportToolStripMenuItem + // + this.diagnosticsDumpDLLReportToolStripMenuItem.Name = "diagnosticsDumpDLLReportToolStripMenuItem"; + this.diagnosticsDumpDLLReportToolStripMenuItem.Size = new System.Drawing.Size(253, 22); + this.diagnosticsDumpDLLReportToolStripMenuItem.Text = "Diagnostics: Dump DLL Report"; + this.diagnosticsDumpDLLReportToolStripMenuItem.Click += new System.EventHandler(this.diagnosticsDumpDLLReportToolStripMenuItem_Click); + // + // toolStripSeparator2 + // + this.toolStripSeparator2.Name = "toolStripSeparator2"; + this.toolStripSeparator2.Size = new System.Drawing.Size(250, 6); + // + // MainForm + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(772, 443); + this.Controls.Add(this.btnGenerate); + this.Controls.Add(this.dgvResponse); + this.Controls.Add(this.txtChallenge); + this.Controls.Add(this.menuStrip1); + this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon"))); + this.MainMenuStrip = this.menuStrip1; + this.Name = "MainForm"; + this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen; + this.Text = "Security Access Query"; + this.Load += new System.EventHandler(this.MainForm_Load); + ((System.ComponentModel.ISupportInitialize)(this.dgvResponse)).EndInit(); + this.menuStrip1.ResumeLayout(false); + this.menuStrip1.PerformLayout(); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.TextBox txtChallenge; + private System.Windows.Forms.DataGridView dgvResponse; + private System.Windows.Forms.MenuStrip menuStrip1; + private System.Windows.Forms.Button btnGenerate; + private System.Windows.Forms.ToolStripMenuItem fileToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem selectDLLToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem selectDLLFilteredToolStripMenuItem; + private System.Windows.Forms.ToolStripSeparator toolStripSeparator1; + private System.Windows.Forms.ToolStripMenuItem exitToolStripMenuItem; + private System.Windows.Forms.ToolStripSeparator toolStripSeparator2; + private System.Windows.Forms.ToolStripMenuItem diagnosticsDumpDLLReportToolStripMenuItem; + } +} + diff --git a/SecurityAccessQuery/SecurityAccessQuery/MainForm.cs b/SecurityAccessQuery/SecurityAccessQuery/MainForm.cs new file mode 100644 index 0000000..43f1408 --- /dev/null +++ b/SecurityAccessQuery/SecurityAccessQuery/MainForm.cs @@ -0,0 +1,242 @@ +using System; +using System.Collections.Generic; +using System.Data; +using System.IO; +using System.Linq; +using System.Text; +using System.Windows.Forms; + +/* +Additional tests: + +CRD3NFZ 2435h +WDB9067331S861252 +Request Seed for Variantcoding: 52 F6 CB D8 +Try B5 E2 62 81 +passed: Access Key: 11 (0xB) + +MED177 +Request 42 21 90 48 +C4 2D E1 7E +passed: 5 + */ + +namespace SecurityAccessQuery +{ + public partial class MainForm : Form + { + private DllContext currentDll; + List cachedDllMetadata = new List(); + + public MainForm() + { + InitializeComponent(); + } + + private void MainForm_Load(object sender, EventArgs e) + { + UnmanagedUtility.SendMessage(txtChallenge.Handle, UnmanagedUtility.EM_SETCUEBANNER, 0, "Enter seed data here"); + + if (!Directory.Exists(Program.GetLibraryPath())) + { + Directory.CreateDirectory(Program.GetLibraryPath()); + MessageBox.Show("A library folder to contain DLL files was not found, so an empty folder has been created for you.\r\nThis application requires DLL files that match your ECU to operate.", "Notice"); + } + + LoadLibraryMetadata(); + TryRefreshKey(); + } + + private void LoadLibraryMetadata() + { + cachedDllMetadata = new List(); + foreach (string file in Program.GetLibraryFiles()) + { + if (Path.GetExtension(file).ToLower() != ".dll") + { + continue; + } + + DllContext libraryToLoad = new DllContext(file, false); + libraryToLoad.UnloadLibrary(); + cachedDllMetadata.Add(libraryToLoad); + } + } + + private void DiagnosticsDumpReport() + { + List libraries = new List(); + foreach (string file in Program.GetLibraryFiles()) + { + if (Path.GetExtension(file).ToLower() != ".dll") + { + continue; + } + + DllContext libraryToLoad = new DllContext(file); + libraryToLoad.UnloadLibrary(); + libraries.Add(libraryToLoad); + } + + string divider = "=========================================================="; + StringBuilder sb = new StringBuilder(); + foreach (DllContext library in libraries) + { + sb.AppendLine(divider); + sb.AppendLine(); + sb.AppendLine(library.FileName); + sb.AppendLine($"SHA1: {library.SHA1Hash}"); + sb.AppendLine($"ECUName: {library.ECUName}"); + sb.AppendLine($"Comment: {library.Comment}"); + sb.AppendLine($"Comment: {library.Comment}"); + sb.AppendLine($"Exports: [{string.Join(", ", library.DllExports)}]"); + string accessLevels = string.Join(", ", library.AccessLevels.Select(t => $"[Level: {t.Item1}, KeySize: {t.Item2}, SeedSize: {t.Item3}]")); + sb.AppendLine($"Levels: [{accessLevels}]"); + sb.AppendLine(); + } + + string exportPath = Program.GetStartupPath() + "Report.txt"; + File.WriteAllText(exportPath, sb.ToString()); + MessageBox.Show($"Export OK : Report saved at \r\n{exportPath}", "Diagnostics"); + } + + private void ShowDllInfoNew(byte[] seed) + { + DataTable dt = new DataTable(); + if (currentDll is null) + { + dt.Columns.Add("Name"); + dt.Columns.Add("Value"); + dt.Rows.Add(new string[] { "Welcome", "Please load a compatible DLL file (File > Select DLL)" }); + dt.Rows.Add(new string[] { "License", "MIT: This application should be made available to you at no cost." }); + dt.Rows.Add(new string[] { "URL", "https://github.com/jglim/SecurityAccessQuery" }); + dgvResponse.DataSource = dt; + dgvResponse.Columns[0].AutoSizeMode = DataGridViewAutoSizeColumnMode.DisplayedCells; + dgvResponse.Columns[1].AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill; + return; + } + + dt.Columns.Add("Name"); + dt.Columns.Add("Value"); + + dt.Rows.Add(new string[] { "DLL Name", currentDll.FileName }); + dt.Rows.Add(new string[] { "DLL SHA1", currentDll.SHA1Hash }); + dt.Rows.Add(new string[] { "DLL Description", currentDll.FileDescription }); + dt.Rows.Add(new string[] { "ECU Name", currentDll.ECUName }); + dt.Rows.Add(new string[] { "Comment", currentDll.Comment }); + dt.Rows.Add(new string[] { "Capability", $"Specify: {currentDll.ModeSpecified}, Generate: {currentDll.KeyGenerationCapability}" }); + dt.Rows.Add(new string[] { "Available Access Levels", $"{currentDll.AccessLevels.Count}" }); + + foreach (Tuple accessLevel in currentDll.AccessLevels) + { + dt.Rows.Add(new string[] { $"Access Level {accessLevel.Item1} (0x{accessLevel.Item1:X})", $"Key size: {accessLevel.Item2}, Seed size: {accessLevel.Item3}" }); + } + + dt.Rows.Add(new string[] { "Interpreted Seed", $"{BitUtility.BytesToHex(seed, true)}" }); + dt.Rows.Add(new string[] { "Last Generation Time", $"{DateTime.Now.ToLongTimeString()}" }); + + foreach (Tuple accessLevel in currentDll.AccessLevels) + { + if (accessLevel.Item3 == seed.Length) + { + dt.Rows.Add(new string[] { $"Access Key: {accessLevel.Item1} (0x{accessLevel.Item1:X})", $"{currentDll.GenerateKeyAuto(accessLevel.Item1, seed)}" }); + } + else + { + dt.Rows.Add(new string[] { $"Access Key: {accessLevel.Item1} (0x{accessLevel.Item1:X})", $"Seed size mismatch: {seed.Length} bytes, expecting {accessLevel.Item3} bytes" }); + } + } + + dgvResponse.DataSource = dt; + dgvResponse.Columns[0].AutoSizeMode = DataGridViewAutoSizeColumnMode.DisplayedCells; + dgvResponse.Columns[1].AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill; + } + + private void txtChallenge_TextChanged(object sender, EventArgs e) + { + TryRefreshKey(); + } + + public void TryRefreshKey() + { + bool validHex = true; + string cleanedText = txtChallenge.Text.Replace(" ", "").Replace("\r", "").Replace("\n", "").Replace("\t", "").Replace("-", "").ToUpper(); + if (cleanedText.Length % 2 != 0) + { + validHex = false; + } + if (!System.Text.RegularExpressions.Regex.IsMatch(cleanedText, @"\A\b[0-9a-fA-F]+\b\Z")) + { + validHex = false; + } + + if (validHex) + { + byte[] seed = BitUtility.BytesFromHex(cleanedText); + txtChallenge.BackColor = System.Drawing.SystemColors.Window; + ShowDllInfoNew(seed); + } + else + { + if (cleanedText.Length == 0) + { + ShowDllInfoNew(new byte[] { }); + } + txtChallenge.BackColor = System.Drawing.Color.LavenderBlush; + } + } + + private void btnGenerate_Click(object sender, EventArgs e) + { + TryRefreshKey(); + } + + private void selectDLLToolStripMenuItem_Click(object sender, EventArgs e) + { + OpenFileDialog ofd = new OpenFileDialog(); + ofd.Title = "Select a compatible DLL file"; + ofd.Multiselect = false; + ofd.InitialDirectory = Program.GetStartupPath(); + ofd.Filter = "DLL files (*.dll)|*.dll|All files (*.*)|*.*"; + + if (ofd.ShowDialog() == DialogResult.OK) + { + currentDll = new DllContext(ofd.FileName); + TryRefreshKey(); + } + } + + private void selectDLLFilteredToolStripMenuItem_Click(object sender, EventArgs e) + { + LibrarySelector selector = new LibrarySelector(); + selector.LoadedDlls = cachedDllMetadata; + if (selector.ShowDialog() == DialogResult.OK) + { + currentDll = new DllContext(selector.SelectedFile); + TryRefreshKey(); + } + } + + private void exitToolStripMenuItem_Click(object sender, EventArgs e) + { + Application.Exit(); + } + + private void txtChallenge_KeyDown(object sender, KeyEventArgs e) + { + if (e.KeyCode == Keys.Enter) + { + e.Handled = true; + TryRefreshKey(); + } + } + + private void diagnosticsDumpDLLReportToolStripMenuItem_Click(object sender, EventArgs e) + { + if (MessageBox.Show("This might take a few minutes, depending on the number of files. Continue?", "Diagnostics", MessageBoxButtons.OKCancel) == DialogResult.OK) + { + DiagnosticsDumpReport(); + } + } + } +} diff --git a/SecurityAccessQuery/SecurityAccessQuery/MainForm.resx b/SecurityAccessQuery/SecurityAccessQuery/MainForm.resx new file mode 100644 index 0000000..0379c9f --- /dev/null +++ b/SecurityAccessQuery/SecurityAccessQuery/MainForm.resx @@ -0,0 +1,148 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 17, 17 + + + + + AAABAAEAEBAAAAEAIABoBAAAFgAAACgAAAAQAAAAIAAAAAEAIAAAAAAAQAQAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAlGE+nJRgPf+TYDz/kl87/5JeOv9gdoT/S5nH/0SHuf9rX1z/j1o2/45aNf+OWTWxAAAAAAAA + AAAAAAAAAAAAAJViP+HMq4X/0a+J/9KwiP/RrYX/Za3O/4bp+f9N2fX/QZPI/46Ihf/HmXH/k2E+/040 + IaEAAAAAAAAAAAAAAACWY0DhyqmF/6N4VP/Gmmf/xJhi/1+nyP+h5vj/ONLy/0fW9v9AlMj/iYSD/41h + Rf9SPjHjAAAAAAAAAAAAAAAAlmRB4cusiP+mflf/yZ9u/8edaf+QmZD/VJ3F/5ni9v9T3PX/Rtn2/z2R + yP8+gML/OX7D/yBep1MAAAAAAAAAAJdlQ+HOsI7/qoVb/8ukdf/KonH/yJ5r/6eaf/9gpsf/X7PU/17Z + 8v9O2/b/W933/1XY9f8ugM33IFiiWQAAAACYZkTh0LSS/6+LYP/OqXz/zKZ3/8ujdP/JoG7/x51q/3mZ + o/+J3fT/auD2/3Pi9/9f3/b/Vdr2/zh/zfMAAAAAmWdF4dK3lv+0kmX/0a6D/8+rf//NqHr/y6V2/8qi + cf9noLr/qe75/37m+P+a6Pj/ftHw/4Di9v8/mNnwAAAAAJloRuHVu5v/uJpp/9Sziv/Sr4f/0K2C/8+q + ff/Npnj/jJ6c/17B6f+j8Pv/gNTw/37H7P9Qo931IW62WQAAAACaaUfh17+f/72fb//UtZD/y62I/8eo + gf/GpX3/xKF6/8Whdv+EnaT/b8ns/8nz+/9Xsdr/JYXNSAAAAAAAAAAAm2pI4dnCpP/BpHL/0riU//Xt + 5P/07OL/9Ozh//Tr4P/z6t//yqmA/32nu/9XnsL/RmBu/wAAAAAAAAAAAAAAAJtqSeHbxab/xqd2/9m/ + m//Rt5P/y7CO/8quiv/Iq4f/y6uD/9Gwh//Yu5v/mWpI/1c+Kv8AAAAAAAAAAAAAAACca0rh3cip/9S9 + lf/m1Ln/5tG2/+TQtf/jzrP/4suw/+DJrf/fx6n/2r+g/5prSv9XPir/AAAAAAAAAAAAAAAAnGxL4NnC + pf+1kXD/q4Bf/6l+Xv+pfl7/qH1c/6h8W/+ne1r/pnlZ/5xrSf+WZEH/Vz4q/wAAAAAAAAAAAAAAAJ1t + S8+6l3j/2MW5/+je1//n3db/5tzW/+Tb1P/j2tP/4tjR/+HX0P/r5+X/7+/v/1c+Kv8AAAAAAAAAAAAA + AACdbUyRnW1L/ruXeP+sgmL/rIFh/6uAYP+rf1//qn9e/6h+Xf+ofFz/nW1M/5dmQ/+IXDz/AAAAAAAA + AAAAAAAAnm5NK51tTNadbUvFnWxL/5xsSv+ca0n/m2pJ/5tqSP+aaUf/mWhG/5hnRf+TZEP/hF0+3gAA + AAAAAAAAgAcAAIADAACAAwAAgAEAAIAAAACAAAAAgAAAAIAAAACAAQAAgAMAAIADAACAAwAAgAMAAIAD + AACAAwAAgAMAAA== + + + \ No newline at end of file diff --git a/SecurityAccessQuery/SecurityAccessQuery/Program.cs b/SecurityAccessQuery/SecurityAccessQuery/Program.cs new file mode 100644 index 0000000..128201f --- /dev/null +++ b/SecurityAccessQuery/SecurityAccessQuery/Program.cs @@ -0,0 +1,37 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Threading.Tasks; +using System.Windows.Forms; + +namespace SecurityAccessQuery +{ + static class Program + { + /// + /// The main entry point for the application. + /// + [STAThread] + static void Main() + { + Application.EnableVisualStyles(); + Application.SetCompatibleTextRenderingDefault(false); + Application.Run(new MainForm()); + } + + // Gets the folder where the binary is executed in + public static string GetStartupPath() + { + return Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location) + Path.DirectorySeparatorChar; + } + public static string GetLibraryPath() + { + return $"{Program.GetStartupPath()}Library{Path.DirectorySeparatorChar}"; + } + public static string[] GetLibraryFiles() + { + return Directory.GetFiles(GetLibraryPath()); + } + } +} diff --git a/SecurityAccessQuery/SecurityAccessQuery/Properties/AssemblyInfo.cs b/SecurityAccessQuery/SecurityAccessQuery/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..cdeade3 --- /dev/null +++ b/SecurityAccessQuery/SecurityAccessQuery/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("SecurityAccessQuery")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("SecurityAccessQuery")] +[assembly: AssemblyCopyright("Copyright © 2020")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("67781f09-398d-4ea7-9087-938c7fbd9d98")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/SecurityAccessQuery/SecurityAccessQuery/Properties/Resources.Designer.cs b/SecurityAccessQuery/SecurityAccessQuery/Properties/Resources.Designer.cs new file mode 100644 index 0000000..5cc2199 --- /dev/null +++ b/SecurityAccessQuery/SecurityAccessQuery/Properties/Resources.Designer.cs @@ -0,0 +1,71 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace SecurityAccessQuery.Properties +{ + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources + { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() + { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager + { + get + { + if ((resourceMan == null)) + { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("SecurityAccessQuery.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture + { + get + { + return resourceCulture; + } + set + { + resourceCulture = value; + } + } + } +} diff --git a/SecurityAccessQuery/SecurityAccessQuery/Properties/Resources.resx b/SecurityAccessQuery/SecurityAccessQuery/Properties/Resources.resx new file mode 100644 index 0000000..af7dbeb --- /dev/null +++ b/SecurityAccessQuery/SecurityAccessQuery/Properties/Resources.resx @@ -0,0 +1,117 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/SecurityAccessQuery/SecurityAccessQuery/Properties/Settings.Designer.cs b/SecurityAccessQuery/SecurityAccessQuery/Properties/Settings.Designer.cs new file mode 100644 index 0000000..52781d5 --- /dev/null +++ b/SecurityAccessQuery/SecurityAccessQuery/Properties/Settings.Designer.cs @@ -0,0 +1,30 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace SecurityAccessQuery.Properties +{ + + + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")] + internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase + { + + private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); + + public static Settings Default + { + get + { + return defaultInstance; + } + } + } +} diff --git a/SecurityAccessQuery/SecurityAccessQuery/Properties/Settings.settings b/SecurityAccessQuery/SecurityAccessQuery/Properties/Settings.settings new file mode 100644 index 0000000..3964565 --- /dev/null +++ b/SecurityAccessQuery/SecurityAccessQuery/Properties/Settings.settings @@ -0,0 +1,7 @@ + + + + + + + diff --git a/SecurityAccessQuery/SecurityAccessQuery/SecurityAccessQuery.csproj b/SecurityAccessQuery/SecurityAccessQuery/SecurityAccessQuery.csproj new file mode 100644 index 0000000..ce00caa --- /dev/null +++ b/SecurityAccessQuery/SecurityAccessQuery/SecurityAccessQuery.csproj @@ -0,0 +1,105 @@ + + + + + Debug + AnyCPU + {67781F09-398D-4EA7-9087-938C7FBD9D98} + WinExe + SecurityAccessQuery + SecurityAccessQuery + v4.6 + 512 + true + true + + + AnyCPU + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + AnyCPU + none + true + bin\Release\ + TRACE + prompt + 4 + + + + + + icon.ico + + + + + + + + + + + + + + + + + + + + Form + + + LibrarySelector.cs + + + Form + + + MainForm.cs + + + + + + LibrarySelector.cs + + + MainForm.cs + + + ResXFileCodeGenerator + Resources.Designer.cs + Designer + + + True + Resources.resx + + + SettingsSingleFileGenerator + Settings.Designer.cs + + + True + Settings.settings + True + + + + + + + + + + \ No newline at end of file diff --git a/SecurityAccessQuery/SecurityAccessQuery/UnmanagedUtility.cs b/SecurityAccessQuery/SecurityAccessQuery/UnmanagedUtility.cs new file mode 100644 index 0000000..5bcc75f --- /dev/null +++ b/SecurityAccessQuery/SecurityAccessQuery/UnmanagedUtility.cs @@ -0,0 +1,126 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Runtime.InteropServices; +using System.Text; +using System.Threading.Tasks; + +namespace SecurityAccessQuery +{ + class UnmanagedUtility + { + /* + Symbol enumeration: + https://stackoverflow.com/questions/18249566/c-sharp-get-the-list-of-unmanaged-c-dll-exports + */ + + [DllImport("dbghelp.dll", SetLastError = true, CharSet = CharSet.Unicode)] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool SymInitialize(IntPtr hProcess, string UserSearchPath, [MarshalAs(UnmanagedType.Bool)] bool fInvadeProcess); + + [DllImport("dbghelp.dll", SetLastError = true, CharSet = CharSet.Unicode)] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool SymCleanup(IntPtr hProcess); + + [DllImport("dbghelp.dll", SetLastError = true, CharSet = CharSet.Unicode)] + public static extern ulong SymLoadModuleEx(IntPtr hProcess, IntPtr hFile, string ImageName, string ModuleName, long BaseOfDll, int DllSize, IntPtr Data, int Flags); + + [DllImport("dbghelp.dll", SetLastError = true, CharSet = CharSet.Unicode)] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool SymEnumerateSymbols64(IntPtr hProcess, ulong BaseOfDll, SymEnumerateSymbolsProc64 EnumSymbolsCallback, IntPtr UserContext); + + public delegate bool SymEnumerateSymbolsProc64(string SymbolName, ulong SymbolAddress, uint SymbolSize, IntPtr UserContext); + + /* + DLL invocation: + https://stackoverflow.com/questions/16518943/dllimport-or-loadlibrary-for-best-performance + */ + + [DllImport("kernel32.dll")] + public static extern IntPtr LoadLibrary(string dllToLoad); + + [DllImport("kernel32.dll")] + public static extern IntPtr GetProcAddress(IntPtr hModule, string procedureName); + + [DllImport("kernel32.dll")] + public static extern bool FreeLibrary(IntPtr hModule); + + + // Required for textbox placeholder string + public const int EM_SETCUEBANNER = 0x1501; + + [DllImport("user32.dll", CharSet = CharSet.Auto)] + public static extern Int32 SendMessage(IntPtr hWnd, int msg, int wParam, [MarshalAs(UnmanagedType.LPWStr)] string lParam); + + + private static List LibraryExports = new List(); + + public static bool SymbolEnumeratedCallback(string name, ulong address, uint size, IntPtr context) + { + // Useful for debug: + // Console.WriteLine(name); + LibraryExports.Add(name); + return true; + } + private static bool EnumerateDllExports(string modulePath) + { + IntPtr hCurrentProcess = Process.GetCurrentProcess().Handle; + + ulong dllBase; + + // Initialize symbol handler with our own process handle + if (!SymInitialize(hCurrentProcess, null, false)) + { + Console.WriteLine("SymInitialize function (dbghelp.h) failed"); + return false; + } + + // Load dll + dllBase = SymLoadModuleEx(hCurrentProcess, IntPtr.Zero, modulePath, null, 0, 0, IntPtr.Zero, 0); + + if (dllBase == 0) + { + Console.Out.WriteLine($"Failed to load module: {modulePath}"); + SymCleanup(hCurrentProcess); + return false; + } + + // Clean up the results list before it gets populated + LibraryExports.Clear(); + + // Enumerate symbols. For every symbol, the callback method SymbolEnumeratedCallback is called. + if (SymEnumerateSymbols64(hCurrentProcess, dllBase, SymbolEnumeratedCallback, IntPtr.Zero) == false) + { + Console.Out.WriteLine($"Failed to enumerate symbols for library {modulePath}"); + return false; + } + + SymCleanup(hCurrentProcess); + return true; + } + + public static List GetExports(string modulePath) + { + if (EnumerateDllExports(modulePath)) + { + return LibraryExports; + } + else + { + return new List(); + } + } + + public static void DumpExportsToConsole(string modulePath) + { + List exports = UnmanagedUtility.GetExports(modulePath); + Console.WriteLine($"Retrieving exports for {modulePath}"); + foreach (string s in exports) + { + Console.WriteLine($"{modulePath}: {s}"); + } + Console.WriteLine($"End of {modulePath} exports."); + } + } +} diff --git a/SecurityAccessQuery/SecurityAccessQuery/icon.ico b/SecurityAccessQuery/SecurityAccessQuery/icon.ico new file mode 100644 index 0000000..0cec543 Binary files /dev/null and b/SecurityAccessQuery/SecurityAccessQuery/icon.ico differ diff --git a/docs/resources/SAQ_Header.png b/docs/resources/SAQ_Header.png new file mode 100644 index 0000000..93fc522 Binary files /dev/null and b/docs/resources/SAQ_Header.png differ diff --git a/docs/resources/diff.png b/docs/resources/diff.png new file mode 100644 index 0000000..fc97563 Binary files /dev/null and b/docs/resources/diff.png differ diff --git a/docs/resources/tests_0.png b/docs/resources/tests_0.png new file mode 100644 index 0000000..c2fedda Binary files /dev/null and b/docs/resources/tests_0.png differ diff --git a/docs/resources/tests_1.png b/docs/resources/tests_1.png new file mode 100644 index 0000000..196c37d Binary files /dev/null and b/docs/resources/tests_1.png differ diff --git a/docs/resources/tests_2.png b/docs/resources/tests_2.png new file mode 100644 index 0000000..1e5ab56 Binary files /dev/null and b/docs/resources/tests_2.png differ diff --git a/docs/resources/tests_3.png b/docs/resources/tests_3.png new file mode 100644 index 0000000..36dfc4b Binary files /dev/null and b/docs/resources/tests_3.png differ diff --git a/docs/resources/tests_4.png b/docs/resources/tests_4.png new file mode 100644 index 0000000..8016888 Binary files /dev/null and b/docs/resources/tests_4.png differ diff --git a/docs/resources/tests_5.png b/docs/resources/tests_5.png new file mode 100644 index 0000000..e597153 Binary files /dev/null and b/docs/resources/tests_5.png differ diff --git a/docs/tests.md b/docs/tests.md new file mode 100644 index 0000000..93b8052 --- /dev/null +++ b/docs/tests.md @@ -0,0 +1,53 @@ +# Tests + +Here, the output of SAQ is compared with the results of online guides and tutorials. + +Since I cannot test them directly on hardware, if you have success stories, please feel welcome to share them in this repository's issues. + +--- + +## VGS4NAG2_vgs4nag2_sec_12_06_01.dll + +[https://youtu.be/9gsuqkiju48?t=329](https://youtu.be/9gsuqkiju48?t=329) + +![test-screenshot-0](https://raw.github.com/jglim/SecurityAccessQuery/main/docs/resources/tests_0.png) + +Seed: `67 09 1A 80 F6 9F 84 55 F5 DE` + +Key: `85 49 35 10` + +Level: `09` + +![test-screenshot-1](https://raw.github.com/jglim/SecurityAccessQuery/main/docs/resources/tests_1.png) + +--- + +## MED40_MED40_12_17_00.dll + +[https://youtu.be/x9tk1r7RHiM?t=59](https://youtu.be/x9tk1r7RHiM?t=59) + +![test-screenshot-2](https://raw.github.com/jglim/SecurityAccessQuery/main/docs/resources/tests_2.png) + +Seed: `39 1C 8E C7` + +Key: `98 B2 F2 B4` + +Level: `0B` + +![test-screenshot-3](https://raw.github.com/jglim/SecurityAccessQuery/main/docs/resources/tests_3.png) + +--- + +## MED177_MED177_12_37_00.dll + +[https://youtu.be/mRM5wdkPXcU?t=263](https://youtu.be/mRM5wdkPXcU?t=263) + +![test-screenshot-4](https://raw.github.com/jglim/SecurityAccessQuery/main/docs/resources/tests_4.png) + +Seed: `71 38 1C 8E` + +Key: `95 9A D0 03` + +Level: `0B` + +![test-screenshot-5](https://raw.github.com/jglim/SecurityAccessQuery/main/docs/resources/tests_5.png) \ No newline at end of file