Skip to content

Commit

Permalink
Release 0.31
Browse files Browse the repository at this point in the history
  • Loading branch information
hanul93 committed Jun 18, 2018
2 parents bd3b015 + f7be082 commit 895209e
Show file tree
Hide file tree
Showing 26 changed files with 3,961 additions and 140 deletions.
32 changes: 29 additions & 3 deletions CHANGELOG.md
@@ -1,4 +1,30 @@
## v0.30 (May 07, 2018)
## v0.30 (Jun 18, 2018)

* **Plugins Modules :**
* cab: Improved speed for cab file extract
* dde: Added a CVE-2017-0199 pattern
* egg: Fixed the problem that file name inside egg file is broken
* emalware: Added a Worm.Win32.Allaple.gen pattern
* html: Added scan function for Trojan.HTML.IFrame.a
* ishield: New support
* macro: Fixed parse of dir_referencesrecord
* ole: Added extraction of Ole's attach data
* olenative: Fixed a _OleNative Stream name
* pe: Fixed missing import API names
* pe: Fixed check to resource size
* rar: New support
* ve: Added New scan areas
* ve: Fixed crc32 of base offset
* yaraex: Fixed detect yara rule name
* yaraex: Fixed malware detection against yaraex.yar
* zip: Added 7z archive

* **Command Line Interface :**
* k2: Added New status (IDENTIFIED)
* k2: Added New options (--copy, --qname)
* k2: Fixed file name assembly

## v0.30 (Mar 07, 2018)

* **Engine :**
* k2engine: Changed WindowsError exception handling to OSError exception handling
Expand Down Expand Up @@ -41,12 +67,12 @@
* k2file: Add a class to process temporary folders by process

* **Plugins Modules :**
* adware: new support
* adware: New support
* attach: process to add size information of an attached image to newly extract an attached image
* bz: New support
* carch: New support
* dde: New support
* egg: new support
* egg: New support
* elf: verbose processing on ELF 64bit
* emalware: Handle MD5 calculations if section size is 0
* emalware: Handle malicious code in addition to .text area
Expand Down
43 changes: 35 additions & 8 deletions Engine/k2.py
Expand Up @@ -15,6 +15,7 @@
try:
from backports import lzma
import yara
import py7zlib
except ImportError:
pass

Expand Down Expand Up @@ -47,8 +48,8 @@
# -------------------------------------------------------------------------
# 주요 상수
# -------------------------------------------------------------------------
KAV_VERSION = '0.30'
KAV_BUILDDATE = 'May 07 2018'
KAV_VERSION = '0.31'
KAV_BUILDDATE = 'Jun 18 2018'
KAV_LASTYEAR = KAV_BUILDDATE[len(KAV_BUILDDATE)-4:]

g_options = None # 옵션
Expand Down Expand Up @@ -308,6 +309,9 @@ def define_options():
default=False)
parser.add_option("-F", "--infp",
metavar="PATH", dest="infp_path")
parser.add_option("", "--qname", # 격리시 악성코드 이름 부여
action="store_true", dest="opt_qname",
default=False)
parser.add_option("-R", "--nor",
action="store_true", dest="opt_nor",
default=False)
Expand All @@ -329,6 +333,9 @@ def define_options():
parser.add_option("", "--move",
action="store_true", dest="opt_move",
default=False)
parser.add_option("", "--copy",
action="store_true", dest="opt_copy",
default=False)
parser.add_option("", "--update",
action="store_true", dest="opt_update",
default=False)
Expand Down Expand Up @@ -404,6 +411,7 @@ def print_options():
-l, --del delete infected files
--no-color don't print with color
--move move infected files in quarantine folder
--copy copy infected files in quarantine folder
--update update
--verbose enabling verbose mode (only Developer Edition)
--sigtool make files for malware signatures
Expand Down Expand Up @@ -639,8 +647,11 @@ def convert_display_filename(real_filename):
display_filename = real_filename.encode(sys.stdout.encoding, 'replace')
else:
display_filename = unicode(real_filename, fsencoding).encode(sys.stdout.encoding, 'replace')
return display_filename

if display_filename[0] == '/' or display_filename[0] == '\\':
return display_filename[1:]
else:
return display_filename

def display_line(filename, message, message_color):
max_sizex = get_terminal_sizex() - 1
Expand Down Expand Up @@ -679,23 +690,30 @@ def scan_callback(ret_value):
fs = ret_value['file_struct']

