예제 #1
0
    def format(self, filehandle, filename, filename_ex):
        ret = {}

        mm = filehandle

        if mm[:8] == '\xD0\xCF\x11\xE0\xA1\xB1\x1A\xE1':  # OLE 헤더와 동일
            o = None
            try:
                o = ole.OleFile(filename)
                if '\x01Ole10Native' in o.listdir():
                    pics = o.openstream('\x01Ole10Native')
                    buf = pics.read()

                    if self.verbose:
                        print '-' * 79
                        kavutil.vprint('Engine')
                        kavutil.vprint(None, 'Engine', 'olenative.kmd')
                        kavutil.vprint(None, 'File name',
                                       os.path.split(filename)[-1])

                    fileformat = analysis_ole10native(buf, self.verbose)
                    if fileformat:
                        ret = {'ff_ole10native': fileformat}
            except ole.Error:
                pass

            if o:
                o.close()

        return ret
예제 #2
0
    def format(self, filehandle, filename, filename_ex):
        fileformat = {}  # 포맷 정보를 담을 공간
        ret = {}

        mm = filehandle

        if mm[:8] == '\xD0\xCF\x11\xE0\xA1\xB1\x1A\xE1':  # OLE 헤더와 동일
            o = None
            try:
                o = ole.OleFile(filename)
                pics = o.openstream('FileHeader')
                data = pics.read()
                if data[:0x11] == 'HWP Document File':
                    ret['ff_hwp'] = 'HWP'
            except ole.Error:
                pass

            if o:
                o.close()

        # HWP 파일 내부에 첨부된 OLE 파일인가?
        if self.hwp_ole.search(filename_ex):
            ret['ff_hwp_ole'] = 'HWP_OLE'

        return ret
예제 #3
0
    def arclist(self, filename, fileformat):
        file_scan_list = []  # 검사 대상 정보를 모두 가짐

        # 미리 분석된 파일 포맷중에 HWP 파일 포맷이 있는가?
        if 'ff_hwp' in fileformat:
            # OLE Stream 목록 추출하기
            o = ole.OleFile(filename)
            for name in o.listdir():
                file_scan_list.append(['arc_hwp', name])
            o.close()
        elif 'ff_hwp_ole' in fileformat:  # HWP 파일 내부에 포함된 OLE 파일?
            file_scan_list.append(['arc_hwp_ole', 'Embedded'])

        return file_scan_list
예제 #4
0
    def unarc(self, arc_engine_id, arc_name, fname_in_arc):
        data = None

        if arc_engine_id == 'arc_hwp':
            o = ole.OleFile(arc_name)
            fp = o.openstream(fname_in_arc)
            data = fp.read()
            o.close()
        elif arc_engine_id == 'arc_hwp_ole':
            with open(arc_name, 'rb') as fp:
                buf = fp.read()

            try:
                buf = zlib.decompress(buf, -15)
            except zlib.error:
                pass

            if kavutil.get_uint32(buf, 0) == len(buf[4:]):
                data = buf[4:]

        return data
예제 #5
0
def cure_office_macro(filename, malware_id):
    cure_macro_ref = {
        MALWARE_ID_WORD95: (None, 'WordDocument', cure_word95_macro),
        MALWARE_ID_WORD97: ('Macros', 'WordDocument', cure_word97_macro),
        MALWARE_ID_EXCEL95: ('_VBA_PROJECT', 'Book', cure_excel95_macro),
        MALWARE_ID_EXCEL97:
        ('_VBA_PROJECT_CUR', 'Workbook', cure_excel97_macro),
        MALWARE_ID_EXCEL_FORMULA97: (None, 'Workbook', cure_excel97_formula),
    }

    ret = False
    try:
        o = ole.OleFile(filename, write_mode=True)
        ole_lists = o.listdir(streams=True, storages=True)

        for name in ole_lists:
            pps = name.split('/')
            if cure_macro_ref[malware_id][0] and pps[-1] == cure_macro_ref[
                    malware_id][0]:
                o.delete(name)
            elif pps[-1] == cure_macro_ref[malware_id][1]:
                pics = o.openstream(name)
                t_data = pics.read()
                t_ret, t_data = cure_macro_ref[malware_id][2](t_data,
                                                              verbose=True)

                if t_ret:
                    o.write_stream(name, t_data)
                    ret = True
                else:
                    ret = False
        o.close()
    except IOError:
        pass

    return ret
