return gethexstr messagedigest.digest) ) int len = in.length; int i; StringBuilder out = new StringBuilder len * 2 for i = 0; i < len; i++ ) catch Exc

Similar documents
chp6.ppt

1: public class MyOutputStream implements AutoCloseable { 3: public void close() throws IOException { 4: throw new IOException(); 5: } 6:

Java

JavaIO.PDF

(TestFailure) JUnit Framework AssertionFailedError JUnit Composite TestSuite Test TestSuite run() run() JUnit

内 容 简 介 本 书 是 一 本 关 于 语 言 程 序 设 计 的 教 材, 涵 盖 了 语 言 的 基 本 语 法 和 编 程 技 术, 其 中 包 含 了 作 者 对 语 言 多 年 开 发 经 验 的 总 结, 目 的 是 让 初 学 的 读 者 感 受 到 语 言 的 魅 力, 并 掌

1.JasperReport ireport JasperReport ireport JDK JDK JDK JDK ant ant...6

Chapter 9: Objects and Classes

Microsoft Word - 01.DOC

3.1 num = 3 ch = 'C' 2

SDK 概要 使用 Maven 的用户可以从 Maven 库中搜索 "odps-sdk" 获取不同版本的 Java SDK: 包名 odps-sdk-core odps-sdk-commons odps-sdk-udf odps-sdk-mapred odps-sdk-graph 描述 ODPS 基

Java java.lang.math Java Java.util.Random : ArithmeticException int zero = 0; try { int i= 72 / zero ; }catch (ArithmeticException e ) { // } 0,

untitled


EJB-Programming-4-cn.doc

Learning Java

雲端 Cloud Computing 技術指南 運算 應用 平台與架構 10/04/15 11:55:46 INFO 10/04/15 11:55:53 INFO 10/04/15 11:55:56 INFO 10/04/15 11:56:05 INFO 10/04/15 11:56:07 INFO

Fun Time (1) What happens in memory? 1 i n t i ; 2 s h o r t j ; 3 double k ; 4 char c = a ; 5 i = 3; j = 2; 6 k = i j ; H.-T. Lin (NTU CSIE) Referenc

新版 明解C++入門編

詞 彙 表 編 號 詞 彙 描 述 1 預 約 人 資 料 中 文 姓 名 英 文 姓 名 身 份 證 字 號 預 約 人 電 話 性 別 2 付 款 資 料 信 用 卡 別 信 用 卡 號 信 用 卡 有 效 日 期 3 住 房 條 件 入 住 日 期 退 房 日 期 人 數 房 間 數 量 入

OOP with Java 通知 Project 4: 4 月 19 日晚 9 点

Java 1 Java String Date

Microsoft Word - ch04三校.doc

KillTest 质量更高 服务更好 学习资料 半年免费更新服务

《大话设计模式》第一章

javaexample-02.pdf

OOP with Java 通知 Project 4: 5 月 2 日晚 9 点

基于CDIO一体化理念的课程教学大纲设计

使用MapReduce读取XML文件

2. AOP 底层技术实现 小风 Java 实战系列教程 关键词 : 代理模式 代理模型分为两种 : 1) 接口代理 (JDK 动态代理 ) 2) 子类代理 (Cglib 子类代理 ) 需求 :CustomerService 业务类, 有 save,update 方法, 希望在 save,updat

Guava学习之Resources

JBuilder Weblogic

untitled

9, : Java 19., [4 ]. 3 Apla2Java Apla PAR,Apla2Java Apla Java.,Apla,,, 1. 1 Apla Apla A[J ] Get elem (set A) A J A B Intersection(set A,set B) A B A B

BOOL EnumWindows(WNDENUMPROC lparam); lpenumfunc, LPARAM (Native Interface) PowerBuilder PowerBuilder PBNI 2

C 1

内 容 提 要 将 JAVA 开 发 环 境 迁 移 到 Linux 系 统 上 是 现 在 很 多 公 司 的 现 实 想 法, 而 在 Linux 上 配 置 JAVA 开 发 环 境 是 步 入 Linux 下 JAVA 程 序 开 发 的 第 一 步, 本 文 图 文 并 茂 地 全 程 指

