Exemple #1
0
    def get_result(self, audio_path):
        def softmax(x):
            e_x = np.exp(x - np.max(x))
            return e_x / e_x.sum(axis=0)

        print('Generate side channel...')
        y_s = utils.get_side(audio_path)
        print('Rendering spectrum...')
        utils.get_spectrum(y_s, 0, 'temp', max=20)
        spectrum_list = utils.get_file_list('temp')
        print('Valid samples...')
        fin = np.zeros(4)
        for i_idx in range(len(spectrum_list)):
            norm_img = self.img_preprocess(spectrum_list[i_idx])
            result = self.session.run([], {self.model_input: norm_img})[0][0]
            result = softmax(result)
            fin[np.argmax(result)] += 1
            print(
                f'Sample {i_idx+1} -> {self.r_map[np.argmax(result)]}, Prob:{np.max(result)*100:.3f}%'
            )
        if fin[0] != len(spectrum_list):
            fin[0] = 0
            print(f'Final result: {self.r_map[np.argmax(fin)]}')
        else:
            print('Final result: Lossless')
Exemple #2
0
    def __split_bc_into_lines(self, codes: list,
                              lnotab: list):  #PASS  2019/7/4
        '''
        code : 字节码对
        lnotab : co_lnotab 字段
        
        !!! 暂不支持出现单行增量大于 255 的行号表
        '''
        tab = list(lnotab[2:])  #去除第一个偏移增量对(起始行)
        tab = utils.get_side(utils.to_pairs(tab))  #将行号表结成对取一边
        tab.append(len(codes) * 2 - sum(tab))  #增加最后一行的偏移增量

        tl = []  #总字节码序列
        ttl = []  #总序列中的子序列
        ofsi = tp = 0  #ofsi : 偏移增量  tp : 增量表的指针

        for cp in codes + [None]:  #加一个None, 防止越界
            if ofsi == tab[tp]:
                tl.append(ttl.copy())
                ttl = []
                tp += 1  #得到一行, 指针右移
                ofsi = 0  #将偏移增量设置为0
            ttl.append(cp)
            ofsi += 2  #将偏移增量增加 2 个 '字节' (一个PyByteCode占一个字节)

        return tl
Exemple #3
0
    def is_def_attr(self, codes: list):
        '''
        codes: 字节码对
        '''
        scodes = utils.get_side(codes)

        if opmap['STORE_ATTR'] in scodes and opmap["SETUP_LOOP"] not in scodes:
            return True
        return False
Exemple #4
0
    def is_store_subscr_expr(self, code: list):
        '''
        codes: 字节码对
        '''
        scodes = utils.get_side(code)

        if opmap['STORE_SUBSCR'] in scodes:
            return True
        return False
Exemple #5
0
    def is_import_expr(self, code: list):
        '''
        codes: 字节码对
        '''
        scodes = utils.get_side(code)

        if opmap['IMPORT_NAME'] in scodes:
            return True
        return False
Exemple #6
0
    def is_def_var(self, codes: list):
        '''
        codes: 字节码对
        '''
        codes = utils.get_side(codes)

        if (opmap['STORE_NAME'] in codes or opmap['STORE_FAST'] in codes) \
                and opmap['IMPORT_NAME'] not in codes and opmap["SETUP_LOOP"] not in codes:
            return True

        return False
Exemple #7
0
    def is_return_expr(self, codes: list):
        '''
        codes: 字节码对
        '''
        scodes = utils.get_side(codes)

        if codes[-2:] == [(100, 0), (83, 0)] and len(codes) > 2:
            #为了排除隐式 return
            return False

        if scodes[-1] != opmap['RETURN_VALUE']:
            #return 语句的 RETURN_VALUE 在最后
            return False

        return True
Exemple #8
0
    def is_assert_expr(self, codes: list):
        '''
        codes: 字节码对
        '''
        #accert 无论如何都会压入一个AssertionError对象
        scodes = utils.get_side(codes)

        if opmap['LOAD_GLOBAL'] in scodes:
            tc = scodes[::-1]  #翻转,寻找最靠后的LOAD_GLOBAL
            ei = tc.index(opmap['LOAD_GLOBAL'])  #寻找最靠后的LOAD_GLOBAL的地址
            ti = codes[::-1][ei][1]  #颠倒字节码对数组,寻找目标字节码对,取出参数

            if self.__load_name(ti) == 'AssertionError':
                return True

            return False
Exemple #9
0
    def is_if_expr(self, codes: list):
        '''
        codes: 字节码对
        !!!暂不支持单行 if 语句
        '''
        #fest = self.__find_jump_fastest(codes) #寻找最远的偏移量
        '''
        python 的 and or 表达式经过了很好的优化,但是,对于反编译来说,这是个噩梦!!!
        我甚至用了2天的时间来找python对于and or语句的规律,例如整个表达式的结束。
        但值得我欣慰的是,它只是一个表达式!!!!
        '''

        scodes = utils.get_side(codes)
        if opname[scodes[-1]] in ('POP_JUMP_IF_FALSE', 'POP_JUMP_IF_TRUE'):
            #如果最后是 POP_JUMP_IF_FALSE 或 POP_JUMP_IF_TRUE,就判断是 if 语句
            return True

        return False