if len(fs.get_additional_filename()) != 0:
disp_name = '%s (%s)' % (fs.get_master_filename(), fs.get_additional_filename())
f2 = convert_display_filename(fs.get_additional_filename())
disp_name = '%s (%s)' % (fs.get_master_filename(), f2)
else:
disp_name = '%s' % (fs.get_master_filename())

if ret_value['result']:
if ret_value['scan_state'] == kernel.INFECTED:
state = 'infected'
message_color = FOREGROUND_RED | FOREGROUND_INTENSITY
elif ret_value['scan_state'] == kernel.SUSPECT:
state = 'suspect'
message_color = FOREGROUND_RED | FOREGROUND_INTENSITY
elif ret_value['scan_state'] == kernel.WARNING:
state = 'warning'
message_color = FOREGROUND_RED | FOREGROUND_INTENSITY
elif ret_value['scan_state'] == kernel.IDENTIFIED:
state = 'identified'
message_color = FOREGROUND_GREEN | FOREGROUND_INTENSITY
else:
state = 'unknown'
message_color = FOREGROUND_RED | FOREGROUND_INTENSITY

vname = ret_value['virus_name']
message = '%s : %s' % (state, vname)
message_color = FOREGROUND_RED | FOREGROUND_INTENSITY
else:
if ret_value['scan_state'] == kernel.ERROR:
message = ret_value['virus_name']
Expand Down Expand Up @@ -861,14 +879,23 @@ def update_callback(ret_file_info, is_success):
# -------------------------------------------------------------------------
# quarantine 콜백 함수
# -------------------------------------------------------------------------
def quarantine_callback(filename, is_success):
def quarantine_callback(filename, is_success, q_type):
import kernel

q_message = {
kavcore.k2const.K2_QUARANTINE_MOVE: ['quarantined', 'quarantine failed'],
kavcore.k2const.K2_QUARANTINE_COPY: ['copied', 'copy failed'],
}

msg = q_message[q_type]

disp_name = filename

if is_success:
message = 'quarantined'
message = msg[0] # 성공
message_color = FOREGROUND_GREEN | FOREGROUND_INTENSITY
else:
message = 'quarantine failed'
message = msg[1] # 실패
message_color = FOREGROUND_RED | FOREGROUND_INTENSITY

display_line(disp_name, message, message_color)
Expand Down
2 changes: 1 addition & 1 deletion Engine/kavcore/__init__.py
Expand Up @@ -2,4 +2,4 @@
# Author: Kei Choi(hanul93@gmail.com)


__version__ = '0.30'
__version__ = '0.31'
6 changes: 6 additions & 0 deletions Engine/kavcore/k2const.py
Expand Up @@ -15,3 +15,9 @@
K2_ACTION_DISINFECT = 1
K2_ACTION_DELETE = 2
K2_ACTION_QUIT = 3

# -------------------------------------------------------------------------
# 악성코드 격리 상태 관련 상수
# -------------------------------------------------------------------------
K2_QUARANTINE_MOVE = 0
K2_QUARANTINE_COPY = 1
61 changes: 49 additions & 12 deletions Engine/kavcore/k2engine.py
Expand Up @@ -52,7 +52,7 @@ def __init__(self, verbose=False):
# 플러그 엔진의 가장 최신 시간 값을 가진다.
# 초기값으로는 1980-01-01을 지정한다.
self.max_datetime = datetime.datetime(1980, 1, 1, 0, 0, 0, 0)

# 키콤백신이 만든 임시 파일 모두 제거 (운영체제의 임시 폴더를 초기화)
k2file.K2Tempfile().removetempdir()

Expand Down Expand Up @@ -256,6 +256,8 @@ def __init__(self, plugins_path, temp_path, max_datetime, verbose=False):
self.identified_virus = set() # 유니크한 악성코드 개수를 구하기 위해 사용
self.set_result() # 악성코드 검사 결과를 초기화한다.

self.quarantine_name = {} # 격리소로 파일 이동시 악성코드 이름 폴더로 이동시 사용

self.disinfect_callback_fn = None # 악성코드 치료 콜백 함수
self.update_callback_fn = None # 악성코드 압축 최종 치료 콜백 함수
self.quarantine_callback_fn = None # 악성코드 격리 콜백 함수
Expand Down Expand Up @@ -304,7 +306,7 @@ def init(self, callback_fn=None):
ret = inst.init(self.plugins_path, self.options['opt_verbose'])
else:
ret = inst.init(self.plugins_path, False)

if not ret: # 성공
t_kavmain_inst.append(inst)

