Ejemplo n.º 1
0
    def read(self, filename):
        if filename in self.nsis_header.files:
            data = None
            (foff, ftime, extract_type) = self.nsis_header.files[filename]

            if self.case_type == 1:  # case 1: 설치 파일 전부를 압축한 경우
                # print '#Case 1'
                # print hex(foff)
                # print hex(kavutil.get_uint32(self.body_data, foff) & 0x7fffffff)
                fsize = kavutil.get_uint32(self.body_data, foff) & 0x7fffffff
                return self.body_data[foff+4:foff+4+fsize]
            elif self.case_type == 2:  # case 2: 개별로 압축한 경우
                # print '#Case 2'
                # print hex(foff)
                # print hex(kavutil.get_uint32(self.body_data, foff) & 0x7fffffff)
                fsize = kavutil.get_uint32(self.body_data, foff) & 0x7fffffff
                fdata = self.body_data[foff+4:foff+4+fsize]
                comp_type = self.__get_comp_type(kavutil.get_uint32(fdata, 0))
                # print comp_type
                if comp_type == self.TYPE_LZMA:
                    try:  # 전체 압축한 경우인지 확인해 본다.
                        data = pylzma.decompress(fdata)
                    except TypeError:
                        pass
                elif comp_type == self.TYPE_ZLIB:
                    try:
                        data = zlib.decompress(fdata, -15)
                    except zlib.error:
                        pass
            return data
        else:
            return None
Ejemplo n.º 2
0
    def parse(self):
        try:
            self.fp = open(self.fname, 'rb')
            self.fsize = os.fstat(self.fp.fileno()).st_size

            cur_pos = 0

            # Magic 체크
            if self.fp.read(0xe) != 'InstallShield\x00':
                raise ValueError

            cur_pos += 0xe

            # InstallShield에 첨부된 파일 수
            data = self.fp.read(0x20)
            num_file = kavutil.get_uint32(data, 0)

            cur_pos += 0x20

            for i in range(num_file):
                data = self.fp.read(0x138)
                fname = data[:0x10b].replace('\x00', '')
                fsize = kavutil.get_uint32(data, 0x10c)
                foff = cur_pos + 0x138
                self.install_name.append((foff, fsize, fname))

                cur_pos += 0x138 + fsize
                self.fp.seek(cur_pos)

            return True
        except (IOError, OSError, ValueError) as e:
            pass

        return False
Ejemplo n.º 3
0
    def read(self, filename):
        if filename in self.nsis_header.files:
            data = None
            (foff, ftime, extract_type) = self.nsis_header.files[filename]

            if self.case_type == 1:  # case 1: 설치 파일 전부를 압축한 경우
                # print '#Case 1'
                # print hex(foff)
                # print hex(kavutil.get_uint32(self.body_data, foff) & 0x7fffffff)
                fsize = kavutil.get_uint32(self.body_data, foff) & 0x7fffffff
                return self.body_data[foff + 4:foff + 4 + fsize]
            elif self.case_type == 2:  # case 2: 개별로 압축한 경우
                # print '#Case 2'
                # print hex(foff)
                # print hex(kavutil.get_uint32(self.body_data, foff) & 0x7fffffff)
                fsize = kavutil.get_uint32(self.body_data, foff) & 0x7fffffff
                fdata = self.body_data[foff + 4:foff + 4 + fsize]
                comp_type = self.__get_comp_type(kavutil.get_uint32(fdata, 0))
                # print comp_type
                if comp_type == self.TYPE_LZMA:
                    try:  # 전체 압축한 경우인지 확인해 본다.
                        data = pylzma.decompress(fdata)
                    except TypeError:
                        pass
                elif comp_type == self.TYPE_ZLIB:
                    try:
                        data = zlib.decompress(fdata, -15)
                    except zlib.error:
                        pass
            return data
        else:
            return None
Ejemplo n.º 4
0
    def __EGG_Header__(self, data):
        try:
            # magic = struct.unpack('<L', data[0:4])[0]
            magic = kavutil.get_uint32(data, 0)
            if magic != 0x41474745:
                raise SystemError

            # version = struct.unpack('<H', data[4:6])[0]
            version = kavutil.get_uint16(data, 4)
            if version != 0x0100:
                raise SystemError

            # header_id = struct.unpack('<L', data[6:10])[0]
            header_id = kavutil.get_uint32(data, 6)
            if header_id == 0:
                raise SystemError

            # reserved = struct.unpack('<L', data[10:14])[0]
            reserved = kavutil.get_uint32(data, 10)
            if reserved != 0:
                raise SystemError

            return 0
        except SystemError:
            pass

        return -1
Ejemplo n.º 5
0
    def unarc(self, arc_engine_id, arc_name, fname_in_arc):
        if arc_engine_id == 'arc_icon':
            mm = self.__get_handle(arc_name)
            num = kavutil.get_uint16(mm, 4)

            p = p_name.search(fname_in_arc)
            if p:
                fw = int(p.groups()[0])
                fh = int(p.groups()[1])
                # fc = int(p.groups()[2])

                for i in range(num):
                    off = 6 + (16 * i)
                    w = ord(mm[off])
                    h = ord(mm[off + 1])
                    # c = kavutil.get_uint16(mm, off+6)

                    if w == fw and h == fh:  # and c == fc:
                        img_size = kavutil.get_uint32(mm, off + 8)
                        img_off = kavutil.get_uint32(mm, off + 12)
                        data = mm[img_off:img_off + img_size]

                        return data

        return None
Ejemplo n.º 6
0
    def __ReadBlockData__(self):
        egg_pos = self.egg_pos
        mm = self.mm
        data_size = self.data_size

        try:
            while egg_pos < data_size:
                # magic = struct.unpack('<L', mm[egg_pos:egg_pos+4])[0]
                magic = kavutil.get_uint32(mm, egg_pos)

                if magic == 0x02B50C13:  # Block Header
                    # print 'Block Header'
                    size = self.__EGG_Block_Header_Size__(mm[egg_pos:])
                    if size == -1:
                        raise SystemError

                    compress__method__m = ord(mm[egg_pos + 4])
                    # Compress_Method_H = ord(mm[egg_pos+5])
                    # Uncompress_Size = struct.unpack('<L', mm[egg_pos+6:egg_pos+10])[0]
                    # compress__size = struct.unpack('<L', mm[egg_pos+10:egg_pos+14])[0]
                    compress__size = kavutil.get_uint32(mm, egg_pos + 10)
                    # CRC = struct.unpack('<L', mm[egg_pos+14:egg_pos+18])[0]
                    compressed__data = mm[egg_pos + 22:egg_pos + 22 +
                                          compress__size]
                    egg_pos += size
                    return compressed__data, compress__method__m, egg_pos
                else:
                    egg_pos = self.__DefaultMagicIDProc__(magic, egg_pos)
                    if egg_pos == -1:
                        raise SystemError
        except SystemError:
            pass

        return None, -1, -1
Ejemplo n.º 7
0
    def __EGG_Header__(self, data):
        try:
            # magic = struct.unpack('<L', data[0:4])[0]
            magic = kavutil.get_uint32(data, 0)
            if magic != 0x41474745:
                raise SystemError

            # version = struct.unpack('<H', data[4:6])[0]
            version = kavutil.get_uint16(data, 4)
            if version != 0x0100:
                raise SystemError

            # header_id = struct.unpack('<L', data[6:10])[0]
            header_id = kavutil.get_uint32(data, 6)
            if header_id == 0:
                raise SystemError

            # reserved = struct.unpack('<L', data[10:14])[0]
            reserved = kavutil.get_uint32(data, 10)
            if reserved != 0:
                raise SystemError

            return 0
        except SystemError:
            pass

        return -1
Ejemplo n.º 8
0
def scan_hwp_recoard(buf, lenbuf):
    pos = 0
    tagid = 0

    while pos < lenbuf:
        extra_size = 4
        val = kavutil.get_uint32(buf, pos)
        tagid, level, size = get_hwp_recoard(val)

        if size == 0xfff:
            extra_size = 8
            size = kavutil.get_uint32(buf, pos + 4)

        if tagid == 0x43 and size > 4000:  # PARA_TEXT
            t_buf = buf[pos:pos+size+extra_size]
            d_buf = zlib.compress(t_buf)
            if len(d_buf) / float(len(t_buf)) < 0.02:
                return False, 0x43

        pos += (size + extra_size)

    if pos == lenbuf:
        return True, -1

    return False, tagid
Ejemplo n.º 9
0
def scan_hwp_recoard(buf, lenbuf):
    pos = 0
    tagid = 0

    while pos < lenbuf:
        extra_size = 4
        val = kavutil.get_uint32(buf, pos)
        tagid, level, size = get_hwp_recoard(val)

        if size == 0xfff:
            extra_size = 8
            size = kavutil.get_uint32(buf, pos + 4)

        if tagid == 0x43 and size > 4000:  # PARA_TEXT
            t_buf = buf[pos:pos+size+extra_size]
            d_buf = zlib.compress(t_buf)
            if len(d_buf) / float(len(t_buf)) < 0.02:
                return False, 0x43

        pos += (size + extra_size)

    if pos == lenbuf:
        return True, -1

    return False, tagid
Ejemplo n.º 10
0
    def __ReadBlockData__(self):
        egg_pos = self.egg_pos
        mm = self.mm
        data_size = self.data_size

        try:
            while egg_pos < data_size:
                # magic = struct.unpack('<L', mm[egg_pos:egg_pos+4])[0]
                magic = kavutil.get_uint32(mm, egg_pos)

                if magic == 0x02B50C13:  # Block Header
                    # print 'Block Header'
                    size = self.__EGG_Block_Header_Size__(mm[egg_pos:])
                    if size == -1:
                        raise SystemError

                    compress__method__m = ord(mm[egg_pos+4])
                    # Compress_Method_H = ord(mm[egg_pos+5])
                    # Uncompress_Size = struct.unpack('<L', mm[egg_pos+6:egg_pos+10])[0]
                    # compress__size = struct.unpack('<L', mm[egg_pos+10:egg_pos+14])[0]
                    compress__size = kavutil.get_uint32(mm, egg_pos+10)
                    # CRC = struct.unpack('<L', mm[egg_pos+14:egg_pos+18])[0]
                    compressed__data = mm[egg_pos+22:egg_pos+22+compress__size]
                    egg_pos += size
                    return compressed__data, compress__method__m, egg_pos
                else:
                    egg_pos = self.__DefaultMagicIDProc__(magic, egg_pos)
                    if egg_pos == -1:
                        raise SystemError
        except SystemError:
            pass

        return None, -1, -1
