吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 144|回复: 1
收起左侧

[经验求助] 代码转换或者生成可用DLL等

[复制链接]
jki500 发表于 2026-3-12 22:06
500吾爱币
以下是从win11 x64版获取 pidgenx.dll获取代码,下面代码是使用GetkeyData调用读取rdi内存数据获取

[C#] 纯文本查看 复制代码
using Reloaded.Hooks;
using Reloaded.Hooks.Definitions;
using Reloaded.Hooks.Definitions.Enums;
using Reloaded.Memory.Utilities;
using System;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;

// 移除多余的 Reloaded.Hooks.Definitions 引用(4.3 无需,避免冲突)
class Program
{
    #region 1. 原生P/Invoke委托与API定义(无修改,适配Winapi)
    [UnmanagedFunctionPointer(CallingConvention.Winapi, CharSet = CharSet.Unicode)]
    public delegate int GetPKeyDataDelegate(
        string productKey,
        IntPtr formatArg,
        string skuOrChannel,
        IntPtr formatArg2,
        int flags,
        out IntPtr outDataBlob,
        out IntPtr outString1,
        out IntPtr outString2,
        out IntPtr outString3,
        int extraFlag
    );

    [UnmanagedFunctionPointer(CallingConvention.Winapi)]
    public unsafe delegate long Sub_7FFBB9DBF60CDelegate(
        IntPtr a1,
        IntPtr a2,
        IntPtr a3,
        IntPtr a4,     // volatile int*
        IntPtr lpMem   // const wchar_t**(核心解析目标)
    );

    [DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
    static extern IntPtr LoadLibrary(string lpFileName);

    [DllImport("kernel32.dll", CharSet = CharSet.Ansi, SetLastError = true)]
    static extern IntPtr GetProcAddress(IntPtr hModule, string lpProcName);

    [DllImport("kernel32.dll")]
    static extern IntPtr GetProcessHeap();

    [DllImport("kernel32.dll")]
    static extern bool HeapFree(IntPtr hHeap, int flags, IntPtr mem);

    [DllImport("kernel32.dll", SetLastError = true)]
    static extern bool FreeLibrary(IntPtr hModule);
    #endregion

    #region 2. Hook核心配置(基址+固定偏移量,全局Hook实例)

    private const int HOOK_OFFSET = 0x2F924; // ← 正确的 mov rdi,[rbp-41] // 你的固定偏移量0x2F60C

    //===================使用asmhook========================
    private static IAsmHook _asmHook;
    private static ReloadedHooks _hooksInstance;
    private static IntPtr _callbackPtr;
    private static IntPtr hMod = IntPtr.Zero;
    //===================使用asmhook========================

    #endregion

    static void Main()
    {
        string productKey = "VD6RP-R2NK7-HBG8F-3DJ8T-KTPKM";
        string pkeyConfigXml = AppDomain.CurrentDomain.BaseDirectory + "pkconfig_winNext.xrm-ms";
        hMod = IntPtr.Zero;
        IntPtr pkeyConfigPtr = IntPtr.Zero;
        NativeState.LastMsftPtr = Marshal.AllocHGlobal(8);
        Marshal.WriteInt64(NativeState.LastMsftPtr, 0);

        try
        {
            // 加载pidgenx.dll并获取基址
            hMod = LoadLibrary("pidgenx.dll");
            if (hMod == IntPtr.Zero)
            {
                Console.WriteLine($"❌ 加载pidgenx.dll失败,错误码:0x{Marshal.GetLastWin32Error():X8}");
                return;
            }
            Console.WriteLine($"✅ pidgenx.dll 64位加载基址:0x{hMod.ToString("X16")}");

            // 动态计算Hook地址(核心:基址 + 固定偏移量,适配ASLR)
            IntPtr hookAddress = IntPtr.Add(hMod, HOOK_OFFSET);
            Console.WriteLine($"✅ 动态计算Hook实际地址:0x{hookAddress.ToString("X16")}(基址+0x{HOOK_OFFSET:X})");

            Console.WriteLine($"[+] LastMsftPtr(native) = 0x{NativeState.LastMsftPtr.ToInt64():X16}");

            // 3️⃣ 创建 AsmHook
            InstallAsmHook(hookAddress.ToInt64());

            // 初始化GetPKeyData委托,执行原始逻辑
            IntPtr fnGetPKeyData = GetProcAddress(hMod, "GetPKeyData");
            if (fnGetPKeyData == IntPtr.Zero)
            {
                Console.WriteLine($"❌ 获取GetPKeyData地址失败,错误码:0x{Marshal.GetLastWin32Error():X8}");
                return;
            }
            var getPKeyData = Marshal.GetDelegateForFunctionPointer<GetPKeyDataDelegate>(fnGetPKeyData);

            // 准备参数并执行GetPKeyData
            pkeyConfigPtr = Marshal.StringToHGlobalUni(pkeyConfigXml);
            IntPtr outBlob = IntPtr.Zero, outStr1 = IntPtr.Zero, outStr2 = IntPtr.Zero, outStr3 = IntPtr.Zero;

            Console.WriteLine("\n&#128204; 按任意键执行GetPKeyData,Hook将自动拦截并解析数据...");
            Console.ReadKey();

            int hr = getPKeyData(
                productKey,
                pkeyConfigPtr,
                null,
                IntPtr.Zero,
                0,
                out outBlob,
                out outStr1,
                out outStr2,
                out outStr3,
                0
            );

            // 输出GetPKeyData执行结果
            if (hr >= 0)
            {
                Console.WriteLine("\n&#9989; GetPKeyData执行成功,原始返回结果:");
                Console.WriteLine($"outStr1密钥描述: {Marshal.PtrToStringUni(outStr1) ?? "空"}");
                Console.WriteLine($"outStr2密钥通道: {Marshal.PtrToStringUni(outStr2) ?? "空"}");
                Console.WriteLine($"outStr3密钥子类型: {Marshal.PtrToStringUni(outStr3) ?? "空"}");
                Console.WriteLine($"outBlobIID唯一标识: {Marshal.PtrToStringUni(outBlob) ?? "空"}");
            }
            else
            {
                Console.WriteLine($"\n&#10060; GetPKeyData执行失败,错误码:0x{hr:X8}");
            }
            IntPtr msftPtr = Marshal.ReadIntPtr(NativeState.LastMsftPtr);

            if (msftPtr != IntPtr.Zero)
            {
                string s = Marshal.PtrToStringUni(msftPtr);
                Console.WriteLine($"[AdtConfigKeg:] {s}");
            }


            // 释放GetPKeyData返回的堆内存
            IntPtr heap = GetProcessHeap();
            if (outStr1 != IntPtr.Zero) HeapFree(heap, 0, outStr1);
            if (outStr2 != IntPtr.Zero) HeapFree(heap, 0, outStr2);
            if (outStr3 != IntPtr.Zero) HeapFree(heap, 0, outStr3);
            if (outBlob != IntPtr.Zero) HeapFree(heap, 0, outBlob);
        }
        catch (Exception ex)
        {
            Console.WriteLine($"\n&#10060; 程序全局异常:{ex.Message}\n{ex.StackTrace}");
        }
        finally
        {
            // 安全释放所有资源,避免泄漏
            if (_asmHook != null && _asmHook.IsEnabled)
            {
                _asmHook?.Disable();
                Console.WriteLine("\n&#9989; Reloaded.Hooks 4.3 已安全释放");
            }
            Marshal.FreeHGlobal(NativeState.LastMsftPtr);
            if (pkeyConfigPtr != IntPtr.Zero) Marshal.FreeHGlobal(pkeyConfigPtr);
            if (hMod != IntPtr.Zero) FreeLibrary(hMod); // 释放DLL句柄
            Console.WriteLine("&#9989; 所有资源已释放完毕,按任意键退出...");
            Console.ReadKey();
        }
    }
    private static void InstallAsmHook(long hookAddress)
    {
        /*
         * 栈布局说明:
         * - push 8 个非易失寄存器 = 64 字节
         * - sub rsp, 20h         = shadow space
         *
         * 原始 RSP = 当前 rsp + 20h + 8*8
         */
        var asm = new[]
        {
            "use64",

            // rdi = msft2009 wchar_t*
            $"mov rax, {NativeState.LastMsftPtr.ToInt64()}",
            "mov [rax], rdi",
        };


        _hooksInstance = new ReloadedHooks();

        _asmHook = _hooksInstance.CreateAsmHook(
            asm,
            hookAddress,
            AsmHookBehaviour.ExecuteFirst
        ).Activate();

        Console.WriteLine("[+] AsmHook 激活成功");
    }

    static class NativeState
    {
        public static IntPtr LastMsftPtr;
    }

}




以下是从x86版获取 ProductKeyUtilities.dll 获取代码,另外此版还可调用pidgenx偏移hook传入参数也可获取,下面代码是使用GetkeyData调用读取rdi内存数据获取

[C#] 纯文本查看 复制代码
using System;
using System.IO;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
using Reloaded.Hooks;
using Reloaded.Hooks.Definitions;
// 必须导入:FunctionAttribute/Registers 所在命名空间(修复特性缺失的核心)
using Reloaded.Hooks.Definitions.X86;

namespace 密钥检测关键字符串Hook
{
    class Program
    {
        #region 核心配置(保持你的偏移0xA981,统一注释说明)
        private const string TARGET_DLL = "ProductKeyUtilities.dll";          // 目标系统DLL
        private const int GET_PKEYDATA_HOOK_OFFSET = 0xA981;                  // Hook偏移:GetPKeyData+0xA981(对应sub_7BBCA981)
        private const int VALID_HOOK_CALL_COUNT = 2;                          // 有效拦截次数:第三次调用
        private const string TARGET_MATCH_STR = "msft2009";                   // 目标匹配字符串
        private const string TEST_PRODUCT_KEY = "VK7JG-NPHTM-C97JM-9MPGT-3V66T"; // 测试产品密钥
        #endregion

        #region 1. GetPKeyData原生函数委托(StdCall,无修改)
        [UnmanagedFunctionPointer(CallingConvention.StdCall, CharSet = CharSet.Unicode)]
        private delegate int DelegateGetPKeyData(
            string ProductKey,
            string PkeyConfigPath,
            string MPCID,
            string pwszPKeyAlgorithm,
            IntPtr OemId,
            IntPtr OtherId,
            out string IID,
            out string Description,
            out string channel,
            out string subType,
            StringBuilder PID
        );
        #endregion

        #region 2. 【核心修复】sub_7BBCA981 Hook委托(添加FunctionAttribute,适配__fastcall)
        // 保留UnmanagedFunctionPointer,适配.NET Marshal封送
        [Function(CallingConventions.Fastcall)]
        private delegate int HookTargetFuncDelegate(int a1, int a2); // 原生:int __fastcall sub_7BBCA981(int a1, int a2)
        #endregion

        #region 全局变量(Hook实例/委托/模块句柄/调用计数器,无修改)
        private static IHook<HookTargetFuncDelegate> _hookTargetFunc; // Hook实例(4.3.3泛型版)
        private static DelegateGetPKeyData _nativeGetPKeyData;        // GetPKeyData原生委托
        private static IntPtr _hModule = IntPtr.Zero;                 // 目标DLL模块句柄
        private static int _hookCallCount = 0;                        // Hook调用计数器(线程安全)
        #endregion

        static void Main(string[] args)
        {
            Console.WriteLine("===== ProductKeyUtilities.dll Hook & Call 开始 =====");
            try
            {
                // 步骤1:加载目标DLL,获取模块句柄
                _hModule = LoadLibrary(TARGET_DLL);
                if (_hModule == IntPtr.Zero)
                {
                    PrintError($"加载{TARGET_DLL}失败", Marshal.GetLastWin32Error());
                    return;
                }
                Console.WriteLine($"&#9989; 加载{TARGET_DLL}成功,模块基址:0x{_hModule.ToString("X8")}");

                // 步骤2:获取GetPKeyData导出函数地址,封送为C#委托
                IntPtr getPKeyDataAddr = GetProcAddress(_hModule, "GetPKeyData");
                if (getPKeyDataAddr == IntPtr.Zero)
                {
                    PrintError($"获取GetPKeyData地址失败", Marshal.GetLastWin32Error());
                    FreeLibrary(_hModule);
                    return;
                }
                _nativeGetPKeyData = Marshal.GetDelegateForFunctionPointer<DelegateGetPKeyData>(getPKeyDataAddr);
                Console.WriteLine($"&#9989; 获取GetPKeyData地址成功:0x{getPKeyDataAddr.ToString("X8")}");

                // 步骤3:【核心修复】计算正确Hook地址(GetPKeyData函数地址 + 偏移,而非模块基址+偏移)
                IntPtr hookTargetAddr = IntPtr.Add(_hModule, GET_PKEYDATA_HOOK_OFFSET);
                Console.WriteLine($"&#9989; 计算Hook目标地址成功sub_7BBCA981 [GetPKeyData+{GET_PKEYDATA_HOOK_OFFSET:X4}]:0x{hookTargetAddr.ToString("X8")}");

                // 步骤4:创建并启用Hook(Reloaded.Hooks 4.3.3标准写法,无修改)
                var hookFactory = new ReloadedHooks();
                _hookTargetFunc = hookFactory.CreateHook<HookTargetFuncDelegate>(
                    HookedGetPKeyData_981,
                    hookTargetAddr.ToInt64()
                );
                _hookTargetFunc.Activate();
                Console.WriteLine($"&#9989; sub_7BBCA981 Hook启用成功,等待调用触发...\n");

                // 步骤5:调用GetPKeyData原生函数,触发Hook拦截(无修改)
                CallGetPKeyData();

                // 步骤6:卸载Hook,恢复原生函数逻辑(4.3.3版本核心:Disable())
                _hookTargetFunc?.Disable();
                Console.WriteLine($"\n&#9989; Hook已禁用,恢复原生sub_7BBCA981执行逻辑");
            }
            catch (Exception ex)
            {
                Console.WriteLine($"&#10060; 程序执行异常:{ex.Message}\n{ex.StackTrace}");
            }
            finally
            {
                // 最终释放所有非托管资源(优化:避免重复Disable())
                if (_hookTargetFunc != null)
                {
                    try { _hookTargetFunc.Disable(); } catch { }
                }
                if (_hModule != IntPtr.Zero) FreeLibrary(_hModule);
                Console.WriteLine($"\n&#9989; 所有非托管资源已释放,程序执行完成");
            }

            Console.WriteLine("\n按任意键退出程序...");
            Console.ReadKey();
        }
        static int count = 0;
        #region Hook拦截函数(匹配2个int参数,无修改)
        private static int HookedGetPKeyData_981(int a1, int a2)
        {
            IntPtr pA1 = (IntPtr)a1;
            IntPtr pA2 = (IntPtr)a2;

            // 1&#65039;&#8419; 直接检测 a1
            if (TryPrintIfMatch(pA1, "a1 (ECX)"))
                return _hookTargetFunc.OriginalFunction(a1, a2);

            // 2&#65039;&#8419; 检测 a2
            if (TryPrintIfMatch(pA2, "a2 (EDX)"))
                return _hookTargetFunc.OriginalFunction(a1, a2);

            // 3&#65039;&#8419; 检测 a1 + 0x14
            if (pA1 != IntPtr.Zero)
            {
                try
                {
                    IntPtr pExt = Marshal.ReadIntPtr(pA1, 0x14);
                    if (TryPrintIfMatch(pExt, "a1 + 0x14"))
                        return _hookTargetFunc.OriginalFunction(a1, a2);
                }
                catch { }
            }

            // 4&#65039;&#8419; 什么都没命中 → 静默放行
            return _hookTargetFunc.OriginalFunction(a1, a2);
        }
        private static bool TryPrintIfMatch(IntPtr ptr, string tag)
        {
            if (ptr == IntPtr.Zero)
                return false;

            // 地址基本合法性校验(32位)
            long addr = ptr.ToInt64();
            if (addr < 0x10000 || addr > 0x7FFFFFFF)
                return false;

            // 内存可读性探测
            if (IsBadReadPtr(ptr, 2))
                return false;

            if (!TryReadUnicodeString(ptr, 256, out var str))
                return false;

            if (string.IsNullOrEmpty(str))
                return false;

            foreach (var key in TARGET_KEYS)
            {
                if (str.IndexOf(key, StringComparison.OrdinalIgnoreCase) >= 0)
                {
                    Console.WriteLine("======================================");
                    Console.WriteLine($"&#128293; 命中关键字符串:{key}");
                    Console.WriteLine($"&#128205; 来源:{tag}");
                    Console.WriteLine($"&#128204; 地址:0x{ptr.ToString("X8")}");
                    string clean = TrimToReadableUnicode(str);
                    Console.WriteLine($"&#129534; 内容:{clean}");
                    Console.WriteLine($"&#128207; 字符串长度:{clean.Length}");
                    Console.WriteLine("======================================\n");
                    return true;
                }
            }

            return false;
        }
        private static readonly string[] TARGET_KEYS =
        {
            "msft2009",
            "msft2005"
        };
        private static string TrimToReadableUnicode(string input)
        {
            if (string.IsNullOrEmpty(input))
                return input;

            var sb = new StringBuilder(input.Length);

            foreach (char c in input)
            {
                // 合法可读字符范围
                if (c == '\0')
                    break;

                if (c >= 0x20 && c <= 0x7E ||   // ASCII
                    c >= 0x4E00 && c <= 0x9FFF) // CJK
                {
                    sb.Append(c);
                }
                else
                {
                    break; // 一旦进入二进制,直接截断
                }
            }

            return sb.ToString();
        }
        private static bool TryReadUnicodeString(
    IntPtr ptr,
    int maxChars,
    out string result)
        {
            result = null;

            if (ptr == IntPtr.Zero)
                return false;

            long addr = ptr.ToInt64();
            if (addr < 0x10000 || addr > 0x7FFFFFFF)
                return false;

            var sb = new StringBuilder();

            for (int i = 0; i < maxChars; i++)
            {
                IntPtr cur = IntPtr.Add(ptr, i * 2);

                // 每次只探测 2 字节(一个 WCHAR)
                if (IsBadReadPtr(cur, 2))
                    break;

                char c;
                try
                {
                    c = (char)Marshal.ReadInt16(cur);
                }
                catch
                {
                    break;
                }

                if (c == '\0')
                    break;

                sb.Append(c);
            }

            if (sb.Length == 0)
                return false;

            result = sb.ToString();
            return true;
        }


        #endregion

        #region GetPKeyData调用逻辑(无修改,已修复PID=null问题)
        private static void CallGetPKeyData()
        {
            Console.WriteLine("==================== 开始调用GetPKeyData ====================");
            string productKey = TEST_PRODUCT_KEY;
            string configPath = Path.Combine(Environment.CurrentDirectory, "pkconfig_winNext.xrm-ms");
            StringBuilder pidSb = new StringBuilder(512);
            string iid = null, description = null, channel = null, subType = null;

            if (!File.Exists(configPath))
            {
                Console.WriteLine($"&#10060; 配置文件不存在:{configPath}");
                Console.WriteLine($"提示:请将pkconfig_winNext.xrm-ms放在程序运行目录下");
                return;
            }

            try
            {
                int retCode = _nativeGetPKeyData(
                    productKey, configPath, null, null, IntPtr.Zero, IntPtr.Zero,
                    out iid, out description, out channel, out subType, pidSb
                );

                if (retCode == 0)
                {
                    Console.WriteLine("&#9989; GetPKeyData调用成功,结构化数据如下:");
                    Console.WriteLine($"产品密钥:{productKey}");
                    Console.WriteLine($"IID唯一标识:{iid ?? "空"}");
                    Console.WriteLine($"密钥描述:{description ?? "空"}");
                    Console.WriteLine($"密钥通道:{channel ?? "空"}");
                    Console.WriteLine($"密钥子类型:{subType ?? "空"}");
                    Console.WriteLine($"PID标识码:{pidSb.ToString() ?? "空"}");
                }
                else
                {
                    PrintError($"GetPKeyData调用失败,返回码", retCode);
                    PrintError($"系统底层错误码", Marshal.GetLastWin32Error());
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine($"&#10060; 调用GetPKeyData异常:{ex.Message}");
            }
            finally
            {
                FreeNativeOutString(iid);
                FreeNativeOutString(description);
                FreeNativeOutString(channel);
                FreeNativeOutString(subType);
            }
            Console.WriteLine("===============================================================");
        }
        #endregion

        #region 辅助方法(无修改)
  
        // 辅助函数:用系统API探测内存是否可读
        [DllImport("kernel32.dll")]
        private static extern bool IsBadReadPtr(IntPtr lp, uint ucb);


        private static void FreeNativeOutString(string str)
        {
            if (!string.IsNullOrEmpty(str))
            {
                try
                {
                    IntPtr strPtr = Marshal.StringToHGlobalUni(str);
                    Marshal.FreeCoTaskMem(strPtr);
                }
                catch { }
            }
        }

        private static void PrintError(string msg, int errorCode)
        {
            Console.WriteLine($"&#10060; {msg}:0x{errorCode:X8}(十进制:{errorCode})");
        }
        #endregion

        #region Kernel32.dll API导入(无修改)
        [DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
        private static extern IntPtr LoadLibrary(string lpFileName);

        [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Ansi)]
        private static extern IntPtr GetProcAddress(IntPtr hModule, string lpProcName);

        [DllImport("kernel32.dll", SetLastError = true)]
        private static extern bool FreeLibrary(IntPtr hModule);
        #endregion
    }
}




以下是xml构建

[C#] 纯文本查看 复制代码
        private const string AtoReqTemplate = @"<?xml version=""1.0"" encoding=""utf-8""?>
<soap:Envelope
    xmlns:soapenc=""http://schemas.xmlsoap.org/soap/encoding/""
    xmlns:soap=""http://schemas.xmlsoap.org/soap/envelope/""
    xmlns:xsd=""http://www.w3.org/2001/XMLSchema""
    xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance"">
    <soap:Body>
        <RequestSecurityToken
            xmlns=""http://schemas.xmlsoap.org/ws/2004/04/security/trust"">
            <TokenType>ProductActivation</TokenType>
            <RequestType>http://schemas.xmlsoap.org/ws/2004/04/security/trust/Issue</RequestType>
            <UseKey>
                <Values
                    xmlns:q1=""http://schemas.xmlsoap.org/ws/2004/04/security/trust"" soapenc:arrayType=""q1:TokenEntry[1]"">
                    <TokenEntry>
                        <Name>PublishLicense</Name>
                        <Value>{plxml}</Value>
                    </TokenEntry>
                </Values>
            </UseKey>
            <Claims>
                <Values
                    xmlns:q1=""http://schemas.xmlsoap.org/ws/2004/04/security/trust"" soapenc:arrayType=""q1:TokenEntry[14]"">
                    <TokenEntry>
                        <Name>BindingType</Name>
                        <Value>msft:rm/algorithm/hwid/4.0</Value>
                    </TokenEntry>
                    <TokenEntry>
                        <Name>Binding</Name>
                        <Value>{binding}</Value>
                    </TokenEntry>
                    <TokenEntry>
                        <Name>ProductKey</Name>
                        <Value>{pkey}</Value>
                    </TokenEntry>
                    <TokenEntry>
                        <Name>ProductKeyType</Name>
                        <Value>msft:rm/algorithm/pkey/2009</Value>
                    </TokenEntry>
                    <TokenEntry>
                        <Name>ProductKeyActConfigId</Name>
                        <Value>{act_config_id}</Value>
                    </TokenEntry>
                    <TokenEntry>
                        <Name>otherInfoPublic.licenseCategory</Name>
                        <Value>msft:sl/EUL/ACTIVATED/PUBLIC</Value>
                    </TokenEntry>
                    <TokenEntry>
                        <Name>otherInfoPrivate.licenseCategory</Name>
                        <Value>msft:sl/EUL/ACTIVATED/PRIVATE</Value>
                    </TokenEntry>
                    <TokenEntry>
                        <Name>otherInfoPublic.sysprepAction</Name>
                        <Value>rearm</Value>
                    </TokenEntry>
                    <TokenEntry>
                        <Name>otherInfoPrivate.sysprepAction</Name>
                        <Value>rearm</Value>
                    </TokenEntry>
                    <TokenEntry>
                        <Name>ClientInformation</Name>
                        <Value>SystemUILanguageId=1033;UserUILanguageId=1033;GeoId=244</Value>
                    </TokenEntry>
                    <TokenEntry>
                        <Name>ClientSystemTime</Name>
                        <Value>{systime}</Value>
                    </TokenEntry>
                    <TokenEntry>
                        <Name>ClientSystemTimeUtc</Name>
                        <Value>{utctime}</Value>
                    </TokenEntry>
                    <TokenEntry>
                        <Name>otherInfoPublic.secureStoreId</Name>
                        <Value>{secure_store_id}</Value>
                    </TokenEntry>
                    <TokenEntry>
                        <Name>otherInfoPrivate.secureStoreId</Name>
                        <Value>{secure_store_id}</Value>
                    </TokenEntry>
                </Values>
            </Claims>
        </RequestSecurityToken>
    </soap:Body>
</soap:Envelope>";

var actConfigId = Utils.XmlEscape($"actConfigId_byhook");  //我们hook到的那串字符串
var ProductKeyType = string.IsNullOrEmpty(actConfigId)? "msft:rm/algorithm/pkey/2009" : actConfigId.Contains("2009")? "msft:rm/algorithm/pkey/2009":"msft:rm/algorithm/pkey/2005";
var now = DateTime.Now;
var timestamp = Utils.FormatTimestamp(now);
var secureStoreId = Guid.NewGuid().ToString();
var binding = Utils.GenerateBinding();
// 检查 PL 是否已经转义过
string processedPl;
if (plXmlPublishLicense.StartsWith("<"))
{
    // 如果已经转义过,直接使用,不要再调用 XmlEscape
    processedPl = plXmlPublishLicense;
}
else
{
    // 如果是原始 XML,则进行转义
    processedPl = Utils.XmlEscape(plXmlPublishLicense);
}

var payload = AtoReqTemplate
     .Replace("{plxml}", processedPl)  //PublishLicense xml , 自己实机测试个密钥抓包提取,可采用固定值,注意同时配合服务器接口
    .Replace("{binding}", binding) //硬件信息,可固定也可随机
    .Replace("{pkey}", pkey)   //密钥
    .Replace("{act_config_id}", actConfigId)  //我们hook到的那串字符串
    .Replace("{systime}", timestamp)  //本地时间(ISO 8601格式,带Z标识)
    .Replace("{utctime}", timestamp)  //utc时间(ISO 8601格式,带Z标识)
    .Replace("{secure_store_id}", secureStoreId);  //guid
    .Replace("{ProductKeyType}", ProductKeyType);  //actconfigid 类型2009或2005
    
//  httpclient 请求接口和 请求参数,自己抓包

//随机硬件
public static string GenerateBinding()
{
    // 16进制转字节数组
    var fixedBytes = HexStringToBytes("2A0000000100020001000100000000000000010001000100");

    // 生成18位随机字节(.NET 4.8 写法)
    var randomBytes = new byte[18];
    using (var rng = RandomNumberGenerator.Create())
    {
        rng.GetBytes(randomBytes);
    }

    // 拼接固定字节和随机字节
    var binding = new byte[fixedBytes.Length + randomBytes.Length];
    Buffer.BlockCopy(fixedBytes, 0, binding, 0, fixedBytes.Length);
    Buffer.BlockCopy(randomBytes, 0, binding, fixedBytes.Length, randomBytes.Length);

    return Convert.ToBase64String(binding);
}



以下是msf2009 actconfigid算法
[C#] 纯文本查看 复制代码
using System;
using System.Collections.Generic;
using System.Numerics;

public class ProductKeyDecoder
{
    public const string ALPHABET = "BCDFGHJKMPQRTVWXY2346789";

    // 静态查找表:将字符直接映射到数值,避免 IndexOf 的 O(n) 搜索
    private static readonly sbyte[] CharTable = new sbyte[128];
    static ProductKeyDecoder()
    {
        for (int i = 0; i < 128; i++) CharTable[i] = -1;
        for (int i = 0; i < ALPHABET.Length; i++) CharTable[ALPHABET[i]] = (sbyte)i;
    }

    public BigInteger Key { get; }
    public long Group { get; }
    public long Serial { get; }
    public BigInteger Security { get; }
    public int Upgrade { get; }

    public ProductKeyDecoder(string key)
    {
        Key = Decode5x5(key);

        // 位域解析(严格遵循 20, 30, 53, 1 的分布)
        Group = (long)(Key & 0xFFFFF); // 20 bits
        Serial = (long)((Key >> 20) & 0x3FFFFFFF); // 30 bits
        Security = (Key >> 50) & ((BigInteger.One << 53) - 1); // 53 bits
        Upgrade = (int)((Key >> 103) & 1); // 1 bit
    }

    public static BigInteger Decode5x5(string key)
    {
        string normalized = key.Replace("-", "").ToUpper();
        if (normalized.Length != 25) throw new FormatException("Key must be 25 characters.");

        // 必须严格保持顺序:N 对应的值作为第一个被计算的元素
        int nIndex = normalized.IndexOf('N');
        string dataPart = normalized.Replace("N", "");

        BigInteger result = (BigInteger)nIndex; // N 的位置先入栈

        foreach (char c in dataPart)
        {
            sbyte val = (c < 128) ? CharTable[c] : (sbyte)-1;
            if (val == -1) throw new FormatException($"Invalid character: {c}");

            // 核心算法:result = result * 24 + value
            result = BigInteger.Add(BigInteger.Multiply(result, 24), (int)val);
        }

        return result;
    }

    public static string EncodeKeyData(long group, long serial, BigInteger security, int upgrade)
    {
        // 严格按照你原始逻辑中的位移重新拼装
        // 1 (upgrade) | 30 (serial) | 20 (group) | 53 (security)
        BigInteger actHash = (BigInteger)(upgrade & 1);
        actHash |= (BigInteger)(serial & 0x3FFFFFFF) << 1;
        actHash |= (BigInteger)(group & 0xFFFFF) << 31;
        actHash |= (security & ((BigInteger.One << 53) - 1)) << 51;

        byte[] bytes = actHash.ToByteArray();

        // 修正:确保输出固定为 13 字节,且不丢失数据
        byte[] result = new byte[13];
        int copyLen = Math.Min(bytes.Length, 13);
        Array.Copy(bytes, result, copyLen);

        return Convert.ToBase64String(result);
    }
}

public class ProductKeyDecoder2
{
    public const string ALPHABET = "BCDFGHJKMPQRTVWXY2346789";

    public BigInteger Key { get; }
    public BigInteger Group { get; }
    public BigInteger Serial { get; }
    public BigInteger Security { get; }
    public BigInteger Upgrade { get; }

    public ProductKeyDecoder2(string key)
    {
        Key = Decode5x5(key, ALPHABET);

        // 位域解析(实测正确)
        Group = Key & ((BigInteger.One << 20) - 1);
        Serial = (Key >> 20) & ((BigInteger.One << 30) - 1);
        Security = (Key >> 50) & ((BigInteger.One << 53) - 1);
        Upgrade = (Key >> 103) & 1;
    }

    /// <summary>
    /// 修复后的5x5密钥解码逻辑(符合微软原版算法)
    /// </summary>
    public static BigInteger Decode5x5(string key, string alphabet)
    {
        key = key.Replace("-", "");

        var dec = new List<int> { key.IndexOf('N') };
        foreach (var l in key.Replace("N", ""))
        {
            dec.Add(alphabet.IndexOf(l));
        }

        BigInteger result = 0;
        foreach (var x in dec)
        {
            result = (result * 24) + x;
        }
        return result;
    }

    /// <summary>
    /// 修复后的密钥数据编码逻辑(修正字节序)
    /// </summary>
    public static string EncodeKeyData(BigInteger group, BigInteger serial, BigInteger security, BigInteger upgrade)
    {
        BigInteger actHash = upgrade & 1;
        actHash |= (serial & ((1UL << 30) - 1)) << 1;
        actHash |= (group & ((1UL << 20) - 1)) << 31;
        actHash |= (security & ((1UL << 53) - 1)) << 51;

        byte[] bytes = actHash.ToByteArray();
        Array.Resize(ref bytes, 13);
        return Convert.ToBase64String(bytes);
    }
}


public class ProductKeyDecoder3
{
    public const string ALPHABET = "BCDFGHJKMPQRTVWXY2346789";

    private static readonly sbyte[] CharTable = new sbyte[128];
    static ProductKeyDecoder3()
    {
        // 修复:手动循环初始化,兼容所有 .NET 版本
        for (int i = 0; i < CharTable.Length; i++)
        {
            CharTable[i] = -1;
        }

        for (int i = 0; i < ALPHABET.Length; i++)
        {
            CharTable[ALPHABET[i]] = (sbyte)i;
        }
    }

    public BigInteger Key { get; }
    public int Group { get; }
    public int Serial { get; }
    public BigInteger Security { get; }
    public int Upgrade { get; }

    public ProductKeyDecoder3(string key)
    {
        if (string.IsNullOrEmpty(key)) throw new ArgumentNullException(nameof(key));

        Key = Decode5x5(key);

        // 位域解析
        Group = (int)(Key & 0xFFFFF);
        Serial = (int)((Key >> 20) & 0x3FFFFFFF);
        Security = (Key >> 50) & ((BigInteger.One << 53) - 1);
        Upgrade = (int)((Key >> 103) & 1);
    }

    public static BigInteger Decode5x5(string key)
    {
        // 兼容性优化:老版本 .NET 不支持 AsSpan,使用普通的字符串操作
        string normalized = key.Replace("-", "").ToUpper();
        if (normalized.Length != 25) throw new FormatException("密钥长度必须为 25 位");

        int nIndex = normalized.IndexOf('N');
        // 如果有 N,移除它以进行 Base24 转换
        string dataPart = nIndex != -1 ? normalized.Replace("N", "") : normalized;

        // N 的位置作为高位权重初始化
        BigInteger result = nIndex != -1 ? (BigInteger)nIndex : BigInteger.Zero;

        foreach (char c in dataPart)
        {
            sbyte val = (c < 128) ? CharTable[c] : (sbyte)-1;
            if (val == -1) throw new FormatException($"密钥包含非法字符: {c}");

            result = result * 24 + val;
        }

        return result;
    }

    public static string EncodeKeyData(int group, int serial, BigInteger security, int upgrade)
    {
        BigInteger actHash = (BigInteger)(upgrade & 1);
        actHash |= (BigInteger)(serial & 0x3FFFFFFF) << 1;
        actHash |= (BigInteger)(group & 0xFFFFF) << 31;
        actHash |= (security & ((BigInteger.One << 53) - 1)) << 51;

        byte[] rawBytes = actHash.ToByteArray();

        // 确保输出 13 字节缓冲区
        byte[] fixedBuffer = new byte[13];
        int bytesToCopy = Math.Min(rawBytes.Length, 13);
        Array.Copy(rawBytes, 0, fixedBuffer, 0, bytesToCopy);

        return Convert.ToBase64String(fixedBuffer);
    }
}

class Program
{
    static void Main()
    {
        string key = "MT6QD-N6YPG-K7CG9-TCYFJ-HMH26";
        var d = new ProductKeyDecoder(key);
        Console.WriteLine("Key:      " + d.Key);
        Console.WriteLine("Group:    " + d.Group);    // 正确输出3308
        Console.WriteLine("Serial:   " + d.Serial);
        Console.WriteLine("Security: " + d.Security);
        Console.WriteLine("Upgrade:  " + d.Upgrade);
        string strbase64 = ProductKeyDecoder.EncodeKeyData(d.Group, d.Serial, d.Security, d.Upgrade);
        Console.WriteLine("Base64:   " + strbase64); // 正确输出hHe2EXYGGMG+BH8FWw==
        Console.WriteLine();
        //=============================
        var d2 = new ProductKeyDecoder2(key);
        Console.WriteLine("Key:      " + d2.Key);
        Console.WriteLine("Group:    " + d2.Group);    // 正确输出3308
        Console.WriteLine("Serial:   " + d2.Serial);
        Console.WriteLine("Security: " + d2.Security);
        Console.WriteLine("Upgrade:  " + d2.Upgrade);
        string strbase64_2 = ProductKeyDecoder2.EncodeKeyData(d2.Group, d2.Serial, d2.Security, d2.Upgrade);
        Console.WriteLine("Base64:   " + strbase64_2); // 正确输出hHe2EXYGGMG+BH8FWw==
        Console.WriteLine();
        //==============================

        var d3 = new ProductKeyDecoder3(key);
        Console.WriteLine("Key:      " + d3.Key);
        Console.WriteLine("Group:    " + d3.Group);    // 正确输出3308
        Console.WriteLine("Serial:   " + d3.Serial);
        Console.WriteLine("Security: " + d3.Security);
        Console.WriteLine("Upgrade:  " + d3.Upgrade);

        string strbase64_3 = ProductKeyDecoder3.EncodeKeyData(d3.Group, d3.Serial, d3.Security, d3.Upgrade);
        Console.WriteLine("Base64:   " + strbase64_3); // 正确输出hHe2EXYGGMG+BH8FWw==
        Console.ReadKey();
    }
}




以上则呢合并成能用的DLL或者NODE.JS,我传入一个格式为XXXXX-XXXXX-XXXXX-XXXXX-XXXXX获取返回值,返回信息例子如下
密钥: XXXXX-XXXXX-XXXXX-XXXXX-XXXXX类型: 密钥的版本PID: XXXXX-XXXXX-XXXXX-XXXXX
代码: 返回的代码次数: 返回的次数时间: 返回时的时间

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

 楼主| jki500 发表于 2026-3-13 08:59
我还是个新手,目前初学易语言,弄好还得告诉我如何用易语言调用。
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - 52pojie.cn ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2026-3-17 14:59

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表