V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
chobits336
V2EX  ›  程序员

如何设计一个尽量防止破解的系统激活码

  •  
  •   chobits336 · 32 天前 · 5477 次点击
    这是一个创建于 32 天前的主题,其中的信息可能已经有所发展或是发生改变。

    系统部署到客户的服务器,全部服务用 docker 启动,如何设计一个激活码机制让这个系统到指定时间不能使用

    现在的设计是:

    1. 生成 rsa 公私钥,使用私钥加密 license ,部署时配置 license 文件
    2. 公钥放在系统中,使用公钥解密 license 校验其合法性
    3. license 里有系统 id 、签发人、过期时间属性

    部署是离线环境,防止通过修改系统时间来破解授权,就想到了用系统运行时间来校验;将运行时间加密存在文件里,但如果这个时间文件被删除或被克隆,记录的运行时间就会被重置了,请问各位大佬怎么解决这个问题

    第 1 条附言  ·  32 天前
    感谢各位大佬的办法,找到一个办法
    1. license 的过期时间改为 xxx 天而不是具体的时间,时间校验根据数据表 license_record 的第一条数据和最后一条数据的创建时间的差来判断
    2. 数据表 license_record 加一个 hash 字段,hash 上一条数据的 id + create_time ,就不会被外部篡改了
    3. 定时调度每分钟向 license_record 表插入数据
    4. license_record 表的第一条数据部署时手动加进去,为 license 的内容
    5. 保证一个 license 只能被激活一次,这样就能解决外部重置 license_record 表的问题
    48 条回复    2024-11-04 08:31:18 +08:00
    newaccount
        1
    newaccount  
       32 天前   ❤️ 1
    把当前时间和已运行时间一起放到时间文件里,多记录几个差值,增加调整时间的模拟难度
    至于文件被删除,那就默认不允许运行好了,让他们找你
    chobits336
        2
    chobits336  
    OP
       32 天前
    @newaccount 如果服务器有快照,回滚到指定时间点,然后把系统时间也修改到那个时间,时间差是一样的,就破解了
    chobits336
        3
    chobits336  
    OP
       32 天前
    @chobits336 但也记录了恢复快照前的时间,用这个来对比当前时间,好像可以防止
    dmitsc
        4
    dmitsc  
       32 天前
    数据上埋呢 加上数据库内容。他们总不能把历史数据清了吧
    ysc3839
        5
    ysc3839  
       32 天前 via Android
    非对称加密是基础操作,但是可能遇到 hook OpenSSL (如果公钥验证用了 OpenSSL 等外部库的话),或者直接替换可执行文件内的公钥。
    建议加解密部分静态链接进可执行文件,同时做好自校验。
    InDom
        6
    InDom  
       32 天前
    发硬件,一年后收回硬件。USBkey 也是。
    ysc3839
        7
    ysc3839  
       32 天前 via Android
    至于修改系统时间,没有好的解决办法,一般的思路是尽可能多的把最后时间存在各种文件中。比如某绘图软件会把试用时间存在源文件里,过了试用期之后,那个源文件就只能用付费版打开,任何其他试用版都打不开。还可以考虑把时间写到配置文件里面,要重置就只能删配置文件。
    janus77
        8
    janus77  
       32 天前
    硬件+1 ,PC 端网银软件不就是这么解决的吗
    rekulas
        9
    rekulas  
       32 天前
    离线
    到指定时间不能使用

    这两者本身就冲突了,从技术上无法完美解决,只有参考那些工业机器授权过期的解决方案,附带一个加密硬件/设备作为钥匙,你的授权强度就看你硬件破解难度了
    chobits336
        10
    chobits336  
    OP
       32 天前
    @ysc3839 把时间写在源文件或配置文件里,回滚磁盘快照就重置时间了
    wfhtqp
        11
    wfhtqp  
       32 天前
    @chobits336 存数据库,数据库还能重置?
    msg7086
        12
    msg7086  
       32 天前
    只有完全可信设备才能做到,比如带时钟的加密狗。

    还有一种做法就是把时间戳合并到永久存储的数据中,比如类似区块链这样每一条数据写入的时候同时写入时间戳,每条数据都可以向上回溯校验数据完整性,这样用户如果要回滚就要连同数据一起回滚。
    GeekGao
        13
    GeekGao  
       32 天前
    做一个发号器机制:运行时长超过特定时间后自动降频(能用,但是会很卡顿,以至于无法继续商用)
    815979670
        14
    815979670  
       32 天前
    如果对时间要求特别严格,可以提供一个带内置时钟的加密狗(淘宝好像就几十块钱)
    chobits336
        15
    chobits336  
    OP
       32 天前
    @wfhtqp 数据库也是部署到同一台服务器上的,快照恢复数据库也会影响到吧
    chobits336
        16
    chobits336  
    OP
       32 天前
    @msg7086 和数据绑定校验的话,完全可以将数据先导出来再回滚,在把数据导进去(数据库也是在客户的服务器部署的,环境变量里有密码)
    thevita
        17
    thevita  
       32 天前
    把授权信息和业务数据混在一起

    比如对历史业务数据 进行分区块签名, 把所有业务操作和结果都记账,也能防止某些时钟回拨

    虽然可以通过不停恢复快照继续使用,但是业务功能也就没意义了
    sn0wdr1am
        18
    sn0wdr1am  
       32 天前
    道高一尺,魔高一丈。
    有意思。
    msg7086
        19
    msg7086  
       32 天前
    @chobits336 数据导出来有什么用,你把时间戳嵌入进去,数据导回去不还是能检查出时间不对吗。
    yuankui
        20
    yuankui  
       32 天前
    电子签名
    la2la
        21
    la2la  
       32 天前   ❤️ 2
    咨询一下律师,签个合同,软件到期后不续费接着用就告他
    wfhtqp
        22
    wfhtqp  
       32 天前
    @chobits336 除非业务数据不存数据库,他还能把业务数据都重置掉?
    nealHuang
        23
    nealHuang  
       32 天前
    你的需求跟我的一模一样。但我完全不担心时间回溯,你想想,数据库中很多纪录都是带时间的,如果他们回溯了时间,那么这一批未来数据就没有意义了,或者整个系统的业务数据都会发生错乱了。如果恢复了快照,那么也没法保留数据了,如果系统对他们很重要,那么业务数据是很关键的,如果系统不重要,那么也不会去回溯快照
    chobits336
        24
    chobits336  
    OP
       32 天前
    @msg7086 这个时间戳是系统时间吗,如果恢复快照前是 2024-11-01 ,回滚快照后再把系统时间改为 2024-11-01 就可以通过校验;如果这个时间是系统运行时间(加密不能被篡改)倒是可以校验一致性,但数据里掺杂时间戳感觉太麻烦了,还是说每个业务表加个字段,但这个字段的值可以篡改呀
    chobits336
        25
    chobits336  
    OP
       32 天前
    @nealHuang 可以先把数据 dump 出来,恢复快照后再 load 进去,这样系统也可以用,数据也还在
    InDom
        26
    InDom  
       32 天前   ❤️ 2
    楼上一堆说把时间嵌入数据中的,楼主是一个也没听懂啊...

    假设授权时间为 2024-01-01 ~ 2024-12-31 的 365 天,并且假设系统第一次使用的时候时间是准确的。

    并且假设每天客户都会添加一条新数据,并且每条数据都带有当前具体时间。

    那么,如果你需要验证当前使用是否到期,只需要从数据库中取出时间最早和最晚的时间,取时间差,是不是超过 365 天了,超过就不能用。

    你需要验证的时间信息始终是跟着数据的时间走的,客户只要需要保留数据,就没法作弊。

    如果你担心数据导出来修改时间,你可以对导出数据加密,还可以每条数据都把当前数据 与上条数据的 hash 作为自己的 hash 来防篡改。
    Esec
        27
    Esec  
       32 天前 via Android
    日志,存储,系统自身文件,甚至宿主文件系统和硬件都是可以埋雷的地方,就是容易报毒,毕竟做的事情本质上差不多
    mylovesaber
        28
    mylovesaber  
       32 天前   ❤️ 1
    楼主项目什么语言写的?我这隔壁组一个 java 老哥解决你这种问题的思路是:
    java 是能够轻松反编译的语言(编译出来的文件直接拖进 ide 就能看到源码的程度)
    rust 主打一个安全,很难被反编译,

    用 rust 写一个启动器,把 key 写在启动器中,魔改 springboot 框架的启动器,将其功能改成 rust 启动器来启动,时间信息加密分散到数据库中,让 rust 去调数据库拿数据,验证通过才能唤醒 sb 启动器来启动项目,而单独启动 java 项目是无法工作的。至于时间怎么防回滚,你可以自行思考下,写文件是不能接受的行为,必须写数据库
    chobits336
        29
    chobits336  
    OP
       32 天前
    @InDom 感谢,这样的确可以解决办法,license 的过期时间改为 xxx 天而不是具体的时间,每个数据表加一个 hash 字段,hash 上一条数据的 id ,就不会被外部篡改了,但数据表的修改和删除就会变得很麻烦
    msg7086
        30
    msg7086  
       32 天前
    @InDom 对,差不多就是你说的意思。
    然后你说的最后一句话其实就是区块链的概念。
    不过这种做法也不简单,需要专门做一个抽象层去处理,或者在系统开始设计的时候就考虑进去,后加就麻烦。
    zengxs
        31
    zengxs  
       32 天前
    禁止他重启你的系统就行了,每次开机要你们的人到现场操作,并且收开机费

    上次我朋友去医院做飞秒,医生给他说做飞秒的机器就是这样收费的,每开一次机要收 1w
    医院只能把所有病人集中到每周的某一天做手术,这样一周只开一次机就行
    iorilu
        32
    iorilu  
       32 天前
    搞这么麻烦干啥

    我想到个方法

    系统启动时候需要输入口令, 这口令和当前日期有关系, 每次启动时候需要对方找你, 你根据日期生成口令
    给他, 这样就不存在启动的时候修改日期

    这样就解决了客户单独启动的问题, 反正服务器也不可能经常重启把

    至于运行时候到期判断, 这就记录数据时间阿 , 每天记录第一笔数据之前查找下系统内是否有更新的数据, 如果有必然是当前时间被改到了过去
    InDom
        33
    InDom  
       32 天前
    楼主最后附言的方案,是打算自己单独建一个表么?

    如果我 docker exec mysql ,然后删除、清空你的这个表会怎么样呢?

    一定要把时间融入到他们的业务中,数据和使用二选一。

    @iorilu #32 ,启动时提供授权是个好主意,相当于间接同步时间了。
    chobits336
        34
    chobits336  
    OP
       32 天前
    @InDom 清空 license_record 表就启动不了系统,第一条记录为 license 凭证,这个凭证也不能被复用
    iorilu
        35
    iorilu  
       32 天前
    @InDom 我个人觉得有这步就够了, 其实也是表明一个态度, 说明很重视版权, 想用就得给钱, 别想白嫖

    其他也没必要, 你软件要真那么牛, 值得费大力气折腾绕过, 那应该早赚大钱了
    maladaxia
        36
    maladaxia  
       32 天前
    @rekulas 有 gps 访问权限也可以, gps 有时间
    maladaxia
        37
    maladaxia  
       32 天前
    我还有个办法,
    1. 运行你的程序获取环境信息
    2. 客户把环境信息发给你, 你来计算激活码
    3. 客户用激活码激活

    环境信息里应该包含时间和硬盘运行时间等信息
    从而保证这个激活码只能一次性使用
    youyouzi
        38
    youyouzi  
       32 天前
    网银的 U 盾啊。这不是很成熟的加密方式了嘛?
    ladypxy
        39
    ladypxy  
       32 天前 via iPhone
    最简单的,参考 2FA 原理,注册就绑定一个 2FA 的 token ,到期从服务器删除即可
    barfi1316
        40
    barfi1316  
       32 天前
    @chobits336 如果 license_record 表清理只保留第一条,同时修改系统时间,是不是 license 就重新计算?
    DeWjjj
        41
    DeWjjj  
       32 天前
    我的做法,内存区一个活跃区块,没有文本,及时校验,如果 nop ,直接跳进暗桩。
    我知道有一些人喜欢看汇编 cmp xx,xx 。没啥用的,防不住,每次迭代的时候都丢点暗桩进去。
    触发,触发信息向服务器获取 ntp 时间校验,ntp 有加随机数盐。
    Lxmzfb43AC35PAkL
        42
    Lxmzfb43AC35PAkL  
       32 天前
    沒有不能破解的系統,
    我把你電腦冰起來讀 memory 取 key 也可以.
    humbass
        43
    humbass  
       32 天前
    设计一个远程的 API ,定期获取 token ,无效的 token 不能启动。
    webcape233
        44
    webcape233  
       31 天前 via iPhone
    @humbass 这要能联网当然就简单了
    isSamle
        45
    isSamle  
       31 天前
    1. 激活码涵盖:内置加密算法的 key 、加密字符、时间戳、相关校验内容、多层加密逻辑
    2. 离线项目涵盖:解密逻辑算法,混淆加密数据文件(用于存放校验信息),系统每日运行按逻辑修改校验信息并加密覆盖回去,在项目多个路径存放校验文件(配随机路径生成逻辑,每次运行变更校验地址,将地址目录集加密存储到校验信息文件中),如果多个随机地址的文件找不到或对应不上,视为被绿色的,限制功能使用
    kokerkov
        46
    kokerkov  
       31 天前
    你去问问隔壁的 Denuvo
    totoro52
        47
    totoro52  
       30 天前   ❤️ 1
    我觉得这些都没啥用,该破解还是破解。不如故意在正式版多留点设计上 BUG 或者坑,后期一点一点慢慢修复,美言其名为商业化支持。
    daimiaopeng
        48
    daimiaopeng  
       29 天前   ❤️ 1
    你先列举一个存在的防破解的系统激活码
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1184 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 24ms · UTC 18:39 · PVG 02:39 · LAX 10:39 · JFK 13:39
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.