虎符-RE-game

基本指令

点击查看详细内容

- 阅读下文代码前基本须知

  
LOAD_CONST 加载常量               1
STORE_NAME 将变量储存为常量值     a=1   局部变量
STORE_GLOBAL同上功能  全局变量
BUILD_LIST  生成list
BUILD_MAP声明字典元素数量
STORE_MAP生成键值对 并储存
LOAD_NAME加载局部变量
BINARY_ADD加法
BINARY_SUBTRACT减法
BINARY_MULTIPLY乘法
BINARY_DIVIDE除法
BINARY_MODULO取余
BINARY_SUBSCR()
BUILD_SLICE切片
POP_TOP将结果从堆栈顶部弹出,以保证堆栈平衡
SETUP_LOOP表明循环开始  (to 28)参数说明此循环知道字节码偏移28字节的指令结束(也就是28字节开始不是循环)。
FOR_ITER调用堆栈   声明generator作用到字节码偏移位置27字节。
PRINT_ITEM为一个print函数。
COMPARE_OP指令对堆栈中两个常量进行比较
POP_JUMP_IF_FALSE指令,判断栈顶值来决定程序运行顺序实现判断功能。
  

基本查看

打开是一个txt文档。里面的内容是,python字节码。python的字节码只能靠自己硬读,没有什么其他方法。
python逆向或者反汇编的目的就是在没有源码的基础上,通过字节码来理解源代码的运行内容

分析

# Python 2.7
# Embedded file name: game.py
#源码行号|指令在函数中的偏移|指令符号|指令参数|实际参数值

   1       0  LOAD_CONST               249
           3  LOAD_CONST               91
           6  LOAD_CONST               149
           9  LOAD_CONST               113
          12  LOAD_CONST               16
          15  LOAD_CONST               91
          18  LOAD_CONST               53
          21  LOAD_CONST               41
          24  BUILD_LIST_8          8
          27  STORE_NAME            0  'arr0'
#arr0=[249,91,149,113,16,91,53,41]
   2      30  LOAD_CONST               43
          33  LOAD_CONST               1
          36  LOAD_CONST               6
          39  LOAD_CONST               69
          42  LOAD_CONST               20
          45  LOAD_CONST               62
          48  LOAD_CONST               6
          51  LOAD_CONST               44
          54  LOAD_CONST               24
          57  LOAD_CONST               113
          60  LOAD_CONST               6
          63  LOAD_CONST               35
          66  LOAD_CONST               0
          69  LOAD_CONST               3
          72  LOAD_CONST               6
          75  LOAD_CONST               44
          78  LOAD_CONST               20
          81  LOAD_CONST               22
          84  LOAD_CONST               127
          87  LOAD_CONST               60
          90  BUILD_LIST_20        20
          93  STORE_NAME            1  'arr1'
#arr1=[43,1,6,69,20,62,6,44,24,113,6,35,0,3,6,44,20,22,127,60]
   3      96  LOAD_CONST               90
          99  LOAD_CONST               100
         102  LOAD_CONST               87
         105  LOAD_CONST               109
         108  LOAD_CONST               86
         111  LOAD_CONST               108
         114  LOAD_CONST               86
         117  LOAD_CONST               105
         120  LOAD_CONST               90
         123  LOAD_CONST               104
         126  LOAD_CONST               88
         129  LOAD_CONST               102
         132  BUILD_LIST_12        12
         135  STORE_NAME            2  'arr2'
#arr2=[90,100,87,109,86,108,86,105,90,104,88,102]
   5     138  LOAD_CODE                <code_object check0>
         141  MAKE_FUNCTION_0       0  None
         144  STORE_NAME            3  'check0'
#check0()
   8     147  LOAD_CODE                <code_object check1>
         150  MAKE_FUNCTION_0       0  None
         153  STORE_NAME            4  'check1'
#check1()
  14     156  LOAD_CODE                <code_object check2>
         159  MAKE_FUNCTION_0       0  None
         162  STORE_NAME            5  'check2'