Ejemplo n.º 11
0
def analysis_ole10native(mm, verbose=False):
    fileformat = {}

    try:
        size = kavutil.get_uint32(mm, 0)

        if mm[4:6] == '\x02\x00':
            if len(mm) == size + 4:
                fileformat['size'] = len(mm)  # 포맷 주요 정보 저장

                label = mm[6:6 + MAX_PATH].split('\x00', 1)[0]
                fileformat['label'] = label

                off = 6 + len(label) + 1
                fname = mm[off:off + MAX_PATH].split('\x00', 1)[0]

                off += len(fname) + 1
                off += 2  # flag

                unknown_size = ord(mm[off])
                off += 1 + unknown_size + 2

                command = mm[off:off + MAX_PATH].split('\x00', 1)[0]
                off += len(command) + 1

                data_size = kavutil.get_uint32(mm, off)

                fileformat['data_off'] = off + 4
                fileformat['data_size'] = data_size

                if len(mm) < off + data_size:  # 오류
                    raise ValueError

                if verbose:
                    print
                    kavutil.vprint('Ole10Native Stream')
                    kavutil.vprint(None, 'Size', '0x%08X' % size)
                    kavutil.vprint(None, 'Label', label)
                    kavutil.vprint(None, 'File Name', fname)
                    kavutil.vprint(None, 'Command Line', command)
                    kavutil.vprint(None, 'Data Offset', '0x%08X' % (off + 4))
                    kavutil.vprint(None, 'Data Size', '0x%08X' % data_size)

                    print
                    kavutil.vprint('Data Dump')
                    print
                    kavutil.HexDump().Buffer(mm[:], off + 4, 0x80)
                    print

                return fileformat
    except ValueError:
        pass
    except struct.error:
        pass

    return None
Ejemplo n.º 12
0
def analysis_ole10native(mm, verbose=False):
    fileformat = {}

    try:
        size = kavutil.get_uint32(mm, 0)

        if mm[4:6] == '\x02\x00':
            if len(mm) == size + 4:
                fileformat['size'] = len(mm)  # 포맷 주요 정보 저장

                label = mm[6:6 + MAX_PATH].split('\x00', 1)[0]
                fileformat['label'] = label

                off = 6 + len(label) + 1
                fname = mm[off:off + MAX_PATH].split('\x00', 1)[0]

                off += len(fname) + 1
                off += 2  # flag

                unknown_size = ord(mm[off])
                off += 1 + unknown_size + 2

                command = mm[off:off + MAX_PATH].split('\x00', 1)[0]
                off += len(command) + 1

                data_size = kavutil.get_uint32(mm, off)

                fileformat['data_off'] = off + 4
                fileformat['data_size'] = data_size

                if len(mm) < off + data_size:  # 오류
                    raise ValueError

                if verbose:
                    print
                    kavutil.vprint('Ole10Native Stream')
                    kavutil.vprint(None, 'Size', '0x%08X' % size)
                    kavutil.vprint(None, 'Label', label)
                    kavutil.vprint(None, 'File Name', fname)
                    kavutil.vprint(None, 'Command Line', command)
                    kavutil.vprint(None, 'Data Offset', '0x%08X' % (off + 4))
                    kavutil.vprint(None, 'Data Size', '0x%08X' % data_size)

                    print
                    kavutil.vprint('Data Dump')
                    print
                    kavutil.HexDump().Buffer(mm[:], off + 4, 0x80)
                    print

                return fileformat
    except ValueError:
        pass
    except struct.error:
        pass

    return None
Ejemplo n.º 13
0
    def parse(self):
        self.temp_name = tempfile.mktemp(prefix='knsf')

        # NSIS 위치 읽기
        fp = open(self.filename, 'rb')
        fp.seek(self.start_offset)
        data = fp.read()
        fp.close()

        open(self.temp_name, 'wb').write(data)

        self.fp = open(self.temp_name, 'rb')
        fsize = os.path.getsize(self.temp_name)
        if fsize == 0:
            return False

        self.mm = mmap.mmap(self.fp.fileno(), 0, access=mmap.ACCESS_READ)

        flag = kavutil.get_uint32(self.mm, 0)
        head_size = kavutil.get_uint32(self.mm, 0x14)
        comp_size = kavutil.get_uint32(self.mm, 0x18)

        data, case_type = self.get_data()  # NSIS의 모든 데이터를 가진다.
        self.body_data = data
        self.case_type = case_type

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

            print
            kavutil.vprint('NSIS')
            kavutil.vprint(None, 'Flag', '%d' % flag)
            kavutil.vprint(None, 'Uncompress Case', '%d' % case_type)

            print
            kavutil.vprint('Uncompress Data')
            print
            kavutil.HexDump().Buffer(data, 0, 0x80)

            s = self.nsis_header.namelist_ex()
            if len(s):
                print
                kavutil.vprint('File Extract')
                print
                for t in s:
                    (foff, fname, ftime, extract_type) = t
                    print "%08X | %-45s | %s" % (foff, fname, ftime
                                                 if ftime != '' else 'N/A')

        return True
Ejemplo n.º 14
0
    def __get_string(self, str_off):
        if str_off < 0:
            off = self.nh.langtables + 2 + 4 + -str_off * 4
            str_off = kavutil.get_uint32(self.header_data, off)

        if (str_off * self.is_unicode) in range(0, self.strings_max):
            str_data = ''

            off = self.nh.strings + (str_off * self.is_unicode)

            char = self.header_data[off:off + (1 * self.is_unicode)]
            off += (1 * self.is_unicode)

            while char != '\x00' * self.is_unicode and len(char) != 0:
                if self.is_unicode == 2:
                    ch = struct.unpack('<H', char)[0]
                else:
                    ch = ord(char)

                if (ch >= self.ns_codes_start) if self.ver3 else (ch < self.ns_codes_start):
                    str_data += char
                elif ch == self.ns_var_code:
                    n_data = self.__decode_short(off)
                    off += 2
                    str_data += self.__binary_str_to_unicode(self.__get_user_var_name(n_data))

                char = self.header_data[off:off + (1 * self.is_unicode)]
                off += (1 * self.is_unicode)
            # end while

            str_data = self.__binary_unicode_to_str(str_data)

            return str_data
        else:
            return ''
Ejemplo n.º 15
0
    def __GetFileName__(self, alz_pos):
        try:
            mm = self.mm
            data_size = len(mm)
        except TypeError:
            return None, -1

        try:
            while alz_pos < data_size:
                magic = kavutil.get_uint32(mm, alz_pos)

                if magic == 0x015A4C42:  # Local File Header
                    _, _, size, fname = self.__Alz_LocalFileHeader__(mm[alz_pos:])
                    if size == -1:
                        raise ValueError
                    alz_pos += size
                    return fname, alz_pos
                else:
                    alz_pos = self.__DefaultMagicIDProc__(magic, alz_pos)
                    if alz_pos == -1:
                        raise ValueError
        except ValueError:
            pass

        return None, -1
Ejemplo n.º 16
0
    def __GetFileName__(self, alz_pos):
        try:
            mm = self.mm
            data_size = len(mm)
        except TypeError:
            return None, -1

        try:
            while alz_pos < data_size:
                magic = kavutil.get_uint32(mm, alz_pos)

                if magic == 0x015A4C42:  # Local File Header
                    _, _, size, fname = self.__Alz_LocalFileHeader__(
                        mm[alz_pos:])
                    if size == -1:
                        raise ValueError
                    alz_pos += size
                    return fname, alz_pos
                else:
                    alz_pos = self.__DefaultMagicIDProc__(magic, alz_pos)
                    if alz_pos == -1:
                        raise ValueError
        except ValueError:
            pass

        return None, -1
Ejemplo n.º 17
0
    def __scan_virus_win32_small_a(self, mm, fileformat):
        if 'ff_pe' in fileformat:
            ff = fileformat['ff_pe']['pe']
            ep_off = ff['EntryPointRaw']

            if cryptolib.crc32(mm[ep_off:ep_off + 12]) == '4d49a25f':
                v_rva = kavutil.get_uint32(mm, ep_off + 12) + 1  # 악성코드 RVA
                v_rva -= ff['ImageBase']

                # v_rva가 마지막 섹션에 속하는 값인지 확인한다.
                sec = ff['Sections'][-1]
                if sec['RVA'] <= v_rva <= sec['RVA'] + sec['VirtualSize']:
                    pe_file_align = ff['FileAlignment']
                    if pe_file_align:
                        foff = (sec['PointerRawData'] / pe_file_align) * pe_file_align
                    else:
                        foff = sec['PointerRawData']

                    v_off = v_rva - sec['RVA'] + foff

                    x = cryptolib.crc32(mm[v_off:v_off + 0x30])
                    if x == '8d964738':
                        return True, 'Virus.Win32.Small.a'
                    elif x == '00000000' or x == 'f288b395':  # 파일이 깨진 경우이거나 모든 값이 0인 경우이다.
                        return True, 'Virus.Win32.SuperThreat.b'

        return False, None
Ejemplo n.º 18
0
    def __scan_virus_win32_small_a(self, mm, fileformat):
        if 'ff_pe' in fileformat:
            ff = fileformat['ff_pe']['pe']
            ep_off = ff['EntryPointRaw']

            if cryptolib.crc32(mm[ep_off:ep_off + 12]) == '4d49a25f':
                v_rva = kavutil.get_uint32(mm, ep_off + 12) + 1  # 악성코드 RVA
                v_rva -= ff['ImageBase']

                # v_rva가 마지막 섹션에 속하는 값인지 확인한다.
                sec = ff['Sections'][-1]
                if sec['RVA'] <= v_rva <= sec['RVA'] + sec['VirtualSize']:
                    pe_file_align = ff['FileAlignment']
                    if pe_file_align:
                        foff = (sec['PointerRawData'] /
                                pe_file_align) * pe_file_align
                    else:
                        foff = sec['PointerRawData']

                    v_off = v_rva - sec['RVA'] + foff

                    x = cryptolib.crc32(mm[v_off:v_off + 0x30])
                    if x == '8d964738':
                        return True, 'Virus.Win32.Small.a'
                    elif x == '00000000' or x == 'f288b395':  # 파일이 깨진 경우이거나 모든 값이 0인 경우이다.
                        return True, 'Virus.Win32.SuperThreat.b'

        return False, None
