美文网首页
2019 中关村网络与信息安全领域专项赛

2019 中关村网络与信息安全领域专项赛

作者: SamiraG | 来源:发表于2020-06-18 21:37 被阅读0次

参考链接

https://apeng.fun/2019/08/16/2019zgc_quals/
PYC 文件的简单分析
PYC文件格式分析
Python字节码解混淆
Python字节码解混淆之反控制流扁平化

src_leak

题目给了源码如下:

#include<iostream>
using namespace std;

typedef unsigned int uint;


template <bool Flag, class MaybeA, class MaybeB> class IfElse;

template <class MaybeA, class MaybeB>
class IfElse<true, MaybeA, MaybeB> {
public:
    using ResultType = MaybeA;
};

template <class MaybeA, class MaybeB>
class IfElse<false, MaybeA, MaybeB> {
public:
    using ResultType = MaybeB;
};

template <uint N, uint L, uint R> struct func1 {
    enum { mid = (L + R + 1) / 2 };

    using ResultType = typename IfElse<(N < mid * mid),
        func1<N, L, mid - 1>, func1<N, mid, R> >::ResultType;

    enum { result = ResultType::result };
};

template <uint N, uint L> struct func1<N, L, L> { enum { result = L }; };

template <uint N> struct _func1 { enum { result = func1<N, 1, N>::result }; };


template<size_t Input>
constexpr size_t func2 = (Input % 2) + func2< (Input / 2) >;

template<>
constexpr size_t func2<0> = 0;

template<size_t num>
constexpr size_t func3 = num % 2;

template<uint n, uint m>struct NEXTN {
    const static uint value = ((n % m != 0) * n);
};
template<uint n, uint m>struct NEXTM {
    const static uint value = (m * m <= n ? (m + 1) : 0);
};
template<uint n, uint m>struct TEST {
    const static uint value = TEST<NEXTN<n, m>::value, NEXTM<n, m>::value>::value;
};
template<uint m>struct TEST<0, m> {
    const static uint value = 0;
};
template<uint n>struct TEST<n, 0> {
    const static uint value = 1;
};
template<uint n>struct func4 {
    const static uint value = TEST<n, 2>::value;
};
template<>struct func4<1> {
    const static uint value = 0;
};
template<>struct func4<2> {
    const static uint value = 1;
};


int main(int argc, char**argv) {
    //input 5 uint numbers ,x1,x2,x3,x4,x5
    //the sum of them should be MIN


    cout << func3< func2<x1> > << endl;
    cout << func3< func2<x2> > << endl;
    cout << func3< func2<x3> > << endl;
    cout << func3< func2<x4> > << endl;
    cout << func3< func2<x5> > << endl;

    // output: 1 1 1 1 1


    cout << _func1<x1>::result << endl;
    cout << _func1<x2>::result << endl;
    cout << _func1<x3>::result << endl;
    cout << _func1<x4>::result << endl;
    cout << _func1<x5>::result << endl;

    //output: 963 4396 6666 1999 3141

    //how many "1" will func4<1>,func4<2>,fun4<3>......fun4<10000> ::value  return?
    x6 = count;


    // your flag is flag{x1-x2-x3-x4-x5-x6}
    // if x1=1,x2=2,x3=3,x4=4,x5=5,x6=6
    // flag is     flag{1-2-3-4-5-6}

    return 0;
}

模板:
https://zh.cppreference.com/w/cpp/language/template_specialization
模板特化:
https://blog.csdn.net/gatieme/article/details/50953564

  • _func1求参数的平方根,向下取整(二分法)
  • func2求参数的二进制数中1的个数
  • func3求参数的奇偶
  • func4求是否位素数(sqrt(n)以下的数是否是n的参数)

所以函数要求: x1-x5都是奇数,而且平方根分别为963 4396 6666 1999 3141, x6是10000以内素数的个数。

pyc

使用010Editor的相应模板打开,并修改pyc.bt中的以下部分:

enum <uint16> MagicValue {
    PY_24a0 = 62041,
    PY_24a3 = 62051,
    PY_24b1 = 62061,
    PY_25a0_1 = 62071,
    PY_25a0_2 = 62081,
    PY_25a0_3 = 62091,
    PY_25a0_4 = 62092,
    PY_25b3_1 = 62101,
    PY_25b3_2 = 62111,
    PY_25c1 = 62121,
    PY_25c2 = 62131,
    PY_26a0 = 62151,
    PY_26a1 = 62161,
    PY_27a0_1 = 62171,
    PY_27a0_2 = 62181,
    PY_27a0_a = 62211,
};
  • Magic Number(四字节)



    前两个字节是可变的,它和编译 python 文件的 python 版本有关,接下来两个字节是固定的 0D0A,转换成 ASC 码就是 \r\n

  • mtime(四字节)
    这个字段表示该 pyc 文件的编译日期,用 unix 时间戳来表示
  • PyCodeObject
//Include/code.h
typedef struct {
    PyObject_HEAD // 用它来表示一个 PyCodeObject的开始
    int co_argcount;        /* #arguments, except *args */
    int co_nlocals;     /* #local variables */
    int co_stacksize;       /* #entries needed for evaluation stack */
    int co_flags;       /* CO_..., see below */
    PyObject *co_code;      /* instruction opcodes */
    PyObject *co_consts;    /* list (constants used) */
    PyObject *co_names;     /* list of strings (names used) */
    PyObject *co_varnames;  /* tuple of strings (local variable names) */
    PyObject *co_freevars;  /* tuple of strings (free variable names) */
    PyObject *co_cellvars;      /* tuple of strings (cell variable names) */
    /* The rest doesn't count for hash/cmp */
    PyObject *co_filename;  /* string (where it was loaded from) */
    PyObject *co_name;      /* string (name, for reference) */
    int co_firstlineno;     /* first source line number */
    PyObject *co_lnotab;    /* string (encoding addr<->lineno mapping) See
                   Objects/lnotab_notes.txt for details. */
    void *co_zombieframe;     /* for optimization only (see frameobject.c) */
    PyObject *co_weakreflist;   /* to support weakrefs to code objects */
} PyCodeObject;

各个字段的含义如下:

argcount  参数个数
nlocals   局部变量个数
stacksize 栈空间大小
flags     N/A
TYPE_STRING 表示字节码开始
r_long n  字节码的数量
struct Instruction inst[] 字节码序列

PyObject 的序列化在 python/marshal.c 内实现,一般是先写入一个 byte 来标识此 PyObject 的类型,每种 PyObject 对应的类型也在 Python/marshal.c 内定义:

#define TYPE_NULL               '0'
#define TYPE_NONE               'N'
#define TYPE_FALSE              'F'
#define TYPE_TRUE               'T'
#define TYPE_STOPITER           'S'
#define TYPE_ELLIPSIS           '.'
#define TYPE_INT                'i'
#define TYPE_INT64              'I'
#define TYPE_FLOAT              'f'
#define TYPE_BINARY_FLOAT       'g'
#define TYPE_COMPLEX            'x'
#define TYPE_BINARY_COMPLEX     'y'
#define TYPE_LONG               'l'
#define TYPE_STRING             's'
#define TYPE_INTERNED           't'
#define TYPE_STRINGREF          'R'
#define TYPE_TUPLE              '('
#define TYPE_LIST               '['
#define TYPE_DICT               '{'
#define TYPE_CODE               'c'
#define TYPE_UNICODE            'u'
#define TYPE_UNKNOWN            '?'
#define TYPE_SET                '<'
#define TYPE_FROZENSET          '>'

如图type等于99就是TYPE_CODE类型,PyCodeObject 的第一个部分肯定是 TYPE_CODE,表示字节码区块
使用dis模块转化为反编译字节码区块部分:

import dis
class read():
    def __init__(self, filename, mode):
        # print filename, mode
        self.file = open(filename, mode)
    def read(self, num):
        return (self.file).read(num)

pyc = read("test.pyc", "rb")
pyc.read(30)
target = pyc.read(0x31)
# print bytes(target)
dis.dis(target)

