简析RE中python的exe文件

news2025/7/28 5:07:58

0x00. 前置学习

简单了解

python为什么要打包成exe文件?在日常生活中的应用是因为传输源文件以及源代码给他人是需要配置好一定的环境才能进行编译操作,而打包成exe文件就可以跟电脑软件一样打开就可以运行也可以分享给他人。

而对于ctf比赛来说,是为了给新手增加解题难度,增加游戏的难度。

在反编译前,先了解几种常见的python文件格式:

.py: 源代码文件,可以用文本编辑器查看和编辑;

.pyc: 源代码py文件编译后生成的二进制文件,无法用文本编辑器进行编辑,由python的虚拟机来执行,pyc文件的内容跟python版本相关;

.pyo: 源代码py文件优化编译后生成的二进制文件,无法用文本编辑器进行编辑,Python3.5之后,不再使用.pyo文件名,而是使用类似"xxx.opt-n.pyc的文件名;

.pyd: python的动态链接库(dll),允许程序共享执行特殊任务所必需的代码和其他资源;

.pyz: zipapp打包文件(类似于pyinstaller打包成exe文件)

0x01.PyInstaller

这里主要利用了工具有pyinstxtractor.py,还有在线转换工具(http://tools.bugscaner.com/decompyle/)把pyc转为py。

步骤:使用pyinstxtractor.py工具可以将pyinstaller
生成的exe文件解包成pyc文件,将下载的pyinstxtractor.py文件拷到exe相同的目录,执行命令:

python pyinstxtractor.py checkme.exe(文件名)

执行结果将生成"checkme(文件名).exe _extracted"的文件夹

需要的工具:

这里主要利用了工具有pyinstxtractor.py,还有在线转换工具(http://tools.bugscaner.com/decompyle/)把pyc转为py。

步骤:使用pyinstxtractor.py工具可以将pyinstaller
生成的exe文件解包成pyc文件,将下载的pyinstxtractor.py文件拷到exe相同的目录,执行命令:

python pyinstxtractor.py checkme.exe(文件名)

执行结果将生成"checkme(文件名).exe _extracted"的文件夹

image

在生成的文件夹中找到在根目录下,包括checkme二进制文件(对应原来checkme.py)

image

我们将checkme 与strust文件用010edit(winhex也可)打开,对比,发现pyc文件缺少前12个字节,补充上另存为checkme.pyc

image

因为pyc是二进制文件,无法直接查看和编译,需要转换成py文件。可以使用在线的工具:http://tools.bugscaner.com/decompyle/

PyInstaller的原理

1.PyInstaller工具可以把python解析器和脚本打包成一个可执行的文件,并不是编译成真正的机器码,打包成一个可执行文件后运行效率可能会降低,好处就是在使用者的机器上可以不用安装python和你的脚本依赖的库。2.利用PyInstaller对指定的的脚本打包时,会先分析脚本所依赖的其他脚本,然后根据导包路径去查找,把所有相关的脚本收集起来,包括Python解析器,然后根据你的命令参数可分别生成文件夹,或者打包成一个可执行文件。3.无论是生成的文件夹里的可执行文件或者只打包成一个可执行文件都可以直接运行,前者需要把整个文件夹都给别人。

常用参数:

-F 指只生成一个exe文件,不生成其他dll文件

-w 不弹出交互窗口,如果你想程序运行的时候,与程序进行交互,则不加该参数

-i 设定程序图标 ,其后面的xxx.ico文件就是程序小图标

dev.py 要打包的程序,如果你不是在dev.py同一级目录下执行的打包命令,这里得写上dev.py的路径地址

–hidden-import=pandas._libs.tslibs.timedeltas 隐藏相关模块的引用

使用pyinstaller加密打包

现在执行如下命令就能加密打包了。key后面为密钥可以随便输。

pyinstaller.exe -F --key 123456 xxx.py

尝试解包

python pyinstxtractor.py .\main-encrypt.exe
  import imp
[*] Processing .\main-encrypt.exe
[*] Pyinstaller version: 2.1+
[*] Python version: 37
[*] Length of package: 5787283 bytes
[*] Found 63 files in CArchive
[*] Beginning extraction...please standby
[+] Possible entry point: pyiboot01_bootstrap
[+] Possible entry point: main
[*] Found 136 files in PYZ archive
[!] Error: Failed to decompress Crypto, probably encrypted. Extracting as is.
[!] Error: Failed to decompress Crypto.Cipher, probably encrypted. Extracting as is.
[!] Error: Failed to decompress __future__, probably encrypted. Extracting as is.
[!] Error: Failed to decompress _compat_pickle, probably encrypted. Extracting as is.
[!] Error: Failed to decompress argparse, probably encrypted. Extracting as is.
[!] Error: Failed to decompress ast, probably encrypted. Extracting as is.
[!] Error: Failed to decompress base64, probably encrypted. Extracting as is.
[!] Error: Failed to decompress bdb, probably encrypted. Extracting as is.
[!] Error: Failed to decompress bisect, probably encrypted. Extracting as is.
[!] Error: Failed to decompress bz2, probably encrypted. Extracting as is.
[!] Error: Failed to decompress calendar, probably encrypted. Extracting as is.
[!] Error: Failed to decompress cmd, probably encrypted. Extracting as is.
[!] Error: Failed to decompress code, probably encrypted. Extracting as is.
[!] Error: Failed to decompress codeop, probably encrypted. Extracting as is.

尝试解包无果,看来是无了。

那个Base_Library.zip里面都是库文件的pyc,然后我们在pyinstaller库中找到archieve这么一个文件夹,里面有一个pyz_crypto.py文件,是对pyz文件的加密代码。
image

源码法解包

此方法参照 github上的文章,会在文章末尾放上出处。

因为此工具是开源的,我们已经知道源码,应该就可以尝试编写解密脚本,我们可以通过archive.pyc文件得到加密过程,crypto_key文件得到具体key参数。这个时候就只需要按照加密的方式进行解密就可以了,加密部分为Cipher脚本来源于archive.pyc的反编译)

import tinyaes
import zlib
 
CRYPT_BLOCK_SIZE = 16
 
key = bytes('MySup3rS3cr3tK3y', 'utf-8')
 
inf = open('baby_core.pyc.encrypted', 'rb') # 打开加密文件
outf = open('baby_core.pyc', 'wb') # 输出文件
 
iv = inf.read(CRYPT_BLOCK_SIZE)
 
cipher = tinyaes.AES(key, iv)
 
#主程序
plaintext = zlib.decompress(cipher.CTR_xcrypt_buffer(inf.read()))
 
outf.write(b'\x55\x0d\x00\x00\0\0\0\0\0\0\0\0\0\0\0\0') #补pyc文件头
 
outf.write(plaintext)
 
inf.close()
outf.close()

0x02 实战中应用

1.简单应用:

CTFshow内部赛:来一个python

我们经过上边的步骤之后,得到了反编译后的python文件:

#!/usr/bin/env python
# visit https://tool.lu/pyc/ for more information
# Version: Python 3.6


def  58encode(tmp = None):
    tmp = list(map(ord, tmp))
    temp = tmp[0]
    base58 = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz'
    for i in range(len(tmp) - 1):
        temp = temp * 256 + tmp[i + 1]
    
    tmp = []
    while None:
        temp = temp // 58
        if temp == 0:
            break
        temp = ''
        for i in tmp:
            temp += base58[i]
        
    tmp = []
    for i in range(len(temp)):
        tmp.append(chr(ord(temp[i]) ^ i))
    
    check = [
        'A',
        '5',
        'q',
        'O',
        'g',
        'q',
        'd',
        '%7f',
        '[',
        '%7f',
        's',
        '{',
        'G',
        'A',
        'x',
        '`',
        'D',
        '@',
        'K',
        'c',
        '-',
        'c',
        ' ',
        'G',
        '+',
        '+',
        '|',
        'x',
        '}',
        'J',
        'h',
        '\\',
        'l']
    if tmp == check:
        return 1

flag = input('%e8%be%93%e5%85%a5flag%ef%bc%9a')
if 58encode(flag):
    print('you win')
else:
    print('try again')

这个程序就是把flag进行base58编码再作个异或,然后与check比较,所以将check异或后再base58解码即可

check = ['A','5','q','O','g','q','d','\x7f','[','\x7f','s','{','G','A','x','`','D','@','K','c','-','c',' ','G','+','+','|','x','}','J','h','\\','l']
a = ''
for i in range(len(check)):
    a+=chr(ord(check[i])^i)
 
print(a)

这里输出a后再base58解码即可

image

结果为:

ctfshow{zhe_bu_shi_flag}

2.结合其他算法的应用

sdpc杯,茶马古道

这个题是利用了TXTEA加密算法,和这个一起的结合起来出的题。

tea简介

TEA算法由剑桥大学计算机实验室的David Wheeler和Roger
Needham于1994年发明。它是一种分组密码算法,其明文密文块为64比特,密钥长度为128比特。TEA算法利用不断增加的Delta(黄金分割率)值作为变化,使得每轮的加密是不同,该加密算法的迭代次数可以改变,建议的迭代次数为32轮。QQ使用此加密技术,加密轮数为16轮。
Tea算法是一种分组加密算法,以原文以8字节(64bite)为一组,密钥16字节(128bite)为一组,(char为1字节,int为4字节,double为8字节),该算法加密轮次可变,建议为32轮。(最低为16轮)
Tea算法的特征是存在0x9e3779b9.

#include <stdint.h>

void encrypt (uint32_t* v, uint32_t* k) {
    uint32_t v0=v[0], v1=v[1], sum=0, i;
    uint32_t delta=0x9e3779b9;
    uint32_t k0=k[0], k1=k[1], k2=k[2], k3=k[3];
    for (i=0; i < 16; i++) {
        sum += delta;
        v0 += ((v1<<4) + k0) ^ (v1 + sum) ^ ((v1>>5) + k1);
        v1 += ((v0<<4) + k2) ^ (v0 + sum) ^ ((v0>>5) + k3);
    }
    v[0]=v0; v[1]=v1;
}

上述是加密过程

解密脚本为:

void decrypt (uint32_t* v, uint32_t* k) {
    uint32_t v0=v[0], v1=v[1], i;  /* set up */
    uint32_t delta=0x9e3779b9;
    uint32_t sum = delta << 4;
    uint32_t k0=k[0], k1=k[1], k2=k[2], k3=k[3];
    for (i=0; i<16; i++) {
        v1 -= ((v0<<4) + k2) ^ (v0 + sum) ^ ((v0>>5) + k3);
        v0 -= ((v1<<4) + k0) ^ (v1 + sum) ^ ((v1>>5) + k1);
        sum -= delta;
    }
    v[0]=v0; v[1]=v1;
}
解题

拿到题,咱们还是进行上边的操作,那这个EXE文件变成python文件,

源码如下:

# uncompyle6 version 3.8.0
# Python bytecode 3.8.0 (3413)
# Decompiled from: Python 3.9.2 (default, Feb 28 2021, 17:03:44) 
# [GCC 10.2.1 20210110]
# Embedded file name: easyre.py
# Size of source mod 2**32: 227 bytes
from ctypes import *
import binascii

def encrypt(v, k):
    v0, v1 = c_uint32(v[0]), c_uint32(v[1])
    delta = 2654435769
    k0, k1, k2, k3 = (k[0], k[1], k[2], k[3])
    total = c_uint32(0)
    for i in range(32):
        total.value += delta
        v0.value += total.value ^ (v1.value << 4) + k0 ^ v1.value + total.value ^ (v1.value >> 5) + k1
        v1.value += total.value ^ (v0.value << 4) + k2 ^ v0.value + total.value ^ (v0.value >> 5) + k3
    else:
        return (
         v0.value, v1.value)


print('这是一个flag校验文件^_^')
xx = input('请输入你的flag:')
vvalue = [212553138, 1725195397, 218496566, 3614246156, 254733149, 2117214528]
while True:
    if len(xx) != 24:
        print('flag错误')
        break
    comppare = []
    for i in range(0, 24, 8):
        value = []
        xxx = xx[i:i + 8]
        xxx1 = xxx[0:4].encode()
        xxx2 = xxx[4:].encode()
        hexvalue1 = binascii.b2a_hex(xxx1).decode()
        hexvalue2 = binascii.b2a_hex(xxx2).decode()
        value.append(int(hexvalue1, 16))
        value.append(int(hexvalue2, 16))
        Arglist = [1263159624, 1330531660, 1397903696, 1465275732]
        res = encrypt(value, Arglist)
        comppare.append(res[0])
        comppare.append(res[1])

    if comppare == vvalue:
        print('flag正确')
        break
    else:
        print('flag错误')
        break

上边的运算逻辑是进行一个一次变种tea然后下边就是简单的运算,直接开逆。

解题脚本如下:

from calendar import c
from ctypes import *
import libnum

def decrypt(v, k):
    v0, v1 = c_uint32(v[0]), c_uint32(v[1])
    delta = 2654435769
    k0, k1, k2, k3 = (k[0], k[1], k[2], k[3])
    total = c_uint32(delta * 32)
    for i in range(32):
        v1.value -= total.value ^ (v0.value << 4) + k[2] ^ v0.value + total.value ^ (v0.value >> 5) + k[3]
        v0.value -= total.value ^ (v1.value << 4) + k[0] ^ v1.value + total.value ^ (v1.value >> 5) + k[1]
        total.value -= delta
    else:
        return (
         v0.value, v1.value)


if __name__ == '__main__':
    flag=b''
    l=[212553138, 1725195397, 218496566, 3614246156, 254733149, 2117214528]
    for i in range(0,6,2):
        a = [l[i],l[i+1]]
        k = [1263159624, 1330531660, 1397903696, 1465275732]
        res = decrypt(a, k)
        flag += libnum.n2s(res[0])
        flag += libnum.n2s(res[1])
    print(flag)

image

0x03 总结:

关于python打包文件的类型的题目在最近ctf比赛中属于的比较门题型,他可以和其他的加密算法结合进行考察,通过融合其他的算法可以大大增加题目的难度,增加解题的繁琐程度。这一块儿还是非常值得我们进行学习的。

e(0,6,2):
a = [l[i],l[i+1]]
k = [1263159624, 1330531660, 1397903696, 1465275732]
res = decrypt(a, k)
flag += libnum.n2s(res[0])
flag += libnum.n2s(res[1])
print(flag)

网络安全工程师企业级学习路线

这时候你当然需要一份系统性的学习路线

如图片过大被平台压缩导致看不清的话,可以在文末下载(无偿的),大家也可以一起学习交流一下。

一些我收集的网络安全自学入门书籍

一些我白嫖到的不错的视频教程:

上述资料【扫下方二维码】就可以领取了,无偿分享

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/368058.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

(三十三)大白话MySQL运行时多个事务同时执行是什么场景?

到目前为止&#xff0c;我们已经给大家深入讲解了MySQL的buffer pool机制、redo log机制和undo log机制&#xff0c;相信大家现在对我们平时执行一些增删改语句的实现原理&#xff0c;都有了一定较为深入的理解了&#xff01; 因为平时我们执行增删改的时候&#xff0c;无非就…

Python|Leetcode刷题日寄Part04

Python|Leetcode刷题日寄Part0401&#xff1a;环形链表02&#xff1a;跳跃游戏03&#xff1a;括号生成04&#xff1a;二分查找05&#xff1a;打家劫舍06&#xff1a;搜索旋转排序数组07&#xff1a;Z字形变换08&#xff1a;买卖股票的最佳时机Ⅱ09&#xff1a;最后一个单词的长…

国产蓝牙耳机300左右哪个牌子的好?三百左右蓝牙耳机推荐

现在的蓝牙耳机样式越来越五花八门&#xff0c;各种性能也越来越好。特别是国产蓝牙耳机&#xff0c;近几年的发展十分快速。那么&#xff0c;三百左右哪个牌子的国产蓝牙耳机好&#xff1f;接下来&#xff0c;我来给大家推荐几款三百左右的蓝牙耳机&#xff0c;一起来看看吧。…

Java加密算法:base64,MD5加密,对称加密,非对称加密

目录 Java&#xff1a;密码算法 1、base64加密方式 2、jdk原生api实现MD5 3、使用codec依赖实现MD5加密 4、SHA加密 5、MAC算法加密 6、对称加密 7、非对称加密 Java&#xff1a;密码算法 1、base64加密方式 public class demo {//设置编码格式private static final S…

搜索引擎的6个技巧

今天看了一期seo优化的视频&#xff0c;其中就有这么一篇关于百度搜索的几个小技巧&#xff0c;这里整理出来&#xff0c;分享给大家。不是标题党&#xff0c;真的99%的人都不知道这个6个小技巧。 搜索引擎一般都会有一些高级的搜索技巧&#xff0c;掌握这些技巧之后就可以过滤…

spring的启动过程(二) :springMvc的启动过程

在上一篇文章中&#xff0c;我们详解了spring的启动过程&#xff0c;这一篇介绍spring mvc的启动过程&#xff0c;那么spring和spring mvc有什么联系呢。 1.Spring和SpringMVC是父子容器关系。2.Spring整体框架的核心思想是容器&#xff0c;用来管理bean的生命周期&#xff0c;…

CAN总线开发一本全(3) - 微控制器集成的FlexCAN外设

CAN总线开发一本全&#xff08;3&#xff09; - 微控制器集成的FlexCAN外设 苏勇&#xff0c;2023年2月 文章目录CAN总线开发一本全&#xff08;3&#xff09; - 微控制器集成的FlexCAN外设引言硬件外设模块系统概要总线接口单元 - 寄存器清单数据结构 - 消息缓冲区MB初始化过…

taobao.top.oaid.merge( OAID订单合并 )

&#xffe5;开放平台免费API必须用户授权 基于OAID&#xff08;收件人ID&#xff0c; Open Addressee ID)做订单合并&#xff0c;确保相同收件人信息的订单合并到相同组。 公共参数 请求地址: HTTP地址 http://gw.api.taobao.com/router/rest 公共请求参数: 公共响应参数: 请…

win10环境下安装java开发环境安装java

一&#xff1a;环境介绍 安装系统版本&#xff1a;win10 java版本&#xff1a;java SE 17 二&#xff1a;下载Java安装包 官网下载Java安装包&#xff1a;Java Downloads | Oracle 中国 选择需要的Java版本进行下载&#xff0c;如果没有要选择的版本&#xff0c;可以选择最新…

称重传感器差分输入信号隔离转换直流放大变送器0-±10mV/0-±20mV转0-10V/4-20mA

主要特性DIN11 IPO 压力应变桥信号处理系列隔离放大器是一种将差分输入信号隔离放大、转换成按比例输出的直流信号导轨安装变送模块。产品广泛应用在电力、远程监控、仪器仪表、医疗设备、工业自控等行业。此系列模块内部嵌入了一个高效微功率的电源&#xff0c;向输入端和输出…

(二十九)大白话MySQL直接强行把redo log写入磁盘?

上一讲我们给大家说了一下redo log block这个概念&#xff0c;大家现在都知道平时我们执行完增删改之后&#xff0c;要写入磁盘的redo log&#xff0c;其实应该是先进入到redo log block这个数据结构里去的&#xff0c;然后再进入到磁盘文件里&#xff0c;如下图所示。 那么今天…

三、锁相关知识

文章目录锁的分类可重入锁、不可重入锁乐观锁、悲观锁公平锁、非公平锁互斥锁、共享锁深入synchronized类锁、对象锁synchronized的优化synchronized实现原理synchronized的锁升级重量锁底层ObjectMonitor深入ReentrantLockReentrantLock和synchronized的区别AQS概述加锁流程源…

Flink中遇到的问题

目录 1、提交flink 批处理任务时遇到的问题 2、flink定时任务&#xff0c;mysql连接超时问题 3、yarn 增加并行任务数量配置 4、flink checkpoint 恢复失败 5、flink程序在hadoop集群跑了一段时间莫名挂掉 1、提交flink 批处理任务时遇到的问题 问题描述&#xff1a; …

超详细树状数组讲解(+例题:动态求连续区间和)

树状数组的作用&#xff1a;快速的对数列的一段范围求和快速的修改数列的某一个数为什么要使用树状数组&#xff1a;大家从作用中看到快速求和的时候可能会想到为什么不使用前缀和只需要预处理一下就可以在O(1)的时间复杂度下实行对于数列的一段范围的和但是我们可以得到当我们…

记一次服务器入侵事件的应急响应

0x01 事件背景 8月某日&#xff0c;客户官网被黑&#xff0c;需在特定时间内完成整改。为避免客户业务受到影响&#xff0c;实验室相关人员第一时间展开本次攻击事件的应急处理。 0x02 事件分析 网站源码被篡改&#xff0c;攻击者一定获取到了权限&#xff0c;那么接下来的思…

Linux进程1 - 进程的相关概念

目录 1.进程的概念 2.并行和并发 3.PCB&#xff08;进程控制块&#xff09; 4.进程状态 1.进程的概念 程序&#xff1a;二进制文件&#xff0c;占用的磁盘空间进程&#xff1a;启动的程序所有的数据都在内存中需要占用更多的系统资源cpu,物理内存 2.并行和并发 并发----在…

Spring事物和事务的传播机制

事务的定义&#xff1a;将一组操作封装到一个执行单元&#xff0c;要么全部成功&#xff0c;要么全部失败。 一、Spring中事务的实现 Spring中事务的操作分为两类&#xff1a; 1.编程式事务&#xff08;手动写代码操作事务&#xff09; 2.声明式事务&#xff08;利用注解自动…

2023财年Q4业绩继续下滑,ChatGPT能驱动英伟达重回巅峰吗?

近年来&#xff0c;全球科创风口不断变换&#xff0c;虚拟货币、元宇宙等轮番登场&#xff0c;不少企业匆忙上台又很快谢幕&#xff0c;但在此期间&#xff0c;有些企业扮演淘金潮中“卖水人”的角色&#xff0c;却也能够见证历史且屹立不倒。不过&#xff0c;这并不意味着其可…

CSS 美化网页元素【快速掌握知识点】

目录 一、为什么使用CSS 二、字体样式 三、文本样式 color属性 四、排版文本段落 五、文本修饰和垂直对齐 1、文本装饰 2、垂直对齐方式 六、文本阴影 七、超链接伪类 1、语法 2、示例 3、访问时&#xff0c;蓝色&#xff1b;访问后&#xff0c;紫色&#xff1b; …

详解八大排序算法

文章目录前言排序算法插入排序直接插入排序:希尔排序(缩小增量排序)选择排序直接选择排序堆排序交换排序冒泡排序快速排序hoare版本挖坑法前后指针版本快速排序的非递归快速排序总结归并排序归并排序的非递归实现&#xff1a;计数排序排序算法复杂度及稳定性分析总结前言 本篇…