-
Notifications
You must be signed in to change notification settings - Fork 8
Expand file tree
/
Copy pathserver_tools_source.sc
More file actions
266 lines (218 loc) · 9.82 KB
/
server_tools_source.sc
File metadata and controls
266 lines (218 loc) · 9.82 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
import java.lang
import io.shiftleft.codepropertygraph.Cpg
import io.shiftleft.codepropertygraph.cpgloading.CpgLoader
import io.shiftleft.codepropertygraph.generated.nodes._
import io.shiftleft.semanticcpg.language.*
import io.shiftleft.codepropertygraph.generated.nodes
import io.shiftleft.codepropertygraph.generated.PropertyNames
import io.joern.dataflowengineoss.language.*
import scala.jdk.CollectionConverters.*
implicit val resolver: ICallResolver = NoResolve
implicit val finder: NodeExtensionFinder = DefaultNodeExtensionFinder
import io.joern.joerncli.console.Joern.context
import scala.collection.mutable
import scala.reflect.ClassTag
import _root_.io.joern.console.*
import _root_.io.joern.joerncli.console.JoernConsole.*
import _root_.io.shiftleft.codepropertygraph.cpgloading.*
import _root_.io.shiftleft.codepropertygraph.generated.{help as _, *}
import _root_.io.shiftleft.codepropertygraph.generated.nodes.*
import _root_.io.joern.dataflowengineoss.language.*
import _root_.io.shiftleft.semanticcpg.language.*
var cpg: Cpg = null
def convertToLong(str: String): Long = {
// 移除字符串末尾的'L'字符(如果存在)
val cleanStr = if (str.endsWith("L")) str.dropRight(1) else str
// 转换为Long
cleanStr.toLong
}
def get_method_info_by_id(id:Long): String = {
/*Get the info of a method by its id
@param id: The id of the method
@return: The info of the method, including the full name, name, signature and id
*/
val method = cpg.method.id(id).head
s"method_full_name=${method.fullName}|method_name=${method.name}|method_signature=${method.signature}|method_id=${method.id}L"
}
def get_class_info_by_id(id:Long): String = {
/*Get the info of a class by its id
@param id: The id of the class
@return: The info of the class, including the full name, name and id
*/
val cls = cpg.typeDecl.id(id).head
s"class_full_name=${cls.fullName}|class_name=${cls.name}|class_id=${cls.id}L"
}
def get_call_info_by_id(id:Long): String = {
/*Get the info of a call by its id
@param id: The id of the call
@return: The info of the call, including the code and id
*/
val call = cpg.call.id(id).head
s"call_code=${call.code}|call_id=${call.id}L"
}
def _get_classes(class_full_name: String, visited: mutable.Set[String] = mutable.Set()): List[nodes.TypeDecl] = {
/*Retrieves a list of anonymous classes defined within a class
@param cpg: The CPG to query
@param class_full_name: The fully qualified name of the class (e.g., com.android.nfc.NfcService)
@return: List of full name and id of classes which are anonymous classes in the source class
*/
if (visited.contains(class_full_name)) return List()
val classDecl = cpg.typeDecl.filter(_.fullName == class_full_name).l.head
var clsList:List[nodes.TypeDecl] = List(classDecl)
val anonymous_lst = cpg.typeDecl.filter(_.filename == classDecl.filename).filter(_.fullName.startsWith(s"${class_full_name}" + "$")).l
clsList = clsList ++ anonymous_lst
visited.addAll(clsList.map(_.fullName))
val sub_clsList = clsList.flatMap(cls => _get_classes(cls.fullName, visited))
(clsList ++ sub_clsList).distinct
}
def load_cpg(cpg_filepath: String) :Boolean = {
/*
Loads a CPG from a file if the cpg is not loaded or the cpg is not the same as the filepath
@param cpg_filepath: The path to the CPG file, the filepath is absolute path
@return: True if the CPG is loaded successfully, False otherwise
*/
try{
if (cpg == null) {
println(s"Loading CPG from ${cpg_filepath}")
cpg = CpgLoader.load(cpg_filepath)
return true
}else{
val cur_cpg_filepath = get_cpg_filepath()
if (cur_cpg_filepath != cpg_filepath) {
println(s"Loading CPG from ${cpg_filepath} replace the old cpg")
cpg = CpgLoader.load(cpg_filepath)
return true
}else{
println(s"CPG already loaded from ${cpg_filepath}")
return true
}
}
}catch{
case e: Exception => {
println(s"Error loading CPG from ${cpg_filepath}: ${e.getMessage}")
return false
}
}
}
def get_cpg_filepath(): String = {
/*Get the filepath of the CPG
@return: The filepath of the CPG
*/
try{
cpg.graph.storagePathMaybe.getOrElse("").toString()
}catch{
case e: Exception => {
println(s"Error getting CPG filepath: ${e.getMessage}")
return ""
}
}
}
def get_method_callees(method_full_name: String): List[String] = {
/*Get the callees of a method
@param method_full_name: The fully qualified name of the source method(e.g., com.android.nfc.NfcService$6.onReceive:void(android.content.Context,android.content.Intent))
@return: List of full name, name, signature and id of methods which call the source method
*/
cpg.method.fullNameExact(method_full_name).head.callee.distinct.map(m => get_method_info_by_id(m.id)).l
}
def get_method_callers(method_full_name: String): List[String] = {
/*Get the callees of a method
@param method_full_name: The fully qualified name of the source method(e.g., com.android.nfc.NfcService$6.onReceive:void(android.content.Context,android.content.Intent))
@return: List of full name, name, signature and id of methods called by the source method
*/
cpg.method.fullNameExact(method_full_name).head.caller.distinct.map(m => get_method_info_by_id(m.id)).l
}
def get_class_full_name_by_id(id: String): String = {
/*Get the fully name of a class by its id
@param id: The id of the class
@return: The fully name of the class
*/
cpg.typeDecl.id(convertToLong(id)).head.fullName
}
def get_class_methods_by_class_full_name(class_full_name: String): List[String] = {
/*Get the methods of a class by its fully qualified name
@param class_full_name: The fully qualified name of the class
@return: List of full name, name, signature and id of methods in the class
*/
val cls_list = _get_classes(class_full_name)
cls_list.flatMap{case cls: nodes.TypeDecl => cls.method.map(m => (s"methodFullName=${m.fullName} methodId=${m.id}L"))}
}
def get_method_code_by_method_full_name(method_full_name: String): String = {
/*Get the code of a method by its fully name
@param method_full_name: The fully qualified name of the method
@return: The code of the method
*/
cpg.method.fullNameExact(method_full_name).head.sourceCode
}
def get_method_code_by_id(id: String): String = {
/*Get the code of a method by its id
@param id: The id of the method
@return: The code of the method
*/
cpg.method.id(convertToLong(id)).head.sourceCode
}
def get_method_full_name_by_id(id: String): String = {
/*Get the fully qualified name of a method by its id
@param id: The id of the method
@return: The fully qualified name of the method
*/
cpg.method.id(convertToLong(id)).head.fullName
}
def get_call_code_by_id(id: String): String = {
/*Get the code of a call by its id
@param id: The id of the call
@return: The code of the call
*/
cpg.call.id(convertToLong(id)).head.code
}
def get_method_code_by_class_full_name_and_method_name(class_full_name: String, method_name: String): List[String] = {
/*Get the code of a method by its class full name and method name
@param class_full_name: The fully qualified name of the class
@param method_name: The name of the method
@return: List of full name, name, signature and id of methods in the class
*/
cpg.typeDecl.filter(_.fullName == class_full_name).head.method.filter(_.name == method_name).map(m => (s"methodFullName=${m.fullName} methodId=${m.id}L")).l
}
def get_method_by_full_name_without_signature(full_name_without_signature: String): List[String] = {
/*Get the info of a method list by its fully qualified name without signature
@param full_name_without_signature: The fully qualified name of the method without signature
@return: The info of the methods, including the full name, name, signature and id
*/
cpg.method.filter(_.fullName.contains(full_name_without_signature)).map(m => get_method_info_by_id(m.id)).l
}
def get_derived_classes_by_class_full_name(class_full_name: String): List[String] = {
/*Get the derived classes of a class
@param class_full_name: The fully qualified name of the class
@return: The derived classes info of the class, including the full name, name and id
*/
cpg.typeDecl.filter(_.fullName == class_full_name).head.derivedTypeDeclTransitive.map(c => get_class_info_by_id(c.id)).l
}
def get_parent_classes_by_class_full_name(class_full_name: String): List[String] = {
/*Get the parent classes of a class
@param class_full_name: The fully qualified name of the class
@return: The parent classes info of the class, including the full name, name and id
*/
val cls = cpg.typeDecl.filter(_.fullName == class_full_name).head
cls.start.repeat(_.inheritsFromOut._refOut.head.asInstanceOf[TypeDecl])(_.until(_.filter(c => c.inheritsFromOut.isEmpty)).emit).map(c => get_class_info_by_id(c.id)).l
}
def get_method_by_call_id(id: String): String = {
/*Get the method info by the call id which the call is in the method
@param id: The id of the call
@return: The method info of the call
*/
get_method_info_by_id(cpg.call.id(convertToLong(id)).head.method.id)
}
def get_referenced_method_full_name_by_call_id(id: String): String = {
/*Get the method info by the call id which the call is referenced the method
@param id: The id of the call
@return: The method info of the call
*/
cpg.call.id(convertToLong(id)).head.methodFullName
}
def get_calls_in_method_by_method_full_name(method_full_name: String): List[String] = {
/* Get the calls in a method by the method full name
@param method_full_name: The fully qualified name of the method
@return: The calls info in the method, including the code and id
*/
val method = cpg.method.filter(_.fullName == method_full_name).head
method.ast.isCall.collect(c => get_call_info_by_id(c.id)).l
}