RUN_PC連載_12_.doc

JAVA String常用APi

IoC容器和Dependency Injection模式.doc

"+handlermethod.getbean().getclass().getname()); public void aftercompletion(httpservletrequest req, HttpServletResponse resp, Object handler, Excepti

untitled

OOP with Java 通知 Project 3: 3 月 29 日晚 9 点 4 月 1 日上课

用手機直接傳值不透過網頁連接, 來當作搖控器控制家電 ( 電視遙控器 ) 按下按鍵發送同時會回傳值來確定是否有送出 問題 :1. 應該是使用了太多 thread 導致在傳值上有問題 2. 一次按很多次按鈕沒辦法即時反應

4.1 AMI MQSeries API AMI MQI AMI / / AMI JavaC C++ AMI / AMI AMI - / /

全国计算机技术与软件专业技术资格(水平)考试

java2d-4.PDF

Swing-02.pdf

第3章.doc

Java第一天 年4月23日

北 风 网 讲 师 原 创 作 品 ---- 仅 供 学 员 内 部 交 流 使 用 前 言 吾 尝 终 日 而 思 矣, 不 如 须 臾 之 所 学 也 ; 吾 尝 跂 而 望 矣, 不 如 登 高 之 博 见 也 登 高 而 招, 臂 非 加 长 也, 而 见

FY.DOC

Microsoft PowerPoint - course2.ppt

javac: 负 责 的 是 编 译 的 部 分, 当 执 行 javac 时, 会 启 动 java 的 编 译 器 程 序 对 指 定 扩 展 名 的.java 文 件 进 行 编 译 生 成 了 jvm 可 以 识 别 的 字 节 码 文 件 也 就 是 class 文 件, 也 就 是 ja

威 福 髮 藝 店 桃 園 市 蘆 竹 區 中 山 里 福 祿 一 街 48 號 地 下 一 樓 50,000 獨 資 李 依 純 105/04/06 府 經 登 字 第 號 宏 品 餐 飲 桃 園 市 桃 園 區 信 光 里 民

软件工程文档编制

Hive:用Java代码通过JDBC连接Hiveserver

<4D F736F F F696E74202D20332D322E432B2BC3E6CFF2B6D4CFF3B3CCD0F2C9E8BCC6A1AAD6D8D4D8A1A2BCCCB3D0A1A2B6E0CCACBACDBEDBBACF2E707074>

Microsoft PowerPoint - 09Future

任務二 : 產生 20 個有炸彈的磚塊, 放在隨機的位置編輯 Block 類別的程式碼 import greenfoot.; // (World, Actor, GreenfootImage, Greenfoot and MouseInfo) Write a description of class

建模与图形思考

Microsoft Office SharePoint Server MOSS Web SharePoint Web SharePoint 22 Web SharePoint Web Web SharePoint Web Web f Lists.asmx Web Web CAML f

概述

電機工程系認可證照清單 /7/1

國家圖書館典藏電子全文

<4D F736F F D20C8EDC9E82DCFC2CEE7CCE22D3039C9CF>

untitled

1 Project New Project 1 2 Windows 1 3 N C test Windows uv2 KEIL uvision2 1 2 New Project Ateml AT89C AT89C51 3 KEIL Demo C C File

Microsoft Word - 把时间当作朋友(2011第3版)3.0.b.07.doc

ebook39-5

第 15 章 程 式 編 写 語 言 15.1 程 式 編 写 語 言 的 角 色 程 式 編 寫 語 言 是 程 式 編 寫 員 與 電 腦 溝 通 的 界 面 語 法 是 一 組 規 則 讓 程 式 編 寫 員 將 字 詞 集 合 起 來 電 腦 是 處 理 位 元 和 字 節 的 機 器, 與

2 WF 1 T I P WF WF WF WF WF WF WF WF 2.1 WF WF WF WF WF WF

Microsoft Word doc

2009年9月全国计算机等级考试二级Java真题及答案

