### HarpoS7.KeyDumper.Cli Command-Line Options Source: https://github.com/bonk-dev/harpos7/blob/main/HarpoS7.KeyDumper.Cli/README.md Lists the available command-line arguments for HarpoS7.KeyDumper.Cli, used to control key dumping behavior. Options include targeting specific TIA Portal installations or MPK files, setting output file paths, controlling JSON indentation, and managing console output. ```shell -t, --tia-portal Dump keys from this TIA Portal installation directory -m, --mpk-file Dump keys from this single MPK file -q, --quiet Do not output anything to stdout -o, --output The output file path containing dumped keys. Put in 'stdout' to output the JSON result to the standard output -j, --indent-json (Default: true) Whether or not to indent the resulting JSON -w, --do-not-wait Whether or not to wait for a key press on exit --help Display this help screen. --version Display version information. ``` -------------------------------- ### Manage PLC Public Keys with C# Interface Source: https://context7.com/bonk-dev/harpos7/llms.txt This C# code demonstrates managing public keys for PLCs using the `IPublicKeyStore` interface. It shows how to use the default embedded store and implement a custom store for managing keys from various sources like databases or file systems. ```csharp using HarpoS7.PublicKeys.Interfaces; using HarpoS7.PublicKeys.Impl; // Use default embedded key store var defaultStore = new DefaultPublicKeyStore(); // Get key length based on fingerprint var fingerprint = "00:181B7B0847D1169"; int keyLength = defaultStore.GetPublicKeyLength(fingerprint); // Read public key into buffer var publicKeyBuffer = new byte[keyLength]; defaultStore.ReadPublicKey(publicKeyBuffer.AsSpan(), fingerprint); // Implement custom key store public class CustomPublicKeyStore : IPublicKeyStore { public int GetPublicKeyLength(string variableNameFingerprint) { // Parse family from fingerprint (00, 01, 03) string family = variableNameFingerprint[..2]; return family == "03" ? 64 : 2048; // PlcSim vs Real PLC } public void ReadPublicKey(Span destination, string variableNameFingerprint) { // Load key from database, file system, etc. var keyData = LoadKeyFromCustomSource(variableNameFingerprint); keyData.CopyTo(destination); } } ``` -------------------------------- ### Display Help for HarpoS7.KeyDumper.Cli Source: https://github.com/bonk-dev/harpos7/blob/main/HarpoS7.KeyDumper.Cli/README.md This command displays the help screen for the HarpoS7.KeyDumper.Cli application, detailing available options for dumping TIA Portal keys. It shows parameters for specifying TIA Portal directories, MPK files, output paths, and formatting preferences. ```shell .\HarpoS7.KeyDumper.Cli.exe --help ``` -------------------------------- ### Legacy Authentication for S7 Comm Plus (C#) Source: https://github.com/bonk-dev/harpos7/blob/main/README.md Demonstrates how to perform legacy challenge-based authentication for S7 Comm Plus protocol sessions using C#. This method is typically used with TIA Portal versions prior to V17. It requires input buffers for challenge and public key, and outputs an encrypted key and session key. ```csharp using HarpoS7.Auth; using HarpoS7.PublicKeys.Impl; // The "input" buffers - you have to load/fill them yourselves // The "output" buffers - the library fills them // Input - challenge received from the PLC (20 bytes long) var challenge = new byte[20]; // Input - public key used by the PLC (loaded from local storage, // can be identified by the fingerprint sent by the PLC) var exampleFingerprint = "00:181B7B0847D1169"; var store = new DefaultPublicKeyStore(); var publicKey = new byte[store.GetPublicKeyLength(exampleFingerprint)]; store.ReadPublicKey(publicKey.AsSpan(), exampleFingerprint); // Input - public key family (must be read from the fingerprint) // Example: 00:181B7B0847D11694, the 00 before the ':' is the public key family // Currently the 00, 01 and 03 families are supported. var family = EPublicKeyFamily.S71500; // Output - "Encrypted key" which you send back to the PLC (216 bytes long) var keyBlob = new byte[Constants.FinalBlobDataLength]; // Output - Session key used later on to calculate packet integrity hashes (24 bytes long) var sessionKey = new byte[Constants.SessionKeyLength]; LegacyAuthenticationScheme.Authenticate( keyBlob.AsSpan(), sessionKey.AsSpan(), challenge.AsSpan(), publicKey.AsSpan(), family); ``` -------------------------------- ### Legacy Challenge-Based Authentication Source: https://context7.com/bonk-dev/harpos7/llms.txt Authenticates a session using challenge-response cryptography for PLCs configured with TIA Portal V16 or older. ```APIDOC ## Legacy Challenge-Based Authentication ### Description Authenticates a session using challenge-response cryptography for PLCs configured with TIA Portal V16 or older. ### Method N/A (Library function) ### Endpoint N/A (Library function) ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Request Example ```csharp using HarpoS7; using HarpoS7.Auth; using HarpoS7.PublicKeys.Impl; // Input: 20-byte challenge received from PLC var challenge = new byte[20]; // Fill challenge with data from PLC CreateObject response // Load public key from default store using fingerprint from PLC var exampleFingerprint = "00:181B7B0847D1169"; var store = new DefaultPublicKeyStore(); var publicKey = new byte[store.GetPublicKeyLength(exampleFingerprint)]; store.ReadPublicKey(publicKey.AsSpan(), exampleFingerprint); // Determine public key family from fingerprint prefix (00, 01, or 03) var family = EPublicKeyFamily.S71500; // Output: encrypted key blob to send back to PLC (216 bytes) var keyBlob = new byte[Constants.FinalBlobDataLength]; // Output: session key for calculating packet digests (24 bytes) var sessionKey = new byte[Constants.SessionKeyLength]; // Perform authentication LegacyAuthenticationScheme.Authenticate( keyBlob.AsSpan(), sessionKey.AsSpan(), challenge.AsSpan(), publicKey.AsSpan(), family); // Send keyBlob back to PLC in SetMultiVars request // Use sessionKey for subsequent packet digest calculations ``` ### Response #### Success Response (N/A) - **keyBlob** (byte[]) - Encrypted key blob to send back to PLC. - **sessionKey** (byte[]) - Session key for calculating packet digests. #### Response Example N/A (Library function outputs are variables within the code) ``` -------------------------------- ### Complete PLC Connection, Authentication, and Legitimation in C# Source: https://context7.com/bonk-dev/harpos7/llms.txt This snippet shows the full process of connecting to a Siemens S7 PLC, establishing a session, authenticating using public keys and challenges, and performing password-based legitimation. It handles potential socket and argument exceptions during the process. Dependencies include System.Net, System.Net.Sockets, and the HarpoS7 library. ```csharp using System.Net; using System.Net.Sockets; using HarpoS7; using HarpoS7.Auth; using HarpoS7.PublicKeys.Impl; using HarpoS7.PublicKeys.Exceptions; var plcEndpoint = IPEndPoint.Parse("192.168.1.10:102"); var plcPassword = "SecurePassword123"; using var client = new TcpClient(); try { // 1. Connect to PLC await client.ConnectAsync(plcEndpoint); var stream = client.GetStream(); // 2. Send COTP Connection Request var cotpRequest = new byte[] { 0x03, 0x00, 0x00, 0x24, 0x1F, 0xE0, 0x00, 0x00, 0x00, 0x01, 0x00, 0xC1, 0x02, 0x06, 0x00, 0xC2, 0x10, 0x53, 0x49, 0x4D, 0x41, 0x54, 0x49, 0x43, 0x2D, 0x52, 0x4F, 0x4F, 0x54, 0x2D, 0x48, 0x4D, 0x49, 0xC0, 0x01, 0x0A }; await stream.WriteAsync(cotpRequest); var readBuffer = new byte[1024]; await stream.ReadAsync(readBuffer); // 3. Send CreateObject request to establish session // (See HarpoS7.PoC/Program.cs for complete packet) // 4. Parse response to extract session ID, fingerprint, and challenge // Session ID is at offset 0x17 (VLQ-encoded) // Fingerprint is at offset 0x2F or 0x37 (VLQ-length + string) // Challenge is 20-byte array at offset 0x75 or 0x7D var fingerprint = "00:181B7B0847D1169"; // Parsed from response var challenge = new byte[20]; // Extracted from response var sessionId = 0x12345678; // Decoded from response // 5. Load public key and authenticate var store = new DefaultPublicKeyStore(); var publicKey = new byte[store.GetPublicKeyLength(fingerprint)]; try { store.ReadPublicKey(publicKey.AsSpan(), fingerprint); } catch (UnknownPublicKeyException) { Console.WriteLine("Public key not found in store"); return; } var family = EPublicKeyFamily.S71500; var sessionKey = new byte[Constants.SessionKeyLength]; var keyBlob = new byte[Constants.FinalBlobDataLength]; LegacyAuthenticationScheme.Authenticate( keyBlob.AsSpan(), sessionKey.AsSpan(), challenge.AsSpan(), publicKey.AsSpan(), family); // 6. Send SetMultiVars with keyBlob // PLC responds with success/failure // 7. If PLC is password-protected, perform legitimation // Request legitimation challenge with GetVarSubStreamed var legitChallenge = new byte[20]; // From PLC response var legitBlob = new byte[LegitimateScheme.OutputBlobDataLengthRealPlc]; LegitimateScheme.SolveLegitimateChallengeRealPlc( legitBlob, legitChallenge, publicKey, family, sessionKey, plcPassword); // Send SetVarSubStreamed with legitBlob // PLC grants/denies access based on password Console.WriteLine("Authentication and legitimation successful"); } catch (SocketException ex) { Console.WriteLine($"Connection failed: {ex.Message}"); } catch (ArgumentException ex) { Console.WriteLine($"Invalid parameters: {ex.Message}"); } ``` -------------------------------- ### Solve Legitimate Authentication Challenge in C# - HarpoS7 Source: https://github.com/bonk-dev/harpos7/blob/main/README.md Demonstrates how to solve a legitimate authentication challenge using the HarpoS7 library in C#. This involves preparing output buffer, and calling the SolveLegitimateChallenge method with necessary input parameters like challenge, public key, family, session key, and password. The output buffer is intended to be sent back to the PLC. ```csharp using HarpoS7.Auth; var blobData = new byte[LegitimateScheme.OutputBlobDataLength]; LegitimateScheme.SolveLegitimateChallenge( blobData, // OUT - send this with SetVarSubStreamed challenge, // IN - get this with GetVarSubStreamed publicKey, // IN - get this from a local storage by matching the fingerprint sent by the PLC family, // IN - public key family (must be read from the fingerprint) sessionKey, // IN - generated by LegacyAuthenticationScheme.Authenticate (TODO: check TLS) "password"); // IN - password required by the PLC ``` -------------------------------- ### TLS Authentication Source: https://context7.com/bonk-dev/harpos7/llms.txt Establishes a TLS-encrypted connection for PLCs configured with TIA Portal V17 or newer. ```APIDOC ## TLS Authentication ### Description Establishes a TLS-encrypted connection for PLCs configured with TIA Portal V17 or newer. ### Method N/A (Library function) ### Endpoint N/A (Library function) ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Request Example ```csharp using System.Net.Sockets; using System.Net.Security; using HarpoS7.Tls; // Connect to PLC var client = new TcpClient(); await client.ConnectAsync("192.168.1.10", 102); var stream = client.GetStream(); // Authenticate using TLS with custom SSL options var sslOptions = new SslClientAuthenticationOptions { TargetHost = "192.168.1.10", RemoteCertificateValidationCallback = (sender, cert, chain, errors) => true }; var sslStream = await HarpoTlsAuth.AuthenticateUsingTlsAsync( stream, sslOptions, destinationTsap: "SIMATIC-ROOT-HMI"); // Use sslStream for encrypted communication with PLC // All S7CommPlus packets now flow through encrypted channel ``` ### Response #### Success Response (N/A) - **sslStream** (SslStream) - An SslStream for encrypted communication. #### Response Example N/A (Library function outputs are variables within the code) ``` -------------------------------- ### Authorize PLC Password Access using C# Source: https://context7.com/bonk-dev/harpos7/llms.txt This C# code snippet demonstrates how to authorize access to password-protected PLCs. It requires obtaining a challenge, public key, and session key to solve the legitimation challenge and generate blob data for transmission. ```csharp using HarpoS7.Auth; // First, obtain legitimation challenge from PLC using GetVarSubStreamed request // Challenge is 20 bytes from PLC response var legitimationChallenge = new byte[20]; // Fill with challenge from GetVarSubStreamed response // Use public key and session key from initial authentication var publicKey = new byte[store.GetPublicKeyLength(fingerprint)]; store.ReadPublicKey(publicKey.AsSpan(), fingerprint); var sessionKey = new byte[Constants.SessionKeyLength]; // sessionKey from LegacyAuthenticationScheme.Authenticate var family = EPublicKeyFamily.S71500; var plcPassword = "zaq1@WSX"; // Output: blob data to send in SetVarSubStreamed request var blobData = new byte[LegitimateScheme.OutputBlobDataLengthRealPlc]; LegitimateScheme.SolveLegitimateChallengeRealPlc( blobData, legitimationChallenge, publicKey, family, sessionKey, plcPassword); // Send blobData to PLC in SetVarSubStreamed request // PLC responds with success/failure status code ``` -------------------------------- ### C# Legacy Authentication for S7 PLCs Source: https://context7.com/bonk-dev/harpos7/llms.txt Authenticates a session using challenge-response cryptography for PLCs configured with TIA Portal V16 or older. This method requires inputting a challenge from the PLC and uses a public key store to generate an encrypted key blob and a session key for subsequent communication. ```csharp using HarpoS7; using HarpoS7.Auth; using HarpoS7.PublicKeys.Impl; // Input: 20-byte challenge received from PLC var challenge = new byte[20]; // Fill challenge with data from PLC CreateObject response // Load public key from default store using fingerprint from PLC var exampleFingerprint = "00:181B7B0847D1169"; var store = new DefaultPublicKeyStore(); var publicKey = new byte[store.GetPublicKeyLength(exampleFingerprint)]; store.ReadPublicKey(publicKey.AsSpan(), exampleFingerprint); // Determine public key family from fingerprint prefix (00, 01, or 03) var family = EPublicKeyFamily.S71500; // Output: encrypted key blob to send back to PLC (216 bytes) var keyBlob = new byte[Constants.FinalBlobDataLength]; // Output: session key for calculating packet digests (24 bytes) var sessionKey = new byte[Constants.SessionKeyLength]; // Perform authentication LegacyAuthenticationScheme.Authenticate( keyBlob.AsSpan(), sessionKey.AsSpan(), challenge.AsSpan(), publicKey.AsSpan(), family); // Send keyBlob back to PLC in SetMultiVars request // Use sessionKey for subsequent packet digest calculations ``` -------------------------------- ### C# TLS Authentication for S7 PLCs Source: https://context7.com/bonk-dev/harpos7/llms.txt Establishes a TLS-encrypted connection for PLCs configured with TIA Portal V17 or newer. This involves connecting via TCP, obtaining a stream, and then using HarpoTlsAuth to perform the TLS handshake with custom SSL options for secure communication. ```csharp using System.Net.Sockets; using System.Net.Security; using HarpoS7.Tls; // Connect to PLC var client = new TcpClient(); await client.ConnectAsync("192.168.1.10", 102); var stream = client.GetStream(); // Authenticate using TLS with custom SSL options var sslOptions = new SslClientAuthenticationOptions { TargetHost = "192.168.1.10", RemoteCertificateValidationCallback = (sender, cert, chain, errors) => true }; var sslStream = await HarpoTlsAuth.AuthenticateUsingTlsAsync( stream, sslOptions, destinationTsap: "SIMATIC-ROOT-HMI"); // Use sslStream for encrypted communication with PLC // All S7CommPlus packets now flow through encrypted channel ``` -------------------------------- ### Packet Digest Calculation for S7 Comm Plus (C#) Source: https://github.com/bonk-dev/harpos7/blob/main/README.md Shows how to calculate a packet digest for S7 Comm Plus protocol using C#. This is essential for ensuring packet integrity by preventing tampering. It requires the packet data and the session key obtained from the authentication process. ```csharp // Input - your packet data (without the S7-Header and S7-Trailer) var data = new byte[dataLength]; // Input - session key (output from LegacyAuthenticationScheme.Authenticate) var sessionKey = new byte[Constants.SessionKeyLength]; // Output - the packet data digest, usually placed in the S7-header var digestBuffer = new byte[HarpoPacketDigest.DigestLength]; HarpoPacketDigest.CalculateDigest(digestBuffer.AsSpan(), data, sessionKey); ``` -------------------------------- ### Packet Integrity Digest Calculation Source: https://context7.com/bonk-dev/harpos7/llms.txt Calculates HMAC-SHA256 digests to prevent packet tampering in authenticated sessions. ```APIDOC ## Packet Integrity Digest Calculation ### Description Calculates HMAC-SHA256 digests to prevent packet tampering in authenticated sessions. ### Method N/A (Library function) ### Endpoint N/A (Library function) ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Request Example ```csharp using HarpoS7.Integrity; // Input: packet data without S7-Header and S7-Trailer var packetData = new byte[] { 0x72, 0x01, 0x00, 0x12, 0x31, 0x00, 0x00, 0x05, // ... rest of packet data }; // Input: session key from authentication var sessionKey = new byte[Constants.SessionKeyLength]; // sessionKey was populated by LegacyAuthenticationScheme.Authenticate // Output: 32-byte digest for S7-header var digestBuffer = new byte[HarpoPacketDigest.DigestLength]; HarpoPacketDigest.CalculateDigest( digestBuffer.AsSpan(), packetData, sessionKey); // Include digestBuffer in S7-header when sending packet to PLC // PLC will verify digest to ensure packet hasn't been tampered with ``` ### Response #### Success Response (N/A) - **digestBuffer** (byte[]) - The calculated 32-byte digest for the S7-header. #### Response Example N/A (Library function outputs are variables within the code) ``` -------------------------------- ### C# Packet Integrity Digest Calculation Source: https://context7.com/bonk-dev/harpos7/llms.txt Calculates HMAC-SHA256 digests to prevent packet tampering in authenticated sessions. This function takes raw packet data and a session key (obtained during authentication) to produce a digest that should be included in the S7-header. ```csharp using HarpoS7.Integrity; // Input: packet data without S7-Header and S7-Trailer var packetData = new byte[] { 0x72, 0x01, 0x00, 0x12, 0x31, 0x00, 0x00, 0x05, // ... rest of packet data }; // Input: session key from authentication var sessionKey = new byte[Constants.SessionKeyLength]; // sessionKey was populated by LegacyAuthenticationScheme.Authenticate // Output: 32-byte digest for S7-header var digestBuffer = new byte[HarpoPacketDigest.DigestLength]; HarpoPacketDigest.CalculateDigest( digestBuffer.AsSpan(), packetData, sessionKey); // Include digestBuffer in S7-header when sending packet to PLC // PLC will verify digest to ensure packet hasn't been tampered with ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.