简体   繁体   English

C#NTLM哈希计算器

[英]C# NTLM Hash Calculator

I recently began learning C#. 我最近开始学习C#。 I tried to generate an NTLM hash in this language but I could't find a function to do this for me. 我尝试用这种语言生成一个NTLM哈希,但我找不到一个函数来为我做这个。 In python 3.x I would import hashlib and calculate it with hashlib.new("md4", "Hello, World!".encode("utf-16le")) . 在python 3.x中,我将导入hashlib并使用hashlib.new("md4", "Hello, World!".encode("utf-16le"))计算它hashlib.new("md4", "Hello, World!".encode("utf-16le"))

I searched through the Object Browser in C# but didn't find anything, the closest was a windows NTLM authentication class. 我在C#中搜索对象浏览器但没有找到任何内容,最接近的是Windows NTLM身份验证类。 I also searched Microsoft's docs and found hash calculators, but only for sha1 and md5. 我还搜索了微软的文档,发现了哈希计算器,但仅限于sha1和md5。

Is there a way to calculate an NTLM hash in C#? 有没有办法在C#中计算NTLM哈希? Can you please show me an example of how to do it, and I would prefer a short method to keep it simple. 你能告诉我一个如何做的例子,我更喜欢一个简短的方法来保持简单。

Thanks. 谢谢。

You can create an extension to the existing cryptography providers using Reflection to call CNG for MD4 (something .Net should probably either do, or make much easier): 您可以使用Reflection为CN4调用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);
        }
    }
}

Once you've done that, a couple of helper extensions will let you use it easily (I modified this to create a singleton so it doesn't have to do the work of reflecting/creating every time you use it): 一旦你完成了这个,一些帮助扩展将让你轻松使用它(我修改它来创建一个单例,所以它不必每次使用时都做反射/创建工作):

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")));
    }
}

Now you just call the extension methods on some sample data: 现在,您只需在某些示例数据上调用扩展方法:

void Main() {
    var input = "testing";

    var hash = input.MD4();
    var hashStr = hash.AsHexString();
    Console.WriteLine(hashStr);
}

I think you need to use the BouncyCastle to calculate the HASH, there is a .net porting that works quite well. 我认为你需要使用BouncyCastle来计算HASH,有一个非常好的.net移植。

and here is all the step to calculate the NTLM hash: https://asecuritysite.com/encryption/lmhash 以下是计算NTLM哈希的所有步骤: https//asecuritysite.com/encryption/lmhash

Code can be found at the end of the post here. 代码可以在帖子的末尾找到。 It uses BC for the MD4, as most MD4 implementations have a way to avid weak keys. 它使用BC作为MD4,因为大多数MD4实现都有一种方法可以使用弱密钥。 NTLM does not account weak keys, so you must be able to use them if they arise. NTLM不会考虑弱密钥,因此如果出现密钥,您必须能够使用它们。

https://markgamache.blogspot.com/2013/01/ntlm-challenge-response-is-100-broken.html https://markgamache.blogspot.com/2013/01/ntlm-challenge-response-is-100-broken.html

Here's a general solution to call CNG for any valid ALG_ID , based on the accepted answer above. 根据上面接受的答案,这是为CNG调用任何有效ALG_ID的一般解决方案。 Thank you NetMage! 谢谢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);
}

Create an instance with algID = 0x8002 for MD4. 为MD4创建一个algID = 0x8002的实例。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM