首页
社区
课程
招聘
[转帖][推荐]Python的decompile问题(1),(2),(3) by Team509
发表于: 2006-12-8 22:31 16215

[转帖][推荐]Python的decompile问题(1),(2),(3) by Team509

2006-12-8 22:31
16215
收藏
免费 7
支持
分享
最新回复 (27)
雪    币: 398
活跃值: (343)
能力值: (RANK:650 )
在线值:
发帖
回帖
粉丝
2
Team509的作品和文章,都不是讲“破解”的,却是比“破解”更透彻
建议段老板做个他们的专题,整理一下他们的作品和文章
2006-12-8 22:34
0
雪    币: 116
活跃值: (220)
能力值: ( LV12,RANK:370 )
在线值:
发帖
回帖
粉丝
3
学习
2006-12-8 23:31
0
雪    币: 846
活跃值: (221)
能力值: (RANK:570 )
在线值:
发帖
回帖
粉丝
4
“我们在网络安全这个行业也混了好多年了”

年轻的强人叫大大,他们那些混了好多年的, 就是老大。
2006-12-8 23:53
0
雪    币: 50141
活跃值: (20740)
能力值: (RANK:350 )
在线值:
发帖
回帖
粉丝
5
最初由 shoooo 发布
Team509的作品和文章,都不是讲“破解”的,却是比“破解”更透彻
建议段老板做个他们的专题,整理一下他们的作品和文章


发现Team509中人确实是牛,共享精神也很值得学习,如果shoooo 能把他们请到论坛,现场给大家指指路,那真是一大幸事
2006-12-9 10:09
0
雪    币: 263
活跃值: (10)
能力值: ( LV9,RANK:210 )
在线值:
发帖
回帖
粉丝
6
是啊
高级的看过了
简单的受益了
比如{
逆向工程的秘密-中文版
}
菜鸟编写CRME宝刀
2006-12-9 10:49
0
雪    币: 5275
活跃值: (476)
能力值: (RANK:1170 )
在线值:
发帖
回帖
粉丝
7
好啊,python
2006-12-9 12:07
0
雪    币: 258
活跃值: (230)
能力值: ( LV12,RANK:770 )
在线值:
发帖
回帖
粉丝
8
shoooooooooooooooooo
我要注册.....
2006-12-9 12:46
0
雪    币: 1241
活跃值: (160)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
9
python 的 decompiler 叫 decompyle ,其利用的扫描和解析模块叫 spark。这个模块在 python 中使用相当广泛。作者非常厉害。
decompyle 支持到 2.3 后不再免费提供,而是在网上搞了个反编译服务,反编译一个软件要好多欧元。#-(
不过在他的 decompyle 基础上通过只修改规则定义就可以支持到 2.4 ,当然对 python 2.4 及 2.5 以后出现新特性需要自己定义规则,另外这种简单方法修改得到的 decompyle 对后来 python 出现的一些结构优化不能很好的解决。所以如果想弄个比较好的 decompiler 就需要自己处理优化出现的问题了。
另外曾有个老外在2.3源码基础之上修订过一个版本使其支持到了2.4,在网上 emaillist中公布过,我通过狗狗搜索到了,不过我看了他的代码之后,很遗憾的是虽然他的代码N长,但并没有很好的解决问题。
2006-12-9 17:14
0
雪    币: 1241
活跃值: (160)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
10
另外,想补充说一点的是 python 是开源的,decompyle也曾是开源的,这些源代码都很有研究价值。
2006-12-9 17:31
0
雪    币: 331
活跃值: (56)
能力值: ( LV13,RANK:410 )
在线值:
发帖
回帖
粉丝
11
对写自己的脚本很有帮助,thx 4 share
2006-12-9 20:39
0
雪    币: 367
活跃值: (42)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
12
最初由 ljtt 发布
python 的 decompiler 叫 decompyle ,其利用的扫描和解析模块叫 spark。这个模块在 python 中使用相当广泛。作者非常厉害。
decompyle 支持到 2.3 后不再免费提供,而是在网上搞了个反编译服务,反编译一个软件要好多欧元。#-(
不过在他的 decompyle 基础上通过只修改规则定义就可以支持到 2.4 ,当然对 python 2.4 及 2.5 以后出现新特性需要自己定义规则,另外这种简单方法修改得到的 decompyle 对后来 python 出现的一些结构优化不能很好的解决。所以如果想弄个比较好的 decompiler 就需要自己处理优化出现的问题了。
另外曾有个老外在2.3源码基础之上修订过一个版本使其支持到了2.4,在网上 emaillist中公布过,我通过狗狗搜索到了,不过我看了他的代码之后,很遗憾的是虽然他的代码N长,但并没有很好的解决问题。

都被你说到了,不过我没有找到这个老外的源码
那些自定义的规则有什么规律和要求没有?
2006-12-9 21:02
0
雪    币: 10
活跃值: (135)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
13
最初由 ljtt 发布
python 的 decompiler 叫 decompyle ,其利用的扫描和解析模块叫 spark。这个模块在 python 中使用相当广泛。作者非常厉害。
decompyle 支持到 2.3 后不再免费提供,而是在网上搞了个反编译服务,反编译一个软件要好多欧元。#-(
不过在他的 decompyle 基础上通过只修改规则定义就可以支持到 2.4 ,当然对 python 2.4 及 2.5 以后出现新特性需要自己定义规则,另外这种简单方法修改得到的 decompyle 对后来 python 出现的一些结构优化不能很好的解决。所以如果想弄个比较好的 decompiler 就需要自己处理优化出现的问题了。
另外曾有个老外在2.3源码基础之上修订过一个版本使其支持到了2.4,在网上 emaillist中公布过,我通过狗狗搜索到了,不过我看了他的代码之后,很遗憾的是虽然他的代码N长,但并没有很好的解决问题。

能否共享一份 decompyle 的源码?我最近也在写一款脚本的 decompiler,在跳转处理上出现了一些问题,想参考一下它是怎么处理的。还有,PB的程序也是以中间代码出现的吗?老大是如何解决条件跳转判断问题的?一般跳转到的地方都是二次扫描后再填充的。先谢过了~
2006-12-10 01:30
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
14
惭愧,惭愧,我们在很多方面(特别是软件破解这方面)跟坛子里的很多老大比起来,水平还差得远了,指路什么的,完全谈不上,说句实话,我们当年也是全靠看雪论坛指路,才能对这个方面有所了解.
今后还得请坛子里的老大们多多指教,
多谢ljtt兄指路,那个decompyle我们现在正在研究,
希望可以尽快的作出对2.4,2.5的版本来.
hermit, DarkNess0ut 兄,这东西可在这里下载:
http://ftp.debian.org/debian/pool/main/d/decompyle/decompyle_2.3.2.orig.tar.gz

最初由 kanxue 发布
发现Team509中人确实是牛,共享精神也很值得学习,如果shoooo 能把他们请到论坛,现场给大家指指路,那真是一大幸事
2006-12-13 17:48
0
雪    币: 367
活跃值: (42)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
15
最初由 wooshi 发布
惭愧,惭愧,我们在很多方面(特别是软件破解这方面)跟坛子里的很多老大比起来,水平还差得远了,指路什么的,完全谈不上,说句实话,我们当年也是全靠看雪论坛指路,才能对这个方面有所了解.
今后还得请坛子里的老大们多多指教,
多谢ljtt兄指路,那个decompyle我们现在正在研究,
希望可以尽快的作出对2.4,2.5的版本来.
hermit, DarkNess0ut 兄,这东西可在这里下载:
........

谢谢,decompyle_2.3.2很早就已经下载到了
我要的是ljtt说的2.4的修改版,对那些自定义的规则不是很了解
2006-12-13 18:20
0
雪    币: 217
活跃值: (15)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
16
ljtt 我的偶像级人物啊
2006-12-13 18:25
0
雪    币: 146
活跃值: (33)
能力值: ( LV6,RANK:90 )
在线值:
发帖
回帖
粉丝
17
这样的站很喜欢.......
2006-12-13 18:48
0
雪    币: 146
活跃值: (33)
能力值: ( LV6,RANK:90 )
在线值:
发帖
回帖
粉丝
18
Forbidden
You don't have permission to access /download/docs/programming/ on this server.
2006-12-13 18:55
0
雪    币: 146
活跃值: (33)
能力值: ( LV6,RANK:90 )
在线值:
发帖
回帖
粉丝
19

虽然不懂,
但是想持续一下关注..
2006-12-14 21:12
0
雪    币: 217
活跃值: (15)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
20
这个页憷荇憷牦问题,洳槟ie7,扉浏览,靓憷韩冼懋体,晕啊