Ejemplo n.º 19
0
    def get_data(self):
        # NSIS가 두가지 종류가 있는것으로 보여짐
        # 설치 파일 전부를 압축한 경우와 개별로 압축한 경우

        # case 1: 설치 파일 전부를 압축한 경우
        try:
            head_size = kavutil.get_uint32(self.mm, 0x14)
            comp_size = kavutil.get_uint32(self.mm, 0x18)
            comp_type = self.__get_comp_type(kavutil.get_uint32(self.mm, 0x1C))
            uncmp_data = self.do_decompress(comp_type, 0x1C, comp_size)
            if uncmp_data:
                if head_size == kavutil.get_uint32(uncmp_data, 0):
                    self.nsis_header = NSISHeader(uncmp_data[4:head_size + 4])
                    if self.nsis_header.parse():
                        return uncmp_data[head_size + 4:], 1
        except struct.error:
            pass

        # case 2: 개별로 압축한 경우
        try:
            head_size = kavutil.get_uint32(self.mm, 0x14)
            comp_size = kavutil.get_uint32(self.mm, 0x1C) & 0x7fffffff
            comp_type = self.__get_comp_type(kavutil.get_uint32(self.mm, 0x20))
            uncmp_data = self.do_decompress(comp_type, 0x20, comp_size)
            if uncmp_data:
                if head_size == len(uncmp_data):
                    self.nsis_header = NSISHeader(uncmp_data)
                    if self.nsis_header.parse():
                        return self.mm[0x20+comp_size:], 2
        except struct.error:
            pass

        return None, 0
Ejemplo n.º 20
0
    def get_data(self):
        # NSIS가 두가지 종류가 있는것으로 보여짐
        # 설치 파일 전부를 압축한 경우와 개별로 압축한 경우

        # case 1: 설치 파일 전부를 압축한 경우
        try:
            head_size = kavutil.get_uint32(self.mm, 0x14)
            comp_size = kavutil.get_uint32(self.mm, 0x18)
            comp_type = self.__get_comp_type(kavutil.get_uint32(self.mm, 0x1C))
            uncmp_data = self.do_decompress(comp_type, 0x1C, comp_size)
            if uncmp_data:
                if head_size == kavutil.get_uint32(uncmp_data, 0):
                    self.nsis_header = NSISHeader(uncmp_data[4:head_size + 4])
                    if self.nsis_header.parse():
                        return uncmp_data[head_size + 4:], 1
        except struct.error:
            pass

        # case 2: 개별로 압축한 경우
        try:
            head_size = kavutil.get_uint32(self.mm, 0x14)
            comp_size = kavutil.get_uint32(self.mm, 0x1C) & 0x7fffffff
            comp_type = self.__get_comp_type(kavutil.get_uint32(self.mm, 0x20))
            uncmp_data = self.do_decompress(comp_type, 0x20, comp_size)
            if uncmp_data:
                if head_size == len(uncmp_data):
                    self.nsis_header = NSISHeader(uncmp_data)
                    if self.nsis_header.parse():
                        return self.mm[0x20 + comp_size:], 2
        except struct.error:
            pass

        return None, 0
Ejemplo n.º 21
0
def scan_hwp_recoard(buf, lenbuf):
    pos = 0

    while pos < lenbuf:
        extra_size = 4
        val = kavutil.get_uint32(buf, pos)
        tagid, level, size = get_hwp_recoard(val)

        if size == 0xfff:
            extra_size = 8
            size = kavutil.get_uint32(buf, pos + 4)

        pos += (size + extra_size)

    if pos == lenbuf:
        return True

    return False
Ejemplo n.º 22
0
def scan_hwp_recoard(buf, lenbuf):
    pos = 0

    while pos < lenbuf:
        extra_size = 4
        val = kavutil.get_uint32(buf, pos)
        tagid, level, size = get_hwp_recoard(val)

        if size == 0xfff:
            extra_size = 8
            size = kavutil.get_uint32(buf, pos + 4)

        pos += (size + extra_size)

    if pos == lenbuf:
        return True

    return False
Ejemplo n.º 23
0
    def parse(self):
        self.fp = open(self.filename, 'rb')
        fsize = os.path.getsize(self.filename)
        if fsize == 0:
            return False

        self.mm = mmap.mmap(self.fp.fileno(), 0, access=mmap.ACCESS_READ)

        flag = kavutil.get_uint32(self.mm, 0)
        head_size = kavutil.get_uint32(self.mm, 0x14)
        comp_size = kavutil.get_uint32(self.mm, 0x18)

        data, case_type = self.get_data()  # NSIS의 모든 데이터를 가진다.
        self.body_data = data
        self.case_type = case_type

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

            print
            kavutil.vprint('NSIS')
            kavutil.vprint(None, 'Flag', '%d' % flag)
            kavutil.vprint(None, 'Uncompress Case', '%d' % case_type)

            print
            kavutil.vprint('Uncompress Data')
            print
            kavutil.HexDump().Buffer(data, 0, 0x80)

            s = self.nsis_header.namelist_ex()
            if len(s):
                print
                kavutil.vprint('File Extract')
                print
                for t in s:
                    (foff, fname, ftime, extract_type) = t
                    print "%08X | %-45s | %s" % (foff, fname, ftime if ftime != '' else 'N/A')

        return True
Ejemplo n.º 24
0
    def __EGG_Block_Header_Size__(self, data):
        size = -1

        try:
            block__size = (18 + 4)
            # compress__size = struct.unpack('<L', data[10:14])[0]
            compress__size = kavutil.get_uint32(data, 10)
            size = block__size + compress__size
        except:
            pass

        return size
Ejemplo n.º 25
0
    def __EGG_Block_Header_Size__(self, data):
        size = -1

        try:
            block__size = (18 + 4)
            # compress__size = struct.unpack('<L', data[10:14])[0]
            compress__size = kavutil.get_uint32(data, 10)
            size = block__size + compress__size
        except:
            pass

        return size
Ejemplo n.º 26
0
    def __Alz_LocalFileHeader__(self, data):
        try:
            fname_size = kavutil.get_uint16(data, 4)
            file_desc = ord(data[11])
            compress__method__m = ord(data[13])

            size = 19
            if file_desc & 0x10:
                compress__size = ord(data[size])
                uncompress__size = ord(data[size + 1])
                size += (1 * 2)  # 파일 크기가 2개 옴(압축전, 압축 후)
            elif file_desc & 0x20:
                compress__size = kavutil.get_uint16(data, size)
                uncompress__size = kavutil.get_uint16(data, size + 2)
                size += (2 * 2)
            elif file_desc & 0x40:
                compress__size = kavutil.get_uint32(data, size)
                uncompress__size = kavutil.get_uint32(data, size + 4)
                size += (4 * 2)
            elif file_desc & 0x80:
                compress__size = kavutil.get_uint64(data, size)
                uncompress__size = kavutil.get_uint64(data, size + 8)
                size += (8 * 2)
            else:
                raise SystemError

            fname = data[size:size + fname_size]
            size += fname_size  # 파일 이름

            if file_desc & 1:
                size += 12  # Encrypt Block

            compressed__data = data[size:size + compress__size]

            return compressed__data, compress__method__m, size + compress__size, fname
        except IndexError:
            pass

        return None, -1
Ejemplo n.º 27
0
    def __Alz_LocalFileHeader__(self, data):
        try:
            fname_size = kavutil.get_uint16(data, 4)
            file_desc = ord(data[11])
            compress__method__m = ord(data[13])

            size = 19
            if file_desc & 0x10:
                compress__size = ord(data[size])
                uncompress__size = ord(data[size + 1])
                size += (1 * 2)  # 파일 크기가 2개 옴(압축전, 압축 후)
            elif file_desc & 0x20:
                compress__size = kavutil.get_uint16(data, size)
                uncompress__size = kavutil.get_uint16(data, size+2)
                size += (2 * 2)
            elif file_desc & 0x40:
                compress__size = kavutil.get_uint32(data, size)
                uncompress__size = kavutil.get_uint32(data, size+4)
                size += (4 * 2)
            elif file_desc & 0x80:
                compress__size = kavutil.get_uint64(data, size)
                uncompress__size = kavutil.get_uint64(data, size+8)
                size += (8 * 2)
            else:
                raise SystemError

            fname = data[size:size + fname_size]
            size += fname_size  # 파일 이름

            if file_desc & 1:
                size += 12  # Encrypt Block

            compressed__data = data[size:size + compress__size]

            return compressed__data, compress__method__m, size+compress__size, fname
        except IndexError:
            pass

        return None, -1
Ejemplo n.º 28
0
def doubleebx(src, myebx, scur, ssize):
    oldebx = myebx

    try:
        myebx = (myebx * 2) & 0xFFFFFFFF
        if not (oldebx & 0x7fffffff):
            if not ISCONTAINED(0, ssize, scur, 4):
                return -1, myebx, scur
            oldebx = kavutil.get_uint32(src, scur)
            myebx = uint32(oldebx * 2 + 1)
            scur += 4
        return (oldebx >> 31), myebx, scur
    except:
        return -1, myebx, scur
Ejemplo n.º 29
0
def checkpe(dst, dsize, pehdr):
    try:
        if kavutil.get_uint32(dst, pehdr) != 0x4550:
            raise ValueError

        valign = kavutil.get_uint32(dst, pehdr + 0x38)
        if not valign:
            raise ValueError

        sectcnt = kavutil.get_uint32(dst, pehdr + 6)
        if not sectcnt:
            raise ValueError

        sections_pos = pehdr + 0xF8

        if (sections_pos + (sectcnt * 0x28)) > dsize:
            raise ValueError
    except ValueError:
        sections_pos = 0
        valign = 0
        sectcnt = 0

    return sections_pos, valign, sectcnt
Ejemplo n.º 30
0
def checkpe(dst, dsize, pehdr):
    try:
        if kavutil.get_uint32(dst, pehdr) != 0x4550:
            raise ValueError

        valign = kavutil.get_uint32(dst, pehdr+0x38)
        if not valign:
            raise ValueError

        sectcnt = kavutil.get_uint32(dst, pehdr+6)
        if not sectcnt:
            raise ValueError

        sections_pos = pehdr + 0xF8

        if (sections_pos + (sectcnt * 0x28)) > dsize:
            raise ValueError
    except ValueError:
        sections_pos = 0
        valign = 0
        sectcnt = 0

    return sections_pos, valign, sectcnt
Ejemplo n.º 31
0
def doubleebx(src, myebx, scur, ssize):
    oldebx = myebx

    try:
        myebx = (myebx * 2) & 0xFFFFFFFF
        if not (oldebx & 0x7fffffff):
            if not ISCONTAINED(0, ssize, scur, 4):
                return -1, myebx, scur
            oldebx = kavutil.get_uint32(src, scur)
            myebx = uint32(oldebx * 2 + 1)
            scur += 4
        return (oldebx >> 31), myebx, scur
    except:
        return -1, myebx, scur