#check2()
  20     165  LOAD_CODE                <code_object check3>
         168  MAKE_FUNCTION_0       0  None
         171  STORE_NAME            6  'check3'
#check3()
  37     174  LOAD_NAME             7  'raw_input'
         177  CALL_FUNCTION_0       0  None
         180  STORE_NAME            8  'flag'
#flag=raw_input()
  38     183  LOAD_NAME             3  'check0'
         186  LOAD_NAME             8  'flag'
         189  CALL_FUNCTION_1       1  None
         192  POP_JUMP_IF_FALSE   239  'to 239'
         195  LOAD_NAME             4  'check1'
         198  LOAD_NAME             8  'flag'
         201  CALL_FUNCTION_1       1  None
         204  POP_JUMP_IF_FALSE   239  'to 239'
         207  LOAD_NAME             5  'check2'
         210  LOAD_NAME             8  'flag'
         213  CALL_FUNCTION_1       1  None
         216  POP_JUMP_IF_FALSE   239  'to 239'
         219  LOAD_NAME             6  'check3'
         222  LOAD_NAME             8  'flag'
         225  CALL_FUNCTION_1       1  None
       228_0  COME_FROM           216  '216'
       228_1  COME_FROM           204  '204'
       228_2  COME_FROM           192  '192'
         228  POP_JUMP_IF_FALSE   239  'to 239'
#if check0(flag):
#if check1(flag):
#    if check2(flag):
#        if check3(flag):
#            print 'no' 
#        else print'ok'   
  39     231  LOAD_CONST               'ok'
         234  PRINT_ITEM
         235  PRINT_NEWLINE_CONT
         236  JUMP_FORWARD          5  'to 244'

  41     239  LOAD_CONST               'no'
         242  PRINT_ITEM
         243  PRINT_NEWLINE_CONT
       244_0  COME_FROM           236  '236'    
         244  LOAD_CONST               None
         247  RETURN_VALUE

# check0 line 5 of game.py

   6       0  LOAD_GLOBAL           0  'all'
           3  LOAD_GENEXPR             '<code_object <genexpr>>'
           6  MAKE_FUNCTION_0       0  None
           9  LOAD_FAST             0  's'
          12  GET_ITER
          13  CALL_FUNCTION_1       1  None
          16  CALL_FUNCTION_1       1  None
          19  RETURN_VALUE
#all='<code_object <genexpr>>'
# check1 line 8 of game.py

   9       0  LOAD_GLOBAL           0  'len'
           3  LOAD_FAST             0  's'
           6  CALL_FUNCTION_1       1  None
           9  LOAD_CONST               100
          12  COMPARE_OP            0  <
          15  POP_JUMP_IF_FALSE    58  'to 58'
          18  LOAD_GLOBAL           0  'len'
          21  LOAD_FAST             0  's'
          24  CALL_FUNCTION_1       1  None
          27  LOAD_GLOBAL           0  'len'
          30  LOAD_FAST             0  's'
          33  CALL_FUNCTION_1       1  None
          36  BINARY_MULTIPLY
          37  LOAD_CONST               777
          40  BINARY_MODULO
          41  LOAD_CONST               233
          44  BINARY_XOR
          45  LOAD_CONST               513
          48  COMPARE_OP            2  ==
        51_0  COME_FROM            15  '15'
          51  POP_JUMP_IF_FALSE    58  'to 58'
#if len(s)<100:
#    if (len(s)*len(s))%777)^233==513
#        return True
#    else:
#        False
#else:
#    False
  10      54  LOAD_GLOBAL           1  'True'
          57  RETURN_END_IF
        58_0  COME_FROM            51  '51'

  12      58  LOAD_GLOBAL           2  'False'
          61  RETURN_VALUE
          62  LOAD_CONST               None
          65  RETURN_VALUE

