Beispiel #1
0
    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
Beispiel #2
0
    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
Beispiel #5
0
    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  # 정상적으로 검사 종료