提升软件安全性 - 运用Inno Setup打包技术实现序列号与机器绑定

背景

  • 随着数字化时代的到来,软件已成为日常生活中不可或缺的一部分。无论是企业级应用还是个人用户,都需要通过软件实现各种功能。然而,在这种情况下,软件的安全性变得越来越重要。
  • 为了防止未经授权的复制和传播,许多软件开发商选择对他们的产品实施许可证管理策略。这其中的一种常见方法就是使用序列号,只有当用户输入正确的序列号时,才能激活并正常使用该软件。
  • 在此背景下,本文将介绍如何使用Inno Setup打包工具,在生成安装包时加入序列号并与用户机器进行绑定。
  • inno setup打包入门

意义

  • 通过使用Inno Setup将序列号与机器绑定,开发者可以有效防止软件被非法复制或滥用,从而提高软件的安全性和收益。此外,这一方法还能帮助企业更好地跟踪软件的安装情况,以了解产品的实际使用情况并制定合理的市场营销策略。因此,掌握这一技能对于软件开发人员来说具有重要的实践意义。

效果

  • 可以看下,不输入序列号或者输入无效序列号,都是无法进行下一步的
    在这里插入图片描述
  • 只有输入有效的序列号,才能进行下一步,继续安装
    在这里插入图片描述

方案说明

方案一

  • 直接在打包脚本中写死一个序列号。这样比较简单,也能实现输入注册码才能安装的功能,但缺点也很明显,注册码没有唯一性,只要序列号公布出去,任何人都可以拿到,仍然阻止不了软件的非法复制和滥用。

方案二

  • 打包过程中,获取一个唯一性标识,要保证这个标识每一台机器都不一样。
  • 在 Windows 注册表这个位置 计算机\HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Cryptography,有一个MachineGuid项,这个项的值每一个系统都是不一样的,可以作为唯一性标识。
  • 然后安装过程中,在安装界面获取这个唯一性标识,让用户把唯一性标识发给我们,我们再对这个标识作摘要计算,计算的结果作为序列号,发送给用户。
  • 这样就能保证每一个系统的序列号都是唯一的。但很容易被破解,稍微有点密码学基础的人,就可以看出这个序列号是对唯一性标识作简单摘要得到的,他们完全可以自己计算获取序列号。

方案三

  • 在方案二的基础上,拿到用户的唯一性标识后,在后面拼接一段冗余数据,再对拼接完成的数据作摘要计算,计算的结果发送给用户作为序列号。
  • 这个冗余数据可以看成是密钥,只要密钥没有泄露,那序列号就无法被破解或者说破解的难度将大大增加。

