提升软件安全性 - 运用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=noSetupIconFile=.\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();beginWizardForm.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;beginstrCmdKill := 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') thenbeginRegQueryStringValue(HKLM64, 'SOFTWARE\Microsoft\Cryptography', 'MachineGuid', strMachineGUID)end// 防止有的系统没有这一项,获取当前日期作为机器码elsebeginstrMachineGUID := '{#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 thenResult := True;end;procedure curpagechanged(curpage: integer);var IDLabel, RegAdr : TLabel; IDEdit: TEdit; RefDisk: String;beginIDLabel:= 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"
    

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/217108.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

java代码编写twitter授权登录

在上一篇内容已经介绍了怎么申请twitter开放的API接口。 下面介绍怎么通过twitter提供的API,进行授权登录功能。 开发者页面设置 首先在开发者页面开启“用户认证设置”,点击edit进行信息编辑。 我的授权登录是个网页,并且只需要进行简单的…

计算机网络(三)

(十一)路由算法 A、路由算法分类 动态路由和静态路由 静态路由:人工配制,路由信息更新慢,优先级高。这种在实际网络中要投入成本大,准确但是可行性弱。 动态路由:路由更新快,自动…

SpringBoot的依赖管理和自动配置

与其明天开始,不如现在行动! 文章目录 1 依赖管理机制2 自动配置机制2.1 初步理解2.2 完整流程 💎总结 1 依赖管理机制 为什么导入starter-web后所有相关依赖都会导入进来? 开发什么场景,导入什么场景启动器-spring-bo…

Redis持久化AOF详解

基础面试题 什么是AOF AOF(Append-Only File)用于将Redis服务器收到的写操作追加到日志文件,通过该机制可以保证服务器重启后依然可以依靠日志文件恢复数据。 它的工作过程大抵分为以下几步: 收到客户端的写入命令(例如SET、DE…

nest.js框架基本使用

前言: 先把npm的镜像源切换成阿里巴巴的,要不然下载挺慢的: npm config set registry https://registry.npm.taobao.org npm config get registry 1.创建文件 先创建一个文件夹:nestDemo npm i -g nestjs/cli nest ne…

Nginx访问FTP服务器文件的时效性/安全校验

背景 FTP文件服务器在我们日常开发中经常使用,在项目中我们经常把FTP文件下载到内存中,然后转为base64给前端进行展示。如果excel中也需要导出图片,数据量大的情况下会直接返回一个后端的开放接口地址,然后在项目中对接口的参数进…

网站使用CDN后无法获取用户真实IP的解决方法

宝塔或Nginx环境 如果你使用的宝塔或Nginx,可以在宝塔面板或Nginx中,找到配置文件增加如下代码后,重载配置或者重启 Nginx 即可: #CDN获取真实ip set_real_ip_from 0.0.0.0/0; real_ip_header X-Forwarded-For; PHP语言函数方法…

Java刷题篇——LeetCode118. 杨辉三角

1.题目描述 给定一个非负整数numRows,生成杨辉三角的前numRows行。 在杨辉三角中,每个数是它左上方和右上方的数的和。 示例1 输入:numRows 5 输出:[1],[1,1],[1,2,1],[1,3,3,1],[1,4,6,4,1] 示例2 输入:numRows 1…

安装DevEco Studio

下载 首先进入鸿蒙开发者官网,顶部导航栏选择开发->DevEco Studio 根据操作系统下载不同版本,其中Mac(X86)为英特尔芯片,Mac(ARM)为M芯片。 安装 下载完毕后,开始安装。 点击Agree 首次使用,请选择Do not impor…

Linux篇之在Centos环境下搭建Nvidia显卡驱动

一、前提条件 1、首先确认内核版本和发行版本,再确认显卡型号 uname -a // Linux localhost.localdomain 4.18.0-408.el8.x86_64 #1 SMP Mon Jul 18 17:42:52 UTC 2022 x86_64 x86_64 x86_64 GNU/Linux1.2 cat /etc/redhat-release // CentOS Stream release 81.3…

使用Git进行版本控制

参考:《Python编程从入门到实践》 前言1、安装、配置 Git1.1 在Linux系统中安装Git1.2 在OS X系统中安装Git1.3 在Windows系统中安装Git1.4 配置Git 2、创建项目3、忽略文件4、初始化仓库5、检查状态6、将文件加入到仓库中7、执行提交8、查看提交历史9、第二次提交1…

Seata配置

参考教程 seata 分布式事务的环境搭建与使用 Seata 1.4.0 nacos配置和使用,超详细 Seata 1.4.2 的安装 Nacos的配置和使用 官网下载地址 本文以v1.4.1为例 1.数据库及表的创建 创建seata数据库,创建以下表(右键连接-》新建数据库seata-》…

2023.12.6 关于 Spring Boot 事务的基本概念

目录 事务基本概念 前置准备 Spring Boot 事务使用 编程式事务 声明式事务 Transactional 注解参数说明 Transational 对异常的处理 解决方案一 解决方案二 Transactional 的工作原理 面试题 Spring Boot 事务失效的场景有那些? 事务基本概念 事务指一…

【AI神器】CodeGeeX智能编程助手

目录 1.CodeGeeX介绍2.IDEA插件安装3.助手功能3.1 代码分析(/explain)3.2 代码自动补全3.3 AI优化代码3.4 代码添加注释(/comment)3.5 AI添加文档3.6 单元测试生成(/tests)3.7 bug查找修正(/fix…

[OpenWrt]RAX3000一根线实现上网和看IPTV

背景: 1.我家电信宽带IPTV 2.入户光猫,桥接模式 3.光猫划分vlan,将上网信号IPTV信号,通过lan口(问客服要光猫超级管理员密码,具体教程需要自行查阅,关键是要设置iptv在客户侧的vlan id&#…

Maven基础

目录 Maven坐标 坐标简介 主要组成 Maven依赖管理 配置依赖 依赖简介 配置依赖 依赖传递 依赖传递简介 排除依赖 依赖范围 生命周期 生命周期简介 执行指定生命周期 Maven坐标 坐标简介 Maven中的坐标是资源的唯一标识,通过该坐标可以唯一定位资…

Yolov5双目测距-双目相机计数及测距教程(附代码)

引言 在计算机视觉领域,Yolov5-Binocular相机距离计数及测距是一个引人注目的研究方向。本教程将为小白用户提供一个简明扼要的学习指南,涵盖了关键步骤,包括标定、公示推倒以及重要的代码片段。 第一步:环境搭建 首先&#x…

cpp:1:10: fatal error: opencv2/core.hpp: 没有那个文件或目录

前言&#xff1a; 我按照官网方法安装了opencv&#xff0c;运行的也是官网的测试代码&#xff1a; #include <opencv2/core.hpp> #include <opencv2/highgui.hpp> using namespace cv; int main() {printf("hello world")return 0; } 半解决&#xff…

07用户行为日志数据采集

用户行为数据由Flume从Kafka直接同步到HDFS&#xff0c;由于离线数仓采用Hive的分区表按天统计&#xff0c;所以目标路径要包含一层日期。具体数据流向如下图所示。 按照规划&#xff0c;该Flume需将Kafka中topic_log的数据发往HDFS。并且对每天产生的用户行为日志进行区分&am…

java-sec-code的xss

java-sec-code 用于学习java漏洞代码 环境部署 直接在idea中使用git 运行即可 RequestMapping("/reflect") ResponseBody public static String reflect(String xss) {return xss;}当用户访问到/reflect URL地址时&#xff0c;程序会自动调用reflect方法&#xff0c…