2013 C 1 # include <stdio.h> 2 int main ( void ) 3 { 4 int cases, a, b, i; 5 scanf ("%d", & cases ); 6 for (i = 0;i < cases ;i ++) 7 { 8 scanf ("%d %d

Transcription:

Javassist 在逆向工程中的应用 安全研究部陈庆 关键词 :Java Javassist class 调试逆向工程摘要 :Javassist 是一种面向程序员的 Java Class 修改工具, 以库的形式封装了诸多 API 供程序员使用, 使得可以在 Java 源码级别直接修改 Java Class, 而不必直接面对 Java Bytecode 和 JVM 在 Java 逆向工程 无源码 Java 程序调试排错中,Javassist 大有用武之地 本文以几份短小精悍的完整代码演示 Javassist 的使用 一 引言 avassist 顾名思义, 是个 Java 辅助工具 按官方说法它使得字 J节码处理变得简单, 在 Java 源码级处理字节码, 给用户提供 封装好的 API 操作 class, 把中间各种繁杂的细节隐藏起来 官网是 : http://www.csg.ci.i.u-tokyo.ac.jp/~chiba/javassist/ 上述文字还是太抽象, 本文将演示 Javassis 与逆向工程较紧密 的部分用法 如果有耐心, 建议将其自带教程完整看一遍 : http://www.csg.ci.i.u-tokyo.ac.jp/~chiba/javassist/tutorial/ tutorial.html 二 一个假想的研究目标 target_0.java 如下, 是我们的假想敌, 也就是 Javassist 的作用 对象 它会检查提供的命令行参数, 如果满足指定检查方案, 就显示 "You are a clever boy!" 我们的目标是在 Javassist 的介入下使得无论命令行参数是啥,target_0 都显示 "You are a clever boy!" import java.security.messagedigest; class Hash private static final char[] HEXDIGITS = '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' ; private static String gethexstr byte[] in ) 49

return gethexstr messagedigest.digest) ) int len = in.length; int i; StringBuilder out = new StringBuilder len * 2 for i = 0; i < len; i++ ) catch Exception e ) throw new RuntimeException e ) out.append HEXDIGITS[ in[i] >> 4 ) & 0x0F ] out.append HEXDIGITS[ in[i] & 0x0F ] return out.tostring) public class target_0 public static String gethash String algorithm, String text ) MessageDigest messagedigest; if null == text ) return null private static boolean VerifyHash String text ) return Hash.gethash "SHA1", text ).equals "7BCD168 6FE4BCE0A06655740FE54D0C233855872" ) public static void main String[] args ) String text; try boolean exit = false; if 1!= args.length ) messagedigest = MessageDigest.getInstance algorithm System.err.println "Usage: target_0 <secret>" messagedigest.update text.getbytes) 50

else CtClass old_class = ClassPool.getDefault).get "Hash" if VerifyHash args[0] ) ) System.out.println "You are a clever boy!" old_class.detach C t M e t h o d o l d _ m e t h o d = o l d _ c l a s s. getdeclaredmethod "gethash" old_class.removemethod old_method return; CtMethod new_method = CtNewMethod.make "public static String gethash String algorithm, String text )" + $ javac -g:none target_0.java $ java -jar target_0.jar anything "" + " System.out.pr intln \" M odif ied\" " 不带调试信息编译 target_0.java, 制做 target_0.jar, 尽可能 + 符合我们最有可能碰上的那种情形 为了不过度分散注意力以及演示方便, 假设未做混淆 三 重新实现或简单修改指定 method crack_target_0_d.java 重新实现 Hash.gethash), 返回固定值, 于是 VerifyHash) 始终返回 true class crack_target_0_d public static void main String[] argv ) throws Exception " return \"7BCD1686FE4BCE0A06655740FE54D 0C233855872\" " + "", old_class old_class.addmethod new_method old_class.toclass target_0.main argv 51