# check2 line 14 of game.py

  15       0  LOAD_GLOBAL           0  'ord'
           3  LOAD_FAST             0  's'
           6  LOAD_CONST               0
           9  BINARY_SUBSCR
          10  CALL_FUNCTION_1       1  None
          13  LOAD_CONST               128
          16  BINARY_MULTIPLY
          17  LOAD_GLOBAL           0  'ord'
          20  LOAD_FAST             0  's'
          23  LOAD_CONST               1
          26  BINARY_SUBSCR
          27  CALL_FUNCTION_1       1  None
          30  BINARY_ADD
          31  LOAD_CONST               128
          34  BINARY_MULTIPLY
          35  LOAD_GLOBAL           0  'ord'
          38  LOAD_FAST             0  's'
          41  LOAD_CONST               2
          44  BINARY_SUBSCR
          45  CALL_FUNCTION_1       1  None
          48  BINARY_ADD
          49  LOAD_CONST               128
          52  BINARY_MULTIPLY
          53  LOAD_GLOBAL           0  'ord'
          56  LOAD_FAST             0  's'
          59  LOAD_CONST               3
          62  BINARY_SUBSCR
          63  CALL_FUNCTION_1       1  None
          66  BINARY_ADD
          67  LOAD_CONST               128
          70  BINARY_MULTIPLY
          71  LOAD_GLOBAL           0  'ord'
          74  LOAD_FAST             0  's'
          77  LOAD_CONST               4
          80  BINARY_SUBSCR
          81  CALL_FUNCTION_1       1  None
          84  BINARY_ADD
          85  LOAD_CONST               128
          88  BINARY_MULTIPLY
          89  LOAD_GLOBAL           0  'ord'
          92  LOAD_FAST             0  's'
          95  LOAD_CONST               5
          98  BINARY_SUBSCR
          99  CALL_FUNCTION_1       1  None
         102  BINARY_ADD
         103  LOAD_CONST               3533889469877L
         106  COMPARE_OP            2  ==
         109  POP_JUMP_IF_FALSE   138  'to 138'
         112  LOAD_GLOBAL           0  'ord'
         115  LOAD_FAST             0  's'
         118  LOAD_CONST               -1
         121  BINARY_SUBSCR
         122  CALL_FUNCTION_1       1  None
         125  LOAD_CONST               125
         128  COMPARE_OP            2  ==
       131_0  COME_FROM           109  '109'
         131  POP_JUMP_IF_FALSE   138  'to 138'
#if ((((ord(s[0])*128+ord(s[1]))*128+ord(s[2]))*128+ord(s[3]))*128+ord(s[4]))*128+ord(s[5]) == 3533889469877:
#    if ord(s[-1])==125:
#        return True
#    else:
#        return False
#else:
#    return False
  16     134  LOAD_GLOBAL           1  'True'
         137  RETURN_END_IF
       138_0  COME_FROM           131  '131'

  18     138  LOAD_GLOBAL           2  'False'
         141  RETURN_VALUE
         142  LOAD_CONST               None
         145  RETURN_VALUE

# check3 line 20 of game.py

  21       0  LOAD_GLOBAL           0  'map'
           3  LOAD_GLOBAL           1  'ord'
           6  LOAD_FAST             0  's'
           9  CALL_FUNCTION_2       2  None
          12  STORE_FAST            1  'arr'
#arr=map(ord,s)
  22      15  LOAD_FAST             1  'arr'
          18  LOAD_CONST               6
          21  LOAD_CONST               30
          24  LOAD_CONST               3
          27  BUILD_SLICE_3         3
          30  BINARY_SUBSCR
          31  STORE_FAST            2  'a'
#a=arr[6:30:3]
  23      34  SETUP_LOOP           62  'to 99'
          37  LOAD_GLOBAL           2  'range'
          40  LOAD_GLOBAL           3  'len'
          43  LOAD_FAST             2  'a'
          46  CALL_FUNCTION_1       1  None
          49  CALL_FUNCTION_1       1  None
          52  GET_ITER
          53  FOR_ITER             42  'to 98'
          56  STORE_FAST            3  'i'
