当前位置:   article > 正文

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

pyc在线反编译

【出现的形式】

出现的话往往是python编写,然后编译好的exe或者elf文件,我们需要做的就是找到源码,分析逻辑,进行解密

【生成pyc文件】

使用的工具就是pyinstxtractor

pyinstxtractor-2023.08.zip

其中的py文件可以实现将exe文件或者elf文件,打包为

使用方法(以snake.elf这个题目为例)

解压,将目标放入文件夹

在这里打开cmd窗口 ,输入指令python pyinstxtractor.py snake

呈现如下就是成功,发现文件中多了一个_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的整正题

[安利] WSL Linux 子系统,真香!完整实操 - 知乎

(在linux上和下面的操作是一样的)

安装完毕wsl之后,打开cmd输入wsl切换系统

{先熟悉几个指令(萌新可以看看)}

cd

地址跳转功能,我们输入cd ~之后会跳到最干净的地址

ls

查看文件目录

我们发现就是我们的这几个目录

{正式安装}
(1)准备工作:安装gcc,cmake,bulid包

sudo apt-get update

sudo apt-get install gcc

sudo apt install cmake

sudo apt install build-essential(第一次装的时候就是因为这个包没装上,cmake一直无法编译)

(2)git拉取文件

git clone https://github.com/zrax/pycdc.git

这样一来,再输入ls之后会像我上面展示的一样出现pycdc这个文件夹,当然我们还要去编译他

(3)地址切换到pycdc,进行编译

cd pycdc

(4)编译过程

cmake .

make

sudo make install

看到安装到bin目录下的两个文件就证明我们成功了,可以正常使用了,是不是非常方便

{使用方法}

进入存放pyc文件的文件夹,打开终端进入wsl

输入命令pycdc ./rc4.pyc

顺利反编译

当然你还可以选择直接生成py文件,命令

pycdc ./rc4.pyc >> ../newrc4.py就会在上一层目录中生成这个py文件

和在窗口打开的并无差异

·Windows系统

windows的操作可能比较繁琐,cmake的安装可能需要一定功夫,这里也给大家讲讲

{前期准备}

首先就是需要的工具,vscode上的一些插件提前下载好

然后去下载一个cmake和MinGW,按照这个两篇文章来就好

CMake 安装教程_cmake下载安装教程-CSDN博客

Mingw快捷安装教程 并完美解决出现的下载错误:The file has been downloaded incorrectly-CSDN博客

{正式安装}

(1)官网下载pycdc压缩包文件

GitHub - zrax/pycdc: C++ python bytecode disassembler and decompiler

(2)解压的文件夹放入vscode中

ctrl shift P 选择生成

下一步选择gcc

最后发现出现了bulid文件夹,控制台也显示编译完成,在我们的文件夹的位置就出现了编译好的可执行文件

{使用方法}

将上面的两个exe放入我们的pyc文件夹中,在终端打开

输入命令 ./pycdc rc4.pyc

(三)应用在题目中,随意修改编译我们的脚本源码

像上面这个图片中,我们并没有生成完整的反编译源码,原因是编写题目的python版本太高,pycdc在识别的时候出现了问题于是就没有继续进行编译,导致大量的信息丢失(当然我觉得pycdc的作者也会在后续进行高版本更新,无论是在线还是本地反编译都会没有问题)

那如果确实出现了这样的错误,我们有两种解决办法

(1)使用pycdas,生成汇编代码,进行阅读

(2)查看报错,让进入源码进行适当修改,编译出新的pycdc生成不报错的反编译。

这里只讲讲第二种方法。

使用wls的话,我们打开vscode

选择右边的远程资源管理器,打开我们的pycdc文件夹

进入这个ASTree.cpp的文件,copy刚才反汇编的报错

Unsupported opcode: JUMP_BACKWARD在vscode中进行检索

找到了这里

  1. fprintf(stderr, "Unsupported opcode: %s\n", Pyc::OpcodeName(opcode & 0xFF));
  2. cleanBuild = false;
  3. //return new ASTNodeList(defblock->nodes());

