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

Jar 包有没有可能防止别人解压再打包运行?

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

    起因是这样的,我司购买了一套 Java 服务的部署版,原先我想 unzip ,并且修改一下 IP 地址(因公司换 IP 了)

    结果重新打包后会出现运行错误,大约错误如下

    An attempt was made to call the method javax.servlet.ServletContext.getVirtualServerName()Ljava/lang/String; but it does not exist. Its class, javax.servlet.ServletContext, is available from the following locations:
    
    Action:
    
    Correct the classpath of your application so that it contains a single, compatible version of javax.servlet.ServletContext
    

    看着像是依赖包冲突了

    操作流程

    unzip xxx.jar -d jar
    
    cd jar
    
    zip -0r xxx.jar ./*
    

    比较神奇,有人研究过这方面的问题吗?厂商原先的包是可以运行的

    只要 unzip 再 zip 就会出现,即使不改任何配置

    已经再安排找厂商拿新的 jar 包了,单纯好奇有技术是不是能防止别人 unzip 修改配置?

    15 条回复    2023-08-10 19:41:09 +08:00
    mineralsalt
        1
    mineralsalt  
       279 天前
    当然能改, 不仅能改配置文件, class 都能反编译修改, 只是你的方法不对
    zhazi
        2
    zhazi  
       279 天前
    没必要 unzip 直接 vim 进去改就行了,打包时可能会有其他步骤,zip 时被忽略了
    wetalk
        3
    wetalk  
       279 天前
    这要从 jar 打包原理说起了
    githmb
        4
    githmb  
       279 天前
    额,Jar 不是有签名吗,你能这样改的啊
    leeseaside
        5
    leeseaside  
       279 天前   ❤️ 1
    可以改,,
    如果是 win ,推荐使用 WinRAR,直接打开 xxx.jar 包,然后把想添加的文件压进去,压缩方式选择存储
    如果是 linux,
    解压出来
    jar -xvf cxf-0.0.1-SNAPSHOT.jar BOOT-INF/classes/application.properties
    压回去
    jar -uvf cxf-0.0.1-SNAPSHOT.jar BOOT-INF/classes/application.properties
    mikasa1024
        6
    mikasa1024  
       279 天前   ❤️ 1
    用 jar -cfM0 打包,例如:

    jar -cvfM0 server.jar BOOT-INF/classes BOOT-INF/lib META-INF org
    nkidgm
        7
    nkidgm  
       279 天前
    对啊,类似安卓 APK 那种,改完还要重新签名,安卓系统才能安装那份包。
    cslive
        8
    cslive  
       279 天前
    winrar 直接打开 jar 包该,你直接 zip 压缩,java 不认,少了参数
    nekoneko
        9
    nekoneko  
       279 天前
    听 5 楼的
    thevita
        10
    thevita  
       279 天前
    软件防串改本来就是个很复杂的问题,各种方案无非是,是用更高可信的代码来验证其他代码的可信性,收窄代码保护的范围,比如你可以这样:

    你可以用一个 自己的 loader(只是一个说法不一定是 ClassLoader ) 来加载 jar 和 class ,通过签名来保证加载代码可信,
    这样就能把对抗的点收窄到 这个 loader 里,如果你用 native code ,一些传统的保护方案也能用了,比如 vmp 之类的

    当然这样也只是提高了成本而已,你还可以更近一步,把信任继续往前推,比如依靠 os 或者 硬件提供的功能来实现,这就是可信计算搞的那堆东西了
    mankismi
        11
    mankismi  
    OP
       279 天前
    谢谢各位大哥,确实用 java 压回去可以。先前也试过 用 jar 命令解压全部,再打包,也不行,没想到能压单个文件进去。学习了
    whp1473
        12
    whp1473  
       278 天前
    当然可以改,不光配置可以,代码也可以反编译改了再编译回去。
    如果想要防止修改再运行,有几种方案:
    (1)掩耳盗铃版:将代码配置全部对称加密,然后将密码生成在内部的一个文件中,在类加载器加载时解密。效果:解压后,反编译或 VIM 全部乱码,不能修改,但如果知道运行步骤是可以找到密码和反编译启动的加密逻辑的。
    (2)输入密码式:可以在启动时-Dpasswrod 输入密码,原理同上。效果:更安全,因为无法得到密码,光反编译加密逻辑不行。
    (3)JDK 加密:第二种方式可以通过另一种方式获得,JAVA 探针,也就是对 JVM 进程 Hook ,然后直接反编译运行时字节码,然后拿到字节码后反向生成代码再编译。因此需要通过对 JDK 加壳进行防护,加密的逻辑被内嵌到 JDK 中,必须使用专用的 JDK 才可以启动。也就是将加密的攻防下沉到二进制层面,更难获得。
    其他的比如网络远程服务认证、本地硬件码认证都是可以通过 Hook 形式反编译和断点绕过的,只是点越多越难绕而已。下沉到二进制层面就类似游戏外挂那种了,需要找进程号、内存地址解析、线程解析等,拼的是肝。
    mikasa1024
        13
    mikasa1024  
       278 天前
    @whp1473 #12

    jdk 加密作用不是很大,只要能运行在标准 jvm 上的代码,都可以获取到字节码进而反编译出 java 代码

    如果你指的是,修改 jvm 的读取和验证 java class 文件的逻辑,确实有更好的效果。缺点就是,现在很多依赖反射的框架会直接读取 class ,导致框架运行可能出错

    再就是 aot 这两年发展好点,编译为 native code 感觉是个不错的方案

    之前看知乎的这个问题与 RednaxelaFX 的回答,学到很多 https://www.zhihu.com/question/19766494
    fengpan567
        14
    fengpan567  
       278 天前
    配置文件的话直接 vim 命令就能改
    whp1473
        15
    whp1473  
       262 天前
    @mikasa1024 给 C++的 JDK 加壳,然后该 JVM 的接口,限制非认证的反编译运行,但会造成比如 Hook 这种无法运行。
    也可以参考新的 JVM 比如 Graalvm SpringBoot3.0 也支持,会编译成 native ,启动超快内存占用低,缺点不支持反射,有些框架不支持。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   1348 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 28ms · UTC 17:25 · PVG 01:25 · LAX 10:25 · JFK 13:25
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.