这个页是不是有问题,我用ie7,一浏览,就是韩文字体,晕啊
2006-12-15 17:42
0
雪    币: 50141
活跃值: (20740)
能力值: (RANK:350 )
在线值:
发帖
回帖
粉丝
21
转帖:Python的decompile问题(2)
URL:http://www.team509.com/modules.php?name=News&file=article&sid=45


上文我们讲到我们已经明白disassemble是怎么产生的了,现在我们来讨论如何从disassemble到decompile的转化,事实上在python 2.3以前是有一个工具来完成这个转化,decompyle , 这个工具可以从这里下载:


http://ftp.debian.org/debian/pool/main/d/decompyle/decompyle_2.3.2.orig.tar.gz


遗憾的是,2.3版本以后这个工具就不支持了,我们先研究一下decompyle,然后再实现我们的支持2.3以后的版本。首先声明一下,我对python和编译原理都不是很熟悉,所以文章中可以谬误难免,如果发现错误,请及时地通知我,我好做修改。




研究decompyle,就不得不研究spark,spark是decompyle的核心,decompyle事实上是spark的一个应用。Spark是一个用python写的,为小型语言准备的编译器的框架(framework),这样说起来真拗口,你把它理解为是一个python写的,功能主要是lex&yacc的功能,基本上就对了,spark主要分成四个部分:词法分析,语法分析,语义分析,代码生成,下面我们分别简单的介绍一下这四个部分:


词法分析:GenericScanner 类,你要用这个类的时候,需要为这个类写一个子类,同时定义一堆以”t_”开头的函数来实现具体的词法,比如说你要定义一个 digit , 在 lex中是这样:

digit [0-9] , 在spark中需要定义成这样:




class DigitScanner(GenericScanner):


def __init__(self):


GenericScanner.__init__(self)


def t_digit(self,s):


r’d’


t= Token(type=’digit’,attr=s)


self.rv.append(t)





语法分析:这个是整个spark最为古怪的部分了,因为它把所有的语法规则都作为相应函数的__doc__,这个前两天我看decompile的src的时候,把我给搞糊涂了,因为我在整个程序代码里没有找到语法规则,后来用debugger跟了半天才发现这个秘密,看spark文档的时候才特别对这个问题注意了,举一例说明之:


def p_funcdef(self, args):


'''


stmt ::= funcdef


funcdef ::= mkfunc designator


load_closure ::= load_closure LOAD_CLOSURE


load_closure ::= LOAD_CLOSURE


'''


语法分析与词法分析类似,你要加你自己的语法规则的话,需要写一个类,作为GenericParser的子类,同时有定义语法规则的函数都以”p_”开始。语法分析的主要目的是建立AST树





语义分析:在spark中,这个功能的framework由GenericASTTraversal实现,主要用来遍历语法分析生成的ast树,做语法检查。同词法分析,语法分析一样,你要使用它,需要写一个GenericASTTraversal的子类,处理函数需要以”n_”开头。





代码生成:这个含义很明显了,生成最终的代码,在spark中,和语义分析一样,都是由GenericASTTraversal实现,方法都一样,遍历语法分析生成的ast树,但主要用途不一样而已。





好了,我们简单的介绍到这里,有不明白的看这里:


http://pages.cpsc.ucalgary.ca/~aycock/spark/paper.pdf


下面我们看看decompyle是怎样利用spark生成python的decompile的。


首先,我们要有个概念,我们只要能成功的定义出词法分析规则和语法分析规则,那么


我们就可以利用spark来实现decompile.


我们来看看如何定出这些规则,下面以例子的形式来说明(decompyle的一个例子):


def kwfunc(**kwargs):


print kwargs.items()





def argsfunc(*args):


print args





def no_apply(*args, **kwargs):


print args


print kwargs.items()


argsfunc(34)


foo = argsfunc(*args)


argsfunc(*args)


argsfunc(34, *args)


kwfunc(**kwargs)


kwfunc(x=11, **kwargs)


no_apply(*args, **kwargs)


no_apply(34, *args, **kwargs)


no_apply(x=11, *args, **kwargs)


no_apply(34, x=11, *args, **kwargs)


no_apply(42, 34, x=11, *args, **kwargs)





