这不是传统的字节码,而是反汇编的字节码,没有编译器来编译这段代码。
我有一个编码器来进行逆向工程。然而,该编码器被拆卸并以人类可读的形式出现。到目前为止,我已将大部分代码重写为源代码,但遇到了倒数第二行的问题,我不知道如何更改为源代码。经过无数个小时在互联网上寻求我没有找到的帮助,如果他们有阅读已经被拆解的python-bytecode的经验,我会向任何人寻求帮助。 到目前为止我所拥有的:
import sys
YSaM = open
YSam = max
YSaN = len
YSaP = xrange
YSap = sys.argv
YSal = YSaM(sys.argv[1],'r').realines()
YSaW = [l.strip().replace(' ','.') for l in (YSal)]
YSas = YSam([YSaN(l) for l in (YSaW)]) #Missing CALL_FUNCTION_VAR with 0 attributes
YSaO = YSaN(YSaW)
YSak = [l + ('.' * (YSas - YSaN(l))) for l in (YSaW)]
YSaJ = [(s[(YSaN(s)/2):] + s[:(YSaN(s)/2)]) for s in (YSak)]
def YSag(s,f,i):
YSaw = ''
if YSaN(s) > YSaO:
YSaw = YSag(s[:-YSaO],f,i)
f(s[-YSaO:]) + YSaw
YSao = ''
for x in YSaP(0,YSas):
YSaL = [l[x] for l in (YSaJ)]
YSaF = ''.join(YSaL)
if x%2 == 0:
YSaF = (YSaF[(x%YSaN(YSaF)):] + YSaF[:(x%YSaN(YSaF))])
else:
YSaF = (YSaF[-(x%YSaN(YSaF)):] + YSaF[:-(x%YSaN(YSaF))])
YSao = YSaF + YSao
YSay = [YSag(YSao,(lambda x: s[x]),x) for x in YSaP(0,YSaO)]
for YSar in (YSay): print YSar
这是在反汇编的python-bytecode中给我的原始信息:
14 0 LOAD_CONST 1 ('')
3 STORE_FAST 3 (YSaw)
15 6 LOAD_GLOBAL 0 (YSaN)
9 LOAD_FAST 0 (s)
12 CALL_FUNCTION 1
15 LOAD_GLOBAL 1 (YSaO)
18 COMPARE_OP 4 (>)
21 POP_JUMP_IF_FALSE 50
16 24 LOAD_GLOBAL 2 (YSag)
27 LOAD_FAST 0 (s)
30 LOAD_GLOBAL 1 (YSaO)
33 UNARY_NEGATIVE
34 SLICE+2
35 LOAD_FAST 1 (f)
38 LOAD_FAST 2 (i)
41 CALL_FUNCTION 3
44 STORE_FAST 3 (YSaw)
47 JUMP_FORWARD 0 (to 50)
17 >> 50 LOAD_FAST 1 (f)
53 LOAD_FAST 0 (s)
56 LOAD_GLOBAL 1 (YSaO)
59 UNARY_NEGATIVE
60 SLICE+1
61 CALL_FUNCTION 1
64 LOAD_FAST 3 (YSaw)
67 BINARY_ADD
68 RETURN_VALUE
27 0 LOAD_FAST 0 (s)
3 LOAD_GLOBAL 0 (x)
6 BINARY_SUBSCR
7 RETURN_VALUE
1 0 LOAD_CONST 0 (-1)
3 LOAD_CONST 1 (None)
6 IMPORT_NAME 0 (sys)
9 STORE_NAME 0 (sys)
2 12 LOAD_NAME 1 (open)
15 STORE_NAME 2 (YSaM)
3 18 LOAD_NAME 3 (max)
21 STORE_NAME 4 (YSam)
4 24 LOAD_NAME 5 (len)
27 STORE_NAME 6 (YSaN)
5 30 LOAD_NAME 7 (xrange)
33 STORE_NAME 8 (YSaP)
6 36 LOAD_NAME 0 (sys)
39 LOAD_ATTR 9 (argv)
42 STORE_NAME 10 (YSap)
7 45 LOAD_NAME 2 (YSaM)
48 LOAD_NAME 10 (YSap)
51 LOAD_CONST 2 (1)
54 BINARY_SUBSCR
55 LOAD_CONST 3 ('r')
58 CALL_FUNCTION 2
61 LOAD_ATTR 11 (readlines)
64 CALL_FUNCTION 0
67 STORE_NAME 12 (YSal)
8 70 BUILD_LIST 0
73 LOAD_NAME 12 (YSal)
76 GET_ITER
>> 77 FOR_ITER 30 (to 110)
80 STORE_NAME 13 (l)
83 LOAD_NAME 13 (l)
86 LOAD_ATTR 14 (strip)
89 CALL_FUNCTION 0
92 LOAD_ATTR 15 (replace)
95 LOAD_CONST 4 (' ')
98 LOAD_CONST 5 ('.')
101 CALL_FUNCTION 2
104 LIST_APPEND 2
107 JUMP_ABSOLUTE 77
>> 110 STORE_NAME 16 (YSaW)
9 113 LOAD_NAME 4 (YSam)
116 BUILD_LIST 0
119 LOAD_NAME 16 (YSaW)
122 GET_ITER
>> 123 FOR_ITER 18 (to 144)
126 STORE_NAME 13 (l)
129 LOAD_NAME 6 (YSaN)
132 LOAD_NAME 13 (l)
135 CALL_FUNCTION 1
138 LIST_APPEND 2
141 JUMP_ABSOLUTE 123
>> 144 CALL_FUNCTION_VAR 0
147 STORE_NAME 17 (YSas)
10 150 LOAD_NAME 6 (YSaN)
153 LOAD_NAME 16 (YSaW)
156 CALL_FUNCTION 1
159 STORE_NAME 18 (YSaO)
11 162 BUILD_LIST 0
165 LOAD_NAME 16 (YSaW)
168 GET_ITER
>> 169 FOR_ITER 30 (to 202)
172 STORE_NAME 13 (l)
175 LOAD_NAME 13 (l)
178 LOAD_CONST 5 ('.')
181 LOAD_NAME 17 (YSas)
184 LOAD_NAME 6 (YSaN)
187 LOAD_NAME 13 (l)
190 CALL_FUNCTION 1
193 BINARY_SUBTRACT
194 BINARY_MULTIPLY
195 BINARY_ADD
196 LIST_APPEND 2
199 JUMP_ABSOLUTE 169
>> 202 STORE_NAME 19 (YSak)
12 205 BUILD_LIST 0
208 LOAD_NAME 19 (YSak)
211 GET_ITER
>> 212 FOR_ITER 44 (to 259)
215 STORE_NAME 20 (s)
218 LOAD_NAME 20 (s)
221 LOAD_NAME 6 (YSaN)
224 LOAD_NAME 20 (s)
227 CALL_FUNCTION 1
230 LOAD_CONST 6 (2)
233 BINARY_DIVIDE
234 SLICE+1
235 LOAD_NAME 20 (s)
238 LOAD_NAME 6 (YSaN)
241 LOAD_NAME 20 (s)
244 CALL_FUNCTION 1
247 LOAD_CONST 6 (2)
250 BINARY_DIVIDE
251 SLICE+2
252 BINARY_ADD
253 LIST_APPEND 2
256 JUMP_ABSOLUTE 212
>> 259 STORE_NAME 21 (YSaJ)
13 262 LOAD_CONST 7 (<code object YSag at 0x7f7ca5faa930, file "./slither_encode_obfu_min.py", line 13>)
265 MAKE_FUNCTION 0
268 STORE_NAME 22 (YSag)
18 271 LOAD_CONST 8 ('')
274 STORE_NAME 23 (YSao)
19 277 SETUP_LOOP 174 (to 454)
280 LOAD_NAME 8 (YSaP)
283 LOAD_CONST 9 (0)
286 LOAD_NAME 17 (YSas)
289 CALL_FUNCTION 2
292 GET_ITER
>> 293 FOR_ITER 157 (to 453)
296 STORE_NAME 24 (x)
20 299 BUILD_LIST 0
302 LOAD_NAME 21 (YSaJ)
305 GET_ITER
>> 306 FOR_ITER 16 (to 325)
309 STORE_NAME 13 (l)
312 LOAD_NAME 13 (l)
315 LOAD_NAME 24 (x)
318 BINARY_SUBSCR
319 LIST_APPEND 2
322 JUMP_ABSOLUTE 306
>> 325 STORE_NAME 25 (YSaL)
21 328 LOAD_CONST 8 ('')
331 LOAD_ATTR 26 (join)
334 LOAD_NAME 25 (YSaL)
337 CALL_FUNCTION 1
340 STORE_NAME 27 (YSaF)
22 343 LOAD_NAME 24 (x)
346 LOAD_CONST 6 (2)
349 BINARY_MODULO
350 LOAD_CONST 9 (0)
353 COMPARE_OP 2 (==)
356 POP_JUMP_IF_FALSE 400
23 359 LOAD_NAME 27 (YSaF)
362 LOAD_NAME 24 (x)
365 LOAD_NAME 6 (YSaN)
368 LOAD_NAME 27 (YSaF)
371 CALL_FUNCTION 1
374 BINARY_MODULO
375 SLICE+1
376 LOAD_NAME 27 (YSaF)
379 LOAD_NAME 24 (x)
382 LOAD_NAME 6 (YSaN)
385 LOAD_NAME 27 (YSaF)
388 CALL_FUNCTION 1
391 BINARY_MODULO
392 SLICE+2
393 BINARY_ADD
394 STORE_NAME 27 (YSaF)
397 JUMP_FORWARD 40 (to 440)
25 >> 400 LOAD_NAME 27 (YSaF)
403 LOAD_NAME 24 (x)
406 LOAD_NAME 6 (YSaN)
409 LOAD_NAME 27 (YSaF)
412 CALL_FUNCTION 1
415 BINARY_MODULO
416 UNARY_NEGATIVE
417 SLICE+1
418 LOAD_NAME 27 (YSaF)
421 LOAD_NAME 24 (x)
424 LOAD_NAME 6 (YSaN)
427 LOAD_NAME 27 (YSaF)
430 CALL_FUNCTION 1
433 BINARY_MODULO
434 UNARY_NEGATIVE
435 SLICE+2
436 BINARY_ADD
437 STORE_NAME 27 (YSaF)
26 >> 440 LOAD_NAME 27 (YSaF)
443 LOAD_NAME 23 (YSao)
446 BINARY_ADD
447 STORE_NAME 23 (YSao)
450 JUMP_ABSOLUTE 293
>> 453 POP_BLOCK
27 >> 454 BUILD_LIST 0
457 LOAD_NAME 8 (YSaP)
460 LOAD_CONST 9 (0)
463 LOAD_NAME 18 (YSaO)
466 CALL_FUNCTION 2
469 GET_ITER
>> 470 FOR_ITER 27 (to 500)
473 STORE_NAME 24 (x)
476 LOAD_NAME 22 (YSag)
479 LOAD_NAME 23 (YSao)
482 LOAD_CONST 10 (<code object <lambda> at 0x7f7ca5faf2b0, file "./slither_encode_obfu_min.py", line 27>)
485 MAKE_FUNCTION 0
488 LOAD_NAME 24 (x)
491 CALL_FUNCTION 3
494 LIST_APPEND 2
497 JUMP_ABSOLUTE 470
>> 500 STORE_NAME 28 (YSay)
28 503 SETUP_LOOP 19 (to 525)
506 LOAD_NAME 28 (YSay)
509 GET_ITER
>> 510 FOR_ITER 11 (to 524)
513 STORE_NAME 29 (YSar)
516 LOAD_NAME 29 (YSar)
519 PRINT_ITEM
520 PRINT_NEWLINE
521 JUMP_ABSOLUTE 510
>> 524 POP_BLOCK
>> 525 LOAD_CONST 1 (None)
528 RETURN_VALUE
任何帮助都将非常感谢!!!
答案 0 :(得分:2)
你真的想要自动化,而不是手工完成;有一些工具,如decompyle
和uncompyle
,可以从字节码生成Python源代码。
来自代码对象的字节码有些混乱,我们错过了代码对象中的co_argcount
和co_varnames
信息。但是,我非常确定列表理解应该是:
YSay = [YSag(YSao, lambda s: s[x], x) for x in YSaP(0, YSaO)]
字节码
476 LOAD_NAME 22 (YSag)
479 LOAD_NAME 23 (YSao)
482 LOAD_CONST 10 (<code object <lambda> at 0x7f7ca5faf2b0, file "./slither_encode_obfu_min.py", line 27>)
485 MAKE_FUNCTION 0
488 LOAD_NAME 24 (x)
491 CALL_FUNCTION 3
从上到下转换为包含x
,lambda,YSao
和YSag
的堆栈,CALL_FUNCTION
以相反的顺序将前3个传递到最后一个,所以YSag(YSao, <lambda>, x)
被称为。{/ p>
lambda从第27行加载,其字节码为:
27 0 LOAD_FAST 0 (s)
3 LOAD_GLOBAL 0 (x)
6 BINARY_SUBSCR
7 RETURN_VALUE
这意味着s
是lambda的参数(它本地加载了LOAD_FAST
),而x
是全局的,所以这转换为lambda s: s[x]
。
请注意,CALL_FUNCTION_VAR
使用*args
来电功能,因此您需要将第9行更正为:
YSas = YSam(*[YSaN(l) for l in YSaW])
结果证明是拼写max(len(l) for l in YSaW)
的冗长方式,但是列表推导扩展为单独的参数而不是作为单个参数传入的生成器表达式。
我发现将dis.dis()
function与compile()
一起使用可以看看我对字节码的解释是否正确;提供表达式或语句,输出应大致匹配您的字节码(行号和字节码编号偏移量):
from dis import dis
dis(compile(string, '', 'exec'))
例如,对于最后一行,我用以下结果验证了结果:
>>> dis(compile('YSas = YSam(*[YSaN(l) for l in YSaW])', '', 'exec'))
1 0 LOAD_NAME 0 (YSam)
3 BUILD_LIST 0
6 LOAD_NAME 1 (YSaW)
9 GET_ITER
>> 10 FOR_ITER 18 (to 31)
13 STORE_NAME 2 (l)
16 LOAD_NAME 3 (YSaN)
19 LOAD_NAME 2 (l)
22 CALL_FUNCTION 1
25 LIST_APPEND 2
28 JUMP_ABSOLUTE 10
>> 31 CALL_FUNCTION_VAR 0
34 STORE_NAME 4 (YSas)
37 LOAD_CONST 0 (None)
40 RETURN_VALUE
对于函数对象,您希望从给定的co_consts
条目(compile(...).co_code.co_consts[an_index]
)中提取代码对象,或者首先创建函数,然后将函数对象传递给dis.dis()
:
>>> dis(lambda s: s[x])
1 0 LOAD_FAST 0 (s)
3 LOAD_GLOBAL 0 (x)
6 BINARY_SUBSCR
7 RETURN_VALUE
最后,你有一个编码很差的软件,它会从文件中混淆字符。我已经清理了混淆并使用了一些惯用的Python来实现我认为产生相同输出的东西:
import sys
def rotn(s, n): return s[n:] + s[:n]
with open(sys.argv[1]) as inf:
lines = [l.strip().replace(' ', '.') for l in inf]
maxlength = max(len(l) for l in lines)
padded = (l.ljust(maxlength, '.') for l in lines)
swapped = [rotn(s, len(s) // 2) for s in padded]
cols = []
for x, col in enumerate(zip(*swapped)):
offset = (x % len(col)) * (-1 if x % 2 else 1)
cols.append(rotn(col, offset))
for row in zip(*cols):
print ''.join(row)
因此将.
的所有剥离线填充到相同的长度,交换开始和结束的行,然后在结果中向上或向下旋转生成的文本块中的每个列数字(每列交换方向),然后显示结果文本。
我怀疑在这里也不一定需要使用'.'
代替空格;放弃.replace()
调用并让str.ljust()
使用默认空格填充为您提供基本相同的结果,但空格保持不变。