深度分析java 使用 proguard 如何解析混淆后的堆栈
经过proguard混淆过后,发生异常时堆栈也进行了混淆,那么如果获取的原始的堆栈呢?我们下面来看下
使用proguard 根据mapping文件直接解析
import proguard.obfuscate.MappingReader;
import proguard.retrace.FrameInfo;
import proguard.retrace.FramePattern;
import proguard.retrace.FrameRemapper;
import proguard.retrace.ReTrace;import java.io.File;
import java.io.IOException;public class SymbolAnalysis {public static void main(String[] args) throws IOException {final FramePattern pattern = new FramePattern(ReTrace.REGULAR_EXPRESSION, false);final FrameRemapper frameRemapper = new FrameRemapper();MappingReader mappingReader = new MappingReader(new File("proguard/target/proguard_map.txt"));mappingReader.pump(frameRemapper);String crashStack = "Caused by: java.lang.RuntimeException: test exception\n" +" at com.example.proguard.b.b.<init>(User.java:25) ~[classes!/:0.0.1]\n" +" at com.example.proguard.ProguardApplication.run(ProguardApplication.java:22) [classes!/:0.0.1]\n" +" at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:804) [spring-boot-2.4.2.jar!/:2.4.2]\n" +" ... 13 common frames omitted\n";final String[] stackList = crashStack.split("\n");for (String stack : stackList) {FrameInfo frameInfo = pattern.parse(stack);if (frameInfo == null) {System.out.println(stack);continue;}for (FrameInfo retracedFrame : frameRemapper.transform(frameInfo)) {String retraceStack = pattern.format(stack, retracedFrame);System.out.println(retraceStack);}}}
}
运行结果如下,可以看到堆栈已经还原为了之前的源代码
proguard 是如何解析的呢
通过魔改proguard.obfuscate.MappingReader
这个类,我们加入写打印日志,分别是下面带有箭头的地方添加日志输出
然后我们修改下解析方法中我们自定义的CustomizeMappingReader
,如下:
通过运行,我们可以得到如下结果:
通过分析我们可以发现:
- class : 分为两个部分,混淆之后的类的全限定名及原始类的全限定名
- field: 分为三部分,分别是混淆之后的类的全限定名、混淆之后的字段名称、以及字段信息
- method: 分为三部分,分别是混淆之后的类的全限定名、混淆之后的方法名称、以及方法信息
根据这个结构,我们可以猜测到如果是方法解析,首先根据混淆之后的类的全限定名找到原始类的全限定名,然后根据混淆之后的方法名称以及方法信息找到原始的方法