Ejemplo n.º 32
0
    def scan(self, filehandle, filename, fileformat, filename_ex):  # 악성코드 검사
        mm = filehandle

        if filename_ex.lower().find('bodytext/section') >= 0 or filename_ex.lower().find('docinfo') >= 0:
            val = kavutil.get_uint32(mm, 0)
            tagid, level, size = get_hwp_recoard(val)

            # 문서의 첫번째 tag가 문서 헤더(0x42), 문서 속성(0x10) 일때만 추적 진행
            if tagid == 0x42 or tagid == 0x10:
                ret, tagid = scan_hwp_recoard(mm, len(mm))
                if ret is False:  # 레코드 추적 실패
                    return True, 'Exploit.HWP.Generic.%02X' % tagid, 0, kernel.INFECTED

        # 악성코드를 발견하지 못했음을 리턴한다.
        return False, '', -1, kernel.NOT_FOUND
Ejemplo n.º 33
0
    def scan(self, filehandle, filename, fileformat, filename_ex):  # 악성코드 검사
        mm = filehandle

        if filename_ex.lower().find('bodytext/section') >= 0 or filename_ex.lower().find('docinfo') >= 0:
            val = kavutil.get_uint32(mm, 0)
            tagid, level, size = get_hwp_recoard(val)

            # 문서의 첫번째 tag가 문서 헤더(0x42), 문서 속성(0x10) 일때만 추적 진행
            if tagid == 0x42 or tagid == 0x10:
                ret, tagid = scan_hwp_recoard(mm, len(mm))
                if ret is False:  # 레코드 추적 실패
                    return True, 'Exploit.HWP.Generic.%02X' % tagid, 0, kernel.INFECTED
        elif filename_ex.lower().find('scripts/defaultjscript') >= 0:
            if self.hwp_js.search(mm):
                return True, 'Exploit.JS.Agent.gen', 0, kernel.INFECTED

        # 악성코드를 발견하지 못했음을 리턴한다.
        return False, '', -1, kernel.NOT_FOUND
Ejemplo n.º 34
0
    def scan(self, filehandle, filename, fileformat, filename_ex):  # 악성코드 검사
        try:
            # 미리 분석된 파일 포맷중에 PE 포맷이 있는가?
            if 'ff_pyc' in fileformat:
                if self.verbose:
                    print '-' * 79
                    kavutil.vprint('Engine')
                    kavutil.vprint(None, 'Engine', 'pyz.kmd')

                mm = filehandle

                # String 추출
                if len(mm):
                    if self.verbose:
                        print
                        kavutil.vprint('String')

                    for match in self.p_string.finditer(mm):
                        find_str = match.group()
                        find_str_off = match.start()

                        # 중요 문자열 시작전에 해당 문자열의 길이가 존재함
                        x = kavutil.get_uint32(mm, find_str_off - 4)
                        if len(find_str) < x:
                            continue

                        buf = find_str[:x]
                        fsize = len(buf)

                        if self.verbose:
                            fmd5 = cryptolib.md5(buf)
                            kavutil.vprint(None, fmd5, '%3d : %s' % (fsize, buf))

                        if fsize and kavutil.handle_pattern_md5.match_size('emalware', fsize):
                            fmd5 = cryptolib.md5(buf)
                            # print fsize, fmd5
                            vname = kavutil.handle_pattern_md5.scan('emalware', fsize, fmd5)
                            if vname:
                                return True, vname, 0, kernel.INFECTED
        except IOError:
            pass

        # 악성코드를 발견하지 못했음을 리턴한다.
        return False, '', -1, kernel.NOT_FOUND
Ejemplo n.º 35
0
    def format(self, filehandle, filename, filename_ex):
        fileformat = {}  # 포맷 정보를 담을 공간

        mm = filehandle
        try:
            zlib.decompress(mm, -15)
            ret = {'ff_zlib': 'ZLIB'}
            return ret
        except zlib.error:
            pass

        try:
            if kavutil.get_uint32(mm, 0) == len(mm) - 4:
                ret = {'ff_embed_ole': 'EMBED_OLE'}
                return ret
        except struct.error:
            pass

        return None
Ejemplo n.º 36
0
    def init(self, plugins_path, verbose=False):  # 플러그인 엔진 초기화
        self.verbose = verbose
        self.sig_num_yara = 0

        # Yara 모듈이 없을 경우 엔질 로딩 실패 처리
        if not LOAD_YARA:
            return -1

        # Adware Yara 룰 로딩
        try:
            b = open(os.path.join(plugins_path, 'adware.y01'), 'rb').read()
            self.sig_num_yara = kavutil.get_uint32(b, 4)
            if b[:4] == 'KAVS':
                t = zlib.decompress(b[12:])

                buff = StringIO.StringIO(t)
                self.adware_gen = yara.load(file=buff)
        except:
            self.adware_gen = None

        return 0  # 플러그인 엔진 초기화 성공
Ejemplo n.º 37
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
Ejemplo n.º 38
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
Ejemplo n.º 39
0
    def init(self, plugins_path, verbose=False):  # 플러그인 엔진 초기화
        self.verbose = verbose
        self.sig_num_yara = 0

        # Yara 모듈이 없을 경우 엔질 로딩 실패 처리
        if not LOAD_YARA:
            return -1

        # Adware Yara 룰 로딩
        try:
            b = open(os.path.join(plugins_path, 'adware.y01'), 'rb').read()
            self.sig_num_yara = kavutil.get_uint32(b, 4)
            if b[:4] == 'KAVS':
                t = zlib.decompress(b[12:])

                buff = StringIO.StringIO(t)
                self.adware_gen = yara.load(file=buff)
        except:
            self.adware_gen = None

        return 0  # 플러그인 엔진 초기화 성공
Ejemplo n.º 40
0
    def format(self, filehandle, filename, filename_ex):
        ret = {}  # 포맷 정보를 담을 공간

        mm = filehandle
        try:
            d = zlib.decompress(mm, -15)
            if len(d) > 1:
                ret['ff_zlib'] = 'ZLIB'
        except zlib.error:
            pass

        try:
            if kavutil.get_uint32(mm, 0) == len(mm) - 4:
                ret['ff_embed_ole'] = 'EMBED_OLE'
        except struct.error:
            pass

        if len(ret):
            return ret

        return None
Ejemplo n.º 41
0
    def format(self, filehandle, filename, filename_ex):
        ret = {}  # 포맷 정보를 담을 공간

        mm = filehandle
        try:
            d = zlib.decompress(mm, -15)
            if len(d) > 1:
                ret['ff_zlib'] = 'ZLIB'
        except zlib.error:
            pass

        try:
            if kavutil.get_uint32(mm, 0) == len(mm) - 4:
                ret['ff_embed_ole'] = 'EMBED_OLE'
        except struct.error:
            pass

        if len(ret):
            return ret

        return None
Ejemplo n.º 42
0
    def __GetFileName__(self, egg_pos):
        mm = self.mm
        data_size = self.data_size

        try:
            while egg_pos < data_size:
                # magic = struct.unpack('<L', mm[egg_pos:egg_pos+4])[0]
                magic = kavutil.get_uint32(mm, egg_pos)

                if magic == 0x0A8591AC:  # Filename Header
                    # print 'Filename Header'
                    size, fname = self.__EGG_Filename_Header__(mm[egg_pos:])
                    if size == -1:
                        raise SystemError
                    egg_pos += size
                    return fname, egg_pos
                else:
                    egg_pos = self.__DefaultMagicIDProc__(magic, egg_pos)
                    if egg_pos == -1:
                        raise SystemError
        except SystemError:
            pass

        return None, -1
Ejemplo n.º 43
0
    def __GetFileName__(self, egg_pos):
        mm = self.mm
        data_size = self.data_size

        try:
            while egg_pos < data_size:
                # magic = struct.unpack('<L', mm[egg_pos:egg_pos+4])[0]
                magic = kavutil.get_uint32(mm, egg_pos)

                if magic == 0x0A8591AC:  # Filename Header
                    # print 'Filename Header'
                    size, fname = self.__EGG_Filename_Header__(mm[egg_pos:])
                    if size == -1:
                        raise SystemError
                    egg_pos += size
                    return fname, egg_pos
                else:
                    egg_pos = self.__DefaultMagicIDProc__(magic, egg_pos)
                    if egg_pos == -1:
                        raise SystemError
        except SystemError:
            pass

        return None, -1
Ejemplo n.º 44
0
def RebuildPE(src, ssize, dst, dsize, ep, upx0, upx1, magic, dend):
    try:
        foffset = uint32(0xD0 + 0xF8)

        if len(src) == 0 or len(dst) == 0:
            raise SystemError

        for valign in magic:
            if (ep - upx1 + valign <= ssize - 5) and \
                            ord(src[ep - upx1 + valign - 2]) == 0x8D and \
                            ord(src[ep - upx1 + valign - 1]) == 0xBE:
                break

        if not valign and (ep - upx1 + len(HEADERS) < ssize - 8):
            i = 0
            while True:
                b1 = ord(src[ep - upx1 + len(HEADERS) + 0 + i])
                b2 = ord(src[ep - upx1 + len(HEADERS) + 1 + i])

                if b1 == 0x8D and b2 == 0xBE:
                    b3 = ord(src[ep - upx1 + len(HEADERS) + 6 + i])
                    b4 = ord(src[ep - upx1 + len(HEADERS) + 7 + i])

                    if b3 == 0x8B and b4 == 0x07:
                        valign = len(HEADERS) + i + 2
                        break
                i += 1

        if valign and ISCONTAINED(0, ssize, ep - upx1 + valign, 4):
            dst_imports = kavutil.get_uint32(src, ep - upx1 + valign)
            # dst_imports = struct.unpack('<l', src[ep - upx1 + valign:ep - upx1 + valign + 4])[0]

            realstuffsz = dst_imports

            if realstuffsz >= dsize:
                raise SystemError
            else:
                pehdr = dst_imports

                while (pehdr + 8 < dsize) and kavutil.get_uint32(dst, pehdr):
                    # while (pehdr + 8 < dsize) and (struct.unpack('<l', dst[pehdr:pehdr + 4])[0]):
                    pehdr += 8
                    while (pehdr + 2 < dsize) and ord(dst[pehdr]):
                        pehdr += 1
                        while (pehdr + 2 < dsize) and ord(dst[pehdr]):
                            pehdr += 1
                        pehdr += 1
                    pehdr += 1
                pehdr += 4

                sections, valign, sectcnt = checkpe(dst, dsize, pehdr)
                if not sections:
                    pehdr = 0

        if not pehdr and dend > (0xF8 + 0x28):
            pehdr = dend - 0xF8 - 0x28
            if int32(pehdr) < 0:
                raise SystemError

            while True:
                sections, valign, sectcnt = checkpe(dst, dsize, pehdr)
                if sections:
                    break
                pehdr -= 1

            realstuffsz = pehdr
            if not realstuffsz:
                raise SystemError

        if not pehdr:
            rebsz = uint32(PESALIGN(dend, 0x1000))
            # print hex(rebsz)
            # To Do

        foffset = PESALIGN(foffset + 0x28 * sectcnt, valign)

        for upd in range(sectcnt):
            t = kavutil.get_uint32(dst, sections + 8)
            vsize = uint32(PESALIGN(t, valign))

            t = kavutil.get_uint32(dst, sections + 12)
            urva = uint32(PESALIGN(t, valign))

            if not (upx0 + realstuffsz >= urva + vsize):
                raise SystemError

            t = struct.pack('<LLLL', vsize, urva, vsize, foffset)
            dest = dst[:sections + 8]
            dest += t
            dest += dst[sections + 24:]
            dst = dest

            foffset += vsize
            sections += 0x28

        t = struct.pack('<L', valign)
        dest = dst[:pehdr + 0x3C]
        dest += t
        dest += dst[pehdr + 0x3C + 4:]
        dst = dest

        newbuf = ['\x00'] * foffset

        for i in range(len(HEADERS)):
            newbuf[i] = HEADERS[i]

        for i in range(0xf8 + 0x28 * sectcnt):
            newbuf[0xD0 + i] = dst[pehdr + i]

        sections = pehdr + 0xF8

        for upd in range(sectcnt):
            t1 = kavutil.get_uint32(dst, sections + 20)
            t2 = kavutil.get_uint32(dst, sections + 12)
            t3 = kavutil.get_uint32(dst, sections + 16)

            for i in range(t3):
                newbuf[t1 + i] = dst[t2 - upx0 + i]

            sections += 0x28

        if foffset > dsize + 8192:
            raise SystemError

        dsize = foffset

        upx_d = ''
        for ch in newbuf:
            upx_d += ch
    except:
        return None

    return upx_d
