├── acaf-core
├── pom.xml
└── src
│ └── main
│ ├── java
│ └── com
│ │ └── er1cccc
│ │ └── acaf
│ │ ├── Launcher.java
│ │ ├── config
│ │ ├── ACAFConfigurer.java
│ │ ├── ControllableParam.java
│ │ ├── PassthroughRegistry.java
│ │ ├── Sanitize.java
│ │ ├── SanitizeRegistry.java
│ │ ├── Sink.java
│ │ ├── SinkRegistry.java
│ │ ├── Source.java
│ │ └── SourceRegistry.java
│ │ ├── core
│ │ ├── audit
│ │ │ ├── auditcore
│ │ │ │ ├── CallGraph.java
│ │ │ │ ├── CallGraphClassVisitor.java
│ │ │ │ ├── CallGraphMethodAdapter.java
│ │ │ │ ├── CoreMethodAdapter.java
│ │ │ │ ├── DataFlowClassVisitor.java
│ │ │ │ ├── DataFlowMethodAdapter.java
│ │ │ │ ├── DiscoveryClassVisitor.java
│ │ │ │ ├── Field.java
│ │ │ │ ├── GotoState.java
│ │ │ │ ├── InheritanceMap.java
│ │ │ │ ├── InheritanceUtil.java
│ │ │ │ ├── LocalVariables.java
│ │ │ │ ├── MethodCallClassVisitor.java
│ │ │ │ ├── MethodCallMethodAdapter.java
│ │ │ │ ├── OperandStack.java
│ │ │ │ ├── SpringAnnoAdapter.java
│ │ │ │ ├── SpringClassVisitor.java
│ │ │ │ ├── SpringConstant.java
│ │ │ │ ├── SpringMethodAdapter.java
│ │ │ │ ├── SpringPathAnnoAdapter.java
│ │ │ │ ├── VulnClassVisitor.java
│ │ │ │ └── VulnMethodAdapter.java
│ │ │ └── discovery
│ │ │ │ ├── CallGraphDiscovery.java
│ │ │ │ ├── DrawService.java
│ │ │ │ ├── MethodDiscovery.java
│ │ │ │ ├── PassthroughDiscovery.java
│ │ │ │ ├── SpringDiscovery.java
│ │ │ │ └── VulnDiscovery.java
│ │ ├── entity
│ │ │ ├── ClassFile.java
│ │ │ ├── ClassReference.java
│ │ │ ├── Command.java
│ │ │ ├── Instruction.java
│ │ │ ├── MethodReference.java
│ │ │ ├── SpringController.java
│ │ │ ├── SpringMapping.java
│ │ │ ├── SpringParam.java
│ │ │ └── impl
│ │ │ │ └── VisitMethodInsnInfoInstruction.java
│ │ ├── resolver
│ │ │ ├── Resolver.java
│ │ │ └── impl
│ │ │ │ ├── CompositResolver.java
│ │ │ │ └── VisitMethodInsnInfoResolver.java
│ │ └── template
│ │ │ ├── VulnTemplateSanitizeVisitor.java
│ │ │ └── VulnTemplateSinkVisitor.java
│ │ ├── data
│ │ ├── DataFactory.java
│ │ └── DataLoader.java
│ │ └── util
│ │ ├── ClassNameClassVisitor.java
│ │ ├── DataUtil.java
│ │ ├── DirUtil.java
│ │ ├── DrawUtil.java
│ │ ├── FileUtil.java
│ │ ├── IOUtil.java
│ │ ├── JarUtil.java
│ │ └── RtUtil.java
│ └── resources
│ └── log4j.properties
├── acaf-example
├── pom.xml
└── src
│ └── main
│ └── java
│ └── com
│ └── er1cccc
│ └── acaf
│ └── example
│ ├── App.java
│ ├── sql
│ ├── SqlConfigurer.java
│ └── SqlSink.java
│ └── ssrf
│ ├── SSRFConfigurer.java
│ ├── SsrfSink1.java
│ ├── SsrfSink2.java
│ ├── SsrfSink3.java
│ └── SsrfSink4.java
├── acaf
├── image-20220103131703025.png
├── image-20220103132616981.png
├── image-20220103133558167.png
├── image-20220103141501161.png
├── image-20220103141828815.png
├── image-20220103141917976.png
├── image-20220103142558198.png
├── image-20220103142721032.png
├── image-20220103142841443.png
├── image-20220103142903948.png
├── image-20220103143104899.png
├── image-20220103143239083.png
├── image-20220103143422984.png
├── image-20220103143507206.png
├── image-20220103145309189.png
├── image-20220103145355140.png
├── image-20220103145427848.png
├── image-20220103145604152.png
├── image-20220103145810118.png
├── image-20220103150117976.png
├── image-20220103151240038.png
├── image-20220103151733418.png
├── image-20220103151747594.png
├── image-20220103155122573.png
├── image-20220103155809694.png
├── image-20220103160230238.png
├── image-20220103160528500.png
├── image-20220103162135990.png
├── image-20220103162254813.png
├── image-20220103162431545.png
├── image-20220103162532243.png
├── image-20220103162812381.png
├── image-20220103164332924.png
├── image-20220103164537493.png
├── image-20220103164749513.png
├── image-20220103170547318.png
└── image-20220103170644290.png
├── pom.xml
└── readme.md
/acaf-core/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
5 | 4.0.0
6 |
7 |
8 | com.er1cccc
9 | acaf
10 | 1.0
11 |
12 |
13 | acaf-core
14 |
15 |
16 |
17 | guru.nidi
18 | graphviz-java
19 |
20 |
21 | ch.qos.logback
22 | logback-classic
23 |
24 |
25 | log4j
26 | log4j
27 |
28 |
29 | com.beust
30 | jcommander
31 |
32 |
33 | org.ow2.asm
34 | asm
35 |
36 |
37 | org.ow2.asm
38 | asm-commons
39 |
40 |
41 | com.google.guava
42 | guava
43 |
44 |
45 | org.projectlombok
46 | lombok
47 |
48 |
49 |
50 |
--------------------------------------------------------------------------------
/acaf-core/src/main/java/com/er1cccc/acaf/Launcher.java:
--------------------------------------------------------------------------------
1 | package com.er1cccc.acaf;
2 |
3 | import com.beust.jcommander.JCommander;
4 | import com.er1cccc.acaf.config.*;
5 | import com.er1cccc.acaf.core.audit.auditcore.CallGraph;
6 | import com.er1cccc.acaf.core.audit.auditcore.InheritanceMap;
7 | import com.er1cccc.acaf.core.audit.auditcore.InheritanceUtil;
8 | import com.er1cccc.acaf.core.audit.discovery.*;
9 | import com.er1cccc.acaf.core.entity.*;
10 | import com.er1cccc.acaf.core.resolver.impl.CompositResolver;
11 | import com.er1cccc.acaf.core.template.VulnTemplateSinkVisitor;
12 | import com.er1cccc.acaf.data.DataLoader;
13 | import com.er1cccc.acaf.util.DataUtil;
14 | import com.er1cccc.acaf.util.DirUtil;
15 | import com.er1cccc.acaf.util.RtUtil;
16 | import org.apache.log4j.Logger;
17 | import org.objectweb.asm.ClassReader;
18 |
19 | import java.io.File;
20 | import java.io.IOException;
21 | import java.nio.file.Files;
22 | import java.nio.file.Path;
23 | import java.nio.file.Paths;
24 | import java.util.*;
25 |
26 | public class Launcher {
27 | private static final Logger logger = Logger.getLogger(Launcher.class);
28 |
29 | public static void launch(ACAFConfigurer configurer,String[] args) throws Exception {
30 | logger.info("start code inspector");
31 | Command command = new Command();
32 | JCommander jc = JCommander.newBuilder().addObject(command).build();
33 | jc.parse(args);
34 | if (command.help) {
35 | jc.usage();
36 | }
37 | if (command.boots != null && command.boots.size() != 0) {
38 | doLaunch(command.boots, command.templates, command.packageName, configurer);
39 | }
40 | }
41 |
42 | private static void doLaunch(List boots, List templates, String packageName, ACAFConfigurer configurer) throws Exception{
43 | List templateClassFileList = RtUtil.getAllClassesFromJars(templates);
44 | List targetClassFileList = RtUtil.getAllClassesFromBoot(boots, true);
45 | Path targetSaveDataDirPath = Paths.get("audit_target");
46 | Path templateSaveDataDirPath = Paths.get("audit_template");
47 | Runtime.getRuntime().addShutdownHook(new Thread(() -> {
48 | DirUtil.removeDir(targetSaveDataDirPath.toFile());
49 | DirUtil.removeDir(templateSaveDataDirPath.toFile());
50 | }));
51 | prepareLaunch(templateClassFileList,templateSaveDataDirPath);
52 | prepareLaunch(targetClassFileList,targetSaveDataDirPath);
53 |
54 | // 包名
55 | String finalPackageName = packageName.replace(".", "/");
56 | // 获取全部controller
57 | SpringDiscovery springDiscovery = new SpringDiscovery();
58 | springDiscovery.discover(targetClassFileList, finalPackageName,targetSaveDataDirPath);
59 | List controllers = springDiscovery.getControllers();
60 |
61 | SourceRegistry sourceRegistry = new SourceRegistry();
62 | SanitizeRegistry sanitizeRegistry = new SanitizeRegistry();
63 | SinkRegistry sinkRegistry = new SinkRegistry();
64 | configurer.addSource(sourceRegistry);
65 | configurer.addSanitize(sanitizeRegistry);
66 | configurer.addSink(sinkRegistry);
67 |
68 | VulnDiscovery vulnDiscovery = new VulnDiscovery(targetClassFileList, sourceRegistry,sanitizeRegistry,sinkRegistry, targetSaveDataDirPath,templateSaveDataDirPath);
69 | vulnDiscovery.discover(controllers);
70 |
71 | // // 画出指定package的调用图
72 | // DrawService.start(discoveredCalls, finalPackageName, classMap, methodImplMap);
73 | }
74 |
75 | private static void prepareLaunch(List classFileList, Path saveDataDirPath) throws IOException {
76 | if(!saveDataDirPath.toFile().exists()){
77 | saveDataDirPath.toFile().mkdirs();
78 | }
79 | // 读取JDK和输入Jar所有class资源
80 | // 获取所有方法和类
81 | File dir = saveDataDirPath.toFile();
82 | if (!new File(dir,"classes.dat").exists() || !new File(dir,"methods.dat").exists()
83 | || !new File(dir,"inheritanceMap.dat").exists()) {
84 | logger.info("Running method discovery...");
85 | MethodDiscovery methodDiscovery = new MethodDiscovery();
86 | methodDiscovery.discover(classFileList);
87 | methodDiscovery.save(saveDataDirPath);
88 | }
89 |
90 | if (!new File(dir,"passthrough.dat").exists()) {
91 | logger.info("Analyzing methods for passthrough dataflow...");
92 | PassthroughDiscovery passthroughDiscovery = new PassthroughDiscovery();
93 | passthroughDiscovery.discover(classFileList,saveDataDirPath);
94 | passthroughDiscovery.save(saveDataDirPath);
95 | }
96 |
97 |
98 | if (!new File(dir,"callgraph.dat").exists()) {
99 | logger.info("Analyzing methods in order to build a call graph...");
100 | CallGraphDiscovery callGraphDiscovery = new CallGraphDiscovery();
101 | callGraphDiscovery.discover(classFileList,saveDataDirPath);
102 | callGraphDiscovery.save(saveDataDirPath);
103 | }
104 | }
105 |
106 |
107 | }
108 |
--------------------------------------------------------------------------------
/acaf-core/src/main/java/com/er1cccc/acaf/config/ACAFConfigurer.java:
--------------------------------------------------------------------------------
1 | package com.er1cccc.acaf.config;
2 |
3 | public interface ACAFConfigurer {
4 | void addSource(SourceRegistry sourceRegistry);
5 | void addSanitize(SanitizeRegistry sanitizeRegistry);
6 | void addSink(SinkRegistry sinkRegistry);
7 | }
8 |
--------------------------------------------------------------------------------
/acaf-core/src/main/java/com/er1cccc/acaf/config/ControllableParam.java:
--------------------------------------------------------------------------------
1 | package com.er1cccc.acaf.config;
2 |
3 | import java.util.HashMap;
4 | import java.util.Map;
5 |
6 | public class ControllableParam {
7 | private Map params=new HashMap<>();
8 |
9 | public V put(String key, V value){
10 | return (V) params.put(key, value);
11 | }
12 |
13 | public Object getParameter(String name){
14 | return params.get(name);
15 | }
16 |
17 | }
18 |
--------------------------------------------------------------------------------
/acaf-core/src/main/java/com/er1cccc/acaf/config/PassthroughRegistry.java:
--------------------------------------------------------------------------------
1 | package com.er1cccc.acaf.config;
2 |
3 | import com.er1cccc.acaf.core.audit.discovery.PassthroughDiscovery;
4 | import com.er1cccc.acaf.core.entity.ClassReference;
5 | import com.er1cccc.acaf.core.entity.MethodReference;
6 | import org.objectweb.asm.*;
7 | import java.io.IOException;
8 | import java.lang.reflect.Constructor;
9 | import java.lang.reflect.Method;
10 | import java.util.HashSet;
11 | import java.util.Map;
12 | import java.util.Set;
13 |
14 | public class PassthroughRegistry {
15 | private Map> passthroughDataflow;
16 |
17 | public PassthroughRegistry(Map> passthroughDataflow) {
18 | this.passthroughDataflow=passthroughDataflow;
19 | }
20 |
21 |
22 | public void addPassthrough(Method method,Integer ...args) throws IOException {
23 | ClassReference.Handle classHandle = new ClassReference.Handle(method.getDeclaringClass().getName().replace(".","/"));
24 | MethodReference.Handle methodHandle = new MethodReference.Handle(classHandle, method.getName(), Type.getMethodDescriptor(method));
25 | HashSet argSet = new HashSet<>();
26 | for(int arg:args){
27 | argSet.add(arg);
28 | }
29 | this.passthroughDataflow.put(methodHandle,argSet);
30 | }
31 |
32 | public void addPassthrough(Constructor constructor, Integer ...args) throws IOException {
33 | ClassReference.Handle classHandle = new ClassReference.Handle(constructor.getDeclaringClass().getName().replace(".","/"));
34 | MethodReference.Handle methodHandle = new MethodReference.Handle(classHandle, "", Type.getConstructorDescriptor(constructor));
35 | HashSet argSet = new HashSet<>();
36 | for(int arg:args){
37 | argSet.add(arg);
38 | }
39 | this.passthroughDataflow.put(methodHandle,argSet);
40 | }
41 |
42 |
43 | public static void main(String[] args) throws Exception{
44 | // PassthroughRegistry passthroughRegistry = new PassthroughRegistry(null);
45 | // passthroughRegistry.addPassthrough(PassthroughRegistry.class.getMethod("main",String[].class),null);
46 | }
47 |
48 | }
49 |
--------------------------------------------------------------------------------
/acaf-core/src/main/java/com/er1cccc/acaf/config/Sanitize.java:
--------------------------------------------------------------------------------
1 | package com.er1cccc.acaf.config;
2 |
3 | public interface Sanitize {
4 | Object sanitizeMethod() throws Exception;
5 | }
6 |
--------------------------------------------------------------------------------
/acaf-core/src/main/java/com/er1cccc/acaf/config/SanitizeRegistry.java:
--------------------------------------------------------------------------------
1 | package com.er1cccc.acaf.config;
2 |
3 | public class SanitizeRegistry {
4 | }
5 |
--------------------------------------------------------------------------------
/acaf-core/src/main/java/com/er1cccc/acaf/config/Sink.java:
--------------------------------------------------------------------------------
1 | package com.er1cccc.acaf.config;
2 |
3 | public interface Sink {
4 | Object sinkMethod() throws Exception;
5 |
6 | default void addPassthrough(PassthroughRegistry passthroughRegistry) {}
7 | }
8 |
--------------------------------------------------------------------------------
/acaf-core/src/main/java/com/er1cccc/acaf/config/SinkRegistry.java:
--------------------------------------------------------------------------------
1 | package com.er1cccc.acaf.config;
2 |
3 | import lombok.Data;
4 |
5 | import java.util.ArrayList;
6 | import java.util.List;
7 |
8 | @Data
9 | public class SinkRegistry {
10 | private List sinkList=new ArrayList<>();
11 |
12 | public SinkRegistry addSink(Sink sink) {
13 | this.sinkList.add(sink);
14 | return this;
15 | }
16 |
17 | }
18 |
--------------------------------------------------------------------------------
/acaf-core/src/main/java/com/er1cccc/acaf/config/Source.java:
--------------------------------------------------------------------------------
1 | package com.er1cccc.acaf.config;
2 |
3 | public interface Source {
4 | }
5 |
--------------------------------------------------------------------------------
/acaf-core/src/main/java/com/er1cccc/acaf/config/SourceRegistry.java:
--------------------------------------------------------------------------------
1 | package com.er1cccc.acaf.config;
2 |
3 | public class SourceRegistry {
4 | }
5 |
--------------------------------------------------------------------------------
/acaf-core/src/main/java/com/er1cccc/acaf/core/audit/auditcore/CallGraph.java:
--------------------------------------------------------------------------------
1 | package com.er1cccc.acaf.core.audit.auditcore;
2 |
3 |
4 | import com.er1cccc.acaf.core.entity.ClassReference;
5 | import com.er1cccc.acaf.core.entity.MethodReference;
6 | import com.er1cccc.acaf.data.DataFactory;
7 |
8 | import java.util.Objects;
9 |
10 | @SuppressWarnings("all")
11 | public class CallGraph {
12 | private final MethodReference.Handle callerMethod;
13 | private final MethodReference.Handle targetMethod;
14 | private final int callerArgIndex;
15 | private final String callerArgPath;
16 | private final int targetArgIndex;
17 |
18 | public CallGraph(MethodReference.Handle callerMethod, MethodReference.Handle targetMethod,
19 | int callerArgIndex, String callerArgPath, int targetArgIndex) {
20 | this.callerMethod = callerMethod;
21 | this.targetMethod = targetMethod;
22 | this.callerArgIndex = callerArgIndex;
23 | this.callerArgPath = callerArgPath;
24 | this.targetArgIndex = targetArgIndex;
25 | }
26 |
27 | public CallGraph(MethodReference.Handle callerMethod, MethodReference.Handle targetMethod) {
28 | this.callerMethod = callerMethod;
29 | this.targetMethod = targetMethod;
30 | this.callerArgIndex = -1;
31 | this.callerArgPath = "";
32 | this.targetArgIndex = -1;
33 | }
34 |
35 | public MethodReference.Handle getCallerMethod() {
36 | return callerMethod;
37 | }
38 |
39 | public MethodReference.Handle getTargetMethod() {
40 | return targetMethod;
41 | }
42 |
43 | public int getCallerArgIndex() {
44 | return callerArgIndex;
45 | }
46 |
47 | public String getCallerArgPath() {
48 | return callerArgPath;
49 | }
50 |
51 | public int getTargetArgIndex() {
52 | return targetArgIndex;
53 | }
54 |
55 | @Override
56 | public boolean equals(Object o) {
57 | if (this == o) return true;
58 | if (o == null || getClass() != o.getClass()) return false;
59 |
60 | CallGraph CallGraph = (CallGraph) o;
61 |
62 | if (callerArgIndex != CallGraph.callerArgIndex) return false;
63 | if (targetArgIndex != CallGraph.targetArgIndex) return false;
64 | if (!Objects.equals(callerMethod, CallGraph.callerMethod))
65 | return false;
66 | if (!Objects.equals(targetMethod, CallGraph.targetMethod))
67 | return false;
68 | return Objects.equals(callerArgPath, CallGraph.callerArgPath);
69 | }
70 |
71 | @Override
72 | public int hashCode() {
73 | int result = callerMethod != null ? callerMethod.hashCode() : 0;
74 | result = 31 * result + (targetMethod != null ? targetMethod.hashCode() : 0);
75 | result = 31 * result + callerArgIndex;
76 | result = 31 * result + (callerArgPath != null ? callerArgPath.hashCode() : 0);
77 | result = 31 * result + targetArgIndex;
78 | return result;
79 | }
80 |
81 |
82 | public static class Factory implements DataFactory {
83 |
84 | @Override
85 | public CallGraph parse(String[] fields) {
86 | return new CallGraph(
87 | new MethodReference.Handle(new ClassReference.Handle(fields[0]), fields[1], fields[2]),
88 | new MethodReference.Handle(new ClassReference.Handle(fields[3]), fields[4], fields[5]),
89 | Integer.parseInt(fields[6]),
90 | fields[7],
91 | Integer.parseInt(fields[8]));
92 | }
93 |
94 | @Override
95 | public String[] serialize(CallGraph obj) {
96 | return new String[]{
97 | obj.callerMethod.getClassReference().getName(), obj.callerMethod.getName(), obj.callerMethod.getDesc(),
98 | obj.targetMethod.getClassReference().getName(), obj.targetMethod.getName(), obj.targetMethod.getDesc(),
99 | Integer.toString(obj.callerArgIndex),
100 | obj.callerArgPath,
101 | Integer.toString(obj.targetArgIndex),
102 | };
103 | }
104 | }
105 | }
106 |
--------------------------------------------------------------------------------
/acaf-core/src/main/java/com/er1cccc/acaf/core/audit/auditcore/CallGraphClassVisitor.java:
--------------------------------------------------------------------------------
1 | package com.er1cccc.acaf.core.audit.auditcore;
2 |
3 | import com.er1cccc.acaf.core.entity.ClassReference;
4 | import com.er1cccc.acaf.core.entity.MethodReference;
5 | import org.objectweb.asm.ClassVisitor;
6 | import org.objectweb.asm.MethodVisitor;
7 | import org.objectweb.asm.Opcodes;
8 | import org.objectweb.asm.commons.JSRInlinerAdapter;
9 |
10 | import java.util.Map;
11 | import java.util.Set;
12 |
13 | @SuppressWarnings("all")
14 | public class CallGraphClassVisitor extends ClassVisitor {
15 | private final Set discoveredCalls;
16 | private final Map classMap;
17 | private final InheritanceMap inheritanceMap;
18 | private final Map> passthroughDataflow;
19 |
20 | private String name;
21 | private String signature;
22 | private String superName;
23 | private String[] interfaces;
24 |
25 | public CallGraphClassVisitor(Map classMap,
26 | InheritanceMap inheritanceMap,
27 | Map> passthroughDataflow,
28 | Set discoveredCalls) {
29 | super(Opcodes.ASM6);
30 | this.classMap = classMap;
31 | this.inheritanceMap = inheritanceMap;
32 | this.passthroughDataflow = passthroughDataflow;
33 | this.discoveredCalls = discoveredCalls;
34 | }
35 |
36 | @Override
37 | public void visit(int version, int access, String name, String signature,
38 | String superName, String[] interfaces) {
39 | super.visit(version, access, name, signature, superName, interfaces);
40 | this.name = name;
41 | this.signature = signature;
42 | this.superName = superName;
43 | this.interfaces = interfaces;
44 | }
45 |
46 | @Override
47 | public MethodVisitor visitMethod(int access, String name, String desc,
48 | String signature, String[] exceptions) {
49 | MethodVisitor mv = super.visitMethod(access, name, desc, signature, exceptions);
50 | CallGraphMethodAdapter modelGeneratorMethodVisitor = new CallGraphMethodAdapter(classMap,
51 | inheritanceMap, passthroughDataflow, api, discoveredCalls,
52 | mv, this.name, access, name, desc, signature, exceptions);
53 | return new JSRInlinerAdapter(modelGeneratorMethodVisitor, access, name, desc, signature, exceptions);
54 | }
55 |
56 | @Override
57 | public void visitEnd() {
58 | super.visitEnd();
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/acaf-core/src/main/java/com/er1cccc/acaf/core/audit/auditcore/CallGraphMethodAdapter.java:
--------------------------------------------------------------------------------
1 | package com.er1cccc.acaf.core.audit.auditcore;
2 |
3 |
4 | import com.er1cccc.acaf.core.entity.ClassReference;
5 | import com.er1cccc.acaf.core.entity.MethodReference;
6 | import org.objectweb.asm.MethodVisitor;
7 | import org.objectweb.asm.Opcodes;
8 | import org.objectweb.asm.Type;
9 |
10 | import java.util.Map;
11 | import java.util.Set;
12 |
13 | @SuppressWarnings("all")
14 | public class CallGraphMethodAdapter extends CoreMethodAdapter {
15 | private final Map classMap;
16 | private final Set discoveredCalls;
17 | private final InheritanceMap inheritanceMap;
18 | private final String owner;
19 | private final int access;
20 | private final String name;
21 | private final String desc;
22 |
23 | public CallGraphMethodAdapter(Map classMap,
24 | InheritanceMap inheritanceMap,
25 | Map> passthroughDataflow,
26 | final int api, Set discoveredCalls,
27 | final MethodVisitor mv, final String owner, int access, String name, String desc,
28 | String signature, String[] exceptions) {
29 | super(inheritanceMap, passthroughDataflow, api, mv, owner, access, name, desc, signature, exceptions);
30 | this.classMap = classMap;
31 | this.inheritanceMap = inheritanceMap;
32 | this.owner = owner;
33 | this.access = access;
34 | this.name = name;
35 | this.desc = desc;
36 | this.discoveredCalls = discoveredCalls;
37 | }
38 |
39 | @Override
40 | public void visitCode() {
41 | super.visitCode();
42 | int localIndex = 0;
43 | int argIndex = 0;
44 | if ((this.access & Opcodes.ACC_STATIC) == 0) {
45 | localVariables.set(localIndex, "arg" + argIndex);
46 | localIndex += 1;
47 | argIndex += 1;
48 | }
49 | for (Type argType : Type.getArgumentTypes(desc)) {
50 | localVariables.set(localIndex, "arg" + argIndex);
51 | localIndex += argType.getSize();
52 | argIndex += 1;
53 | }
54 | }
55 |
56 | @Override
57 | public void visitMethodInsn(int opcode, String owner, String name, String desc, boolean itf) {
58 | Type[] argTypes = Type.getArgumentTypes(desc);
59 | if (opcode != Opcodes.INVOKESTATIC) {
60 | Type[] extendedArgTypes = new Type[argTypes.length + 1];
61 | System.arraycopy(argTypes, 0, extendedArgTypes, 1, argTypes.length);
62 | extendedArgTypes[0] = Type.getObjectType(owner);
63 | argTypes = extendedArgTypes;
64 | }
65 | switch (opcode) {
66 | case Opcodes.INVOKESTATIC:
67 | case Opcodes.INVOKEVIRTUAL:
68 | case Opcodes.INVOKESPECIAL:
69 | case Opcodes.INVOKEINTERFACE:
70 | int stackIndex = 0;
71 | for (int i = 0; i < argTypes.length; i++) {
72 | int argIndex = argTypes.length - 1 - i;
73 | Type type = argTypes[argIndex];
74 | Set taint = operandStack.get(stackIndex);
75 | if (taint.size() > 0) {
76 | for (String argSrc : taint) {
77 | if (!argSrc.startsWith("arg")) {
78 | throw new IllegalStateException("invalid taint arg: " + argSrc);
79 | }
80 | int dotIndex = argSrc.indexOf('.');
81 | int srcArgIndex;
82 | String srcArgPath;
83 | if (dotIndex == -1) {
84 | srcArgIndex = Integer.parseInt(argSrc.substring(3));
85 | srcArgPath = null;
86 | } else {
87 | srcArgIndex = Integer.parseInt(argSrc.substring(3, dotIndex));
88 | srcArgPath = argSrc.substring(dotIndex + 1);
89 | }
90 | discoveredCalls.add(new CallGraph(
91 | new MethodReference.Handle(
92 | new ClassReference.Handle(this.owner), this.name, this.desc),
93 | new MethodReference.Handle(
94 | new ClassReference.Handle(owner), name, desc),
95 | srcArgIndex,
96 | srcArgPath,
97 | argIndex));
98 | }
99 | }else{
100 | discoveredCalls.add(new CallGraph(
101 | new MethodReference.Handle(
102 | new ClassReference.Handle(this.owner), this.name, this.desc),
103 | new MethodReference.Handle(
104 | new ClassReference.Handle(owner), name, desc)
105 | ));
106 | }
107 | stackIndex += type.getSize();
108 | }
109 | break;
110 | default:
111 | throw new IllegalStateException("unsupported opcode: " + opcode);
112 | }
113 | super.visitMethodInsn(opcode, owner, name, desc, itf);
114 | }
115 | }
116 |
--------------------------------------------------------------------------------
/acaf-core/src/main/java/com/er1cccc/acaf/core/audit/auditcore/DataFlowClassVisitor.java:
--------------------------------------------------------------------------------
1 | package com.er1cccc.acaf.core.audit.auditcore;
2 |
3 | import com.er1cccc.acaf.core.entity.ClassReference;
4 | import com.er1cccc.acaf.core.entity.MethodReference;
5 | import org.objectweb.asm.ClassVisitor;
6 | import org.objectweb.asm.FieldVisitor;
7 | import org.objectweb.asm.MethodVisitor;
8 | import org.objectweb.asm.Opcodes;
9 | import org.objectweb.asm.commons.JSRInlinerAdapter;
10 |
11 | import java.util.HashSet;
12 | import java.util.Map;
13 | import java.util.Set;
14 |
15 | @SuppressWarnings("all")
16 | public class DataFlowClassVisitor extends ClassVisitor {
17 | Map classMap;
18 | private final MethodReference.Handle methodToVisit;
19 | private final InheritanceMap inheritanceMap;
20 | private final Map> passthroughDataflow;
21 |
22 | private String name;
23 | private DataFlowMethodAdapter dataFlowMethodAdapter;
24 |
25 | private Set fields;
26 |
27 | public DataFlowClassVisitor(Map classMap,
28 | InheritanceMap inheritanceMap,
29 | Map> passthroughDataflow,
30 | MethodReference.Handle methodToVisit) {
31 | super(Opcodes.ASM6);
32 | this.classMap = classMap;
33 | this.inheritanceMap = inheritanceMap;
34 | this.methodToVisit = methodToVisit;
35 | this.passthroughDataflow = passthroughDataflow;
36 | this.fields=new HashSet<>();
37 | }
38 |
39 | @Override
40 | public void visit(int version, int access, String name, String signature,
41 | String superName, String[] interfaces) {
42 | super.visit(version, access, name, signature, superName, interfaces);
43 | this.name = name;
44 | }
45 |
46 | @Override
47 | public FieldVisitor visitField(int access, String name, String descriptor, String signature, Object value) {
48 | FieldVisitor fieldVisitor = super.visitField(access, name, descriptor, signature, value);
49 | fields.add(new Field(name,descriptor));
50 | return fieldVisitor;
51 | }
52 |
53 | @Override
54 | public MethodVisitor visitMethod(int access, String name, String desc,
55 | String signature, String[] exceptions) {
56 | if (!name.equals(methodToVisit.getName()) || !desc.equals(methodToVisit.getDesc())) {
57 | return null;
58 | }
59 | MethodVisitor mv = super.visitMethod(access, name, desc, signature, exceptions);
60 | dataFlowMethodAdapter = new DataFlowMethodAdapter(classMap, inheritanceMap,
61 | this.passthroughDataflow, mv, this.name, access, name, desc, signature, exceptions, this.fields);
62 | return new JSRInlinerAdapter(dataFlowMethodAdapter, access, name, desc, signature, exceptions);
63 | }
64 |
65 | public Set getReturnTaint() {
66 | if (dataFlowMethodAdapter == null) {
67 | return null;
68 | } else {
69 | return dataFlowMethodAdapter.getReturnTaint();
70 | }
71 | }
72 | }
73 |
--------------------------------------------------------------------------------
/acaf-core/src/main/java/com/er1cccc/acaf/core/audit/auditcore/DataFlowMethodAdapter.java:
--------------------------------------------------------------------------------
1 | package com.er1cccc.acaf.core.audit.auditcore;
2 |
3 | import com.er1cccc.acaf.core.entity.ClassReference;
4 | import com.er1cccc.acaf.core.entity.MethodReference;
5 | import org.objectweb.asm.MethodVisitor;
6 | import org.objectweb.asm.Opcodes;
7 | import org.objectweb.asm.Type;
8 |
9 | import java.util.*;
10 |
11 | @SuppressWarnings("all")
12 | public class DataFlowMethodAdapter extends CoreMethodAdapter {
13 |
14 | private final Map classMap;
15 | private final InheritanceMap inheritanceMap;
16 | private final Map> passthroughDataflow;
17 |
18 | private final int access;
19 | private final String desc;
20 | private final Set returnTaint;
21 | private String owner;
22 | private boolean getter;
23 |
24 | public DataFlowMethodAdapter(Map classMap,
25 | InheritanceMap inheritanceMap,
26 | Map> passthroughDataflow,
27 | MethodVisitor mv, String owner, int access, String name,
28 | String desc, String signature, String[] exceptions, Set fields) {
29 | super(inheritanceMap, passthroughDataflow,
30 | Opcodes.ASM6, mv, owner, access, name, desc, signature, exceptions);
31 | this.classMap = classMap;
32 | this.inheritanceMap = inheritanceMap;
33 | this.passthroughDataflow = passthroughDataflow;
34 | this.access = access;
35 | this.desc = desc;
36 | this.owner=owner;
37 | returnTaint = new HashSet<>();
38 |
39 | initGetter(name, desc, fields, access);
40 | }
41 |
42 | private void initGetter(String name, String desc, Set fields, int access) {
43 | if ((this.access & Opcodes.ACC_STATIC) !=0) {
44 | getter=false;
45 | }else if(name.startsWith("get")||name.startsWith("is")){
46 | String fieldName;
47 | if(name.startsWith("get")){
48 | fieldName=name.replaceFirst("get","");
49 | }else{
50 | fieldName=name.replaceFirst("is","");
51 | }
52 | if(fieldName.length()==0)
53 | return;
54 | char[] chars = fieldName.toCharArray();
55 | chars[0]= Character.toLowerCase(fieldName.charAt(0));
56 | fieldName=new String(chars);
57 | Type returnType = Type.getReturnType(desc);
58 | Field field = new Field(fieldName, returnType.getDescriptor());
59 | getter = fields.contains(field);
60 | }
61 | }
62 |
63 | @Override
64 | public void visitCode() {
65 | super.visitCode();
66 | int localIndex = 0;
67 | int argIndex = 0;
68 | if ((this.access & Opcodes.ACC_STATIC) == 0) {
69 | localVariables.set(localIndex, argIndex);
70 | localIndex += 1;
71 | argIndex += 1;
72 | }
73 | for (Type argType : Type.getArgumentTypes(desc)) {
74 | localVariables.set(localIndex, argIndex);
75 | localIndex += argType.getSize();
76 | argIndex += 1;
77 | }
78 | }
79 |
80 | @Override
81 | public void visitInsn(int opcode) {
82 | switch (opcode) {
83 | case Opcodes.IRETURN:
84 | case Opcodes.FRETURN:
85 | case Opcodes.ARETURN:
86 | returnTaint.addAll(operandStack.get(0));
87 | break;
88 | case Opcodes.LRETURN:
89 | case Opcodes.DRETURN:
90 | returnTaint.addAll(operandStack.get(1));
91 | break;
92 | case Opcodes.RETURN:
93 | break;
94 | default:
95 | break;
96 | }
97 | super.visitInsn(opcode);
98 | }
99 |
100 | @Override
101 | public void visitFieldInsn(int opcode, String owner, String name, String desc) {
102 | super.visitFieldInsn(opcode,owner,name,desc);
103 | if(isGetter()&&opcode==Opcodes.GETFIELD){
104 | operandStack.get(0).add(0);
105 | }
106 | }
107 |
108 | private boolean isGetter() {
109 | return getter;
110 | }
111 |
112 |
113 | @Override
114 | public void visitMethodInsn(int opcode, String owner, String name, String desc, boolean itf) {
115 | Type[] argTypes = Type.getArgumentTypes(desc);
116 | if (opcode != Opcodes.INVOKESTATIC) {
117 | Type[] extendedArgTypes = new Type[argTypes.length+1];
118 | System.arraycopy(argTypes, 0, extendedArgTypes, 1, argTypes.length);
119 | extendedArgTypes[0] = Type.getObjectType(owner);
120 | argTypes = extendedArgTypes;
121 | }
122 | int retSize = Type.getReturnType(desc).getSize();
123 | Set resultTaint;
124 | switch (opcode) {
125 | case Opcodes.INVOKESTATIC:
126 | case Opcodes.INVOKEVIRTUAL:
127 | case Opcodes.INVOKESPECIAL:
128 | case Opcodes.INVOKEINTERFACE:
129 | final List> argTaint = new ArrayList<>(argTypes.length);
130 | for (int i = 0; i < argTypes.length; i++) {
131 | argTaint.add(null);
132 | }
133 | int stackIndex = 0;
134 | for (int i = 0; i < argTypes.length; i++) {
135 | Type argType = argTypes[i];
136 | if (argType.getSize() > 0) {
137 | argTaint.set(argTypes.length - 1 - i,
138 | operandStack.get(stackIndex+argType.getSize()-1));
139 | }
140 | stackIndex += argType.getSize();
141 | }
142 | if (name.equals("")) {
143 | resultTaint = argTaint.get(0);
144 | } else {
145 | resultTaint = new HashSet<>();
146 | }
147 | Set passthrough = passthroughDataflow.get(
148 | new MethodReference.Handle(new ClassReference.Handle(owner), name, desc));
149 | if (passthrough != null) {
150 | for (Integer passthroughDataflowArg : passthrough) {
151 | resultTaint.addAll(argTaint.get(passthroughDataflowArg));
152 | }
153 | }
154 | break;
155 | default:
156 | throw new IllegalStateException("unsupported opcode: " + opcode);
157 | }
158 | super.visitMethodInsn(opcode, owner, name, desc, itf);
159 | if (retSize > 0) {
160 | operandStack.get(retSize-1).addAll(resultTaint);
161 | }
162 | }
163 |
164 | public Set getReturnTaint() {
165 | return returnTaint;
166 | }
167 |
168 | }
169 |
--------------------------------------------------------------------------------
/acaf-core/src/main/java/com/er1cccc/acaf/core/audit/auditcore/DiscoveryClassVisitor.java:
--------------------------------------------------------------------------------
1 | package com.er1cccc.acaf.core.audit.auditcore;
2 |
3 | import com.er1cccc.acaf.core.entity.ClassFile;
4 | import com.er1cccc.acaf.core.entity.ClassReference;
5 | import com.er1cccc.acaf.core.entity.MethodReference;
6 | import org.apache.log4j.Logger;
7 | import org.objectweb.asm.*;
8 |
9 | import java.util.*;
10 |
11 | @SuppressWarnings("all")
12 | public class DiscoveryClassVisitor extends ClassVisitor {
13 | private static final Logger logger = Logger.getLogger(DiscoveryClassVisitor.class);
14 |
15 | private String name;
16 | private String superName;
17 | private String[] interfaces;
18 | private boolean isInterface;
19 | private List members;
20 | private ClassReference.Handle classHandle;
21 | private Set annotations;
22 | private List discoveredClasses;
23 | private List discoveredMethods;
24 | private ClassFile classFile;
25 |
26 | public DiscoveryClassVisitor(List discoveredClasses,
27 | List discoveredMethods,
28 | ClassFile classFile) {
29 | super(Opcodes.ASM6);
30 | this.discoveredClasses = discoveredClasses;
31 | this.discoveredMethods = discoveredMethods;
32 | this.classFile=classFile;
33 | }
34 |
35 | @Override
36 | public void visit(int version, int access, String name,
37 | String signature, String superName, String[] interfaces) {
38 | this.name = name;
39 | this.superName = superName;
40 | this.interfaces = interfaces;
41 | this.isInterface = (access & Opcodes.ACC_INTERFACE) != 0;
42 | this.members = new ArrayList<>();
43 | this.classHandle = new ClassReference.Handle(name);
44 | annotations = new HashSet<>();
45 | super.visit(version, access, name, signature, superName, interfaces);
46 | }
47 |
48 | @Override
49 | public AnnotationVisitor visitAnnotation(String descriptor, boolean visible) {
50 | annotations.add(descriptor);
51 | return super.visitAnnotation(descriptor, visible);
52 | }
53 |
54 | public FieldVisitor visitField(int access, String name, String desc,
55 | String signature, Object value) {
56 | if ((access & Opcodes.ACC_STATIC) == 0) {
57 | Type type = Type.getType(desc);
58 | String typeName;
59 | if (type.getSort() == Type.OBJECT || type.getSort() == Type.ARRAY) {
60 | typeName = type.getInternalName();
61 | } else {
62 | typeName = type.getDescriptor();
63 | }
64 | members.add(new ClassReference.Member(name, access, new ClassReference.Handle(typeName)));
65 | }
66 | return super.visitField(access, name, desc, signature, value);
67 | }
68 |
69 | @Override
70 | public MethodVisitor visitMethod(int access, String name, String desc,
71 | String signature, String[] exceptions) {
72 | boolean isStatic = (access & Opcodes.ACC_STATIC) != 0;
73 | discoveredMethods.add(new MethodReference(
74 | classHandle,
75 | name,
76 | desc,
77 | isStatic));
78 | return super.visitMethod(access, name, desc, signature, exceptions);
79 | }
80 |
81 | @Override
82 | public void visitEnd() {
83 | ClassReference classReference = new ClassReference(
84 | name,
85 | superName,
86 | Arrays.asList(interfaces),
87 | isInterface,
88 | members,
89 | annotations);
90 | discoveredClasses.add(classReference);
91 | super.visitEnd();
92 | }
93 | }
94 |
--------------------------------------------------------------------------------
/acaf-core/src/main/java/com/er1cccc/acaf/core/audit/auditcore/Field.java:
--------------------------------------------------------------------------------
1 | package com.er1cccc.acaf.core.audit.auditcore;
2 |
3 | import lombok.AllArgsConstructor;
4 | import lombok.Data;
5 | import lombok.NoArgsConstructor;
6 |
7 | @Data
8 | @AllArgsConstructor
9 | @NoArgsConstructor
10 | public class Field {
11 | private String name;
12 | private String descriptor;
13 |
14 |
15 | }
16 |
--------------------------------------------------------------------------------
/acaf-core/src/main/java/com/er1cccc/acaf/core/audit/auditcore/GotoState.java:
--------------------------------------------------------------------------------
1 | package com.er1cccc.acaf.core.audit.auditcore;
2 |
3 | @SuppressWarnings("all")
4 | public class GotoState {
5 | private LocalVariables localVariables;
6 | private OperandStack operandStack;
7 |
8 | public LocalVariables getLocalVariables() {
9 | return localVariables;
10 | }
11 |
12 | public void setLocalVariables(LocalVariables localVariables) {
13 | this.localVariables = localVariables;
14 | }
15 |
16 | public OperandStack getOperandStack() {
17 | return operandStack;
18 | }
19 |
20 | public void setOperandStack(OperandStack operandStack) {
21 | this.operandStack = operandStack;
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/acaf-core/src/main/java/com/er1cccc/acaf/core/audit/auditcore/InheritanceMap.java:
--------------------------------------------------------------------------------
1 | package com.er1cccc.acaf.core.audit.auditcore;
2 |
3 | import com.er1cccc.acaf.core.entity.ClassReference;
4 | import com.er1cccc.acaf.data.DataFactory;
5 | import com.er1cccc.acaf.data.DataLoader;
6 |
7 | import java.io.File;
8 | import java.io.IOException;
9 | import java.nio.file.Path;
10 | import java.nio.file.Paths;
11 | import java.util.*;
12 |
13 | @SuppressWarnings("all")
14 | public class InheritanceMap {
15 | private final Map> inheritanceMap;
16 | private final Map> subClassMap;
17 |
18 | public InheritanceMap(Map> inheritanceMap) {
19 | this.inheritanceMap = inheritanceMap;
20 | subClassMap = new HashMap<>();
21 | for (Map.Entry> entry : inheritanceMap.entrySet()) {
22 | ClassReference.Handle child = entry.getKey();
23 | for (ClassReference.Handle parent : entry.getValue()) {
24 | if (!subClassMap.containsKey(parent)) {
25 | Set tempSet = new HashSet<>();
26 | tempSet.add(child);
27 | subClassMap.put(parent, tempSet);
28 | } else {
29 | subClassMap.get(parent).add(child);
30 | }
31 | }
32 | }
33 | }
34 |
35 | public Set>> entrySet() {
36 | return inheritanceMap.entrySet();
37 | }
38 |
39 | public Set getSuperClasses(ClassReference.Handle clazz) {
40 | Set parents = inheritanceMap.get(clazz);
41 | if (parents == null) {
42 | return null;
43 | }
44 | return Collections.unmodifiableSet(parents);
45 | }
46 |
47 | public boolean isSubclassOf(ClassReference.Handle clazz, ClassReference.Handle superClass) {
48 | Set parents = inheritanceMap.get(clazz);
49 | if (parents == null) {
50 | return false;
51 | }
52 | return parents.contains(superClass);
53 | }
54 |
55 | public Set getSubClasses(ClassReference.Handle clazz) {
56 | Set subClasses = subClassMap.get(clazz);
57 | if (subClasses == null) {
58 | return null;
59 | }
60 | return Collections.unmodifiableSet(subClasses);
61 | }
62 |
63 | public void save(Path dirPath) throws IOException {
64 | DataLoader.saveData(new File(dirPath.toFile(),"inheritanceMap.dat").toPath(), new InheritanceMapFactory(), inheritanceMap.entrySet());
65 | }
66 |
67 | public static InheritanceMap load(Path dirPath) throws IOException {
68 | Map> inheritanceMap = new HashMap<>();
69 | for (Map.Entry> entry : DataLoader.loadData(
70 | new File(dirPath.toFile(),"inheritanceMap.dat").toPath(), new InheritanceMapFactory())) {
71 | inheritanceMap.put(entry.getKey(), entry.getValue());
72 | }
73 | return new InheritanceMap(inheritanceMap);
74 | }
75 |
76 | private static class InheritanceMapFactory implements DataFactory>> {
77 | @Override
78 | public Map.Entry> parse(String[] fields) {
79 | ClassReference.Handle clazz = new ClassReference.Handle(fields[0]);
80 | Set superClasses = new HashSet<>();
81 | for (int i = 1; i < fields.length; i++) {
82 | superClasses.add(new ClassReference.Handle(fields[i]));
83 | }
84 | return new AbstractMap.SimpleEntry<>(clazz, superClasses);
85 | }
86 |
87 | @Override
88 | public String[] serialize(Map.Entry> obj) {
89 | final String[] fields = new String[obj.getValue().size()+1];
90 | fields[0] = obj.getKey().getName();
91 | int i = 1;
92 | for (ClassReference.Handle handle : obj.getValue()) {
93 | fields[i++] = handle.getName();
94 | }
95 | return fields;
96 | }
97 | }
98 | }
99 |
--------------------------------------------------------------------------------
/acaf-core/src/main/java/com/er1cccc/acaf/core/audit/auditcore/InheritanceUtil.java:
--------------------------------------------------------------------------------
1 | package com.er1cccc.acaf.core.audit.auditcore;
2 |
3 | import com.er1cccc.acaf.core.entity.ClassReference;
4 | import com.er1cccc.acaf.core.entity.MethodReference;
5 |
6 | import java.util.HashMap;
7 | import java.util.HashSet;
8 | import java.util.Map;
9 | import java.util.Set;
10 |
11 | @SuppressWarnings("all")
12 | public class InheritanceUtil {
13 | public static InheritanceMap derive(Map classMap) {
14 | Map> implicitInheritance = new HashMap<>();
15 | for (ClassReference classReference : classMap.values()) {
16 | Set allParents = new HashSet<>();
17 | getAllParents(classReference, classMap, allParents);
18 | implicitInheritance.put(classReference.getHandle(), allParents);
19 | }
20 | return new InheritanceMap(implicitInheritance);
21 | }
22 |
23 | /**
24 | * 递归查找classReference的祖先类、祖先接口,全部存到allParents里去
25 | * @param classReference
26 | * @param classMap
27 | * @param allParents
28 | */
29 | private static void getAllParents(ClassReference classReference,
30 | Map classMap,
31 | Set allParents) {
32 | Set parents = new HashSet<>();
33 | if (classReference.getSuperClass() != null) {
34 | parents.add(new ClassReference.Handle(classReference.getSuperClass()));
35 | }
36 | for (String i : classReference.getInterfaces()) {
37 | parents.add(new ClassReference.Handle(i));
38 | }
39 |
40 | for (ClassReference.Handle immediateParent : parents) {
41 | ClassReference parentClassReference = classMap.get(immediateParent);
42 | if (parentClassReference == null) {
43 | continue;
44 | }
45 | allParents.add(parentClassReference.getHandle());
46 | getAllParents(parentClassReference, classMap, allParents);
47 | }
48 | }
49 |
50 | public static Map> getAllMethodImplementations(
51 | InheritanceMap inheritanceMap, Map methodMap) {
52 | Map> methodsByClass = getMethodsByClass(methodMap);
53 | Map> subClassMap = new HashMap<>();
54 | for (Map.Entry> entry : inheritanceMap.entrySet()) {
55 | for (ClassReference.Handle parent : entry.getValue()) {
56 | if (!subClassMap.containsKey(parent)) {
57 | Set subClasses = new HashSet<>();
58 | subClasses.add(entry.getKey());
59 | subClassMap.put(parent, subClasses);
60 | } else {
61 | subClassMap.get(parent).add(entry.getKey());
62 | }
63 | }
64 | }
65 | Map> methodImplMap = new HashMap<>();
66 | for (MethodReference method : methodMap.values()) {
67 | if (method.isStatic()) {
68 | continue;
69 | }
70 | Set overridingMethods = new HashSet<>();
71 | Set subClasses = subClassMap.get(method.getClassReference());
72 | if (subClasses != null) {
73 | for (ClassReference.Handle subClass : subClasses) {
74 | Set subClassMethods = methodsByClass.get(subClass);
75 | if (subClassMethods != null) {
76 | for (MethodReference.Handle subClassMethod : subClassMethods) {
77 | if (subClassMethod.getName().equals(method.getName()) &&
78 | subClassMethod.getDesc().equals(method.getDesc())) {
79 | overridingMethods.add(subClassMethod);
80 | }
81 | }
82 | }
83 | }
84 | }
85 | if (overridingMethods.size() > 0) {
86 | methodImplMap.put(method.getHandle(), overridingMethods);
87 | }
88 | }
89 | return methodImplMap;
90 | }
91 |
92 | public static Map> getMethodsByClass(
93 | Map methodMap) {
94 | Map> methodsByClass = new HashMap<>();
95 | for (MethodReference.Handle method : methodMap.keySet()) {
96 | ClassReference.Handle classReference = method.getClassReference();
97 | if (!methodsByClass.containsKey(classReference)) {
98 | Set methods = new HashSet<>();
99 | methods.add(method);
100 | methodsByClass.put(classReference, methods);
101 | } else {
102 | methodsByClass.get(classReference).add(method);
103 | }
104 | }
105 | return methodsByClass;
106 | }
107 | }
108 |
--------------------------------------------------------------------------------
/acaf-core/src/main/java/com/er1cccc/acaf/core/audit/auditcore/LocalVariables.java:
--------------------------------------------------------------------------------
1 | package com.er1cccc.acaf.core.audit.auditcore;
2 |
3 | import java.util.ArrayList;
4 | import java.util.HashSet;
5 | import java.util.List;
6 | import java.util.Set;
7 |
8 | @SuppressWarnings("all")
9 | public class LocalVariables {
10 | private final ArrayList> array;
11 |
12 | public LocalVariables() {
13 | this.array = new ArrayList<>();
14 | }
15 |
16 | public void clear(){
17 | this.array.clear();
18 | }
19 |
20 | public void add(Set t){
21 | this.array.add(t);
22 | }
23 |
24 | public void set(int index, Set t) {
25 | array.set(index, t);
26 | }
27 |
28 | public void set(int index, T t) {
29 | Set set = new HashSet<>();
30 | set.add(t);
31 | array.set(index, set);
32 | }
33 |
34 | public Set get(int index) {
35 | return array.get(index);
36 | }
37 |
38 | public int size(){
39 | return this.array.size();
40 | }
41 |
42 | public void remove(int index){
43 | this.array.remove(index);
44 | }
45 | public List> getList(){
46 | return this.array;
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/acaf-core/src/main/java/com/er1cccc/acaf/core/audit/auditcore/MethodCallClassVisitor.java:
--------------------------------------------------------------------------------
1 | package com.er1cccc.acaf.core.audit.auditcore;
2 |
3 | import com.er1cccc.acaf.core.entity.MethodReference;
4 | import org.objectweb.asm.ClassVisitor;
5 | import org.objectweb.asm.MethodVisitor;
6 | import org.objectweb.asm.Opcodes;
7 | import org.objectweb.asm.commons.JSRInlinerAdapter;
8 |
9 | import java.util.Map;
10 | import java.util.Set;
11 |
12 | @SuppressWarnings("all")
13 | public class MethodCallClassVisitor extends ClassVisitor {
14 | private final Map> methodCalls;
15 |
16 | public MethodCallClassVisitor(Map> methodCalls) {
17 | super(Opcodes.ASM6);
18 | this.methodCalls = methodCalls;
19 | }
20 |
21 | private String name = null;
22 |
23 | @Override
24 | public void visit(int version, int access, String name, String signature,
25 | String superName, String[] interfaces) {
26 | super.visit(version, access, name, signature, superName, interfaces);
27 | if (this.name != null) {
28 | throw new IllegalStateException("ClassVisitor already visited a class!");
29 | }
30 | this.name = name;
31 | }
32 |
33 | public String getName() {
34 | return name;
35 | }
36 |
37 | public Map> getMethodCalls() {
38 | return this.methodCalls;
39 | }
40 |
41 | @Override
42 | public MethodVisitor visitMethod(int access, String name, String desc,
43 | String signature, String[] exceptions) {
44 | MethodVisitor mv = super.visitMethod(access, name, desc, signature, exceptions);
45 | MethodCallMethodAdapter adapter = new MethodCallMethodAdapter(
46 | api, this.methodCalls, mv, this.name, name, desc);
47 | return new JSRInlinerAdapter(adapter, access, name, desc, signature, exceptions);
48 | }
49 |
50 | @Override
51 | public void visitEnd() {
52 | super.visitEnd();
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/acaf-core/src/main/java/com/er1cccc/acaf/core/audit/auditcore/MethodCallMethodAdapter.java:
--------------------------------------------------------------------------------
1 | package com.er1cccc.acaf.core.audit.auditcore;
2 |
3 | import com.er1cccc.acaf.core.entity.ClassReference;
4 | import com.er1cccc.acaf.core.entity.MethodReference;
5 | import org.objectweb.asm.MethodVisitor;
6 | import java.util.HashSet;
7 | import java.util.Map;
8 | import java.util.Set;
9 |
10 | @SuppressWarnings("all")
11 | public class MethodCallMethodAdapter extends MethodVisitor {
12 | private final Set calledMethods;
13 |
14 | public MethodCallMethodAdapter(int api, Map> methodCalls,
15 | final MethodVisitor mv, final String owner, String name, String desc) {
16 | super(api, mv);
17 | this.calledMethods = new HashSet<>();
18 | methodCalls.put(new MethodReference.Handle(new ClassReference.Handle(owner), name, desc), calledMethods);
19 | }
20 |
21 | @Override
22 | public void visitMethodInsn(int opcode, String owner, String name, String desc, boolean itf) {
23 | calledMethods.add(new MethodReference.Handle(new ClassReference.Handle(owner), name, desc));
24 | super.visitMethodInsn(opcode, owner, name, desc, itf);
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/acaf-core/src/main/java/com/er1cccc/acaf/core/audit/auditcore/OperandStack.java:
--------------------------------------------------------------------------------
1 | package com.er1cccc.acaf.core.audit.auditcore;
2 |
3 | import java.util.HashSet;
4 | import java.util.LinkedList;
5 | import java.util.List;
6 | import java.util.Set;
7 |
8 | @SuppressWarnings("all")
9 | public class OperandStack {
10 | private final LinkedList> stack;
11 |
12 | public OperandStack() {
13 | this.stack = new LinkedList<>();
14 | }
15 |
16 | public Set pop() {
17 | return stack.remove(stack.size() - 1);
18 | }
19 |
20 | public void push(T t) {
21 | Set set = new HashSet<>();
22 | set.add(t);
23 | stack.add(set);
24 | }
25 |
26 | public void push() {
27 | stack.add(new HashSet<>());
28 | }
29 |
30 | public void push(Set t) {
31 | stack.add(t);
32 | }
33 |
34 | public void clear() {
35 | stack.clear();
36 | }
37 |
38 | public Set get(int index) {
39 | return stack.get(stack.size() - index - 1);
40 | }
41 |
42 | public void set(int index, Set t) {
43 | stack.set(stack.size() - index - 1, t);
44 | }
45 |
46 | public void set(int index, T t) {
47 | Set set = new HashSet<>();
48 | set.add(t);
49 | stack.set(stack.size() - index - 1, set);
50 | }
51 |
52 | public void add(Set t) {
53 | this.stack.add(t);
54 | }
55 |
56 | public int size() {
57 | return this.stack.size();
58 | }
59 |
60 | public void remove(int index) {
61 | this.stack.remove(index);
62 | }
63 |
64 | public List> getList() {
65 | return this.stack;
66 | }
67 | }
68 |
--------------------------------------------------------------------------------
/acaf-core/src/main/java/com/er1cccc/acaf/core/audit/auditcore/SpringAnnoAdapter.java:
--------------------------------------------------------------------------------
1 | package com.er1cccc.acaf.core.audit.auditcore;
2 |
3 | import com.er1cccc.acaf.core.entity.SpringParam;
4 | import org.objectweb.asm.AnnotationVisitor;
5 |
6 | import java.util.List;
7 |
8 | public class SpringAnnoAdapter extends AnnotationVisitor {
9 | private final List params;
10 | private final int index;
11 |
12 | public SpringAnnoAdapter(int api, AnnotationVisitor annotationVisitor,
13 | List params, int parameter) {
14 | super(api, annotationVisitor);
15 | this.index = parameter;
16 | this.params = params;
17 | }
18 |
19 | @Override
20 | public void visit(String name, Object value) {
21 | if (name.equals("name")) {
22 | SpringParam param = this.params.get(this.index);
23 | param.setReqName(value.toString());
24 | param.setParamIndex(this.index);
25 | this.params.set(this.index,param);
26 | }
27 | super.visit(name, value);
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/acaf-core/src/main/java/com/er1cccc/acaf/core/audit/auditcore/SpringClassVisitor.java:
--------------------------------------------------------------------------------
1 | package com.er1cccc.acaf.core.audit.auditcore;
2 |
3 | import com.er1cccc.acaf.core.entity.ClassReference;
4 | import com.er1cccc.acaf.core.entity.MethodReference;
5 | import com.er1cccc.acaf.core.entity.SpringController;
6 | import org.objectweb.asm.ClassVisitor;
7 | import org.objectweb.asm.MethodVisitor;
8 | import org.objectweb.asm.Opcodes;
9 |
10 | import java.util.List;
11 | import java.util.Map;
12 | import java.util.Set;
13 |
14 | public class SpringClassVisitor extends ClassVisitor {
15 | private final Map classMap;
16 | private final Map methodMap;
17 | private final List controllers;
18 | private boolean isSpring;
19 | private SpringController currentController;
20 | private final String packageName;
21 | private String name;
22 |
23 | public SpringClassVisitor(String packageName, List controllers,
24 | Map classMap,
25 | Map methodMap) {
26 | super(Opcodes.ASM6);
27 | this.methodMap = methodMap;
28 | this.controllers = controllers;
29 | this.packageName = packageName;
30 | this.classMap = classMap;
31 | }
32 |
33 | @Override
34 | public void visit(int version, int access, String name, String signature,
35 | String superName, String[] interfaces) {
36 | this.name = name;
37 | if (name.startsWith(this.packageName)) {
38 | Set annotations = classMap.get(new ClassReference.Handle(name)).getAnnotations();
39 | if (annotations.contains(SpringConstant.ControllerAnno) ||
40 | annotations.contains(SpringConstant.RestControllerAnno)) {
41 | this.isSpring = true;
42 | currentController = new SpringController();
43 | currentController.setClassReference(classMap.get(new ClassReference.Handle(name)));
44 | currentController.setClassName(new ClassReference.Handle(name));
45 | currentController.setRest(!annotations.contains(SpringConstant.ControllerAnno));
46 | }
47 | } else {
48 | this.isSpring = false;
49 | }
50 | super.visit(version, access, name, signature, superName, interfaces);
51 | }
52 |
53 | @Override
54 | public MethodVisitor visitMethod(int access, String name, String descriptor,
55 | String signature, String[] exceptions) {
56 | MethodVisitor mv = super.visitMethod(access, name, descriptor, signature, exceptions);
57 | if (this.isSpring) {
58 | if (this.name.equals("") || this.name.equals("")) {
59 | return mv;
60 | }
61 | return new SpringMethodAdapter(name, descriptor, this.name, Opcodes.ASM6, mv,
62 | currentController, this.methodMap);
63 | } else {
64 | return mv;
65 | }
66 | }
67 |
68 | @Override
69 | public void visitEnd() {
70 | if (isSpring) {
71 | controllers.add(currentController);
72 | }
73 | super.visitEnd();
74 | }
75 | }
76 |
--------------------------------------------------------------------------------
/acaf-core/src/main/java/com/er1cccc/acaf/core/audit/auditcore/SpringConstant.java:
--------------------------------------------------------------------------------
1 | package com.er1cccc.acaf.core.audit.auditcore;
2 |
3 | public interface SpringConstant {
4 | String ControllerAnno = "Lorg/springframework/stereotype/Controller;";
5 | String RestControllerAnno = "Lorg/springframework/web/bind/annotation/RestController;";
6 | String RequestMappingAnno = "Lorg/springframework/web/bind/annotation/RequestMapping;";
7 | String ResponseBodyAnno = "Lorg/springframework/web/bind/annotation/ResponseBody;";
8 | String RequestParamAnno = "Lorg/springframework/web/bind/annotation/RequestParam;";
9 | }
10 |
--------------------------------------------------------------------------------
/acaf-core/src/main/java/com/er1cccc/acaf/core/audit/auditcore/SpringMethodAdapter.java:
--------------------------------------------------------------------------------
1 | package com.er1cccc.acaf.core.audit.auditcore;
2 |
3 | import com.er1cccc.acaf.core.entity.*;
4 | import org.objectweb.asm.AnnotationVisitor;
5 | import org.objectweb.asm.MethodVisitor;
6 | import org.objectweb.asm.Opcodes;
7 | import org.objectweb.asm.Type;
8 |
9 | import java.util.ArrayList;
10 | import java.util.List;
11 | import java.util.Map;
12 |
13 |
14 | public class SpringMethodAdapter extends MethodVisitor {
15 | private final Map methodMap;
16 | private final List requestParam = new ArrayList<>();
17 | private SpringMapping currentMapping;
18 | private final SpringController controller;
19 | private final String name;
20 | private final String owner;
21 | private final String desc;
22 |
23 | private SpringPathAnnoAdapter pathAnnoAdapter;
24 |
25 | public SpringMethodAdapter(String name, String descriptor, String owner,
26 | int api, MethodVisitor methodVisitor,
27 | SpringController currentController,
28 | Map methodMap) {
29 | super(api, methodVisitor);
30 | this.owner = owner;
31 | this.desc = descriptor;
32 | this.name = name;
33 | this.methodMap = methodMap;
34 | this.controller = currentController;
35 | }
36 |
37 | @Override
38 | public AnnotationVisitor visitAnnotation(String descriptor, boolean visible) {
39 | AnnotationVisitor av = super.visitAnnotation(descriptor, visible);
40 | if (descriptor.equals(SpringConstant.RequestMappingAnno)) {
41 | currentMapping = new SpringMapping();
42 | currentMapping.setMethodName(new MethodReference.Handle(
43 | new ClassReference.Handle(this.owner), this.name, this.desc));
44 | currentMapping.setController(controller);
45 | currentMapping.setMethodReference(methodMap.get(currentMapping.getMethodName()));
46 | currentMapping.setParamMap(this.requestParam);
47 | pathAnnoAdapter = new SpringPathAnnoAdapter(Opcodes.ASM6, av);
48 | av = pathAnnoAdapter;
49 | }
50 | if (descriptor.equals(SpringConstant.ResponseBodyAnno)) {
51 | currentMapping.setRest(true);
52 | }
53 | return av;
54 | }
55 |
56 | @Override
57 | public void visitCode() {
58 | if (this.currentMapping != null) {
59 | if (pathAnnoAdapter.getResults().size() > 0) {
60 | currentMapping.setPath(pathAnnoAdapter.getResults().get(0));
61 | }
62 | }
63 | Type[] argTypes = Type.getArgumentTypes(this.desc);
64 | for (int i = 0; i < argTypes.length; i++) {
65 | this.requestParam.get(i).setParamType(argTypes[i].getClassName());
66 | }
67 | super.visitCode();
68 | }
69 |
70 | @Override
71 | public AnnotationVisitor visitParameterAnnotation(int parameter, String descriptor, boolean visible) {
72 | AnnotationVisitor av = super.visitParameterAnnotation(parameter, descriptor, visible);
73 | if (descriptor.equals(SpringConstant.RequestParamAnno)) {
74 | return new SpringAnnoAdapter(Opcodes.ASM6, av, requestParam, parameter);//修正请求参数的key
75 | }
76 | return av;
77 | }
78 |
79 |
80 | @Override
81 | public void visitParameter(String name, int access) {
82 | SpringParam param = new SpringParam();
83 | param.setParamName(name);
84 | this.requestParam.add(param);
85 | super.visitParameter(name, access);
86 | }
87 |
88 |
89 | @Override
90 | public void visitEnd() {
91 | if (currentMapping != null) {
92 | controller.addMapping(currentMapping);
93 | }
94 | super.visitEnd();
95 | }
96 | }
97 |
--------------------------------------------------------------------------------
/acaf-core/src/main/java/com/er1cccc/acaf/core/audit/auditcore/SpringPathAnnoAdapter.java:
--------------------------------------------------------------------------------
1 | package com.er1cccc.acaf.core.audit.auditcore;
2 |
3 | import org.objectweb.asm.AnnotationVisitor;
4 | import org.objectweb.asm.Opcodes;
5 |
6 | import java.util.ArrayList;
7 | import java.util.List;
8 |
9 | public class SpringPathAnnoAdapter extends AnnotationVisitor {
10 | private final List results = new ArrayList<>();
11 |
12 | public SpringPathAnnoAdapter(int api, AnnotationVisitor annotationVisitor) {
13 | super(api, annotationVisitor);
14 | }
15 |
16 | public List getResults() {
17 | return results;
18 | }
19 |
20 | @Override
21 | public AnnotationVisitor visitArray(String name) {
22 | AnnotationVisitor av = super.visitArray(name);
23 | return new ArrayVisitor(Opcodes.ASM6, av,results);
24 | }
25 |
26 | static class ArrayVisitor extends AnnotationVisitor {
27 | private final List results;
28 |
29 | public ArrayVisitor(int api, AnnotationVisitor annotationVisitor, List results) {
30 | super(api, annotationVisitor);
31 | this.results = results;
32 | }
33 |
34 | @Override
35 | public void visit(String name, Object value) {
36 | if (!value.toString().trim().equals("")) {
37 | results.add(value.toString());
38 | }
39 | super.visit(name, value);
40 | }
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/acaf-core/src/main/java/com/er1cccc/acaf/core/audit/auditcore/VulnClassVisitor.java:
--------------------------------------------------------------------------------
1 | package com.er1cccc.acaf.core.audit.auditcore;
2 |
3 | import com.er1cccc.acaf.core.entity.MethodReference;
4 | import com.er1cccc.acaf.core.resolver.Resolver;
5 | import org.objectweb.asm.ClassVisitor;
6 | import org.objectweb.asm.MethodVisitor;
7 | import org.objectweb.asm.Opcodes;
8 | import org.objectweb.asm.commons.JSRInlinerAdapter;
9 | import java.util.ArrayList;
10 | import java.util.List;
11 | import java.util.Map;
12 | import java.util.Set;
13 |
14 | public class VulnClassVisitor extends ClassVisitor {
15 | private final InheritanceMap inheritanceMap;
16 | private final Map> dataFlow;
17 |
18 | private String name;
19 | private String signature;
20 | private String superName;
21 | private String[] interfaces;
22 | Resolver vulnResolver;
23 |
24 | private MethodReference.Handle methodHandle;
25 | private int methodArgIndex;
26 | private List pass;
27 |
28 | public VulnClassVisitor(MethodReference.Handle targetMethod,
29 | int targetIndex, InheritanceMap inheritanceMap,
30 | Map> dataFlow,
31 | Resolver vulnResolver) {
32 | super(Opcodes.ASM6);
33 | this.inheritanceMap = inheritanceMap;
34 | this.dataFlow = dataFlow;
35 | this.methodHandle = targetMethod;
36 | this.methodArgIndex = targetIndex;
37 | this.pass = new ArrayList<>();
38 | this.vulnResolver=vulnResolver;
39 | }
40 |
41 |
42 | @Override
43 | public void visit(int version, int access, String name, String signature,
44 | String superName, String[] interfaces) {
45 | super.visit(version, access, name, signature, superName, interfaces);
46 | this.name = name;
47 | this.signature = signature;
48 | this.superName = superName;
49 | this.interfaces = interfaces;
50 | }
51 |
52 | @Override
53 | public MethodVisitor visitMethod(int access, String name, String descriptor,
54 | String signature, String[] exceptions) {
55 | MethodVisitor mv = super.visitMethod(access, name, descriptor, signature, exceptions);
56 | if (name.equals(this.methodHandle.getName())) {
57 | VulnMethodAdapter vulnMethodAdapter = new VulnMethodAdapter(
58 | this.methodArgIndex, this.pass,
59 | inheritanceMap, dataFlow, Opcodes.ASM6, mv,
60 | this.name, access, name, descriptor, signature, exceptions,
61 | vulnResolver
62 | );
63 | return new JSRInlinerAdapter(vulnMethodAdapter,
64 | access, name, descriptor, signature, exceptions);
65 | }
66 | return mv;
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/acaf-core/src/main/java/com/er1cccc/acaf/core/audit/auditcore/VulnMethodAdapter.java:
--------------------------------------------------------------------------------
1 | package com.er1cccc.acaf.core.audit.auditcore;
2 |
3 | import com.er1cccc.acaf.config.PassthroughRegistry;
4 | import com.er1cccc.acaf.core.entity.MethodReference;
5 | import com.er1cccc.acaf.core.entity.impl.VisitMethodInsnInfoInstruction;
6 | import com.er1cccc.acaf.core.resolver.Resolver;
7 | import com.er1cccc.acaf.core.resolver.impl.CompositResolver;
8 | import org.objectweb.asm.MethodVisitor;
9 | import org.objectweb.asm.Opcodes;
10 | import org.objectweb.asm.Type;
11 | import org.objectweb.asm.TypeReference;
12 |
13 | import java.util.HashSet;
14 | import java.util.List;
15 | import java.util.Map;
16 | import java.util.Set;
17 |
18 | public class VulnMethodAdapter extends CoreMethodAdapter {
19 | private final int access;
20 | private final String desc;
21 | private final int methodArgIndex;
22 | private final List pass;
23 | private Resolver vulnResolver;
24 |
25 | public VulnMethodAdapter(int methodArgIndex, List pass, InheritanceMap inheritanceMap,
26 | Map> passthroughDataflow,
27 | int api, MethodVisitor mv, String owner, int access, String name,
28 | String desc, String signature, String[] exceptions, Resolver vulnResolver) {
29 | super(inheritanceMap, passthroughDataflow, api, mv, owner, access, name, desc, signature, exceptions);
30 | this.access = access;
31 | this.desc = desc;
32 | this.methodArgIndex = methodArgIndex;
33 | this.pass = pass;
34 | this.vulnResolver=vulnResolver;
35 | }
36 |
37 | @Override
38 | public void visitCode() {
39 | super.visitCode();
40 | int localIndex = 0;
41 | int argIndex = 0;
42 | if ((this.access & Opcodes.ACC_STATIC) == 0) {
43 | localIndex += 1;
44 | argIndex += 1;
45 | }
46 | for (Type argType : Type.getArgumentTypes(desc)) {
47 | if (argIndex == this.methodArgIndex) {
48 | localVariables.set(localIndex, true);
49 | }
50 | localIndex += argType.getSize();
51 | argIndex += 1;
52 | }
53 | }
54 |
55 | @Override
56 | public void visitMethodInsn(int opcode, String owner, String name, String desc, boolean itf) {
57 | Set controllableArgIndex = getControllableArgIndex(desc);
58 | boolean resolve = vulnResolver.resolve(new VisitMethodInsnInfoInstruction(opcode, owner, name, desc, itf, controllableArgIndex));
59 | super.visitMethodInsn(opcode, owner, name, desc, itf);
60 | }
61 |
62 | private Set getControllableArgIndex(String descriptor) {
63 | Type[] argTypes = Type.getArgumentTypes(descriptor);
64 | int stackIndex = 0;
65 | Set controllableArgIndexList=new HashSet<>();
66 | for (int i = 0; i < argTypes.length; i++) {
67 | int argIndex = argTypes.length - 1 - i;
68 | Type type = argTypes[argIndex];
69 | Set param = operandStack.get(stackIndex);
70 | if (param.size() > 0 && param.contains(true)) {
71 | controllableArgIndexList.add(argIndex);
72 | }
73 | stackIndex += type.getSize();
74 | }
75 | return controllableArgIndexList;
76 | }
77 |
78 | // @Override
79 | // public void visitFieldInsn(int opcode, String owner, String name, String desc){
80 | // if(opcode==Opcodes.GETFIELD){
81 | // Set obj = operandStack.get(0);
82 | // super.visitFieldInsn(opcode,owner,name,desc);
83 | // //如果对象可控,那么认为对象的字段也是可控的
84 | // if(obj.contains(true))
85 | // operandStack.get(0).add(true);
86 | // }else{
87 | // super.visitFieldInsn(opcode,owner,name,desc);
88 | // }
89 | // }
90 |
91 | }
92 |
--------------------------------------------------------------------------------
/acaf-core/src/main/java/com/er1cccc/acaf/core/audit/discovery/CallGraphDiscovery.java:
--------------------------------------------------------------------------------
1 | package com.er1cccc.acaf.core.audit.discovery;
2 |
3 | import com.er1cccc.acaf.core.audit.auditcore.CallGraph;
4 | import com.er1cccc.acaf.core.audit.auditcore.CallGraphClassVisitor;
5 | import com.er1cccc.acaf.core.audit.auditcore.InheritanceMap;
6 | import com.er1cccc.acaf.core.entity.ClassFile;
7 | import com.er1cccc.acaf.core.entity.ClassReference;
8 | import com.er1cccc.acaf.core.entity.MethodReference;
9 | import com.er1cccc.acaf.data.DataLoader;
10 | import org.apache.log4j.Logger;
11 | import org.objectweb.asm.ClassReader;
12 |
13 | import java.io.File;
14 | import java.io.IOException;
15 | import java.io.InputStream;
16 | import java.nio.file.Path;
17 | import java.nio.file.Paths;
18 | import java.util.*;
19 |
20 | public class CallGraphDiscovery {
21 | private static final Logger logger = Logger.getLogger(CallGraphDiscovery.class);
22 | private final Set discoveredCalls = new HashSet<>();
23 |
24 | public void discover(List classFileList,Path saveDataDirPath) throws IOException{
25 | logger.info("build call graph");
26 | Map classMap = DataLoader.loadClasses(saveDataDirPath);
27 | InheritanceMap inheritanceMap = InheritanceMap.load(saveDataDirPath);
28 | Map> passthroughDataflow = PassthroughDiscovery.load(saveDataDirPath);
29 |
30 | for (ClassFile classFile:classFileList) {
31 | try (InputStream in = classFile.getInputStream()) {
32 | ClassReader cr = new ClassReader(in);
33 | try {
34 | cr.accept(new CallGraphClassVisitor(classMap, inheritanceMap, passthroughDataflow,discoveredCalls),
35 | ClassReader.EXPAND_FRAMES);
36 | } catch (Exception e) {
37 | logger.error("Error analyzing: " + classFile.getClassName(), e);
38 | }
39 | }
40 | }
41 |
42 | }
43 |
44 | public void save(Path dirPath) throws IOException {
45 | DataLoader.saveData(new File(dirPath.toFile(),"callgraph.dat").toPath(), new CallGraph.Factory(), discoveredCalls);
46 | }
47 |
48 | public static List load(Path dirPath) throws IOException {
49 | return DataLoader.loadData(new File(dirPath.toFile(),"callgraph.dat").toPath(), new CallGraph.Factory());
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/acaf-core/src/main/java/com/er1cccc/acaf/core/audit/discovery/DrawService.java:
--------------------------------------------------------------------------------
1 | package com.er1cccc.acaf.core.audit.discovery;
2 |
3 | import com.er1cccc.acaf.core.audit.auditcore.CallGraph;
4 | import com.er1cccc.acaf.core.entity.ClassReference;
5 | import com.er1cccc.acaf.core.entity.MethodReference;
6 | import com.er1cccc.acaf.util.DrawUtil;
7 |
8 | import java.util.HashSet;
9 | import java.util.Map;
10 | import java.util.Set;
11 |
12 | public class DrawService {
13 | public static void start(Set discoveredCalls, String finalPackageName,
14 | Map classMap,
15 | Map> methodImplMap) {
16 | Set targetCallGraphs = new HashSet<>();
17 | for (CallGraph callGraph : discoveredCalls) {
18 | ClassReference callerClass = classMap.get(callGraph.getCallerMethod().getClassReference());
19 | ClassReference targetClass = classMap.get(callGraph.getTargetMethod().getClassReference());
20 | if (targetClass == null) {
21 | continue;
22 | }
23 | if (targetClass.getName().equals("java/lang/Object") &&
24 | callGraph.getTargetMethod().getName().equals("") &&
25 | callGraph.getTargetMethod().getDesc().equals("()V")) {
26 | continue;
27 | }
28 | if (callerClass.getName().startsWith(finalPackageName)) {
29 | targetCallGraphs.add(callGraph);
30 | }
31 | }
32 | DrawUtil.drawCallGraph(targetCallGraphs);
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/acaf-core/src/main/java/com/er1cccc/acaf/core/audit/discovery/MethodDiscovery.java:
--------------------------------------------------------------------------------
1 | package com.er1cccc.acaf.core.audit.discovery;
2 |
3 | import com.er1cccc.acaf.core.audit.auditcore.DiscoveryClassVisitor;
4 | import com.er1cccc.acaf.core.audit.auditcore.InheritanceUtil;
5 | import com.er1cccc.acaf.core.entity.ClassFile;
6 | import com.er1cccc.acaf.core.entity.ClassReference;
7 | import com.er1cccc.acaf.core.entity.MethodReference;
8 | import com.er1cccc.acaf.data.DataLoader;
9 | import org.apache.log4j.Logger;
10 | import org.objectweb.asm.ClassReader;
11 |
12 | import java.io.File;
13 | import java.io.IOException;
14 | import java.io.InputStream;
15 | import java.nio.file.Path;
16 | import java.nio.file.Paths;
17 | import java.util.ArrayList;
18 | import java.util.HashMap;
19 | import java.util.List;
20 | import java.util.Map;
21 |
22 | public class MethodDiscovery {
23 | private static final Logger logger = Logger.getLogger(MethodDiscovery.class);
24 | private final List discoveredClasses = new ArrayList<>();
25 | private final List discoveredMethods = new ArrayList<>();
26 |
27 | public void discover(List classFileList) {
28 | logger.info("discover all classes");
29 | for (ClassFile file : classFileList) {
30 | try {
31 | DiscoveryClassVisitor dcv = new DiscoveryClassVisitor(discoveredClasses, discoveredMethods,file);
32 | InputStream ins = file.getInputStream();
33 | ClassReader cr = new ClassReader(ins);
34 | ins.close();
35 | cr.accept(dcv, ClassReader.EXPAND_FRAMES);
36 | } catch (IOException e) {
37 | e.printStackTrace();
38 | }
39 | }
40 | }
41 |
42 | public void save(Path dirPath) throws IOException {
43 | DataLoader.saveData(new File(dirPath.toFile(),"classes.dat").toPath(), new ClassReference.Factory(), discoveredClasses);
44 | DataLoader.saveData(new File(dirPath.toFile(),"methods.dat").toPath(), new MethodReference.Factory(), discoveredMethods);
45 |
46 | Map classMap = new HashMap<>();
47 | for (ClassReference clazz : discoveredClasses) {
48 | classMap.put(clazz.getHandle(), clazz);
49 | }
50 | InheritanceUtil.derive(classMap).save(dirPath);
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/acaf-core/src/main/java/com/er1cccc/acaf/core/audit/discovery/PassthroughDiscovery.java:
--------------------------------------------------------------------------------
1 | package com.er1cccc.acaf.core.audit.discovery;
2 |
3 | import com.er1cccc.acaf.core.audit.auditcore.*;
4 | import com.er1cccc.acaf.core.entity.ClassFile;
5 | import com.er1cccc.acaf.core.entity.ClassReference;
6 | import com.er1cccc.acaf.core.entity.MethodReference;
7 | import com.er1cccc.acaf.data.DataFactory;
8 | import com.er1cccc.acaf.data.DataLoader;
9 | import org.apache.log4j.Logger;
10 | import org.objectweb.asm.ClassReader;
11 | import org.objectweb.asm.Opcodes;
12 |
13 | import java.io.File;
14 | import java.io.IOException;
15 | import java.io.InputStream;
16 | import java.nio.file.Path;
17 | import java.nio.file.Paths;
18 | import java.util.*;
19 |
20 | public class PassthroughDiscovery {
21 | private static final Logger logger = Logger.getLogger(PassthroughDiscovery.class);
22 | private final Map> methodCalls = new HashMap<>();
23 | private Map> passthroughDataflow;
24 |
25 | public void discover(List classFileList,Path saveDataDirPath) throws IOException{
26 | logger.info("get data flow");
27 |
28 | Map methodMap = DataLoader.loadMethods(saveDataDirPath);
29 | Map classMap = DataLoader.loadClasses(saveDataDirPath);
30 | InheritanceMap inheritanceMap = InheritanceMap.load(saveDataDirPath);
31 |
32 | Map classFileByName = discoverMethodCalls(classFileList);
33 |
34 | List sortedMethods = topologicallySortMethodCalls();
35 | passthroughDataflow = calculatePassthroughDataflow(classFileByName, classMap, inheritanceMap, sortedMethods);
36 | }
37 |
38 | private Map> calculatePassthroughDataflow(Map classFileByName, Map classMap, InheritanceMap inheritanceMap, List sortedMethods) {
39 | final Map> passthroughDataflow = new HashMap<>();
40 |
41 | for (MethodReference.Handle method : sortedMethods) {
42 | if (method.getName().equals("")) {
43 | continue;
44 | }
45 | ClassFile file = classFileByName.get(method.getClassReference().getName());
46 | try {
47 | InputStream ins = file.getInputStream();
48 | ClassReader cr = new ClassReader(ins);
49 | ins.close();
50 |
51 | DataFlowClassVisitor cv = new DataFlowClassVisitor(classMap, inheritanceMap, passthroughDataflow, method);
52 | cr.accept(cv, ClassReader.EXPAND_FRAMES);
53 | passthroughDataflow.put(method, cv.getReturnTaint());
54 | } catch (IOException e) {
55 | logger.error("Exception analyzing " + method.getClassReference().getName(), e);
56 | }
57 | }
58 | return passthroughDataflow;
59 | }
60 |
61 | private List topologicallySortMethodCalls() {
62 | logger.info("topological sort methods");
63 | Map> outgoingReferences = new HashMap<>();
64 | for (Map.Entry> entry : methodCalls.entrySet()) {
65 | MethodReference.Handle method = entry.getKey();
66 | outgoingReferences.put(method, new HashSet<>(entry.getValue()));
67 | }
68 | Set dfsStack = new HashSet<>();
69 | Set visitedNodes = new HashSet<>();
70 | List sortedMethods = new ArrayList<>(outgoingReferences.size());
71 | for (MethodReference.Handle root : outgoingReferences.keySet()) {
72 | dfsSort(outgoingReferences, sortedMethods, visitedNodes, dfsStack, root);
73 | }
74 | return sortedMethods;
75 | }
76 |
77 | public void dfsSort(Map> outgoingReferences,
78 | List sortedMethods, Set visitedNodes,
79 | Set stack, MethodReference.Handle node) {
80 | if (stack.contains(node)) {
81 | return;
82 | }
83 | if (visitedNodes.contains(node)) {
84 | return;
85 | }
86 | Set outgoingRefs = outgoingReferences.get(node);
87 | if (outgoingRefs == null) {
88 | return;
89 | }
90 | stack.add(node);
91 | for (MethodReference.Handle child : outgoingRefs) {
92 | dfsSort(outgoingReferences, sortedMethods, visitedNodes, stack, child);
93 | }
94 | stack.remove(node);
95 | visitedNodes.add(node);
96 | sortedMethods.add(node);
97 | }
98 |
99 | private Map discoverMethodCalls(final List classFileList) throws IOException {
100 | Map classFileByName = new HashMap<>();
101 | for (ClassFile file : classFileList) {
102 | try {
103 | MethodCallClassVisitor mcv = new MethodCallClassVisitor(methodCalls);
104 | InputStream ins = file.getInputStream();
105 | ClassReader cr = new ClassReader(ins);
106 | ins.close();
107 | cr.accept(mcv, ClassReader.EXPAND_FRAMES);
108 | classFileByName.put(mcv.getName(), file);
109 | } catch (IOException e) {
110 | e.printStackTrace();
111 | }
112 | }
113 | return classFileByName;
114 | }
115 |
116 | public void save(Path dirPath) throws IOException {
117 | if (passthroughDataflow == null) {
118 | throw new IllegalStateException("Save called before discover()");
119 | }
120 | DataLoader.saveData(new File(dirPath.toFile(),"passthrough.dat").toPath(), new PassThroughFactory(), passthroughDataflow.entrySet());
121 | }
122 |
123 | public static class PassThroughFactory implements DataFactory>> {
124 |
125 | @Override
126 | public Map.Entry> parse(String[] fields) {
127 | ClassReference.Handle clazz = new ClassReference.Handle(fields[0]);
128 | MethodReference.Handle method = new MethodReference.Handle(clazz, fields[1], fields[2]);
129 |
130 | Set passthroughArgs = new HashSet<>();
131 | for (String arg : fields[3].split(",")) {
132 | if (arg.length() > 0) {
133 | passthroughArgs.add(Integer.parseInt(arg));
134 | }
135 | }
136 | return new AbstractMap.SimpleEntry<>(method, passthroughArgs);
137 | }
138 |
139 | @Override
140 | public String[] serialize(Map.Entry> entry) {
141 | if (entry.getValue()==null||entry.getValue().size() == 0) {
142 | return null;
143 | }
144 |
145 | final String[] fields = new String[4];
146 | fields[0] = entry.getKey().getClassReference().getName();
147 | fields[1] = entry.getKey().getName();
148 | fields[2] = entry.getKey().getDesc();
149 |
150 | StringBuilder sb = new StringBuilder();
151 | for (Integer arg : entry.getValue()) {
152 | sb.append(Integer.toString(arg));
153 | sb.append(",");
154 | }
155 | fields[3] = sb.toString();
156 |
157 | return fields;
158 | }
159 | }
160 |
161 | public static Map> load(Path dirPath) throws IOException {
162 | Map> passthroughDataflow = new HashMap<>();
163 | for (Map.Entry> entry : DataLoader.loadData(new File(dirPath.toFile(),"passthrough.dat").toPath(), new PassThroughFactory())) {
164 | passthroughDataflow.put(entry.getKey(), entry.getValue());
165 | }
166 | return passthroughDataflow;
167 | }
168 |
169 | }
170 |
--------------------------------------------------------------------------------
/acaf-core/src/main/java/com/er1cccc/acaf/core/audit/discovery/SpringDiscovery.java:
--------------------------------------------------------------------------------
1 | package com.er1cccc.acaf.core.audit.discovery;
2 |
3 | import com.er1cccc.acaf.core.audit.auditcore.SpringClassVisitor;
4 | import com.er1cccc.acaf.core.entity.ClassFile;
5 | import com.er1cccc.acaf.core.entity.ClassReference;
6 | import com.er1cccc.acaf.core.entity.MethodReference;
7 | import com.er1cccc.acaf.core.entity.SpringController;
8 | import com.er1cccc.acaf.data.DataLoader;
9 | import org.apache.log4j.Logger;
10 | import org.objectweb.asm.ClassReader;
11 | import java.io.IOException;
12 | import java.io.InputStream;
13 | import java.nio.file.Path;
14 | import java.util.ArrayList;
15 | import java.util.List;
16 | import java.util.Map;
17 |
18 | public class SpringDiscovery {
19 | private static final Logger logger = Logger.getLogger(SpringDiscovery.class);
20 | private List controllers=new ArrayList<>();
21 |
22 | public void discover(List classFileList, String packageName, Path saveDataDirPath) {
23 | logger.info("discover spring classes");
24 | Map classMap = DataLoader.loadClasses(saveDataDirPath);
25 | Map methodMap = DataLoader.loadMethods(saveDataDirPath);
26 |
27 | for (ClassFile file : classFileList) {
28 | try {
29 | SpringClassVisitor mcv = new SpringClassVisitor(packageName,controllers,classMap,methodMap);
30 | InputStream ins = file.getInputStream();
31 | ClassReader cr = new ClassReader(ins);
32 | ins.close();
33 | cr.accept(mcv, ClassReader.EXPAND_FRAMES);
34 | } catch (IOException e) {
35 | e.printStackTrace();
36 | }
37 | }
38 | }
39 |
40 | public List getControllers() {
41 | return controllers;
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/acaf-core/src/main/java/com/er1cccc/acaf/core/audit/discovery/VulnDiscovery.java:
--------------------------------------------------------------------------------
1 | package com.er1cccc.acaf.core.audit.discovery;
2 |
3 | import com.er1cccc.acaf.config.*;
4 | import com.er1cccc.acaf.core.audit.auditcore.CallGraph;
5 | import com.er1cccc.acaf.core.audit.auditcore.InheritanceMap;
6 | import com.er1cccc.acaf.core.audit.auditcore.InheritanceUtil;
7 | import com.er1cccc.acaf.core.audit.auditcore.VulnClassVisitor;
8 | import com.er1cccc.acaf.core.entity.*;
9 | import com.er1cccc.acaf.core.resolver.Resolver;
10 | import com.er1cccc.acaf.core.resolver.impl.CompositResolver;
11 | import com.er1cccc.acaf.core.template.VulnTemplateSinkVisitor;
12 | import com.er1cccc.acaf.data.DataLoader;
13 | import org.apache.log4j.Logger;
14 | import org.objectweb.asm.ClassReader;
15 | import org.objectweb.asm.Type;
16 | import java.io.IOException;
17 | import java.io.InputStream;
18 | import java.nio.file.Path;
19 | import java.util.*;
20 |
21 | public class VulnDiscovery {
22 | private static final Logger logger = Logger.getLogger(VulnDiscovery.class);
23 |
24 | private Map classFileMap;
25 | private InheritanceMap localInheritanceMap;
26 | private Map> localDataFlow;
27 | private Map methodMap;
28 | private Map classMap ;
29 | private List discoveredCalls ;
30 | private SourceRegistry sourceRegistry;
31 | private SanitizeRegistry sanitizeRegistry;
32 | private SinkRegistry sinkRegistry;
33 | private Map> callGraphMap;
34 | private Path templateSaveDataDirPath;
35 | private Map resolverMap=new HashMap<>();
36 |
37 | public VulnDiscovery(List targetClassFileList,
38 | SourceRegistry sourceRegistry,
39 | SanitizeRegistry sanitizeRegistry,
40 | SinkRegistry sinkRegistry,
41 | Path targetSaveDataDirPath,
42 | Path templateSaveDataDirPath) throws IOException{
43 | this.sourceRegistry=sourceRegistry;
44 | this.sanitizeRegistry=sanitizeRegistry;
45 | this.sinkRegistry=sinkRegistry;
46 | this.templateSaveDataDirPath=templateSaveDataDirPath;
47 | localInheritanceMap = InheritanceMap.load(targetSaveDataDirPath);
48 | localDataFlow = PassthroughDiscovery.load(targetSaveDataDirPath);
49 | methodMap= DataLoader.loadMethods(targetSaveDataDirPath);
50 | classMap= DataLoader.loadClasses(targetSaveDataDirPath);
51 | discoveredCalls= CallGraphDiscovery.load(targetSaveDataDirPath);
52 | classFileMap=new HashMap<>();
53 | for (ClassFile classFile : targetClassFileList) {
54 | classFileMap.put(classFile.getClassName(),classFile);
55 | }
56 | }
57 |
58 | private CompositResolver getResolver(Sink sink) throws IOException {
59 | CompositResolver compositResolver = resolverMap.get(sink);
60 | if(compositResolver==null){
61 | ClassReader classReader = new ClassReader(sink.getClass().getName());
62 | compositResolver = new CompositResolver(sink);
63 | classReader.accept(new VulnTemplateSinkVisitor(compositResolver,templateSaveDataDirPath, sink),ClassReader.EXPAND_FRAMES);
64 | PassthroughRegistry passthroughRegistry = new PassthroughRegistry(this.localDataFlow);
65 | //TODO 这样的话上一个sink添加的Passthrough会传递给下一个sink,有没有影响?
66 | sink.addPassthrough(passthroughRegistry);
67 | resolverMap.put(sink,compositResolver);
68 | }else{
69 | //重复利用之前要先重置resolver的ind
70 | compositResolver.reset();
71 | }
72 | return compositResolver;
73 | }
74 |
75 |
76 | public void discover(List controllers) throws IOException {
77 | logger.info("finding vuln...");
78 | callGraphMap = prepareCallGraphMap(methodMap);
79 | doDiscover(controllers);
80 | }
81 |
82 | /**
83 | * 准备方法调用图。把抽象方法全部具体化
84 | * @param methodMap
85 | * @return
86 | * @throws IOException
87 | */
88 | private Map> prepareCallGraphMap(Map methodMap){
89 | Map> graphCallMap=new HashMap<>();
90 |
91 | Map> methodImplMap =
92 | InheritanceUtil.getAllMethodImplementations(localInheritanceMap, methodMap);
93 | List tempList = new ArrayList<>(discoveredCalls);
94 | for (int i = 0; i < discoveredCalls.size(); i++) {
95 | CallGraph edge = tempList.get(i);
96 | ClassReference.Handle handle = edge.getTargetMethod().getClassReference();
97 | ClassReference classReference = classMap.get(handle);
98 | if (classReference != null && classReference.isInterface()) {
99 | Set implSet = methodImplMap.get(edge.getTargetMethod());
100 | if (implSet == null || implSet.size() == 0) {
101 | continue;
102 | }
103 | for (MethodReference.Handle methodHandle : implSet) {
104 | String callerDesc = methodMap.get(methodHandle).getDesc();
105 | if (edge.getTargetMethod().getDesc().equals(callerDesc)) {
106 | tempList.add(new CallGraph(
107 | edge.getTargetMethod(),
108 | methodHandle,
109 | edge.getTargetArgIndex(),
110 | null,
111 | edge.getTargetArgIndex()
112 | ));
113 | }
114 | }
115 | }
116 | }
117 |
118 | discoveredCalls.clear();
119 | discoveredCalls.addAll(tempList);
120 | for (CallGraph graphCall : discoveredCalls) {
121 | MethodReference.Handle caller = graphCall.getCallerMethod();
122 | if (!graphCallMap.containsKey(caller)) {
123 | Set graphCalls = new HashSet<>();
124 | graphCalls.add(graphCall);
125 | graphCallMap.put(caller, graphCalls);
126 | } else {
127 | graphCallMap.get(caller).add(graphCall);
128 | }
129 | }
130 | return graphCallMap;
131 | }
132 |
133 | private void doDiscover(List controllers) throws IOException {
134 | for (SpringController controller : controllers) {
135 | for (SpringMapping mapping : controller.getMappings()) {
136 | MethodReference methodReference = mapping.getMethodReference();
137 | if (methodReference == null) {
138 | continue;
139 | }
140 | Type[] argTypes = Type.getArgumentTypes(methodReference.getDesc());
141 | Type[] extendedArgTypes = new Type[argTypes.length + 1];
142 | System.arraycopy(argTypes, 0, extendedArgTypes, 1, argTypes.length);
143 | argTypes = extendedArgTypes;
144 | boolean[] vulnerableIndex = new boolean[argTypes.length];
145 | for (int i = 1; i < argTypes.length; i++) {
146 | if (!isPrimitive(argTypes[i])) {
147 | vulnerableIndex[i] = true;
148 | }
149 | }
150 | Set calls = callGraphMap.get(methodReference.getHandle());
151 | if (calls == null || calls.size() == 0) {
152 | continue;
153 | }
154 | // mapping method中的call
155 | for (CallGraph callGraph : calls) {
156 | int callerIndex = callGraph.getCallerArgIndex();
157 | if (callerIndex == -1) {
158 | continue;
159 | }
160 | if (vulnerableIndex[callerIndex]) {
161 | // 防止循环
162 | for(Sink sink: sinkRegistry.getSinkList()){
163 | CompositResolver resolver = getResolver(sink);
164 |
165 | List visited = new ArrayList<>();
166 | LinkedList stack = new LinkedList<>();
167 | stack.push(callGraph.getCallerMethod());
168 | doTask(callGraph.getTargetMethod(), callGraph.getTargetArgIndex(), visited, stack, resolver);
169 | }
170 | }
171 | }
172 | }
173 | }
174 | }
175 |
176 | private boolean isPrimitive(Type argType) {
177 | int sort = argType.getSort();
178 | return sort==Type.BYTE||
179 | sort==Type.INT||
180 | sort==Type.SHORT||
181 | sort==Type.LONG||
182 | sort==Type.FLOAT||
183 | sort==Type.DOUBLE||
184 | sort==Type.BOOLEAN||
185 | sort==Type.CHAR;
186 | }
187 |
188 | private void doTask(MethodReference.Handle targetMethod, int targetIndex,
189 | List visited,
190 | Deque stack,
191 | CompositResolver vulnResolver) {
192 | if (visited.contains(targetMethod)) {
193 | return;
194 | } else {
195 | visited.add(targetMethod);
196 | }
197 | stack.push(targetMethod);
198 | ClassFile file = classFileMap.get(targetMethod.getClassReference().getName());
199 | try {
200 | InputStream ins = file.getInputStream();
201 | ClassReader cr = new ClassReader(ins);
202 | ins.close();
203 | VulnClassVisitor cv = new VulnClassVisitor(
204 | targetMethod, targetIndex, localInheritanceMap, localDataFlow, vulnResolver);
205 | cr.accept(cv, ClassReader.EXPAND_FRAMES);
206 | if(vulnResolver.resolve(null)){
207 | logger.info("detect vuln: " + vulnResolver.getSink().getClass().getName());
208 | printStackTrace(stack);
209 | return;
210 | }
211 |
212 | } catch (IOException e) {
213 | e.printStackTrace();
214 | return;
215 | }
216 | Set calls = callGraphMap.get(targetMethod);
217 | if (calls == null || calls.size() == 0) {
218 | return;
219 | }
220 | for (CallGraph callGraph : calls) {
221 | if (callGraph.getCallerArgIndex() == targetIndex && targetIndex != -1) {
222 | if (visited.contains(callGraph.getTargetMethod())) {
223 | return;
224 | }
225 | doTask(callGraph.getTargetMethod(), callGraph.getTargetArgIndex(),visited, stack, vulnResolver);
226 | stack.pop();
227 | }
228 | }
229 | }
230 |
231 | private void printStackTrace(Deque stack) {
232 | Deque copyStack = new LinkedList<>(stack);
233 | StringBuilder prefix=new StringBuilder("\t");
234 | for (MethodReference.Handle handle : stack) {
235 | logger.info(prefix+handle.getClassReference().getName()+"."+handle.getName());
236 | prefix.append("\t");
237 | }
238 | }
239 |
240 | public static void main(String[] args) throws Exception{
241 |
242 | }
243 | }
244 |
--------------------------------------------------------------------------------
/acaf-core/src/main/java/com/er1cccc/acaf/core/entity/ClassFile.java:
--------------------------------------------------------------------------------
1 | package com.er1cccc.acaf.core.entity;
2 |
3 |
4 | import com.er1cccc.acaf.util.IOUtil;
5 | import lombok.Data;
6 |
7 | import java.io.ByteArrayInputStream;
8 | import java.io.ByteArrayOutputStream;
9 | import java.io.IOException;
10 | import java.io.InputStream;
11 | import java.util.Objects;
12 |
13 | @Data
14 | public class ClassFile {
15 | private String className;
16 | private InputStream inputStream;
17 |
18 | public ClassFile(String className, InputStream inputStream) {
19 | this.className = className;
20 | this.inputStream = inputStream;
21 | }
22 |
23 | @Override
24 | public boolean equals(Object o) {
25 | if (this == o) {
26 | return true;
27 | }
28 | if (o == null || getClass() != o.getClass()) {
29 | return false;
30 | }
31 | ClassFile classFile = (ClassFile) o;
32 | return Objects.equals(className, classFile.className);
33 | }
34 |
35 | @Override
36 | public int hashCode() {
37 | return className != null ? className.hashCode() : 0;
38 | }
39 |
40 | public InputStream getInputStream() {
41 | ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
42 | IOUtil.copy(inputStream, outputStream);
43 | this.inputStream = new ByteArrayInputStream(outputStream.toByteArray());
44 | return new ByteArrayInputStream(outputStream.toByteArray());
45 | }
46 |
47 | public void close() {
48 | try {
49 | this.inputStream.close();
50 | } catch (IOException e) {
51 | e.printStackTrace();
52 | }
53 | }
54 | }
--------------------------------------------------------------------------------
/acaf-core/src/main/java/com/er1cccc/acaf/core/entity/ClassReference.java:
--------------------------------------------------------------------------------
1 | package com.er1cccc.acaf.core.entity;
2 |
3 | import com.er1cccc.acaf.data.DataFactory;
4 |
5 | import java.util.*;
6 |
7 | public class ClassReference {
8 | private final String name;
9 | private final String superClass;
10 | private final List interfaces;
11 | private final boolean isInterface;
12 | private final List members;
13 | private final Set annotations;
14 |
15 | public static class Member {
16 | private final String name;
17 | private final int modifiers;
18 | private final Handle type;
19 |
20 | public Member(String name, int modifiers, Handle type) {
21 | this.name = name;
22 | this.modifiers = modifiers;
23 | this.type = type;
24 | }
25 |
26 | public String getName() {
27 | return name;
28 | }
29 |
30 | public int getModifiers() {
31 | return modifiers;
32 | }
33 |
34 | public Handle getType() {
35 | return type;
36 | }
37 | }
38 |
39 | public ClassReference(String name, String superClass, List interfaces,
40 | boolean isInterface, List members, Set annotations) {
41 | this.name = name;
42 | this.superClass = superClass;
43 | this.interfaces = interfaces;
44 | this.isInterface = isInterface;
45 | this.members = members;
46 | this.annotations = annotations;
47 | }
48 |
49 | public String getName() {
50 | return name;
51 | }
52 |
53 | public String getSuperClass() {
54 | return superClass;
55 | }
56 |
57 | public List getInterfaces() {
58 | return interfaces;
59 | }
60 |
61 | public boolean isInterface() {
62 | return isInterface;
63 | }
64 |
65 | public List getMembers() {
66 | return members;
67 | }
68 |
69 | public Handle getHandle() {
70 | return new Handle(name);
71 | }
72 |
73 | public Set getAnnotations() {
74 | return annotations;
75 | }
76 |
77 | public static class Handle {
78 | private final String name;
79 |
80 | public Handle(String name) {
81 | this.name = name;
82 | }
83 |
84 | public String getName() {
85 | return name;
86 | }
87 |
88 | @Override
89 | public boolean equals(Object o) {
90 | if (this == o) return true;
91 | if (o == null || getClass() != o.getClass()) return false;
92 | Handle handle = (Handle) o;
93 | return Objects.equals(name, handle.name);
94 | }
95 |
96 | @Override
97 | public int hashCode() {
98 | return name != null ? name.hashCode() : 0;
99 | }
100 | }
101 |
102 | public static class Factory implements DataFactory {
103 |
104 | @Override
105 | public ClassReference parse(String[] fields) {
106 | String[] interfaces;
107 | if (fields[2].equals("")) {
108 | interfaces = new String[0];
109 | } else {
110 | interfaces = fields[2].split(",");
111 | }
112 |
113 | String[] memberEntries = fields[4].split("!");
114 | int size=memberEntries.length/3;
115 | List members = new ArrayList<>(size);
116 | for (int i = 0; i < size; i++) {
117 | members.add(new Member(memberEntries[3*i], Integer.parseInt(memberEntries[3*i+1]),
118 | new ClassReference.Handle(memberEntries[3*i+2])));
119 | }
120 |
121 | String[] annotationEntries = fields[5].split("!");
122 | Set annotations = new HashSet<>();
123 | for (int i = 0; i < annotationEntries.length; i++) {
124 | if(annotationEntries[i]!=null&&!annotationEntries[i].trim().equals(""))
125 | annotations.add(annotationEntries[i]);
126 | }
127 |
128 | return new ClassReference(
129 | fields[0],
130 | fields[1].equals("") ? null : fields[1],
131 | new ArrayList<>(Arrays.asList(interfaces)),
132 | Boolean.parseBoolean(fields[3]),
133 | members,
134 | annotations);
135 | }
136 |
137 | @Override
138 | public String[] serialize(ClassReference obj) {
139 | String interfaces;
140 | if (obj.interfaces.size() > 0) {
141 | StringBuilder interfacesSb = new StringBuilder();
142 | for (String iface : obj.interfaces) {
143 | interfacesSb.append(",").append(iface);
144 | }
145 | interfaces = interfacesSb.substring(1);
146 | } else {
147 | interfaces = "";
148 | }
149 |
150 | StringBuilder members = new StringBuilder();
151 | for (Member member : obj.members) {
152 | members.append("!").append(member.getName())
153 | .append("!").append(Integer.toString(member.getModifiers()))
154 | .append("!").append(member.getType().getName());
155 | }
156 |
157 | StringBuilder annotations = new StringBuilder();
158 | for (String annotation : obj.annotations) {
159 | annotations.append("!").append(annotation);
160 | }
161 |
162 | return new String[]{
163 | obj.name,
164 | obj.superClass,
165 | interfaces,
166 | Boolean.toString(obj.isInterface),
167 | members.length() == 0 ? null : members.substring(1),
168 | annotations.length()==0? null: annotations.substring(1)
169 | };
170 | }
171 | }
172 |
173 | }
174 |
--------------------------------------------------------------------------------
/acaf-core/src/main/java/com/er1cccc/acaf/core/entity/Command.java:
--------------------------------------------------------------------------------
1 | package com.er1cccc.acaf.core.entity;
2 |
3 | import com.beust.jcommander.Parameter;
4 |
5 | import java.util.List;
6 |
7 | public class Command {
8 | @Parameter(names = {"-h", "--help"}, description = "Help Info", help = true)
9 | public boolean help;
10 |
11 | @Parameter(names = {"-j", "--jar"}, description = "Scan Jar File")
12 | public List jars;
13 |
14 | @Parameter(names = {"-b", "--boot"}, description = "Scan SpringBoot File")
15 | public List boots;
16 |
17 | @Parameter(names = {"-t", "--template"}, description = "Scan SpringBoot File")
18 | public List templates;
19 |
20 | @Parameter(names = {"-p", "--pack"}, description = "SpringBoot Package Name")
21 | public String packageName;
22 | }
23 |
--------------------------------------------------------------------------------
/acaf-core/src/main/java/com/er1cccc/acaf/core/entity/Instruction.java:
--------------------------------------------------------------------------------
1 | package com.er1cccc.acaf.core.entity;
2 |
3 | public interface Instruction {
4 | }
5 |
--------------------------------------------------------------------------------
/acaf-core/src/main/java/com/er1cccc/acaf/core/entity/MethodReference.java:
--------------------------------------------------------------------------------
1 | package com.er1cccc.acaf.core.entity;
2 |
3 | import com.er1cccc.acaf.data.DataFactory;
4 |
5 | import java.util.Objects;
6 |
7 | public class MethodReference {
8 | private final ClassReference.Handle classReference;
9 | private final String name;
10 | private final String desc;
11 | private final boolean isStatic;
12 |
13 | public MethodReference(ClassReference.Handle classReference,
14 | String name, String desc, boolean isStatic) {
15 | this.classReference = classReference;
16 | this.name = name;
17 | this.desc = desc;
18 | this.isStatic = isStatic;
19 | }
20 |
21 | public ClassReference.Handle getClassReference() {
22 | return classReference;
23 | }
24 |
25 | public String getName() {
26 | return name;
27 | }
28 |
29 | public String getDesc() {
30 | return desc;
31 | }
32 |
33 | public boolean isStatic() {
34 | return isStatic;
35 | }
36 |
37 | public Handle getHandle() {
38 | return new Handle(classReference, name, desc);
39 | }
40 |
41 | public static class Handle {
42 | private final ClassReference.Handle classReference;
43 | private final String name;
44 | private final String desc;
45 |
46 | public Handle(ClassReference.Handle classReference, String name, String desc) {
47 | this.classReference = classReference;
48 | this.name = name;
49 | this.desc = desc;
50 | }
51 |
52 | public ClassReference.Handle getClassReference() {
53 | return classReference;
54 | }
55 |
56 | public String getName() {
57 | return name;
58 | }
59 |
60 | public String getDesc() {
61 | return desc;
62 | }
63 |
64 | @Override
65 | public boolean equals(Object o) {
66 | if (this == o) return true;
67 | if (o == null || getClass() != o.getClass()) return false;
68 | Handle handle = (Handle) o;
69 | if (!Objects.equals(classReference, handle.classReference))
70 | return false;
71 | if (!Objects.equals(name, handle.name))
72 | return false;
73 | return Objects.equals(desc, handle.desc);
74 | }
75 |
76 | @Override
77 | public int hashCode() {
78 | int result = classReference != null ? classReference.hashCode() : 0;
79 | result = 31 * result + (name != null ? name.hashCode() : 0);
80 | result = 31 * result + (desc != null ? desc.hashCode() : 0);
81 | return result;
82 | }
83 | }
84 |
85 | public static class Factory implements DataFactory {
86 |
87 | @Override
88 | public MethodReference parse(String[] fields) {
89 | return new MethodReference(
90 | new ClassReference.Handle(fields[0]),
91 | fields[1],
92 | fields[2],
93 | Boolean.parseBoolean(fields[3]));
94 | }
95 |
96 | @Override
97 | public String[] serialize(MethodReference obj) {
98 | return new String[] {
99 | obj.classReference.getName(),
100 | obj.name,
101 | obj.desc,
102 | Boolean.toString(obj.isStatic),
103 | };
104 | }
105 | }
106 |
107 | }
108 |
--------------------------------------------------------------------------------
/acaf-core/src/main/java/com/er1cccc/acaf/core/entity/SpringController.java:
--------------------------------------------------------------------------------
1 | package com.er1cccc.acaf.core.entity;
2 |
3 | import java.util.ArrayList;
4 | import java.util.List;
5 |
6 | public class SpringController {
7 | private boolean isRest;
8 | private ClassReference.Handle className;
9 | private ClassReference classReference;
10 | private final List mappings = new ArrayList<>();
11 |
12 | public boolean isRest() {
13 | return isRest;
14 | }
15 |
16 | public void setRest(boolean rest) {
17 | isRest = rest;
18 | }
19 |
20 | public ClassReference.Handle getClassName() {
21 | return className;
22 | }
23 |
24 | public void setClassName(ClassReference.Handle className) {
25 | this.className = className;
26 | }
27 |
28 | public ClassReference getClassReference() {
29 | return classReference;
30 | }
31 |
32 | public void setClassReference(ClassReference classReference) {
33 | this.classReference = classReference;
34 | }
35 |
36 | public List getMappings() {
37 | return mappings;
38 | }
39 |
40 | public void addMapping(SpringMapping mapping) {
41 | this.mappings.add(mapping);
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/acaf-core/src/main/java/com/er1cccc/acaf/core/entity/SpringMapping.java:
--------------------------------------------------------------------------------
1 | package com.er1cccc.acaf.core.entity;
2 |
3 | import java.util.ArrayList;
4 | import java.util.List;
5 |
6 | public class SpringMapping {
7 | private boolean isRest;
8 | private SpringController controller;
9 | private MethodReference.Handle methodName;
10 | private MethodReference methodReference;
11 | private String path;
12 | private List paramMap = new ArrayList<>();
13 |
14 | public List getParamMap() {
15 | return paramMap;
16 | }
17 |
18 | public void setParamMap(List paramMap) {
19 | this.paramMap = paramMap;
20 | }
21 |
22 | public boolean isRest() {
23 | return isRest;
24 | }
25 |
26 | public void setRest(boolean rest) {
27 | isRest = rest;
28 | }
29 |
30 | public SpringController getController() {
31 | return controller;
32 | }
33 |
34 | public void setController(SpringController controller) {
35 | this.controller = controller;
36 | }
37 |
38 | public MethodReference.Handle getMethodName() {
39 | return methodName;
40 | }
41 |
42 | public void setMethodName(MethodReference.Handle methodName) {
43 | this.methodName = methodName;
44 | }
45 |
46 | public MethodReference getMethodReference() {
47 | return methodReference;
48 | }
49 |
50 | public void setMethodReference(MethodReference methodReference) {
51 | this.methodReference = methodReference;
52 | }
53 |
54 | public String getPath() {
55 | return path;
56 | }
57 |
58 | public void setPath(String path) {
59 | this.path = path;
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/acaf-core/src/main/java/com/er1cccc/acaf/core/entity/SpringParam.java:
--------------------------------------------------------------------------------
1 | package com.er1cccc.acaf.core.entity;
2 |
3 | public class SpringParam {
4 | private int paramIndex;
5 | private String paramName;
6 | private String paramType;
7 | private String reqName;
8 |
9 | public int getParamIndex() {
10 | return paramIndex;
11 | }
12 |
13 | public void setParamIndex(int paramIndex) {
14 | this.paramIndex = paramIndex;
15 | }
16 |
17 | public String getParamName() {
18 | return paramName;
19 | }
20 |
21 | public void setParamName(String paramName) {
22 | this.paramName = paramName;
23 | }
24 |
25 | public String getParamType() {
26 | return paramType;
27 | }
28 |
29 | public void setParamType(String paramType) {
30 | this.paramType = paramType;
31 | }
32 |
33 | public String getReqName() {
34 | return reqName;
35 | }
36 |
37 | public void setReqName(String reqName) {
38 | this.reqName = reqName;
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/acaf-core/src/main/java/com/er1cccc/acaf/core/entity/impl/VisitMethodInsnInfoInstruction.java:
--------------------------------------------------------------------------------
1 | package com.er1cccc.acaf.core.entity.impl;
2 |
3 | import com.er1cccc.acaf.core.entity.Instruction;
4 | import lombok.AllArgsConstructor;
5 | import lombok.Data;
6 | import lombok.NoArgsConstructor;
7 |
8 | import java.util.Set;
9 |
10 | @Data
11 | @AllArgsConstructor
12 | @NoArgsConstructor
13 | public class VisitMethodInsnInfoInstruction implements Instruction {
14 | int opcode;
15 | String owner;
16 | String name;
17 | String descriptor;
18 | boolean isInterface;
19 | Set controllableArgIndex;
20 | }
21 |
--------------------------------------------------------------------------------
/acaf-core/src/main/java/com/er1cccc/acaf/core/resolver/Resolver.java:
--------------------------------------------------------------------------------
1 | package com.er1cccc.acaf.core.resolver;
2 |
3 |
4 | import com.er1cccc.acaf.core.entity.Instruction;
5 |
6 | public interface Resolver {
7 | boolean resolve(Instruction instruction);
8 | }
9 |
--------------------------------------------------------------------------------
/acaf-core/src/main/java/com/er1cccc/acaf/core/resolver/impl/CompositResolver.java:
--------------------------------------------------------------------------------
1 | package com.er1cccc.acaf.core.resolver.impl;
2 |
3 | import com.er1cccc.acaf.config.Sink;
4 | import com.er1cccc.acaf.core.entity.Instruction;
5 | import com.er1cccc.acaf.core.resolver.Resolver;
6 | import lombok.Data;
7 |
8 | import java.util.ArrayList;
9 | import java.util.List;
10 |
11 | @Data
12 | public class CompositResolver implements Resolver {
13 | List resolverList=new ArrayList<>();
14 | int ind=0;
15 | Sink sink;
16 |
17 | public CompositResolver(Sink sink) {
18 | this.sink = sink;
19 | }
20 |
21 | @Override
22 | public boolean resolve(Instruction instruction) {
23 | int size=resolverList.size();
24 |
25 | if(ind==size){
26 | return true;
27 | }
28 | if(instruction!=null){
29 | Resolver resolver = resolverList.get(ind);
30 | if(resolver.resolve(instruction)){
31 | ind++;
32 | return true;
33 | }
34 | }
35 | return false;
36 | }
37 |
38 | public void addResolver(Resolver resolver){
39 | resolverList.add(resolver);
40 | }
41 |
42 | public void reset(){
43 | ind=0;
44 | }
45 |
46 | }
47 |
--------------------------------------------------------------------------------
/acaf-core/src/main/java/com/er1cccc/acaf/core/resolver/impl/VisitMethodInsnInfoResolver.java:
--------------------------------------------------------------------------------
1 | package com.er1cccc.acaf.core.resolver.impl;
2 |
3 | import com.er1cccc.acaf.core.entity.Instruction;
4 | import com.er1cccc.acaf.core.entity.impl.VisitMethodInsnInfoInstruction;
5 | import com.er1cccc.acaf.core.resolver.Resolver;
6 | import com.google.common.collect.Sets;
7 | import lombok.AllArgsConstructor;
8 | import lombok.NoArgsConstructor;
9 |
10 | import java.util.Set;
11 |
12 | @NoArgsConstructor
13 | @AllArgsConstructor
14 | public class VisitMethodInsnInfoResolver implements Resolver {
15 | int opcode;
16 | String owner;
17 | String name;
18 | String descriptor;
19 | boolean isInterface;
20 | Set controllableArgIndex;
21 |
22 | @Override
23 | public boolean resolve(Instruction instruction) {
24 | VisitMethodInsnInfoInstruction inst= (VisitMethodInsnInfoInstruction) instruction;
25 | return owner.equals(inst.getOwner()) &&
26 | name.equals(inst.getName()) &&
27 | descriptor.equals(inst.getDescriptor())&&
28 | Sets.difference(controllableArgIndex, inst.getControllableArgIndex()).size()==0;
29 |
30 | }
31 |
32 | }
33 |
--------------------------------------------------------------------------------
/acaf-core/src/main/java/com/er1cccc/acaf/core/template/VulnTemplateSanitizeVisitor.java:
--------------------------------------------------------------------------------
1 | package com.er1cccc.acaf.core.template;
2 |
3 | public class VulnTemplateSanitizeVisitor {
4 | }
5 |
--------------------------------------------------------------------------------
/acaf-core/src/main/java/com/er1cccc/acaf/core/template/VulnTemplateSinkVisitor.java:
--------------------------------------------------------------------------------
1 | package com.er1cccc.acaf.core.template;
2 |
3 | import com.er1cccc.acaf.config.PassthroughRegistry;
4 | import com.er1cccc.acaf.config.Sink;
5 | import com.er1cccc.acaf.core.audit.auditcore.CoreMethodAdapter;
6 | import com.er1cccc.acaf.core.audit.auditcore.InheritanceMap;
7 | import com.er1cccc.acaf.core.audit.discovery.PassthroughDiscovery;
8 | import com.er1cccc.acaf.core.entity.MethodReference;
9 | import com.er1cccc.acaf.core.resolver.impl.CompositResolver;
10 | import com.er1cccc.acaf.core.resolver.impl.VisitMethodInsnInfoResolver;
11 | import org.apache.log4j.Logger;
12 | import org.objectweb.asm.ClassVisitor;
13 | import org.objectweb.asm.MethodVisitor;
14 | import org.objectweb.asm.Opcodes;
15 | import org.objectweb.asm.Type;
16 | import org.objectweb.asm.commons.JSRInlinerAdapter;
17 | import java.io.IOException;
18 | import java.nio.file.Path;
19 | import java.util.*;
20 |
21 | public class VulnTemplateSinkVisitor extends ClassVisitor {
22 | private static final Logger logger = Logger.getLogger(VulnTemplateSinkVisitor.class);
23 | private CompositResolver resolver;
24 | private String name;
25 | private String signature;
26 | private String superName;
27 | private String[] interfaces;
28 | private InheritanceMap inheritanceMap;
29 | private Map> passthrough;
30 |
31 | public VulnTemplateSinkVisitor(CompositResolver resolver, Path templateSaveDataDirPath, Sink sink) {
32 | super(Opcodes.ASM6);
33 | this.resolver=resolver;
34 | try{
35 | inheritanceMap = InheritanceMap.load(templateSaveDataDirPath);
36 | passthrough = PassthroughDiscovery.load(templateSaveDataDirPath);
37 | PassthroughRegistry passthroughRegistry = new PassthroughRegistry(passthrough);
38 | sink.addPassthrough(passthroughRegistry);
39 | }catch (IOException e){
40 | logger.error("error when loading inheritanceMap or passthrough",e);
41 | }
42 | }
43 |
44 | @Override
45 | public void visit(int version, int access, String name, String signature,
46 | String superName, String[] interfaces) {
47 | super.visit(version, access, name, signature, superName, interfaces);
48 | this.name = name;
49 | this.signature = signature;
50 | this.superName = superName;
51 | this.interfaces = interfaces;
52 | }
53 |
54 | @Override
55 | public MethodVisitor visitMethod(int access, String name, String descriptor,
56 | String signature, String[] exceptions) {
57 | MethodVisitor mv = super.visitMethod(access, name, descriptor, signature, exceptions);
58 | if (name.equals("sinkMethod")) {
59 | VulnTemplateSinkMethodVisitor vulnTemplateSinkMethodVisitor = new VulnTemplateSinkMethodVisitor(inheritanceMap,passthrough,Opcodes.ASM6,mv,this.name,access,name,descriptor,signature,exceptions,this.resolver);
60 | return new JSRInlinerAdapter(vulnTemplateSinkMethodVisitor,
61 | access, name, descriptor, signature, exceptions);
62 | }
63 | return mv;
64 | }
65 |
66 | private static class VulnTemplateSinkMethodVisitor extends CoreMethodAdapter {
67 | private CompositResolver resolver;
68 | private final int access;
69 | private final String desc;
70 |
71 | public VulnTemplateSinkMethodVisitor(InheritanceMap inheritanceMap,
72 | Map> passthroughDataflow,
73 | int api, MethodVisitor mv, String owner, int access, String name,
74 | String desc, String signature, String[] exceptions, CompositResolver resolver) {
75 | super(inheritanceMap, passthroughDataflow, api, mv, owner, access, name, desc, signature, exceptions);
76 | this.access = access;
77 | this.desc = desc;
78 | this.resolver=resolver;
79 |
80 | }
81 |
82 |
83 | @Override
84 | public void visitMethodInsn(int opcode, String owner, String name, String descriptor, boolean isInterface) {
85 | if(isGetParamMethod(owner,name,descriptor,isInterface)) {
86 | super.visitMethodInsn(opcode, owner, name, descriptor, isInterface);
87 | operandStack.get(0).add(true);
88 | }else{
89 | Set