Exemple #10
0
    def __find_jump_fastest(self, codes: list):
        '''
        寻找在 POP_JUMP 中跳得最远的偏移量
        codes : 需要用来判断的字节码对
        '''
        scodes = utils.get_side(codes)
        cp = 0  #字节码对指针
        fest = 0  #最远的偏移量

        for c in scodes:
            if opname[c] in ('POP_JUMP_IF_TRUE', 'POP_JUMP_IF_FALSE',
                             'JUMP_IF_TRUE_OR_POP', 'JUMP_IF_FALSE_OR_POP'):
                if codes[cp][1] > fest:  #如果现偏移量大于原偏移量
                    fest = codes[cp][1]
            cp += 1

        if fest <= 0:
            raise error.DecomplierError('The jump target can not be 0')

        return fest
Exemple #11
0
    def __make_line(self, codes: list):
        '''
        codes : 所有已经分行的字节码对
        将反编译出来的行写入文件
        '''
        ln_index = 0  #行号索引

        for ln in codes:  #codes: 整个已分行co_code, ln : 每行
            if self.__reco.is_return_expr(ln):  #如果是 return expr
                beh = 'return {0}'
                #开始处理 POP_TOP 以下, RETURN_VALUE 以上的字节码

                if opmap['POP_TOP'] in utils.get_side(ln):  #寻找行里是否有POP_TOP
                    lln = ln[::-1]  #将该字节码颠倒,开始寻找最靠后的POP_TOP
                    pti = lln.index(opmap['POP_TOP'])  #寻找最靠后的一个 POP_TOP
                    lln = lln[1:pti -
                              1][::-1]  #得到RETURN_VALUE ~ POP_TOP之间的字节码,并翻转
                else:
                    #一般来说,如果没有POP_TOP, 那么这个return表达式就是独立的
                    lln = ln[:-1]

                expr = self.__make_expr(lln)  #生成return之后的表达式
                self.__add_line(beh.format(expr))  #将结果添加到源码文件

            elif self.__reco.is_assert_expr(ln):
                beh = 'assert {0}'
                hsn = False  #如果assert后面出现了not
                #开始处理 LOAD_GLOBAL 以上的字节码对
                sc = utils.get_side(ln)[::-1]  #取出一边,并颠倒
                try:
                    ci = sc.index(opmap['POP_JUMP_IF_TRUE'])
                    #如果assert后面出现not,则应该是POP_JUMP_IF_FALSE
                except ValueError:
                    hsn = True
                    ci = ci = sc.index(opmap['POP_JUMP_IF_FALSE'])

                ci += 1  #不包括POP_JUMP_IF_XXXX 指令

                cs = ln[::-1][ci:][::-1]  #截取 POP_JUMP_IF_FALSE 以上的字节码对
                cond = self.__make_expr(cs)  #取得表达式

                self.__add_line(beh.format(('not ' if hsn else '') +
                                           cond))  #将结果添加至源码行中,如果hsn,则将'not '加入

            elif self.__reco.is_def_var(ln):
                isf = False  #如果是STORE_FAST
                beh = '{0} = {1}'
                #处理STORE_XXX以上的字节码

                rc = utils.get_side(ln)  #取出一边

                try:
                    ci = rc.index(opmap['STORE_NAME'])  #找到STORE_NAME的位置
                except ValueError:
                    #当是STORE_FAST的时候
                    isf = True
                    ci = rc.index(opmap['STORE_FAST'])  #找到STORE_FAST的位置

                exprcs = ln[:ci]  #截取STORE_XXX以上的字节码
                expr = self.__make_expr(exprcs)  #生成表达式
                argv = ln[ci][1]  #得到 STORE_XXX 的参数

                if not isf:
                    name = self.__load_name(argv)  #根据参数,得到变量名
                else:
                    name = self.__load_fast(argv)  #根据参数,得到变量名

                self.__add_line(beh.format(name, expr))

            elif self.__reco.is_def_attr(ln):
                #处理LOAD_NAME/LOAD_FAST,STORE_ATTR之间的字节码
                beh = '{0}.{1} = {2}'
                scs = utils.get_side(ln)[::-1]  #取一边,并颠倒
                si = scs.index(opmap['STORE_ATTR'])
                loni = lofi = logi = 0xffffffff  #先设置得很大,然后再比较那个小
                #因为是取最小值,而且也不能保证LOAD三家族都存在

                try:
                    loni = scs.index(opmap['LOAD_NAME'])  #寻找最近的LOAD_NAME
                except:
                    pass
                try:
                    lofi = scs.index(opmap['LOAD_FAST'])  #寻找最近的LOAD_FAST
                except:
                    pass
                try:
                    logi = scs.index(opmap['LOAD_GLOBAL'])  #寻找最近的LOAD_FAST
                except:
                    pass

                #比较loni 和 lofi的大小,取最小,因为当LOAD_NAME/LOAD_FAST没有时,不代表没有LOAD_FAST/LOAD_NAME
                loi = min(logi, lofi, loni)
                pexprc = ln[::-1][
                    si + 1:loi +
                    1][::-1]  #截取LOAD_NAME/LOAD_FAST以下STORE_ATTR以上的字节码,并回正
                pexpr = self.__make_expr(pexprc)
                #接着,再将loi以上的字节码截取,作为属性值
                vexprc = ln[::-1][loi + 1:][::-1]  #截取loi以上的字节码
                vexpr = self.__make_expr(vexprc)
                pname = self.__load_name(ln[::-1][si][1])  #获取属性名称

                self.__add_line(beh.format(pexpr, pname, vexpr))

            elif self.__reco.is_import_expr(ln):
                behn = 'import {0}'  #简单import
                behf = 'from {0} import {1}'  #from import

                has = False  #是否拥有as
                hsf = False  #是否是from import

                isfast = False  #如果是LOAD_FAST
                '''
                as 其实不用省略,因为 import os => import os as os
                但是为了人性化,还是选择省略
                '''
                #处理 STORE_NAME 以上的字节码

                sln = utils.get_side(ln)[::-1]
                try:
                    ci = sln.index(opmap['STORE_FAST'])  #如果是在函数/方法里面import
                except ValueError:
                    ci = sln.index(opmap['STORE_NAME'])  #在global域import

                cs = ln[::-1][ci + 1:][::-1]  #截取ci以上的字节码,然后回正
                scs = utils.get_side(cs)

                #开始处理ci以上的字节码
                if opmap['IMPORT_STAR'] in scs:  #如果是from xx import *
                    #尽管 from xx import * 不允许出现在函数中
                    imp_ni = scs.index(opmap['IMPORT_NAME'])
                    imp_name = self.__load_name(ln[imp_ni][1])

                    self.__add_line(behf.format(imp_name, '*'))
                elif opmap['IMPORT_FROM'] in scs:  #如果是 from xx import xx的样式
                    #最开头的IMPORT_FROM是from的位置
                    fi = scs.index(opmap['IMPORT_NAME'])
                    imp_pos = self.__load_name(ln[fi][1])  #from的位置
                    imp_nbr = self.__load_const(
                        ln[fi - 1][1])  #再往前就是import的内容,应该是一个元祖
                    imp_nbn = len(
                        imp_nbr
                    ) * 2  #元祖的长度*2为下面 IMPORT_NAME STORE_NAME 的数量,用于生成 __ as __
                    imp_nbrl = ln[fi + 1:fi + imp_nbn +
                                  1]  #得到import的成员和其别名(as xxx)
                    imp_ol = [
                        self.__load_name(op[1]) for op in imp_nbrl
                        if op[0] == 109
                    ]  #原成员名字
                    imp_nl = [
                        self.__load_fast(op[1]) for op in imp_nbrl
                        if op[0] in [125, 90]
                    ]  #现成员名字

                    if len(imp_ol) != len(imp_nl):
                        raise error.DecomplierError(
                            'len(imp_ol) != len(imp_nl)!\nimp_ol:' +
                            str(imp_ol) + '\nimp_nl:' + str(imp_nl))

                    onp = utils.merge(imp_ol, imp_nl)
                    ons = [
                        '{0}{1}'.format(o, (f' as {n}' if o != n else ''))
                        for o, n in onp
                    ]
                    #生成的 xx as xx列表 如果o, n同名,则取o

                    self.__add_line(behf.format(imp_pos, ', '.join(ons)))
                else:
                    ci = scs.index(opmap['IMPORT_NAME'])  #获取最开头的IMPORT_NAME位置
                    imp_n = self.__load_name(ln[ci][1])  #获取import名称
                    imp_as = self.__load_name(ln[ci + 1][1])  #import对象的as名称

                    if imp_n != imp_as:  #如果导入对象原名称不等于现名称
                        self.__add_line(behn.format(imp_n + ' as ' +
                                                    imp_as))  #将as加在后面
                        return
                    self.__add_line(behn.format(imp_n))  #不加as

            elif self.__reco.is_store_subscr_expr(ln):
                beh = '{0}[{1}] = {2}'
                scs = utils.get_side(ln)
                si = scs.index(opmap['STORE_SUBSCR'])  #得到STORE_SUBSCR的位置
                vli = []  #用于生成索引的表达式

                sv = {
                    opmap['LOAD_NAME']: lambda i: self.__load_name(i),
                    opmap['LOAD_GLOBAL']: lambda i: self.__load_name(i),
                    opmap['LOAD_FAST']: lambda i: self.__load_fast(i),
                }.get(
                    scs[si - 1], lambda i: error.DecomplierError(
                        'Un know opcode:{0}'.format(opname[scs[si - 1]])))(
                            ln[si][1])  #根据字节码类型,得到对应解决方案

            else:  #单独表达式
                expr = self.__make_expr(ln)
                self.__add_line(expr)

            ln_index += 1
Exemple #12
0
def do(src_path, dst_path, idx, noise=True):
    y_s = utils.get_side(src_path)
    if noise:
        utils.get_spectrum(y_s, idx, dst_path, noise=[0.001, 0.01])
    else:
        utils.get_spectrum(y_s, idx, dst_path)