def arclist(self, file_struct, fileformat): import kernel file_scan_list = [] # 검사 대상 정보를 모두 가짐 (k2file.FileStruct) rname = file_struct.get_filename() deep_name = file_struct.get_additional_filename() mname = file_struct.get_master_filename() level = file_struct.get_level() # 압축 엔진 모듈의 arclist 멤버 함수 호출 for inst in self.kavmain_inst: is_archive_engine = False can_arc = kernel.MASTER_IGNORE try: ret_getinfo = inst.getinfo() if 'engine_type' in ret_getinfo: if ret_getinfo[ 'engine_type'] == kernel.ARCHIVE_ENGINE: # 압축 엔진 Type is_archive_engine = True if 'make_arc_type' in ret_getinfo: can_arc = ret_getinfo['make_arc_type'] except AttributeError: pass try: arc_list = [] # 압축 파일 리스트 if self.options['opt_arc']: # 압축 검사 옵션이 있으면 모두 호출 arc_list = inst.arclist(rname, fileformat) # 단, 카운트는 압축 엔진일때만 처리 if len(arc_list) and is_archive_engine: self.result['Packed'] += 1 else: # 압축 엔진 Type이 아니면 일반 엔진 호출 if not is_archive_engine: arc_list = inst.arclist(rname, fileformat) except AttributeError: pass if len(arc_list): # 압축 리스트가 존재한다면 추가하고 종료 for alist in arc_list: arc_id = alist[0] # 항상 압축 엔진 ID가 들어옴 name = alist[1] # 압축 파일의 내부 파일 이름 if len(deep_name): # 압축 파일 내부 표시용 dname = '%s/%s' % (deep_name, name) else: dname = '%s' % name fs = k2file.FileStruct() fs.set_archive(arc_id, rname, name, dname, mname, False, can_arc, level + 1) file_scan_list.append(fs) # break return file_scan_list
def scan(self, filename, *callback): scan_callback_fn = None # 악성코드 검사 콜백 함수 move_master_file = False # 마스터 파일 격리 필요 여부 t_master_file = '' # 마스터 파일 # 악성코드 검사 결과 ret_value = { 'filename': '', # 파일 이름 'result': False, # 악성코드 발견 여부 'virus_name': '', # 발견된 악성코드 이름 'virus_id': -1, # 악성코드 ID 'engine_id': -1 # 악성코드를 발견한 플러그인 엔진 ID } try: # 콜백 함수 저장 scan_callback_fn = callback[0] self.disinfect_callback_fn = callback[1] self.update_callback_fn = callback[2] self.quarantine_callback_fn = callback[3] except IndexError: pass # 1. 검사 대상 리스트에 파일을 등록 file_info = k2file.FileStruct(filename) file_scan_list = [file_info] # 최초 한번만 하위 폴더 검색 is_sub_dir_scan = True while len(file_scan_list): try: t_file_info = file_scan_list.pop(0) # 검사 대상 파일 하나를 가짐 real_name = t_file_info.get_filename() # 폴더면 내부 파일리스트만 검사 대상 리스트에 등록 if os.path.isdir(real_name): # 폴더 등을 처리할 때를 위해 뒤에 붇는 os.sep는 우선 제거 if real_name[-1] == os.sep: real_name = real_name[:-1] # 콜백 호출 또는 검사 리턴값 생성 ret_value['result'] = False # 폴더이므로 악성코드 없음 ret_value['filename'] = real_name # 검사 파일 이름 ret_value['file_struct'] = t_file_info # 검사 파일 이름 self.result['Folders'] += 1 # 폴더 개수 카운트 if self.options['opt_list']: # 옵션 내용 중 모든 리스트 출력인가? if isinstance(scan_callback_fn, types.FunctionType): # 콜백 함수가 존재하는가? scan_callback_fn(ret_value) # 콜백 함수 호출 if is_sub_dir_scan: # 폴더 안의 파일들을 검사대상 리스트에 추가 flist = glob.glob(real_name + os.sep + '*') tmp_flist = [] for rfname in flist: tmp_info = k2file.FileStruct(rfname) tmp_flist.append(tmp_info) file_scan_list = tmp_flist + file_scan_list if self.options['opt_nor']: # 하위 폴더 검색 옵션이 체크 is_sub_dir_scan = False # 하위 폴더 검색 하지 않음 elif os.path.isfile(real_name) or t_file_info.is_archive( ): # 검사 대상이 파일인가? 압축 해제 대상인가? self.result['Files'] += 1 # 파일 개수 카운트 # 압축된 파일이면 해제하기 if real_name == '': # 이미 실제 파일명이 존재하지 않으면 압축 파일임 ret = self.unarc(t_file_info) if ret: t_file_info = ret # 압축 결과물이 존재하면 파일 정보 교체 # 2. 포맷 분석 ff = self.format(t_file_info) # 파일로 악성코드 검사 ret, vname, mid, scan_state, eid = self.__scan_file( t_file_info, ff) if self.options[ 'opt_feature'] != 0xffffffff: # 인공지능 AI를 위한 Feature 추출 self.__feature_file(t_file_info, ff, self.options['opt_feature']) if ret: # 악성코드 진단 개수 카운트 import kernel if scan_state == kernel.INFECTED: self.result['Infected_files'] += 1 elif scan_state == kernel.SUSPECT: self.result['Suspect_files'] += 1 elif scan_state == kernel.WARNING: self.result['Warnings'] += 1 self.identified_virus.update([vname]) # 콜백 호출 또는 검사 리턴값 생성 ret_value['result'] = ret # 악성코드 발견 여부 ret_value['engine_id'] = eid # 엔진 ID ret_value['virus_name'] = vname # 악성코드 이름 ret_value['virus_id'] = mid # 악성코드 ID ret_value['scan_state'] = scan_state # 악성코드 검사 상태 ret_value['file_struct'] = t_file_info # 검사 파일 이름 # 격리 시점 체크하기? if move_master_file: if t_master_file != t_file_info.get_master_filename(): # print 'move 2 :', t_master_file self.__quarantine_file(t_master_file) move_master_file = False if ret_value['result']: # 악성코드 발견인가? if isinstance(scan_callback_fn, types.FunctionType): action_type = scan_callback_fn(ret_value) if self.options['opt_move']: if t_file_info.get_additional_filename() == '': # print 'move 1 :', t_file_info.get_master_filename() self.__quarantine_file( t_file_info.get_master_filename()) move_master_file = False else: move_master_file = True t_master_file = t_file_info.get_master_filename( ) else: # 격리 옵션이 치료 옵션보다 우선 적용 if action_type == k2const.K2_ACTION_QUIT: # 종료인가? return 0 self.__disinfect_process( ret_value, action_type) # 악성코드 치료 후 해당 파일이 삭제되지 않고 존재한다면 다시 검사 필요 if self.options[ 'opt_dis']: # 치료 옵션이 존재할때에만... 실행 if os.path.exists( t_file_info.get_filename()): t_file_info.set_modify(True) file_scan_list = [t_file_info ] + file_scan_list else: # 압축 파일 최종 치료 처리 self.__update_process(t_file_info) else: if self.options['opt_list']: # 모든 리스트 출력인가? if isinstance(scan_callback_fn, types.FunctionType): scan_callback_fn(ret_value) # 압축 파일 최종 치료 처리 self.__update_process(t_file_info) # 이미 해당 파일이 악성코드라고 판명되었다면 # 그 파일을 압축해제해서 내부를 볼 필요는 없다. # 압축 파일이면 검사대상 리스트에 추가 arc_file_list = self.arclist(t_file_info, ff) if len(arc_file_list): file_scan_list = arc_file_list + file_scan_list except KeyboardInterrupt: return 1 # 키보드 종료 self.__update_process(None, True) # 최종 파일 정리 # 격리 시점 체크하기? if move_master_file: # print 'move 3 :', t_master_file self.__quarantine_file(t_master_file) move_master_file = False return 0 # 정상적으로 검사 종료
def scan(self, filename, *callback): import kernel self.update_info = [] scan_callback_fn = None move_master_file = False t_master_file = '' ret_value = { 'filename': '', 'result': False, 'virus_name': '', 'virus_id': -1, 'engine_id': -1 } try: scan_callback_fn = callback[0] self.disinfect_callback_fn = callback[1] self.update_callback_fn = callback[2] self.quarantine_callback_fn = callback[3] except IndexError: pass file_info = k2file.FileStruct(filename) file_scan_list = [file_info] is_sub_dir_scan = True while len(file_scan_list): try: t_file_info = file_scan_list.pop(0) real_name = t_file_info.get_filename() if os.path.isdir(real_name): real_name = os.path.abspath(real_name) ret_value['result'] = False ret_value['filename'] = real_name ret_value['file_struct'] = t_file_info ret_value['scan_state'] = kernel.NOT_FOUND self.result['Folders'] += 1 if self.options['opt_list']: self.call_scan_callback_fn(scan_callback_fn, ret_value) if is_sub_dir_scan: flist = glob.glob1(real_name, '*') tmp_flist = [] for rfname in flist: rfname = os.path.join(real_name, rfname) tmp_info = k2file.FileStruct(rfname) tmp_flist.append(tmp_info) file_scan_list = tmp_flist + file_scan_list if self.options['opt_nor']: is_sub_dir_scan = False elif os.path.isfile(real_name) or t_file_info.is_archive(): self.result['Files'] += 1 if real_name == '': ret, ret_fi = self.unarc(t_file_info) if ret: t_file_info = ret_fi else: if ret_fi: ret_value['result'] = ret ret_value['engine_id'] = -1 ret_value['virus_name'] = ret_fi ret_value['virus_id'] = -1 ret_value['scan_state'] = kernel.ERROR ret_value['file_struct'] = t_file_info if self.options['opt_list']: self.call_scan_callback_fn( scan_callback_fn, ret_value) continue if self.options['opt_debug']: ret_value['result'] = False ret_value['engine_id'] = -1 ret_value['virus_name'] = 'debug' ret_value['virus_id'] = -1 ret_value['scan_state'] = kernel.ERROR ret_value['file_struct'] = t_file_info self.call_scan_callback_fn(scan_callback_fn, ret_value) ff = self.format(t_file_info) ret, vname, mid, scan_state, eid = self.__scan_file( t_file_info, ff) if self.options['opt_feature'] != 0xffffffff: self.__feature_file(t_file_info, ff, self.options['opt_feature']) if ret: if scan_state == kernel.INFECTED: self.result['Infected_files'] += 1 elif scan_state == kernel.SUSPECT: self.result['Suspect_files'] += 1 elif scan_state == kernel.WARNING: self.result['Warnings'] += 1 self.identified_virus.update([vname]) ret_value['result'] = ret ret_value['engine_id'] = eid ret_value['virus_name'] = vname ret_value['virus_id'] = mid ret_value['scan_state'] = scan_state ret_value['file_struct'] = t_file_info if move_master_file: if t_master_file != t_file_info.get_master_filename(): self.__arcclose() self.__quarantine_file(t_master_file) move_master_file = False if ret_value['result']: t_master_file = t_file_info.get_master_filename() if not self.quarantine_name.get(t_master_file, None): self.quarantine_name[t_master_file] = ret_value[ 'virus_name'] action_type = self.call_scan_callback_fn( scan_callback_fn, ret_value) if self.options['opt_move'] or self.options['opt_copy']: if t_file_info.get_additional_filename() == '': self.__arcclose() self.__quarantine_file(t_master_file) move_master_file = False else: move_master_file = True else: if action_type == k2const.K2_ACTION_QUIT: return 0 d_ret = self.__disinfect_process( ret_value, action_type) if d_ret: if self.options['opt_dis'] or \ (action_type == k2const.K2_ACTION_DISINFECT or action_type == k2const.K2_ACTION_DELETE): if os.path.exists( t_file_info.get_filename()): t_file_info.set_modify(True) file_scan_list = [t_file_info ] + file_scan_list else: self.__update_process(t_file_info) else: self.__update_process(t_file_info) try: arc_file_list = self.arclist(t_file_info, ff) if len(arc_file_list): file_scan_list = arc_file_list + file_scan_list except zipfile.BadZipfile: pass if self.options['opt_list']: self.call_scan_callback_fn(scan_callback_fn, ret_value) except KeyboardInterrupt: return 1 except: if k2const.K2DEBUG: import traceback print traceback.format_exc() pass self.__update_process(None, True) if move_master_file: self.__arcclose() self.__quarantine_file(t_master_file) move_master_file = False return 0
def arclist(self, file_struct, fileformat): import kernel file_scan_list = [] rname = file_struct.get_filename() deep_name = file_struct.get_additional_filename() mname = file_struct.get_master_filename() level = file_struct.get_level() for inst in self.kavmain_inst: is_archive_engine = False can_arc = kernel.MASTER_IGNORE try: ret_getinfo = inst.getinfo() if 'engine_type' in ret_getinfo: if ret_getinfo['engine_type'] == kernel.ARCHIVE_ENGINE: is_archive_engine = True if 'make_arc_type' in ret_getinfo: can_arc = ret_getinfo['make_arc_type'] except AttributeError: pass try: arc_list = [] if self.options['opt_arc']: arc_list = inst.arclist(rname, fileformat) if len(arc_list) and is_archive_engine: self.result['Packed'] += 1 else: if not is_archive_engine: arc_list = inst.arclist(rname, fileformat) except AttributeError: pass if len(arc_list): for alist in arc_list: arc_id = alist[0] name = alist[1] if len(deep_name): try: deep_name1 = deep_name name1 = name if type(deep_name) != type(name): if isinstance(deep_name, unicode): name1 = name.decode('utf-8', 'ignore') elif isinstance(name, unicode): deep_name1 = deep_name.decode( 'utf-8', 'ignore') dname = '%s/%s' % (deep_name1, name1) except UnicodeDecodeError: continue else: dname = '%s' % name fs = k2file.FileStruct() fs.set_archive(arc_id, rname, name, dname, mname, False, can_arc, level + 1) file_scan_list.append(fs) return file_scan_list
def scan(self, filename, *callback): import kernel # 파일을 한 개씩 검사 요청할 경우 압축으로 인해 self.update_info 정보가 누적 된 경우 self.update_info = [] scan_callback_fn = None # 악성코드 검사 콜백 함수 move_master_file = False # 마스터 파일 격리 필요 여부 t_master_file = '' # 마스터 파일 # 악성코드 검사 결과 ret_value = { 'filename': '', # 파일 이름 'result': False, # 악성코드 발견 여부 'virus_name': '', # 발견된 악성코드 이름 'virus_id': -1, # 악성코드 ID 'engine_id': -1 # 악성코드를 발견한 플러그인 엔진 ID } try: # 콜백 함수 저장 scan_callback_fn = callback[0] self.disinfect_callback_fn = callback[1] self.update_callback_fn = callback[2] self.quarantine_callback_fn = callback[3] except IndexError: pass # 1. 검사 대상 리스트에 파일을 등록 file_info = k2file.FileStruct(filename) file_scan_list = [file_info] # 최초 한번만 하위 폴더 검색 is_sub_dir_scan = True while len(file_scan_list): try: t_file_info = file_scan_list.pop(0) # 검사 대상 파일 하나를 가짐 real_name = t_file_info.get_filename() # 폴더면 내부 파일리스트만 검사 대상 리스트에 등록 if os.path.isdir(real_name): # 폴더 등을 처리할 때를 위해 뒤에 붇는 os.sep는 우선 제거 real_name = os.path.abspath(real_name) # 콜백 호출 또는 검사 리턴값 생성 ret_value['result'] = False # 폴더이므로 악성코드 없음 ret_value['filename'] = real_name # 검사 파일 이름 ret_value['file_struct'] = t_file_info # 검사 파일 이름 ret_value['scan_state'] = kernel.NOT_FOUND # 악성코드 없음 self.result['Folders'] += 1 # 폴더 개수 카운트 if self.options['opt_list']: # 옵션 내용 중 모든 리스트 출력인가? self.call_scan_callback_fn(scan_callback_fn, ret_value) if is_sub_dir_scan: # 폴더 안의 파일들을 검사대상 리스트에 추가 flist = glob.glob(os.path.join(real_name, '*')) tmp_flist = [] for rfname in flist: tmp_info = k2file.FileStruct(rfname) tmp_flist.append(tmp_info) file_scan_list = tmp_flist + file_scan_list if self.options['opt_nor']: # 하위 폴더 검색 옵션이 체크 is_sub_dir_scan = False # 하위 폴더 검색 하지 않음 elif os.path.isfile(real_name) or t_file_info.is_archive(): # 검사 대상이 파일인가? 압축 해제 대상인가? self.result['Files'] += 1 # 파일 개수 카운트 # 압축된 파일이면 해제하기 if real_name == '': # 이미 실제 파일명이 존재하지 않으면 압축 파일임 ret, ret_fi = self.unarc(t_file_info) if ret: t_file_info = ret_fi # 압축 결과물이 존재하면 파일 정보 교체 else: # 압축 해제 오류 발생 if ret_fi: # 오류 메시지가 존재하는가? # 콜백 호출 또는 검사 리턴값 생성 ret_value['result'] = ret # 악성코드 발견 여부 ret_value['engine_id'] = -1 # 엔진 ID ret_value['virus_name'] = ret_fi # 에러 메시지로 대체 ret_value['virus_id'] = -1 # 악성코드 ID ret_value['scan_state'] = kernel.ERROR # 악성코드 검사 상태 ret_value['file_struct'] = t_file_info # 검사 파일 이름 if self.options['opt_list']: # 모든 리스트 출력인가? self.call_scan_callback_fn(scan_callback_fn, ret_value) continue # 비정상 종료의 파일을 찾기 위해 추가된 모드 if self.options['opt_debug']: # 디버깅 모드인가? ret_value['result'] = False # 악성코드 발견 여부 ret_value['engine_id'] = -1 # 엔진 ID ret_value['virus_name'] = 'debug' # 에러 메시지로 대체 ret_value['virus_id'] = -1 # 악성코드 ID ret_value['scan_state'] = kernel.ERROR # 악성코드 검사 상태 ret_value['file_struct'] = t_file_info # 검사 파일 이름 self.call_scan_callback_fn(scan_callback_fn, ret_value) # 2. 포맷 분석 ff = self.format(t_file_info) # 파일로 악성코드 검사 ret, vname, mid, scan_state, eid = self.__scan_file(t_file_info, ff) if self.options['opt_feature'] != 0xffffffff: # 인공지능 AI를 위한 Feature 추출 self.__feature_file(t_file_info, ff, self.options['opt_feature']) if ret: # 악성코드 진단 개수 카운트 if scan_state == kernel.INFECTED: self.result['Infected_files'] += 1 elif scan_state == kernel.SUSPECT: self.result['Suspect_files'] += 1 elif scan_state == kernel.WARNING: self.result['Warnings'] += 1 self.identified_virus.update([vname]) # 콜백 호출 또는 검사 리턴값 생성 ret_value['result'] = ret # 악성코드 발견 여부 ret_value['engine_id'] = eid # 엔진 ID ret_value['virus_name'] = vname # 악성코드 이름 ret_value['virus_id'] = mid # 악성코드 ID ret_value['scan_state'] = scan_state # 악성코드 검사 상태 ret_value['file_struct'] = t_file_info # 검사 파일 이름 # 격리 시점 체크하기? if move_master_file: if t_master_file != t_file_info.get_master_filename(): # print 'move 2 :', t_master_file self.__arcclose() self.__quarantine_file(t_master_file) move_master_file = False if ret_value['result']: # 악성코드 발견인가? t_master_file = t_file_info.get_master_filename() # 격리소에 생성시 악성코드 이름 부여할 경우 사용할 목적임 if not self.quarantine_name.get(t_master_file, None): self.quarantine_name[t_master_file] = ret_value['virus_name'] action_type = self.call_scan_callback_fn(scan_callback_fn, ret_value) if self.options['opt_move'] or self.options['opt_copy']: if t_file_info.get_additional_filename() == '': # print 'move 1 :', t_master_file self.__arcclose() self.__quarantine_file(t_master_file) move_master_file = False else: move_master_file = True else: # 격리 옵션이 치료 옵션보다 우선 적용 if action_type == k2const.K2_ACTION_QUIT: # 종료인가? return 0 d_ret = self.__disinfect_process(ret_value, action_type) if d_ret: # 치료 성공? # 악성코드 치료 후 해당 파일이 삭제되지 않고 존재한다면 다시 검사 필요 if self.options['opt_dis'] or \ (action_type == k2const.K2_ACTION_DISINFECT or action_type == k2const.K2_ACTION_DELETE): # 치료 옵션이 존재할때에만... 실행 if os.path.exists(t_file_info.get_filename()): t_file_info.set_modify(True) file_scan_list = [t_file_info] + file_scan_list else: # 압축 파일 최종 치료 처리 self.__update_process(t_file_info) else: # 압축 파일 최종 치료 처리 self.__update_process(t_file_info) # 이미 해당 파일이 악성코드라고 판명되었다면 # 그 파일을 압축해제해서 내부를 볼 필요는 없다. # 압축 파일이면 검사대상 리스트에 추가 try: arc_file_list = self.arclist(t_file_info, ff) if len(arc_file_list): file_scan_list = arc_file_list + file_scan_list ''' # 한 개의 정보가 추가되는 것 중에 /<...> 형태로 입력되는 파일이면 파일 카운트를 하지 않는다. if len(arc_file_list) == 1 and \ self.disable_path.search(arc_file_list[0].get_additional_filename()): self.result['Files'] -= 1 # 파일 개수 카운트 ''' except zipfile.BadZipfile: # zip 헤더 오류 pass # 검사 결과 출력하기 if self.options['opt_list']: # 모든 리스트 출력인가? self.call_scan_callback_fn(scan_callback_fn, ret_value) except KeyboardInterrupt: return 1 # 키보드 종료 except: if k2const.K2DEBUG: import traceback print traceback.format_exc() pass self.__update_process(None, True) # 최종 파일 정리 # 격리 시점 체크하기? if move_master_file: # print 'move 3 :', t_master_file self.__arcclose() self.__quarantine_file(t_master_file) move_master_file = False return 0 # 정상적으로 검사 종료