$ javac -g -cp "javassist.jar;target_0.jar" crack_target_0_ d.java $ java -cp "javassist.jar;target_0.jar;." crack_target_0_d anything Modified You are a clever boy! 值得一提的是, 上述代码没有修改硬盘上的静态文件, 是将 ).insertbefore "" + " System.out.println \"Modified\" " + " return \"7BCD1686FE4BCE0A06655740FE54D 0C233855872\" " + "" Hash.class 加载到内存中再修改, 所有的改动仅仅停留在内存中, 并未写回硬盘, 可以说 crack_target_0_d 是个 Loader 如果一定要写回硬盘, 将 toclass) 改成 writefile), 但我不推荐 关于这里用到的 API, 参看 : http://www.csg.ci.i.u-tokyo.ac.jp/~chiba/javassist/html/ old_class.toclass target_0.main argv crack_target_0_e.java 用了更省事的 insertbefore), 在 Hash.gethexstr) 入口处插入代码 class crack_target_0_e public static void main String[] argv ) throws Exception 有人可能认为在 Hash.gethash) 入口处插入同样的代码也能达到同样效果, 实际上这里有名堂 把前面的 "gethexstr" 改成 "gethash", 执行中触发 : Exception in thread "main" java.lang.classformaterror: Illegal exception table end_pc 38 in method Hash.gethashLjava/ lang/string;ljava/lang/string;)ljava/lang/string; at target_0.verifyhashunknown Source) "Hash" CtClass old_class old_class.detach = ClassPool.getDefault).get at target_0.mainunknown Source) at crack_target_0_e.maincrack_target_0_e.java) 简单点说,Hash.gethash) 中有 try/catch, 直接在方法入口插 old _ c lass.get D eclaredmethod "gethexstr " 代码, 会影响与 try/catch 相关的定位, 涉及 class 格式中 method 52

附属 "Exception table" 的修正, 看上去 insertbefore) 不会进行这种修正 与 insertbefore 类似的有 insertafter addcatch insertat 等等, 参看 : http://www.csg.ci.i.u-tokyo.ac.jp/~chiba/javassist/html/ javassist/ctbehavior.html 四 替换对指定 method 的调用代码 crack_target_0_n.java 在 Hash.class 中搜索调用 Hash. gethexstr) 的代码, 将找到的调用代码替换成另外两条代码 import javassist.expr.*; class crack_target_0_n_expreditor extends ExprEditor p u b l i c v o i d e d i t M e t h o d C a l l e x p r ) t h r o w s CannotCompileException if expr.getclassname).equals "Hash" ) && expr.getmethodname).equals "gethexstr" ) ) expr.replace "" + " System.out.println \"Modified\" " + " $_ = \"7BCD1686FE4BCE0A06655740FE54D 0C233855872\";" + "" public class crack_target_0_n public static void main String[] argv ) throws Throwable CtClass.debugDump = "./debugdump/"; ClassPool pool = ClassPool.getDefault pool.get "Hash" ).instrument new crack_target_0_n_ ExprEditor) new Loader pool ) ).run "target_0", argv 53

虽然 crack_target_0_n.java 只是在内存中修改了 Hash.class, digest 但 Javassist 提供调试设置, 允许开发人员出于调试目的获取被修改过的 Hash.class CtClass.debugDump 指定一个目录, 被修改过的 Hash.class 将写入该目录 用 JD-GUI 查看被修改过的 Hash.class,gethash) 已被修改 : public static String gethashstring paramstring1, String paramstring2) if null == paramstring2 ) return null; try M e s s a g e D i g e s t l o c a l M e s s a g e D i g e s t = MessageDigest.getInstance paramstring1 localmessagedigest.update paramstring2.getbytes) Object localobject = null; String str = null; System.out.println "Modified" str = "7BCD1686FE4BCE0A06655740FE54D 0C233855872"; return str; catch Exception localexception ) throw new RuntimeException localexception 五 在字节码级别操作 class 一般来说 Javassist 鼓励在 Java 源码级操作 class, 但它确实支持 byteocde 级的操作 crack_target_0_i.java 在加载 target_0. * 后面的代码原来是 : * * return gethexstr localmessagedigest.digest) byte[] arrayofbyte = localmessagedigest. class 时修改了 VerifyHash) 的 bytecode, 相当于直接 return true ) import javassist.bytecode.*; class crack_target_0_i_translator implements Translator p u b l i c v o i d s t a r t C l a s s P o o l p o o l ) t h r o w s NotFoundException, CannotCompileException 54