这里的return语句就是我们没找到反编译的字节之后,我就不再继续反编译return,我们注释掉这条语句,重新按照(二)中的过程进行编译,这样子我们的pycdc就是不会再return的工具了

  1. # Source Generated with Decompyle++
  2. # File: rc4.pyc (Python 3.11)
  3. import time
  4. a = input()
  5. def swap_uchar(x, y):
  6. return (y, x)
  7. def rc4_ksa(key):
  8. sbox = list(range(256))
  9. j = 0
  10. for i in range(256):
  11. j = (j + sbox[i] + key[i % len(key)]) % 256
  12. (sbox[i], sbox[j]) = swap_uchar(sbox[i], sbox[j])
  13. return sbox
  14. def rc4_prga(sbox, data_length):
  15. i = 0
  16. j = 0
  17. key_stream = bytearray()
  18. for k in range(data_length):
  19. i = (i + 1) % 256
  20. j = (j + sbox[i]) % 256
  21. (sbox[i], sbox[j]) = swap_uchar(sbox[i], sbox[j])
  22. t = (sbox[i] + sbox[j]) % 256
  23. key_stream.append(sbox[t])
  24. return key_stream
  25. def rc4_crypt(data, key_stream):
  26. result = bytearray()
  27. for i in range(len(data)):
  28. result.append(data[i] ^ key_stream[i])
  29. return result
  30. def tea(v, k):
  31. delta = 0x9E3779B9
  32. mask = 0xFFFFFFFF
  33. rounds = 32
  34. v1 = v[1]
  35. v0 = v[0]
  36. sum = delta * rounds & mask
  37. for i in range(rounds):
  38. v1 -= (v0 << 4) + k[2] ^ v0 + sum ^ (v0 >> 5) + k[3]
  39. v1 &= mask
  40. v0 -= (v1 << 4) + k[0] ^ v1 + sum ^ (v1 >> 5) + k[1]
  41. v0 &= mask
  42. sum -= delta
  43. sum &= mask
  44. return [
  45. v0,
  46. v1]
  47. def main():
  48. key = 'abcdefghijklmnopqrstuvwxyz'
  49. key3 = [
  50. 19088743,
  51. 0x89ABCDEF,
  52. 0xFEDCBA98,
  53. 1985229328]
  54. data = bytearray(str(a), 'utf-8')
  55. sbox = rc4_ksa(bytearray(key, 'utf-8'))
  56. key_stream = rc4_prga(sbox[:], len(data))
  57. encrypted_data = rc4_crypt(data, key_stream)
  58. b = (lambda .0: for x in .0:
  59. format(x, '02X')None)(encrypted_data())
  60. key_list = [
  61. 47,
  62. 138,
  63. 127,
  64. 57,
  65. 117,
  66. 188,
  67. 51,
  68. 143,
  69. 17,
  70. 22]
  71. encrypted_values = range(0, len(b), 16)()
  72. original_data = []
  73. for i, encrypted_value in enumerate(encrypted_values):
  74. encrypted_value = encrypted_value.ljust(16, '0')
  75. key2 = (key_list[i] >> 4) + ((key_list[i] & 15) << 4)
  76. original_data.append([
  77. int(encrypted_value[:8], 16) ^ key2,
  78. int(encrypted_value[8:], 16) ^ key2])
  79. decrypted_values = original_data()
  80. check = (lambda .0: for value in .0:
  81. [ hex(value[0])[2:] + ' ' + hex(value[1])[2:] + ' ' ])(decrypted_values()).upper().strip()
  82. if check == '2E895417 9EDAC23D E4A8A87A B63C2690 E6423D70 F7E9C8AD':
  83. print('yea!')
  84. time.sleep(10)
  85. quit()
  86. return None
  87. ''.join('nooooooooooooooooooooooooooooooooooooo')
  88. time.sleep(10)
  89. quit()
  90. return None
  91. if __name__ == '__main__':
  92. main()
  93. return None

题解就写在别的文章中了,题目附件放到这里了

RC4.zip

【总结】

通过这次的学习,深入了解了python的反编译过程,学习到了wsl这个方便的功能,也简单学习了linux上的一些操作。

参考文章:

Python 反编译:pycdc工具的使用-CSDN博客

[Linux] 使用 Decompile++ (pycdc) 反組譯 pyc 檔案 | EPH 的程式日記

[安利] WSL Linux 子系统,真香!完整实操 - 知乎

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/你好赵伟/article/detail/554844
推荐阅读
相关标签
  

闽ICP备14008679号