C# NTLM 哈希计算器
C# NTLM Hash Calculator
我最近开始学习 C#。我试图用这种语言生成一个 NTLM 散列,但找不到为我执行此操作的函数。在 python 3.x 中,我将导入 hashlib
并用 hashlib.new("md4", "Hello, World!".encode("utf-16le"))
计算它。
我在 C# 中搜索了对象浏览器,但没有找到任何东西,最接近的是 windows NTLM 身份验证 class。我还搜索了 Microsoft 的文档并找到了哈希计算器,但仅适用于 sha1 和 md5。
有没有办法在 C# 中计算 NTLM 哈希?你能告诉我一个如何做的例子吗,我更喜欢一个简短的方法来保持简单。
谢谢。
我认为你需要使用 BouncyCastle 来计算 HASH,有一个 .net 移植效果很好。
这里是计算 NTLM 哈希的所有步骤:
https://asecuritysite.com/encryption/lmhash
您可以使用反射为现有的加密提供程序创建一个扩展,为 MD4 调用 CNG(.Net 可能应该这样做,或者更容易):
namespace System.Security.Cryptography {
[System.Runtime.InteropServices.ComVisible(true)]
public abstract class MD4 : HashAlgorithm {
static MD4() {
CryptoConfig.AddAlgorithm(typeof(MD4CryptoServiceProvider), "System.Security.Cryptography.MD4");
}
protected MD4() {
HashSizeValue = 128;
}
new static public MD4 Create() {
return Create("System.Security.Cryptography.MD4");
}
new static public MD4 Create(string algName) {
return (MD4)CryptoConfig.CreateFromName(algName);
}
}
[System.Runtime.InteropServices.ComVisible(true)]
public sealed class MD4CryptoServiceProvider : MD4 {
internal static class Utils {
internal static Type UtilsType = Type.GetType("System.Security.Cryptography.Utils");
public static T InvokeInternalMethodOfType<T>(object o, object pType, string methodName, params object[] args) {
var internalType = (pType is string internalTypeName) ? Type.GetType(internalTypeName) : (Type)pType;
var internalMethods = internalType.GetMethods(BindingFlags.NonPublic | BindingFlags.FlattenHierarchy | (o == null ? BindingFlags.Static : 0));
var internalMethod = internalMethods.Where(m => m.Name == methodName && m.GetParameters().Length == args.Length).Single();
return (T)internalMethod?.Invoke(o, args);
}
public static T GetInternalPropertyValueOfInternalType<T>(object o, object pType, string propertyName) {
var internalType = (pType is string internalTypeName) ? Type.GetType(internalTypeName) : (Type)pType;
var internalProperty = internalType.GetProperty(propertyName, BindingFlags.NonPublic | (o == null ? BindingFlags.Static : 0));
return (T)internalProperty.GetValue(o);
}
internal static SafeHandle CreateHash(int algid) {
return InvokeInternalMethodOfType<SafeHandle>(null, UtilsType, "CreateHash", GetInternalPropertyValueOfInternalType<object>(null, UtilsType, "StaticProvHandle"), algid);
}
internal static void HashData(SafeHandle h, byte[] data, int ibStart, int cbSize) {
InvokeInternalMethodOfType<object>(null, UtilsType, "HashData", h, data, ibStart, cbSize);
}
internal static byte[] EndHash(SafeHandle h) {
return InvokeInternalMethodOfType<byte[]>(null, UtilsType, "EndHash", h);
}
}
internal const int ALG_CLASS_HASH = (4 << 13);
internal const int ALG_TYPE_ANY = (0);
internal const int ALG_SID_MD4 = 2;
internal const int CALG_MD4 = (ALG_CLASS_HASH | ALG_TYPE_ANY | ALG_SID_MD4);
[System.Security.SecurityCritical]
private SafeHandle _safeHashHandle = null;
[System.Security.SecuritySafeCritical]
public MD4CryptoServiceProvider() {
if (CryptoConfig.AllowOnlyFipsAlgorithms)
throw new InvalidOperationException("Cryptography_NonCompliantFIPSAlgorithm");
Contract.EndContractBlock();
// cheat with Reflection
_safeHashHandle = Utils.CreateHash(CALG_MD4);
}
protected override void Dispose(bool disposing) {
if (_safeHashHandle != null && !_safeHashHandle.IsClosed)
_safeHashHandle.Dispose();
base.Dispose(disposing);
}
public override void Initialize() {
if (_safeHashHandle != null && !_safeHashHandle.IsClosed)
_safeHashHandle.Dispose();
_safeHashHandle = Utils.CreateHash(CALG_MD4);
}
protected override void HashCore(byte[] rgb, int ibStart, int cbSize) {
Utils.HashData(_safeHashHandle, rgb, ibStart, cbSize);
}
protected override byte[] HashFinal() {
return Utils.EndHash(_safeHashHandle);
}
}
}
完成后,几个辅助扩展将使您轻松使用它(我修改了它以创建一个单例,因此它不必每次都执行 reflecting/creating 的工作使用它):
static class Ext {
public static HashAlgorithm MD4Singleton;
static Ext() {
MD4Singleton = System.Security.Cryptography.MD4.Create();
}
public static byte[] MD4(this string s) {
return MD4Singleton.ComputeHash(System.Text.Encoding.Unicode.GetBytes(s));
}
public static string AsHexString(this byte[] bytes) {
return String.Join("", bytes.Select(h => h.ToString("X2")));
}
}
现在您只需对一些示例数据调用扩展方法:
void Main() {
var input = "testing";
var hash = input.MD4();
var hashStr = hash.AsHexString();
Console.WriteLine(hashStr);
}
代码可以在 post 的末尾找到。它使用 BC 作为 MD4,因为大多数 MD4 实现都有一种获取弱密钥的方法。 NTLM 不考虑弱密钥,因此您必须能够在它们出现时使用它们。
https://markgamache.blogspot.com/2013/01/ntlm-challenge-response-is-100-broken.html
这是根据上面接受的答案为任何有效 ALG_ID
调用 CNG 的通用解决方案。谢谢 NetMage!
public class HashByID : HashAlgorithm {
static readonly Dictionary<int, int> hashSizes = new Dictionary<int,int>() { {0x8001,128},{0x8002,128},{0x8003,128},{0x8004,160},{0x8006,128},{0x8007,160},{0x800c,256},{0x800d,384},{0x800e,512}};
static readonly Type hUtils;
static readonly SafeHandle hStaticProv;
static readonly Func<SafeHandle, int, SafeHandle> fCreate;
static readonly Action<SafeHandle, byte[], int, int> fHash;
static readonly Func<SafeHandle, byte[]> fHashEnd;
public static bool inited;
public readonly int algID;
SafeHandle hh = null;
static HashByID() {
try {
hUtils = Type.GetType("System.Security.Cryptography.Utils");
hStaticProv = (SafeHandle)hUtils.GetProperty("StaticProvHandle", BindingFlags.NonPublic | BindingFlags.Static).GetValue(null, null);
fCreate = (Func<SafeHandle, int, SafeHandle>)hUtils.GetMethods(BindingFlags.NonPublic | BindingFlags.Static).Where(x => x.Name == "CreateHash" && x.GetParameters().Length == 2).Single().CreateDelegate(null, typeof(SafeHandle), typeof(int), typeof(SafeHandle));
fHash = (Action<SafeHandle, byte[], int, int>)hUtils.GetMethods(BindingFlags.NonPublic | BindingFlags.Static).Where(x => x.Name == "HashData" && x.GetParameters().Length == 4).Single().CreateDelegate(null, typeof(SafeHandle), typeof(byte[]), typeof(int), typeof(int));
fHashEnd = (Func<SafeHandle, byte[]>)hUtils.GetMethods(BindingFlags.NonPublic | BindingFlags.Static).Where(x => x.Name == "EndHash" && x.GetParameters().Length == 1).Single().CreateDelegate(null, typeof(SafeHandle), typeof(byte[]));
inited = true;
} catch { }
}
public HashByID(int algID) {
if (algID == 0x8009) algID = 0x8004; //map CALG_HMAC -> CALG_SHA1
this.algID = algID;
hashSizes.TryGetValue(algID, out HashSizeValue);
Initialize();
}
protected override void Dispose(bool disposing) {
if (hh != null && !hh.IsClosed) hh.Dispose();
base.Dispose(disposing);
}
public override void Initialize() {
if (hh != null && !hh.IsClosed) hh.Dispose();
hh = fCreate(hStaticProv, algID);
}
protected override void HashCore(byte[] data, int ofs, int len) {
fHash(hh, data, ofs, len);
}
protected override byte[] HashFinal() {
return fHashEnd(hh);
}
}
//Delegate creation helper
public static Delegate CreateDelegate(this MethodInfo methodInfo, object target, params Type[] custTypes) {
Func<Type[], Type> getType;
bool isAction = methodInfo.ReturnType.Equals((typeof(void))), cust = custTypes.Length > 0;
Type[] types = cust ? custTypes : methodInfo.GetParameters().Select(p => p.ParameterType).ToArray();
if (isAction) getType = Expression.GetActionType;
else {
getType = Expression.GetFuncType;
if (!cust) types = types.Concat(new[] { methodInfo.ReturnType }).ToArray();
}
if (cust) {
int i, nargs = types.Length - (isAction ? 0 : 1);
var dm = new DynamicMethod(methodInfo.Name, isAction ? typeof(void) : types.Last(), types.Take(nargs).ToArray(), typeof(object), true);
var il = dm.GetILGenerator();
for (i = 0; i < nargs; i++)
il.Emit(OpCodes.Ldarg_S, i);
il.Emit(OpCodes.Call, methodInfo);
il.Emit(OpCodes.Ret);
if (methodInfo.IsStatic) return dm.CreateDelegate(getType(types));
return dm.CreateDelegate(getType(types), target);
}
if (methodInfo.IsStatic) return Delegate.CreateDelegate(getType(types), methodInfo);
return Delegate.CreateDelegate(getType(types), target, methodInfo.Name);
}
为 MD4 创建一个 algID = 0x8002
的实例。
我最近开始学习 C#。我试图用这种语言生成一个 NTLM 散列,但找不到为我执行此操作的函数。在 python 3.x 中,我将导入 hashlib
并用 hashlib.new("md4", "Hello, World!".encode("utf-16le"))
计算它。
我在 C# 中搜索了对象浏览器,但没有找到任何东西,最接近的是 windows NTLM 身份验证 class。我还搜索了 Microsoft 的文档并找到了哈希计算器,但仅适用于 sha1 和 md5。
有没有办法在 C# 中计算 NTLM 哈希?你能告诉我一个如何做的例子吗,我更喜欢一个简短的方法来保持简单。
谢谢。
我认为你需要使用 BouncyCastle 来计算 HASH,有一个 .net 移植效果很好。
这里是计算 NTLM 哈希的所有步骤: https://asecuritysite.com/encryption/lmhash
您可以使用反射为现有的加密提供程序创建一个扩展,为 MD4 调用 CNG(.Net 可能应该这样做,或者更容易):
namespace System.Security.Cryptography {
[System.Runtime.InteropServices.ComVisible(true)]
public abstract class MD4 : HashAlgorithm {
static MD4() {
CryptoConfig.AddAlgorithm(typeof(MD4CryptoServiceProvider), "System.Security.Cryptography.MD4");
}
protected MD4() {
HashSizeValue = 128;
}
new static public MD4 Create() {
return Create("System.Security.Cryptography.MD4");
}
new static public MD4 Create(string algName) {
return (MD4)CryptoConfig.CreateFromName(algName);
}
}
[System.Runtime.InteropServices.ComVisible(true)]
public sealed class MD4CryptoServiceProvider : MD4 {
internal static class Utils {
internal static Type UtilsType = Type.GetType("System.Security.Cryptography.Utils");
public static T InvokeInternalMethodOfType<T>(object o, object pType, string methodName, params object[] args) {
var internalType = (pType is string internalTypeName) ? Type.GetType(internalTypeName) : (Type)pType;
var internalMethods = internalType.GetMethods(BindingFlags.NonPublic | BindingFlags.FlattenHierarchy | (o == null ? BindingFlags.Static : 0));
var internalMethod = internalMethods.Where(m => m.Name == methodName && m.GetParameters().Length == args.Length).Single();
return (T)internalMethod?.Invoke(o, args);
}
public static T GetInternalPropertyValueOfInternalType<T>(object o, object pType, string propertyName) {
var internalType = (pType is string internalTypeName) ? Type.GetType(internalTypeName) : (Type)pType;
var internalProperty = internalType.GetProperty(propertyName, BindingFlags.NonPublic | (o == null ? BindingFlags.Static : 0));
return (T)internalProperty.GetValue(o);
}
internal static SafeHandle CreateHash(int algid) {
return InvokeInternalMethodOfType<SafeHandle>(null, UtilsType, "CreateHash", GetInternalPropertyValueOfInternalType<object>(null, UtilsType, "StaticProvHandle"), algid);
}
internal static void HashData(SafeHandle h, byte[] data, int ibStart, int cbSize) {
InvokeInternalMethodOfType<object>(null, UtilsType, "HashData", h, data, ibStart, cbSize);
}
internal static byte[] EndHash(SafeHandle h) {
return InvokeInternalMethodOfType<byte[]>(null, UtilsType, "EndHash", h);
}
}
internal const int ALG_CLASS_HASH = (4 << 13);
internal const int ALG_TYPE_ANY = (0);
internal const int ALG_SID_MD4 = 2;
internal const int CALG_MD4 = (ALG_CLASS_HASH | ALG_TYPE_ANY | ALG_SID_MD4);
[System.Security.SecurityCritical]
private SafeHandle _safeHashHandle = null;
[System.Security.SecuritySafeCritical]
public MD4CryptoServiceProvider() {
if (CryptoConfig.AllowOnlyFipsAlgorithms)
throw new InvalidOperationException("Cryptography_NonCompliantFIPSAlgorithm");
Contract.EndContractBlock();
// cheat with Reflection
_safeHashHandle = Utils.CreateHash(CALG_MD4);
}
protected override void Dispose(bool disposing) {
if (_safeHashHandle != null && !_safeHashHandle.IsClosed)
_safeHashHandle.Dispose();
base.Dispose(disposing);
}
public override void Initialize() {
if (_safeHashHandle != null && !_safeHashHandle.IsClosed)
_safeHashHandle.Dispose();
_safeHashHandle = Utils.CreateHash(CALG_MD4);
}
protected override void HashCore(byte[] rgb, int ibStart, int cbSize) {
Utils.HashData(_safeHashHandle, rgb, ibStart, cbSize);
}
protected override byte[] HashFinal() {
return Utils.EndHash(_safeHashHandle);
}
}
}
完成后,几个辅助扩展将使您轻松使用它(我修改了它以创建一个单例,因此它不必每次都执行 reflecting/creating 的工作使用它):
static class Ext {
public static HashAlgorithm MD4Singleton;
static Ext() {
MD4Singleton = System.Security.Cryptography.MD4.Create();
}
public static byte[] MD4(this string s) {
return MD4Singleton.ComputeHash(System.Text.Encoding.Unicode.GetBytes(s));
}
public static string AsHexString(this byte[] bytes) {
return String.Join("", bytes.Select(h => h.ToString("X2")));
}
}
现在您只需对一些示例数据调用扩展方法:
void Main() {
var input = "testing";
var hash = input.MD4();
var hashStr = hash.AsHexString();
Console.WriteLine(hashStr);
}
代码可以在 post 的末尾找到。它使用 BC 作为 MD4,因为大多数 MD4 实现都有一种获取弱密钥的方法。 NTLM 不考虑弱密钥,因此您必须能够在它们出现时使用它们。
https://markgamache.blogspot.com/2013/01/ntlm-challenge-response-is-100-broken.html
这是根据上面接受的答案为任何有效 ALG_ID
调用 CNG 的通用解决方案。谢谢 NetMage!
public class HashByID : HashAlgorithm {
static readonly Dictionary<int, int> hashSizes = new Dictionary<int,int>() { {0x8001,128},{0x8002,128},{0x8003,128},{0x8004,160},{0x8006,128},{0x8007,160},{0x800c,256},{0x800d,384},{0x800e,512}};
static readonly Type hUtils;
static readonly SafeHandle hStaticProv;
static readonly Func<SafeHandle, int, SafeHandle> fCreate;
static readonly Action<SafeHandle, byte[], int, int> fHash;
static readonly Func<SafeHandle, byte[]> fHashEnd;
public static bool inited;
public readonly int algID;
SafeHandle hh = null;
static HashByID() {
try {
hUtils = Type.GetType("System.Security.Cryptography.Utils");
hStaticProv = (SafeHandle)hUtils.GetProperty("StaticProvHandle", BindingFlags.NonPublic | BindingFlags.Static).GetValue(null, null);
fCreate = (Func<SafeHandle, int, SafeHandle>)hUtils.GetMethods(BindingFlags.NonPublic | BindingFlags.Static).Where(x => x.Name == "CreateHash" && x.GetParameters().Length == 2).Single().CreateDelegate(null, typeof(SafeHandle), typeof(int), typeof(SafeHandle));
fHash = (Action<SafeHandle, byte[], int, int>)hUtils.GetMethods(BindingFlags.NonPublic | BindingFlags.Static).Where(x => x.Name == "HashData" && x.GetParameters().Length == 4).Single().CreateDelegate(null, typeof(SafeHandle), typeof(byte[]), typeof(int), typeof(int));
fHashEnd = (Func<SafeHandle, byte[]>)hUtils.GetMethods(BindingFlags.NonPublic | BindingFlags.Static).Where(x => x.Name == "EndHash" && x.GetParameters().Length == 1).Single().CreateDelegate(null, typeof(SafeHandle), typeof(byte[]));
inited = true;
} catch { }
}
public HashByID(int algID) {
if (algID == 0x8009) algID = 0x8004; //map CALG_HMAC -> CALG_SHA1
this.algID = algID;
hashSizes.TryGetValue(algID, out HashSizeValue);
Initialize();
}
protected override void Dispose(bool disposing) {
if (hh != null && !hh.IsClosed) hh.Dispose();
base.Dispose(disposing);
}
public override void Initialize() {
if (hh != null && !hh.IsClosed) hh.Dispose();
hh = fCreate(hStaticProv, algID);
}
protected override void HashCore(byte[] data, int ofs, int len) {
fHash(hh, data, ofs, len);
}
protected override byte[] HashFinal() {
return fHashEnd(hh);
}
}
//Delegate creation helper
public static Delegate CreateDelegate(this MethodInfo methodInfo, object target, params Type[] custTypes) {
Func<Type[], Type> getType;
bool isAction = methodInfo.ReturnType.Equals((typeof(void))), cust = custTypes.Length > 0;
Type[] types = cust ? custTypes : methodInfo.GetParameters().Select(p => p.ParameterType).ToArray();
if (isAction) getType = Expression.GetActionType;
else {
getType = Expression.GetFuncType;
if (!cust) types = types.Concat(new[] { methodInfo.ReturnType }).ToArray();
}
if (cust) {
int i, nargs = types.Length - (isAction ? 0 : 1);
var dm = new DynamicMethod(methodInfo.Name, isAction ? typeof(void) : types.Last(), types.Take(nargs).ToArray(), typeof(object), true);
var il = dm.GetILGenerator();
for (i = 0; i < nargs; i++)
il.Emit(OpCodes.Ldarg_S, i);
il.Emit(OpCodes.Call, methodInfo);
il.Emit(OpCodes.Ret);
if (methodInfo.IsStatic) return dm.CreateDelegate(getType(types));
return dm.CreateDelegate(getType(types), target);
}
if (methodInfo.IsStatic) return Delegate.CreateDelegate(getType(types), methodInfo);
return Delegate.CreateDelegate(getType(types), target, methodInfo.Name);
}
为 MD4 创建一个 algID = 0x8002
的实例。