ython是一种解释型语言,但是与javascript这种纯脚本语言不同,python提供了一种编译成字节码运行的方法,编译之后就得到pyc文件,这点和java编译成class文件再用jvm解释运行很类似,但是与java不同的是,python编译字节码不是一个强制的操作,事实上,编译是一个自动的过程,一般不会在意它的存在。
编译成字节码可以节省加载模块的时间,提高效率。除了效率之外,字节码的形式也增加了反向工程的难度,可以保护源代码。这个只是一定程度上的保护,反编译还是可以的。
我们编写两个py脚本
mylib.py:包含一个函数,打印一行文字.
def keyFun():
print("keyFun is running")
main.py:程序运行入口,调用mylib种的keyFun函数
from mylib import keyFun
if __name__=="__main__":
keyFun()
编译所有文件,在脚本目录执行以下命令:
python -m compileall .
可以看到生成了相对应的两个pyc文件
编译生成pyc文件
此时执行main.cpython-38.pyc会提示找不到mylib模块,需要将文件名中的.cpython-38删掉.
执行pyc文件
反编译pyc的工具很多,我用的是python3.8,这里介绍几种可以反编译python3.8的工具.
本文作为演示,使用在线网站反编译mylib.py,可以看到下图反编译代码与实际代码一模一样.
反编译pyc结果
我们使用pyinstaller将main.py打包成exe文件
pyinstaller -F main.py
pyinstaller打包exe并执行
反编译pyinstaller打包的exe需要用到pyinstxtractor(https://github.com/extremecoders-re/pyinstxtractor).
将main.exe复制到pyinstxtractor文件夹,执行python pyinstxtractor.py main.exe
python pyinstxtractor.py main.exe
反编译exe
可以看到pyinstxtractor已经提示入口文件为main.pyc.我们反编译main.pyc就可以看到pyc引入可哪些模块,这个例子可以从反编译代码中看到引入了mylib模块,再接着反编译mylib.pyc就可以了.
从上面的反编译pyc文件结果可以看出,pyc很容易就被反编译,无法保护我们的代码.这里我们介绍使用Cython将python文件编译成pyd文件的方法.
首先安装Cython(Anaconda自带Cython的话不需要安装)
pip install Cython
在mylib.py所在目录新建build_pyd.py文件
from distutils.core import setup
from Cython.Build import cythonize
setup(
ext_modules=cythonize([
"mylib.py"
]),
)
#1.执行 python build_pyd.py build_ext --inplace
#2.再把.cp38-win_amd64删掉 python renamepyd_file.py
执行python build_pyd.py build_ext --inplace.将会为mylib.py生成对应的.c文件和.pyd文件
Cython生成pyd文件
与上文提到的pyc文件无法直接执行一样,pyd文件也需要删除文件名中的.cp38-win_amd64.这样main.py才能找到对应的mylib.pyd.
import os
lists=os.listdir("./")
for item in lists:
try:
if ".cp38-win_amd64.pyd" in item:
# 重命名文件
fileName=item.replace("cp38-win_amd64.", "")
files=os.rename(item, fileName)
except Exception as e:
print(e)
执行main.py,此时main.py引用的是编译后的mylib.pyd.如果修改了mylib.py中的代码,需要删除pyd文件后调试,不然不会看到改动后的效果.
使用上文中的方法将python文件编译为pyd文件后,再用pynstaller打包,这时候我们反编译就只能看到pyd文件了,要想破解pyd文件就需要使用汇编级别的破解技术,如果你的代码需要别人这样去破解的话,那恭喜你了,哈哈.
需要注意的是,编译为pyd再用pyinstaller打包,可能会出现模块无法被打包进去的情况,这时候需要编辑spec文件,将mylib模块添加到hiddenimports中.
a=Analysis(['main.py'],
pathex=['E:\\playground\\decompiletest'],
binaries=[],
datas=[],
//这里引入mylib模块
hiddenimports=['mylib'],
hookspath=[],
runtime_hooks=[],
excludes=[],
win_no_prefer_redirects=False,
win_private_assemblies=False,
cipher=block_cipher,
noarchive=False)
更多pyinstaller的高级技巧可以看我之前的一篇文章pyinstaller打包python程序高级技巧
注于Java领域优质技术,欢迎关注
来自:漫画编程
某天下班后,我在家里进行电话面试,问到面试者这样一个问题:"你知道使用哪些办法可以反编译Java代码吗?"。但是面试者回答的并不好,所以我在面试评价中写到:"对编译原理相关知识理解的不透彻"。这时,女朋友看到这句话。
计算机语言(Computer Language)指用于人与计算机之间通讯的语言。计算机语言是人与计算机之间传递信息的媒介。
计算机系统最大特征是指令通过一种语言传达给机器。为了使电子计算机进行各种工作,就需要有一套用以编写计算机程序的数字、字符和语法规划,由这些字符和语法规则组成计算机各种指令(或各种语句)。这些就是计算机能接受的语言。
计算机语言包括机器语言、汇编语言和高级语言三种。
机器语言
机器语言是用二进制代码表示的计算机能直接识别和执行的一种机器指令的集合。机器语言具有灵活、直接执行和速度快等特点。但是不同型号的计算机其机器语言是不相通的,按着一种计算机的机器指令编制的程序,不能在另一种计算机上执行。
因为机器语言是使用二进制表示的,所以编出的程序全是些0和1的指令代码。
机器语言的优点就是可以直接被计算机识别和执行,比较高效,但是同时也有很多缺点,如:
由于机器语言有这么多的弊端,于是有了汇编语言。
汇编语言
汇编语言使用助记符(Mnemonics)来代替和表示特定低级机器语言的操作。
助记符(mnemonic)是便于人们记忆、并能描述指令功能和指令操作数的符号,助记符是表明指令功能的英语单词或其缩写。如用ADD表示加法、MOV表示传送、SUB表示减法等。
但是,汇编语言只是让使用者,即程序员们更加容易记住和使用,计算机并不认识汇编语言,所以,想要让计算机执行汇编代码,需要先将汇编程序将它们转换成可执行的机器语言代码。这一过程被称为汇编过程。
由于汇编更接近机器语言,能够直接对硬件进行操作,生成的程序与其他的语言相比具有更高的运行速度,占用更小的内存,因此在一些对于时效性要求很高的程序、许多大型程序的核心模块以及工业控制方面大量应用。
机器语言和汇编语言,二者是几乎很少或者完全没有做任何语法抽象的,这种语言我们通常称之为低级语言,这种更加接近硬件,而且是不可以在不同硬件间移植的。
但是随着现代软件系统越来越庞大复杂,大量经过了封装的高级语言如C/C++,Pascal/Object Pascal也应运而生。这些新的语言使得程序员在开发过程中能够更简单,更有效率,使软件开发人员得以应付快速的软件开发的要求。
高级语言
高级语言是高度封装了的编程语言,与低级语言相对。
它是以人类的日常语言为基础的一种编程语言,使用一般人易于接受的文字来表示(例如汉字、不规则英文或其他外语),从而使程序编写员编写更容易,亦有较高的可读性,以方便对电脑认知较浅的人亦可以大概明白其内容。
如流行的java,c,c++,C#,pascal,python,lisp,prolog,FoxPro,易语言,中文版的C语言习语言等等,这些语言的语法、命令格式都不相同。
同汇编语言一样,高级语言离机器语言更加远了,计算机无法直接诶识别高级语言。所以,想要让计算机执行高级语言,就需要将其转化为机器语言。
?
文对常用的反编译工具进行简单介绍
JD-GUI、procyon-decompiler、luyten、crf
JDK7以及之前可以使用 JD-GUI,如果版本>=1.8 各种问题
http://java-decompiler.github.io
如果版本>=1.8 ,可以使用 procyon-decompiler,不过是命令行界面
https://bitbucket.org/mstrobel/procyon/downloads/
luyten是Procyon的GUI,只需要下载luyten即可,不用下载Procyon
https://github.com/deathmarine/Luyten
下载地址
https://github.com/deathmarine/Luyten/releases
crf也可以支持更高版本
http://www.benf.org/other/cfr/
小结
如果你的版本<=7,都可以使用,如果版本更高,请使用除了JD-GUI以外的选择
略,JD-GUI网上教程很多,不再介绍。
可以直接解析class文件到cmd窗口显示
也可以将反编译之后的文件保存到指定位置,如果需要保存在指定位置,需要增加 -o命令参数,并且需要指定保存的路径
直接显示:
java -jar D:\ApplicationFiles\program\procyon-decompiler-0.5.30.jar D:\ProgramData\ideaProjects\...\news\NewsController.class
保存文件:
java -jar D:\ApplicationFiles\program\procyon-decompiler-0.5.30.jar D:\ProgramData\ideaProjects\...\news\NewsController.class -o C:\Users\noteless\Desktop\dddddd
luyten是图形化界面
通过File直接打开class文件即可
当然,也可以进行文件保存等操作
注意
直接打开luyten的时候,给出了下面的提示信息
但是,系统中的java环境是没有问题的,也是一直在使用的,CMD下运行java或者javac命令都没有问题
这是为什么?
据网上分析是因为使用了免安装版本的JDK,简单说不是从官网下载可执行程序一步一步安装而来
这也就导致了注册表中不存在JDK的信息
一种变通的途径就是借助于命令,通过在命令提示符下面输入 java -jar .\luyten-0.5.4.exe打开
(此时,我的文件存在于桌面上,所以使用的当前路径)
如果设置到其他位置,请给出路径,比如
也可以进一步设置为bat命令
文件就一行内容:
java -jar D:\ApplicationFiles\program\luyten-0.5.4.exe
再进一步可以创建一个快捷方式,使用下文的方式,就可以直接使用WIN键+R打开
https://www.cnblogs.com/noteless/p/10471005.html
另一种方法,就是手动设置注册表
还有一种方法是重新安装JDK,走一遍过程
建议通过命令java -jar就好了,改注册表后续出现什么奇怪问题,自己可能都忘记了是自己改出来的
重新安装麻烦费事
http://www.benf.org/other/cfr/
CFR更新还是蛮及时的
它的使用,与procyon-decompiler没有区别
可以直接反编译呈现在CMD中,也可以输出到文件中
直接解析:
C:\Users\noteless>java -jar D:\ApplicationFiles\program\cfr-0.141.jar C:\Users\noteless\Desktop\NewsController.class
输出文件:
java -jar D:\ApplicationFiles\program\cfr-0.141.jar C:\Users\noteless\Desktop\NewsController.class --outputdir C:\Users\noteless\Desktop\xxx
文章来源:https://www.cnblogs.com/noteless/p/10592362.html
*请认真填写需求信息,我们会在24小时内与您取得联系。