本来想说“用JVM指令编写Java程序”,转念一想,现在已经有不少基于JVM的语言了,比如Groovy、Scala、JRuby和Jython等,它们底层都是以合法JVM执行的。所以,从某种意义上说,用JVM指令写不出Java程序。[图片] 这几天一时兴起玩起了逆向工程,看看程序背后的底层指令长成啥样。大学课程学了汇编, ..

用JVM指令编写JVM程序

本贴最后更新于 2347 天前,其中的信息可能已经沧海桑田

    本来想说“用JVM指令编写Java程序”,转念一想,现在已经有不少基于JVM的语言了,比如Groovy、Scala、JRuby和Jython等,它们底层都是以合法JVM执行的。所以,从某种意义上说,用JVM指令写不出Java程序。

    这几天一时兴起玩起了逆向工程,看看程序背后的底层指令长成啥样。大学课程学了汇编,对于基本的汇编程序还是能流畅地完成编码、编译链接和反编译调试工作的。而玩了那么久Java却没从字节码的角度了解过JVM工作机制,实在是惭愧。前些天逆向了一个APK,并且在smali中嵌入自己的代码再次编译打包,实现了去广告和改变某些工作逻辑。(是的,没错,改变了程序某些地方的执行流程,比如……)对于Android虚拟机,网上已经有很多现成的工具编译其汇编指令,而纯Java的却很难找到。如今JAR/class已经可以很方便地反编译成Java源文件,或许Java代码比JVM指令更容易修改所以直接用JVM指令编程的需求很少吧。

    Dalvik是基于寄存器的虚拟机,而JVM是基于栈的虚拟机。参考http://casper.cii.saxion.nl:8083/~vanleeuw/pse/spanje/jasm.html,文中提到可用Jasmin编译JVM指令,我试了一下,感觉还算简单。因为JVM字节码有很严格的格式和验证机制,而javap反编译出来的纯指令是无法编译成合法的class的,因此Jasmin语法的源文件需要加入一些额外的属性修饰。以下是我参考上文写的Hello类。


.class public Hello
.super java/lang/Object

.method public <init>()V
aload_0
invokenonvirtual java/lang/Object/<init>()V
return
.end method

.method public static main([Ljava/lang/String;)V
.limit stack 2
getstatic java/lang/System/out Ljava/io/PrintStream;
ldc "Hello, World!"
invokevirtual java/io/PrintStream/println(Ljava/lang/String;)V
return
.end method

    最小的代码可以连<init>方法都不要,试过可运行。唯一不爽的就是很麻烦地要用“签名”的形式,比如[Ljava/lang/String;。以上Hello类输出Hello, World!。


  • Jasmin
    1 引用 • 2 回帖
  • 指令
    3 引用 • 20 回帖
  • 字节码
    2 引用 • 2 回帖
  • JVM

    JVM(Java Virtual Machine)Java 虚拟机是一个微型操作系统,有自己的硬件构架体系,还有相应的指令系统。能够识别 Java 独特的 .class 文件(字节码),能够将这些文件中的信息读取出来,使得 Java 程序只需要生成 Java 虚拟机上的字节码后就能在不同操作系统平台上进行运行。

    91 引用 • 106 回帖
2 回帖   
请输入回帖内容...
  • nana API  

    这又是神马呀?

  • Armstrong API  

    [em01]JVM 指令