Beispiel #1
0
    def feature(self, filehandle, filename, fileformat, filename_ex,
                malware_id):  # Feature 추출
        try:
            mm = filehandle

            # 미리 분석된 파일 포맷중에 PE 포맷이 있는가?
            if 'ff_pe' in fileformat:
                buf = mm[:]
                fmd5 = cryptolib.md5(buf).decode('hex')  # 파일 전체 MD5 생성
                header = 'PE\x00\x00' + struct.pack('<L', malware_id) + fmd5

                pe = PE(mm, False, filename)
                pe_format = pe.parse()
                if not pe_format:
                    return None

                pe_off = pe_format['PE_Position']  # pe.DOS_HEADER.e_lfanew
                ep = pe_format[
                    'EntryPoint']  # pe.OPTIONAL_HEADER.AddressOfEntryPoint

                text_off = 0
                text_size = 0

                for sec in pe_format['Sections']:  # pe.sections:
                    rva = sec['RVA']  # sec.VirtualAddress
                    vsize = sec['VirtualSize']  # sec.Misc_VirtualSize
                    if rva <= ep <= rva + vsize:
                        text_off = sec[
                            'PointerRawData']  # sec.PointerToRawData
                        text_size = sec['SizeRawData']  # sec.SizeOfRawData
                        break

                # Feature 추출
                f = kavutil.Feature()

                data = ''
                # 1. text 섹션에 대해서 엔트로피를 추출한다.
                data += f.entropy(mm[text_off:text_off + text_size])

                # 2. PE 헤더 정보를 추출한다.
                data += mm[pe_off + 6:pe_off + 6 + 256]

                # 3. DATA 섹션 2-gram 추출하기
                data_off = 0
                data_size = 0

                for sec in pe_format['Sections']:  # pe.sections:
                    if sec['Characteristics'] & 0x40000040 == 0x40000040:  # if DATA and Read
                        data_off = sec[
                            'PointerRawData']  # sec.PointerToRawData
                        data_size = sec['SizeRawData']  # sec.SizeOfRawData
                        break

                data += f.k_gram(mm[data_off:data_off + data_size], 2)

                # 4. Import API 해시 추가하기
                def import_api(l_pe_format):
                    api_hash = set()

                    l_data = ''

                    if 'Import_API' in l_pe_format:
                        imp_api = pe_format['Import_API']
                        # print imp_api

                        for dll in imp_api.keys():
                            for api in dll:
                                api_name = ('%s:%s' % (dll, api)).lower()
                                api_hash.add(
                                    struct.pack(
                                        '<H',
                                        cryptolib.CRC16().calculate(api_name)))

                        t = list(api_hash)
                        l_data = ''.join(t)

                    if len(l_data) < 256:
                        l_data += '\x00' * (256 - len(l_data))

                    return l_data[:256]

                data += import_api(pe_format)

                open('pe.bin', 'ab').write(header + data)  # Feature 파일 생성

                return True
        except IOError:
            pass

        # Feature 추출 실패했음을 리턴한다.
        return False
Beispiel #2
0
    def feature(self, filehandle, filename, fileformat, filename_ex,
                malware_id):  # Feature 추출
        try:
            mm = filehandle

            # 미리 분석된 파일 포맷중에 NSIS 포맷이 있는가?
            # 파일의 전체 영역에 대해 MD5를 구하기 위해 ff_attach를 확인한다.
            if 'ff_attach' in fileformat:
                foff = fileformat['ff_attach']['Attached_Pos']

                # NSIS가 맞나?
                if mm[foff + 4:foff + 20] == '\xEF\xBE\xAD\xDENullsoftInst':
                    buf = mm[:]
                    fmd5 = cryptolib.md5(buf).decode('hex')  # 파일 전체 MD5 생성
                    header = 'NSIS' + struct.pack('<L', malware_id) + fmd5

                    rname = tempfile.mktemp(prefix='ktmp')
                    open(rname, 'wb').write(mm[foff:])

                    max_len = 0
                    max_extract_data = ''  # 용량이 큰 파일

                    n = NSIS(rname, False)
                    if n.parse() is False:
                        n.close()
                        return False

                    for name in n.namelist():
                        data = n.read(name)
                        if data is None:
                            continue

                        data_len = len(data)
                        if max_len < data_len:
                            max_len = data_len
                            max_extract_data = data

                    # Feature 추출
                    f = kavutil.Feature()

                    data = ''
                    # 1. NSIS 내부 파일 중 용량이 제일 큰 파일을 찾아 엔트로피를 추출한다.
                    data += f.entropy(max_extract_data)

                    # 2. NSIS 헤더 정보를 추출한다.
                    data += n.nsis_header.header_data[:256]

                    # 3. NSIS 헤더의 문자열을 추출 후 2-gram 처리한다.
                    data += f.k_gram(n.nsis_header.header_data, 2)

                    # 4. NSIS 스크립트의 OPcode를 추출한다.
                    t = [0] * 256
                    off = n.nsis_header.nh.entries

                    for i in range(n.nsis_header.nh.entries_num):
                        nr = StructNsisRecord()
                        memmove(addressof(nr), n.nsis_header.header_data[off:],
                                sizeof(nr))
                        off += sizeof(nr)

                        if t[nr.which & 0xff] < 0xff:
                            t[nr.which & 0xff] += 1  # Opcode 등장 회수를 누적

                    data += ''.join(map(chr, t))
                    n.close()

                    open('nsis.bin',
                         'ab').write(header + data)  # Feature 파일 생성
                    os.remove(rname)

                    return True
        except IOError:
            pass

        # Feature 추출 실패했음을 리턴한다.
        return False