no_apply(1,2,4,8,a=2,b=3,c=5)





编译后利用decompyle 进行 disassemble得到:


6 LOAD_CONST 'code_object kwfunc'


9 MAKE_FUNCTION_0 ''


12 STORE_NAME 'kwfunc'


18 LOAD_CONST 'code_object argsfunc'


21 MAKE_FUNCTION_0 ''


24 STORE_NAME 'argsfunc'


30 LOAD_CONST 'code_object no_apply'


33 MAKE_FUNCTION_0 ''


36 STORE_NAME 'no_apply'


42 LOAD_NAME 'no_apply'


45 LOAD_CONST 1


48 LOAD_CONST 2


51 LOAD_CONST 4


54 LOAD_CONST 8


57 LOAD_CONST 'a'


60 LOAD_CONST 2


63 LOAD_CONST 'b'


66 LOAD_CONST 3


69 LOAD_CONST 'c'


72 LOAD_CONST 5


75 CALL_FUNCTION_772 ''


78 POP_TOP ''


79 LOAD_CONST ''


82 RETURN_VALUE ''





6 LOAD_FAST 'kwargs'


9 LOAD_ATTR 'items'


12 CALL_FUNCTION_0 ''


15 PRINT_ITEM ''


16 PRINT_NEWLINE ''


17 LOAD_CONST ''


20 RETURN_VALUE ''





6 LOAD_FAST 'args'


9 PRINT_ITEM ''


10 PRINT_NEWLINE ''


11 LOAD_CONST ''


14 RETURN_VALUE ''





6 LOAD_FAST 'args'


………………………………………………….





220 CALL_FUNCTION_VAR_KW_258 ''


223 POP_TOP ''


224 LOAD_CONST ''


227 RETURN_VALUE ''





可以看到,disassemble的指令的格式基本上是:





Opcode


或 opcode+一个参数





Decompyle为了简便起见,把一些opcode做了一些变形,比如说上面标有220的这行:


220 CALL_FUNCTION_VAR_KW_258 ''


事实上应该是 220 CALL_FUNCTION_VAR_KW 258





在Decompyle中,每一个token都有四个属性:opname ,oparg,pattr,offset, opname就是每一行前面那个词,比如LOAD_CONST, LOAD_FAST,oparg就是后面跟的那个short型的整数了,pattr是把有些opcode用到的局部变量,名称从pyc或pyo中查出来,填到这个地方,还有就是计算跳转型的opcode)的跳转地址计算出来填进去,具体例子可以看这系列文章的(1)的做法,offset是这条opcode在这条指令流的偏移地址,比如说上面这个(220 CALL_FUNCTION_VAR_KW 258)的220就是offset.





词法分析规则是相当的简单,因为一条opcode无非是1 byte 或 3 bytes长,一个字节一个字节的读进来,有参数的(opcode > 90) 再读两字节,然后按照不同的opcode属性,比如说用到局部变量的,查查局部变量表,填到pattr里去,我们就得到了排列好的tokens了。





下面要进行的工作就是把一维的tokens列表,变成2维的AST树,这个除了语法分析规则要我们提供以外,其他的工作都由spark帮我们做好了,我们考虑语法分析规则就行了。


Decompiler的语法分析规则其实就是确定哪些opcode的组合对应哪一条高级语言的语句,比如说:


LOAD_CONST ‘hello world’


PRINT_ITEM


PRINT_NEWLINE


你就知道是 print “ hello world”


我们把它抽象出来,用spark的定义语义规则形式就是:


def p_print(self, args):


'''


stmt ::= print_stmt


stmt ::= print_stmt_nl


stmt ::= print_nl_stmt


print_stmt ::= expr PRINT_ITEM


print_nl_stmt ::= PRINT_NEWLINE


print_stmt_nl ::= print_stmt print_nl_stmt


'''





遇到这样的opcode组合后,代表这部分的AST树可归约成: print_stmt_nl,然后在decompyle的walk.py中你会发现:


'print_stmt_nl': ( '%|print %[0]C ', (0,1, None) ),





有了这条规则,decompyle在输出的就会直接把print_stmt_nl这个node输出为 print 加上参数。





好了,我们大概知道decompyle是怎么干的了,如果我们要给decompyle做一个扩展,让它能够符合2.4,2.5的话,那么有哪些地方需要修改呢?