예제 #6
0
    def unarc(self, arc_engine_id, arc_name, fname_in_arc):
        if arc_engine_id.find('arc_ole10native:') != -1:
            val = arc_engine_id.split(':')
            off = int(val[1])
            size = int(val[2])

            data = None
            o = None
            try:
                o = ole.OleFile(arc_name)
                if '\x01Ole10Native' in o.listdir():
                    pics = o.openstream('\x01Ole10Native')
                    buf = pics.read()

                    data = buf[off:]
            except ole.Error:
                pass

            if o:
                o.close()

            return data

        return None
예제 #7
0
    def scan(self, filehandle, filename, fileformat, filename_ex):  # 악성코드 검사
        mm = filehandle
        o = None

        try:
            # 미리 분석된 파일 포맷중에 OLE 포맷이 있는가?
            if 'ff_ole' in fileformat:
                o = ole.OleFile(filename)

                # 취약점 공격인가?
                if len(o.exploit):
                    if o:
                        o.close()

                    return True, o.exploit[0], MALWARE_ID_OLE, kernel.INFECTED

                ole_lists = o.listdir()

                for pps_name in ole_lists:
                    if pps_name.lower().find(
                            '/vba/dir') != -1:  # 오피스 97 매크로 존재 여부
                        pics = o.openstream(pps_name)
                        data = pics.read()
                        ret, decom_data = decompress(data)  # dir 스트림 압축 해제
                        if ret:
                            vba_modules = analysis_dir_stream(decom_data)

                            t = pps_name.split('/')

                            for vba in vba_modules:
                                t[-1] = vba[0]
                                t_pps_name = '/'.join(t)

                                t_pics = o.openstream(
                                    t_pps_name)  # 매크로가 존재하는 스트림 열기
                                t_data = t_pics.read()

                                if len(t_data) == 0:  # 데이터가 없으면 다음 vba 체크
                                    continue

                                t_ret, buf = decompress(
                                    t_data[vba[1]:])  # 매크로 소스코드 획득 완료
                                buf = buf.replace('\r\n', '\n')

                                if t_ret:
                                    if self.verbose:
                                        # 매크로 소스코드 출력
                                        kavutil.vprint('Macro Source')
                                        kavutil.vprint(None, 'PPS',
                                                       '%s' % t_pps_name)
                                        print buf

                                    buf = self.p_vba_cmt.sub('', buf)  # 주석문 제거
                                    buf = buf.lower()  # 영어 소문자로 통일

                                    key_words = self.p_vba_word.findall(buf)

                                    vba_keyword_crc32 = set()
                                    for i in range(len(key_words) - 1):
                                        word = key_words[i] + key_words[i + 1]
                                        c = zlib.crc32(word) & 0xffffffffL
                                        vba_keyword_crc32.add(c)

                                    # 테스트
                                    if self.verbose:
                                        max_len = len(key_words[0])

                                        t_word = []
                                        for i in range(len(key_words) - 1):
                                            word = key_words[i] + key_words[i +
                                                                            1]
                                            c = zlib.crc32(word) & 0xffffffffL
                                            t_word.append([
                                                c, key_words[i],
                                                key_words[i + 1]
                                            ])

                                            if len(key_words[i + 1]) > max_len:
                                                max_len = len(key_words[i + 1])

                                        t_l = '+-' + ('-' * 8) + '-+-' + (
                                            '-' * max_len) + '-+-' + (
                                                '-' * max_len) + '-+'
                                        print t_l
                                        msg = '| %%-8s | %%-%ds | %%-%ds |' % (
                                            max_len, max_len)
                                        print msg % ('CRC32', 'Keyword #1',
                                                     'Keyword #2')
                                        print t_l

                                        msg = '| %%08X | %%-%ds | %%-%ds |' % (
                                            max_len, max_len)
                                        for n in t_word:
                                            print msg % (n[0], n[1], n[2])

                                        print t_l

                                    # Heuristic 검사
                                    for macro_crc in self.word97_macro_crcs:
                                        if macro_crc.issubset(
                                                vba_keyword_crc32):
                                            if o:
                                                o.close()
                                            return True, 'Virus.MSWord.Generic', MALWARE_ID_WORD97, kernel.SUSPECT

        except IOError:
            pass
        except ole.Error:
            pass

        if o:
            o.close()

        # 악성코드를 발견하지 못했음을 리턴한다.
        return False, '', -1, kernel.INFECTED