{ "Scenario": "Local integrated full-history read", "Sensitivity": "Raw OpenConnection3 artifacts contain local identity and machine/process metadata. Keep raw capture under ignored artifacts only.", "RawArtifact": "artifacts/reverse-engineering/instrumented-openconnection3-correlation", "InstrumentedTokens": { "HistorianClient.OpenConnection": "0x060055D8", "aahClientCommon.CClientBase.OpenConnection": "0x0600388D", "CHistoryConnectionWCF.OpenConnection3": "0x06004059", "aahClientCommon.CClientCommon.StartQuery": "0x06002E86", "CRetrievalConnectionWCF.StartQuery2": "0x06004A0D" }, "Observed": { "LegacyClientHandle": 2, "CClientBaseInitialHandle": 0, "OpenConnection3Success": 1, "OpenConnection3RequestLength": 1346, "OpenConnection3RequestSha256": "b50af3af5145c6e1293865e1a9cf1d6c5f850518f1ffcac84a19ef321280a64e", "OpenConnection3RequestSerializerToken": "0x06004003", "OpenConnection3RequestSerializer": "CClientInfo.SerializeOpenConnectionInParams4", "OpenConnection3RequestContentToken": "0x06004005", "OpenConnection3RequestContentSerializer": "CClientInfo.SerializeOpenConnectionInParams2Content", "OpenConnection3ContextKeySetterToken": "0x0600386E", "OpenConnection3ContextKeySetter": "CClientInfo.SetContextKey", "OpenConnection3ContextSource": { "LatestRawArtifact": "artifacts/reverse-engineering/instrumented-cclientinfo-context/auth-context-capture.ndjson", "InstrumentationToken": "0x06004003", "ContextFieldOffsetInCClientInfo": 1240, "SelectorFieldOffsetInCClientInfo": 1608, "RequestPrefixMatchesContextField": true, "RequestSelectorMatchesSelectorField": true, "ConfigureOpenConnectionToken": "0x0600388C", "AuthenticateClientToken": "0x06005DCB", "ClientContextOffsetInCClientBase": 2112, "ClientContextKeyOffset": 64, "ContextKeyOffsetInCClientBase": 2176, "CopiedContextOffsetInCClientBase": 1480, "RuntimeCorrelation": { "BeforeAuthEqualsClientKey": true, "AfterAuthDiffersFromBeforeAuth": true, "AfterAuthEqualsCopiedContextField": true, "CopiedContextEqualsSerializedContextField": true, "SerializedContextEqualsRequestPrefix": true, "LatestBeforeAuthAndSerializedClientKeyAreAllZero": true, "RequestVersionByte": 6, "RequestSelectorByte": 0 }, "NegativeAuthProbeEvidence": { "DirectManagedWcfProbeArtifact": "artifacts/reverse-engineering/wcf-auth-context-localhost-latest.json", "DirectValidateClient2Success": false, "DirectValidateClient2NativeErrorType": 4, "DirectValidateClient2NativeErrorCode": 51, "ManagedWrapperAuthInstrumentationArtifact": "artifacts/reverse-engineering/instrumented-wcf-auth-context", "SuccessfulNativeReadEmittedValidateClientOrExchangeKeyRecords": false, "SuccessfulNativeReadValClRounds": 2, "SuccessfulNativeReadValClInputLengths": [ 69, 93 ], "SuccessfulNativeReadSspiCaptureArtifact": "artifacts/reverse-engineering/system-boundary-sspi-token-localhost-latest.ndjson", "SuccessfulNativeReadSspiPackage": "Negotiate", "SuccessfulNativeReadSspiTarget": "NT SERVICE\\aahClientAccessPoint", "SuccessfulNativeReadSspiCredentialUse": 2, "SuccessfulNativeReadSspiInitializeStatuses": [ "0x90312", "0x0" ], "SuccessfulNativeReadSspiOutputTokenLengths": [ 64, 88 ], "SuccessfulNativeReadSspiWrappedLengthDelta": 5, "NativeCClientContextWindowArtifact": "artifacts/reverse-engineering/instrumented-cclientcontext-window/capture.ndjson", "NativeCClientContextNestedWindowArtifact": "artifacts/reverse-engineering/instrumented-cclientcontext-window/capture-nested.ndjson", "NativeAuthenticateClientDisassemblyArtifact": "artifacts/reverse-engineering/cclientcontext-authenticateclient-disasm-latest.txt", "NativeAuthenticateClientDisassemblyRange": "VA 0x180298BA0..0x180299500", "NativeAuthenticateClientNativeOnly": true, "NativeAuthenticateClientCreatesContextKeyAtOffset": 64, "NativeAuthenticateClientAcquireCredentialsHandleCall": "VA 0x180298CBB via Secur32 IAT", "NativeAuthenticateClientLoopEntry": "VA 0x180298DE0", "NativeAuthenticateClientSspiHelper": "VA 0x180298F30", "NativeAuthenticateClientInitializeSecurityContextCall": "VA 0x1802990F6 via Secur32 IAT", "NativeAuthenticateClientFirstRoundRequestFlags": "0x2081C", "NativeAuthenticateClientSubsequentRoundRequestFlags": "0x81C", "NativeAuthenticateClientWritesTokenEnvelope": "round byte, UInt32 little-endian token length, token bytes", "NativeAuthenticateClientValidateClientCredentialVirtualCalls": [ "VA 0x180298E63", "VA 0x180298E95" ], "NativeAuthenticateClientLocalContextFlag50": 0, "NativeAuthenticateClientObservedVirtualPath": "CClientContext +0x50 is zero in the captured local read, so the normal connection-object virtual call path at VA 0x180298E95 is selected.", "NativeCClientContextPostAuthChangedRanges": [ "8-13", "16-21", "24-29", "64-79" ], "NativeCClientContextKeyOffset": 64, "NativeCClientContextReadablePointerOffsets": [ 8, 16 ], "NativeCClientContextPointer8ContainsSecurityPackageMetadata": true, "NativeCClientContextPointer8ObservedPackageNames": [ "Schannel", "Microsoft Kerberos V1.0", "TSSSP", "System.Core", "Default TLS SSP" ], "NativeCClientContextPointer16NestedPointerOffsets": [ 0, 8, 64 ], "NativeCClientContextPointer16NestedTargetsHaveReadableStrings": false, "NativeCClientContextPointer16NestedTargetKinds": [ "pointer-rich state block", "pointer-rich state block", "all-zero block" ], "NativeCClientContextPointer16Pointer64AllZero": true, "NativeCClientContextPointer16AppearsHistorianPayload": false, "NativeCClientContextPointer16Decoded": "partial-structure-only", "NativeCClientContextPointer24DirectBufferReadSafe": false, "SuccessfulNativeReadValClOutputLengths": [ 239, 1 ], "SuccessfulNativeReadValClFirstInputPrefix": "01400000004e544c4d5353500001000000b7b218e209000900370000000f000f", "ManagedStandaloneValClArtifacts": [ "artifacts/reverse-engineering/wcf-auth-valcl-localhost-cert-latest.json", "artifacts/reverse-engineering/wcf-auth-valcl-localhost-integrated-latest.json", "artifacts/reverse-engineering/wcf-auth-valcl-localhost-cert-lazy-skipgetv-latest.json", "artifacts/reverse-engineering/wcf-auth-valcl-localhost-integrated-lazy-skipgetv-latest.json", "artifacts/reverse-engineering/wcf-auth-valcl-localhost-pipe-latest.json", "artifacts/reverse-engineering/wcf-auth-valcl-localhost-pipe-impersonated-latest.json", "artifacts/reverse-engineering/wcf-auth-valcl-localhost-pipe-lowerhandle-latest.json", "artifacts/reverse-engineering/netfx-wcf-valcl-localhost-pipe-latest.json" ], "ManagedStandaloneValClFirstInputMatchesNative": true, "ManagedStandaloneValClNativeErrorType": 4, "ManagedStandaloneValClNativeErrorCode": 1, "NativeOperationStart2SuccessBeforeValCl": true, "NativeOperationStart2ErrorType": 0, "NativeOperationStart2ErrorCode": 0, "NativeOperationStart2StaticIlLocalGateOnly": true, "NativeOperationStart2StaticIlCallsWcfOperation": false, "NativeOperationStart2StaticIlCalls": [ "CServerConnection.WaitUntilOperationPriorityAllowed", "CCommControl.WaitUntilBandWidthAllowed" ], "NativeOperationStart2StaticIlGateFailureErrorCodes": [ 243, 150 ], "NativeExistingProxyFaultedBeforeValCl": false, "NativeReconnectRequiredBeforeValCl": false, "NativeGetInterfaceVersionCaptureArtifact": "artifacts/reverse-engineering/instrumented-wcf-auth-context/auth-wcf-getinterfaceversion-valcl-capture.ndjson", "NativeGetInterfaceVersionObjectWindowArtifact": "artifacts/reverse-engineering/instrumented-wcf-auth-context/auth-wcf-object-window-current-capture.ndjson", "NativeGetInterfaceVersionObjectWindowTargetArtifact": "artifacts/reverse-engineering/instrumented-wcf-auth-context/auth-wcf-object-window-targets-current-capture.ndjson", "NativeGetInterfaceVersionBeforeValCl": true, "NativeGetInterfaceVersionFirstInitializeProxySuccess": true, "NativeGetInterfaceVersionFirstSetManagedPtrReadyFlag": true, "NativeGetInterfaceVersionObjectWindowChangedRanges": [ "144", "148", "152-153", "472", "608-613", "669" ], "NativeGetInterfaceVersionToValClEntryAdditionalChangedRanges": [ "88", "144", "148", "152-153", "300", "472", "616-621" ], "NativeValClParentObjectStableAcrossRounds": true, "NativeValClHistoryProxyTargetChangedAcrossRounds": [ "96-101" ], "NativeValClBindingTargetStableAcrossRounds": true, "NativeValClWindowsIdentityTargetStableAcrossRounds": true, "NativeInitializeProxyHistoryConnectionMode": 1, "NativeConfigureTcpProxyRecordsForLocalRead": false, "NativeConfigurePipeProxyRecordsForLocalRead": true, "NativeConfigurePipeProxyEndpointLength": 25, "NativeConfigurePipeProxyCompression": false, "NativeConfigurePipeProxySecurityMode": "None", "NativeConfigurePipeProxyUsesStaticChannelFactoryCreateChannel": true, "NativeConfigurePipeProxySetsOperationTimeoutFromTimeoutMinutes": true, "NativeIntegratedSecurityFlagOffset": 540, "NativeWindowsIdentityManagedPtrOffsets": [ 640, 600, 664 ], "NativeSetIntegratedSecurityCapturesCurrentWindowsIdentity": true, "NativeGetInterfaceVersionImpersonatesStoredWindowsIdentity": true, "ManagedNamedPipeValClGetVersionReturnCode": 0, "ManagedNamedPipeValClInterfaceVersion": 11, "ManagedNamedPipeValClFirstInputMatchesNative": true, "ManagedNamedPipeValClNativeErrorType": 4, "ManagedNamedPipeValClNativeErrorCode": 1, "ManagedNamedPipeValClRunImpersonatedStillFails": true, "ManagedNamedPipeValClImpersonatedChannelSetupStillFails": true, "ManagedNamedPipeValClImpersonatedChannelSetupArtifacts": [ "artifacts/reverse-engineering/wcf-auth-valcl-localhost-pipe-impersonated-channel-current-latest.json", "artifacts/reverse-engineering/wcf-auth-valcl-localhost-pipe-impersonated-channel-and-calls-current-latest.json" ], "NativeValClHandleUppercaseGuidText": true, "ManagedNamedPipeValClLowercaseHandleStillFails": true, "ManagedNamedPipeValClServerLogException": "ValidateClientCredential caught exception: System.NullReferenceException at HistoryService.ValidateClientCredential line 1593", "ManagedNamedPipeTransportSecurityRejectedAsBindingMismatch": true, "ManagedNamedPipeValClStaticChannelFactoryStillFails": true, "ManagedNamedPipeValClStaticChannelFactoryLazyOpenStillFails": true, "ManagedNamedPipeValClStaticChannelCurrentArtifact": "artifacts/reverse-engineering/wcf-auth-valcl-localhost-pipe-static-channel-current-latest.json", "ManagedNamedPipeValClStaticChannelLazyCurrentArtifact": "artifacts/reverse-engineering/wcf-auth-valcl-localhost-pipe-static-channel-lazy-current-latest.json", "StaticIlGetClientKeyHandleSource": "ToString(contextKey) argument converted to 36-character System.String before ExchangeKey", "StaticIlValidateClientCredentialHandleSource": "ToString(contextKey) argument converted to 36-character System.String before ValidateClientCredential", "ManagedNamedPipeExchangeKeySeedArtifacts": [ "artifacts/reverse-engineering/wcf-auth-valcl-localhost-pipe-exchangekey-current-latest.json", "artifacts/reverse-engineering/wcf-auth-valcl-localhost-pipe-exchangekey-default-current-latest.json", "artifacts/reverse-engineering/wcf-auth-valcl-localhost-pipe-exchangekey-lazy-current-latest.json" ], "ManagedNamedPipeExchangeKeySeedGetVersionReturnCode": 0, "ManagedNamedPipeExchangeKeySeedInterfaceVersion": 11, "ManagedNamedPipeExchangeKeySeedNativeErrorType": 4, "ManagedNamedPipeExchangeKeySeedNativeErrorCode": 1, "ManagedNamedPipeExchangeKeySeedStillFailsValCl": true, "NetFrameworkDirectNamedPipeValClGetVersionReturnCode": 0, "NetFrameworkDirectNamedPipeValClInterfaceVersion": 11, "NetFrameworkDirectNamedPipeValClFirstInputMatchesNative": true, "NetFrameworkDirectNamedPipeValClNativeErrorType": 4, "NetFrameworkDirectNamedPipeValClNativeErrorCode": 1, "NetFrameworkDirectNamedPipeValClServerLogException": "ValidateClientCredential caught exception: System.NullReferenceException at HistoryService.ValidateClientCredential line 1593", "ServerValidateClientCredentialIlArtifact": "artifacts/reverse-engineering/server-historyservice-validateclientcredential-il-latest.json", "ServerValidateIntegratedCredentialsIlArtifact": "artifacts/reverse-engineering/server-historyservice-validateintegratedcredentials-il-latest.json", "ServerProcessServerTokenDisassemblyArtifact": "artifacts/reverse-engineering/server-cservernode-processservertoken-disasm-latest.txt", "ServerProcessServerTokenHelperArtifacts": [ "artifacts/reverse-engineering/server-helper-0050ffc0-disasm-latest.txt", "artifacts/reverse-engineering/server-helper-00517ab0-disasm-latest.txt", "artifacts/reverse-engineering/server-helper-00505ae0-disasm-latest.txt", "artifacts/reverse-engineering/server-helper-00505c00-disasm-latest.txt", "artifacts/reverse-engineering/server-helper-00505100-disasm-latest.txt", "artifacts/reverse-engineering/server-helper-0042f590-disasm-latest.txt" ], "ServerValidateClientCredentialParsesGuidHandle": true, "ServerValidateClientCredentialCallsProcessServerToken": true, "ServerValidateClientCredentialRegistersContextAfterTerminalRound": true, "ServerProcessServerTokenParsesValClEnvelope": "round byte, UInt32 little-endian token length, token bytes", "ServerProcessServerTokenFirstRoundContextSetupHelper": "VA 0x0050FFC0", "ServerProcessServerTokenContextLookupHelper": "VA 0x00517AB0", "ServerProcessServerTokenAcquireCredentialsHelper": "VA 0x00505AE0", "ServerProcessServerTokenAcceptSecurityContextHelper": "VA 0x00505C00", "ServerContextTypeName": "aahClientAccessPoint::CServerContext", "ServerContextSetupLockOffset": "CServerNode +0xE80", "ServerContextMapOffset": "CServerNode +0xE98", "ServerContextSetupConstructsObject": "VA 0x00505100 constructs a 0x3c-byte CServerContext", "ServerContextSetupInsertHelper": "VA 0x0042F590", "ServerContextLookupValueOffsets": [ "map node +0x20", "map node +0x24" ], "ServerAcquireCredentialsPackageString": "Negotiate", "ServerContextAddLogString": "Adding ServerContext 0x%p", "ServerProcessClientTokenLogString": "aahClientAccessPoint::CServerContext::ProcessClientToken", "ServerAcceptSecurityContextImportAddress": "0x005A0340", "ServerAcceptSecurityContextProgressStatuses": [ "0x0", "0x90312" ], "ServerProcessServerTokenMissingContextCustomErrorCode": "0x29", "ServerValidateIntegratedCredentialsReadsServiceSecurityContextCurrentWindowsIdentity": true, "ClientHistoryConnectionInitializeIlArtifact": "artifacts/reverse-engineering/client-chistoryconnectionwcf-initialize-il-latest.json", "ClientHistoryConnectionInitializeProxyHistoryIlArtifact": "artifacts/reverse-engineering/client-chistoryconnectionwcf-initializeproxy-history-il-latest.json", "ClientHistoryConnectionInitializeSetsHistoryProxySlots": [ 608, 616 ], "ClientHistoryConnectionInitializeSetsTransactionProxySlots": [ 568, 576 ], "ClientHistoryInitializeProxyPipeBranchOffset": "0x0098", "ClientHistoryInitializeProxyTcpBranchOffset": "0x038E", "HistoryServiceContractHasInitializeOperation": false, "ServerRuntimeValClProbeScript": "scripts/frida/aahclientaccesspoint-valcl-context.js", "ServerRuntimeValClProbeRunner": "scripts/Capture-AahClientAccessPointValClContext.ps1", "ServerRuntimeValClProbeSanitizedFieldsOnly": true, "ServerRuntimeValClProbeCurrentSessionAttachRefused": true, "ServerRuntimeValClProbeElevatedSessionAttachRefused": true, "ServerRuntimeValClProbeElevatedSessionPrivileges": [ "SeDebugPrivilege", "SeImpersonatePrivilege", "BUILTIN\\Administrators", "Mandatory Label\\High Mandatory Level" ], "ServerRuntimeValClProbeTargetServiceAccount": "NT SERVICE\\aahClientAccessPoint", "ServerRuntimeValClProbeAttachErrorMessage": "Failed to attach: process with pid either refused to load frida-agent, or terminated during injection", "ServerRuntimeValClProbeMinimalAttachAlsoRefused": true, "ServerRuntimeValClProbePythonExceptionClass": "frida.ProcessNotRespondingError", "ServerRuntimeValClProbeProcessMitigationPolicyAllOff": true, "ServerRuntimeValClProbeProcessMitigationCategoriesChecked": [ "Dep", "Aslr", "StrictHandle", "SystemCall", "ExtensionPoint", "DynamicCode", "Cfg", "BinarySignature", "FontDisable", "ImageLoad", "Payload", "ChildProcess", "UserShadowStack" ], "ServerRuntimeValClProbeProcessAllAccessOpenSucceeds": true, "ServerRuntimeValClProbeCrossBitnessFridaWorksOnControlProcess": true, "ServerRuntimeValClProbeControlProcess": "C:\\Windows\\SysWOW64\\cmd.exe", "ServerRuntimeValClProbeDefenderRealTimeProtectionEnabled": false, "ServerRuntimeValClProbeDefenderBehaviorMonitorEnabled": false, "ServerRuntimeValClProbeThirdPartyAvOrEdrRegistered": false, "ServerRuntimeValClProbeIfeoDebuggerEntry": false, "ServerRuntimeValClProbeAppInitDllsEmpty": true, "ServerRuntimeValClProbeFridaAgentNeverAppearsInTargetModules": true, "ServerRuntimeValClProbeAttachVariantsTried": [ "realm=native", "realm=emulated", "persist_timeout=30" ], "ServerRuntimeValClProbeAttachVariantsAllFailedSameError": true, "ServerRuntimeValClProbeTargetThreadCount": 152, "ServerRuntimeValClProbeRevisedSuspectedCause": "Service-internal: agent injection RPC handshake times out (Frida ProcessNotRespondingError). Mitigation policy, DACL, AV/EDR, IFEO, AppInit_DLLs, and bitness are all ruled out.", "EtwSspiTraceProvidersUsed": [ "{199FE037-2B82-40A9-82AC-E1D46C792B99} LsaSrv", "{CC85922F-DB41-11D2-9244-006008269001} Local Security Authority (LSA)", "{AC43300D-5FCC-4800-8E99-1BD3F85F0320} Microsoft-Windows-NTLM", "{C92CF544-91B3-4DC0-8E11-C580339A0BF8} NTLM Security Protocol", "{5BBB6C18-AA45-49B1-A15F-085F7ED0AA90} Security: NTLM Authentication" ], "EtwSspiTraceLevel": "0xFF", "EtwSspiTraceKeywords": "0xFFFFFFFFFFFFFFFF", "EtwSspiTraceNativeReadEventTotal": 5610, "EtwSspiTraceNativeReadAahClientAccessPointEventCount": 10, "EtwSspiTraceNativeReadAahClientAccessPointEventIds": [30, 34, 35, 40, 84, 10, 12, 16, 17, 86], "EtwSspiTraceNativeReadAahClientAccessPointEventBurstMs": 47, "EtwSspiTraceNativeReadLsassEventCount": 4330, "EtwSspiTraceManagedValClEventTotal": 133, "EtwSspiTraceManagedValClAahClientAccessPointEventCount": 0, "EtwSspiTraceManagedValClLsassEventCount": 121, "EtwSspiTraceManagedValClProbeProcessEventIds": [10, 12, 18, 19, 21, 22, 23], "EtwSspiTraceConclusion": "Server-side aahClientAccessPoint never invokes any SSPI helper during the failing managed ValCl. The HistoryService.ValidateClientCredential NullReferenceException at line 1593 fires before reaching CServerNode.ProcessServerToken at IL 0x01DC.", "EtwSspiTraceRawArtifactsKind": "ETL files containing SSPI tokens and identity metadata, kept under artifacts/reverse-engineering/etw-sspi-{nativeread,managedvalcl}-*.etl and not committed.", "ValidateClientCredentialIlMethodToken": "0x06000774", "ValidateClientCredentialIlInstructionCount": 779, "ValidateClientCredentialIlAssembly": "C:\\Program Files (x86)\\Common Files\\ArchestrA\\aahClientAccessPoint.exe (mixed-mode C++/CLI)", "ValidateClientCredentialIlNreCandidates": [ { "Offset": "0x00ED", "OpCode": "call", "Target": "::aahClientAccessPoint.CServerNode.LogHistorianMessage(this, _, CServerClient*, _, _, _, _)", "Risk": "If CServerClient* arg is derived from WCF context and is null on the failing binding, the call NREs before Guid.TryParse.", "Differentiator": "Both successful native and failing managed paths use Security.Mode=None pipe binding, so unlikely the differentiator. Confirm via PsExec SYSTEM Frida or signed Detours." }, { "Offset": "0x017E", "OpCode": "ldind.i4", "Target": "*(value at g_ClientAccessPoint + 2328) = vtable pointer of pAllocator", "Risk": "NREs if g_ClientAccessPoint+2328 is null/uninitialised.", "Differentiator": "g_ClientAccessPoint is a process-wide singleton; same value for native and managed callers. Ruled out unless lazily initialised per-binding." }, { "Offset": "0x0182", "OpCode": "ldind.i4", "Target": "*(vtable + 40) = allocator function pointer", "Risk": "NREs if the vtable+40 slot is null or vtable pointer was zero.", "Differentiator": "Same as 0x017E — unlikely the differentiator." }, { "Offset": "0x01AA", "OpCode": "ldelema System.Byte", "Target": "&arg.2[0] where arg.2 is byte[] inputBuffer", "Risk": "NREs if WCF deserialises inputBuffer as null even though a 69-byte token was on the wire (SOAP body schema mismatch).", "Differentiator": "Most plausible remaining differentiator. The managed probe's WCF body schema is the testable hypothesis." }, { "Offset": "0x01B2", "OpCode": "ldlen", "Target": "arg.2.Length", "Risk": "Same as 0x01AA — NREs if inputBuffer is null after WCF deserialisation.", "Differentiator": "Same as 0x01AA." } ], "ValidateClientCredentialIlAllocatorOffsets": { "AllocatorPointerFieldOffsetInGClientAccessPoint": 2328, "VtableSlotForAllocatorMethodOffset": 40, "ServerBufferDataPointerFieldOffset": 72, "ServerBufferDataLengthFieldOffset": 76, "CServerNodeOffsetInGClientAccessPoint": 2144 }, "ValidateClientCredentialIlNreCustomErrorPathsAreHandled": [ { "Code": 28, "Trigger": "Guid.TryParse on arg.1 returns false at IL 0x012F" }, { "Code": 204, "Trigger": "Allocator returns null CServerBuffer* at IL 0x018A" } ], "ValidateClientCredentialIlNextEvidenceTarget": "Compare the SOAP body element bound to inputBuffer between the .NET Framework probe and the native wrapper for /Hist-Integrated.ValCl. If schemas differ, IL 0x01AA NREs decisively. If schemas match, instrument IL 0x00ED via PsExec SYSTEM Frida or a signed Detours stub.", "ValidateClientCredentialSoapBodyComparisonResolved": true, "ValidateClientCredentialSoapBodyComparisonMethod": "WCF message logging (logEntireMessage=true, logMessagesAtTransportLevel=true) in NetFxWcfProbe.exe.config; capture under artifacts/reverse-engineering/netfx-wcf-probe-messages.svclog (gitignored, contains identity metadata).", "ValidateClientCredentialServerActualParameterNames": { "Param1": "handle", "Param2": "inBuff", "Param3": "outBuff", "Param4": "errorBuffer" }, "ValidateClientCredentialClientPreviousParameterNames": { "Param1": "handle", "Param2": "inputBuffer", "Param3": "outputBuffer", "Param4": "errorBuffer" }, "ValidateClientCredentialBugRootCause": "WCF builds the request body element name from the C# parameter name. The probe and SDK declared inputBuffer/outputBuffer; the AVEVA server expects inBuff/outBuff. Server WCF deserialiser ignores unknown element, leaving server arg.2 (inBuff) null. IL 0x01AA ldelema NREs, the C++/CLI catch handler returns native Type=4 Code=1 Failure with empty error buffer.", "ValidateClientCredentialFixApplied": "[MessageParameter(Name = \"inBuff\")] / Name = \"outBuff\" attributes added to NetFxWcfProbe contract and to src/AVEVA.Historian.Client/Wcf/Contracts/IHistoryServiceContract2.cs and IStorageServiceContract.cs ValidateClientCredential declarations.", "ValidateClientCredentialPostFixRound0": { "ServerSuccess": true, "ServerOutputLength": 239, "ServerOutputPrefixHex": "014e544c4d53535000020000001e001e003800000035c29ae2338a6d03cdfb9e", "ServerContinue": true, "NativeError": null, "MatchesDocumentedNative69To239ByteShape": true }, "ValidateClientCredentialPostFixRound1": { "ClientStatus": "Completed", "WrappedOutgoingLength": 93, "ServerSuccess": false, "ErrorLength": 100, "NativeErrorType": 129, "NativeErrorCodeHex": "0x80090308", "NativeErrorMeaning": "SEC_E_INVALID_TOKEN", "ErrorBufferDecodedAsciiContains": [ "aahClientAccessPoint::CServerContext::ProcessClientToken", "InitializeSecurityContext" ] }, "ValidateClientCredentialNextEvidenceTarget": "SEC_E_INVALID_TOKEN on round 1. Native traces showed InitializeSecurityContextW request flags 0x2081C first round and 0x81C later. NetFxWcfProbe SSPI wrapper uses defaults. Replicate the exact native flags and confirm the Negotiate target name matches NT SERVICE\\aahClientAccessPoint.", "ValidateClientCredentialSspiFlagFixApplied": true, "ValidateClientCredentialSspiFlagsRound0": "ISC_REQ_REPLAY_DETECT (0x4) | ISC_REQ_SEQUENCE_DETECT (0x8) | ISC_REQ_CONFIDENTIALITY (0x10) | ISC_REQ_CONNECTION (0x800) | ISC_REQ_IDENTIFY (0x20000) | ISC_REQ_ALLOCATE_MEMORY (0x100, kept for buffer convenience)", "ValidateClientCredentialSspiFlagsRound1Plus": "Same as Round 0 minus ISC_REQ_IDENTIFY", "ValidateClientCredentialSspiFlagsNativeReference": { "Round0": "0x2081C", "Round1Plus": "0x81C", "Source": "Existing native disassembly of CClientContext.AuthenticateClient at VA 0x180298F30" }, "ValidateClientCredentialSspiFlagPostFixRound0": { "ServerSuccess": true, "ServerOutputLength": 239, "ServerOutputPrefixHex": "014e544c4d53535000020000001e001e003800000035c29ae20c816c094fe20f", "ServerContinue": true, "NativeError": null }, "ValidateClientCredentialSspiFlagPostFixRound1": { "ServerSuccess": true, "ServerOutputLength": 1, "ServerOutputPrefixHex": "00", "ServerContinue": false, "NativeError": null, "MatchesDocumentedNativeOneByteTerminal": true }, "ValidateClientCredentialBlockerResolved": true, "ValidateClientCredentialResolvedDate": "2026-05-04", "ManagedValClChainNowReproducible": [ "Hist-Integrated.GetV → version 11", "Hist-Integrated.ValCl round 0 (69 → 239 bytes)", "Hist-Integrated.ValCl round 1 (93 → 1 byte terminal)" ], "ProductionSdkSspiTodo": "src/AVEVA.Historian.Client has no SSPI client yet. When the SDK auth flow is wired up, must use the same native-equivalent flags. .NET 10 NegotiateAuthentication does not expose ISC_REQ_* directly; P/Invoke InitializeSecurityContextW to set IDENTIFY + REPLAY_DETECT + SEQUENCE_DETECT explicitly. Reference implementation in tools/AVEVA.Historian.NetFxWcfProbe/Program.cs SspiClient.", "EndToEndChainVerified": true, "EndToEndChainVerifiedDate": "2026-05-04", "EndToEndChainSteps": [ {"Step": "Hist.GetV", "Result": "version 11"}, {"Step": "Hist.ValCl round 0", "Result": "239-byte server response (NTLM type-2 challenge)"}, {"Step": "Hist.ValCl round 1", "Result": "1-byte terminal"}, {"Step": "Hist.Open2", "Result": "42 bytes, version 0x03, transient /Retr client handle decoded"}, {"Step": "Retr.GetV", "Result": "version 4"}, {"Step": "Retr.IsOriginalAllowed(handle)", "Result": "return code 0, isAllowed=true"}, {"Step": "Retr.StartQuery2(handle, 1, 251 bytes, ...)", "Result": "Success=true, response 31 bytes, QueryHandlePresent=true, no error"} ], "EndToEndStartQuery2ResponseSha256": "4c062b5ce8181308f0f46bfd8c6088acb52e6ade94401651b7d3ccc8952edfb5", "EndToEndStartQuery2ResponseMatchesNativeCapture": true, "EndToEndAdditionalSdkContractFix": { "File": "src/AVEVA.Historian.Client/Wcf/Contracts/IRetrievalServiceContract2.cs", "Operations": ["StartQuery2", "GetNextQueryResultBuffer2", "EndQuery2"], "ServerNamesUsed": ["pRequestBuff", "pResponseBuff", "pResultBuff", "errSize", "err"], "ClientPreviousNames": ["requestBuffer", "responseBuffer", "resultBuffer", "errorSize", "errorBuffer"] }, "EndToEndReplayInputs": { "Open2RequestPath": "artifacts/reverse-engineering/openconnection3-request-replay.bin (1346 bytes; bytes 1..16 spliced with new managed context-key GUID)", "DataQueryRequestPath": "artifacts/reverse-engineering/startdataquery-request-replay.bin (251 bytes, OtOpcUaParityTest_001.Counter)", "Note": "Both inputs are gitignored under artifacts/. Probe stdout JSON only echoes lengths, SHAs, version bytes, and prefix hex; identity payloads stay in the binary inputs." }, "ProductionSdkRemainingWork": "Implement managed SSPI client for ValCl rounds, then wire ValCl → Open2 (using HistorianOpen2Protocol.SerializeNativeOpenConnection3Version6) → /Retr.StartQuery2 → /Retr.GetNextQueryResultBuffer2 for the production read path. Protocol now fully understood end-to-end for the read flow; remaining work is plumbing.", "ProductionSdkPlumbingLanded": true, "ProductionSdkPlumbingLandedDate": "2026-05-04", "ProductionSdkPlumbingFiles": [ "src/AVEVA.Historian.Client/AVEVA.Historian.Client.csproj (added System.ServiceModel.NetNamedPipe 10.0.652802)", "src/AVEVA.Historian.Client/Wcf/HistorianWcfBindingFactory.cs (added CreateMdasNetNamedPipeBinding + CreatePipeEndpointAddress, [SupportedOSPlatform(\"windows\")])", "src/AVEVA.Historian.Client/Wcf/HistorianSspiClient.cs (new — InitializeSecurityContextW with native flags 0x2081C / 0x81C)", "src/AVEVA.Historian.Client/Wcf/HistorianDataQueryProtocol.cs (added TryParseGetNextQueryResultBufferRows for raw rows + 5-byte terminal recognition)", "src/AVEVA.Historian.Client/Wcf/HistorianWcfReadOrchestrator.cs (new — chains GetV → ValCl×N → Open2 → Retr.IsOriginalAllowed → Retr.StartQuery2 → loop Retr.GetNextQueryResultBuffer2)", "src/AVEVA.Historian.Client/HistorianClientOptions.cs (added Transport, TargetSpn)", "src/AVEVA.Historian.Client/HistorianTransport.cs (new — LocalPipe / RemoteTcpIntegrated / RemoteTcpCertificate, only LocalPipe implemented this pass)", "src/AVEVA.Historian.Client/Models/HistorianSample.cs (added PercentGood)", "src/AVEVA.Historian.Client/Protocol/Historian2020ProtocolDialect.cs (constructor takes options; ReadRawAsync delegates to orchestrator on Windows + LocalPipe)" ], "ProductionSdkUnitTestsAdded": [ "HistorianSspiClientTests (5 flag-selection tests)", "WcfBindingFactoryTests (3 binding-shape tests)", "WcfDataQueryResultBufferTests (5 golden-byte parser tests using captured 570-byte fixture)" ], "ProductionSdkLiveIntegrationTest": { "Class": "HistorianClientIntegrationTests", "Method": "ReadRawAsync_AgainstLocalHistorian_ReturnsAtLeastOneRow", "GatedOn": ["HISTORIAN_HOST=localhost", "HISTORIAN_TEST_TAG", "OperatingSystem.IsWindows()"], "ResultWithEnvSet": "Pass — 69/69 tests pass including live read against local Historian.", "ResultWithoutEnvSet": "Skip cleanly; 64/64 pass." }, "ProductionSdkOpenConnection3Constants": { "ClientType": 4, "ConnectionMode": "0x402 (process integrated read-only)", "FormatVersion": 4, "HcalVersion": 17, "DataSourceId": "2020.406.2652.2", "ClientDllVersion": "2020.406.2652.2", "ClientCommonInfoClientVersion": 999999, "ShardId": "Guid.Empty", "CredentialBlockSize": 1026, "Open2RequestClientVersion": 9 }, "ProductionSdkReadPathWorking": true, "ProductionSdkReadPathDoesNotLoadAvevaBinaries": true, "ProductionSdkRemainingFollowUpWork": [ "Aggregate row layouts (Interpolated, TimeWeightedAverage) + ReadAggregateAsync wiring", "ReadAtTimeAsync wiring", "ReadEventsAsync wiring", "Remote TCP transport (RemoteTcpIntegrated, RemoteTcpCertificate)", "Explicit username/password auth (currently integrated-only)", "[MessageParameter] audit on EnsT / RTag2 / ExKey / StJb / GtJb (ildasm-confirmed parameter-name mismatches with current SDK; not blocking the read path)", "Decode trailing 34 bytes per row (likely contains StringValue placeholder + aggregate-EndTime slot)" ], "Phase2FollowUpsLanded": true, "Phase2FollowUpsLandedDate": "2026-05-04", "Phase2FollowUpsCompleted": [ {"Item": "[MessageParameter] audit", "FilesTouched": ["IHistoryServiceContract.cs", "IHistoryServiceContract2.cs", "IRetrievalServiceContract.cs", "IRetrievalServiceContract3.cs", "IRetrievalServiceContract4.cs"], "MismatchesFixed": 30}, {"Item": "Aggregate row parser", "Method": "HistorianDataQueryProtocol.TryParseGetNextQueryResultBufferAggregateRows", "WireLayout": "Same as raw rows; FILETIME #1 = EndTimeUtc, FILETIME at trailer offset 2 = StartTimeUtc; verified by live ReadAggregateAsync test"}, {"Item": "ReadAggregateAsync + ReadAtTimeAsync wiring", "Notes": "QueryType mapping: Full=2, Interpolated=3, TimeWeightedAverage=5, Cyclic=4. ReadAtTime uses one-tick Interpolated window per requested timestamp."}, {"Item": "Event flow", "Result": "StartEventQuery succeeds end-to-end; GetNextEventQueryResultBuffer returns native error type=4 code=85 (0x55) — new server response, treated as soft terminal. Likely needs RegisterTags2(CM_EVENT) prerequisite + event-row WCF wire format capture."}, {"Item": "Remote TCP transport", "FactoryMethod": "HistorianWcfBindingFactory.CreateBindingPair", "TransportMap": {"LocalPipe": "/Hist + /Retr over net.pipe", "RemoteTcpIntegrated": "/Hist-Integrated (Windows transport security) + /Retr (plain MDAS)", "RemoteTcpCertificate": "/HistCert (cert transport) + /Retr (plain MDAS)"}, "Status": "Wired but untested on this host"}, {"Item": "Explicit username/password auth", "Implementation": "HistorianSspiClient ctor overload builds SEC_WINNT_AUTH_IDENTITY (Unicode) and passes to AcquireCredentialsHandleW; auth chain helper parses DOMAIN\\user from HistorianClientOptions.UserName.", "Status": "Wired but untested on this host"} ], "Phase2LiveTestResults": { "EnvVarsSet": ["HISTORIAN_HOST=localhost", "HISTORIAN_TEST_TAG=OtOpcUaParityTest_001.Counter"], "TotalTests": 72, "PassedTests": 72, "LiveIntegrationTests": [ "ProbeAsync_ReturnsTrueForConfiguredHistorian", "BrowseTagNamesAsync_ReturnsConfiguredTestTag", "GetTagMetadataAsync_ReturnsConfiguredTestTagMetadata", "ReadRawAsync_AgainstLocalHistorian_ReturnsAtLeastOneRow", "ReadAggregateAsync_AgainstLocalHistorian_ReturnsTimeWeightedAverageRows", "ReadAtTimeAsync_AgainstLocalHistorian_ReturnsRequestedTimestamps", "ReadEventsAsync_AgainstLocalHistorian_DoesNotThrow" ] }, "Phase2OpenItems": [ "Decode event-row WCF wire format (no captured fixture yet)", "Investigate native error type=4 code=85 (0x55) terminal from GetNextEventQueryResultBuffer (likely missing RegisterTags2 CM_EVENT prerequisite)", "Verify RemoteTcpIntegrated / RemoteTcpCertificate against a remote Historian", "Verify explicit username/password auth against a non-current user account", "Add RetrievalMode mappings beyond Full/Interpolated/TimeWeightedAverage/Cyclic", "Decode trailing ~24 bytes of each row that vary across rows (possibly per-sample StringValue, source ID, or state metadata)" ], "EventFlowWcfWriteMessageCaptureBuilt20260504": { "ToolingAdded": "tools/AVEVA.Historian.ReverseEngineering instrument-wcf-writemessage CLI command + LogByteArraySegment helper in CaptureLogger.", "InstrumentationTarget": "aahMDASEncoder.ClientMessageEncoder.WriteMessage token 0x06005E65 — captures every outgoing WCF message body via ArraySegment.get_Array/get_Offset/get_Count.", "DnlibFix": "ArraySegment::get_Array MemberRef must use GenericVar(0) for return type, not concrete byte[]. Existing get_Count MemberRef in the method body is reusable for its DeclaringType (the generic instance ArraySegment TypeSpec).", "CaptureArtifact": "artifacts/reverse-engineering/instrumented-wcf-writemessage/writemessage-capture-event-latest.ndjson (27 records).", "EventFlowDecoded": [ {"Record": 0, "Action": "aa/Hist/GetV"}, {"Record": "1-2", "Action": "aa/Hist/GetI"}, {"Record": "3-4", "Action": "aa/Hist/ValCl", "Handle": "ValCl context key"}, {"Record": 5, "Action": "aa/Hist/Open2", "Length": 1472}, {"Record": "6-7", "Action": "unknown 105-byte calls"}, {"Record": "8-9", "Action": "unknown 211-byte calls — establish session GUID 6D332FCD-… used by subsequent operations"}, {"Record": 10, "Action": "aa/Hist/UpdC3", "Handle": "session GUID 6D332FCD-…"}, {"Record": "11-16", "Action": "6 unknown setup calls (183/185/188/192-byte)"}, {"Record": 17, "Action": "aa/Hist/RTag2", "Handle": "session GUID 6D332FCD-…"}, {"Record": 18, "Action": "unknown 184-byte"}, {"Record": 19, "Action": "aa/Trx/GetV"}, {"Record": 20, "Action": "unknown 105-byte"}, {"Record": 21, "Action": "aa/Retr/GetV"}, {"Record": 22, "Action": "aa/Hist/EnsT2", "Handle": "session GUID 6D332FCD-…", "PayloadLength": 83, "PayloadDecoded": true}, {"Record": 23, "Action": "aa/Retr/StartEventQuery"}, {"Record": 24, "Action": "aa/Retr/GetNextEventQueryResultBuffer"}, {"Record": 25, "Action": "aa/Retr/EndEventQuery"}, {"Record": 26, "Action": "aa/Hist/Close2"} ], "CtagMetadataLayoutCorrected": { "ActionUri": "aa/Hist/EnsT2 (NOT aa/Hist/AddT)", "Layout": "version(1)=0x03 + mask(2)=0x0086 + CDataType(1)=0x05 + tagId(16)=353b8145-5df0-4d46-a253-871aef49b321 + compactString(11)='CM_EVENT' + compactString(12)='AnE Event' + flags(7)=02 02 01 00 00 00 01 + uint(4)=0 + FILETIME(8) + commonEventTypeId(16)=5f59ae42-3bb6-4760-91a5-ab0be01f9f02 + tail(5)=2F 27 01 01 01", "TotalLength": 83, "PreviouslyDocumentedDifferences": [ "Action was thought to be AddT, actually EnsT2", "7-byte flags ended in 0x00 (wrong), captured ends in 0x01", "Order was FILETIME+flags+rate+deadband+GUID (wrong), actually flags+rate+FILETIME+GUID — no time deadband uint", "Common event type GUID was 5f59ae42-3bb6-4760-91a5-ab0be01f2f27 (wrong), actually 5f59ae42-3bb6-4760-91a5-ab0be01f9f02", "Tail was 0 bytes (wrong), actually 5 bytes 2F 27 01 01 01" ], "VerificationMethod": "SDK serializer reflection-invoked with captured FILETIME (0x01DCDB9447EA2578) returns 83 bytes byte-for-byte identical to captured native bytes." }, "WhyEventsStillReturnEmpty": "EnsT2 needs the session GUID established by records 8-9 as its handle. We pass storage session id from Open2 response (different value), so server returns false. Need to decode records 6-9 (unknown actions) and 11-16 (6 more unknown setup calls) before EnsT2 can succeed.", "RemainingDecode": "17 unknown WCF actions (records 6-9, 11-16, 18, 20). Each captured body is in the ndjson; ASCII inspection of each will reveal the action URI." }, "PriorEventFlowInvestigation20260504Followup": { "AddTwithCmEventCtagMetadataAttempt": { "Payload": "HistorianAddTagsProtocol.SerializeCmEventCTagMetadata cloned from reverse-engineering CLI BuildCommonArchestraEventTagMetadata: version=3, mask=0x0086, CDataType=5, tag id 353b8145-5df0-4d46-a253-871aef49b321, name CM_EVENT, description AnE Event, FILETIME UTC, storage type 2 + flags, common Archestra event type id 5f59ae42-3bb6-4760-91a5-ab0be01f2f27.", "Handle": "ClientHandle from OpenConnection3 v6 response (UInt32 LE at offset 1).", "ConnectionMode": "0x501 (event mode)", "ServerResponse": {"AddReturnCode": 76, "AddOutputLength": 0, "AddOutputCode0x": "0x4C"}, "Conclusion": "AddT now reaches the server (the WCF parameter-name fixes ensure pInBuff is parsed) but server rejects with native code 76. This code is not in the documented set (1/30/51/73/85/127/171). The chain still cannot read events because GetNextEventQueryResultBuffer returns code 85 (0x55).", "DiagnosticHelpers": [ "HistorianWcfEventOrchestrator.LastAddReturnCode (uint)", "HistorianWcfEventOrchestrator.LastAddOutputLength (int)", "HistorianWcfEventOrchestrator instance .LastResultBufferLength + .LastErrorBufferDescription", "EventChainDiagnosticTests.EventOrchestrator_DiagnosticDump_AgainstLocalHistorian prints all four" ], "ConcreteNextStep": "Instrument Wcf.AddT.Request on a successful native event harness run via the existing IL-rewrite pattern (clone instrument-starteventquery from tools/AVEVA.Historian.ReverseEngineering/Program.cs lines 1308-1367; replace target method/phase). Diff the captured payload byte-for-byte against HistorianAddTagsProtocol.SerializeCmEventCTagMetadata to identify the mismatch. Once AddT returns 0, capture Wcf.GetNextEventQueryResultBuffer.ResultBytes and write the event row parser." }, "PriorEventFlowInvestigation20260504": { "ConnectionModeChange": "Event orchestrator now sends ConnectionMode=0x501 (Event) instead of 0x402 (Process). Confirmed via native evidence 'SetConnectionMode(Event, integratedSecurity:true) yields connection mode 1281 (0x501)'.", "RegisterTags2AttemptResult": "All variants returned native error code=51 (InvalidParameter). Tested handle candidates: storageSessionId (upper/lower case GUID-D), contextKey (upper/lower case GUID-D). Body format: UInt32 count=1 + 16 bytes CM_EVENT GUID 353b8145-5df0-4d46-a253-871aef49b321.", "RegisterTags2Reverted": "Removed from event orchestrator; chain returns to silently treating server code 85 as soft terminal (empty events).", "ActualNativePrerequisite": "Per implementation-status.md lines 673-728, native CreateDefaultEventTag → AddTagInternal → HistorianClient.AddHistorianTag flow uses AddTags (AddT) on IHistoryServiceContract with a CTagMetadata payload (NOT RegisterTags2). CTagMetadata format: version(1) + optional-mask(2) + data-type-byte(1) + tag-id(16) + compact UTF-16 strings.", "CmEventIdentity": { "TagId": "353b8145-5df0-4d46-a253-871aef49b321", "EventTypeId": "5f59ae42-3bb6-4760-91a5-ab0be01f2f27", "CDataType": 10, "StorageType": 2, "Description": "AnE Event", "EngineeringUnit": "NONE" }, "DiagnosticHelper": "EventChainDiagnosticTests.EventOrchestrator_DiagnosticDump_AgainstLocalHistorian uses InternalsVisibleTo to call the orchestrator directly and prints LastResultBufferLength + LastErrorBufferDescription.", "SqlGroundTruth": "SELECT * FROM Runtime.dbo.Events confirms events exist in the test window; native harness returns 5 events; managed ReadEventsAsync currently returns 0 because of the missing AddT(CTagMetadata) prereq.", "NextEvidenceCapture": "Instrument Wcf.AddT.Request on a running NativeTraceHarness event scenario to capture exact CTagMetadata wire bytes." }} "ServerContractAuditedOtherOperationsWithLikelySameMismatch": [ {"Operation": "EnsT", "ServerNames": ["Handle","elementCount","InByteCount","InBuff","OutByteCount","OutBuff"], "ClientNames": ["handle","elementCount","inByteCount","inBuffer","outByteCount","outBuffer"]}, {"Operation": "EnsT2", "ServerNames": ["Handle","elementCount","InBuff","OutBuff","errorBuffer"], "ClientNames": ["handle","elementCount","inputBuffer","outputBuffer","errorBuffer"]}, {"Operation": "RTag2", "ServerNames": ["handle","ElementCount","pInBuff","outBuff","errorBuffer"], "ClientNames": ["handle","elementCount","inputBuffer","outputBuffer","errorBuffer"]}, {"Operation": "ExKey", "ServerNames": ["handle","inBuff","OutBuff","errorBuffer"], "ClientNames": ["handle","inputBuffer","outputBuffer","errorBuffer"]}, {"Operation": "StJb", "ServerNames": ["handle","jobBuffer","strJobid","errorBuffer"], "ClientNames": ["handle","jobBuffer","jobId","errorBuffer"]}, {"Operation": "GtJb", "ServerNames": ["handle","strJobid","jobstatus","errorBuffer"], "ClientNames": ["handle","jobId","jobStatus","errorBuffer"]} ], "ServerContractAuditFixDeferredReason": "Out of scope for the read-only SDK pass. Audit when those flows become required.", "ServerRuntimeValClProbeNativeReadBaselineRowFixture": { "TagKey": 238, "Value": 0, "Quality": 133, "OpcQuality": 192, "QualityDetail": 248, "PercentGood": 100 }, "ServerRuntimeValClProbeManagedValClRoundZero": { "Endpoint": "net.pipe://localhost/Hist", "Transport": "NamedPipeNone", "GetVersionReturnCode": 0, "InterfaceVersion": 11, "OutgoingTokenLength": 64, "WrappedOutgoingLength": 69, "WrappedOutgoingPrefixHex": "01400000004e544c4d5353500001000000b7b218e209000900370000000f000f", "ServerSuccess": false, "ServerOutputLength": 0, "ErrorLength": 5, "NativeErrorType": 4, "NativeErrorCode": 1, "NativeErrorName": "Failure" }, "ServerRuntimeValClProbeAlternativePathsConsidered": [ "PsExec -i -s SYSTEM-token frida (requires user consent for SYSTEM shell)", "Signed Detours instrumentation DLL trusted by local mitigation policy", "ETW providers Microsoft-Windows-Security-SSPICli/Negotiate/Kerberos filtered to PID for AcceptSecurityContext call/status visibility", "Inspect Get-ProcessMitigation -Name aahClientAccessPoint.exe and temporarily relax with explicit user consent" ], "ManagedLazyOpenAndSkipGetVersionStillFails": true, "Conclusion": "The successful integrated local read does not traverse the managed CHistoryConnectionWCF.ValidateClient or GetClientKey IL methods instrumented at tokens 0x06004044 and 0x06004041. It does call CHistoryConnectionWCF.ValidateClientCredential / ValCl with wrapped NTLM tokens. Runtime setup instrumentation shows the successful native path constructs CHistoryConnectionWCF, calls GetInterfaceVersion before auth, succeeds through its first InitializeProxy path, enters ConfigurePipeProxy with connection mode 1, and has a ready non-faulted proxy by both ValCl rounds. Static IL shows ConfigurePipeProxy explicitly uses NetNamedPipeSecurityMode.None, while SetIntegratedSecurity stores WindowsIdentity.GetCurrent through the managed-pointer tuple at +640/+600/+664 and GetInterfaceVersion impersonates it. Static IL shows both GetClientKey and ValidateClientCredential derive the WCF handle string by converting the contextKey argument to GUID text. Calling ExchangeKey with the same style of handle on the managed named-pipe path fails with native type 4/code 1 before ValCl, so a simple preceding ExchangeKey call is not the missing registration step. Static IL shows COperation.Start2 is a local operation-priority/bandwidth gate and does not call a WCF operation. Native disassembly shows CClientContext.AuthenticateClient creates the context GUID locally with UuidCreate, stores it at CClientContext +64, then passes that GUID through the ValCl virtual path. Server-side IL and disassembly show HistoryService.ValidateClientCredential parses that handle as a GUID, copies the ValCl byte array into a CServerBuffer, calls CServerNode.ProcessServerToken, and only registers the context handle after ProcessServerToken reaches the terminal round. ProcessServerToken parses the same AVEVA token envelope and calls Secur32 AcceptSecurityContext through helper VA 0x00505C00 after first-round context setup and lookup helpers. Managed replay now matches the native first wrapped token over both TCP and the local named-pipe /Hist path, but ValCl still rejects round 0 with native type 4/code 1, including when the managed calls run under the current Windows token and when the managed channel is created/opened under that impersonation scope. The nested CClientContext +16 buffers contain pointer-rich native state and no readable Historian payload, so the missing managed replay state is therefore the native wrapper/proxy/session state that makes server ProcessServerToken create and find the client-generated context key, not merely the transport, endpoint, Windows token, NTLM token envelope, ExchangeKey, channel impersonation, COperation.Start2, OpenConnection3, or an undecoded WCF request body." }, "Evidence": [ "Runtime instrumentation shows request bytes 1..16 exactly match CClientInfo +1240 in the same successful native OpenConnection3 run.", "Runtime instrumentation shows request byte 17 exactly matches CClientInfo +1608 and is 0 for the active content branch.", "CClientBase.ConfigureOpenConnection calls native CClientContext.AuthenticateClient on CClientBase +2112.", "After successful authentication, ConfigureOpenConnection copies 16 bytes from CClientBase +2176 to CClientBase +1480.", "CClientContext.GetContextKey returns CClientContext +64, so CClientBase +2176 is the context key location.", "Runtime instrumentation shows CClientBase +2176 equals the generated client key before AuthenticateClient, changes after AuthenticateClient, and then matches both the copied CClientInfo field and the OpenConnection3 request prefix.", "Native disassembly confirms CClientContext.AuthenticateClient is native-only. It calls UuidCreate, stores the GUID into CClientContext +64, calls AcquireCredentialsHandleW, then loops through an internal SSPI helper and the connection's ValidateClientCredential virtual method.", "The internal SSPI helper at VA 0x180298F30 calls InitializeSecurityContextW, uses request flags 0x2081C for the first round and 0x81C after that, and writes the native ValCl token envelope as round byte, UInt32 token length, then token bytes.", "The AuthenticateClient loop passes the CClientContext +64 GUID as the context key to the ValidateClientCredential virtual path. In the captured local read CClientContext +0x50 is zero, selecting the normal connection-object virtual call at VA 0x180298E95.", "Direct managed ValidateClient2 probing reached Hist-Integrated but returned native error type 4/code 51 before ExchangeKey.", "Sanitized instrumentation of CHistoryConnectionWCF.ValidateClient and GetClientKey emitted no records during a successful native integrated read, even though the instrumented DLL and logger smoke test were verified.", "Sanitized instrumentation of CHistoryConnectionWCF.ValidateClientCredential emitted two successful ValCl rounds: 69-byte client input to 239-byte server output, then 93-byte client input to one-byte terminal output.", "System-boundary SSPI instrumentation shows native auth calls AcquireCredentialsHandleW with package Negotiate, then two InitializeSecurityContextW calls targeting NT SERVICE\\aahClientAccessPoint. The raw SSPI output tokens are 64 and 88 bytes, which exactly account for the 69- and 93-byte ValCl bodies after the 5-byte AVEVA wrapper.", "IL-side CClientContext memory windows show successful AuthenticateClient mutates pointer-sized regions at offsets +8, +16, and +24, plus the context key at +64..+79. The +8 target contains SSPI/security-package metadata including Schannel, Microsoft Kerberos V1.0, TSSSP, System.Core, and Default TLS SSP. The +16 target contains pointer-rich nested state at offsets 0 and 8, with an all-zero target at offset 64; the nested targets have no readable ASCII or UTF-16 Historian payload strings in the captured windows. The +24 value is not safe to dereference as a direct buffer.", "The native first ValCl input is a wrapped NTLM type-1 token: one round byte, four-byte little-endian token length, then NTLMSSP bytes. The managed probe reproduces that first wrapped token hash after setting the NTLM VERSION negotiate flag.", "Standalone managed ValCl replay still fails with native error type 4/code 1 on both HistCert and Hist-Integrated, proving the missing piece is channel/session prerequisite state rather than the first token envelope.", "Skipping GetInterfaceVersion and avoiding explicit WCF channel open does not change the standalone managed ValCl failure.", "Successful local native auth setup constructs CHistoryConnectionWCF, then calls GetInterfaceVersion before ValCl.", "The first GetInterfaceVersion InitializeProxy path succeeds and SetManagedPtr leaves the proxy ready flag set before ValidateClientCredential runs.", "Object-window instrumentation shows GetInterfaceVersion populates the history proxy managed-pointer slot at CHistoryConnectionWCF +608 and ready flag +669. Between GetInterfaceVersion completion and ValCl entry, the binding managed-pointer slot at +616 is also populated.", "ValCl object-window instrumentation shows the parent CHistoryConnectionWCF window is stable across the two successful ValCl rounds, while the +608 history proxy target mutates at bytes 96-101. The +616 binding target and +640 Windows identity target are stable across both rounds.", "Static IL inspection of CHistoryConnectionWCF.Initialize shows it is client-side proxy setup: it calls InitializeProxy, stores the history proxy and binding through CServiceUtility.SetManagedPtr, then initializes the transaction proxy. The history InitializeProxy method has ConfigurePipeProxy at IL 0x0098 and ConfigureTcpProxy at IL 0x038E.", "The decompiled HistoryServiceContract interfaces contain no Initialize operation contract, so the native Initialize log line is not evidence for a missing WCF Initialize request before ValCl.", "A focused server-side Frida probe was added for ProcessServerToken, the context setup/lookup helpers, and the AcceptSecurityContext wrapper. The current non-elevated session could not inject into the long-running aahClientAccessPoint service, so runtime server-helper comparison remains pending an elevated capture.", "Branch instrumentation shows the local native path uses connection mode 1 and enters ConfigurePipeProxy, not ConfigureTcpProxy.", "The named-pipe ConfigurePipeProxy endpoint summary has length 25 with compression false, matching the local uncompressed /Hist pipe endpoint shape.", "Static IL inspection of CWcfConfig.ConfigurePipeProxy shows NetNamedPipeBinding.Security.Mode is set to None, with TransactionFlow false, native-sized buffers, and the aahMDASEncoder.ClientBinding wrapper.", "Static IL inspection of CWcfConfig.ConfigurePipeProxy shows the native path creates the pipe channel through ChannelFactory.CreateChannel(binding, endpoint) and sets IContextChannel.OperationTimeout from the timeout-minutes argument. Managed pipe probes using the static factory shape, with and without eager channel open, still fail ValCl round 0 with native type 4/code 1.", "Static IL inspection of CHistoryConnectionWCF.GetClientKey and ValidateClientCredential shows both methods build the WCF handle string from the contextKey argument via ToString(contextKey), producing 36-character GUID text before ExchangeKey or ValCl.", "Managed named-pipe probes that call ExchangeKey with the same generated handle before ValCl reach GetInterfaceVersion version 11, but ExchangeKey itself fails with native type 4/code 1 across default, static-channel, and lazy static-channel variants.", "Static IL inspection of CHistoryConnectionWCF.SetIntegratedSecurity shows integrated security is flag +540 and WindowsIdentity.GetCurrent is stored through offsets +640/+600/+664; GetInterfaceVersion later reads that tuple and calls WindowsIdentity.Impersonate.", "Managed named-pipe ValCl reaches GetInterfaceVersion version 11 and still fails at round 0 with native error type 4/code 1 despite matching the native first wrapped token.", "Running the managed named-pipe GetInterfaceVersion and ValCl calls under the current Windows token does not change the failure.", "Creating and opening the managed named-pipe channel under the current Windows impersonation token, with and without also wrapping the calls, still fails at ValCl round 0 with native type 4/code 1.", "Sanitized native handle summaries show uppercase GUID text; managed lowercase-handle replay still fails, so handle casing is not the mismatch.", "System Platform logs for the managed pipe probes show aahClientAccessPoint warning that ValidateClientCredential hit a NullReferenceException at HistoryService.cpp line 1593.", "Changing the managed named-pipe probe to transport security is rejected as a binding mismatch, so the local service expects the uncompressed no-security pipe binding shape.", "A direct .NET Framework WCF named-pipe probe with the aa/Hist contract and MDAS content type also reaches GetV version 11, matches the native first wrapped token, and fails ValCl round 0 with native type 4/code 1 plus the same server NullReferenceException.", "Server-side static IL shows HistoryService.ValidateClientCredential parses the WCF handle as a GUID, copies the ValCl byte array into a CServerBuffer, calls CServerNode.ProcessServerToken, and only adds the context GUID to its managed context-handle collection after ProcessServerToken reaches a terminal round.", "Server-side native disassembly shows CServerNode.ProcessServerToken parses the same ValCl envelope shape as the client: one round byte, a four-byte little-endian token length, then SSPI token bytes.", "On the first round, ProcessServerToken calls helper VA 0x0050FFC0 for keyed context setup, then helper VA 0x00517AB0 for context lookup. If lookup returns no context object, the server sets custom error code 0x29 before ValCl can progress.", "String decoding and disassembly identify the inserted native object as aahClientAccessPoint::CServerContext. The setup helper uses CServerNode +0xE80 as the lock and +0xE98 as the keyed map, logs Adding ServerContext 0x%p, constructs the context at VA 0x00505100, and inserts it through a red-black-tree helper at VA 0x0042F590.", "The credential helper calls AcquireCredentialsHandleW with the UTF-16 package string Negotiate. The server token-processing log name is aahClientAccessPoint::CServerContext::ProcessClientToken.", "The ProcessServerToken helper at VA 0x00505C00 calls Secur32 AcceptSecurityContext through import address 0x005A0340 and treats both success and SEC_I_CONTINUE_NEEDED (0x90312) as valid protocol progress.", "Server-side static IL shows HistoryService.ValidateIntegratedCredentials starts by reading ServiceSecurityContext.Current.WindowsIdentity, explaining earlier null-reference failures on bindings that did not populate ServiceSecurityContext.Current.", "Successful local native ValCl setup records show COperation.Start2 success with error type/code 0, existing proxy faulted false, and reconnect-required false.", "Static IL inspection of COperation.Start2 shows it calls only local operation-priority and bandwidth gates, setting local gate-failure error codes 243 or 150 when those fail. It does not call a WCF service operation.", "The same instrumented local native runs emit no CWcfConfig.ConfigureTcpProxy records, so the successful ValCl evidence is using the native GetInterfaceVersion pipe proxy setup path, not the standalone managed TCP proxy setup path.", "CClientInfo starts at CClientBase +240 on this path because CClientBase +1480 aligns with CClientInfo +1240." ], "Conclusion": "The OpenConnection3 prefix is not a fresh managed replay GUID. It is the client-generated context key stored by native CClientContext.AuthenticateClient at CClientContext +64, accepted during the native ValCl path, and copied into CClientInfo before serialization." }, "OpenConnection3RequestLayout": [ { "Offset": 0, "Field": "protocolVersion", "Encoding": "Byte", "Evidence": "Serializer writes 6 when the boolean selector argument is true; observed request starts with 0x06" }, { "Offset": 1, "Field": "authenticatedContextKey", "Encoding": "16 raw GUID bytes", "Evidence": "Loaded from CClientInfo +1240; same-run instrumentation proves it equals the key copied from CClientBase +2176 after CClientContext.AuthenticateClient" }, { "Offset": 17, "Field": "contentSelector", "Encoding": "Boolean byte", "Evidence": "Loaded from CClientInfo +1608; observed value is 0, selecting SerializeOpenConnectionInParams2Content" }, { "Offset": 18, "Field": "content", "Encoding": "OpenConnectionInParams2Content", "Evidence": "Host string, UInt16 secret length plus bytes, client type, connection mode, metadata namespace, two strings, then client common info" } ], "OpenConnection3ResponseLength": 42, "OpenConnection3ResponseSha256": "2bfb55d7a39bcfecf1658e013b85eb38f13acd85fba365db71922d791c8f075b", "OpenConnection3ResponseByte0": "0x03", "OpenConnection3ResponseClientHandleOffset": 1, "OpenConnection3ResponseClientHandleEncoding": "UInt32 little-endian", "OpenConnection3ResponseDeserializerToken": "0x06004008", "OpenConnection3ResponseDeserializer": "CClientInfo.DeserializeOpenConnectionOutParams", "OpenConnection3ResponseLayout": [ { "Offset": 0, "Field": "protocolVersion", "Encoding": "Byte", "Evidence": "Deserializer accepts version 2 or 3; observed response uses 3" }, { "Offset": 1, "Field": "clientHandle", "Encoding": "UInt32 little-endian", "Evidence": "Loaded into CClientInfo +1256" }, { "Offset": 5, "Field": "storageSessionId", "Encoding": "16 raw GUID bytes", "Evidence": "Loaded into CClientInfo +1260" }, { "Offset": 21, "Field": "connectTime", "Encoding": "Int64 FILETIME UTC", "Evidence": "Loaded into CClientInfo +1296" }, { "Offset": 29, "Field": "serverTime", "Encoding": "Int64 FILETIME UTC", "Evidence": "Loaded into CClientInfo +1312 when protocolVersion >= 3" }, { "Offset": 37, "Field": "trailingBytes", "Encoding": "5 bytes observed in the current 42-byte fixture", "Evidence": "Not read by CClientInfo.DeserializeOpenConnectionOutParams in the decoded IL window" } ], "OpenConnection3ErrorLength": 0, "CClientBaseSecondaryOpenSuccess": 1, "CClientBaseHandleAfterSecondaryOpen": "", "CClientCommonClientHandleForConnection": "", "WcfStartQuery2ClientHandle": "", "WcfStartQuery2ServerQueryHandle": "", "CClientCommonQueryHandleAfterCall": "" }, "ManagedReplay": { "RawArtifact": "artifacts/reverse-engineering/managed-native-v6-openconnection3", "Attempts": [ { "Name": "native-v6-openconnection3-integrated-windows-mode1026-hist-integrated", "Endpoint": "Hist-Integrated", "TransportSecurity": "Windows", "InputLength": 1348, "Success": false, "NativeError": { "Type": 132, "Code": 171, "Name": "AuthenticationFailed" }, "ServerMessage": "Failed to find server context; context GUID redacted" }, { "Name": "native-v6-openconnection3-cert-mode1026-histcert", "Endpoint": "HistCert", "TransportSecurity": "Certificate", "InputLength": 1348, "Success": false, "NativeError": { "Type": 132, "Code": 171, "Name": "AuthenticationFailed" }, "ServerMessage": "Failed to find server context; context GUID redacted" } ], "Conclusion": "After switching empty metadata to the compact CMetadataNamespace.Save layout, managed replay is parsed past packet-version validation. The server now fails while validating integrated credentials because the 16-byte OpenConnection3 prefix key has not been accepted by the server context table. The next evidence target is the native wrapper/proxy/session state that makes the server accept the client-generated context key during ValCl before OpenConnection3." }, "Conclusion": "The secondary open branch in CClientBase.OpenConnection is CHistoryConnectionWCF.OpenConnection3. OpenConnection3 calls IHistoryServiceContract2.OpenConnection2 with a 1346-byte request and receives a 42-byte response. The transient /Retr client handle is UInt32 little-endian at response offset 1, after byte 0x03. Deserializing that response initializes the vtable offset 24 handle later used by CClientCommon.StartQuery and /Retr.StartQuery2. The managed driver should now reproduce the OpenConnection3/OpenConnection2 envelope, not the older OpenConnection2 probe shape that failed." }