代码

  •   #define MyDebugAppName "TCP调试助手"
      
      #define MyDebAppVersion "1.0.2"
      
      // 获取系统时间
      #define tcpDebugPackDateTimeString GetDateTimeString('yyyymmdd','','')
      
      #define serialNumberData GetDateTimeString('yyyy','','')
      
      [setup]
      
      ; 安装应用程序的标题
      AppName={#MyDebugAppName}
      
      ; 安装应用程序版本号
      AppVersion = {#MyDebAppVersion}
      
      ; 默认安装目录
      DefaultDirName={pf}
      
      ; 控制面板中显示
      CreateUninstallRegKey=yes
      
      ; 编译输出文件夹
      OutputDir=.\output
      
      ; 编译后的安装包文件名
      OutputBaseFilename=TcpDebugTools_{#MyDebAppVersion}_{#tcpDebugPackDateTimeString}
      
      ; 允许安装过程中取消进程
      AllowCancelDuringInstall=yes
      
      ;卸载程序路径
      UninstallFilesDir={app}\TcpDebugTools
      
      ; 不显示开始菜单文档向导页面
      DisableProgramGroupPage=yes
      
      ; 默认包含卸载程序在安装程序中
      Uninstallable=yes
      
      ; 设置为no,表示显示欢迎向导页面
      DisableWelcomePage=no
      
      SetupIconFile=.\candy.ico
      
      // 设置该参数后,才有序列号校验界面
      UserInfoPage=yes
      
      [Languages]
      Name: "Chinese"; MessagesFile: "compiler:Languages\Chinese.isl"
      
      [Icons]
      ;创建卸载程序
      Name: "{group}\卸载"; Filename: "{app}\TcpDebugTools\unins000.exe"
      ;创建桌面图标
      Name: {commondesktop}\{#MyDebugAppName}; Filename: "{app}\TcpDebugTools\networkDebugTools.exe"; WorkingDir: "{app}\TcpDebugTools"; IconFilename:"{app}\TcpDebugTools\image\logo.ico"
      
      [Files]
      Source: "..\bin\Release\*"; DestDir: "{app}\TcpDebugTools"
      Source: "..\bin\Release\image\*"; DestDir: "{app}\TcpDebugTools\image"
      Source: "..\bin\Release\platforms\*"; DestDir: "{app}\TcpDebugTools\platforms"
      Source: "..\bin\Release\config\*"; DestDir: "{app}\TcpDebugTools\config"
      
      [code]
      procedure InitializeWizard();
      begin
        WizardForm.WelcomeLabel1.Caption:= '欢迎使用 TCP调试助手';
        WizardForm.WelcomeLabel2.Caption:= '版本 {#MyDebAppVersion}';
      
        WizardForm.USERINFOSERIALLABEL.top := WizardForm.USERINFOORGLABEL.top+2*(WizardForm.USERINFOORGLABEL.top - WizardForm.USERINFONAMELABEL.top); 
        WizardForm.USERINFOSERIALEDIT.top := WizardForm.USERINFOORGEDIT.top+2*(WizardForm.USERINFOORGEDIT.top - WizardForm.USERINFONAMEEDIT.top); 
        WizardForm.USERINFOSERIALLABEL.Font.Color := clblack;
      end;
      
      
      function InitializeSetup(): Boolean;
      var strCmdKill: String;
      var ErrorCode: Integer;
      begin
        strCmdKill := Format('/c taskkill /f /t /im networkDebugTools.exe', []);
        ShellExec('open', ExpandConstant('{cmd}'), strCmdKill, '', SW_HIDE, ewNoWait, ErrorCode);
        Result := true;
      end;
      
      // 获取机器码
      function getMachineGuid(): String;
      var strMachineGUID: String;
      begin
        // 从注册表获取MachineGuid的值
        if RegValueExists(HKLM64, 'SOFTWARE\Microsoft\Cryptography', 'MachineGuid') then
          begin
            RegQueryStringValue(HKLM64, 'SOFTWARE\Microsoft\Cryptography', 'MachineGuid', strMachineGUID)
          end
        // 防止有的系统没有这一项,获取当前日期作为机器码
        else
          begin
            strMachineGUID := '{#serialNumberData}'
          end;
      
      Result := strMachineGUID;
      end;
      
      // 检查序列号
      function CheckSerial(Serial: String): Boolean;
      var strMachineGUID: String;
      var serialNumber: String;
      var serialNumberEncrypt: String;
      var encryptKey: String;
      begin  
        // 此冗余数据可以看作是密钥
        encryptKey := '20240101';
      
        // 拼接用户的机器码和冗余数据
        serialNumber := getMachineGuid() + encryptKey;
        
        // 弹框可以调试时使用
        //MsgBox(serialNumber, mbInformation, MB_OK);
      
        // 对拼接好的数据作MD5摘要计算,结果作为序列号
        serialNumberEncrypt := GetMD5OfString(serialNumber);
        // 比对用户输入的序列号是否正确,返回true才可以继续进行下一步
        if Serial = serialNumberEncrypt then
          Result := True;
      end;
      
      procedure curpagechanged(curpage: integer);
      var IDLabel, RegAdr : TLabel; 
        IDEdit: TEdit; 
        RefDisk: String;
      begin
        IDLabel:= TLabel.Create(WizardForm);  
        IDLabel.parent:= WizardForm.USERINFONAMELABEL.parent;  
        IDLabel.top:= WizardForm.USERINFONAMELABEL.top+2*(WizardForm.USERINFOORGLABEL.top - WizardForm.USERINFONAMELABEL.top);  
        IDLabel.left:= WizardForm.USERINFOSERIALLABEL.left;  
        IDLabel.autosize:= true;  
        IDLabel.font.color:= clblack;  
        IDLabel.caption:= '机器码:';
      
        RegAdr:= TLabel.Create(WizardForm);  
        RegAdr.parent:= WizardForm.USERINFONAMELABEL.parent;  
        RegAdr.top:= WizardForm.USERINFOSERIALLABEL.top+(WizardForm.USERINFOORGLABEL.top - WizardForm.USERINFONAMELABEL.top) - 7;  
        RegAdr.left:= WizardForm.USERINFOSERIALLABEL.left + 195;  
        RegAdr.autosize:= true;  
        RegAdr.caption:= '注册请联系 : https://blog.csdn.net/new9232';
      
        IDEdit:= TEdit.Create(WizardForm);  
        IDEdit.parent:= WizardForm.USERINFONAMEEDIT.parent;  
        IDEdit.top:= WizardForm.USERINFONAMEEDIT.top+2*(WizardForm.USERINFOORGEDIT.top - WizardForm.USERINFONAMEEDIT.top);  
        IDEdit.left:= WizardForm.USERINFOSERIALEDIT.left;  
        IDEdit.width:= WizardForm.USERINFOSERIALEDIT.width;  
        IDEdit.readonly:= true;   
        // 安装界面展示用户机器码
        IDEdit.text := getMachineGuid(); 
      end;
        
      [UninstallRun]
      ; 卸载前杀掉进程
      Filename: taskkill;Parameters:"/t /f /im networkDebugTools.exe";Flags: runhidden
      
      [UninstallDelete]
      ; 卸载后删除安装目录下所有文件
      Type: filesandordirs; Name: "{app}\TcpDebugTools"
    
  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
习惯使用的打包工具就是 Inno Setup,而 Inno Setup 是用于安装软件的流行程序。不幸的是,没有官方的解压程序-将文件从自解压的可执行文件中取出的唯一方法是运行它。对于使用 Inno Setup 创建的安装程序的用户,Inno Setup Unpacker 可以派上用场。该工具严格从命令行运行,可让您从其安装包中快速提取安装文件。 解决此问题的一个软件是 Sergei Wanin 的 InstallExplorer,它是 FAR Manager 的插件,可以解压缩多种安装类型,包括 Inno Setup(IS)。 但是由于它没有及时更新,因此大部分时间都不支持最新的 IS,因此该程序诞生了。 Inno Setup 提取工具 Inno Setup Unpacker 中文版Inno Setup 提取工具 Inno Setup Unpacker 中文版 与 InstallExplorer 相比优点是: Innounp 是开源的,基于IS源码。 因此,它更有可能支持将来的IS版本。 它会恢复安装脚本(.iss文件)的一部分,包括注册表更改和已编译的 Innerfuse/RemObjects Pascal 脚本(如果有)。 Inno Setup 管理变得简单 Inno Setup 是一个流行且可靠的应用程序,可通过帮助您生成脚本来促进程序安装程序的创建。使用 Inno Setup 编译代码会导致从容器中解压缩安装文件,只能通过自解压文件来完成。换句话说,您需要创建一个自解压的可执行文件来封装安装文档。 Inno Setup Unpacker 可以帮助您避免此类操作,这特别有用,因为多种系统安全协议会阻止可执行文件的下载。该程序允许您通过几次按键从存档中提取文件。 从命令行运行程序 Inno Setup Unpacker 没有 GUI,但是您可以查看所有功能并从命令行轻松操作它。可能需要管理权限才能打开程序,但否则程序运行就没有问题。 Inno Setup Unpacker 的功能包括命令和选项。这些命令包括显示安装信息,详细列出文件,将文件提取到当前目录。您也可以提取不带路径的文件并测试它们的完整性。 至于选项,例如,您可以启用批处理模式,提取内部嵌入式文件,使用密码解密安装或提取所有重复文件的副本。 简单的使用说明 在命令行中打开 Inno Setup Unpacker 时,您可以查看命令,选项和使用说明的列表。该程序使您可以快速,轻松地从 Inno Setup 软件包中提取文件。此外,它使用简单,无需安装。 用法 Innounp是一个控制台应用程序,它使用命令行选项来找出要执行的操作。有关使用FAR或Total Commander作为前端的更人性化的界面,请参见下面的MultiArc部分。 Windows资源管理器爱好者:nullz制作了一些.reg脚本,以将innounp添加到右键菜单中,而Richard Santaella为innounp制作了图形包装(在下载页面上获取)。 innounp [command] [options] [@filelist] [filemask …] 命令: (no) 显示常规安装信息 -v 详细列出文件(带有大小和时间戳) -x 从安装中提取文件(到当前目录,另请参见 -d) -e 提取没有路径的文件 -t 测试文件的完整性 选项: -b 批处理(非交互式)模式-不会提示您输入密码或更改磁盘 -q 提取时不指示进度 -m 处理内部嵌入式文件(例如 license 和 uninstall.exe) -pPASS 使用密码解密安装 -dDIR 将文件提取到 DIR 中(可以是绝对路径,也可以是相对路径) -cDIR 指定 DIR 是安装中的当前目录 -n 不要尝试解压缩新版本 -fFILE 与 -p 相同,但是从 FILE 读取密码 -a 处理重复文件的所有副本 -y 在所有查询中均假设为“是”(例如覆盖文件) 如果安装程序具有 setup.0(在不使用 SetupLdr 的情况下进行安装),请在 setup.0 而不是 setup.exe 上运行 innounp。 要从特定目录提取所有文件,请使用 dirname \ *.*,而不仅仅是 dirname。 默认情况下,所有文件都提取到当前目录。使用 -d 替代此行为。例如,-dUnpacked 将在当前目录内创建一个名为 Unpacked 的目录,并将提取的文件放在此处。 -c 选项很难解释。假设您在文件管理器中打开了一个安装,然后浏览到 {app}\subdir\program.exe。现在,如果将 program.exe 复制到另一个位置,将创建整个目录树
要使用Inno Setup打包MySQL 8.0.30,首先需要下载MySQL的安装程序和Inno Setup软件。 1. 下载MySQL 8.0.30安装程序:进入MySQL官方网站,找到下载页面,下载MySQL 8.0.30的安装程序。保存到本地目录。 2. 下载Inno Setup软件:进入Inno Setup的官方网站,找到下载页面,下载最新版本的Inno Setup软件。保存到本地目录,并安装在你的电脑上。 3. 创建Inno Setup脚本文件:使用文本编辑器,新建一个空的文本文件。将以下代码复制到该文件中: ``` [Setup] AppName=MySQL 8.0.30 AppVersion=8.0.30 DefaultDirName={pf}\MySQL\MySQL Server 8.0 DefaultGroupName=MySQL AllowNoIcons=yes OutputDir=userdocs:Inno Setup Examples Output [Files] Source: "C:\path\to\mysql-8.0.30-installer.exe"; DestDir: "{tmp}"; Flags: deleteafterinstall [Run] Filename: "{tmp}\mysql-8.0.30-installer.exe"; Parameters: "--install-server"; WorkingDir: "{tmp}"; StatusMsg: "Installing MySQL 8.0.30, please wait..." [UninstallDelete] Type: files; Name: "{app}\unins000.dat" Type: files; Name: "{app}\unins000.exe" [Tasks] Name: "desktopicon"; Description: "Create a desktop icon"; GroupDescription: "Additional tasks:"; Flags: unchecked [Icons] Name: "{commondesktop}\MySQL 8.0.30"; Filename: "{app}\{#MyAppExeName}" [Run] Filename: "{app}\{#MyAppExeName}"; Description: "{cm:LaunchProgram,{#StringChange(MyAppName, '&', '&&')}}"; Flags: nowait postinstall skipifsilent ``` 4. 修改脚本文件中的路径:将代码中的"C:\path\to\mysql-8.0.30-installer.exe"修改为你自己保存MySQL安装程序的路径。 5. 保存脚本文件:将该文本文件保存为任意名称的脚本文件,并将文件后缀改为.iss。 6. 编译安装程序:在Inno Setup安装目录中,找到并运行Inno Setup编译器(iscc.exe)。在编译器中选择刚才保存的脚本文件,并点击编译按钮。将会生成一个名为setup.exe的安装程序。 7. 运行安装程序:双击生成的setup.exe文件,按照安装程序的提示和选项进行MySQL的安装。 通过以上步骤,你就可以使用Inno Setup打包MySQL 8.0.30,并生成一个可执行的安装程序。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值