System.out.println "\nmodified\n" public void onload ClassPool pool, String classname ) ConstPool cp = cf.getconstpool throws NotFoundException, CannotCompileException if classname.equals "target_0" ) ) Bytecode bc = new Bytecode cp, 1, 0 * iconst_1 * ireturn ClassFile cf = pool.get classname ).getclassfile MethodInfo mi = cf.getmethod "VerifyHash" CodeAttribute ca = mi.getcodeattribute bc.addiconst 1 bc.addreturn CtClass.intType CodeAttribute tca = bc.tocodeattribute CodeIterator try ci = ca.iterator tca.setmaxlocals ca.getmaxlocals) tca.computemaxstack mi.setcodeattribute tca int int index; op; catch BadBytecode e ) * 显示 VerifyHash) 的 opcode e.printstacktrace while ci.hasnext) ) index = ci.next op = ci.byteat index System.out.println Mnemonic.OPCODE[op] public class crack_target_0_i 55

public static void main String[] argv ) throws Throwable 演示性玩具, 不具备实际价值, 至少目前是这样的 出于演示完备 性, 提供 crack_target_0_m.java 演示之 它先保存原来的 Hash. ClassPool pool = ClassPool.getDefault class, 然后在内存中修改 Hash.class,reload 修改过的版本, 然 Loader loader = new Loader Translator t = new crack_target_0_i_translator loader.addtranslator pool, t loader.run "target_0", argv $ java -cp "javassist.jar;target_0.jar;." crack_target_0_i anything ldc aload_0 invokestatic ldc invokevirtual ireturn Modified You are a clever boy! 对于编写 Loader, 前面演示的技术足以应付绝大多数需求 可能有很多小变种, 但本质上没有区别 六 鸡肋一般的 HotSwap 支持最后提一下 Javassist 提供的 HotSwapper 类, 这几乎是个 后 reload 原来的版本 import javassist.util.hotswapper; public class crack_target_0_m public static void main String[] argv ) throws Throwable HotSwapper hs = new HotSwapper 31337 System.out.println Hash.gethash "SHA1", "anything" ) * 保存原来的 class ClassPool pool = ClassPool.getDefault CtClass old_class = pool.get "Hash" old_class.detach byte[] old_buf = old_class.tobytecode * 修改 class method if old_class.isfrozen) ) 56

System.out.println "\nreload original version\n" old_class.defrost hs.reload "Hash", old_buf target_0.main argv C t M e t h o d o l d _ m e t h o d = o l d _ c l a s s. getdeclaredmethod "gethash" old_class.removemethod old_method CtMethod new_method = CtMethod.make "public static String gethash String algorithm, String text )" + "" + " System.out.pr intln \" M odif ied\" " + " return \"7BCD1686FE4BCE0A06655740FE54D 0C233855872\" " + "", old_class old_class.addmethod new_method byte[] new_buf = old_class.tobytecode System.out.println "\nreload modified version\n" hs.reload "Hash", new_buf target_0.main argv $ javac -cp "tools.jar;javassist.jar;target_0.jar" crack_ target_0_m.java $ java -agentlib:jdwp=transport=dt_socket,address=127.0.0. 1:31337,server=y,suspend=n -cp "tools.jar;javassist.jar;target_0. jar;." crack_target_0_m anything Listening for transport dt_socket at address: 31337 8867C88B56E0BFB82CFFAF15A66BC8D107D6754A reload modified version Modified You are a clever boy! reload original version 编译时需要 tools.jar 执行时必须以调试模式启动 Javassist 能干些什么完全取决于你对 Java 语言 class 格式以及 JVM 的理解程度 比如有人用它给无调试信息的 class 添加行号信息, 这样某些动态调试工具就可以更有作为 ; 有人用它反混淆等等 本文演示了 Javassist 的基本技术, 更多高级用法等待着大家在实际需求产生后去探索并应用 57