#for i in range(len(a))
  24      59  LOAD_FAST             2  'a'
          62  LOAD_FAST             3  'i'
          65  BINARY_SUBSCR
          66  LOAD_CONST               17684
          69  BINARY_MULTIPLY
          70  LOAD_CONST               372511
          73  BINARY_ADD
          74  LOAD_CONST               257
          77  BINARY_MODULO
          78  LOAD_GLOBAL           4  'arr0'
          81  LOAD_FAST             3  'i'
          84  BINARY_SUBSCR
          85  COMPARE_OP            3  !=
          88  POP_JUMP_IF_FALSE    53  'to 53'
#if (a[i]*17684+372511)%257!=arr0[i]
  25      91  LOAD_GLOBAL           5  'False'
          94  RETURN_END_IF
        95_0  COME_FROM            88  '88'
          95  JUMP_BACK            53  'to 53'
          98  POP_BLOCK
        99_0  COME_FROM            34  '34'
#return Flase
  26      99  LOAD_FAST             1  'arr'
         102  LOAD_CONST               -2
         105  LOAD_CONST               33
         108  LOAD_CONST               -1
         111  BUILD_SLICE_3         3
         114  BINARY_SUBSCR
         115  LOAD_CONST               5
         118  BINARY_MULTIPLY
         119  STORE_FAST            4  'b'
#b=arr[-2:33:-1]*5
  27     122  LOAD_GLOBAL           0  'map'
         125  LOAD_LAMBDA              '<code_object <lambda>>'
         128  MAKE_FUNCTION_0       0  None
         131  LOAD_GLOBAL           6  'zip'
         134  LOAD_FAST             4  'b'
         137  LOAD_FAST             1  'arr'
         140  LOAD_CONST               7
         143  LOAD_CONST               27
         146  SLICE+3
         147  CALL_FUNCTION_2       2  None
         150  CALL_FUNCTION_2       2  None
         153  STORE_FAST            5  'c'
#c=map('<code_object <lambda>>' zip(b,arr[7,27]))
  28     156  LOAD_FAST             5  'c'
         159  LOAD_GLOBAL           7  'arr1'
         162  COMPARE_OP            3  !=
         165  POP_JUMP_IF_FALSE   172  'to 172'
#if c!=arr1
  29     168  LOAD_GLOBAL           5  'False'
         171  RETURN_END_IF
       172_0  COME_FROM           165  '165'
#else:return False
  30     172  LOAD_CONST               0
         175  STORE_FAST            6  'p'
#p=0
  31     178  SETUP_LOOP          105  'to 286'
         181  LOAD_GLOBAL           2  'range'
         184  LOAD_CONST               28
         187  LOAD_CONST               34
         190  CALL_FUNCTION_2       2  None
         193  GET_ITER
         194  FOR_ITER             88  'to 285'
         197  STORE_FAST            3  'i'
#for i in range(28,34)
  32     200  LOAD_FAST             1  'arr'
         203  LOAD_FAST             3  'i'
         206  BINARY_SUBSCR
         207  LOAD_CONST               107
         210  BINARY_ADD
         211  LOAD_CONST               16
         214  BINARY_DIVIDE
         215  LOAD_CONST               77
         218  BINARY_ADD
         219  LOAD_GLOBAL           8  'arr2'
         222  LOAD_FAST             6  'p'
         225  BINARY_SUBSCR
         226  COMPARE_OP            3  !=
         229  POP_JUMP_IF_TRUE    268  'to 268'
         232  LOAD_FAST             1  'arr'
         235  LOAD_FAST             3  'i'
         238  BINARY_SUBSCR
         239  LOAD_CONST               117
         242  BINARY_ADD
         243  LOAD_CONST               16
         246  BINARY_MODULO
         247  LOAD_CONST               99
         250  BINARY_ADD
         251  LOAD_GLOBAL           8  'arr2'
         254  LOAD_FAST             6  'p'
         257  LOAD_CONST               1
         260  BINARY_ADD
         261  BINARY_SUBSCR
         262  COMPARE_OP            3  !=
       265_0  COME_FROM           229  '229'
         265  POP_JUMP_IF_FALSE   272  'to 272'
