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

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

  •  
  •   chobits336 · 15 小时 4 分钟前 · 3455 次点击

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

    现在的设计是:

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    我想到个方法

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

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

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

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

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

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

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

    环境信息里应该包含时间和硬盘运行时间等信息
    从而保证这个激活码只能一次性使用
    youyouzi
        38
    youyouzi  
       7 小时 53 分钟前
    网银的 U 盾啊。这不是很成熟的加密方式了嘛?
    ladypxy
        39
    ladypxy  
       7 小时 10 分钟前 via iPhone
    最简单的,参考 2FA 原理,注册就绑定一个 2FA 的 token ,到期从服务器删除即可
    barfi1316
        40
    barfi1316  
       4 小时 40 分钟前
    @chobits336 如果 license_record 表清理只保留第一条,同时修改系统时间,是不是 license 就重新计算?
    DeWjjj
        41
    DeWjjj  
       4 小时 7 分钟前
    我的做法,内存区一个活跃区块,没有文本,及时校验,如果 nop ,直接跳进暗桩。
    我知道有一些人喜欢看汇编 cmp xx,xx 。没啥用的,防不住,每次迭代的时候都丢点暗桩进去。
    触发,触发信息向服务器获取 ntp 时间校验,ntp 有加随机数盐。
    jadeluvlove
        42
    jadeluvlove  
       3 小时 37 分钟前
    沒有不能破解的系統,
    我把你電腦冰起來讀 memory 取 key 也可以.
    humbass
        43
    humbass  
       2 小时 34 分钟前
    设计一个远程的 API ,定期获取 token ,无效的 token 不能启动。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1228 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 25ms · UTC 18:26 · PVG 02:26 · LAX 11:26 · JFK 14:26
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.