找回密码
 会员注册
查看: 35|回复: 0

逆向-Python反编译保姆级教程

[复制链接]

5

主题

0

回帖

16

积分

新手上路

积分
16
发表于 2024-9-13 14:36:53 | 显示全部楼层 |阅读模式
【出现的形式】出现的话往往是python编写,然后编译好的exe或者elf文件,我们需要做的就是找到源码,分析逻辑,进行解密【生成pyc文件】使用的工具就是pyinstxtractorpyinstxtractor-2023.08.zip其中的py文件可以实现将exe文件或者elf文件,打包为使用方法(以snake.elf这个题目为例)解压,将目标放入文件夹在这里打开cmd窗口,输入指令pythonpyinstxtractor.pysnake呈现如下就是成功,发现文件中多了一个_extracted文件夹,打开,去里面找到"目标文件名.pyc"的文件(往往与struct.pyc一并出现,都有用)注:进行完上述操作之后,可能会遇到文件头结构需要补充修改的情况,就是讲sanke和struct两个pyc文件放入010查看sanke的文件头是否与struct相同,不同的话要把后者的内容补充上去(目前做题还没遇到过这样的情况,可能现在这个工具比较好用了)再进行下一步操作。【生成py文件,实现反编译】这一步实现pyc文件转化为py源码(一)使用在线反编译网站python反编译-在线工具这个网站可以实现的版本较多,但是有使用限制在线pyc,pyo,python,py文件反编译,目前支持python1.5到3.6版本的反编译-在线工具这个网站使用方便但是很久没更新了一般直接将上一步生成的pyc文件放入其中就可以生成py文件(二)pycdc工具进行反编译其实在线工具就是利用这个玩意进行了python的反编译,之所以我们会用到这个工具,因为做题遇到了一个使用高版本python编写的exe,使用在线工具是无法完美反编译出来的。其实使用这个pycdc的话也会报错,但是由于我们在本地使用的脚本,我们就可以修改文件中的代码,实现绕过一些报错,大致反编译出来源码进行解密(下面第三点讲到)其次就是,到后期,在没有联网的比赛中,这个工具就显得尤为重要了,我们接下来进行pycdc的几种安装方式的教程。Windows与Linux系统安装的大致思路相似github上下载压缩包/文件-cmake进行编译生成可执行文件-成功运行·Linux系统(利用wsl,方便进行源码修改)参考了上面提到的题目的题解,认识到了wsl这个伟大的功能(在windows的命令框中实现我们的linux操作)这篇文章讲的十分详尽了,本文就不再过多赘述了,直接进入我们安装pycdc的整正题[安利]WSLLinux子系统,真香!完整实操-知乎(在linux上和下面的操作是一样的)安装完毕wsl之后,打开cmd输入wsl切换系统{先熟悉几个指令(萌新可以看看)}cd地址跳转功能,我们输入cd~之后会跳到最干净的地址ls查看文件目录我们发现就是我们的这几个目录{正式安装}(1)准备工作:安装gcc,cmake,bulid包sudoapt-getupdatesudoapt-getinstallgccsudoaptinstallcmakesudoaptinstallbuild-essential(第一次装的时候就是因为这个包没装上,cmake一直无法编译)(2)git拉取文件gitclonehttps://github.com/zrax/pycdc.git这样一来,再输入ls之后会像我上面展示的一样出现pycdc这个文件夹,当然我们还要去编译他(3)地址切换到pycdc,进行编译cdpycdc(4)编译过程cmake.makesudomakeinstall看到安装到bin目录下的两个文件就证明我们成功了,可以正常使用了,是不是非常方便{使用方法}进入存放pyc文件的文件夹,打开终端进入wsl输入命令pycdc./rc4.pyc顺利反编译当然你还可以选择直接生成py文件,命令pycdc./rc4.pyc>>../newrc4.py就会在上一层目录中生成这个py文件和在窗口打开的并无差异·Windows系统windows的操作可能比较繁琐,cmake的安装可能需要一定功夫,这里也给大家讲讲{前期准备}首先就是需要的工具,vscode上的一些插件提前下载好然后去下载一个cmake和MinGW,按照这个两篇文章来就好CMake安装教程_cmake下载安装教程-CSDN博客Mingw快捷安装教程并完美解决出现的下载错误:Thefilehasbeendownloadedincorrectly-CSDN博客{正式安装}(1)官网下载pycdc压缩包文件GitHub-zrax/pycdc:C++pythonbytecodedisassembleranddecompiler(2)解压的文件夹放入vscode中ctrlshiftP选择生成下一步选择gcc最后发现出现了bulid文件夹,控制台也显示编译完成,在我们的文件夹的位置就出现了编译好的可执行文件{使用方法}将上面的两个exe放入我们的pyc文件夹中,在终端打开输入命令./pycdcrc4.pyc(三)应用在题目中,随意修改编译我们的脚本源码像上面这个图片中,我们并没有生成完整的反编译源码,原因是编写题目的python版本太高,pycdc在识别的时候出现了问题于是就没有继续进行编译,导致大量的信息丢失(当然我觉得pycdc的作者也会在后续进行高版本更新,无论是在线还是本地反编译都会没有问题)那如果确实出现了这样的错误,我们有两种解决办法(1)使用pycdas,生成汇编代码,进行阅读(2)查看报错,让进入源码进行适当修改,编译出新的pycdc生成不报错的反编译。这里只讲讲第二种方法。使用wls的话,我们打开vscode选择右边的远程资源管理器,打开我们的pycdc文件夹进入这个ASTree.cpp的文件,copy刚才反汇编的报错Unsupportedopcode:JUMP_BACKWARD在vscode中进行检索找到了这里fprintf(stderr,"Unsupportedopcode:%s\n",Pyc::OpcodeName(opcode&0xFF));cleanBuild=false;//returnnewASTNodeList(defblock->nodes());这里的return语句就是我们没找到反编译的字节之后,我就不再继续反编译return,我们注释掉这条语句,重新按照(二)中的过程进行编译,这样子我们的pycdc就是不会再return的工具了#SourceGeneratedwithDecompyle++#File:rc4.pyc(Python3.11)importtimea=input()defswap_uchar(x,y):return(y,x)defrc4_ksa(key):sbox=list(range(256))j=0foriinrange(256):j=(j+sbox[i]+key[i%len(key)])%256(sbox[i],sbox[j])=swap_uchar(sbox[i],sbox[j])returnsboxdefrc4_prga(sbox,data_length):i=0j=0key_stream=bytearray()forkinrange(data_length):i=(i+1)%256j=(j+sbox[i])%256(sbox[i],sbox[j])=swap_uchar(sbox[i],sbox[j])t=(sbox[i]+sbox[j])%256key_stream.append(sbox[t])returnkey_streamdefrc4_crypt(data,key_stream):result=bytearray()foriinrange(len(data)):result.append(data[i]^key_stream[i])returnresultdeftea(v,k):delta=0x9E3779B9mask=0xFFFFFFFFrounds=32v1=v[1]v0=v[0]sum=delta*rounds&maskforiinrange(rounds):v1-=(v0<< 4) + k[2] ^ v0 + sum ^ (v0 >>5)+k[3]v1&=maskv0-=(v1<< 4) + k[0] ^ v1 + sum ^ (v1 >>5)+k[1]v0&=masksum-=deltasum&=maskreturn[v0,v1]defmain():key='abcdefghijklmnopqrstuvwxyz'key3=[19088743,0x89ABCDEF,0xFEDCBA98,1985229328]data=bytearray(str(a),'utf-8')sbox=rc4_ksa(bytearray(key,'utf-8'))key_stream=rc4_prga(sbox[:],len(data))encrypted_data=rc4_crypt(data,key_stream)b=(lambda.0:forxin.0:format(x,'02X')None)(encrypted_data())key_list=[47,138,127,57,117,188,51,143,17,22]encrypted_values=range(0,len(b),16)()original_data=[]fori,encrypted_valueinenumerate(encrypted_values):encrypted_value=encrypted_value.ljust(16,'0')key2=(key_list[i]>>4)+((key_list[i]&15)<< 4) original_data.append([ int(encrypted_value[:8], 16) ^ key2, int(encrypted_value[8:], 16) ^ key2]) decrypted_values = original_data() check = (lambda .0: for value in .0:[ hex(value[0])[2:] + ' ' + hex(value[1])[2:] + ' ' ])(decrypted_values()).upper().strip() if check == '2E895417 9EDAC23D E4A8A87A B63C2690 E6423D70 F7E9C8AD': print('yea!') time.sleep(10) quit() return None ''.join('nooooooooooooooooooooooooooooooooooooo') time.sleep(10) quit() return None if __name__ == '__main__': main()return None 题解就写在别的文章中了,题目附件放到这里了 RC4.zip 【总结】 通过这次的学习,深入了解了python的反编译过程,学习到了wsl这个方便的功能,也简单学习了linux上的一些操作。 参考文章: Python 反编译:pycdc工具的使用-CSDN博客 [Linux] 使用 Decompile++ (pycdc) 反組譯 pyc 檔案 | EPH 的程式日記 [安利] WSL Linux 子系统,真香!完整实操 - 知乎
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 会员注册

本版积分规则

QQ|手机版|心飞设计-版权所有:微度网络信息技术服务中心 ( 鲁ICP备17032091号-12 )|网站地图

GMT+8, 2024-12-25 13:43 , Processed in 0.299316 second(s), 25 queries .

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表