21
21
class ScriptManager :
22
22
def __init__ (self , elasticsearch_host :str , elasticsearch_port :int ):
23
23
24
- self .current_thread_count = 0
25
- self .thread_limit = 3
26
- self .thread_limit_lock = threading .Lock ()
24
+
27
25
28
26
self .scripts = {}
29
27
self .scripts_mutex = threading .Lock ()
@@ -35,6 +33,9 @@ def __init__(self, elasticsearch_host:str, elasticsearch_port:int):
35
33
elasticport = elasticsearch_port ,
36
34
)
37
35
36
+ self .Analysis_Start_Queue = queue .Queue ()
37
+ threading .Thread (target = self .Start_Analysis ,daemon = True ).start ()
38
+
38
39
self .remove_script_name_queue :List [str ] = [] # 삭제 요청 대기 큐 (script 이름을 전달)
39
40
self .remove_script_name_queue_mutex = threading .Lock ()
40
41
threading .Thread (target = self ._check_remove_script_loop ,daemon = True ).start ()
@@ -149,79 +150,83 @@ def _remove_script(self, script_name:str):
149
150
150
151
##########################
151
152
152
- def Start_Analysis (self , script_type :Script_Packages_type_enum , DATA ) :
153
-
153
+ def Start_Analysis (self , ):#script_type:Script_Packages_type_enum, DATA ) :
154
154
155
- if DATA == None :
156
- with self .thread_limit_lock :
157
- self .current_thread_count -= 1
158
- return
155
+
156
+ # 단일 스레드 분석 수행 (과부하 방지)
157
+ while True :
158
+ request :Optional [dict ] = self .Analysis_Start_Queue .get ()
159
+
160
+ if request == None :
161
+ continue
162
+
163
+ script_type :Script_Packages_type_enum = request ["script_type" ]
164
+ DATA :dict = request ["DATA" ]
165
+
166
+ # 분석 완료 확인
167
+ if self .Get_Analysis_Result_ (script_type = script_type , DATA = DATA ):
168
+ # 이미 분석 완료된 경우 skip
169
+ continue
170
+
171
+ if DATA == None :
172
+ continue
159
173
160
- queue_list :list [queue .Queue ] = []
174
+ queue_list :list [queue .Queue ] = []
161
175
162
- using_scripts = [] # 참조 해제 시 정확히 사용된 스크립트 목록
163
- print (f"스크립트 분석 시작!" )
164
- with self .scripts_mutex :
165
- for script_name in self .scripts :
176
+ using_scripts = [] # 참조 해제 시 정확히 사용된 스크립트 목록
177
+ print (f"스크립트 분석 시작!" )
178
+ with self .scripts_mutex :
179
+ for script_name in self .scripts :
166
180
167
- # 블랙리스트 스크립립트는 제외하고, 타입이 다른 스크립트는 제외한다.
168
- if self .scripts [script_name ]["type" ] != script_type .name :
169
- continue
170
-
171
- queue_instance = queue .Queue ()
181
+ # 블랙리스트 스크립립트는 제외하고, 타입이 다른 스크립트는 제외한다.
182
+ if self .scripts [script_name ]["type" ] != script_type .name :
183
+ continue
184
+
185
+ queue_instance = queue .Queue ()
172
186
173
- queue_list .append ( self .scripts [script_name ]["module" ].Start_Analysis (self .ToolManager , queue_instance , DATA ) ) # 분석 유형 일치한 스크립트 실행
187
+ queue_list .append ( self .scripts [script_name ]["module" ].Start_Analysis (self .ToolManager , queue_instance , DATA ) ) # 분석 유형 일치한 스크립트 실행
174
188
175
- using_scripts .append (script_name )
176
-
177
- # 참조 카운트 증가 (필수적)
178
- self .scripts [script_name ]["reference_count" ] += 1
189
+ using_scripts .append (script_name )
190
+
191
+ # 참조 카운트 증가 (필수적)
192
+ self .scripts [script_name ]["reference_count" ] += 1
179
193
180
- if len (queue_list ) > 0 :
194
+ if len (queue_list ) > 0 :
181
195
182
- # 모두 완료할 때까지 대기
183
- result :list [dict ] = []
184
- for q in queue_list :
185
-
186
- try :
187
- data = q .get ()
196
+ # 모두 완료할 때까지 대기
197
+ result :list [dict ] = []
198
+ for q in queue_list :
188
199
189
- if not data :
200
+ try :
201
+ data = q .get ()
202
+
203
+ if not data :
204
+ continue
205
+ elif isinstance (data , Exception ):
206
+ continue
207
+ elif isinstance (data , dict ):
208
+ result .append ( data )
209
+ except :
190
210
continue
191
- elif isinstance (data , Exception ):
192
- continue
193
- elif isinstance (data , dict ):
194
- result .append ( data )
195
- except :
196
- continue
197
-
211
+
212
+
213
+ if len (result ) > 0 :
214
+
215
+ # 분석 결과 가져오기 성공
216
+
217
+ # ElasticSearch에 저장 ( mutex 필요 )
218
+ with self .Analysis_ElasticSearch .mutex_ :
219
+ self .save_to_elasticsearch (
220
+ SCRIPT_TYPE = script_type ,
221
+ DATA = DATA ,
222
+ analyzed_results = result
223
+ )
224
+
225
+ # 참조 카운트 감소 (필수적)
226
+ with self .scripts_mutex :
227
+ for script_name in using_scripts :
228
+ self .scripts [script_name ]["reference_count" ] -= 1
198
229
199
- if len (result ) > 0 :
200
-
201
- # 분석 결과 가져오기 성공
202
-
203
- # ElasticSearch에 저장 ( mutex 필요 )
204
- with self .Analysis_ElasticSearch .mutex_ :
205
- self .save_to_elasticsearch (
206
- SCRIPT_TYPE = script_type ,
207
- DATA = DATA ,
208
- analyzed_results = result
209
- )
210
-
211
- else :
212
- print ("분석결과가 하나도 없음" )
213
- with self .thread_limit_lock :
214
- self .current_thread_count -= 1
215
- return
216
-
217
- # 참조 카운트 감소 (필수적)
218
- with self .scripts_mutex :
219
- for script_name in using_scripts :
220
- self .scripts [script_name ]["reference_count" ] -= 1
221
-
222
- with self .thread_limit_lock :
223
- self .current_thread_count -= 1
224
- return
225
230
226
231
def save_to_elasticsearch (
227
232
self ,
@@ -270,7 +275,15 @@ def save_to_elasticsearch(
270
275
def Get_Analysis_Result_ (self , script_type :str , DATA :dict )-> Optional [bool ]:
271
276
272
277
if script_type == Script_Packages_type_enum .file .name :
273
- sha256 = str (DATA ["sha256" ]).lower ()
278
+
279
+ sha256 = ""
280
+
281
+ if "sha256" in DATA :
282
+ sha256 = str (DATA ["sha256" ]).lower ()
283
+ elif "binary" in DATA :
284
+ sha256 = hashlib .sha256 ( base64 .b64decode (DATA ["binary" ]) ).hexdigest ()
285
+ else :
286
+ raise Exception ("분석 데이터에 sha256값이 없습니다." )
274
287
275
288
# 엘라스틱서치 를 통해 sha256 조회
276
289
return self .Analysis_ElasticSearch .is_document_exist_from_FILE (
0 commit comments