NESmaker 4.5.9 记录

NESmaker_4_5_9_note

第一部分:c# 主程序pj

NESMaker.exe c#程序,没有保护

PE32
    操作系统: Windows(95)[I386, 32 位, GUI]
    链接程序: Microsoft linker(48.00)
    编译器: Visual C#
    语言: C#
    库: .NET(v4.0.30319)

dnspy启动

MysticSearchToolMainDialog

MysticSearchesTool.MysticSearchToolMainDialog.MysticSearchToolMainDialog() : void @06000C6E

		public MysticSearchToolMainDialog()
		{
			string cultureOveride = this.GetCultureOveride();
			bool flag = !string.IsNullOrEmpty(cultureOveride);
			if (flag)
			{
				try
				{
					Thread.CurrentThread.CurrentUICulture = new CultureInfo(cultureOveride);
				}
				catch (Exception)
				{
				}
			}
			List<byte> list = new List<byte>();
			list.Add(90);
			list.Add(48);
			list.Add(76);
			list.Add(20);
			list.Add(127);
			list.Add(202);
			list.Add(143);
			list.Add(217);
			list.Add(125);
			list.Add(65);
			list.Add(207);
			list.Add(221);
			list.Add(20);
			list.Add(155);
			list.Add(146);
			list.Add(199);
			string text = "";
			foreach (byte b in list)
			{
				text += string.Format("{0:X2}", b);
			}
			this.SecDNAHash = text;
			list = new List<byte>();
			list.Add(162);
			list.Add(82);
			list.Add(86);
			list.Add(102);
			list.Add(25);
			list.Add(105);
			list.Add(230);
			list.Add(161);
			list.Add(53);
			list.Add(153);
			list.Add(89);
			list.Add(127);
			list.Add(160);
			list.Add(4);
			list.Add(54);
			list.Add(227);
			string text2 = "";
			foreach (byte b2 in list)
			{
				text2 += string.Format("{0:X2}", b2);
			}
			this.SecDNA32Hash = text2;
			this.ProductKey = "P0003024-QAB:D2fhogQkHWOB0jVkEtrS3lr6hgNe";
			this.ProductKey += "/";
			this.ProductKey += "O7pAkxsv2OVHTT6AHyWdPJv1KIwLpUoPh";
			this.ProductKey += "/";
			this.ProductKey += "D1N+BVQ5jGQ1a+nJpptW0SX";
			MysticSearchToolMainDialog.ScreenBorderGhostTiles = 1;
			MysticSearchToolMainDialog.DefaultGraphicBank = 1;
			MysticSearchToolMainDialog.MainTileBag = new Dictionary<Tuple<int, int>, Dictionary<int, GraphicAsset>>();
			MysticSearchToolMainDialog.ScreenTileBag = new Dictionary<Tuple<int, int>, Dictionary<int, GraphicAsset>>();
			MysticSearchToolMainDialog.MainHighResTileBag = new Dictionary<Tuple<int, int>, Dictionary<int, GraphicAsset>>();
			MysticSearchToolMainDialog.ScreenHighResTileBag = new Dictionary<Tuple<int, int>, Dictionary<int, GraphicAsset>>();
			MysticSearchToolMainDialog.PathTileBag = new Dictionary<Tuple<int, int>, Dictionary<int, GraphicAsset>>();
			MysticSearchToolMainDialog.MonsterTileBag = new Dictionary<Tuple<int, int>, Dictionary<int, GraphicAsset>>();
			MysticSearchToolMainDialog.PathInfoGroupGuidBag = new Dictionary<Tuple<int, int>, List<Guid>>();
			MysticSearchToolMainDialog.SpecialTileBag = new Dictionary<int, Dictionary<int, GraphicAsset>>();
			MysticSearchToolMainDialog.GameObjectTileBag = new Dictionary<int, GraphicAsset>();
			MysticSearchToolMainDialog.HudTileBag = new Dictionary<int, GraphicAsset>();
			this.InitializeComponent();
			MysticSearchToolMainDialog.Singleton = this;
			this.BaseTitle = this.Text;
			Environment.CurrentDirectory = this.GetAppFolder();
			bool flag2 = !this.VerifyDNADLL();
			if (!flag2)
			{
				bool flag3 = !this.VerifyDNACert();
				if (!flag3)
				{
					this.FinalInit();
					this.LoadColorPickerNames();
					this.PreparePlugins();
					this.CheckForCommandLineLoad();
				}
			}
		}

VerifyDNADLL

MysticSearchesTool.MysticSearchToolMainDialog.VerifyDNADLL() : bool @06000C83

		private bool VerifyDNADLL()
		{
			string b = DNA.MD5File("dna.dll");
			bool flag = this.SecDNAHash == b || this.SecDNA32Hash == b;
			bool result;
			if (flag)
			{
				result = true;
			}
			else
			{
				this.Text += " - Missing License DLL";
				this.fileToolStripMenuItem.Enabled = false;
				this.projectToolStripMenuItem.Enabled = false;
				this.testToolStripMenuItem.Enabled = false;
				result = false;
			}
			return result;
		}

VerifyDNACert

MysticSearchesTool.MysticSearchToolMainDialog.VerifyDNACert() : bool @06000C87

		// Token: 0x06000C87 RID: 3207 RVA: 0x0007C4E8 File Offset: 0x0007A6E8
		private bool VerifyDNACert()
		{
			string path_name = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + "\\NESMaker\\NESMaker.lic";
			path_name = "C:\\Users\\Public\\NESMaker\\NESMaker.CDM";
			DNA.DNA_SetCDMPathName(path_name);
			int num = DNA.DNA_Validate(this.ProductKey);
			bool flag = num > 0;
			bool result;
			if (flag)
			{
				string text = DNA.DNA_Error(num);
				this.fileToolStripMenuItem.Enabled = false;
				this.projectToolStripMenuItem.Enabled = false;
				this.testToolStripMenuItem.Enabled = false;
				result = false;
			}
			else
			{
				result = true;
			}
			return result;
		}

activateNESMakerToolStripMenuItem_Click

MysticSearchesTool.MysticSearchToolMainDialog.activateNESMakerToolStripMenuItem_Click(object, EventArgs) : void @06000D7D

private void activateNESMakerToolStripMenuItem_Click(object sender, EventArgs e)
		{
			int num = DNA.DNA_Validate(this.ProductKey);
			bool flag = num > 0;
			if (flag)
			{
				string text = DNA.DNA_Error(num);
				this.fileToolStripMenuItem.Enabled = false;
				this.projectToolStripMenuItem.Enabled = false;
				this.testToolStripMenuItem.Enabled = false;
				ActivationDialog activationDialog = new ActivationDialog();
				DialogResult dialogResult = activationDialog.ShowDialog();
				bool flag2 = dialogResult == DialogResult.OK;
				if (flag2)
				{
					int num2 = DNA.DNA_Activate(this.ProductKey, activationDialog.Code, activationDialog.Password, activationDialog.Email);
					bool flag3 = num2 > 0;
					if (flag3)
					{
						string str = DNA.DNA_Error(num2);
						string text2 = "There was an error activating NESMaker: " + str;
						MessageBox.Show(text2, Resources.s_ActivationError, MessageBoxButtons.OK);
					}
					else
					{
						string s_DLG_Activate = Resources.s_DLG_Activate;
						MessageBox.Show(s_DLG_Activate, Resources.s_ActivationSuccess, MessageBoxButtons.OK);
						bool flag4 = num > 0;
						if (flag4)
						{
							this.FinalInit();
							this.fileToolStripMenuItem.Enabled = true;
							this.projectToolStripMenuItem.Enabled = true;
							this.testToolStripMenuItem.Enabled = true;
							StupidStartupDialog stupidStartupDialog = new StupidStartupDialog();
							stupidStartupDialog.ShowDialog();
						}
					}
				}
			}
			else
			{
				string s_DLG_alreadyActivate = Resources.s_DLG_alreadyActivate;
				MessageBox.Show(s_DLG_alreadyActivate, Resources.s_ActivationSuccess, MessageBoxButtons.OK);
			}
		}

HackCheck

MysticSearchesTool.MysticSearchToolMainDialog.HackCheck() : bool @06000C86

private bool HackCheck()
		{
			string secDNAHash = this.SecDNAHash;
			string secDNA32Hash = this.SecDNA32Hash;
			this.SecDNAHash = "";
			this.SecDNA32Hash = "";
			string text = this.Text;
			bool flag = this.VerifyDNADLL();
			bool result;
			if (flag)
			{
				this.IsHacked = true;
				this.Text += " - Missing License DLL";
				this.fileToolStripMenuItem.Enabled = false;
				this.projectToolStripMenuItem.Enabled = false;
				this.testToolStripMenuItem.Enabled = false;
				result = false;
			}
			else
			{
				this.SecDNAHash = secDNAHash;
				this.SecDNA32Hash = secDNA32Hash;
				this.Text = text;
				this.fileToolStripMenuItem.Enabled = true;
				this.projectToolStripMenuItem.Enabled = true;
				this.testToolStripMenuItem.Enabled = true;
				result = true;
			}
			return result;
		}

InitRootTree

