From 7c995f273c39f6fa31c2829a6406e67a6095e962 Mon Sep 17 00:00:00 2001 From: Rick Shaw Date: Thu, 31 Aug 2023 07:47:52 -0400 Subject: [PATCH 1/4] Added a static Boolean on the SocketOptions class to avoid using the opcode injection technique for reading the time stamp counter. --- src/NetMQ/Core/Utils/OpCode.cs | 2 ++ src/NetMQ/SocketOptions.cs | 10 ++++++++++ 2 files changed, 12 insertions(+) diff --git a/src/NetMQ/Core/Utils/OpCode.cs b/src/NetMQ/Core/Utils/OpCode.cs index 7228fcfc3..f2ae43658 100644 --- a/src/NetMQ/Core/Utils/OpCode.cs +++ b/src/NetMQ/Core/Utils/OpCode.cs @@ -11,6 +11,8 @@ internal static class Opcode public static bool Open() { + if (SocketOptions.DoNotUseRDTSC) + return false; #if NETSTANDARD1_1_OR_GREATER || NET471_OR_GREATER if (RuntimeInformation.ProcessArchitecture != Architecture.X86 && RuntimeInformation.ProcessArchitecture != Architecture.X64) diff --git a/src/NetMQ/SocketOptions.cs b/src/NetMQ/SocketOptions.cs index 38ed476d5..3844e3ca0 100644 --- a/src/NetMQ/SocketOptions.cs +++ b/src/NetMQ/SocketOptions.cs @@ -12,6 +12,16 @@ namespace NetMQ /// public class SocketOptions { + /// + /// If set, the time stamp counter is not read directly through opcode injection, + /// rather is used. + /// When false, the time stamp counter is read by allocating a few bytes on the heap with + /// read/write/execute privilege. OpCode is copied to this allocated memory and invoked to read + /// the time stamp counter, (which is a register available on most modern CPUs). While this is + /// an accurate way to read the time stamp counter, because it injects code onto the heap, this + /// can be detected as a malware technique by some anti-virus defenders. + /// + public static bool DoNotUseRDTSC; /// /// The NetMQSocket that this SocketOptions is referencing. /// From 285b77ed0c4286a979b2316dbd33803d17296f70 Mon Sep 17 00:00:00 2001 From: Rick Shaw Date: Wed, 6 Sep 2023 05:45:48 -0400 Subject: [PATCH 2/4] Removing the static flag on SocketOptions for avoidance of reading the Time Stamp Counter and altering the implementation to read an Environment variable. --- src/NetMQ/Core/Utils/OpCode.cs | 8 +++++++- src/NetMQ/SocketOptions.cs | 10 ---------- 2 files changed, 7 insertions(+), 11 deletions(-) diff --git a/src/NetMQ/Core/Utils/OpCode.cs b/src/NetMQ/Core/Utils/OpCode.cs index f2ae43658..a7f7a212b 100644 --- a/src/NetMQ/Core/Utils/OpCode.cs +++ b/src/NetMQ/Core/Utils/OpCode.cs @@ -11,7 +11,13 @@ internal static class Opcode public static bool Open() { - if (SocketOptions.DoNotUseRDTSC) + //Look for an environment variable: "NETQM_SUPPRESS_RDTSC" with a value of "TRUE" + // The application can set this environment variable when this code is running in a system where + // it is not desirable to read the processor's time stamp counter. + // While this is supported in modern CPUs, the technique used for allocating executable memory, copying OP Code + // for the read of the time stamp and invoking the OP Code can be detected as Malware by some anti-virus vendors. + var val = Environment.GetEnvironmentVariable("NETQM_SUPPRESS_RDTSC"); + if ("TRUE".Equals(val, StringComparison.OrdinalIgnoreCase)) return false; #if NETSTANDARD1_1_OR_GREATER || NET471_OR_GREATER if (RuntimeInformation.ProcessArchitecture != Architecture.X86 && diff --git a/src/NetMQ/SocketOptions.cs b/src/NetMQ/SocketOptions.cs index 3844e3ca0..38ed476d5 100644 --- a/src/NetMQ/SocketOptions.cs +++ b/src/NetMQ/SocketOptions.cs @@ -12,16 +12,6 @@ namespace NetMQ /// public class SocketOptions { - /// - /// If set, the time stamp counter is not read directly through opcode injection, - /// rather is used. - /// When false, the time stamp counter is read by allocating a few bytes on the heap with - /// read/write/execute privilege. OpCode is copied to this allocated memory and invoked to read - /// the time stamp counter, (which is a register available on most modern CPUs). While this is - /// an accurate way to read the time stamp counter, because it injects code onto the heap, this - /// can be detected as a malware technique by some anti-virus defenders. - /// - public static bool DoNotUseRDTSC; /// /// The NetMQSocket that this SocketOptions is referencing. /// From 6e9e93368228f3598e5587ad30d014467313d7e3 Mon Sep 17 00:00:00 2001 From: rickshaw5724 Date: Wed, 6 Sep 2023 18:28:37 -0400 Subject: [PATCH 3/4] Altered the environment variable read to accept any value, rather than just "true". Added a reference to the github issue. --- src/NetMQ/Core/Utils/OpCode.cs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/NetMQ/Core/Utils/OpCode.cs b/src/NetMQ/Core/Utils/OpCode.cs index a7f7a212b..df65abded 100644 --- a/src/NetMQ/Core/Utils/OpCode.cs +++ b/src/NetMQ/Core/Utils/OpCode.cs @@ -11,13 +11,14 @@ internal static class Opcode public static bool Open() { - //Look for an environment variable: "NETQM_SUPPRESS_RDTSC" with a value of "TRUE" + //Look for an environment variable: "NETQM_SUPPRESS_RDTSC" with any value // The application can set this environment variable when this code is running in a system where // it is not desirable to read the processor's time stamp counter. // While this is supported in modern CPUs, the technique used for allocating executable memory, copying OP Code // for the read of the time stamp and invoking the OP Code can be detected as Malware by some anti-virus vendors. - var val = Environment.GetEnvironmentVariable("NETQM_SUPPRESS_RDTSC"); - if ("TRUE".Equals(val, StringComparison.OrdinalIgnoreCase)) + // https://github.com/zeromq/netmq/issues/1071 + string val = Environment.GetEnvironmentVariable("NETQM_SUPPRESS_RDTSC"); + if (!string.IsNullOrEmpty(val)) return false; #if NETSTANDARD1_1_OR_GREATER || NET471_OR_GREATER if (RuntimeInformation.ProcessArchitecture != Architecture.X86 && From 743673acae899966e4f141f4701e451bd5555c89 Mon Sep 17 00:00:00 2001 From: rickshaw5724 Date: Wed, 6 Sep 2023 18:45:57 -0400 Subject: [PATCH 4/4] comment fixing --- src/NetMQ/Core/Utils/OpCode.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/NetMQ/Core/Utils/OpCode.cs b/src/NetMQ/Core/Utils/OpCode.cs index df65abded..060064c60 100644 --- a/src/NetMQ/Core/Utils/OpCode.cs +++ b/src/NetMQ/Core/Utils/OpCode.cs @@ -11,7 +11,7 @@ internal static class Opcode public static bool Open() { - //Look for an environment variable: "NETQM_SUPPRESS_RDTSC" with any value + // Look for an environment variable: "NETQM_SUPPRESS_RDTSC" with any value. // The application can set this environment variable when this code is running in a system where // it is not desirable to read the processor's time stamp counter. // While this is supported in modern CPUs, the technique used for allocating executable memory, copying OP Code