结果:

 0 LOAD_CONST          0 (0)    # 读取常量列表中的 0 号常量
 3 MAKE_FUNCTION       0      # 制作一个函数
 6 STORE_NAME          0 (0)  # 函数命名为字符串列表中的 0 号
 9 LOAD_CONST          1 (1)
12 MAKE_FUNCTION       0
15 STORE_NAME          1 (1)
18 LOAD_NAME           0 (0)  # 取出函数 1
21 CALL_FUNCTION       0     # 调用
24 STORE_NAME          2 (2) # 存储返回值
27 LOAD_NAME           1 (1) 
30 CALL_FUNCTION       0
33 STORE_NAME          3 (3)
36 LOAD_NAME           2 (2)   # 取出两个返回值
39 LOAD_NAME           3 (3)
42 BINARY_ADD                 # 相加
43 PRINT_ITEM                 # 打印结果
44 PRINT_NEWLINE
45 LOAD_CONST          2 (2)
48 RETURN_VALUE

混淆的一般思路:



uncompyle 的工作原理和一般的反编译器类似,它会尽力去匹配每一条指令,尝试将所有指令都覆盖到,但是在解析上面的代码时,碰到 load 不存在的常量时就会出错,无法继续反编译。
所有的指令可以分为两类,不需要参数和需要参数的,Python字节码在设计的时候故意把没有参数的指令分配在了对应编号的低位,高位都是有参数的,以Include/opcode.h中的HAVE_ARGUMENT分界。他们的在二进制级别上的组织是这样的:

[指令] 不需要参数的指令只占用一个字节
[指令] [参数低字节] [参数高字节] 需要参数的指令占用三个字节,一个字节指令,两个字节参数
本题中经过混淆的字节码:

>>> list(map(ord,code.co_code[:9]))
[113, 158, 2, 136, 104, 110, 126, 58, 140]
>>> dis.opname[113]
'JUMP_ABSOLUTE'
>>> 2*256+158
670
>>> dis.opname[136]
'LOAD_DEREF'
>>> 110*256+104
28264

从上面可以看到,第一条指令是JUMP_ABSOLTE 670,这个offset的指令是真实存在的,所以指令合法。但是第二条指令应该是LOAD_DEREF 28264,这个index的对象并不存在,在dis尝试解析的时候就会崩溃。

实际上因为之前的跳转指令所以第二条的非法指令并不会被真实执行到,所以pyc文件作者是故意加入不影响执行的非法指令触发分析软件崩溃,阻碍对该pyc文件的分析。

去混淆

用Apeng师傅的方法可以去掉混淆

# python2 disasm_anti.py py.pyc
import dis, marshal, struct, sys, time, types
from opcode import *

def ana_branch(code, i, hits):
    if i > len(code):
        return
    if i in hits:
        return
    else:
        hits.append(i)
    c = code[i]
    op = ord(c)
    if op == 111 or op == 112 or op == 114 or op == 115 or op == 120 or op == 93:
        oparg = ord(code[i+1]) + ord(code[i+2])*256
        if op == 120 or op == 93:
            oparg += i
            oparg += 3
        ana_branch(code, oparg, hits)
        ana_branch(code, i+3, hits)
    elif op == 110:
        oparg = ord(code[i+1]) + ord(code[i+2])*256
        ana_branch(code, i + oparg + 3, hits)
    elif op == 113:
        oparg = ord(code[i+1]) + ord(code[i+2])*256
        ana_branch(code, oparg, hits)
    else:
        if op>=HAVE_ARGUMENT:
            ana_branch(code, i+3, hits)
        else:
            ana_branch(code, i+1, hits)

def findlinestarts(code):
    """Find the offsets in a byte code which are start of lines in the source.

    Generate pairs (offset, lineno) as described in Python/compile.c.

    """
    byte_increments = [ord(c) for c in code.co_lnotab[0::2]]
    line_increments = [ord(c) for c in code.co_lnotab[1::2]]

    lastlineno = None
    lineno = code.co_firstlineno
    addr = 0
    for byte_incr, line_incr in zip(byte_increments, line_increments):
        if byte_incr:
            if lineno != lastlineno:
                yield (addr, lineno)
                lastlineno = lineno
            addr += byte_incr
        lineno += line_incr
    if lineno != lastlineno:
        yield (addr, lineno)