#if (arr[i]+107)/16+77!=arr2[p]:
#if (arr[i]+117)/16+99!=arr2[p+1]:
  33     268  LOAD_GLOBAL           9  'false'
         271  RETURN_END_IF
       272_0  COME_FROM           265  '265'
#else:return False
  34     272  LOAD_FAST             6  'p'
         275  LOAD_CONST               2
         278  INPLACE_ADD
         279  STORE_FAST            6  'p'
         282  JUMP_BACK           194  'to 194'
         285  POP_BLOCK
       286_0  COME_FROM           178  '178'
#p+=2
  35     286  LOAD_GLOBAL          10  'True'
         289  RETURN_VALUE

# <genexpr> line 6 of game.py

   6       0  LOAD_FAST             0  '.0'
           3  FOR_ITER             32  'to 38'
           6  STORE_FAST            1  'x'
           9  LOAD_GLOBAL           0  'ord'
          12  LOAD_FAST             1  'x'
          15  CALL_FUNCTION_1       1  None
          18  LOAD_GLOBAL           1  'range'
          21  LOAD_CONST               32
          24  LOAD_CONST               128
          27  CALL_FUNCTION_2       2  None
          30  COMPARE_OP            6  in
          33  YIELD_VALUE
          34  POP_TOP
          35  JUMP_BACK             3  'to 3'
          38  LOAD_CONST               None
          41  RETURN_VALUE
#for x in range(ord(x))
# <lambda> line 27 of game.py

  27       0  LOAD_FAST             0  'x'
           3  LOAD_CONST               0
           6  BINARY_SUBSCR
           7  LOAD_FAST             0  'x'
          10  LOAD_CONST               1
          13  BINARY_SUBSCR
          14  BINARY_XOR
          15  RETURN_VALUE
#lambda x[0]^x[1]

整理后

arr0=[249,91,149,113,16,91,53,41]
arr1=[43,1,6,69,20,62,6,44,24,113,6,35,0,3,6,44,20,22,127,60]
arr2=[90,100,87,109,86,108,86,105,90,104,88,102]
def check0()
def check1()
def check2()
def check3()
flag=raw_input()
if check0(flag):
    if check1(flag):
        if check2(flag):
            if check3(flag):
                print 'ok' 
            else:
                print'no'  
def check0():
all=ord(x) for x in range(32,128)
iter(s)

def check1():
if len(s)<100:
    if (len(s)*len(s))%777)^233==513:
        return True
    else:
        False
else:
    False

def check2():
if ((((ord(s[0])*128+ord(s[1]))*128+ord(s[2]))*128+ord(s[3]))*128+ord(s[4]))*128+ord(s[5]) == 3533889469877:
    if ord(s[-1])==125:
        return True
    else:
        return False
else:
    return False

def check3():
arr=map(ord,s)
a=arr[6:30:3]
for i in range(len(a))
    if (a[i]*17684+372511)%257!=arr0[i]:
        return Flase
b=arr[-2:33:-1]*5
c=map(lambda x[0]:x[0]^x[1] zip(b,arr[7,27]))
if c!=arr1:
    p=0
    for i in range(28,34):
        if (arr[i]+107)/16+77!=arr2[p]:
            if (arr[i]+117)/16+99!=arr2[p+1]:
                p+=2
else:
    return False
#<genexpr> ord(x) for x in range(32,128)
#<lambda> x[0]^x[1]

这只能看个大概...不一定完全准确...有不同意见欢迎指正留言QAQ事实上非常期望得到指教。毕竟这是我第一次读这种。