1. Dis部分,这部分可能要把2.4,2.5新出现的opcode(有么?),加进去,简单。


2. 词法分析阶段,跟Dis部分差不多,新出现的opcode对应得token处理加进去,简单。


3. 语法分析阶段,这个复杂了,pyc应该和以前的差不多,但如果python采用了新的优化技术的话,pyo的处理(语法规则)可能很多要重新写过了,这个比较花时间了。


4. Output(代码生成),简单,小修改即可。





下面我们就研究研究2.4,2.5跟2.3,2.2的处理有什么不同吧。


(待续)
2006-12-19 09:10
0
雪    币: 50141
活跃值: (20740)
能力值: (RANK:350 )
在线值:
发帖
回帖
粉丝
22
Python的decompile问题(3)
URL:http://www.team509.com/modules.php?name=News&file=article&sid=46

Python的decompile问题(3)

现在我们开始修改decompyle,来使它能够符合python2.4, 2.5.




(1) 用decompyle-2.3.2.orig这个版本为基础进行修改,首先在magics.py中加入(一看就知道加到magics.py的什么地方):


__build_magic(62061): '2.4',


__build_magic(62131): '2.5',


在dis_files.py中加入:


'2.4': dis('2.4’, 'dis_24'),


'2.5': dis('2.5', 'dis_25'),


在marshal_files.py中加入:





'2.4': 'marshal_24',


'2.5': 'marshal_25',





分别从安装2.4,2.5版本的python 的lib目录下(c:python24lib,c:python25lib)把dis.py和opcode.py拷贝过来,命名为dis_24.py,opcode_24.py, dis_25.py,opcode_25.py,并把两个dis文件里的import opcode做相应修改。


(2) 把python2.4,python2.5的src包里的marshal.c拷贝过来,命名为marshal_24.c, marshal_25.c,并照着marshal_23.c格式修改其中内容,就是最后3行啦。再修改setup.py中的内容,把marshal_24.c, marshal_25.c加进去。


(3) 下面就是修改parser.py和walker.py,这个内容比较多,我试举一例来说明如何修改,先安装前面修改的这个decompyle到python2.5,再用python2.5编译decompyle的test_import.py,到test_import.pyc, 用我们新修改的decompyle试一下,发现不能用了,


错误是:Syntax error at or near `IMPORT_NAME' token at offset 12


我们看看错误周围的test_import.pyc的asm:


6 LOAD_CONST -1


9 LOAD_CONST ''


12 IMPORT_NAME 'sys'


15 STORE_NAME 'sys'


我们再比较2.2的相应得asm:


15 LOAD_CONST ''


18 IMPORT_NAME 'sys'


21 STORE_NAME 'sys'


发现一个import sys对应得asm多了一条:LOAD_CONST -1,


看来我们需要在parser.py中的p_import20函数中添加:


stmt ::= importstar25


stmt ::= importstmt25


stmt ::= importfrom25





importstmt25 ::= LOAD_CONST LOAD_CONST import_as


importstar25 ::= LOAD_CONST LOAD_CONST IMPORT_NAME IMPORT_STAR


importfrom25 ::= LOAD_CONST LOAD_CONST IMPORT_NAME importlist2 POP_TOP


就是把原来每条实用规则前面多加一条LOAD_CONST就行了。


再在walker.py的importstmt2规则下面添加:


'importstmt25': ( '%|import %c ', 2),


'importstar25': ( '%|from %[2]{pattr} import * ', ),


'importfrom25': ( '%|from %[2]{pattr} import %c ', 3 ),


Hehe,照着上面的importstmt2,还是很容易写的。


好了,把修改过的parser.py,walker.py存盘,运行decompyle 来 decompile test_import.pyc,OK,这次一点错都没有了。





这个修改过程还比较多,一个完整的版本大家还得等一段时间了。不过,照上面修改过的版本对一般简单的pyc,pyo已经可以用了。
2006-12-19 09:11
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
23
谢谢楼主的介绍,很有意思
2006-12-19 09:42
0
雪    币: 217
活跃值: (15)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
24
高淫啊,佩服啊
2006-12-19 09:50
0
雪    币: 10
活跃值: (135)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
25
这工作相当于自己写一款脚本引擎了~

思路非常有创意,俺咋木有想到涅~
2006-12-19 13:59
0
游客
登录 | 注册 方可回帖
返回
// // 统计代码