Ejemplo n.º 45
0
    def unarc(self, arc_engine_id, arc_name, fname_in_arc):
        fp = None
        mm = None
        data = None

        if arc_engine_id.find('arc_upx') != -1:
            filename = fname_in_arc

            try:
                # UPX로 압축된 파일 열기
                fp = open(arc_name, 'rb')
                mm = mmap.mmap(fp.fileno(), 0, access=mmap.ACCESS_READ)

                p = pe.PE(mm, False, arc_name)
                pe_format = p.parse()  # PE 파일 분석
                if pe_format is None:
                    return ValueError

                pe_img = pe_format['ImageBase']
                pe_ep = pe_format['EntryPoint']
                sections = pe_format['Sections']
                ep_raw = pe_format['EntryPointRaw']  # EP의 Raw 위치
                ep_nsec = pe_format[
                    'EntryPoint_in_Section']  # EP는 몇번째 섹션에 있는가?

                foff = 0
                ssize = 0
                dsize = 0

                for section in sections:
                    ssize = section['VirtualSize']
                    rva = section['RVA']
                    if rva <= pe_ep < rva + ssize:
                        foff = section['PointerRawData']
                        i = sections.index(section)
                        if i != 0:
                            upx0 = sections[i - 1]['RVA']
                            upx1 = sections[i]['RVA']
                            dsize = sections[i - 1]['VirtualSize'] + ssize
                        break

                if ssize == 0 or dsize == 0:
                    raise ValueError

                upx_data_rva = kavutil.get_uint32(mm, ep_raw + 2)
                sec_rva = sections[ep_nsec]['RVA']

                skew = upx_data_rva - sec_rva - pe_img

                if mm[ep_raw + 1] != '\xBE' or skew <= 0 or skew > 0xFFF:
                    skew = 0
                elif skew > ssize:
                    skew = 0
                else:
                    raise ValueError

                data = mm[foff + skew:foff + ssize - skew]

                unpack_data = ''  # UPX 해제된 이미지

                if arc_engine_id[8:] == 'nrv2b':  # UPX 알고리즘 중 nrv2b 압축인가?
                    ret_val, unpack_data = upx_inflate2b(
                        data, dsize, pe_ep, upx0, upx1, pe_img)

                if unpack_data == '':  # 압축 해제 실패
                    raise ValueError

                data = unpack_data
            except IOError:
                pass
            except ValueError:
                pass

            if mm:
                mm.close()

            if fp:
                fp.close()

            return data

        return None
Ejemplo n.º 46
0
Archivo: pe.py Proyecto: jaepil/kicomav
    def parse(self):
        mm = self.mm

        pe_format = {
            'PE_Position': 0,
            'EntryPoint': 0,
            'SectionNumber': 0,
            'Sections': None,
            'EntryPointRaw': 0,
            'FileAlignment': 0
        }

        try:
            if mm[0:2] != 'MZ':  # MZ로 시작하나?
                raise ValueError

            # PE 표식자 위치 알아내기
            pe_pos = kavutil.get_uint32(mm, 0x3C)

            # PE 인가?
            if mm[pe_pos:pe_pos + 4] != 'PE\x00\x00':
                raise ValueError

            pe_format['PE_Position'] = pe_pos

            # Optional Header의 Magic ID?
            if mm[pe_pos + 0x18:pe_pos + 0x18 + 2] != '\x0B\x01':
                raise ValueError

            # Entry Point 구하기
            pe_ep = kavutil.get_uint32(mm, pe_pos + 0x28)
            pe_format['EntryPoint'] = pe_ep

            # Image Base 구하기
            pe_img = kavutil.get_uint32(mm, pe_pos + 0x34)
            pe_format['ImageBase'] = pe_img

            # File Alignment 구하기
            self.pe_file_align = kavutil.get_uint32(mm, pe_pos + 0x3C)
            pe_format['FileAlignment'] = self.pe_file_align

            # Section 개수 구하기
            section_num = kavutil.get_uint16(mm, pe_pos + 0x6)
            pe_format['SectionNumber'] = section_num

            # Optional Header 크기 구하기
            opthdr_size = kavutil.get_uint16(mm, pe_pos + 0x14)
            pe_format['OptionalHederSize'] = opthdr_size

            # t섹션 시작 위치
            section_pos = pe_pos + 0x18 + opthdr_size

            # 모든 섹션 정보 추출
            for i in range(section_num):
                section = {}

                s = section_pos + (0x28 * i)

                section['Name'] = mm[s:s + 8].replace('\x00', '')
                section['VirtualSize'] = kavutil.get_uint32(mm, s + 8)
                section['RVA'] = kavutil.get_uint32(mm, s + 12)
                section['SizeRawData'] = kavutil.get_uint32(mm, s + 16)
                section['PointerRawData'] = kavutil.get_uint32(mm, s + 20)
                section['Characteristics'] = kavutil.get_uint32(mm, s + 36)

                self.sections.append(section)

            pe_format['Sections'] = self.sections

            # EntryPoint의 파일에서의 위치 구하기
            ep_raw, sec_idx = self.rva_to_off(pe_ep)
            pe_format['EntryPointRaw'] = ep_raw  # EP의 Raw 위치
            pe_format['EntryPoint_in_Section'] = sec_idx  # EP가 포함된 섹션

            # 리소스 분석
            rsrc_rva = kavutil.get_uint32(mm, pe_pos + 0x88)  # 리소스 위치(RVA)
            rsrc_size = kavutil.get_uint32(mm, pe_pos + 0x8C)  # 리소스 크기

            if rsrc_rva:  # 리소스가 존재한가?
                try:
                    rsrc_off, _ = self.rva_to_off(rsrc_rva)  # 리소스 위치 변환

                    # Type 체크
                    num_type_name = kavutil.get_uint16(mm, rsrc_off + 0xC)
                    num_type_id = kavutil.get_uint16(mm, rsrc_off + 0xE)

                    for i in range(num_type_name + num_type_id):
                        type_id = kavutil.get_uint32(mm,
                                                     rsrc_off + 0x10 + (i * 8))
                        name_id_off = kavutil.get_uint32(
                            mm, rsrc_off + 0x14 + (i * 8))

                        # Type이 사용자가 정의한 이름 or RCDATA?
                        if type_id & 0x80000000 == 0x80000000 or type_id == 0xA:
                            if type_id & 0x80000000 == 0x80000000:
                                # 사용자가 정의한 이름 추출
                                string_off = (type_id & 0x7FFFFFFF) + rsrc_off
                                len_name = kavutil.get_uint16(mm, string_off)
                                rsrc_type_name = mm[string_off + 2:string_off +
                                                    2 + (len_name * 2):2]
                            else:
                                rsrc_type_name = 'RCDATA'

                            # Name ID
                            name_id_off = (name_id_off & 0x7FFFFFFF) + rsrc_off
                            num_name_id_name = kavutil.get_uint16(
                                mm, name_id_off + 0xC)
                            num_name_id_id = kavutil.get_uint16(
                                mm, name_id_off + 0xE)

                            for j in range(num_name_id_name + num_name_id_id):
                                name_id_id = kavutil.get_uint32(
                                    mm, name_id_off + 0x10 + (j * 8))
                                language_off = kavutil.get_uint32(
                                    mm, name_id_off + 0x14 + (j * 8))

                                # 리소스 영역의 최종 이름 생성
                                if name_id_id & 0x80000000 == 0x80000000:
                                    string_off = (name_id_id
                                                  & 0x7FFFFFFF) + rsrc_off
                                    len_name = kavutil.get_uint16(
                                        mm, string_off)
                                    rsrc_name_id_name = mm[string_off +
                                                           2:string_off + 2 +
                                                           (len_name * 2):2]
                                    string_name = rsrc_type_name + '/' + rsrc_name_id_name
                                else:
                                    string_name = rsrc_type_name + '/' + hex(
                                        name_id_id).upper()[2:]

                                # Language
                                language_off = (language_off
                                                & 0x7FFFFFFF) + rsrc_off
                                num_language_name = kavutil.get_uint16(
                                    mm, language_off + 0xC)
                                num_language_id = kavutil.get_uint16(
                                    mm, language_off + 0xE)

                                for k in range(num_language_name +
                                               num_language_id):
                                    # language_id = kavutil.get_uint32(mm, language_off + 0x10 + (k * 8))
                                    data_entry_off = kavutil.get_uint32(
                                        mm, language_off + 0x14 + (k * 8))

                                    data_entry_off = (data_entry_off
                                                      & 0x7FFFFFFF) + rsrc_off

                                    data_rva = kavutil.get_uint32(
                                        mm, data_entry_off)
                                    data_off, _ = self.rva_to_off(data_rva)
                                    data_size = kavutil.get_uint32(
                                        mm, data_entry_off + 4)

                                    if data_size > 8192:  # 최소 8K 이상인 리소스만 데이터로 추출
                                        if 'Resource_UserData' in pe_format:
                                            pe_format['Resource_UserData'][
                                                string_name] = (data_off,
                                                                data_size)
                                        else:
                                            pe_format['Resource_UserData'] = {
                                                string_name:
                                                (data_off, data_size)
                                            }
                except struct.error:
                    pass

                # if 'Resource_UserData' in pe_format:
                #     print pe_format['Resource_UserData']

            # Import API 분석
            imp_rva = kavutil.get_uint32(mm,
                                         pe_pos + 0x80)  # Import API 위치(RVA)
            imp_size = kavutil.get_uint32(mm, pe_pos + 0x84)  # Import API 크기

            if imp_rva:  # Import API 존재
                imp_api = {}

                # print 'IMP : %08X' % imp_rva
                imp_off = self.rva_to_off(imp_rva)[0]
                # print hex(imp_off), imp_size
                imp_data = mm[imp_off:imp_off + imp_size]
                for i in range(imp_size / 0x14):  # DLL 정보 크기가 0x14
                    try:
                        dll_rva = kavutil.get_uint32(imp_data,
                                                     (i * 0x14) + 0xC)
                        api_rva = kavutil.get_uint32(imp_data, (i * 0x14))
                        bo = 2
                        if api_rva == 0:
                            api_rva = kavutil.get_uint32(
                                imp_data, (i * 0x14) + 0x10)
                            bo = 0

                        # print hex(api_rva)
                        if dll_rva == 0:  # DLL 정보가 없음
                            break

                        t_off = self.rva_to_off(dll_rva)[0]
                        dll_name = p_str.search(mm[t_off:t_off + 0x20]).group()
                        # print '[+]', dll_name
                        imp_api[dll_name] = []

                        t_off = self.rva_to_off(api_rva)[0]
                        while True:
                            try:
                                api_name_rva = kavutil.get_uint32(mm, t_off)
                            except struct.error:
                                break

                            if api_name_rva & 0x80000000 == 0x80000000:  # Odinal API
                                t_off += 4
                                continue

                            if api_name_rva == 0:
                                break

                            t = self.rva_to_off(api_name_rva)[0]
                            # print hex(t_off), hex(t)
                            api_name = p_str.search(mm[t + bo:t + bo +
                                                       0x20]).group()
                            # print '   ', api_name
                            imp_api[dll_name].append(api_name)
                            t_off += 4
                    except struct.error:
                        pass

                pe_format['Import_API'] = imp_api

            # 디지털 인증서 분석
            cert_off = kavutil.get_uint32(mm, pe_pos +
                                          0x98)  # 디지털 인증서 위치(유일하게 RVA가 아닌 오프셋)
            cert_size = kavutil.get_uint32(mm, pe_pos + 0x9C)  # 디지털 인증서 크기

            if cert_off:  # 디지털 인증서 존재
                if cert_off + cert_size <= len(mm[:]):  # UPack의 경우 이상한 값이 셋팅 됨
                    pe_format['CERTIFICATE_Offset'] = cert_off
                    pe_format['CERTIFICATE_Size'] = cert_size

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

                print
                kavutil.vprint('PE')
                kavutil.vprint(None, 'EntryPoint',
                               '%08X' % pe_format['EntryPoint'])
                kavutil.vprint(None, 'EntryPoint (Section)',
                               '%d' % pe_format['EntryPoint_in_Section'])

                # 섹션 보기
                if section_num:
                    print
                    kavutil.vprint('Section Header')
                    print '    %-8s %-8s %-8s %-8s %-8s %-8s' % (
                        'Name', 'VOFF', 'VSIZE', 'FOFF', 'FSIZE', 'EXEC')
                    print '    ' + ('-' * (9 * 6 - 1))

                    for s in self.sections:
                        print '    %-8s %08X %08X %08X %08X %-05s' % (
                            s['Name'], s['RVA'], s['VirtualSize'],
                            s['PointerRawData'], s['SizeRawData'],
                            s['Characteristics'] & 0x20000000 == 0x20000000)

                if section_num:
                    print
                    kavutil.vprint('Section MD5')
                    print '    %-8s %-8s %-32s' % ('Name', 'FSIZE', 'MD5')
                    print '    ' + ('-' * ((9 * 2 - 1) + 32))

                    for s in self.sections:
                        if s['Characteristics'] & 0x20000000 == 0x20000000:
                            off = s['PointerRawData']
                            size = s['SizeRawData']
                            fmd5 = cryptolib.md5(mm[off:off + size])
                            print '    %-8s %8d %s' % (s['Name'], size, fmd5)

                print
                kavutil.vprint('Entry Point (Raw)')
                print
                kavutil.HexDump().Buffer(mm[:], pe_format['EntryPointRaw'],
                                         0x80)
                print

        except ValueError:
            return None

        return pe_format
