Python字节码逆向分析

ctf题目

名称:misc-easypy

内容:

In [1]: import dis

In [2]: dis.dis(encrypt)

  4           0 LOAD_CONST               1 ('')
              2 STORE_FAST               1 (O0O)

  5           4 LOAD_FAST                0 (oO0)
              6 LOAD_ATTR                0 (upper)
              8 CALL_FUNCTION            0
             10 STORE_FAST               2 (o0O)

  6          12 LOAD_FAST                2 (o0O)
             14 LOAD_CONST               0 (None)
             16 LOAD_CONST               0 (None)
             18 LOAD_CONST               3 (-1)
             20 BUILD_SLICE              3
             22 BINARY_SUBSCR
             24 STORE_FAST               2 (o0O)

  7          26 SETUP_LOOP              60 (to 88)
             28 LOAD_GLOBAL              1 (range)
             30 LOAD_GLOBAL              2 (len)
             32 LOAD_FAST                2 (o0O)
             34 CALL_FUNCTION            1
             36 CALL_FUNCTION            1
             38 GET_ITER
        >>   40 FOR_ITER                44 (to 86)
             42 STORE_FAST               3 (O0)

  8          44 LOAD_GLOBAL              3 (ord)
             46 LOAD_FAST                2 (o0O)
             48 LOAD_FAST                3 (O0)
             50 BINARY_SUBSCR
             52 CALL_FUNCTION            1
             54 LOAD_FAST                3 (O0)
             56 BINARY_ADD
             58 LOAD_GLOBAL              2 (len)
             60 LOAD_FAST                2 (o0O)
             62 CALL_FUNCTION            1
             64 LOAD_FAST                3 (O0)
             66 BINARY_SUBTRACT
             68 BINARY_XOR
             70 STORE_FAST               4 (OO)

  9          72 LOAD_FAST                1 (O0O)
             74 LOAD_GLOBAL              4 (chr)
             76 LOAD_FAST                4 (OO)
             78 CALL_FUNCTION            1
             80 INPLACE_ADD
             82 STORE_FAST               1 (O0O)
             84 JUMP_ABSOLUTE           40
        >>   86 POP_BLOCK

 10     >>   88 LOAD_FAST                1 (O0O)
             90 RETURN_VALUE
			 
#result:[cgjegl_&]!VW&KS_GVXHWI_EVCVDXGc^™mgrj

上面的result显示异常,我截图放给大家。

 

解题:

分析题目发现与python有关,并且题目内容与python交互框架相似。使用网络搜索 dis.dis(encrypt)、import dis发现“dis库是python(默认的CPython)自带的一个库,可以用来分析字节码”。

找了几个例子查看下

import dis
def func2():
    a = 0
    a + 1
dis.dis(func2)

  执行后内容如下

 3           0 LOAD_CONST               1 (0)
              2 STORE_FAST               0 (a)

  4           4 LOAD_FAST                0 (a)
              6 LOAD_CONST               2 (1)
              8 BINARY_ADD
             10 POP_TOP
             12 LOAD_CONST               0 (None)
             14 RETURN_VALUE

网上找到一张解释较清晰的图片

回到题目的开头代码,猜想意思是 第四行的代码是“O0O=''

  4           0 LOAD_CONST               1 ('')
              2 STORE_FAST               1 (O0O)

第5行的代码是“o0O=oO0.upper()”

  5           4 LOAD_FAST                0 (oO0)
              6 LOAD_ATTR                0 (upper)
              8 CALL_FUNCTION            0
             10 STORE_FAST               2 (o0O)

第一次看看不懂,就使用python的dis库正向的编写代码生成字节码进行对比,中间列的内容当成英文理解。按照行数一行一行的翻译,每一行就是接下来python代码将要执行的操作,包括加、减、乘、除、调用函数等。完整翻译如下:

 1     
 2 
 3 
 4     O0O=''
 5     o0O=oO0.upper()
 6     o0O=o0O[::-1]
 7     for O0 in range(len(o0O)):
 8         OO=ord(o0O[O0])+O0^len(o0O)-O0
 9         O0O+=chr(OO)
10     return O0O    

拼接函数其他部分可生成对应的字节码,执行以下内容即可生成

 1 import dis
 2 def func1():
 3 
 4     O0O=''
 5     o0O=oO0.upper()
 6     o0O=o0O[::-1]
 7     for O0 in range(len(o0O)):
 8         OO=ord(o0O[O0])+O0^len(o0O)-O0
 9         O0O+=chr(OO)
10     return O0O
11 print(dis.dis(func1))

到这一步花的时间不多,而且算法也很简单,只有一个循环计算。根据算法逆向出反向代码

1 list1="[cgjegl_&]!VW&KS_GVXHWI_EVCVDXGc^™mgrj"
2 flag=""
3 for x in range(len(list1)):
4     temp=int(ord(list1[x])^(len(list1)-x))-x
5     flag+=chr(temp)
6 print(flag[::-1].lower())

运行得到flag

flag{8e142b5b39c1f80a95e2ab3709facfae}

插曲:反向计算时错误理解了减号和异或的运算优先级,导致解密出现错误。虽然是一个减号的位置不对,但是花了好长时间排查问题。

减号优先级>异或优先级

posted @ 2020-09-23 22:36  S_m_workers  阅读(631)  评论(0)    收藏  举报