-
Notifications
You must be signed in to change notification settings - Fork 6
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
30 changed files
with
2,176 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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/) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
<?xml version="1.0" encoding="utf-8" ?> | ||
<configuration> | ||
<startup> | ||
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6" /> | ||
</startup> | ||
</configuration> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
using System; | ||
|
||
namespace SecurityAccessQuery | ||
{ | ||
/// <summary> | ||
/// Utilities for bit and byte operations. | ||
/// (Frequently copied-and-pasted across my projects) | ||
/// </summary> | ||
class BitUtility | ||
{ | ||
/// <summary> | ||
/// Sets all values in an array of bytes to a specific value | ||
/// </summary> | ||
/// <param name="value">Value to set byte array to</param> | ||
/// <param name="buf">Target byte array buffer</param> | ||
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); | ||
} | ||
/// <summary> | ||
/// Converts an array of bytes into its hex-string equivalent | ||
/// </summary> | ||
/// <param name="inBytes">Input byte array</param> | ||
/// <param name="spacedOut">Option to add spaces between individual bytes</param> | ||
/// <returns>Hex-string based on the input byte array</returns> | ||
public static string BytesToHex(byte[] inBytes, bool spacedOut = false) | ||
{ | ||
return BitConverter.ToString(inBytes).Replace("-", spacedOut ? " " : ""); | ||
} | ||
|
||
/// <summary> | ||
/// Converts an array of bytes into a printable hex-string | ||
/// </summary> | ||
/// <param name="hexString">Input hex-string to convert into a byte array</param> | ||
/// <returns>Byte array based on the input hex-string</returns> | ||
public static byte[] BytesFromHex(string hexString) | ||
{ | ||
return StringToByteArrayFastest(hexString.Replace(" ", "")); | ||
} | ||
|
||
/// <summary> | ||
/// Resize a smaller array of bytes to a larger array. The padding bytes will be 0. | ||
/// </summary> | ||
/// <param name="inData">Input byte array</param> | ||
/// <param name="finalSize">New size for the input array</param> | ||
/// <returns>Resized byte array</returns> | ||
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; | ||
} | ||
} | ||
} |
Oops, something went wrong.