Ejemplo n.º 47
0
def RebuildPE(src, ssize, dst, dsize, ep, upx0, upx1, magic, dend):
    try:
        foffset = uint32(0xD0 + 0xF8)

        if len(src) == 0 or len(dst) == 0:
            raise SystemError

        for valign in magic:
            if (ep - upx1 + valign <= ssize - 5) and \
                            ord(src[ep - upx1 + valign - 2]) == 0x8D and \
                            ord(src[ep - upx1 + valign - 1]) == 0xBE:
                break

        if not valign and (ep - upx1 + 0x80 < ssize - 8):
            i = 0
            while True:
                b1 = ord(src[ep - upx1 + 0x80 + 0 + i])
                b2 = ord(src[ep - upx1 + 0x80 + 1 + i])

                if b1 == 0x8D and b2 == 0xBE:
                    b3 = ord(src[ep - upx1 + 0x80 + 6 + i])
                    b4 = ord(src[ep - upx1 + 0x80 + 7 + i])

                    if b3 == 0x8B and b4 == 0x07:
                        valign = 0x80 + i + 2
                        break
                i += 1

        if valign and ISCONTAINED(0, ssize, ep - upx1 + valign, 4):
            dst_imports = struct.unpack('<l', src[ep - upx1 + valign:ep - upx1 + valign + 4])[0]

            realstuffsz = dst_imports

            if realstuffsz >= dsize:
                raise SystemError
            else:
                pehdr = dst_imports

                while (pehdr + 8 < dsize) and (struct.unpack('<l', dst[pehdr:pehdr + 4])[0]):
                    pehdr += 8
                    while (pehdr + 2 < dsize) and ord(dst[pehdr]):
                        pehdr += 1
                        while (pehdr + 2 < dsize) and ord(dst[pehdr]):
                            pehdr += 1
                        pehdr += 1
                    pehdr += 1
                pehdr += 4

                sections, valign, sectcnt = checkpe(dst, dsize, pehdr)
                if not sections:
                    pehdr = 0

        if not pehdr and dend > (0xF8 + 0x28):
            pehdr = dend - 0xF8 - 0x28

            while int32(pehdr) > 0:
                sections, valign, sectcnt = checkpe(dst, dsize, pehdr)
                if sections:
                    break
                pehdr -= 1

            realstuffsz = pehdr
            if not realstuffsz:
                raise SystemError

        if not pehdr:
            rebsz = uint32(PESALIGN(dend, 0x1000))
            # print hex(rebsz)
            # To Do

        foffset = PESALIGN(foffset + 0x28 * sectcnt, valign)

        for upd in range(sectcnt):
            t = kavutil.get_uint32(dst, sections + 8)
            vsize = uint32(PESALIGN(t, valign))

            t = kavutil.get_uint32(dst, sections + 12)
            urva = uint32(PESALIGN(t, valign))

            if not (upx0 + realstuffsz >= urva + vsize):
                raise SystemError

            t = struct.pack('<LLLL', vsize, urva, vsize, foffset)
            dest = dst[:sections + 8]
            dest += t
            dest += dst[sections + 24:]
            dst = dest

            foffset += vsize
            sections += 0x28

        t = struct.pack('<L', valign)
        dest = dst[:pehdr + 0x3C]
        dest += t
        dest += dst[pehdr + 0x3C + 4:]
        dst = dest

        newbuf = ['\x00'] * foffset

        for i in range(len(HEADERS)):
            newbuf[i] = HEADERS[i]

        for i in range(0xf8 + 0x28 * sectcnt):
            newbuf[0xD0 + i] = dst[pehdr + i]

        sections = pehdr + 0xF8

        for upd in range(sectcnt):
            t1 = kavutil.get_uint32(dst, sections + 20)
            t2 = kavutil.get_uint32(dst, sections + 12)
            t3 = kavutil.get_uint32(dst, sections + 16)

            for i in range(t3):
                newbuf[t1 + i] = dst[t2 - upx0 + i]

            sections += 0x28

        if foffset > dsize + 8192:
            raise SystemError

        dsize = foffset

        upx_d = ''
        for ch in newbuf:
            upx_d += ch
    except:
        return ''

    return upx_d
