From ef5b167805d1c750e5e6daeeae79d3e370752212 Mon Sep 17 00:00:00 2001 From: yxxx Date: Fri, 6 May 2022 10:56:01 +0800 Subject: [PATCH 01/16] remove type parameterisation --- example/one-callsite-sensitive-pt-example-1.dl | 4 ++-- example/one-object-sensitive-pt-example-1.dl | 4 ++-- example/one-type-sensitive-pt-example-1.dl | 4 ++-- logic/one-callsite-sensitive-pt.dl | 2 +- logic/one-object-sensitive-pt.dl | 2 +- logic/one-type-sensitive-pt.dl | 2 +- 6 files changed, 9 insertions(+), 9 deletions(-) diff --git a/example/one-callsite-sensitive-pt-example-1.dl b/example/one-callsite-sensitive-pt-example-1.dl index 0a07ead..d640850 100644 --- a/example/one-callsite-sensitive-pt-example-1.dl +++ b/example/one-callsite-sensitive-pt-example-1.dl @@ -1,10 +1,10 @@ #define MAXSTEP 8 #include "../logic/one-callsite-sensitive-pt.dl" -.init callsitecsDemo1 = OneCallsiteSensitivePT +.init callsitecsDemo1 = OneCallsiteSensitivePT callsitecsDemo1.Reachable("", "initCtx", 0). .output callsitecsDemo1.VarPointsTo -.init callsitecsDemo2 = OneCallsiteSensitivePT +.init callsitecsDemo2 = OneCallsiteSensitivePT callsitecsDemo2.Reachable("", "initCtx", 0). .output callsitecsDemo2.VarPointsTo \ No newline at end of file diff --git a/example/one-object-sensitive-pt-example-1.dl b/example/one-object-sensitive-pt-example-1.dl index becfa38..69f37d1 100644 --- a/example/one-object-sensitive-pt-example-1.dl +++ b/example/one-object-sensitive-pt-example-1.dl @@ -1,10 +1,10 @@ #define MAXSTEP 8 #include "../logic/one-object-sensitive-pt.dl" -.init objectDemo1 = OneObjectSensitivePT +.init objectDemo1 = OneObjectSensitivePT objectDemo1.Reachable("", "initCtx", 0). .output objectDemo1.VarPointsTo -.init objectDemo2 = OneObjectSensitivePT +.init objectDemo2 = OneObjectSensitivePT objectDemo2.Reachable("", "initCtx", 0). .output objectDemo2.VarPointsTo \ No newline at end of file diff --git a/example/one-type-sensitive-pt-example-1.dl b/example/one-type-sensitive-pt-example-1.dl index f24d9b2..741891e 100644 --- a/example/one-type-sensitive-pt-example-1.dl +++ b/example/one-type-sensitive-pt-example-1.dl @@ -1,10 +1,10 @@ #define MAXSTEP 8 #include "../logic/one-type-sensitive-pt.dl" -.init typeDemo1 = OneTypeSensitivePT +.init typeDemo1 = OneTypeSensitivePT typeDemo1.Reachable("", "initCtx", 0). .output typeDemo1.VarPointsTo -.init typeDemo2 = OneTypeSensitivePT +.init typeDemo2 = OneTypeSensitivePT typeDemo2.Reachable("", "initCtx", 0). .output typeDemo2.VarPointsTo \ No newline at end of file diff --git a/logic/one-callsite-sensitive-pt.dl b/logic/one-callsite-sensitive-pt.dl index 253c6c2..1267533 100644 --- a/logic/one-callsite-sensitive-pt.dl +++ b/logic/one-callsite-sensitive-pt.dl @@ -4,7 +4,7 @@ .type HContext = Insn .type Context = Insn -.comp OneCallsiteSensitivePT : AbstractContextSensitivePT{ +.comp OneCallsiteSensitivePT: AbstractContextSensitivePT{ .override SelectInvocationContext SelectInvocationContext(callerCtx, insn, baseHeap, hctx, calleeCtx) :- Reachable(caller, callerCtx, _), diff --git a/logic/one-object-sensitive-pt.dl b/logic/one-object-sensitive-pt.dl index 7ca1f24..d3f204d 100644 --- a/logic/one-object-sensitive-pt.dl +++ b/logic/one-object-sensitive-pt.dl @@ -4,7 +4,7 @@ .type HContext = Heap .type Context = Heap -.comp OneObjectSensitivePT : AbstractContextSensitivePT{ +.comp OneObjectSensitivePT: AbstractContextSensitivePT{ .override SelectInvocationContext SelectInvocationContext(callerCtx, insn, baseHeap, hctx, calleeCtx) :- Reachable(caller, callerCtx, _), diff --git a/logic/one-type-sensitive-pt.dl b/logic/one-type-sensitive-pt.dl index fa0f716..48ff9cf 100644 --- a/logic/one-type-sensitive-pt.dl +++ b/logic/one-type-sensitive-pt.dl @@ -4,7 +4,7 @@ .type HContext = Class .type Context = Class -.comp OneTypeSensitivePT : AbstractContextSensitivePT{ +.comp OneTypeSensitivePT: AbstractContextSensitivePT{ .override SelectInvocationContext SelectInvocationContext(callerCtx, insn, baseHeap, hctx, calleeCtx) :- Reachable(caller, callerCtx, _), From 62082d3e76a9f428dd63ed3dc7a20949eff74402 Mon Sep 17 00:00:00 2001 From: yxxx Date: Fri, 6 May 2022 15:22:39 +0800 Subject: [PATCH 02/16] add abstract-context-sensitive-pt --- logic/abstract-context-sensitive-pt.dl | 127 +++++++++++++++++++++++++ 1 file changed, 127 insertions(+) create mode 100644 logic/abstract-context-sensitive-pt.dl diff --git a/logic/abstract-context-sensitive-pt.dl b/logic/abstract-context-sensitive-pt.dl new file mode 100644 index 0000000..1967fab --- /dev/null +++ b/logic/abstract-context-sensitive-pt.dl @@ -0,0 +1,127 @@ +#pragma once +#include "utils.dl" + +.comp AbstractContextSensitivePT{ + .decl VarPointsTo(heap:Heap, hctx:HContext, var:Var, vCtx:Context) + .decl InstanceFieldPointsTo(heap:Heap, hctx:Context, baseHeap:Heap, bhCtx:Context, field:Field) + .decl StaticFieldPointsTo(heap:Heap, hctx:Context, field:Field) + .decl ArrayIndexPointsTo(heap:Heap, hctx:Context, baseHeap:Heap, bhCtx:Context) + .decl Reachable(method:Method, ctx:Context, n:number) + .decl CallGraph(insn:Insn, caller:Method, callerCtx:Context, callee:Method, calleeCtx:Context) + + .decl SelectInvocationContext(callerCtx:Context, invocation:Insn, baseHeap:Heap, hctx:HContext, calleeCtx:Context) overridable + .decl SelectStaticInvocationContext(callerCtx:Context, invocation:Insn, calleeCtx:Context) overridable + + SelectStaticInvocationContext(callerCtx, insn, calleeCtx) :- + Reachable(caller, callerCtx, _), + StaticMethodInvocation(insn, _, _, caller), + calleeCtx = callerCtx. + + // new + VarPointsTo(heap, ctx, var, ctx) :- + Reachable(method, ctx, _), + AssignHeapAllocation(_, _, heap, var, method, _). + + // assign + VarPointsTo(heap, hctx, to, ctx) :- + Reachable(method, ctx, _), + VarPointsTo(heap, hctx, from, ctx), + AssignLocal(_, _, from, to, method). + + // cast + VarPointsTo(heap, hctx, to, ctx) :- + Reachable(method, ctx, _), + AssignCast(_, _, from, to, _, method), + VarPointsTo(heap, hctx, from, ctx). + + // load field + VarPointsTo(heap, hctx, to, ctx) :- + Reachable(method, ctx, _), + LoadInstanceField(_, _, to, base, field, method), + VarPointsTo(baseHeap, bhCtx, base, ctx), + InstanceFieldPointsTo(heap, hctx, baseHeap, bhCtx, field). + + // store field + InstanceFieldPointsTo(heap, hctx, baseHeap, bhCtx, field) :- + Reachable(method, ctx, _), + StoreInstanceField(_, _, from, base, field, method), + VarPointsTo(heap, hctx, from, ctx), + VarPointsTo(baseHeap, bhCtx, base, ctx). + + // load staic field + VarPointsTo(heap, hctx, to, ctx) :- + Reachable(method, ctx, _), + LoadStaticField(_, _, to, field, method), + StaticFieldPointsTo(heap, hctx, field). + + // store static field + StaticFieldPointsTo(heap, hctx, field) :- + Reachable(method, ctx, _), + StoreStaticField(_, _, from, field, method), + VarPointsTo(heap, hctx, from, ctx). + + // load from array + VarPointsTo(heap, hctx, to, ctx) :- + Reachable(method, ctx, _), + LoadArrayIndex(_, _, to, base, method), + VarPointsTo(baseHeap, bhCtx, base, ctx), + ArrayIndexPointsTo(heap, hctx, baseHeap, bhCtx). + + // store into array + ArrayIndexPointsTo(heap, hctx, baseHeap, bhCtx) :- + Reachable(method, ctx, _), + StoreArrayIndex(_, _, from, base, method), + VarPointsTo(heap, hctx, from, ctx), + VarPointsTo(baseHeap, bhCtx, base, ctx). + + Reachable(callee, calleeCtx, n+1), + CallGraph(insn, caller, callerCtx, callee, calleeCtx) :- + Reachable(caller, callerCtx, n), + n < MAXSTEP, + SpecialMethodInvocation(insn, _, callee, base, caller), + VarPointsTo(baseHeap, hctx, base, calleeCtx), + SelectInvocationContext(callerCtx, insn, baseHeap, hctx, callerCtx). + + Reachable(callee, calleeCtx, n+1), + CallGraph(insn, caller, callerCtx, callee, calleeCtx) :- + Reachable(caller, callerCtx, n), + n < MAXSTEP, + StaticMethodInvocation(insn, _, callee, caller), + SelectStaticInvocationContext(callerCtx, insn, calleeCtx). + + Reachable(callee, calleeCtx, n+1), + CallGraph(insn, caller, callerCtx, callee, calleeCtx) :- + Reachable(caller, callerCtx, n), + n < MAXSTEP, + VirtualMethodInvocation(insn, _, method, base, caller), + VarPointsTo(baseHeap, hctx, base, callerCtx), + NormalHeap(baseHeap, class), + MethodInfo(method, simplename, _, _, _, descriptor, _), + Dispatch(simplename, descriptor, class, callee), + SelectInvocationContext(callerCtx, insn, baseHeap, hctx, calleeCtx). + + // param + VarPointsTo(heap, hctx, param, calleeCtx) :- + CallGraph(insn, _, callerCtx, callee, calleeCtx), + ActualParam(n, insn, arg), + FormalParam(n, callee, param), + VarPointsTo(heap, hctx, arg, callerCtx), + NormalHeap(heap, _). + + // return + VarPointsTo(heap, hctx, return, callerCtx) :- + CallGraph(insn, _, callerCtx, callee, calleeCtx), + Return(_, _, var, callee), + AssignReturnValue(insn, return), + VarPointsTo(heap, hctx, var, calleeCtx). + + // this + VarPointsTo(heap, hctx, this, calleeCtx) :- + CallGraph(insn, _, callerCtx, callee, calleeCtx), + ( + VirtualMethodInvocation(insn, _, _, base, _); + SpecialMethodInvocation(insn, _, _, base, _) + ), + ThisVar(callee, this), + VarPointsTo(heap, hctx, base, callerCtx). +} \ No newline at end of file From 1d644ea6edbd34d955d5fb64f03bbae2ef7878e7 Mon Sep 17 00:00:00 2001 From: yxxx Date: Fri, 6 May 2022 15:25:52 +0800 Subject: [PATCH 03/16] add context sensitive ptaint --- example/cs-ptaint-example-1.dl | 39 +++++++++++++++++++++ logic/cs-ptaint.dl | 64 ++++++++++++++++++++++++++++++++++ 2 files changed, 103 insertions(+) create mode 100644 example/cs-ptaint-example-1.dl create mode 100644 logic/cs-ptaint.dl diff --git a/example/cs-ptaint-example-1.dl b/example/cs-ptaint-example-1.dl new file mode 100644 index 0000000..d1614c0 --- /dev/null +++ b/example/cs-ptaint-example-1.dl @@ -0,0 +1,39 @@ +#define MAXSTEP 8 +//#include "../logic/one-callsite-sensitive-pt.dl" +#include "../logic/cs-ptaint.dl" +#include "../logic/one-object-sensitive-pt.dl" + +//.comp MyCallsitePtaint : CSPTaint, OneCallsiteSensitivePT{ +//} +//.init csptaint = MyCallsitePtaint +.comp MyObjectPtaint : CSPTaint, OneObjectSensitivePT{ +} + + +.init csptaint = MyObjectPtaint + + +csptaint.Reachable("", "initCtx", 0). + +csptaint.SourceMethod(""). +csptaint.SinkMethod("", 0). + +csptaint.BaseToRetTransfer(""). +csptaint.BaseToRetTransfer(""). + +csptaint.ArgToRetTransfer("", 0). + +csptaint.SanitizeMethod(""). + + +.decl TaintVar(var:Var, vCtx:Context) + +TaintVar(var, vCtx) :- + csptaint.VarPointsTo(heap, _, var, vCtx), + csptaint.TaintHeap(_, heap). + +.output TaintVar + +.output csptaint.TaintHeap +.output csptaint.TransferTaint +.output csptaint.VarPointsTo \ No newline at end of file diff --git a/logic/cs-ptaint.dl b/logic/cs-ptaint.dl new file mode 100644 index 0000000..524394c --- /dev/null +++ b/logic/cs-ptaint.dl @@ -0,0 +1,64 @@ +#pragma once +#include "utils.dl" +#include "abstract-context-sensitive-pt.dl" + +.comp CSPTaint{ + //.init cspt = AbstractContextSensitivePT + //.init cspt = CSPT + + .decl TaintHeap(insn:Insn, heap:Heap) + .decl SourceMethod(method:Method) + .decl SinkMethod(method:Method, n:number) + + .decl SanitizeMethod(method:Method) + + .decl BaseToRetTransfer(method:Method) + .decl ArgToRetTransfer(method:Method, n:number) + .decl IsTaintedFrom(insn:Insn, from:Var, fromCtx:Context, to:Var, toCtx:Context) + .decl TransferTaint(heap:Heap, newHeap:Heap) + + + // taint arg to param + VarPointsTo(heap, hctx, param, calleeCtx) :- + CallGraph(insn, _, callerCtx, callee, calleeCtx), + ActualParam(n, insn, arg), + FormalParam(n, callee, param), + VarPointsTo(heap, hctx, arg, callerCtx), + TaintHeap(_, heap), // sensitive? + !SanitizeMethod(callee). + + + TaintHeap(insn, heap), + VarPointsTo(heap, hctx, to, callerCtx):- + SourceMethod(callee), + CallGraph(insn, _, callerCtx, callee, _), + AssignReturnValue(insn, to), + heap = cat("NewTainted::", insn), + hctx = "Mock::". + + IsTaintedFrom(insn, base, callerCtx, ret, callerCtx) :- + CallGraph(insn, _, callerCtx, callee, _), + BaseToRetTransfer(callee), + ( + VirtualMethodInvocation(insn, _, _, base, _); + SpecialMethodInvocation(insn, _, _, base, _) + ), + AssignReturnValue(insn, ret). + + IsTaintedFrom(insn, arg, callerCtx, ret, callerCtx) :- + CallGraph(insn, _, callerCtx, callee, _), + ArgToRetTransfer(callee, n), + ActualParam(n, insn, arg), + AssignReturnValue(insn, ret). + + TaintHeap(insn, newHeap), + TransferTaint(heap, newHeap), + VarPointsTo(heap, hctx, var, vCtx) :- + IsTaintedFrom(insn, from, fromCtx, to, toCtx), + VarPointsTo(heap, hctx, from, fromCtx), + TaintHeap(_, heap), + newHeap = cat("TransferTaint::", insn), + VarPointsTo(oldHeap, oldHCtx, to, toCtx), + VarPointsTo(oldHeap, oldHCtx, var, vCtx), + AssignHeapAllocation(_, _, oldHeap, var, _, _). +} \ No newline at end of file From 1d1c189f80ad39e4951eb435d9c6c94fdb59fa7d Mon Sep 17 00:00:00 2001 From: yxxx Date: Fri, 6 May 2022 15:26:22 +0800 Subject: [PATCH 04/16] update ptaint --- logic/ptaint.dl | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/logic/ptaint.dl b/logic/ptaint.dl index a557cd6..2d83ea0 100644 --- a/logic/ptaint.dl +++ b/logic/ptaint.dl @@ -35,7 +35,10 @@ IsTaintedFrom(insn, base, ret) :- CallGraph(insn, _, callee), BaseToRetTransfer(callee), - VirtualMethodInvocation(insn, _, _, base, _), + ( + VirtualMethodInvocation(insn, _, _, base, _); + SpecialMethodInvocation(insn, _, _, base, _) + ), AssignReturnValue(insn, ret). IsTaintedFrom(insn, arg, ret) :- From b99ea8652f2f20053e010f9d92b71f7b515e2586 Mon Sep 17 00:00:00 2001 From: yxxx Date: Fri, 6 May 2022 15:33:25 +0800 Subject: [PATCH 05/16] update readme --- README.md | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index e043fa5..f81858c 100644 --- a/README.md +++ b/README.md @@ -37,9 +37,12 @@ you can use the docker we builded like docker-compose.yml - [x] 一阶上下文对象敏感指针分析 - [x] 一阶上下文类型敏感指针分析 - [ ] 可选择上下文敏感指针分析 -- [ ] 污点分析 +- [x] 污点分析 - [x] 上下文无关ptaint - - [ ] 上下文敏感ptaint + - [x] 上下文敏感ptaint +- [ ] 输出sarif +- [ ] 实现JackEE +- [ ] 性能优化 ## Usage From 6edd373b1086affe9914f78caa8f1da9bc44864a Mon Sep 17 00:00:00 2001 From: yxxx Date: Mon, 30 May 2022 15:43:46 +0800 Subject: [PATCH 06/16] add support info --- README.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/README.md b/README.md index f81858c..c3a2af1 100644 --- a/README.md +++ b/README.md @@ -48,6 +48,16 @@ you can use the docker we builded like docker-compose.yml 见docs文件夹 +## Support + +在使用中遇到什么问题,可以通过 + +- email: help@bytecodedl.com +- github: issue/discussion +- telegram: [bytecodedl](https://t.me/bytecodedl) + +三种途径向我们反馈 + ## Plugin - IDEA From 1328e80a551ca3e73bdca1343550cf9511905e2e Mon Sep 17 00:00:00 2001 From: yxxx Date: Sun, 28 Aug 2022 22:32:50 +0800 Subject: [PATCH 07/16] fix little bug --- logic/cha.dl | 2 +- logic/utils.dl | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/logic/cha.dl b/logic/cha.dl index 77387fb..dcb7e91 100644 --- a/logic/cha.dl +++ b/logic/cha.dl @@ -14,7 +14,7 @@ SinkMethod(method) :- SinkDesc(simplename, class), SubEqClass(subeqclass, class), - !ClassModifier("abstract", subeqclass), + !MethodModifier("abstract", method), MethodInfo(method, simplename, _, subeqclass, _, _, _). EntryMethod(method), diff --git a/logic/utils.dl b/logic/utils.dl index 9bcc016..a7e564a 100644 --- a/logic/utils.dl +++ b/logic/utils.dl @@ -7,6 +7,9 @@ .decl SubClass(subclass:Class, class:Class) .decl SubEqClass(subeqclass:Class, class:Class) +SubEqClass("byte", "byte"). +SubEqClass("byte[]", "byte[]"). + SubEqClass(subclass, class) :- SubClass(subclass, class). SubEqClass(class, class) :- ClassType(class). From 244b7ed954d0d50353565d3fdd99094116af894d Mon Sep 17 00:00:00 2001 From: yxxx Date: Fri, 10 Mar 2023 17:58:44 +0800 Subject: [PATCH 08/16] update import headers --- neo4j/CallEdgeHeader.csv | 2 +- neo4j/CallNodeHeader.csv | 2 +- neo4j/ChaEdgeHeader.csv | 1 + 3 files changed, 3 insertions(+), 2 deletions(-) create mode 100644 neo4j/ChaEdgeHeader.csv diff --git a/neo4j/CallEdgeHeader.csv b/neo4j/CallEdgeHeader.csv index a163d36..eec8984 100644 --- a/neo4j/CallEdgeHeader.csv +++ b/neo4j/CallEdgeHeader.csv @@ -1 +1 @@ -:START_ID :END_ID \ No newline at end of file +:START_ID(Method) :END_ID(Method) \ No newline at end of file diff --git a/neo4j/CallNodeHeader.csv b/neo4j/CallNodeHeader.csv index bff2ea0..27f9b61 100644 --- a/neo4j/CallNodeHeader.csv +++ b/neo4j/CallNodeHeader.csv @@ -1 +1 @@ -method:ID :LABEL \ No newline at end of file +method:ID(Method) :LABEL \ No newline at end of file diff --git a/neo4j/ChaEdgeHeader.csv b/neo4j/ChaEdgeHeader.csv new file mode 100644 index 0000000..27b0681 --- /dev/null +++ b/neo4j/ChaEdgeHeader.csv @@ -0,0 +1 @@ +:START_ID(Method) method :END_ID(Method) \ No newline at end of file From 774df7eb2d2d7a8d4a798ee2a198576cdb2fe493 Mon Sep 17 00:00:00 2001 From: yxxx Date: Mon, 13 Mar 2023 22:45:52 +0800 Subject: [PATCH 09/16] add simple-cha and log4shell example --- example/simple-cha-log4shell.dl | 19 ++++++ logic/simple-cha.dl | 105 ++++++++++++++++++++++++++++++++ 2 files changed, 124 insertions(+) create mode 100644 example/simple-cha-log4shell.dl create mode 100644 logic/simple-cha.dl diff --git a/example/simple-cha-log4shell.dl b/example/simple-cha-log4shell.dl new file mode 100644 index 0000000..e4ac3ff --- /dev/null +++ b/example/simple-cha-log4shell.dl @@ -0,0 +1,19 @@ +#define MAXSTEP 33 + +#include "../logic/simple-cha.dl" + + +SinkDesc("lookup", "javax.naming.Context"). + +// init entrypoint +EntryPoint(simplename, descriptor, class) :- + MethodInfo(_, simplename, _, class, _, descriptor, _), + simplename = "error", + class = "org.apache.logging.log4j.spi.AbstractLogger", + descriptor = "(Ljava/lang/String;)V". + + +.output EntryPoint +.output EntryMethod +.output SinkMethod +.output SimpleCallGraph \ No newline at end of file diff --git a/logic/simple-cha.dl b/logic/simple-cha.dl new file mode 100644 index 0000000..240a3b2 --- /dev/null +++ b/logic/simple-cha.dl @@ -0,0 +1,105 @@ +#pragma once +#include "utils.dl" + +.decl EntryPoint(simplename:symbol, descriptor:symbol, class:Class) +.decl Reachable(method:Method, step:number) +.decl SinkDesc(simplename:symbol, class:Class) +.decl SinkMethod(method:Method) +.decl EntryMethod(method:Method) +.decl BanCaller(method:Method) + +BanCaller(method) :- + MethodInfo(method, simplename, _, class, _, _, _), + contains("java.util", class). + +.output BanCaller + + +.decl CallGraph(insn:Insn, caller:Method, callee:Method) +.decl SimpleCallGraph(insn:Insn, caller:Method, callee:Method) +.decl ChaGraph(caller:Method, implementation:Method, callee:Method) + +SinkMethod(method) :- + SinkDesc(simplename, class), + SubEqClass(subeqclass, class), + !MethodModifier("abstract", method), + MethodInfo(method, simplename, _, subeqclass, _, _, _). + +EntryMethod(method), +Reachable(method, 0) :- + EntryPoint(simplename, descriptor, class), + Dispatch(simplename, descriptor, class, method). + +Reachable(callee, n+1), +SimpleCallGraph(insn, caller, callee), +CallGraph(insn, caller, callee) :- + Reachable(caller, n), + !BanCaller(caller), + n < MAXSTEP, + SpecialMethodInvocation(insn, _, callee, _, caller). + +Reachable(callee, n+1), +SimpleCallGraph(insn, caller, callee), +CallGraph(insn, caller, callee) :- + Reachable(caller, n), + !BanCaller(caller), + n < MAXSTEP, + StaticMethodInvocation(insn, _, callee, caller). + +Reachable(method, n+1), +Reachable(callee, n+1), +SimpleCallGraph(insn, caller, method), +CallGraph(insn, caller, callee) :- + Reachable(caller, n), + !BanCaller(caller), + n < MAXSTEP, + VirtualMethodInvocation(insn, _, method, receiver, caller), + MethodInfo(method, simplename, _, _, _, descriptor, _), + VarType(receiver, class), + SubEqClass(subeqclass, class), + !ClassModifier("abstract", subeqclass), + Dispatch(simplename, descriptor, subeqclass, callee). + +Reachable(callee, n+1), +SimpleCallGraph(insn, caller, callee), +CallGraph(insn, caller, callee) :- + Reachable(caller, n), + !BanCaller(caller), + n < MAXSTEP, + StaticMethodInvocation(insn, _, method, caller), + MethodInfo(method, "doPrivileged", _, "java.security.AccessController", _, _, _), + ActualParam(0, insn, param), + VarType(param, class), + MethodInfo(callee, "run", _, class, _, _, 0). + +ChaGraph(caller, implementation, callee) :- + Reachable(caller, _), + MethodInfo(caller, simplename, _, class, _, descriptor, _), + SubClass(subclass, class), + Dispatch(simplename, descriptor, subclass, implementation), + caller != implementation, + SimpleCallGraph(_, implementation, callee). + +.output ChaGraph + +.decl CallNode(node:Method, label:symbol) +.output CallNode + +CallNode(node, "method") :- + !EntryMethod(node), + !SinkMethod(node), + Reachable(node, _). + +CallNode(node, "sink") :- + Reachable(node, _), + SinkMethod(node). + +CallNode(node, "entry") :- + Reachable(node, _), + EntryMethod(node). + +.decl CallEdge(caller:Method, callee:Method) +.output CallEdge + +CallEdge(caller, callee) :- + SimpleCallGraph(_, caller, callee). From 3afb958e7d3c0a3262bd93cda304e1a4cc7c9365 Mon Sep 17 00:00:00 2001 From: yxxx Date: Mon, 13 Mar 2023 22:49:46 +0800 Subject: [PATCH 10/16] add import simple cha results script --- neoImportChaCall.sh | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 neoImportChaCall.sh diff --git a/neoImportChaCall.sh b/neoImportChaCall.sh new file mode 100644 index 0000000..d1445e9 --- /dev/null +++ b/neoImportChaCall.sh @@ -0,0 +1,11 @@ +#!/bin/bash + +dbname=$1$(date "+%m%d%H%M") + +neo4j-admin import --nodes=Method="/bytecodedl/neo4j/CallNodeHeader.csv,/bytecodedl/output/.*CallNode.csv" --relationships=Call="/bytecodedl/neo4j/CallEdgeHeader.csv,/bytecodedl/output/CallEdge.csv" --relationships=Cha="/bytecodedl/neo4j/ChaEdgeHeader.csv,/bytecodedl/output/ChaGraph.csv" --database=$dbname --delimiter="\t" + +if grep -q "dbms.active_database" /var/lib/neo4j/conf/neo4j.conf; then + sed -i -E "s/dbms.active_database=\w+/dbms.active_database=$dbname/g" /var/lib/neo4j/conf/neo4j.conf +else + echo "dbms.active_database=$dbname" >> /var/lib/neo4j/conf/neo4j.conf +fi \ No newline at end of file From 1e7ea622e5e06ca22b0354ab0e6839cedd6e6269 Mon Sep 17 00:00:00 2001 From: yxxx Date: Mon, 13 Mar 2023 23:02:36 +0800 Subject: [PATCH 11/16] neo4j docker add apoc plugin --- docker-compose.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/docker-compose.yml b/docker-compose.yml index 0f77ab8..364657e 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -14,5 +14,10 @@ services: - "0.0.0.0:7687:7687" environment: - NEO4J_AUTH=neo4j/bytecodedl + - NEO4J_apoc_export_file_enabled=true + - NEO4J_apoc_import_file_enabled=true + - NEO4J_apoc_import_file_use__neo4j__config=true + - NEO4JLABS_PLUGINS=["apoc"] + - NEO4J_dbms_security_procedures_unrestricted=apoc.* volumes: - ./:/bytecodedl \ No newline at end of file From dc472472afc72d3112e8b614721f9f2f766c898a Mon Sep 17 00:00:00 2001 From: yxxx Date: Mon, 13 Mar 2023 23:03:57 +0800 Subject: [PATCH 12/16] add simple-cha --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index c3a2af1..785250a 100644 --- a/README.md +++ b/README.md @@ -30,6 +30,7 @@ you can use the docker we builded like docker-compose.yml - [x] 搜索功能 - [x] 调用图分析 - [x] CHA + - [x] SIMPLE-CHA - [x] RTA - [ ] 指针分析 - [x] 上下文无关指针分析 From eb6449206de4a488c06df4f58edb5a7d763717de Mon Sep 17 00:00:00 2001 From: yxxx Date: Thu, 28 Dec 2023 19:13:36 +0800 Subject: [PATCH 13/16] add cha-log4shell example --- docker-compose.yml | 11 ++--------- example/cha-log4shell.dl | 18 ++++++++++++++++++ logic/cha.dl | 6 +++--- neo4j/CallEdgeHeader.csv | 2 +- neoImportCall-4.4.sh | 11 +++++++++++ neoImportCall.sh | 10 +++++----- neoImportChaCall-4.4.sh | 11 +++++++++++ neoImportChaCall.sh | 10 +++++----- 8 files changed, 56 insertions(+), 23 deletions(-) create mode 100644 example/cha-log4shell.dl create mode 100644 neoImportCall-4.4.sh create mode 100644 neoImportChaCall-4.4.sh diff --git a/docker-compose.yml b/docker-compose.yml index 364657e..e21273c 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -7,17 +7,10 @@ services: volumes: - ./:/bytecodedl neo: - image: neo4j:4.4.4-community + image: neo4j-server:5.12.0-bytecodedl-pathfinder-1.0.0 restart: always ports: - "0.0.0.0:7474:7474" - "0.0.0.0:7687:7687" - environment: - - NEO4J_AUTH=neo4j/bytecodedl - - NEO4J_apoc_export_file_enabled=true - - NEO4J_apoc_import_file_enabled=true - - NEO4J_apoc_import_file_use__neo4j__config=true - - NEO4JLABS_PLUGINS=["apoc"] - - NEO4J_dbms_security_procedures_unrestricted=apoc.* volumes: - - ./:/bytecodedl \ No newline at end of file + - ./:/bytecodedl diff --git a/example/cha-log4shell.dl b/example/cha-log4shell.dl new file mode 100644 index 0000000..4b9f606 --- /dev/null +++ b/example/cha-log4shell.dl @@ -0,0 +1,18 @@ +#define MAXSTEP 33 +#define CHAO 1 + +#include "../logic/cha.dl" + +BanCaller(method) :- + MethodInfo(method, _, _, class, _, _, _), + !contains("org.apache.logging.log4j", class). + + +SinkDesc("lookup", "javax.naming.Context"). + +// init entrypoint +EntryPoint(simplename, descriptor, class) :- + MethodInfo(_, simplename, _, class, _, descriptor, _), + simplename = "error", + class = "org.apache.logging.log4j.spi.AbstractLogger", + descriptor = "(Ljava/lang/String;)V". \ No newline at end of file diff --git a/logic/cha.dl b/logic/cha.dl index dcb7e91..d290216 100644 --- a/logic/cha.dl +++ b/logic/cha.dl @@ -123,10 +123,10 @@ CallNode(node, "entry") :- RefinedReachable(node), EntryMethod(node). -.decl CallEdge(caller:Method, callee:Method) +.decl CallEdge(caller:Method, insn:Insn, callee:Method) .output CallEdge -CallEdge(caller, callee) :- +CallEdge(caller, insn, callee) :- RefinedReachable(caller), RefinedReachable(callee), - CallGraph(_, caller, callee). + CallGraph(insn, caller, callee). diff --git a/neo4j/CallEdgeHeader.csv b/neo4j/CallEdgeHeader.csv index eec8984..5e2a8da 100644 --- a/neo4j/CallEdgeHeader.csv +++ b/neo4j/CallEdgeHeader.csv @@ -1 +1 @@ -:START_ID(Method) :END_ID(Method) \ No newline at end of file +:START_ID(Method) insn :END_ID(Method) \ No newline at end of file diff --git a/neoImportCall-4.4.sh b/neoImportCall-4.4.sh new file mode 100644 index 0000000..0e82b0d --- /dev/null +++ b/neoImportCall-4.4.sh @@ -0,0 +1,11 @@ +#!/bin/bash + +dbname=$1$(date "+%m%d%H%M") + +neo4j-admin database import full --relationships=Call="/bytecodedl/neo4j/CallEdgeHeader.csv,/bytecodedl/output/.*CallEdge.csv" --nodes="/bytecodedl/neo4j/CallNodeHeader.csv,/bytecodedl/output/.*CallNode.csv" --delimiter="\t" $dbname + +if grep -q "dbms.active_database" /var/lib/neo4j/conf/neo4j.conf; then + sed -i -E "s/dbms.active_database=\w+/dbms.active_database=$dbname/g" /var/lib/neo4j/conf/neo4j.conf +else + echo "dbms.active_database=$dbname" >> /var/lib/neo4j/conf/neo4j.conf +fi diff --git a/neoImportCall.sh b/neoImportCall.sh index da1e711..7e2ae73 100644 --- a/neoImportCall.sh +++ b/neoImportCall.sh @@ -2,10 +2,10 @@ dbname=$1$(date "+%m%d%H%M") -neo4j-admin import --relationships=Call="/bytecodedl/neo4j/CallEdgeHeader.csv,/bytecodedl/output/.*CallEdge.csv" --nodes="/bytecodedl/neo4j/CallNodeHeader.csv,/bytecodedl/output/.*CallNode.csv" --database=$dbname --delimiter="\t" +neo4j-admin database import full --nodes="/bytecodedl/neo4j/CallNodeHeader.csv,/bytecodedl/output/.*CallNode.csv" --relationships=Call="/bytecodedl/neo4j/CallEdgeHeader.csv,/bytecodedl/output/CallEdge.csv" --delimiter="\t" $dbname -if grep -q "dbms.active_database" /var/lib/neo4j/conf/neo4j.conf; then - sed -i -E "s/dbms.active_database=\w+/dbms.active_database=$dbname/g" /var/lib/neo4j/conf/neo4j.conf +if grep -q "#initial.dbms.default_database" /var/lib/neo4j/conf/neo4j.conf; then + sed -i -E "s/#initial.dbms.default_database=\S+/initial.dbms.default_database=$dbname/g" /var/lib/neo4j/conf/neo4j.conf else - echo "dbms.active_database=$dbname" >> /var/lib/neo4j/conf/neo4j.conf -fi \ No newline at end of file + sed -i -E "s/initial.dbms.default_database=\S+/initial.dbms.default_database=$dbname/g" /var/lib/neo4j/conf/neo4j.conf +fi diff --git a/neoImportChaCall-4.4.sh b/neoImportChaCall-4.4.sh new file mode 100644 index 0000000..ef763e4 --- /dev/null +++ b/neoImportChaCall-4.4.sh @@ -0,0 +1,11 @@ +#!/bin/bash + +dbname=$1$(date "+%m%d%H%M") + +neo4j-admin database import --nodes=Method="/bytecodedl/neo4j/CallNodeHeader.csv,/bytecodedl/output/.*CallNode.csv" --relationships=Call="/bytecodedl/neo4j/CallEdgeHeader.csv,/bytecodedl/output/CallEdge.csv" --relationships=Cha="/bytecodedl/neo4j/ChaEdgeHeader.csv,/bytecodedl/output/ChaGraph.csv" --database=$dbname --delimiter="\t" + +if grep -q "dbms.active_database" /var/lib/neo4j/conf/neo4j.conf; then + sed -i -E "s/dbms.active_database=\w+/dbms.active_database=$dbname/g" /var/lib/neo4j/conf/neo4j.conf +else + echo "dbms.active_database=$dbname" >> /var/lib/neo4j/conf/neo4j.conf +fi diff --git a/neoImportChaCall.sh b/neoImportChaCall.sh index d1445e9..130c7bb 100644 --- a/neoImportChaCall.sh +++ b/neoImportChaCall.sh @@ -2,10 +2,10 @@ dbname=$1$(date "+%m%d%H%M") -neo4j-admin import --nodes=Method="/bytecodedl/neo4j/CallNodeHeader.csv,/bytecodedl/output/.*CallNode.csv" --relationships=Call="/bytecodedl/neo4j/CallEdgeHeader.csv,/bytecodedl/output/CallEdge.csv" --relationships=Cha="/bytecodedl/neo4j/ChaEdgeHeader.csv,/bytecodedl/output/ChaGraph.csv" --database=$dbname --delimiter="\t" +neo4j-admin database import full --nodes=Method="/bytecodedl/neo4j/CallNodeHeader.csv,/bytecodedl/output/.*CallNode.csv" --relationships=Call="/bytecodedl/neo4j/CallEdgeHeader.csv,/bytecodedl/output/CallEdge.csv" --relationships=Cha="/bytecodedl/neo4j/ChaEdgeHeader.csv,/bytecodedl/output/ChaEdge.csv" --delimiter="\t" $dbname -if grep -q "dbms.active_database" /var/lib/neo4j/conf/neo4j.conf; then - sed -i -E "s/dbms.active_database=\w+/dbms.active_database=$dbname/g" /var/lib/neo4j/conf/neo4j.conf +if grep -q "#initial.dbms.default_database" /var/lib/neo4j/conf/neo4j.conf; then + sed -i -E "s/#initial.dbms.default_database=\w+/initial.dbms.default_database=$dbname/g" /var/lib/neo4j/conf/neo4j.conf else - echo "dbms.active_database=$dbname" >> /var/lib/neo4j/conf/neo4j.conf -fi \ No newline at end of file + sed -i -E "s/initial.dbms.default_database=\w+/initial.dbms.default_database=$dbname/g" /var/lib/neo4j/conf/neo4j.conf +fi From 85e4bb7d09a5b2efc2941a91c464ad27034eeac7 Mon Sep 17 00:00:00 2001 From: yxxx Date: Thu, 28 Dec 2023 19:19:23 +0800 Subject: [PATCH 14/16] update neo4j docker image --- docker-compose.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker-compose.yml b/docker-compose.yml index e21273c..8f8e453 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -7,7 +7,7 @@ services: volumes: - ./:/bytecodedl neo: - image: neo4j-server:5.12.0-bytecodedl-pathfinder-1.0.0 + image: wuxxxxx/neo4j-server:5.12.0-bytecodedl-pathfinder-1.0.0 restart: always ports: - "0.0.0.0:7474:7474" From a5be2913ac971fd5699a8c03c100589b2e1eecb5 Mon Sep 17 00:00:00 2001 From: yxxx Date: Sat, 30 Dec 2023 10:10:15 +0800 Subject: [PATCH 15/16] update neo4j image name --- docker-compose.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docker-compose.yml b/docker-compose.yml index 8f8e453..5a834cf 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,13 +1,13 @@ version: '2.4' services: bytecodedl: - image: wuxxxxx/bytecodedl:1.0.0 + image: wuxxxxx/bytecodedl:1.0.1 restart: always command: sleep infinity volumes: - ./:/bytecodedl neo: - image: wuxxxxx/neo4j-server:5.12.0-bytecodedl-pathfinder-1.0.0 + image: wuxxxxx/neo4j-server:5.12.0-bytecodedl-pathfinder-1.0.1 restart: always ports: - "0.0.0.0:7474:7474" From d7a833973cc8d68c944288270b6a50092c65f98e Mon Sep 17 00:00:00 2001 From: yxxx Date: Sat, 6 Jan 2024 16:53:02 +0800 Subject: [PATCH 16/16] update bytecodedl docker --- docker-compose.yml | 2 +- docker/bytecodedl/Dockerfile | 16 ++++++++++++++++ docker/neo4j-server/Dockerfile | 9 +++++++++ 3 files changed, 26 insertions(+), 1 deletion(-) create mode 100644 docker/bytecodedl/Dockerfile create mode 100644 docker/neo4j-server/Dockerfile diff --git a/docker-compose.yml b/docker-compose.yml index 5a834cf..e4435eb 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,7 +1,7 @@ version: '2.4' services: bytecodedl: - image: wuxxxxx/bytecodedl:1.0.1 + image: wuxxxxx/bytecodedl:1.0.2 restart: always command: sleep infinity volumes: diff --git a/docker/bytecodedl/Dockerfile b/docker/bytecodedl/Dockerfile new file mode 100644 index 0000000..b5e456a --- /dev/null +++ b/docker/bytecodedl/Dockerfile @@ -0,0 +1,16 @@ +From ubuntu:22.04 + +LABEL version="1.0.2" +LABEL maintainer="yxxx " + +RUN apt-get update \ + && apt-get install -y vim \ + && apt-get install -y wget \ + && apt-get install -y git \ + && apt-get install -y openjdk-8-jdk + +RUN wget https://souffle-lang.github.io/ppa/souffle-key.public -O /usr/share/keyrings/souffle-archive-keyring.gpg \ + && echo "deb [signed-by=/usr/share/keyrings/souffle-archive-keyring.gpg] https://souffle-lang.github.io/ppa/ubuntu/ stable main" | tee /etc/apt/sources.list.d/souffle.list \ + && apt update && apt install -y souffle + +RUN wget https://github.com/BytecodeDL/soot-fact-generator/releases/download/v1.4.2/soot-fact-generator-1.4.2.jar \ No newline at end of file diff --git a/docker/neo4j-server/Dockerfile b/docker/neo4j-server/Dockerfile new file mode 100644 index 0000000..303c642 --- /dev/null +++ b/docker/neo4j-server/Dockerfile @@ -0,0 +1,9 @@ +From neo4j:5.12.0 + +LABEL version="1.0.1" +LABEL maintainer="yxxx " + +RUN wget https://github.com/BytecodeDL/bytecodedl-pathfinder-neo4j-procedure/releases/download/v1.0.1/bytecodedl-pathfinder-1.0.1.jar -O /var/lib/neo4j/plugins/bytecodedl-pathfinder-1.0.1.jar + +ENV NEO4J_AUTH=neo4j/bytecodedl \ + NEO4J_dbms_security_procedures_unrestricted=bytecodedl.* \ No newline at end of file