Expand Down Expand Up @@ -552,17 +554,22 @@ def scan(self, filename, *callback):
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']:
if self.options['opt_move'] or self.options['opt_copy']:
if t_file_info.get_additional_filename() == '':
# print 'move 1 :', t_file_info.get_master_filename()
# print 'move 1 :', t_master_file
self.__arcclose()
self.__quarantine_file(t_file_info.get_master_filename())
self.__quarantine_file(t_master_file)
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
Expand Down Expand Up @@ -645,13 +652,26 @@ def call_scan_callback_fn(self, a_scan_callback_fn, ret_value):
# 입력값 : filename - 격리 대상 파일 이름
# ---------------------------------------------------------------------
def __quarantine_file(self, filename):
if self.options['infp_path']:
if self.options['infp_path'] and (self.options['opt_move'] or self.options['opt_copy']):
is_success = False

try:
if self.options['opt_qname']:
x = self.quarantine_name.get(filename, None)
if x:
q_path = os.path.join(self.options['infp_path'], x)
self.quarantine_name.pop(filename)
else:
q_path = self.options['infp_path']
else:
q_path = self.options['infp_path']

if not os.path.exists(q_path):
os.makedirs(q_path) # 다중 폴더 생성

t_filename = os.path.split(filename)[-1]
# 격리소에 동일한 파일 이름이 존재하는지 체크
fname = os.path.join(self.options['infp_path'], t_filename)
fname = os.path.join(q_path, t_filename)
t_quarantine_fname = fname
count = 1
while True:
Expand All @@ -661,13 +681,23 @@ def __quarantine_file(self, filename):
else:
break

shutil.move(filename, t_quarantine_fname) # 격리소로 이동
if self.options['opt_move']:
shutil.move(filename, t_quarantine_fname) # 격리소로 이동
elif self.options['opt_copy']:
shutil.copy(filename, t_quarantine_fname) # 격리소로 복사
q_type = k2const.K2_QUARANTINE_COPY

is_success = True
except (shutil.Error, OSError) as e:
pass

if isinstance(self.quarantine_callback_fn, types.FunctionType):
self.quarantine_callback_fn(filename, is_success)
if self.options['opt_copy']:
q_type = k2const.K2_QUARANTINE_COPY
else:
q_type = k2const.K2_QUARANTINE_MOVE

self.quarantine_callback_fn(filename, is_success, q_type)

# ---------------------------------------------------------------------
# __update_process(self, file_struct, immediately_flag=False)
Expand Down Expand Up @@ -915,7 +945,7 @@ def __scan_file(self, file_struct, fileformat):
if k2const.K2DEBUG:
import traceback
print traceback.format_exc()
raw_input('>>')
# raw_input('>>')
self.result['IO_errors'] += 1 # 파일 I/O 오류 발생 수

if mm:
Expand Down Expand Up @@ -1045,7 +1075,10 @@ def unarc(self, file_struct):
shutil.copy(rname, sig_fname)

# sigtool.log 파일을 생성한다.
msg = '%s : %s\n' % (sig_fname, rname_struct.get_additional_filename())
t = rname_struct.get_additional_filename()
if t[0] == '/' or t[0] == '\\':
t = t[1:]
msg = '%s : %s\n' % (sig_fname, t)
fp = open('sigtool.log', 'at')
fp.write(msg)
fp.close()
Expand Down Expand Up @@ -1213,23 +1246,27 @@ def set_options(self, options=None):
self.options['opt_nor'] = options.opt_nor
self.options['opt_list'] = options.opt_list
self.options['opt_move'] = options.opt_move
self.options['opt_copy'] = options.opt_copy
self.options['opt_dis'] = options.opt_dis
self.options['infp_path'] = options.infp_path
self.options['opt_verbose'] = options.opt_verbose
self.options['opt_sigtool'] = options.opt_sigtool
self.options['opt_debug'] = options.opt_debug
self.options['opt_feature'] = options.opt_feature
self.options['opt_qname'] = options.opt_qname
else: # 기본값 설정
self.options['opt_arc'] = False
self.options['opt_nor'] = False
self.options['opt_list'] = False
self.options['opt_move'] = False
self.options['opt_copy'] = False
self.options['opt_dis'] = False
self.options['infp_path'] = None
self.options['opt_verbose'] = False
self.options['opt_sigtool'] = False
self.options['opt_debug'] = False
self.options['opt_feature'] = 0xffffffff
self.options['opt_qname'] = False
return True

# -----------------------------------------------------------------
Expand Down

0 comments on commit 895209e

Please sign in to comment.