Ejemplo n.º 48
0
    def parse(self):
        mm = self.mm

        pe_format = {'PE_Position': 0, 'EntryPoint': 0, 'SectionNumber': 0,
                     'Sections': None, 'EntryPointRaw': 0, 'FileAlignment': 0}

        try:
            if mm[0:2] != 'MZ':  # MZ로 시작하나?
                raise ValueError

            dos_header = DOS_HEADER()
            ctypes.memmove(ctypes.addressof(dos_header), mm[0:], ctypes.sizeof(dos_header))

            # PE 표식자 위치 알아내기
            pe_pos = dos_header.e_lfanew

            # PE 인가?
            if mm[pe_pos:pe_pos + 4] != 'PE\x00\x00':
                raise ValueError

            pe_format['PE_Position'] = pe_pos

            # File Header 읽기
            file_header = FILE_HEADER()
            file_header_size = ctypes.sizeof(file_header)  # file_header_size : 0x14
            ctypes.memmove(ctypes.addressof(file_header), mm[pe_pos + 4:], file_header_size)

            # Optional Header 읽기
            optional_header = OPTIONAL_HEADER()
            optional_header_size = ctypes.sizeof(optional_header)
            ctypes.memmove(ctypes.addressof(optional_header), mm[pe_pos + 4 + file_header_size:], optional_header_size)

            # Optional Header의 Magic ID?
            if optional_header.Magic != 0x10b:
                raise ValueError

            # Entry Point 구하기
            pe_ep = optional_header.AddressOfEntryPoint
            pe_format['EntryPoint'] = pe_ep

            # Image Base 구하기
            pe_img = optional_header.ImageBase
            pe_format['ImageBase'] = pe_img

            # File Alignment 구하기
            self.pe_file_align = optional_header.FileAlignment
            pe_format['FileAlignment'] = self.pe_file_align

            # Section 개수 구하기
            section_num = file_header.NumberOfSections
            pe_format['SectionNumber'] = section_num

            # Optional Header 크기 구하기
            opthdr_size = file_header.SizeOfOptionalHeader
            pe_format['OptionalHederSize'] = opthdr_size

            # Data Directory 읽기
            data_directory_size = ctypes.sizeof(DATA_DIRECTORY())  # data_directory_size : 8
            num_data_directory = (opthdr_size - optional_header_size) / data_directory_size
            off_data_directory = pe_pos + 4 + file_header_size + optional_header_size

            for i in range(num_data_directory):
                dx = DATA_DIRECTORY()
                ctypes.memmove(ctypes.addressof(dx),
                               mm[off_data_directory + (i * data_directory_size):],
                               data_directory_size)

                self.data_directories.append(dx)

            # 섹션 시작 위치
            section_pos = pe_pos + 4 + file_header_size + opthdr_size

            # 모든 섹션 정보 추출
            for i in range(section_num):
                section = {}

                section_header = SECTION_HEADER()
                section_header_size = ctypes.sizeof(section_header)  # section_header_size : 0x28

                s = section_pos + (section_header_size * i)
                ctypes.memmove(ctypes.addressof(section_header), mm[s:], section_header_size)

                sec_name = ctypes.cast(section_header.Name, ctypes.c_char_p)
                section['Name'] = sec_name.value.replace('\x00', '')
                section['VirtualSize'] = section_header.Misc_VirtualSize
                section['RVA'] = section_header.VirtualAddress
                section['SizeRawData'] = section_header.SizeOfRawData
                section['PointerRawData'] = section_header.PointerToRawData
                section['Characteristics'] = section_header.Characteristics

                self.sections.append(section)

            pe_format['Sections'] = self.sections

            # EntryPoint의 파일에서의 위치 구하기
            ep_raw, sec_idx = self.rva_to_off(pe_ep)
            pe_format['EntryPointRaw'] = ep_raw  # EP의 Raw 위치
            pe_format['EntryPoint_in_Section'] = sec_idx  # EP가 포함된 섹션

            # 리소스 분석
            try:
                rsrc_rva = self.data_directories[image_directory_entry.RESOURCE].VirtualAddress  # 리소스 위치(RVA)
                rsrc_size = self.data_directories[image_directory_entry.RESOURCE].Size  # 리소스 크기
            except IndexError:
                rsrc_rva = 0
                rsrc_size = 0

            if rsrc_rva:  # 리소스가 존재한가?
                try:
                    rsrc_off, rsrc_idx = self.rva_to_off(rsrc_rva)  # 리소스 위치 변환

                    if rsrc_off > self.filesize:
                        raise ValueError

                    t_size = self.sections[rsrc_idx]['SizeRawData']
                    if not (len(mm[rsrc_off:rsrc_off + rsrc_size]) == rsrc_size or \
                        len(mm[rsrc_off:rsrc_off + t_size]) == t_size):  # 충분한 리소스가 존재하지 않음
                        raise ValueError

                    # Type 체크
                    num_type_name = kavutil.get_uint16(mm, rsrc_off+0xC)
                    num_type_id = kavutil.get_uint16(mm, rsrc_off + 0xE)

                    for i in range(num_type_name + num_type_id):
                        type_id = kavutil.get_uint32(mm, rsrc_off + 0x10 + (i*8))
                        name_id_off = kavutil.get_uint32(mm, rsrc_off + 0x14 + (i * 8))

                        # Type이 사용자가 정의한 이름 or RCDATA?
                        if type_id & 0x80000000 == 0x80000000 or type_id == 0xA or type_id == 0:
                            if type_id & 0x80000000 == 0x80000000:
                                # 사용자가 정의한 이름 추출
                                string_off = (type_id & 0x7FFFFFFF) + rsrc_off
                                len_name = kavutil.get_uint16(mm, string_off)
                                rsrc_type_name = mm[string_off + 2:string_off + 2 + (len_name * 2):2]
                            elif type_id == 0xA:
                                rsrc_type_name = 'RCDATA'
                            else:
                                rsrc_type_name = '%d' % type_id

                            # Name ID
                            name_id_off = (name_id_off & 0x7FFFFFFF) + rsrc_off
                            if name_id_off > self.filesize:
                                raise ValueError

                            num_name_id_name = kavutil.get_uint16(mm, name_id_off + 0xC)
                            num_name_id_id = kavutil.get_uint16(mm, name_id_off + 0xE)

                            for j in range(num_name_id_name + num_name_id_id):
                                name_id_id = kavutil.get_uint32(mm, name_id_off + 0x10 + (j * 8))
                                language_off = kavutil.get_uint32(mm, name_id_off + 0x14 + (j * 8))

                                # 리소스 영역의 최종 이름 생성
                                if name_id_id & 0x80000000 == 0x80000000:
                                    string_off = (name_id_id & 0x7FFFFFFF) + rsrc_off
                                    if string_off > self.filesize:
                                        raise ValueError

                                    len_name = kavutil.get_uint16(mm, string_off)
                                    rsrc_name_id_name = mm[string_off + 2:string_off + 2 + (len_name * 2):2]
                                    string_name = rsrc_type_name + '/' + rsrc_name_id_name
                                else:
                                    string_name = rsrc_type_name + '/' + hex(name_id_id).upper()[2:]

                                # Language
                                language_off = (language_off & 0x7FFFFFFF) + rsrc_off
                                if language_off > self.filesize:
                                    raise ValueError

                                num_language_name = kavutil.get_uint16(mm, language_off + 0xC)
                                num_language_id = kavutil.get_uint16(mm, language_off + 0xE)

                                for k in range(num_language_name + num_language_id):
                                    # language_id = kavutil.get_uint32(mm, language_off + 0x10 + (k * 8))
                                    data_entry_off = kavutil.get_uint32(mm, language_off + 0x14 + (k * 8))

                                    data_entry_off = (data_entry_off & 0x7FFFFFFF) + rsrc_off

                                    data_rva = kavutil.get_uint32(mm, data_entry_off)
                                    data_off, _ = self.rva_to_off(data_rva)
                                    if data_off > self.filesize:
                                        continue

                                    data_size = kavutil.get_uint32(mm, data_entry_off + 4)
                                    if data_size > self.filesize:
                                        continue

                                    if data_size > 8192:  # 최소 8K 이상인 리소스만 데이터로 추출
                                        if 'Resource_UserData' in pe_format:
                                            pe_format['Resource_UserData'][string_name] = (data_off, data_size)
                                        else:
                                            pe_format['Resource_UserData'] = {string_name: (data_off, data_size)}
                except (struct.error, ValueError) as e:
                    pass

                # if 'Resource_UserData' in pe_format:
                #     print pe_format['Resource_UserData']

            # Import API 분석
            try:
                imp_rva = self.data_directories[image_directory_entry.IMPORT].VirtualAddress  # Import API 위치(RVA)
                imp_size = self.data_directories[image_directory_entry.IMPORT].Size  # Import API 크기
            except IndexError:
                imp_rva = 0
                imp_size = 0

            if imp_rva:  # Import API 존재
                imp_api = {}

                # print 'IMP : %08X' % imp_rva
                imp_off = self.rva_to_off(imp_rva)[0]
                # print hex(imp_off), imp_size
                imp_data = mm[imp_off:imp_off+imp_size]
                if len(imp_data) == imp_size:
                    for i in range(imp_size / 0x14):  # DLL 정보 크기가 0x14
                        try:
                            dll_rva = kavutil.get_uint32(imp_data, (i*0x14)+0xC)
                            api_rva = kavutil.get_uint32(imp_data, (i * 0x14))
                            bo = 2
                            if api_rva == 0:
                                api_rva = kavutil.get_uint32(imp_data, (i*0x14)+0x10)
                                bo = 0

                            # print hex(api_rva)
                            if dll_rva == 0:  # DLL 정보가 없음
                                break

                            t_off = self.rva_to_off(dll_rva)[0]
                            dll_name = p_str.search(mm[t_off:t_off+0x20]).group()
                            # print '[+]', dll_name
                            imp_api[dll_name] = []

                            t_off = self.rva_to_off(api_rva)[0]
                            while True:
                                try:
                                    api_name_rva = kavutil.get_uint32(mm, t_off)
                                except struct.error:
                                    break

                                if api_name_rva & 0x80000000 == 0x80000000:  # Odinal API
                                        t_off += 4
                                        continue

                                if api_name_rva == 0:
                                    break

                                t = self.rva_to_off(api_name_rva)[0]
                                # print hex(t_off), hex(t)
                                api_name = p_str.search(mm[t+bo:t+bo+0x20]).group()
                                # print '   ', api_name
                                imp_api[dll_name].append(api_name)
                                t_off += 4
                        except struct.error:
                            pass
                # end if

                pe_format['Import_API'] = imp_api

            # 디지털 인증서 분석
            try:
                cert_off = self.data_directories[image_directory_entry.SECURITY].VirtualAddress  # 유일하게 RVA가 아닌 오프셋
                cert_size = self.data_directories[image_directory_entry.SECURITY].Size  # 디지털 인증서 크기
            except IndexError:
                cert_off = 0
                cert_size = 0

            if cert_off:  # 디지털 인증서 존재
                if cert_off + cert_size <= len(mm[:]):  # UPack의 경우 이상한 값이 셋팅 됨
                    pe_format['CERTIFICATE_Offset'] = cert_off
                    pe_format['CERTIFICATE_Size'] = cert_size

            # Debug 정보 분석
            try:
                debug_rva = self.data_directories[image_directory_entry.DEBUG].VirtualAddress  # RVA
                debug_size = self.data_directories[image_directory_entry.DEBUG].Size  # 크기
                if debug_size < 0x1C:
                    raise ValueError
            except (IndexError, ValueError) as e:
                debug_rva = 0
                debug_size = 0

            if debug_rva:  # Debug 정보 존재
                t = self.rva_to_off(debug_rva)[0]
                debug_off = kavutil.get_uint32(mm, t + 0x18)
                debug_size = kavutil.get_uint32(mm, t + 0x10)

                debug_data = mm[debug_off:debug_off + debug_size]

                if debug_data[:4] == 'RSDS':
                    pe_format['PDB_Name'] = debug_data[0x18:]
                else:
                    pe_format['PDB_Name'] = 'Not support Type : %s' % debug_data[:4]

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

                print
                kavutil.vprint('PE')
                kavutil.vprint(None, 'EntryPoint', '%08X' % pe_format['EntryPoint'])
                kavutil.vprint(None, 'EntryPoint (Section)', '%d' % pe_format['EntryPoint_in_Section'])

                # 섹션 보기
                if section_num:
                    print
                    kavutil.vprint('Section Header')
                    print '    %-8s %-8s %-8s %-8s %-8s %-8s' % ('Name', 'VOFF', 'VSIZE', 'FOFF', 'FSIZE', 'EXEC')
                    print '    ' + ('-' * (9*6 - 1))

                    for s in self.sections:
                        print '    %-8s %08X %08X %08X %08X %-05s' % (s['Name'], s['RVA'], s['VirtualSize'],
                                                                     s['PointerRawData'], s['SizeRawData'],
                                                                     s['Characteristics'] & 0x20000000 == 0x20000000)

                if section_num:
                    print
                    kavutil.vprint('Section MD5')
                    print '    %-8s %-8s %-32s' % ('Name', 'FSIZE', 'MD5')
                    print '    ' + ('-' * ((9 * 2 - 1)+32))

                    for s in self.sections:
                        # if s['Characteristics'] & 0x20000000 == 0x20000000:
                        off = s['PointerRawData']
                        size = s['SizeRawData']
                        fmd5 = cryptolib.md5(mm[off:off+size]) if size else '-'
                        print '    %-8s %8d %s' % (s['Name'], size, fmd5)

                print
                kavutil.vprint('Entry Point (Raw)')
                print
                kavutil.HexDump().Buffer(mm[:], pe_format['EntryPointRaw'], 0x80)
                print
                if 'PDB_Name' in pe_format:
                    kavutil.vprint('PDB Information')
                    kavutil.vprint(None, 'Name', '%s' % repr(pe_format['PDB_Name']))
                    print repr(pe_format['PDB_Name'])
                    print

        except (ValueError, struct.error) as e:
            return None

        return pe_format