def findhits(code):
    hits = []
    n = len(code)
    i = 0
    ana_branch(code, i, hits)
    hits.sort()
    return hits

def anti_findlabels(code):
    """Detect all offsets in a byte code which are jump targets.
    Return the list of offsets.
    """
    hits = findhits(code)
    labels = []
    n = len(code)
    i = 0
    while i < n:
        if i not in hits:
            i+=1
            continue
        c = code[i]
        op = ord(c)
        i = i+1
        if op >= HAVE_ARGUMENT:
            oparg = ord(code[i]) + ord(code[i+1])*256
            i = i+2
            label = -1
            if op in hasjrel:
                label = i+oparg
            elif op in hasjabs:
                label = oparg
            if label >= 0:
                if label not in labels:
                    labels.append(label)
    return labels

def dis_anti_obf(co, lasti = -1):
    """Disassemble a code object, anti obf"""
    anti_code = ""
    code = co.co_code
    hits = findhits(code)
    labels = anti_findlabels(code)
    linestarts = dict(findlinestarts(co))
    n = len(code)
    i = 0
    i = 0
    extended_arg = 0
    free = None
    while i < n:
        if i not in hits:
            i+=1
            anti_code+="\x09"
            continue
        c = code[i]
        op = ord(c)
        if i in linestarts:
            if i > 0:
                print
            print "%3d" % linestarts[i],
        else:
            print '   ',
        
        if i == lasti: print '-->',
        else: print '   ',
        if i in labels: print '>>',
        else: print '  ',
        print repr(i).rjust(4),
        print opname[op].ljust(20),
        anti_code += code[i]
        i = i+1
        if op >= HAVE_ARGUMENT:
            oparg = ord(code[i]) + ord(code[i+1])*256 + extended_arg
            extended_arg = 0
            anti_code+=code[i]
            anti_code+=code[i+1]
            i = i+2
            if op == EXTENDED_ARG:
                extended_arg = oparg*65536L
            print repr(oparg).rjust(5),
            if op in hasconst:
                print '(' + repr(co.co_consts[oparg]) + ')',
            elif op in hasname:
                print '(' + co.co_names[oparg] + ')',
            elif op in hasjrel:
                print '(to ' + repr(i + oparg) + ')',
            elif op in haslocal:
                print '(' + co.co_varnames[oparg] + ')',
            elif op in hascompare:
                print '(' + cmp_op[oparg] + ')',
            elif op in hasfree:
                if free is None:
                    free = co.co_cellvars + co.co_freevars
                print '(' + free[oparg] + ')',
        print
    print "patch code:"
    print(anti_code.encode("hex"))




def show_file(fname):
    f = open(fname, "rb")
    magic = f.read(4)
    moddate = f.read(4)
    modtime = time.asctime(time.localtime(struct.unpack('L', moddate)[0]))
    print "magic %s" % (magic.encode('hex'))
    print "moddate %s (%s)" % (moddate.encode('hex'), modtime)
    code = marshal.load(f)
    show_code(code)
     
def show_code(code, indent=''):
    print "%scode" % indent
    indent += '   '
    print "%sargcount %d" % (indent, code.co_argcount)
    print "%snlocals %d" % (indent, code.co_nlocals)
    print "%sstacksize %d" % (indent, code.co_stacksize)
    print "%sflags %04x" % (indent, code.co_flags)
    show_hex("code", code.co_code, indent=indent)
    dis_anti_obf(code)
    print "%sconsts" % indent
    for const in code.co_consts:
        if type(const) == types.CodeType:
            show_code(const, indent+'   ')
        else:
            print "   %s%r" % (indent, const)
    print "%snames %r" % (indent, code.co_names)
    print "%svarnames %r" % (indent, code.co_varnames)
    print "%sfreevars %r" % (indent, code.co_freevars)
    print "%scellvars %r" % (indent, code.co_cellvars)
    print "%sfilename %r" % (indent, code.co_filename)
    print "%sname %r" % (indent, code.co_name)
    print "%sfirstlineno %d" % (indent, code.co_firstlineno)
    show_hex("lnotab", code.co_lnotab, indent=indent)
     