MysticSearchesTool.MysticSearchToolMainDialog.InitRootTree() : void @06000C8F

		protected void InitRootTree()
		{
			this.HackCheck();
			TreeNode treeNode = null;
			bool flag = MysticSearchToolMainDialog.RootNodes.ContainsKey("Plugins");
			if (flag)
			{
				treeNode = MysticSearchToolMainDialog.RootNodes["Plugins"];
			}
			……

pj点

修改VerifyDNACert 函数直接return true,当然直接修改MysticSearchToolMainDialog()也可,方法很多,不再赘述。

不需要修改dna.dll,如果修改dna.dll会导致文件md5值改变从而使主程序VerifyDNADLL校验失败

		// Token: 0x06000D8E RID: 3470 RVA: 0x00007680 File Offset: 0x00005880
		private bool VerifyDNACert()
		{
			return true;
		}

第二部分:software_DNA CDM验证分析

dna.dll DNA_Validate 使用ProductKey 传入的rsa_512公钥进行签名验证,

故想要通过.cdm过校验需要修改ProductKey (作为参数传入),使cdm使用的私钥与ProductKey 中的公钥相匹配。

所以不如直接在c#主程序上做文章。下文仅对cdm校验流程进行记录

software_DNA 有关信息可参考官网链接:

Home - software_DNA

https://www.softworkz.com/support/overviews/kb_art_overviews.aspx

这里只分析DNA_Validate 函数,即cdm 许可文件的验证函数。

DNA_Validate

DNA_Validate>Validate_check_with_ProductKey_110029890>wrap_check_cdm_with_product_key_1100295E0

__int64 __fastcall DNA_Validate(_BYTE *ProductKey)
{
  _QWORD *v2; // rax
  __int64 v4; // [rsp+28h] [rbp-78h] BYREF
  __int64 v5; // [rsp+30h] [rbp-70h]
  _BYTE v6[80]; // [rsp+38h] [rbp-68h] BYREF
  _BYTE v7[24]; // [rsp+88h] [rbp-18h] BYREF

  v4 = 0LL;
  v2 = (_QWORD *)sub_11000FC50(1, (__int64)v6, (__int64)v7);
  v5 = allocate_110012650(v2);
  if ( !(_DWORD)v5 )
  {
    str_clear_110009FC0(&v4);
    v4 = 0LL;
    str_11000A4F0(&v4, ProductKey);
    LODWORD(ProductKey) = Validate_check_with_ProductKey_110029890(v4);
  }
  sub_11000FFE0();
  str_clear_110009FC0(&v4);
  v4 = 0LL;
  if ( v5 )
    sub_1100101B0();
  return (unsigned int)ProductKey;              // 需要<=0
}

Validate_check_with_ProductKey_110029890

// 需要<=0
__int64 __fastcall Validate_check_with_ProductKey_110029890(__int64 ProductKey)
{
  unsigned int v1; // ebx
  _QWORD *v2; // rax
  __int64 _110012650; // [rsp+28h] [rbp-78h]
  _BYTE v5[80]; // [rsp+30h] [rbp-70h] BYREF
  _BYTE v6[24]; // [rsp+80h] [rbp-20h] BYREF
  __int64 v7; // [rsp+98h] [rbp-8h] BYREF

  v7 = ProductKey;
  STR_REF_11000A020(ProductKey);
  v2 = (_QWORD *)sub_11000FC50(1, (__int64)v5, (__int64)v6);
  _110012650 = allocate_110012650(v2);
  if ( !(_DWORD)_110012650 )
    v1 = wrap_check_cdm_with_product_key_1100295E0(v7);
  sub_11000FFE0();
  str_clear_110009FC0(&v7);
  if ( _110012650 )
    sub_1100101B0();
  return v1;
}

wrap_check_cdm_with_product_key_1100295E0

// 需要<=0
__int64 __fastcall wrap_check_cdm_with_product_key_1100295E0(__int64 ProductKey)
{
  // [COLLAPSED LOCAL DECLARATIONS. PRESS NUMPAD "+" TO EXPAND]

  v20 = ProductKey;
  STR_REF_11000A020(ProductKey);
  v18 = 0LL;
  v17 = 0LL;
  v16 = 0LL;
  v9 = 0LL;
  v1 = (_QWORD *)sub_11000FC50(1, (__int64)v14, (__int64)v15);
  _110012650 = allocate_110012650(v1);
  if ( !(_DWORD)_110012650 )
  {
    v2 = (_QWORD *)sub_11000FC50(1, (__int64)v11, (__int64)v12);
    v10 = allocate_110012650(v2);
    if ( !(_DWORD)v10 )
    {
      v19 = check_cdm_with_product_key_110029020(v20);
      if ( v19 <= 0 )
      {
        sub_110019360(&v18, ccdm_path_1102B0500);
        sub_1100196A0(&v16, ccdm_path_1102B0500);
        sub_110019610((__int64 *)&v17, ccdm_path_1102B0500);
        str_clear_110009FC0((__int64 *)&v9);
        v9 = 0LL;
        v3 = v17;
        if ( v17 )
          v3 = (const CHAR *)*((_QWORD *)v17 - 1);
        v4 = v16;
        if ( v16 )
          v4 = *(_QWORD *)(v16 - 8);
        str_COPY_11000A980((__int64 *)&v9, (__int64)v17, 1LL, (signed __int64)&v3[-v4]);
        STR_REF_11000A020((__int64)v9);
        str_clear_110009FC0((__int64 *)&v17);
        v17 = v9;
        str_clear_110009FC0((__int64 *)&v9);
        v9 = 0LL;
        v6 = v18;
        v7 = v17;
        v8 = ".lic";
        str_cat_11000A220((__int64 *)&v9, &v6, 2LL);
        if ( x_file_exist_1101A9A10((__int64)v9) )
        {
          str_clear_110009FC0((__int64 *)&v9);
          v9 = 0LL;
          v6 = v18;
          v7 = v17;
          v8 = ".lic";
          str_cat_11000A220((__int64 *)&v9, &v6, 2LL);
          x_DeleteFileA_110025C80(v9);
        }
      }
    }
    sub_11000FFE0();
    if ( v10 )
      sub_1100101B0();
  }
  sub_11000FFE0();
  str_clear_110009FC0((__int64 *)&v9);
  v9 = 0LL;
  str_clear_110009FC0(&v18);
  v18 = 0LL;
  str_clear_110009FC0((__int64 *)&v17);
  v17 = 0LL;
  str_clear_110009FC0(&v16);
  v16 = 0LL;
  str_clear_110009FC0(&v20);
  if ( _110012650 )
    sub_1100101B0();
  return (unsigned int)v19;
}

check_cdm_with_product_key_110029020

主要步骤:

  1. 分隔ProductKey

    '-' 前面 为.dna的文件名(??与software_DNA 网络验证地址配置相关)

    ‘-’后面部分为 RSA_PUBKEY

  2. cdm 文件解密

  3. cdm内容解析、签名验证、字段验证

// 需要<=0
__int64 __fastcall check_cdm_with_product_key_110029020(__int64 ProductKey)
{
  // [COLLAPSED LOCAL DECLARATIONS. PRESS NUMPAD "+" TO EXPAND]

  ProductKey_1 = ProductKey;
  STR_REF_11000A020(ProductKey);
  part1 = 0LL;
  part2 = 0LL;
  PROTECTION_LEVEL = 0LL;
  v9 = 0LL;
  v1 = (_QWORD *)sub_11000FC50(1, (__int64)v14, (__int64)v15);
  _110012650 = allocate_110012650(v1);
  if ( !(_DWORD)_110012650 )
  {
    if ( (unsigned __int8)sub_1101A28F0(ProductKey_1) )
    {
      code = 99;
      // P0003024
      find_substr_1101A2230((int)&part1, ProductKey_1, 1, '-');
      find_substr_1101A2230((int)&part2, ProductKey_1, 2, '-');// QAB:D2fhogQkHWOB0jVkEtrS3lr6hgNe/O7pAkxsv2OVHTT6AHyWdPJv1KIwLpUoPh/D1N+BVQ5jGQ1a+nJpptW0SX
      if ( (unsigned __int8)find_and_check_dna_1101ACD70(part2, ModuleFile_dir_path_1102B04F0, (__int64)part1) )// rdx:"E:\\crack\\NESmaker_4_5_9\\NESmaker_4_5_x\\", 00000001102B04F0:&"E:\\crack\\NESmaker_4_5_9\\NESmaker_4_5_x\\"
      {
        // DNA disable
        code = -2;
      }
      else
      {
        TCDM_obj = TCDM_1101AA940(0LL, (unsigned __int64)&TCDM_11027D5A8);
        TCDM_sig_check_1101AAB60((__int64)TCDM_obj, part2, 0LL);
        v16 = TCDM_check_MACHINE_ID_and_EXPIRY_DATE_1101AB9E0((__int64)TCDM_obj);// 返回错误代码,成功时返回0
        if ( v16 )
        {
          sub_11000ED20((__int64)TCDM_obj);
          code = v16;
        }
        else
        {
          v2 = (_QWORD *)sub_11000FC50(1, (__int64)v11, (__int64)v12);
          v10 = allocate_110012650(v2);
          if ( !(_DWORD)v10 )
          {
            str_clear_110009FC0(&v9);
            v9 = 0LL;
            // PROTECTION_LEVEL
            list_get_1101AB3D0((__int64)TCDM_obj, (__int64)&v9, (__int64)"PROTECTION_LEVEL");
            str_1101A2600((__int64)&PROTECTION_LEVEL, v9);
            str_clear_110009FC0(&v9);
            v9 = 0LL;
            list_get_1101AB3D0((__int64)TCDM_obj, (__int64)&v9, (__int64)"VALIDATION_DATE");
            if ( (unsigned __int8)not_printable_characters_1101A2560(v9) )
            {
              // 无VALIDATION_DATE 字段时
              // ACTIVATION_DATE
              // REACTIVATION_DATE
              v3 = parse_date_1101ABC70((__int64)TCDM_obj);
              if ( get_date_110020180() == v3 )
                dna_net_check_1102AD8B0 = 0;
            }
            else
            {
              _1101AB430 = tcdm_get_1101AB430((__int64)TCDM_obj, (__int64)"VALIDATION_DATE");
              if ( get_date_110020180() == _1101AB430 )
                dna_net_check_1102AD8B0 = 0;    // 当前日期匹配VALIDATION_DATE 时
            }
            if ( !str_cmp_11000A690(PROTECTION_LEVEL, (__int64)"1") )
              dna_net_check_1102AD8B0 = 0;
            if ( !str_cmp_11000A690(PROTECTION_LEVEL, (__int64)"3") )
            {
              str_clear_110009FC0(&v9);
              v9 = 0LL;
              list_get_1101AB3D0((__int64)TCDM_obj, (__int64)&v9, (__int64)"VALIDATION_WARNING");
              if ( !(unsigned __int8)not_printable_characters_1101A2560(v9) )
              {
                date_110020180 = get_date_110020180();
                if ( tcdm_get_1101AB430((__int64)TCDM_obj, (__int64)"VALIDATION_WARNING") <= date_110020180 )
                  dna_net_check_1102AD8B0 = 1;
              }
            }
            if ( exist_NESMaker_dna_dna_1102AD8C0 )
              dna_net_check_1102AD8B0 = 1;
            if ( dna_net_check_1102AD8B0 )
            {
              get_date_110020180();
              sub_1101AB690((__int64)TCDM_obj, (__int64)"VALIDATION_DATE");
              sub_1101AB8A0((__int64)TCDM_obj, (__int64)"SIGNATURE");
              if ( (unsigned __int8)sub_1101AAE10((__int64)TCDM_obj) )
              {
                code = net_check_110027FC0((void *)"V", part1, (__int64 *)&TCDM_obj, 1u);
                if ( code <= 0 )
                  save_cdm_1101AB190((__int64)TCDM_obj);
              }
              else
              {                                 // error
                code = 18;                      // The directory or file for storing the License file (CDM) is write-protected. Please ensure that you have read-write permissions for this directory or file and try again
              }
            }
            else
            {
              code = 0;
            }
            if ( (!str_cmp_11000A690(PROTECTION_LEVEL, (__int64)"1")
               || !str_cmp_11000A690(PROTECTION_LEVEL, (__int64)"2"))
              && (code == 1 || code == 2) )
            {
              code = 0;
            }
            if ( !str_cmp_11000A690(PROTECTION_LEVEL, (__int64)"3") && (unsigned int)(code - 1) < 2 )
            {
              str_clear_110009FC0(&v9);
              v9 = 0LL;
              list_get_1101AB3D0((__int64)TCDM_obj, (__int64)&v9, (__int64)"VALIDATION_LIMIT");
              if ( !(unsigned __int8)not_printable_characters_1101A2560(v9) )
              {
                v6 = get_date_110020180();
                if ( tcdm_get_1101AB430((__int64)TCDM_obj, (__int64)"VALIDATION_LIMIT") < v6 )
                  goto LABEL_44;
              }
              str_clear_110009FC0(&v9);
              v9 = 0LL;
              list_get_1101AB3D0((__int64)TCDM_obj, (__int64)&v9, (__int64)"VALIDATION_WARNING");
              if ( !(unsigned __int8)not_printable_characters_1101A2560(v9) )
              {
                v7 = get_date_110020180();
                if ( tcdm_get_1101AB430((__int64)TCDM_obj, (__int64)"VALIDATION_WARNING") > v7 )
                {
                  code = 0;
                }
                else
                {
                  code = -1;
                  str_clear_110009FC0(&v9);
                  v9 = 0LL;
                  list_get_1101AB3D0((__int64)TCDM_obj, (__int64)&v9, (__int64)"VALIDATION_LIMIT");
                  STR_REF_11000A020(v9);
                  str_clear_110009FC0(&qword_1102AD870);
                  qword_1102AD870 = v9;
                }
              }
            }
          }
          while ( 1 )
          {
            sub_11000FFE0();
            dna_net_check_1102AD8B0 = code > 0;
            sub_11000ED20((__int64)TCDM_obj);
            if ( !v10 || v10 == 2 )
              break;
            sub_1100101B0();
LABEL_44:
            v10 = 2LL;
          }
        }
      }
    }
    else
    {
      code = 5;
    }
  }
  sub_11000FFE0();
  str_clear_110009FC0(&v9);
  v9 = 0LL;
  str_clear_110009FC0((__int64 *)&part1);
  part1 = 0LL;
  str_clear_110009FC0((__int64 *)&part2);
  part2 = 0LL;
  str_clear_110009FC0(&PROTECTION_LEVEL);
  PROTECTION_LEVEL = 0LL;
  str_clear_110009FC0(&ProductKey_1);
  if ( _110012650 )
    sub_1100101B0();
  return (unsigned int)code;
}

TCDM_sig_check_1101AAB60 (cdm解密+签名验证)

__int64 __fastcall TCDM_sig_check_1101AAB60(__int64 TCDM_obj, _BYTE *rsa_key, __int64 local_cdm_path)
{
  // [COLLAPSED LOCAL DECLARATIONS. PRESS NUMPAD "+" TO EXPAND]

  rsa_key_1 = rsa_key;
  n1 = local_cdm_path;
  STR_REF_11000A020(local_cdm_path);
  part1 = 0LL;
  v10 = 0LL;
  text = 0LL;
  v4 = (_QWORD *)sub_11000FC50(1, (__int64)v8, (__int64)v9);
  _110012650 = allocate_110012650(v4);
  if ( (_DWORD)_110012650 )
    goto LABEL_14;
  // 000000011003D7E0
  (*(void (__fastcall **)(_QWORD))(**(_QWORD **)(TCDM_obj + 8) + 360LL))(*(_QWORD *)(TCDM_obj + 8));
  if ( (unsigned __int8)not_printable_characters_1101A2560(n1) )
  {
    STR_REF_11000A020(ccdm_path_1102B0500);     // 00000001102B0500:&"C:\\Users\\Public\\NESMaker\\NESMaker.CDM"
    str_clear_110009FC0(&n1);
    n1 = ccdm_path_1102B0500;
  }
  if ( !x_file_exist_1101A9A10(n1) )
  {
LABEL_11:
    if ( (unsigned __int8)not_printable_characters_1101A2560((__int64)rsa_key_1)
      || check_SIGNATURE_1101AB8F0(TCDM_obj, rsa_key_1) )
    {
      goto LABEL_14;
    }
    goto LABEL_13;
  }
  sub_1101A93C0(*(_QWORD *)(TCDM_obj + 8), n1);
  // 000000011003D3B0
  if ( (*(int (__fastcall **)(_QWORD))(**(_QWORD **)(TCDM_obj + 8) + 256LL))(*(_QWORD *)(TCDM_obj + 8)) < 1 )
  {
    (*(void (__fastcall **)(_QWORD))(**(_QWORD **)(TCDM_obj + 8) + 360LL))(*(_QWORD *)(TCDM_obj + 8));
    goto LABEL_14;
  }
  str_clear_110009FC0(&text);
  text = 0LL;
  // 000000011003D320
  // stringlist[0]
  (*(void (__fastcall **)(_QWORD, __int64 *, _QWORD))(**(_QWORD **)(TCDM_obj + 8) + 0xF0LL))(
    *(_QWORD *)(TCDM_obj + 8),
    &text,
    0LL);
  find_substr_1101A2230((int)&part1, text, 1, '|');
  str_clear_110009FC0(&text);
  text = 0LL;
  (*(void (__fastcall **)(_QWORD, __int64 *, _QWORD))(**(_QWORD **)(TCDM_obj + 8) + 0xF0LL))(
    *(_QWORD *)(TCDM_obj + 8),
    &text,
    0LL);
  find_substr_1101A2230((int)&v10, text, 2, '|');
  if ( !str_cmp_11000A690(v10, (__int64)"1") )
  {
    str_clear_110009FC0(&text);
    text = 0LL;
    aes_cfb_dec_b64_1101ACC60(&text, (__int64)"[MQ(UL/&C:&a7eEW", part1);
    // 000000011003B810
    (*(void (__fastcall **)(_QWORD, __int64))(**(_QWORD **)(TCDM_obj + 8) + 0x130LL))(*(_QWORD *)(TCDM_obj + 8), text);
    goto LABEL_11;
  }
LABEL_13:
  (*(void (__fastcall **)(_QWORD))(**(_QWORD **)(TCDM_obj + 8) + 360LL))(*(_QWORD *)(TCDM_obj + 8));
LABEL_14:
  sub_11000FFE0();
  str_clear_110009FC0(&text);
  text = 0LL;
  str_clear_110009FC0(&part1);
  part1 = 0LL;
  str_clear_110009FC0(&v10);
  v10 = 0LL;
  str_clear_110009FC0(&n1);
  result = _110012650;
  if ( _110012650 )
    return sub_1100101B0();
  return result;
}

aes_cfb_dec_b64_1101ACC60

__int64 __fastcall aes_cfb_dec_b64_1101ACC60(__int64 *out, __int64 key, __int64 data)
{
  __int64 result; // rax
  _QWORD *v5; // rax
  __int64 _110012650; // [rsp+30h] [rbp-90h]
  _BYTE v7[80]; // [rsp+38h] [rbp-88h] BYREF
  _BYTE v8[24]; // [rsp+88h] [rbp-38h] BYREF
  __int64 v9; // [rsp+A0h] [rbp-20h]
  __int64 *v10; // [rsp+A8h] [rbp-18h]
  __int64 v11; // [rsp+B0h] [rbp-10h]
  __int64 v12; // [rsp+B8h] [rbp-8h]

  v10 = out;
  v12 = key;
  v11 = data;
  str_clear_110009FC0(out);
  *out = 0LL;
  result = not_printable_characters_1101A2560(v12);
  if ( !(_BYTE)result )
  {
    result = not_printable_characters_1101A2560(v11);
    if ( !(_BYTE)result )
    {
      // 00000001101B1F10
      v9 = ((__int64 (__fastcall *)(_QWORD, __int64 *, _QWORD))*(&TDCP_rijndael_11027DFD0 + 49))(
             0LL,
             &TDCP_rijndael_11027DFD0,
             0LL);
      v5 = (_QWORD *)sub_11000FC50(1, (__int64)v7, (__int64)v8);
      _110012650 = allocate_110012650(v5);
      if ( !(_DWORD)_110012650 )
      {
        sub_1101B1420(v9, v12, (__int64)&TDCP_md5_11027DCC0);
        // 00000001101B1CF0
        (*(void (__fastcall **)(__int64, __int64 *, __int64))(*(_QWORD *)v9 + 0x200LL))(v9, v10, v11);
      }
      sub_11000FFE0();
      sub_11000ED20(v9);
      result = _110012650;
      if ( _110012650 )
        return sub_1100101B0();
    }
  }
  return result;
}

check_SIGNATURE_1101AB8F0

// 失败0,成功1
_BOOL8 __fastcall check_SIGNATURE_1101AB8F0(__int64 obj, _BYTE *rsa_key)
{
  bool v2; // si
  _QWORD *v4; // rax
  __int64 _110012650; // [rsp+38h] [rbp-88h]
  _BYTE v7[80]; // [rsp+40h] [rbp-80h] BYREF
  _BYTE v8[24]; // [rsp+90h] [rbp-30h] BYREF
  __int64 v9; // [rsp+A8h] [rbp-18h] BYREF
  __int64 v10; // [rsp+B0h] [rbp-10h] BYREF
  _BYTE *rsa_key_1; // [rsp+B8h] [rbp-8h]

  rsa_key_1 = rsa_key;
  v10 = 0LL;
  v9 = 0LL;
  v4 = (_QWORD *)sub_11000FC50(1, (__int64)v7, (__int64)v8);
  _110012650 = allocate_110012650(v4);
  if ( !(_DWORD)_110012650 )
  {
    // TStringListUTF
    TStringListUTF_1101A2670(*(_QWORD *)(obj + 8), &v9);
    // SIGNATURE
    list_get_1101AB3D0(obj, (__int64)&v10, (__int64)"SIGNATURE");
    v2 = rsa_check_1101ACA90(rsa_key_1, v9, v10);
  }
  sub_11000FFE0();
  str_clear_110009FC0(&v10);
  v10 = 0LL;
  str_clear_110009FC0(&v9);
  v9 = 0LL;
  if ( _110012650 )
    sub_1100101B0();
  return v2;
}

rsa_check_1101ACA90

// 验证失败返回0
_BOOL8 __fastcall rsa_check_1101ACA90(_BYTE *key, __int64 M, __int64 S_b64)
{
  _QWORD *v3; // rax
  __int64 _110012650; // [rsp+28h] [rbp-98h]
  _BYTE v6[80]; // [rsp+30h] [rbp-90h] BYREF
  _BYTE v7[24]; // [rsp+80h] [rbp-40h] BYREF
  __int64 v8; // [rsp+98h] [rbp-28h]
  bool v9; // [rsp+A0h] [rbp-20h]
  __int64 S_b64_; // [rsp+A8h] [rbp-18h]
  __int64 M_; // [rsp+B0h] [rbp-10h]
  _BYTE *key_; // [rsp+B8h] [rbp-8h]

  key_ = key;
  M_ = M;
  S_b64_ = S_b64;
  v9 = 0;
  if ( !(unsigned __int8)not_printable_characters_1101A2560((__int64)key)
    && !(unsigned __int8)not_printable_characters_1101A2560(S_b64_) )
  {
    v8 = TRSA_1101B0C40(0LL, (unsigned __int64)&TRSA_110281638);
    v3 = (_QWORD *)sub_11000FC50(1, (__int64)v6, (__int64)v7);
    _110012650 = allocate_110012650(v3);
    if ( !(_DWORD)_110012650 )
    {
      load_key_1101B1000(v8, key_);
      v9 = RSAVerify_b64_1101B0F20(v8, M_, S_b64_);
    }
    sub_11000FFE0();
    sub_11000ED20(v8);
    if ( _110012650 )
      sub_1100101B0();
  }
  return v9;
}

RSAVerify_b64_1101B0F20

_BOOL8 __fastcall RSAVerify_b64_1101B0F20(__int64 obj, __int64 M, __int64 S_b64)
{
  _QWORD *v4; // rax
  __int64 _110012650; // [rsp+40h] [rbp-90h]
  _BYTE v7[80]; // [rsp+48h] [rbp-88h] BYREF
  _BYTE v8[24]; // [rsp+98h] [rbp-38h] BYREF
  __int64 S_; // [rsp+B0h] [rbp-20h] BYREF
  bool valid[8]; // [rsp+B8h] [rbp-18h] BYREF
  __int64 S_b64_; // [rsp+C0h] [rbp-10h] BYREF
  __int64 M_; // [rsp+C8h] [rbp-8h] BYREF

  M_ = M;
  S_b64_ = S_b64;
  STR_REF_11000A020(M);
  STR_REF_11000A020(S_b64_);
  S_ = 0LL;
  v4 = (_QWORD *)sub_11000FC50(1, (__int64)v7, (__int64)v8);
  _110012650 = allocate_110012650(v4);
  if ( !(_DWORD)_110012650 )
  {
    x_b64dec_1101A5180(&S_, S_b64_);
    // Procedure RSAVerify(M, S : String; Var e, n : TFGInt; Var valid : boolean);
    RSAVerify_1101B7B40(M_, S_, obj + 40, obj + 24, valid);
  }
  sub_11000FFE0();
  str_clear_110009FC0(&S_);
  S_ = 0LL;
  str_clear_110009FC0(&M_);
  str_clear_110009FC0(&S_b64_);
  if ( _110012650 )
    sub_1100101B0();
  return valid[0];
}
RSAVerify_1101B7B40
// Procedure RSAVerify(M, S : String; Var e, n : TFGInt; Var valid : boolean);
// // Verify digitally signed strings with the RSA algorihthm,
// // If M = S^e mod n then ok:=true else ok:=false
__int64 __fastcall RSAVerify_1101B7B40(__int64 M, __int64 S, __int64 e, __int64 n, bool *valid)
{
  // [COLLAPSED LOCAL DECLARATIONS. PRESS NUMPAD "+" TO EXPAND]

  M1 = M;
  S1 = S;
  e1 = e;
  n1 = n;
  STR_REF_11000A020(M);
  STR_REF_11000A020(S1);
  TFGInt_110010F30(MGInt, &byte_110282910);
  TFGInt_110010F30(SGInt, &byte_110282910);
  TFGInt_110010F30(temp, &byte_110282910);
  v5 = (_QWORD *)sub_11000FC50(1, (__int64)v8, (__int64)v9);
  _110012650 = allocate_110012650(v5);
  if ( !(_DWORD)_110012650 )
  {
    Base256StringToFGInt_1101B4050(S1, SGInt);
    Base256StringToFGInt_1101B4050(M1, MGInt);
    FGIntMod_1101B6190(MGInt, n1, temp);
    FGIntCopy_1101B5120((__int64)temp, MGInt);
    FGIntMontgomeryModExp_1101B6D50(SGInt, e1, n1, temp);
    FGIntCopy_1101B5120((__int64)temp, SGInt);
    *valid = (unsigned __int8)FGIntCompareAbs_1101B47B0(SGInt, MGInt) == 2;
    FGIntDestroy_1101B4780(SGInt);
    FGIntDestroy_1101B4780(MGInt);
  }
  sub_11000FFE0();
  sub_110010FF0(MGInt, &byte_110282910);
  sub_110010FF0(SGInt, &byte_110282910);
  sub_110010FF0(temp, &byte_110282910);
  str_clear_110009FC0(&M1);
  str_clear_110009FC0(&S1);
  result = _110012650;
  if ( _110012650 )
    return sub_1100101B0();
  return result;
}

接口调用、cdm验证

通过py脚本生成.cdm文件后,可主动调用dna.dll接口 进行验证。

// NESMaker_dna.cpp : This file contains the 'main' function. Program execution begins and ends there.
//

#include <iostream>
#include <Windows.h>

__int64(__fastcall* DNA_ActivateOffline)(const char* product_key, const char* activation_code);
__int64(__fastcall* DNA_Validate)(const char* ProductKey);
__int64(__fastcall* DNA_Error)(unsigned int code, char* buf, int bufsz);
__int64(__fastcall* DNA_SetCDMPathName)(const char* path_name);
int main()
{
	int code = 0;
	//path_name = "C:\\Users\\Public\\NESMaker\\NESMaker.CDM";
	//DNA.DNA_SetCDMPathName(path_name);
	char buf[0x100]{ 0 };
	//auto ProductKey = R"(P0003024-QAB:D2fhogQkHWOB0jVkEtrS3lr6hgNe/O7pAkxsv2OVHTT6AHyWdPJv1KIwLpUoPh/D1N+BVQ5jGQ1a+nJpptW0SX)";

	//my gen rsa pub_key
	auto ProductKey = R"(P0003024-QAB:DEYss/FyLOVPDC4yXMyQVYxFqE8ZlaQtkRHrxdu/wwIn6gDbxgQNj3uKd5I/YV8na5pnHZZP9j56ejPiKlzPtP)";
	auto md = LoadLibraryA(R"(dna.dll)");
	if (!md) {
		printf("load dna.dll error");
		return 1;
	}
	DNA_Validate = (decltype(DNA_Validate))GetProcAddress(md, "DNA_Validate");
	DNA_Error = (decltype(DNA_Error))GetProcAddress(md, "DNA_Error");
	DNA_SetCDMPathName = (decltype(DNA_SetCDMPathName))GetProcAddress(md, "DNA_SetCDMPathName");
	//DNA_ActivateOffline = (decltype(DNA_ActivateOffline))GetProcAddress(md, "DNA_ActivateOffline");
	//if (DNA_Validate && DNA_ActivateOffline)
	if (DNA_Validate && DNA_Error && DNA_SetCDMPathName)
	{
		code = DNA_SetCDMPathName("C:\\Users\\Public\\NESMaker\\NESMaker.CDM");
		if (code) {
			DNA_Error(code, buf, sizeof(buf));
			printf("DNA_SetCDMPathName error:[%d] %s\n", code, buf);
		}
		code = DNA_Validate(ProductKey);
		if (code == 0) {
			printf("DNA_Validate succeed!\n");
			/*		code = DNA_ActivateOffline(ProductKey, "BRH9EIONIOU4RWYIUOEAG");
					printf("DNA_ActivateOffline code:%d\n", code);
					DNA_Error(code, buf, sizeof(buf));
					printf("error: %s\n", buf);*/
		}
		else
		{
			printf("DNA_Validate code:%d\n", code);
			DNA_Error(code, buf, sizeof(buf));
			printf("error: %s\n", buf);
		}

	}

	return 0;
}


其他

error info

error_info_11002ACC0

__int64 __fastcall error_info_11002ACC0(__int64 *a1, int a2)
{
  // [COLLAPSED LOCAL DECLARATIONS. PRESS NUMPAD "+" TO EXPAND]

  v14 = a1;
  v13 = 0LL;
  v6 = 0LL;
  v3 = (_QWORD *)sub_11000FC50(1, (__int64)v11, (__int64)v12);
  v10 = sub_110012650(v3);
  if ( (_DWORD)v10 )
    goto LABEL_59;
  switch ( a2 )
  {
    case -3:
      // Banned activation code
      find_error_str_1101AA7C0((__int64 *)&v13, 0x7Au);
      break;
    case -2:
      // DNA disable
      find_error_str_1101AA7C0((__int64 *)&v13, 0x65u);
      break;
    case -1:
      str_clear_110009FC0((__int64 *)&v6);
      v6 = 0LL;
      // Must validate by
      find_error_str_1101AA7C0((__int64 *)&v6, 0x66u);
      v7 = v6;
      v8 = &unk_1101FB878;
      v9 = qword_1102AD870;
      str_cat_11000A220((__int64 *)&v13, &v7, 2LL);
      break;
    default:
      if ( a2 )
      {
        switch ( a2 )
        {
          case 1:
            str_clear_110009FC0((__int64 *)&v6);
            v6 = 0LL;
            // Please verify your connection to the Internet or the presence of a Proxy Server
            find_error_str_1101AA7C0((__int64 *)&v6, 0x67u);
            sub_11000A020((__int64)v6);
            str_clear_110009FC0((__int64 *)&v13);
            v13 = v6;
            break;
          case 2:
            str_clear_110009FC0((__int64 *)&v6);
            v6 = 0LL;
            // Connection lost
            find_error_str_1101AA7C0((__int64 *)&v6, 0x68u);
            sub_11000A020((__int64)v6);
            str_clear_110009FC0((__int64 *)&v13);
            v13 = v6;
            break;
          case 3:
            str_clear_110009FC0((__int64 *)&v6);
            v6 = 0LL;
            // Lockout until
            find_error_str_1101AA7C0((__int64 *)&v6, 0x69u);
            v7 = v6;
            v8 = &unk_1101FB878;
            v9 = qword_1102AD870;
            str_cat_11000A220((__int64 *)&v13, &v7, 2LL);
            break;
          case 4:
            str_clear_110009FC0((__int64 *)&v6);
            v6 = 0LL;
            // Invalid CDM
            find_error_str_1101AA7C0((__int64 *)&v6, 0x6Au);
            sub_11000A020((__int64)v6);
            str_clear_110009FC0((__int64 *)&v13);
            v13 = v6;
            break;
          case 5:
            str_clear_110009FC0((__int64 *)&v6);
            v6 = 0LL;
            // Invalid product key
            find_error_str_1101AA7C0((__int64 *)&v6, 0x6Bu);
            sub_11000A020((__int64)v6);
            str_clear_110009FC0((__int64 *)&v13);
            v13 = v6;
            break;
          case 6:
            str_clear_110009FC0((__int64 *)&v6);
            v6 = 0LL;
            // Invalid activation code
            find_error_str_1101AA7C0((__int64 *)&v6, 0x6Cu);
            sub_11000A020((__int64)v6);
            str_clear_110009FC0((__int64 *)&v13);
            v13 = v6;
            break;
          case 7:
            str_clear_110009FC0((__int64 *)&v6);
            v6 = 0LL;
            // Invalid password
            find_error_str_1101AA7C0((__int64 *)&v6, 0x6Du);
            sub_11000A020((__int64)v6);
            str_clear_110009FC0((__int64 *)&v13);
            v13 = v6;
            break;
          default:
            if ( a2 != 8 )
            {
              switch ( a2 )
              {
                case 9:
LABEL_43:
                  str_clear_110009FC0((__int64 *)&v6);
                  v6 = 0LL;
                  // Re-activation expected
                  find_error_str_1101AA7C0((__int64 *)&v6, 0x6Fu);
                  sub_11000A020((__int64)v6);
                  str_clear_110009FC0((__int64 *)&v13);
                  v13 = v6;
                  goto LABEL_58;
                case 10:
                  str_clear_110009FC0((__int64 *)&v6);
                  v6 = 0LL;
                  // Banned activation code
                  find_error_str_1101AA7C0((__int64 *)&v6, 0x70u);
                  sub_11000A020((__int64)v6);
                  str_clear_110009FC0((__int64 *)&v13);
                  v13 = v6;
                  goto LABEL_58;
                case 11:
                  str_clear_110009FC0((__int64 *)&v6);
                  v6 = 0LL;
                  // No email provided
                  find_error_str_1101AA7C0((__int64 *)&v6, 0x71u);
                  sub_11000A020((__int64)v6);
                  str_clear_110009FC0((__int64 *)&v13);
                  v13 = v6;
                  goto LABEL_58;
                case 12:
                  str_clear_110009FC0((__int64 *)&v6);
                  v6 = 0LL;
                  // Invalid build number
                  find_error_str_1101AA7C0((__int64 *)&v6, 0x72u);
                  sub_11000A020((__int64)v6);
                  str_clear_110009FC0((__int64 *)&v13);
                  v13 = v6;
                  goto LABEL_58;
                case 13:
                  str_clear_110009FC0((__int64 *)&v6);
                  v6 = 0LL;
                  // Evaluation code already sent
                  find_error_str_1101AA7C0((__int64 *)&v6, 0x73u);
                  sub_11000A020((__int64)v6);
                  str_clear_110009FC0((__int64 *)&v13);
                  v13 = v6;
                  goto LABEL_58;
                case 14:
                  str_clear_110009FC0((__int64 *)&v6);
                  v6 = 0LL;
                  // Evaluation code unavailable
                  find_error_str_1101AA7C0((__int64 *)&v6, 0x74u);
                  sub_11000A020((__int64)v6);
                  str_clear_110009FC0((__int64 *)&v13);
                  v13 = v6;
                  goto LABEL_58;
                case 15:
                  str_clear_110009FC0((__int64 *)&v6);
                  v6 = 0LL;
                  // CDM has expired
                  find_error_str_1101AA7C0((__int64 *)&v6, 0x75u);
                  sub_11000A020((__int64)v6);
                  str_clear_110009FC0((__int64 *)&v13);
                  v13 = v6;
                  goto LABEL_58;
                case 16:
                  str_clear_110009FC0((__int64 *)&v6);
                  v6 = 0LL;
                  // Activation code has expired
                  find_error_str_1101AA7C0((__int64 *)&v6, 0x76u);
                  sub_11000A020((__int64)v6);
                  str_clear_110009FC0((__int64 *)&v13);
                  v13 = v6;
                  goto LABEL_58;
                case 17:
                  str_clear_110009FC0((__int64 *)&v6);
                  v6 = 0LL;
                  // The new password has already been used. Please provide a New and Never Used password to re-activate
                  find_error_str_1101AA7C0((__int64 *)&v6, 0x79u);
                  sub_11000A020((__int64)v6);
                  str_clear_110009FC0((__int64 *)&v13);
                  v13 = v6;
                  goto LABEL_58;
                case 18:
                  str_clear_110009FC0((__int64 *)&v6);
                  v6 = 0LL;
                  // The directory or file for storing the License file (CDM) is write-protected. Please ensure that you have read-write permissions for this directory or file and try again
                  find_error_str_1101AA7C0((__int64 *)&v6, 0x7Bu);
                  sub_11000A020((__int64)v6);
                  str_clear_110009FC0((__int64 *)&v13);
                  v13 = v6;
                  goto LABEL_58;
              }
              if ( a2 != 19 )
              {
                if ( a2 != 20 )
                {
                  if ( a2 == 21 )
                  {
                    str_clear_110009FC0((__int64 *)&v13);
                    v13 = "The number of activations has been exceeded for this Activation Code.";
                  }
                  else if ( a2 == 98 )
                  {
                    str_clear_110009FC0((__int64 *)&v6);
                    v6 = 0LL;
                    // Cancelled by user
                    find_error_str_1101AA7C0((__int64 *)&v6, 120u);
                    sub_11000A020((__int64)v6);
                    str_clear_110009FC0((__int64 *)&v13);
                    v13 = v6;
                  }
                  else
                  {
                    str_clear_110009FC0((__int64 *)&v6);
                    v6 = 0LL;
                    if ( a2 == 99 )
                      // Please verify your Activation Code, Password and try again
                      find_error_str_1101AA7C0((__int64 *)&v6, 119u);
                    else
                      // Undefined error
                      find_error_str_1101AA7C0((__int64 *)&v6, 100u);
                    sub_11000A020((__int64)v6);
                    str_clear_110009FC0((__int64 *)&v13);
                    v13 = v6;
                  }
                  goto LABEL_58;
                }
                goto LABEL_43;
              }
            }
            str_clear_110009FC0((__int64 *)&v6);
            v6 = 0LL;
            // Activation expected
            find_error_str_1101AA7C0((__int64 *)&v6, 110u);
            sub_11000A020((__int64)v6);
            str_clear_110009FC0((__int64 *)&v13);
            v13 = v6;
            break;
        }
      }
      else
      {
        str_clear_110009FC0((__int64 *)&v13);
        v13 = 0LL;
      }
      break;
  }
LABEL_58:
  sub_11000A020((__int64)v13);
  v4 = v14;
  str_clear_110009FC0(v14);
  *v4 = (__int64)v13;
LABEL_59:
  sub_11000FFE0();
  str_clear_110009FC0((__int64 *)&v6);
  v6 = 0LL;
  str_clear_110009FC0((__int64 *)&v13);
  v13 = 0LL;
  result = v10;
  if ( v10 )
    return sub_1100101B0();
  return result;
}
.data:000000011027C810 off_11027C810   dq offset a100          ; DATA XREF: find_error_str_1101AA7C0+95↑o
.data:000000011027C810                                         ; find_error_str_1101AA7C0+CA↑o ...
.data:000000011027C810                                         ; "100"
.data:000000011027C818                 dq offset aUndefinedError ; "Undefined error"
.data:000000011027C820                 dq offset aErreurNonDefin ; "Erreur non définie"
.data:000000011027C828                 dq offset aUnbekannterFeh ; "Unbekannter Fehler"
.data:000000011027C830                 dq offset aErrorIndefinid ; "Error indefinido"
.data:000000011027C838                 dq 0
.data:000000011027C840                 dq offset a101          ; "101"
.data:000000011027C848                 dq offset aDnaDisable   ; "DNA disable"
.data:000000011027C850                 dq offset aDnaNeutralise ; "DNA neutralisé"
.data:000000011027C858                 dq offset aDnaDeaktiviert ; "DNA deaktiviert"
.data:000000011027C860                 dq offset aDnaDeshabilita ; "DNA deshabilitado"
.data:000000011027C868                 dq 0
.data:000000011027C870                 dq offset a102          ; "102"
.data:000000011027C878                 dq offset aMustValidateBy ; "Must validate by"
.data:000000011027C880                 dq offset aValidationRequ ; "Validation requise avant le"
.data:000000011027C888                 dq offset aMussValidiertW ; "Muss validiert werden durch"
.data:000000011027C890                 dq offset aDebeValidarAnt ; "Debe validar antes"
.data:000000011027C898                 align 20h
.data:000000011027C8A0                 dq offset a103          ; "103"
.data:000000011027C8A8                 dq offset aPleaseVerifyYo ; "Please verify your connection to the In"...
.data:000000011027C8B0                 dq offset aSvpVerifierVot ; "SVP vérifier votre connection à l'inter"...
.data:000000011027C8B8                 dq offset aBitteUberprufe ; "Bitte überprüfen Sie ihre Internetverbi"...
.data:000000011027C8C0                 dq offset aPorFavorVerifi ; "Por favor, verifique su conexión a Inte"...
.data:000000011027C8C8                 align 10h
.data:000000011027C8D0                 dq offset a104          ; "104"
.data:000000011027C8D8                 dq offset aConnectionLost ; "Connection lost"
.data:000000011027C8E0                 dq offset aConnectionPerd ; "Connection perdue"
.data:000000011027C8E8                 dq offset aVerbindungGetr ; "Verbindung getrennt"
.data:000000011027C8F0                 dq offset aConexionPerdid ; "Conexión perdida"
.data:000000011027C8F8                 align 20h
.data:000000011027C900                 dq offset a105          ; "105"
.data:000000011027C908                 dq offset aLockoutUntil ; "Lockout until"
.data:000000011027C910                 dq offset aVerrouillageJu ; "Verrouillage jusqu'au"
.data:000000011027C918                 dq offset aAusgeschlossen ; "Ausgeschlossen bis"
.data:000000011027C920                 dq offset aBloqueadoHasta ; "Bloqueado hasta"
.data:000000011027C928                 align 10h
.data:000000011027C930                 dq offset a106          ; "106"
.data:000000011027C938                 dq offset aInvalidCdm   ; "Invalid CDM"
.data:000000011027C940                 dq offset aCdmInadmissibl ; "CDM Inadmissible"
.data:000000011027C948                 dq offset aUngultigeCdm ; "Ungültige CDM"
.data:000000011027C950                 dq offset aCdmIncorrecta ; "CDM incorrecta"
.data:000000011027C958                 align 20h
.data:000000011027C960                 dq offset a107          ; "107"
.data:000000011027C968                 dq offset aInvalidProduct ; "Invalid product key"
.data:000000011027C970                 dq offset aClefDeProduitI ; "Clef de produit inadmissible"
.data:000000011027C978                 dq offset aUngultigerProd ; "Ungültiger Produktschlüssel"
.data:000000011027C980                 dq offset aClaveDeProduct ; "Clave de producto incorrecta"
.data:000000011027C988                 align 10h
.data:000000011027C990                 dq offset a108          ; "108"
.data:000000011027C998                 dq offset aInvalidActivat ; "Invalid activation code"
.data:000000011027C9A0                 dq offset aCodeDActivatio ; "Code d'activation inadmissible"
.data:000000011027C9A8                 dq offset aUngultigerAkti ; "Ungültiger Aktivierungscode"
.data:000000011027C9B0                 dq offset aCodigoDeActiva_0 ; "Código de Activación incorrecto"
.data:000000011027C9B8                 align 20h
.data:000000011027C9C0                 dq offset a109          ; "109"
.data:000000011027C9C8                 dq offset aInvalidPasswor ; "Invalid password"
.data:000000011027C9D0                 dq offset aMotDePasseInad ; "Mot de passe inadmissible"
.data:000000011027C9D8                 dq offset aUngultigesPass ; "Ungültiges Passwort"
.data:000000011027C9E0                 dq offset aClaveDeAccesoI ; "Clave de acceso incorrecta"
.data:000000011027C9E8                 align 10h
.data:000000011027C9F0                 dq offset a110          ; "110"
.data:000000011027C9F8                 dq offset aActivationExpe ; "Activation expected"
.data:000000011027CA00                 dq offset aActivationPrev ; "Activation prévue"
.data:000000011027CA08                 dq offset aAktivierungErw ; "Aktivierung erwartet"
.data:000000011027CA10                 dq offset aSeEsperaActiva ; "Se espera activación"
.data:000000011027CA18                 align 20h
.data:000000011027CA20                 dq offset a111          ; "111"
.data:000000011027CA28                 dq offset aReActivationEx ; "Re-activation expected"
.data:000000011027CA30                 dq offset aReactivationPr ; "Réactivation prévue"
.data:000000011027CA38                 dq offset aReaktivierungE ; "Reaktivierung erwartet"
.data:000000011027CA40                 dq offset aSeEsperaReacti ; "Se espera reactivación"
.data:000000011027CA48                 align 10h
.data:000000011027CA50                 dq offset a112          ; "112"
.data:000000011027CA58                 dq offset aBannedActivati ; "Banned activation code"
.data:000000011027CA60                 dq offset aCodeDActivatio_0 ; "Code d'activation interdit"
.data:000000011027CA68                 dq offset aBlockierterAkt ; "Blockierter Aktivierungscode"
.data:000000011027CA70                 dq offset aCodigoDeActiva ; "Código de Activación bloqueado"
.data:000000011027CA78                 align 20h
.data:000000011027CA80                 dq offset a113          ; "113"
.data:000000011027CA88                 dq offset aNoEmailProvide ; "No email provided"
.data:000000011027CA90                 dq offset aAucunCourrielF ; "Aucun courriel fourni"
.data:000000011027CA98                 dq offset aKeineEmailAnge ; "Keine Email angegeben"
.data:000000011027CAA0                 dq offset aFaltaDireccion ; "Falta dirección email"
.data:000000011027CAA8                 align 10h
.data:000000011027CAB0                 dq offset a114          ; "114"
.data:000000011027CAB8                 dq offset aInvalidBuildNu ; "Invalid build number"
.data:000000011027CAC0                 dq offset aVersionInadmis ; "Version inadmissible"
.data:000000011027CAC8                 dq offset aUngultigeBuild ; "Ungültige Build-Nummer"
.data:000000011027CAD0                 dq offset aVersionIncorre ; "Versión incorrecta"
.data:000000011027CAD8                 align 20h
.data:000000011027CAE0                 dq offset a115          ; "115"
.data:000000011027CAE8                 dq offset aEvaluationCode ; "Evaluation code already sent"
.data:000000011027CAF0                 dq offset aCodeDEvaluatio ; "Code d'évaluation déjà transmis"
.data:000000011027CAF8                 dq offset aEvaluationscod ; "Evaluationscode bereits gesendet"
.data:000000011027CB00                 dq offset aCodigoDeEvalua ; "Código de evaluación ya enviado"
.data:000000011027CB08                 align 10h
.data:000000011027CB10                 dq offset a116          ; "116"
.data:000000011027CB18                 dq offset aEvaluationCode_0 ; "Evaluation code unavailable"
.data:000000011027CB20                 dq offset aCodeDEvaluatio_0 ; "Code d'évaluation non disponible"
.data:000000011027CB28                 dq offset aEvaluationscod_1 ; "Evaluationscode nicht verfügbar"
.data:000000011027CB30                 dq offset aCodigoDeEvalua_0 ; "Código de Evaluación no disponible"
.data:000000011027CB38                 align 20h
.data:000000011027CB40                 dq offset a117          ; "117"
.data:000000011027CB48                 dq offset aCdmHasExpired ; "CDM has expired"
.data:000000011027CB50                 dq offset aCdmExpire    ; "CDM expiré"
.data:000000011027CB58                 dq offset aCdmIstAbgelauf ; "CDM ist abgelaufen"
.data:000000011027CB60                 dq offset aCdmHaCaducado ; "CDM ha caducado"
.data:000000011027CB68                 align 10h
.data:000000011027CB70                 dq offset a118          ; "118"
.data:000000011027CB78                 dq offset aActivationCode_1 ; "Activation code has expired"
.data:000000011027CB80                 dq offset aCodeDActivatio_2 ; "Code d'activation expiré"
.data:000000011027CB88                 dq offset aAktivierungsco ; "Aktivierungscode ist abgelaufen"
.data:000000011027CB90                 dq offset aElCodigoDeActi ; "El Código de Activación ha caducado"
.data:000000011027CB98                 align 20h
.data:000000011027CBA0                 dq offset a119          ; "119"
.data:000000011027CBA8                 dq offset aPleaseVerifyYo_0 ; "Please verify your Activation Code, Pas"...
.data:000000011027CBB0                 dq offset aSvpVerifierVot_0 ; "SVP vérifier votre code d'activation, m"...
.data:000000011027CBB8                 dq offset aBitteUberprufe_0 ; "Bitte überprüfen sie ihre Aktivierungsc"...
.data:000000011027CBC0                 dq offset aPorFavorCompru ; "Por favor, compruebe su Código de Activ"...
.data:000000011027CBC8                 align 10h
.data:000000011027CBD0                 dq offset a120          ; "120"
.data:000000011027CBD8                 dq offset aCancelledByUse ; "Cancelled by user"
.data:000000011027CBE0                 dq offset aAnnuleParLUtil ; "Annulé par l'utilisateur"
.data:000000011027CBE8                 dq offset aDurchBenutzerA ; "Durch Benutzer abgebrochen"
.data:000000011027CBF0                 dq offset aCanceladoPorEl ; "Cancelado por el usuario"
.data:000000011027CBF8                 align 20h
.data:000000011027CC00                 dq offset a121          ; "121"
.data:000000011027CC08                 dq offset aTheNewPassword ; "The new password has already been used."...
.data:000000011027CC10                 dq offset aLeNouveauMotDe ; "Le nouveau mot de passe a déjà été util"...
.data:000000011027CC18                 dq offset aDasNeueKennwor ; "Das Neue Kennwort ist schon benutzt wor"...
.data:000000011027CC20                 dq offset aLaClaveDeAcces ; "La clave de acceso ya ha sido utilizada"...
.data:000000011027CC28                 align 10h
.data:000000011027CC30                 dq offset a122          ; "122"
.data:000000011027CC38                 dq offset aTheNumberOfPer ; "The number of permitted activations has"...
.data:000000011027CC40                 dq offset aLeNombreDActiv ; "Le nombre d'activations permises est dé"...
.data:000000011027CC48                 dq offset aTheNumberOfPer_0 ; "The number of permitted activations has"...
.data:000000011027CC50                 dq offset aSeHaSobrepasad ; "Se ha sobrepasado el número de activaci"...
.data:000000011027CC58                 align 20h
.data:000000011027CC60                 dq offset a123          ; "123"
.data:000000011027CC68                 dq offset aTheDirectoryOr ; "The directory or file for storing the L"...
.data:000000011027CC70                 dq offset aLeRepertoireOu ; "Le répertoire ou le fichier pour écrire"...
.data:000000011027CC78                 dq offset aTheDirectoryOr_0 ; "The directory or file for storing the L"...
.data:000000011027CC80                 dq offset aElDirectorioUs ; "El directorio usado para almacenar el f"...
.data:000000011027CC88                 align 10h
.data:000000011027CC90                 dq offset a200          ; "200"
.data:000000011027CC98                 dq offset aProductActivat ; "Product Activation"
.data:000000011027CCA0                 dq offset aActivation_0 ; "Activation"
.data:000000011027CCA8                 dq offset aProduktAktivie ; "Produkt Aktivierung"
.data:000000011027CCB0                 dq offset aActivacion   ; "Activación"
.data:000000011027CCB8                 align 20h
.data:000000011027CCC0                 dq offset a201          ; "201"
.data:000000011027CCC8                 dq offset aActivationInfo ; "Activation Information"
.data:000000011027CCD0                 dq offset aInformationDAc ; "Information d'activation"
.data:000000011027CCD8                 dq offset aAktivierungsin ; "Aktivierungsinformation"
.data:000000011027CCE0                 dq offset aInformacionDeA ; "Información de activación"
.data:000000011027CCE8                 align 10h
.data:000000011027CCF0                 dq offset a202          ; "202"
.data:000000011027CCF8                 dq offset aPassword_3   ; "Password :"
.data:000000011027CD00                 dq offset aMotDePasse   ; "Mot de passe :"
.data:000000011027CD08                 dq offset aPasswort     ; "Passwort :"
.data:000000011027CD10                 dq offset aClaveDeAcceso ; "Clave de acceso :"
.data:000000011027CD18                 align 20h
.data:000000011027CD20                 dq offset a203          ; "203"
.data:000000011027CD28                 dq offset aConfirm      ; "Confirm :"
.data:000000011027CD30                 dq offset aConfirmez    ; "Confirmez :"
.data:000000011027CD38                 dq offset aBestatigung  ; "Bestätigung :"
.data:000000011027CD40                 dq offset aConfirme     ; "Confirme :"
.data:000000011027CD48                 align 10h
.data:000000011027CD50                 dq offset a204          ; "204"
.data:000000011027CD58                 dq offset aEmail_0      ; "Email :"
.data:000000011027CD60                 dq offset aCourriel     ; "Courriel :"
.data:000000011027CD68                 dq offset aEmail_1      ; "Email :"
.data:000000011027CD70                 dq offset aEmail_2      ; "Email :"
.data:000000011027CD78                 align 20h
.data:000000011027CD80                 dq offset a205          ; "205"
.data:000000011027CD88                 dq offset aConfirm_0    ; "Confirm :"
.data:000000011027CD90                 dq offset aConfirmez_0  ; "Confirmez :"
.data:000000011027CD98                 dq offset aBestatigung_0 ; "Bestätigung :"
.data:000000011027CDA0                 dq offset aConfirme_0   ; "Confirme :"
.data:000000011027CDA8                 align 10h
.data:000000011027CDB0                 dq offset a206          ; "206"
.data:000000011027CDB8                 dq offset aPleaseEnterAnd ; "Please enter and confirm a password."
.data:000000011027CDC0                 dq offset aSvpEntrerEtCon ; "SVP entrer et confirmer un mot de passe"...
.data:000000011027CDC8                 dq offset aBittePasswortE ; "Bitte Passwort eingeben und bestätigen."
.data:000000011027CDD0                 dq offset aPorFavorIntrod ; "Por favor, introduzca y confirme una cl"...
.data:000000011027CDD8                 align 20h
.data:000000011027CDE0                 dq offset a207          ; "207"
.data:000000011027CDE8                 dq offset aItIsRecommende ; "It is recommended that you also enter a"...
.data:000000011027CDF0                 dq offset aIlEstRecommand ; "Il est recommandé d'enregistrer et conf"...
.data:000000011027CDF8                 dq offset aEsWirdEmpfohle ; "Es wird empfohlen, daß Sie auch Ihre Em"...
.data:000000011027CE00                 dq offset aTambienEsConve ; "También es conveniente que introduzca y"...
.data:000000011027CE08                 align 10h
.data:000000011027CE10                 dq offset a208          ; "208"
.data:000000011027CE18                 dq offset aActivate     ; "&Activate"
.data:000000011027CE20                 dq offset aActiver      ; "&Activer"
.data:000000011027CE28                 dq offset aAktivieren   ; "&Aktivieren"
.data:000000011027CE30                 dq offset aActivar      ; "&Activar"
.data:000000011027CE38                 align 20h
.data:000000011027CE40                 dq offset a209          ; "209"
.data:000000011027CE48                 dq offset aCancel_1     ; "&Cancel"
.data:000000011027CE50                 dq offset aAnnuler      ; "&Annuler"
.data:000000011027CE58                 dq offset aAbbrechen    ; "&Abbrechen"
.data:000000011027CE60                 dq offset aCancelar     ; "&Cancelar"
.data:000000011027CE68                 align 10h
.data:000000011027CE70                 dq offset a210          ; "210"
.data:000000011027CE78                 dq offset aPasswordsDonTM ; "Passwords don't match"
.data:000000011027CE80                 dq offset aLesMotsDePasse ; "Les mots de passe ne sont pas identique"...
.data:000000011027CE88                 dq offset aPassworterStim ; "Passwörter stimmen nicht überein"
.data:000000011027CE90                 dq offset aLasClavesDeAcc ; "Las claves de acceso no concuerdan"
.data:000000011027CE98                 align 20h
.data:000000011027CEA0                 dq offset a211          ; "211"
.data:000000011027CEA8                 dq offset aEmailsDonTMatc ; "Emails don't match"
.data:000000011027CEB0                 dq offset aLesAdressesCou ; "Les adresses courriel ne sont pas ident"...
.data:000000011027CEB8                 dq offset aEmailsStimmenN ; "Emails stimmen nicht überein"
.data:000000011027CEC0                 dq offset aLasDirecciones ; "Las direcciones email no concuerdan"
.data:000000011027CEC8                 align 10h
.data:000000011027CED0                 dq offset a300          ; "300"
.data:000000011027CED8                 dq offset aProductActivat_0 ; "Product Activation"
.data:000000011027CEE0                 dq offset aActivationDuPr ; "Activation du produit"
.data:000000011027CEE8                 dq offset aProduktAktivie_0 ; "Produkt Aktivierung"
.data:000000011027CEF0                 dq offset aActivacionDelP ; "Activación del producto"
.data:000000011027CEF8                 align 20h
.data:000000011027CF00                 dq offset a301          ; "301"
.data:000000011027CF08                 dq offset aPleaseEnterYou ; "Please enter your Activation Code"
.data:000000011027CF10                 dq offset aSvpEntrerVotre ; "SVP entrer votre code d'activation"
.data:000000011027CF18                 dq offset aBitteAktivieru ; "Bitte Aktivierungscode eingeben"
.data:000000011027CF20                 dq offset aPorFavorIntrod_0 ; "Por favor, introduzca su Código de Acti"...
.data:000000011027CF28                 align 10h
.data:000000011027CF30                 dq offset a302          ; "302"
.data:000000011027CF38                 dq offset aActivationCode_2 ; "Activation Code :"
.data:000000011027CF40                 dq offset aCodeDActivatio_1 ; "Code d'activation :"
.data:000000011027CF48                 dq offset aAktivierungsco_0 ; "Aktivierungscode :"
.data:000000011027CF50                 dq offset aCodigoDeActiva_1 ; "Código de activación :"
.data:000000011027CF58                 align 20h
.data:000000011027CF60                 dq offset a303          ; "303"
.data:000000011027CF68                 dq offset aRequestEvalCod ; "&Request Eval Code"
.data:000000011027CF70                 dq offset aRequeteCodeDEv ; "&Requête code d'éval"
.data:000000011027CF78                 dq offset aEvalCodeVerlan ; "&Eval. Code verlangen"
.data:000000011027CF80                 dq offset aSolicitarCodDe ; "&Solicitar Cód. de Ev."
.data:000000011027CF88                 align 10h
.data:000000011027CF90                 dq offset a304          ; "304"
.data:000000011027CF98                 dq offset aProxySettings ; "&Proxy Settings"
.data:000000011027CFA0                 dq offset aReglagesPasser ; "&Réglages passerelle"
.data:000000011027CFA8                 dq offset aProxyEinstellu ; "&Proxy Einstellungen"
.data:000000011027CFB0                 dq offset aSetearProxi  ; "&Setear Proxi"
.data:000000011027CFB8                 align 20h
.data:000000011027CFC0                 dq offset a305          ; "305"
.data:000000011027CFC8                 dq offset aNext_2       ; "&Next >"
.data:000000011027CFD0                 dq offset aSuivant      ; "&Suivant >"
.data:000000011027CFD8                 dq offset aWeiter       ; "&Weiter >"
.data:000000011027CFE0                 dq offset aSiguiente    ; "&Siguiente >"
.data:000000011027CFE8                 align 10h
.data:000000011027CFF0                 dq offset a306          ; "306"
.data:000000011027CFF8                 dq offset aCancel_2     ; "&Cancel"
.data:000000011027D000                 dq offset aAnnuler_0    ; "&Annuler"
.data:000000011027D008                 dq offset aAbbrechen_0  ; "&Abbrechen"
.data:000000011027D010                 dq offset aCancelar_0   ; "&Cancelar"
.data:000000011027D018                 align 20h
.data:000000011027D020                 dq offset a307          ; "307"
.data:000000011027D028                 dq offset aRequestEvaluat ; "Request Evaluation Code"
.data:000000011027D030                 dq offset aRequeteCodeDEv_0 ; "Requête code d'évaluation"
.data:000000011027D038                 dq offset aEvaluationscod_0 ; "Evaluationscode verlangen"
.data:000000011027D040                 dq offset aSolicitarCodig ; "Solicitar Código de Evaluación"
.data:000000011027D048                 align 10h
.data:000000011027D050                 dq offset a308          ; "308"
.data:000000011027D058                 dq offset aEnterAValidEma ; "Enter a valid email ?"
.data:000000011027D060                 dq offset aEntrerUneAdres ; "Entrer une adresse courriel valide ?"
.data:000000011027D068                 dq offset aGultigeEmailEi ; "Gültige Email eingegeben ?"
.data:000000011027D070                 dq offset aEsValidaLaDire ; "Es válida la dirección email?"
.data:000000011027D078                 align 20h
.data:000000011027D080                 dq offset a309          ; "309"
.data:000000011027D088                 dq offset aYourEvaluation ; "Your evaluation code has been sent"
.data:000000011027D090                 dq offset aVotreCodeDEval ; "Votre code d'évaluation a été envoyé"
.data:000000011027D098                 dq offset aIhrEvaluations ; "Ihr Evaluationscode wurde gesendet"
.data:000000011027D0A0                 dq offset aSuCodigoDeEval ; "Su Código de Evaluación ha sido enviado"
.data:000000011027D0A8                 align 10h
.data:000000011027D0B0                 dq offset a310          ; "310"
.data:000000011027D0B8                 dq offset aEvaluateNow  ; "&Evaluate Now"
.data:000000011027D0C0                 dq offset aEvaluerMainten ; "&Évaluer maintenant"
.data:000000011027D0C8                 dq offset aJetztEvaluiere ; "&Jetzt evaluieren"
.data:000000011027D0D0                 dq offset aEvaluarAhora ; "&Evaluar ahora"
.data:000000011027D0D8                 align 20h
.data:000000011027D0E0                 dq offset a311          ; "311"
.data:000000011027D0E8                 dq offset aLicenseFileCre ; "License File created successfully"
.data:000000011027D0F0                 dq offset aLeFichierDeLic ; "Le fichier de licence a été créé"
.data:000000011027D0F8                 dq offset aDieLizenzdatei ; "Die Lizenzdatei wurde erfolgreich erzeu"...
.data:000000011027D100                 dq offset aFicheroDeLicen ; "Fichero de Licencia creado satisfactori"...
.data:000000011027D108                 align 10h
.data:000000011027D110                 dq offset a312          ; "312"
.data:000000011027D118                 dq offset aLicenseFileNot ; "License File not created !"
.data:000000011027D120                 dq offset aLaCreationDuFi ; "La création du fichier de licence a éch"...
.data:000000011027D128                 dq offset aDieLizenzdatei_0 ; "Die Lizenzdatei konnte nicht erzeugt we"...
.data:000000011027D130                 dq offset aFicheroDeLicen_0 ; "Fichero de Licencia no creado !"
.data:000000011027D138                 align 20h
.data:000000011027D140                 dq offset a400          ; "400"
.data:000000011027D148                 dq offset aProxySettings_0 ; "Proxy Settings"
.data:000000011027D150                 dq offset aReglagesPasser_0 ; "Réglages passerelle"
.data:000000011027D158                 dq offset aProxyEinstellu_0 ; "Proxy Einstellungen"
.data:000000011027D160                 dq offset aReglajesDeProx ; "Reglajes de Proxi"
.data:000000011027D168                 align 10h
.data:000000011027D170                 dq offset a401          ; "401"
.data:000000011027D178                 dq offset aAuthentication_1 ; "Authentication"
.data:000000011027D180                 dq offset aAuthentificati ; "Authentification"
.data:000000011027D188                 dq offset aAuthentifikati ; "Authentifikation"
.data:000000011027D190                 dq offset aAutenticacion ; "Autenticación"
.data:000000011027D198                 align 20h
.data:000000011027D1A0                 dq offset a402          ; "402"
.data:000000011027D1A8                 dq offset aUsername_3   ; "Username :"
.data:000000011027D1B0                 dq offset aUsager       ; "Usager :"
.data:000000011027D1B8                 dq offset aBenutzername ; "Benutzername :"
.data:000000011027D1C0                 dq offset aNombreDeUsuari ; "Nombre de usuario :"
.data:000000011027D1C8                 align 10h
.data:000000011027D1D0                 dq offset a403          ; "403"
.data:000000011027D1D8                 dq offset aPassword_4   ; "Password :"
.data:000000011027D1E0                 dq offset aMotDePasse_0 ; "Mot de passe :"
.data:000000011027D1E8                 dq offset aPasswort_0   ; "Passwort :"
.data:000000011027D1F0                 dq offset aClaveDeAcceso_0 ; "Clave de acceso :"
.data:000000011027D1F8                 align 20h
.data:000000011027D200                 dq offset a404          ; "404"
.data:000000011027D208                 dq offset aOk           ; "&Ok"
.data:000000011027D210                 dq offset aOk_0         ; "&Ok"
.data:000000011027D218                 dq offset aOk_1         ; "&Ok"
.data:000000011027D220                 dq offset aOk_2         ; "&Ok"
.data:000000011027D228                 align 10h
.data:000000011027D230                 dq offset a405          ; "405"
.data:000000011027D238                 dq offset aCancel_3     ; "&Cancel"
.data:000000011027D240                 dq offset aAnnuler_1    ; "&Annuler"
.data:000000011027D248                 dq offset aAbbrechen_1  ; "&Abbrechen"
.data:000000011027D250                 dq offset aCancelar_1   ; "&Cancelar"
.data:000000011027D258                 align 20h
.data:000000011027D260                 dq offset a406          ; "406"
.data:000000011027D268                 dq offset aProxy_1      ; "Proxy"
.data:000000011027D270                 dq offset aPasserelle   ; "Passerelle"
.data:000000011027D278                 dq offset aProxy_2      ; "Proxy"
.data:000000011027D280                 dq offset aProxi        ; "Proxi"
.data:000000011027D288                 align 10h
.data:000000011027D290                 dq offset a407          ; "407"
.data:000000011027D298                 dq offset aServer_2     ; "Server :"
.data:000000011027D2A0                 dq offset aServeur      ; "Serveur :"
.data:000000011027D2A8                 dq offset aServer_3     ; "Server :"
.data:000000011027D2B0                 dq offset aServidor     ; "Servidor :"
.data:000000011027D2B8                 align 20h
.data:000000011027D2C0                 dq offset a408          ; "408"
.data:000000011027D2C8                 dq offset aPort_1       ; "Port :"
.data:000000011027D2D0                 dq offset aPort_2       ; "Port :"
.data:000000011027D2D8                 dq offset aPort_3       ; "Port :"
.data:000000011027D2E0                 dq offset aPort_4       ; "Port :"
.data:000000011027D2E8                 align 10h
.data:000000011027D2F0                 dq offset a409          ; "409"
.data:000000011027D2F8                 dq offset aUseInternetExp ; "Use Internet Explorer Settings"
.data:000000011027D300                 dq offset aUtiliserLesPar ; "Utiliser les paramètres d'Internet Expl"...
.data:000000011027D308                 dq offset aBenutzeInterne ; "Benutze Internet Explorer Einstellungen"
.data:000000011027D310                 dq offset aUsarParametros ; "Usar parámetros de Internet Explorer"
.data:000000011027D318                 dq 0
.data:000000011027D320                 dq offset a500          ; "500"
.data:000000011027D328                 dq offset aProductActivat_1 ; "Product Activation"
.data:000000011027D330                 dq offset aActivationDuPr_0 ; "Activation du produit"
.data:000000011027D338                 dq offset aProduktAktivie_1 ; "Produkt Aktivierung"
.data:000000011027D340                 dq offset aActivacionDelP_0 ; "Activación del producto"
.data:000000011027D348                 align 10h
.data:000000011027D350                 dq offset a501          ; "501"
.data:000000011027D358                 dq offset aReActivationIn ; "Re-Activation Information"
.data:000000011027D360                 dq offset aInformationDeR ; "Information de réactivation"
.data:000000011027D368                 dq offset aReaktivierungs ; "Reaktivierungs Information"
.data:000000011027D370                 dq offset aInformacionDeR ; "Información de reactivación"
.data:000000011027D378                 align 20h
.data:000000011027D380                 dq offset a502_1        ; "502"
.data:000000011027D388                 dq offset aCurrentPasswor ; "Current Password :"
.data:000000011027D390                 dq offset aMotDePasseCour ; "Mot de passe courant :"
.data:000000011027D398                 dq offset aAktuellesPassw ; "Aktuelles Passwort :"
.data:000000011027D3A0                 dq offset aClaveDeAccesoA ; "Clave de acceso actual :"
.data:000000011027D3A8                 align 10h
.data:000000011027D3B0                 dq offset a503          ; "503"
.data:000000011027D3B8                 dq offset aNewNeverUsedPa ; "New (never-used) password :"
.data:000000011027D3C0                 dq offset aNouveauJamaisU ; "Nouveau (jamais utilisé) mot de passe :"
.data:000000011027D3C8                 dq offset aNeuesNieGenomm ; "Neues (Nie genommen) Passwort :"
.data:000000011027D3D0                 dq offset aNuevaClaveDeAc ; "Nueva clave de acceso (no usada antes) "...
.data:000000011027D3D8                 align 20h
.data:000000011027D3E0                 dq offset a504          ; "504"
.data:000000011027D3E8                 dq offset aConfirm_1    ; "Confirm :"
.data:000000011027D3F0                 dq offset aConfirmer    ; "Confirmer :"
.data:000000011027D3F8                 dq offset aBestatigung_1 ; "Bestätigung :"
.data:000000011027D400                 dq offset aConfirmar    ; "Confirmar"
.data:000000011027D408                 align 10h
.data:000000011027D410                 dq offset a505          ; "505"
.data:000000011027D418                 dq offset aThisCodeHasAlr ; "This code has already been activated !"
.data:000000011027D420                 dq offset aCeCodeADejaEte ; "Ce code a déjà été activé !"
.data:000000011027D428                 dq offset aDieserCodeWurd ; "Dieser Code wurde bereits aktiviert !"
.data:000000011027D430                 dq offset aEsteCodigoHaSi ; "Este código ha sido activado anteriorme"...
.data:000000011027D438                 align 20h
.data:000000011027D440                 dq offset a506          ; "506"
.data:000000011027D448                 dq offset aPleaseConfirmT ; "Please confirm that you wish to re-acti"...
.data:000000011027D450                 dq offset aSvpConfirmerQu ; "SVP confirmer que vous souhaitez le réa"...
.data:000000011027D458                 dq offset aBestatigenSieB ; "Bestätigen Sie bitte, daß Sie reaktivie"...
.data:000000011027D460                 dq offset aPorFavorConfir ; "Por favor, confirme que desea reactivar"...
.data:000000011027D468                 align 10h
.data:000000011027D470                 dq offset a507          ; "507"
.data:000000011027D478                 dq offset aForgotYourPass ; "&Forgot your Password ?"
.data:000000011027D480                 dq offset aMotDePasseOubl ; "&Mot de passe oublié ?"
.data:000000011027D488                 dq offset aPasswortVerges ; "&Passwort vergessen?"
.data:000000011027D490                 dq offset aOlvidoSuClaveD ; "&Olvidó su Clave de acceso?"
.data:000000011027D498                 align 20h
.data:000000011027D4A0                 dq offset a508          ; "508"
.data:000000011027D4A8                 dq offset aReActivate   ; "&Re-Activate"
.data:000000011027D4B0                 dq offset aReactiver    ; "&Réactiver"
.data:000000011027D4B8                 dq offset aReaktivierung ; "&Reaktivierung"
.data:000000011027D4C0                 dq offset aReactivar    ; "&Reactivar"
.data:000000011027D4C8                 align 10h
.data:000000011027D4D0                 dq offset a509          ; "509"
.data:000000011027D4D8                 dq offset aCancel_4     ; "&Cancel"
.data:000000011027D4E0                 dq offset aAnnuler_2    ; "&Annuler"
.data:000000011027D4E8                 dq offset aAbbrechen_2  ; "&Abbrechen"
.data:000000011027D4F0                 dq offset aCancelar_2   ; "&Cancelar"
.data:000000011027D4F8                 align 20h
.data:000000011027D500                 dq offset a510          ; "510"
.data:000000011027D508                 dq offset aPasswordsDonTM_0 ; "Passwords don't match"
.data:000000011027D510                 dq offset aLesMotsDePasse_0 ; "Les mots de passe ne sont pas identique"...
.data:000000011027D518                 dq offset aPassworterStim_0 ; "Passwörter stimmen nicht überein"
.data:000000011027D520                 dq offset aLasClavesDeAcc_0 ; "Las claves de acceso no concuerdan"
.data:000000011027D528                 align 10h
.data:000000011027D530                 dq offset a511          ; "511"
.data:000000011027D538                 dq offset aYourPasswordHa ; "Your password has been sent"
.data:000000011027D540                 dq offset aVotreMotDePass ; "Votre mot de passe a été envoyé"
.data:000000011027D548                 dq offset aIhrPasswortWur ; "Ihr Passwort wurde gesendet"
.data:000000011027D550                 dq offset aSuClaveDeAcces ; "Su clave de acceso ha sido enviada"

py

from Crypto.Math.Numbers import Integer
from Crypto.Math.Primality import generate_probable_prime

from Crypto.Cipher import AES

from Crypto.Util.number import bytes_to_long, long_to_bytes
from Crypto.PublicKey import RSA
from Crypto import Random
import hashlib
import base64
import ctypes
from ctypes import wintypes
import os


def get_volume_serial_number(drive_letter: str):
    # 确保驱动器字母格式正确
    if not drive_letter.endswith('\\'):
        drive_letter += '\\'

    # 定义函数参数和返回类型
    kernel32 = ctypes.WinDLL('kernel32', use_last_error=True)
    kernel32.GetVolumeInformationW.argtypes = [
        wintypes.LPCWSTR,   # lpRootPathName
        wintypes.LPWSTR,    # lpVolumeNameBuffer
        wintypes.DWORD,     # nVolumeNameSize
        ctypes.POINTER(wintypes.DWORD),  # lpVolumeSerialNumber
        ctypes.POINTER(wintypes.DWORD),  # lpMaximumComponentLength
        ctypes.POINTER(wintypes.DWORD),  # lpFileSystemFlags
        wintypes.LPWSTR,    # lpFileSystemNameBuffer
        wintypes.DWORD      # nFileSystemNameSize
    ]
    kernel32.GetVolumeInformationW.restype = wintypes.BOOL

    # 准备参数
    volume_name_buffer = ctypes.create_unicode_buffer(1024)
    volume_serial_number = wintypes.DWORD()
    max_component_length = wintypes.DWORD()
    file_system_flags = wintypes.DWORD()
    file_system_name_buffer = ctypes.create_unicode_buffer(1024)

    # 调用函数
    success = kernel32.GetVolumeInformationW(
        drive_letter,
        volume_name_buffer,
        ctypes.sizeof(volume_name_buffer),
        ctypes.byref(volume_serial_number),
        ctypes.byref(max_component_length),
        ctypes.byref(file_system_flags),
        file_system_name_buffer,
        ctypes.sizeof(file_system_name_buffer)
    )

    if not success:
        error_code = ctypes.get_last_error()
        raise RuntimeError(
            f"GetVolumeInformationW failed with error code {error_code}")

    # 格式化序列号
    ser_num = volume_serial_number.value
    return f'{ser_num:08X}'
    high = ser_num >> 16
    low = ser_num & 0xFFFF
    return f"{high:04X}-{low:04X}"


def get_disk_space(drive_letter: str):
    # 确保驱动器字母格式正确
    if not drive_letter.endswith('\\'):
        drive_letter += '\\'

    # 定义函数参数和返回类型
    kernel32 = ctypes.WinDLL('kernel32', use_last_error=True)
    kernel32.GetDiskFreeSpaceExW.argtypes = [
        wintypes.LPCWSTR,      # lpDirectoryName
        ctypes.POINTER(ctypes.c_ulonglong),  # lpFreeBytesAvailable
        ctypes.POINTER(ctypes.c_ulonglong),  # lpTotalNumberOfBytes
        ctypes.POINTER(ctypes.c_ulonglong)   # lpTotalNumberOfFreeBytes
    ]
    kernel32.GetDiskFreeSpaceExW.restype = wintypes.BOOL

    # 准备参数
    free_bytes_available = ctypes.c_ulonglong()
    total_number_of_bytes = ctypes.c_ulonglong()
    total_number_of_free_bytes = ctypes.c_ulonglong()

    # 调用函数
    success = kernel32.GetDiskFreeSpaceExW(
        drive_letter,
        ctypes.byref(free_bytes_available),
        ctypes.byref(total_number_of_bytes),
        ctypes.byref(total_number_of_free_bytes)
    )

    if not success:
        error_code = ctypes.get_last_error()
        raise RuntimeError(
            f"GetDiskFreeSpaceExW failed with error code {error_code}")

    return {
        'total_bytes': total_number_of_bytes.value,
        'free_bytes': free_bytes_available.value,
        'used_bytes': total_number_of_bytes.value - free_bytes_available.value
    }


def get_computer_name():
    return os.environ['COMPUTERNAME']


COMPUTER_NAME = get_computer_name()


def gen_MACHINE_ID(drive_letter: str = "C:") -> str:
    m_id = str(586)
    m_id += get_volume_serial_number(drive_letter)
    m_id += str(get_disk_space(drive_letter)['total_bytes'])
    m_id += COMPUTER_NAME
    return hashlib.md5(m_id.encode()).hexdigest().upper()


MACHINE_ID = gen_MACHINE_ID()
B64_Table = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'


def b64_to_value(char):
    if char in B64_Table:
        return B64_Table.index(char)
    else:
        return -1


def int2b64(n: int) -> str:
    if n == 0:
        return B64_Table[0]
    result = []
    # 不断除以64并取余数
    while n > 0:
        remainder = n % 64
        result.append(B64_Table[remainder])
        n = n // 64

    base64_str = ''.join(reversed(result))

    return base64_str


def b64toint(s: str) -> int:
    n = 0
    for i, x in enumerate(s[::-1]):
        n += B64_Table.index(x)*(0x40**i)
        # n+=b64_to_value(x)*(0x40**i)
    # print(n)
    return n


def generate(bits, randfunc=None, e=65537):
    """Create a new RSA key pair.

    The algorithm closely follows NIST `FIPS 186-4`_ in its
    sections B.3.1 and B.3.3. The modulus is the product of
    two non-strong probable primes.
    Each prime passes a suitable number of Miller-Rabin tests
    with random bases and a single Lucas test.

    Args:
      bits (integer):
        Key length, or size (in bits) of the RSA modulus.
        It must be at least 1024, but **2048 is recommended.**
        The FIPS standard only defines 1024, 2048 and 3072.
    Keyword Args:
      randfunc (callable):
        Function that returns random bytes.
        The default is :func:`Crypto.Random.get_random_bytes`.
      e (integer):
        Public RSA exponent. It must be an odd positive integer.
        It is typically a small number with very few ones in its
        binary representation.
        The FIPS standard requires the public exponent to be
        at least 65537 (the default).

    Returns: an RSA key object (:class:`RsaKey`, with private key).

    .. _FIPS 186-4: http://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.186-4.pdf
    """

    # if bits < 1024:
    #     raise ValueError("RSA modulus length must be >= 1024")
    if e % 2 == 0 or e < 3:
        raise ValueError(
            "RSA public exponent must be a positive, odd integer larger than 2.")

    if randfunc is None:
        randfunc = Random.get_random_bytes

    d = n = Integer(1)
    e = Integer(e)

    while n.size_in_bits() != bits and d < (1 << (bits // 2)):
        # Generate the prime factors of n: p and q.
        # By construciton, their product is always
        # 2^{bits-1} < p*q < 2^bits.
        size_q = bits // 2
        size_p = bits - size_q

        min_p = min_q = (Integer(1) << (2 * size_q - 1)).sqrt()
        if size_q != size_p:
            min_p = (Integer(1) << (2 * size_p - 1)).sqrt()

        def filter_p(candidate):
            return candidate > min_p and (candidate - 1).gcd(e) == 1

        p = generate_probable_prime(exact_bits=size_p,
                                    randfunc=randfunc,
                                    prime_filter=filter_p)

        min_distance = Integer(1) << (bits // 2 - 100)

        def filter_q(candidate):
            return (candidate > min_q and
                    (candidate - 1).gcd(e) == 1 and
                    abs(candidate - p) > min_distance)

        q = generate_probable_prime(exact_bits=size_q,
                                    randfunc=randfunc,
                                    prime_filter=filter_q)

        n = p * q
        lcm = (p - 1).lcm(q - 1)
        d = e.inverse(lcm)

    if p > q:
        p, q = q, p

    u = p.inverse(q)

    return RSA.RsaKey(n=n, e=e, d=d, p=p, q=q, u=u)


def gen_rsa_key():
    key = generate(512)
    e = key.e
    n = key.n
    d = key.d
    print(f'e:{e}')
    print(f'd:{d}')
    print(f'n:{n}')
    enc_e = int2b64(e)
    enc_d = int2b64(d)
    enc_n = int2b64(n)
    print(f'enc_e:{enc_e}')
    print(f'enc_d:{enc_d}')
    print(f'enc_n:{enc_n}')


'''
e:65537
d:2315142751447774213952423067949813422569754036134759105608004489422512735584755869184456019497130666058725012033222813113267097391007513555249989601567353
n:10285564891816613812819032003811607109443376623812067078211150745570499078196870907576605909732992329074468778493495219319635616763418198567059489030994767
enc_e:QAB
enc_d:sNC6af1sqxUzCGT3XaAIHln7ngLgrbHOOmnP8x0T/EkeNENLF0J1WdWd+rfxMqW2Q2pYtdPf4mJ2TeOeMgaJ5
enc_n:DEYss/FyLOVPDC4yXMyQVYxFqE8ZlaQtkRHrxdu/wwIn6gDbxgQNj3uKd5I/YV8na5pnHZZP9j56ejPiKlzPtP


QAB:DEYss/FyLOVPDC4yXMyQVYxFqE8ZlaQtkRHrxdu/wwIn6gDbxgQNj3uKd5I/YV8na5pnHZZP9j56ejPiKlzPtP

'''
E = 65537
D = 2315142751447774213952423067949813422569754036134759105608004489422512735584755869184456019497130666058725012033222813113267097391007513555249989601567353
N = 10285564891816613812819032003811607109443376623812067078211150745570499078196870907576605909732992329074468778493495219319635616763418198567059489030994767


def base256_string_to_int(s: bytes):
    # bytes_to_long
    if isinstance(s, str):
        s = s.encode()
    """
    将 Base256 字符串转换为整数
    """
    result = 0
    for char in s:
        result = (result << 8) | char
    return result


def int_to_base256_string(n: int) -> bytes:
    """
    == long_to_bytes
    将整数转换为 Base256 字符串
    """
    if n == 0:
        return chr(0)

    result = b""
    while n > 0:
        result = (n & 0xFF).to_bytes(1, 'little') + result
        n >>= 8

    return result


def rsa_Sign_b64enc(msg: bytes, d: int = D, n: int = N):
    # Sign strings with the RSA algorithm, M^d mod n = S
    if isinstance(msg, str):
        msg = msg.encode()
    # m_int=int.from_bytes(msg,'little')
    m_int = bytes_to_long(msg)
    # print('m_int:',m_int)
    # print('m_int_bs:',long_to_bytes(m_int).hex())
    # m_int %= n
    print('[-]m_int:', m_int)
    print('[-]m_int_bs:', long_to_bytes(m_int).hex())

    # m_int=base256_string_to_int(msg)
    # print('m_int:',m_int)
    s = pow(m_int, d, n)
    print('[-]sign_int:', s)
    sign = long_to_bytes(s)
    print('[-]sign_bs:', sign.hex())
    return base64.standard_b64encode(sign)


def rsa_Verify_b64(msg: bytes, sign_b64: bytes, e: int = E, n: int = N):
    if isinstance(msg, str):
        msg = msg.encode()
    sign = base64.standard_b64decode(sign_b64)
    s_int = bytes_to_long(sign)
    m_int = pow(s_int, e, n)
    print('[-]dec_sign:', m_int)
    m = long_to_bytes(m_int)
    print('[-]dec_sign_bs:', m)
    v = m_int == (bytes_to_long(msg) % N)
    print('[+]Verify:', v)
    return v


def x_aes_cfb_b64enc(k: bytes, msg: bytes):
    if isinstance(k, str):
        k = k.encode()
    if isinstance(msg, str):
        msg = msg.encode()
    key = hashlib.md5(k).digest()
    iv = AES.new(key=key, mode=AES.MODE_ECB).encrypt(b'\x00'*16)

    print(f'[-]aes_key:{key.hex()}')
    print(f'[-]aes_iv:{iv.hex()}')
    aes_cipher = AES.new(key=key, iv=iv, mode=AES.MODE_CFB)
    ret = aes_cipher.encrypt(msg)
    return base64.b64encode(ret)
    # return ret


def x_aes_cfb_b64dec(k: bytes, data: bytes):
    if isinstance(k, str):
        k = k.encode()
    data = base64.standard_b64decode(data)
    key = hashlib.md5(k).digest()
    iv = AES.new(key=key, mode=AES.MODE_ECB).encrypt(b'\x00'*16)

    print(f'[-]aes_key:{key.hex()}')
    print(f'[-]aes_iv:{iv.hex()}')
    aes_cipher = AES.new(key=key, iv=iv, mode=AES.MODE_CFB)
    ret = aes_cipher.decrypt(data)
    return ret


def parse_rsa_pub_key(rsa_key_str='QAB:D2fhogQkHWOB0jVkEtrS3lr6hgNe/O7pAkxsv2OVHTT6AHyWdPJv1KIwLpUoPh/D1N+BVQ5jGQ1a+nJpptW0SX'):
    rsa_key = rsa_key_str.split(':')
    exp = b64toint(rsa_key[0])
    mod = b64toint(rsa_key[1])
    print('exp:', exp)
    print('exp_bs:', exp.to_bytes(4, 'little').hex())
    print('mod:', mod)
    print('mod_bs:', mod.to_bytes(0x40, 'little').hex())
    return exp, mod


def gen_CDM_text(save_path:str='',vdate: str = '09/07/2025'):
    text = '\r\n'.join(
        (
            f'VALIDATION_DATE={vdate}',
            'PROTECTION_LEVEL=1',
            f'MACHINE_ID={MACHINE_ID}\r\n'
        )
    )
    SIGNATURE = rsa_Sign_b64enc(text).decode()
    text += f'SIGNATURE={SIGNATURE}\r\n'
    k = r"[MQ(UL/&C:&a7eEW"
    enc = x_aes_cfb_b64enc(k, text)
    cdm=enc.decode()+'|1'
    print('[#]CDM text==>\n%s' % cdm)
    # dec=x_aes_cfb_b64dec(k,enc)
    # print(dec.decode())
    if save_path:
        with open(save_path,'w') as f:
            f.write(cdm)
            print('[+]save cdm to==>',save_path)
    pass

def parse_cdm(fpath:str):
    data=b''
    with open(fpath,'rb') as f:
        data=f.read()
    if data:
        dec=x_aes_cfb_b64dec( r"[MQ(UL/&C:&a7eEW",data)
        print(dec.decode())
        return dec
    

def fgint_to_int(fgint_number):
    """
    将 FGInt.Number 数组转换为 Python 整数

    参数:
    fgint_number: 列表,第一个元素是数组长度,后续元素是实际数据

    返回:
    Python 整数
    """
    if not fgint_number:
        return 0

    # 第一个元素是数组长度
    n = fgint_number[0]

    # 处理特殊情况:空数组或长度为0
    if n == 0:
        return 0

    result = 0
    # 从最高位开始处理(数组的最后一个元素是最高位)
    for i in range(n, 0, -1):
        # 将当前部分左移31位,然后与结果合并
        result = (result << 31) | fgint_number[i]

    return result


def test_fgint():
    m = fgint_to_int([0x00000018, 0x33300D0A, 0x6E848686, 0x6114E0D8, 0x3A119199, 0x73042333, 0x07068846, 0x0C0C4DCE,
                      0x1CA21822, 0x3D363338, 0x0ABE9288, 0x0D212539, 0x68526A0A, 0x54C3D310, 0x6988AAC8, 0x1253D397,
                      0x2A22A1AA, 0x0A50524F, 0x60646A1A, 0x40DCBCC8, 0x6981C979, 0x44154453, 0x29E9CBE8, 0x51105512,
                      0x2B20A624])
    print('m:', m)
    print('m_bs:', long_to_bytes(m).hex())


def test_rsa_enc():
    '''
    offine;  
    .lic use rsa_enc; 
    NESMaker unuse
    '''
    # t=int2b64(65537)
    # print(t)
    rsa_key_str = 'QAB:D2fhogQkHWOB0jVkEtrS3lr6hgNe/O7pAkxsv2OVHTT6AHyWdPJv1KIwLpUoPh/D1N+BVQ5jGQ1a+nJpptW0SX'
    # rsa_key_str='QAB:DuYQfR+z9n79UFzMSBlXVOtjIJLuJUapcwG4s8GI9HKNdYD9gtTiG73iM9Ll4yBtao4/YN+v8BgPdctP0wvSYd'
    k = b'JBCHDNSZWT44B36S'#random_key_str  random_key_1102AD890
    rsa_key = rsa_key_str.split(':')
    exp = b64toint(rsa_key[0])
    mod = b64toint(rsa_key[1])
    print('exp:', exp)
    print('exp_bs:', exp.to_bytes(4, 'little').hex())
    print('mod:', mod)
    print('mod_bs:', mod.to_bytes(0x40, 'little').hex())

    # RSAEncrypt
    random_key = 0b111.to_bytes(1, 'little')+k
    p = int.from_bytes(random_key, 'big')
    print('p:', p.to_bytes(0x40, 'little'))
    Enc: int = pow(p, exp, mod)

    x = Enc.to_bytes(0x40, 'big')
    print('E:', x.hex())
    print(base64.standard_b64encode(x))


def test_rsa_verify():
    '''Verify'''
    msg = b'popk'
    sign_b64 = rsa_Sign_b64enc(msg)
    ok = rsa_Verify_b64(msg, sign_b64)
    print(ok)
    pass


if __name__ == "__main__":

    # gen_rsa_key()
    # parse_rsa_pub_key()

    # test_fgint()

    # test_rsa_enc()
    # test_rsa_verify()
    # cdm_path='C:\\Users\\Public\\NESMaker\\NESMaker.CDM'
    cdm_path='xxx.cdm'
    validation_date='09/07/2025'
    gen_CDM_text(cdm_path,validation_date)

    print('\n\n[+]parse_cdm:')
    parse_cdm(cdm_path)
    pass


'''
[-]m_int: 31178946879257292080898240688144354096635147173692852980966625521388923503413672082345513126911752778805311863617272330815814095581703302651273131528539640583977426287721202654953948320197003686583134745256644711333795728650
[-]m_int_bs: 56414c49444154494f4e5f444154453d30392f30372f323032350d0a50524f54454354494f4e5f4c4556454c3d310d0a4d414348494e455f49443d36333839443044303137383834423730423337423233384538363742434333300d0a
[-]sign_int: 1333855104739181946828192935857681260161462519271575509983654792872898270838449267810765543894119693776075229040494657515955471535802349330038939333573169
[-]sign_bs: 1977bf790f3cb5accc3eb11ca853ffbb8c16a4361cbeaa82f60d48f83b8754c90a1f5c6fd39260a53a986f70245cdf51c75360853e328d80c1e7c72e609a3a31
[-]aes_key:d181d4c2f5d1db0a997db7337a7182a5
[-]aes_iv:ad63cf43f5b0b05b3f3618a0384e8fb9
[#]CDM text==>
y9R02uquDNP24sly54empJ/o3cTurrFYgwwTb1aa0ZXZSMV7C1LlX6LKRF0duy+U5dBAWcYQhaQSypyjQBZ/d0fPt6dP+mrz1dlxfda6hD0Xgg00cPoQaY0uygd96ZrnaxZ2Tq/I0VJamm9HyO4a4IiHD6NPjgHtSxwIbhg1QgBvCuC3SPuqd9ic3oMaok4sPbQAfO0NjiQAuPvaVu1eYEurXmbHRcOxu+7cL54AILOG0N+oIjxyyzDPwgDWLCHKnw==|1
[+]save cdm to==> xxx.cdm


[+]parse_cdm:
[-]aes_key:d181d4c2f5d1db0a997db7337a7182a5
[-]aes_iv:ad63cf43f5b0b05b3f3618a0384e8fb9
VALIDATION_DATE=09/07/2025
PROTECTION_LEVEL=1
MACHINE_ID=6389D0D017884B70B37B238E867BCC30
SIGNATURE=GXe/eQ88tazMPrEcqFP/u4wWpDYcvqqC9g1I+DuHVMkKH1xv05JgpTqYb3AkXN9Rx1NghT4yjYDB58cuYJo6MQ==

'''

ps

image-20250913124854118

posted @ 2025-09-13 13:42  DirWangK  阅读(41)  评论(0)    收藏  举报