Ejemplo n.º 49
0
def ModifyCallAddr(src, dest, ep, upx0, upx1, baseaddr):
    try:
        # Call 개수 확인
        ssize = len(src)
        pos = ep - upx1
        call_count = -1

        while True:
            if pos > ssize - 13:
                break

            if ord(src[pos]) == 0xE9 and \
                    ord(src[pos + 3]) == 0xFF and \
                    ord(src[pos + 4]) == 0xFF and \
                    ord(src[pos + 5]) == 0x5E and \
                    ord(src[pos + 6]) == 0x89 and \
                    ord(src[pos + 7]) == 0xF7 and \
                    ord(src[pos + 8]) == 0xB9:
                call_count = kavutil.get_uint32(src, pos + 9)
                break
            else:
                pos += 1

        if call_count == -1:
            raise SystemError

        # Call Address 수정
        dst = ''
        pos = 0
        dcur = 0
        dsize = len(dest)

        while call_count:
            if pos > dsize - 5:
                break

            if (ord(dest[pos]) == 0xE9 or ord(dest[pos]) == 0xE8) and \
                    ord(dest[pos + 1]) == 0x01:
                eax = kavutil.get_uint32(dest, pos + 1)
                ax = eax & 0xFFFF
                ax >>= 8
                eax &= 0xFFFF0000
                eax |= ax
                eax = ROL(eax, 0x10)
                ah = (eax & 0xFF00) >> 8
                al = (eax & 0x00FF) << 8
                ax = ah | al
                eax &= 0xFFFF0000
                eax |= ax
                eax = uint32(eax - (baseaddr + upx0 + pos + 1))
                eax = uint32(eax + (baseaddr + upx0))
                dst += dest[dcur:pos + 1]
                dst += struct.pack('<L', eax)

                pos += 5
                dcur = pos
                call_count -= 1
            else:
                pos += 1

        dst += dest[dcur:]
    except:
        return None

    return dst
Ejemplo n.º 50
0
    def scan(self, filehandle, filename, fileformat, filename_ex):  # 악성코드 검사
        try:
            mm = filehandle

            if mm[0:8] != '\x4c\x00\x00\x00\x01\x14\x02\x00':  # LNK 헤더 체크
                raise ValueError

            flag = kavutil.get_uint32(mm, 0x14)

            off = 0x4c
            if flag & 0x0001 == 0x0001:  # HasLinkTargetIDList
                clid_mycom = '14001F50E04FD020EA3A6910A2D808002B30309D'.decode(
                    'hex')
                if mm[off + 2:off + 2 + 0x14] != clid_mycom:  # MyComputer
                    raise ValueError

                off += 2
                while True:
                    size = kavutil.get_uint16(mm, off)
                    if size == 0:
                        off += 2
                        break
                    if ord(mm[off + 2]) == 0x32:
                        if mm[off + 0xe:off + 0xe + 7].lower() != 'cmd.exe':
                            raise ValueError

                    off += size

            if flag & 0x0002 == 0x0002:  # HasLinkInfo
                off += kavutil.get_uint16(mm, off)

            if flag & 0x0004 == 0x0004:  # HasName
                size = kavutil.get_uint16(mm, off)
                off += (2 + (size * 2))

            if flag & 0x0008 == 0x0008:  # HasRelativePath
                size = kavutil.get_uint16(mm, off)
                cmd_path = mm[off + 2:off + 2 + (size * 2):2].lower()

                # print cmd_path

                if cmd_path.find('cmd.exe') == -1:
                    raise ValueError
                off += (2 + (size * 2))

            if flag & 0x0010 == 0x0010:  # HasWorkingDir
                size = kavutil.get_uint16(mm, off)
                off += (2 + (size * 2))

            if flag & 0x0020 == 0x0020:  # HasArguments
                size = kavutil.get_uint16(mm, off)
                cmd_arg = mm[off + 2:off + 2 + (size * 2):2].lower()
                cmd_arg = cmd_arg.replace('^', '')

                # print cmd_arg

                # 악성코드 패턴을 비교한다.
                if self.p_http.search(cmd_arg):
                    return True, 'Trojan.LNK.Agent.gen', 0, kernel.INFECTED
        except (IOError, ValueError):
            pass

        # 악성코드를 발견하지 못했음을 리턴한다.
        return False, '', -1, kernel.NOT_FOUND
Ejemplo n.º 51
0
def ModifyCallAddr(src, dest, ep, upx0, upx1, baseaddr):
    try:
        # Call 개수 확인
        ssize = len(src)
        pos = ep - upx1
        call_count = -1

        while True:
            if pos > ssize - 13:
                break

            if ord(src[pos]) == 0xE9 and \
                    ord(src[pos + 3]) == 0xFF and ord(src[pos + 4]) == 0xFF and \
                    ord(src[pos + 5]) == 0x5E and ord(src[pos + 6]) == 0x89 and \
                    ord(src[pos + 7]) == 0xF7 and ord(src[pos + 8]) == 0xB9:
                call_count = kavutil.get_uint32(src, pos + 9)
                break
            else:
                pos += 1

        if call_count == -1:
            raise SystemError

        # Call Address 수정
        dst = ''
        pos = 0
        dcur = 0
        dsize = len(dest)

        while call_count:
            if pos > dsize - 5:
                break

            if (ord(dest[pos]) == 0xE9 or ord(dest[pos]) == 0xE8) and \
                    ord(dest[pos + 1]) == 0x01:
                eax = kavutil.get_uint32(dest, pos + 1)
                ax = eax & 0xFFFF
                ax >>= 8
                eax &= 0xFFFF0000
                eax |= ax
                eax = ROL(eax, 0x10)
                ah = (eax & 0xFF00) >> 8
                al = (eax & 0x00FF) << 8
                ax = ah | al
                eax &= 0xFFFF0000
                eax |= ax
                eax = uint32(eax - (baseaddr + upx0 + pos + 1))
                eax = uint32(eax + (baseaddr + upx0))
                dst += dest[dcur:pos + 1]
                dst += struct.pack('<L', eax)

                pos += 5
                dcur = pos
                call_count -= 1
            else:
                pos += 1

        dst += dest[dcur:]
        '''
        fp = open('call.dmp', 'wb')
        fp.write(dst)
        fp.close()
        '''
    except:
        return None

    return dst
Ejemplo n.º 52
0
    def unarc(self, arc_engine_id, arc_name, fname_in_arc):
        fp = None
        mm = None
        data = None

        if arc_engine_id.find('arc_upx') != -1:
            filename = fname_in_arc

            try:
                # UPX로 압축된 파일 열기
                fp = open(arc_name, 'rb')
                mm = mmap.mmap(fp.fileno(), 0, access=mmap.ACCESS_READ)

                p = pe.PE(mm, False, arc_name)
                pe_format = p.parse()  # PE 파일 분석
                if pe_format is None:
                    return ValueError

                pe_img = pe_format['ImageBase']
                pe_ep = pe_format['EntryPoint']
                sections = pe_format['Sections']
                ep_raw = pe_format['EntryPointRaw']  # EP의 Raw 위치
                ep_nsec = pe_format['EntryPoint_in_Section']  # EP는 몇번째 섹션에 있는가?

                foff = 0
                ssize = 0
                dsize = 0

                for section in sections:
                    ssize = section['VirtualSize']
                    rva = section['RVA']
                    if rva <= pe_ep < rva+ssize:
                        foff = section['PointerRawData']
                        i = sections.index(section)
                        if i != 0:
                            upx0 = sections[i-1]['RVA']
                            upx1 = sections[i]['RVA']
                            dsize = sections[i-1]['VirtualSize'] + ssize
                        break

                if ssize == 0 or dsize == 0:
                    raise ValueError

                upx_data_rva = kavutil.get_uint32(mm, ep_raw+2)
                sec_rva = sections[ep_nsec]['RVA']

                skew = upx_data_rva - sec_rva - pe_img

                if mm[ep_raw+1] != '\xBE' or skew <= 0 or skew > 0xFFF:
                    skew = 0
                elif skew > ssize:
                    skew = 0
                else:
                    raise ValueError

                data = mm[foff+skew:foff+ssize-skew]

                unpack_data = ''  # UPX 해제된 이미지

                if arc_engine_id[8:] == 'nrv2b':  # UPX 알고리즘 중 nrv2b 압축인가?
                    try:
                        ret_val, unpack_data = upx_inflate2b(data, dsize, pe_ep, upx0, upx1, pe_img)
                    except OverflowError:
                        raise ValueError

                if self.verbose:
                    kavutil.vprint('Decompress')
                    kavutil.vprint(None, 'Compressed Size', '%d' % len(data))
                    if unpack_data == '':  # 압축 해제 실패
                        kavutil.vprint(None, 'Decompress Size', 'Error')
                    else:
                        kavutil.vprint(None, 'Decompress Size', '%d' % len(unpack_data))
                    print

                if unpack_data == '':  # 압축 해제 실패
                    raise ValueError

                data = unpack_data
            except IOError:
                pass
            except ValueError:
                pass

            if mm:
                mm.close()

            if fp:
                fp.close()

            return data

        return None