分析代码

结合官方的wp分析
flag需经过check0,check1,check2,check3四个函数的检查
check0,flag字符均在32, 128范围内
check1,条件l < 100 and ((l*l) % 777) ^ 233 == 513获得flag长度为39
check2,通过128进制得到flag的开头为“flag{5”以及结尾为“}”
check3,其中对三段flag进行了计算,第一部分可以爆破运算式得到,第二部分需要通过第一部分的结果异或得到,第三部分类似16进制编码,可以直接恢复

解题脚本

爆破

flag = [' ']*39
x = 3533889469877
t = ''
while x != 0:
	t += chr(x%128)
	x/=128
flag[:6] = t[::-1]
flag[-1] = '}'
arr0 = [249,91,149,113,16,91,53,41]
for i in range(8):
	for ch in range(32, 128):
		if (ch * 17684 + 372511) % 257 == arr0[i]:
			flag[6+i*3]=chr(ch)
arr1 = [43, 1, 6, 69, 20, 62, 6, 44, 24, 113, 6, 35, 0, 3, 6, 44, 20, 22, 127, 60]
key = [0]*4
key[0] = arr1[8] ^ ord(flag[15])
key[1] = arr1[5] ^ ord(flag[12])
key[2] = arr1[2] ^ ord(flag[9])
key[3] = arr1[11] ^ ord(flag[18])

flag[-2] = chr(key[0])
flag[-3] = chr(key[1])
flag[-4] = chr(key[2])
flag[-5] = chr(key[3])
for i in range(len(arr1)):
	flag[7+i] = chr(arr1[i] ^ key[i%4])
arr2 = [90, 100, 87, 109, 86, 108, 86, 105, 90, 104, 88, 102]

z3脚本解

from z3 import *
arr0 = [249,91,149,113,16,91,53,41]
arr1 = [43,1,6,69,20,62,6,44,24,113,6,35,0,3,6,44,20,22,127,60] 
arr2 = [90,100,87,109,86,108,86,105,90,104,88,102]  
k = Solver()
s = [BitVec('s[%d]'%i,64)for i in range(39)]
for i in range(39):
    k.add(32<=s[i])
    k.add(s[i]<128)
k.add(((((s[0]*128+s[1])*128+s[2])*128+s[3])*128+s[4])*128+s[5] == 3533889469877)
k.add(s[-1]== ord('}'))
arr =  list(s)
a = arr[6:30:3]
for i in range(len(a)):
    k.add((a[i]*17684+372511)%257==arr0[i])

b = arr[-2:33:-1]*5
c = list(map(lambda x:x[0]^x[1] ,zip(b,arr[7:27])))
for i in range(len(c)):
    k.add(c[i]==arr1[i])

p = 0
for i in range(28,34):
    k.add(arr2[p] == (arr[i]+107)/16+77)
    k.add((arr[i]+117)%16+99==arr2[p+1])
    p+=2
print(k.check())
print(k.model())

z3脚本二次转换

s = [0]*39
s[5]=53
s[4]=123
s[34]=117
s[7]=90
s[6]=76
s[30]=52
s[18]=86
s[35]=51
s[33]=78
s[24]=80
s[12]=120
s[11]=101
s[20]=69
s[15]=105
s[3]=103
s[25]=76
s[23]=101
s[2]=97
s[16]=55
s[29]=53
s[17]=53
s[22]=89
s[36]=70
s[21]=53
s[8]=71
s[13]=53
s[28]=108
s[26]=73
s[14]=89
s[0]=102
s[37]=113
s[31]=49
s[10]=48
s[1]=108
s[9]=53
s[27]=75
s[32]=112
s[19]=113
s[38]=125
for i in range(39):
   print(chr(s[i]),end="")

z3很好用。z3这部分脚本详细参考于CX-330的博文。
第一次知道有这种东西,值得学习嗷!

原文地址:https://www.cnblogs.com/Nickyl07/p/12748955.html