def show_hex(label, h, indent):
    h = h.encode('hex')
    if len(h) < 60:
        print "%s%s %s" % (indent, label, h)
    else:
        print "%s%s" % (indent, label)
        for i in range(0, len(h), 60):
            print "%s   %s" % (indent, h[i:i+60])

show_file(sys.argv[1])

或者使用FXTi师傅的方法将不合法的指令转换为nop:

import marshal, sys, opcode, types, dis

NOP = 9

HAVE_ARGUMENT = 90

JUMP_FORWARD = 110
JUMP_IF_FALSE_OR_POP = 111
JUMP_IF_TRUE_OR_POP = 112
JUMP_ABSOLUTE = 113
POP_JUMP_IF_FALSE = 114
POP_JUMP_IF_TRUE = 115

CONTINUE_LOOP = 119
FOR_ITER = 93

RETURN_VALUE = 83

used_set = set()

def deconf_inner(code, now):
    global used_set

    while code[now] != RETURN_VALUE:
        if now in used_set:
            break
        used_set.add(now)
        if code[now] >= HAVE_ARGUMENT:
            used_set.add(now+1)
            used_set.add(now+2)
        op = code[now]

        #print(str(now) + " " + opcode.opname[op])

        if op == JUMP_FORWARD:
            arg = code[now+2] << 8 | code[now+1]
            now += arg + 3
            continue

        elif op == JUMP_ABSOLUTE:
            arg = code[now+2] << 8 | code[now+1]
            now = arg
            continue

        elif op == JUMP_IF_TRUE_OR_POP:
            arg = code[now+2] << 8 | code[now+1] 
            deconf_inner(code, arg)

        elif op == JUMP_IF_FALSE_OR_POP:
            arg = code[now+2] << 8 | code[now+1] 
            deconf_inner(code, arg)

        elif op == POP_JUMP_IF_TRUE:
            arg = code[now+2] << 8 | code[now+1] 
            deconf_inner(code, arg)

        elif op == POP_JUMP_IF_FALSE: 
            arg = code[now+2] << 8 | code[now+1] 
            deconf_inner(code, arg)

        elif op == CONTINUE_LOOP:
            arg = code[now+2] << 8 | code[now+1] 
            deconf_inner(code, arg)

        elif op == FOR_ITER: 
            arg = code[now+2] << 8 | code[now+1] 
            deconf_inner(code, now + arg + 3)

        if op < HAVE_ARGUMENT:
            now += 1
        else:
            now += 3

    used_set.add(now)
    if code[now] >= HAVE_ARGUMENT:
        used_set.add(now+1)
        used_set.add(now+2)

def deconf(code):
    global used_set

    used_set = set() #Remember to clean up used_set for every target function

    cod = list(map(ord, code))
    deconf_inner(cod, 0)

    for i in range(len(cod)):
        if i not in used_set:
            cod[i] = NOP

    return "".join(list(map(chr, cod)))

with open(sys.argv[1], 'rb') as f:
    header = f.read(8)
    code = marshal.load(f)

'''
print(code.co_consts[3].co_name)
print(dis.dis(deconf(code.co_consts[3].co_code)))
'''

consts = list()

for i in range(len(code.co_consts)):
    if hasattr(code.co_consts[i], 'co_code'):
        consts.append(types.CodeType(code.co_consts[i].co_argcount,
            # c.co_kwonlyargcount,  Add this in Python3
            code.co_consts[i].co_nlocals,
            code.co_consts[i].co_stacksize,
            code.co_consts[i].co_flags,
            deconf(code.co_consts[i].co_code),
            code.co_consts[i].co_consts,
            code.co_consts[i].co_names,
            code.co_consts[i].co_varnames,
            code.co_consts[i].co_filename,
            code.co_consts[i].co_name,
            code.co_consts[i].co_firstlineno,
            code.co_consts[i].co_lnotab,   # In general, You should adjust this
            code.co_consts[i].co_freevars,
            code.co_consts[i].co_cellvars))
    else:
        consts.append(code.co_consts[i])

mode = types.CodeType(code.co_argcount,
    # c.co_kwonlyargcount,  Add this in Python3
    code.co_nlocals,
    code.co_stacksize,
    code.co_flags,
    deconf(code.co_code),
    tuple(consts),
    code.co_names,
    code.co_varnames,
    code.co_filename,
    code.co_name,
    code.co_firstlineno,
    code.co_lnotab,   # In general, You should adjust this
    code.co_freevars,
    code.co_cellvars)

f = open(sys.argv[1]+".mod", 'wb') 
f.write(header)
marshal.dump(mode, f)

NOP指令去除与块的合并

fxti师傅给了一个工具:
https://github.com/extremecoders-re/bytecode_simplifier
利用这个工具可以去除上面去混淆以后生成的全是NOP指令的块,以及合并一些块
完成之后使用uncompyle6可以反汇编一下(反编译还是会失败)

 L.   1         0  LOAD_CONST               2694209818L
                3  STORE_FAST            0  'DIVIDER'
                6  JUMP_FORWARD          0  'to 9'
              9_0  COME_FROM             6  '6'
                9  LOAD_CONST               4130330538L

 L.   3        12  LOAD_FAST             0  'DIVIDER'
               15  COMPARE_OP            2  ==
               18  POP_JUMP_IF_TRUE    366  'to 366'

 L.   9        21  LOAD_CONST               3168701571L
               24  LOAD_FAST             0  'DIVIDER'
               27  COMPARE_OP            2  ==

 L.  14        30  POP_JUMP_IF_TRUE    345  'to 345'
               33  LOAD_CONST               3715947653L
               36  LOAD_FAST             0  'DIVIDER'

 L.  17        39  COMPARE_OP            2  ==
               42  POP_JUMP_IF_TRUE    324  'to 324'
               45  LOAD_CONST               2694209818L

 L.  20        48  LOAD_FAST             0  'DIVIDER'
               51  COMPARE_OP            2  ==
               54  POP_JUMP_IF_TRUE    306  'to 306'

 L.  38        57  LOAD_CONST               651787064
               60  LOAD_FAST             0  'DIVIDER'
               63  COMPARE_OP            2  ==
               66  POP_JUMP_IF_TRUE    285  'to 285'
               69  LOAD_CONST               3521152606L
               72  LOAD_FAST             0  'DIVIDER'
               75  COMPARE_OP            2  ==
               78  POP_JUMP_IF_TRUE    264  'to 264'
               81  LOAD_CONST               2730391645L
               84  LOAD_FAST             0  'DIVIDER'
               87  COMPARE_OP            2  ==
               90  POP_JUMP_IF_TRUE    246  'to 246'
               93  LOAD_CONST               4084147187L
               96  LOAD_FAST             0  'DIVIDER'
               99  COMPARE_OP            2  ==
              102  POP_JUMP_IF_TRUE    222  'to 222'
              105  LOAD_CONST               1860581437
              108  LOAD_FAST             0  'DIVIDER'
              111  COMPARE_OP            2  ==
              114  POP_JUMP_IF_TRUE    204  'to 204'
              117  LOAD_CONST               3816944324L
              120  LOAD_FAST             0  'DIVIDER'
              123  COMPARE_OP            2  ==
              126  POP_JUMP_IF_TRUE    203  'to 203'
              129  LOAD_CONST               394367122
              132  LOAD_FAST             0  'DIVIDER'
              135  COMPARE_OP            2  ==
              138  POP_JUMP_IF_TRUE    181  'to 181'
              141  LOAD_CONST               1627830889
              144  LOAD_FAST             0  'DIVIDER'
              147  COMPARE_OP            2  ==
              150  POP_JUMP_IF_TRUE    157  'to 157'
              153  LOAD_CONST               None
              156  RETURN_END_IF    
            157_0  COME_FROM           150  '150'
              157  STORE_NAME            0  'sys'
              160  LOAD_CODE                <code_object str2hex>
              163  MAKE_FUNCTION_0       0  None
              166  STORE_NAME            1  'str2hex'
              169  LOAD_CODE                <code_object hex2str>
              172  LOAD_CONST               3715947653L
              175  STORE_FAST            0  'DIVIDER'
              178  JUMP_BACK             9  'to 9'
              181  LOAD_NAME            10  'flag'
              184  CALL_FUNCTION_1       1  None
              187  CALL_FUNCTION_1       1  None
              190  POP_TOP          
              191  LOAD_CONST               None
              194  LOAD_CONST               3816944324L
              197  STORE_FAST            0  'DIVIDER'
              200  JUMP_BACK             9  'to 9'
              203  RETURN_END_IF    
            204_0  COME_FROM           114  '114'
              204  LOAD_CONST               97
              207  LOAD_CONST               103
              210  LOAD_CONST               58
              213  LOAD_CONST               2730391645L
              216  STORE_FAST            0  'DIVIDER'
              219  JUMP_BACK             9  'to 9'
              222  LOAD_ATTR             6  'stdout'
              225  LOAD_ATTR             7  'write'
              228  LOAD_NAME             2  'hex2str'
              231  LOAD_CONST               102
              234  LOAD_CONST               108
              237  LOAD_CONST               1860581437
              240  STORE_FAST            0  'DIVIDER'
              243  JUMP_BACK             9  'to 9'
              246  BUILD_LIST_5          5 
              249  CALL_FUNCTION_1       1  None
              252  CALL_FUNCTION_1       1  None
              255  LOAD_CONST               4130330538L
              258  STORE_FAST            0  'DIVIDER'
              261  JUMP_BACK             9  'to 9'
              264  CALL_FUNCTION_1       1  None
              267  STORE_NAME           10  'flag'
              270  LOAD_NAME             5  'count'
              273  LOAD_NAME             1  'str2hex'
              276  LOAD_CONST               394367122
              279  STORE_FAST            0  'DIVIDER'
              282  JUMP_BACK             9  'to 9'
              285  STORE_NAME            3  'p_s'
              288  LOAD_CODE                <code_object p_f>
              291  MAKE_FUNCTION_0       0  None
              294  STORE_NAME            4  'p_f'
              297  LOAD_CONST               3168701571L
              300  STORE_FAST            0  'DIVIDER'
              303  JUMP_BACK             9  'to 9'
              306  LOAD_CONST               -1
              309  LOAD_CONST               None
              312  IMPORT_NAME           0  'sys'
              315  LOAD_CONST               1627830889
              318  STORE_FAST            0  'DIVIDER'
              321  JUMP_BACK             9  'to 9'
              324  MAKE_FUNCTION_0       0  None
              327  STORE_NAME            2  'hex2str'
              330  LOAD_CODE                <code_object p_s>
              333  MAKE_FUNCTION_0       0  None
              336  LOAD_CONST               651787064
              339  STORE_FAST            0  'DIVIDER'
              342  JUMP_BACK             9  'to 9'
              345  LOAD_CODE                <code_object count>
              348  MAKE_FUNCTION_0       0  None
              351  STORE_NAME            5  'count'
              354  LOAD_NAME             0  'sys'
              357  LOAD_CONST               4084147187L
              360  STORE_FAST            0  'DIVIDER'
              363  JUMP_BACK             9  'to 9'
              366  POP_TOP          
              367  LOAD_NAME             0  'sys'
              370  LOAD_ATTR             8  'stdin'
              373  LOAD_ATTR             9  'read'
              376  LOAD_CONST               38
              379  LOAD_CONST               3521152606L
              382  STORE_FAST            0  'DIVIDER'
              385  JUMP_BACK             9  'to 9'

然后我暂时只会看这个字节码,fxti师傅那个自己去混淆的方案没开源,我打算自己仔细研究一下这个发编译的代码,看能不能按照那个思路复现一下。

相关文章

网友评论

      本文标题:2019 中关村网络与信息安全领域专项赛

      本文链接:https://www.haomeiwen.com/subject/pngjxktx.html