吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 5411|回复: 57
上一主题 下一主题
收起左侧

[原创] 记一次PyInstaller打包exe的python程序逆向

  [复制链接]
跳转到指定楼层
楼主
失神我醉了 发表于 2024-3-21 18:10 回帖奖励
本帖最后由 失神我醉了 于 2024-3-22 14:40 编辑

最近迷上了DOTA2游廊里的一款游戏,但是太肝了,想着能不能用脚本帮我玩,于是去gayhub一顿搜,还真被我找到了,但是要激活码。。。还是你们会玩,专薅同行羊毛。。


看着这license,我想着python写的,应该好搞吧。。。但是网上有用信息真少,此文记录一下遇到的坑。
exe文件,首先用exeinfoPE 查壳

可以看到是pyinstaller打包的,无壳。

破解思路
1. 直接动态调试exe文件,patch激活逻辑。
2. 既然python写的,直接反编译成源码。

关于方式1,我沉浸在python虚拟机里无法自拔,没有找到真正的程序入口。。。(太菜了),用x64dbg调试,尝试过在按钮控件下断点(没啥用),希望有经验大佬分享一下。

代码还原
本文主要讨论的是方式2。
根据网上搜到的经验,可以用pyinstxtractor.py 解包脚本进行解包,这里最好下载和源码相同的python环境,不然会出问题。
解包后,接下来就是还原源代码,这里有些坑,根据程序执行流程,我们找到与license激活的pyc文件进行源代码还原。
因为python是3.10,根据公开资料,可以找到gayhub上的pycdc项目进行源代码还原,但是如果你去试,会发现还原不全。
依照pycdc的issue,主要原因是一些opcodes支持不全。


但是pycdas 完全支持,也就是说可以完美翻译为字节码。

所以用pycdas直接将pyc翻译成字节码。字节码当然可以直接分析的,对于大佬来说应该不难,但对于我这种小白就很痛苦,那有没有优雅的做法?
还真被我找到了,我直接将字节码喂给chatgpt,让他帮我还原为源代码。就这么简单,惊不惊喜。。。感叹gpt是真的牛逼
import json
import os
import sys
import machineid
import requests
from dateutil.parser import parse
from controller import ConfigManager
from controller.filelog import logger
from controller.global_variables import config, path, path_rau_ma

license_key = ''

try:
    license_key = config.read_config('AutoConfig', 'license')
except:
    pass

if not license_key:
    config.save_config('AutoConfig', 'license', '2024')

days_left = 0
machine_fingerprint = machineid.id()

def activate_license(license_key):
    try:
        validation = requests.get(f'https://xxxx.net/api/license/{license_key}').json()
        # License not found
        if not validation:
            logger.info('License not found')
            days_left = 0
            return False, days_left

        for key in validation:
            if key['detail'] == 'License not found':
                logger.info('License not found')
                days_left = 0
                return False, days_left

        datenow = parse(validation['datenow'])
        expire_date = parse(validation['expire_date'])

        days_left = (expire_date - datenow).days
        global days_left
        if days_left < 0:
            days_left = 0
            return False, days_left

        for key in validation['machines']:
            if key['machine_uuid'] == machine_fingerprint:
                global days_left
                days_left = True, days_left
                return True, days_left

        return False, days_left
    except Exception as e:
        return False, days_left

if __name__ == '__main__':
    status, msg = activate_license(license_key)
    print(status, msg)

我还帮你们问问他为什么这么牛逼。


还原很完美,理论用这个方法可以还原所有源代码。但是没必要。各位可以去试试调戏一下chatgpt,我prompt不太行。。
顺便让chatgpt帮我生成validation 的json响应,方便后面伪造响应。
知道了请求,知道了响应格式,按理说很简单,伪造响应就行了,但这里面还有一些坑。

主要就是requests的https抓包问题
抓包
工具使用:Proxifier,Fiddler
因为requests自己实现了http(s)协议的封装,没有用windows的WinInet库,只靠fiddler抓不到包,得用proxifier将流量导入fiddler
proxifier要注意两点
1. 设置[Profile] — [Name Resolution] — 勾选 [Resolve hostnames through proxy],通过代{过}{滤}理解析域名
2. 在Proxifier中添加127.0.0.1:8888的https代{过}{滤}理服务器,并设置rule让改exe走该代{过}{滤}理。

但是仅仅这样还不行,我们知道要想fiddler抓取https流量,是需要导入证书的,基于windows的,我们可以直接用fiddler安装,基于浏览器的,我们可以将证书导入浏览器
那么requests呢,是的,他内置了ssl证书,不走系统的。一般是记录在certifi文件夹下的cacert.pem文件里。
到这一步,我能搜到的网上的信息是是让我们改源代码,我啪啪一巴掌,能改源代码,我他妈还抓包啊。
当然主要还是我经验不足,后来想了想,都知道证书在哪儿了,我往里面添加fiddler证书不就可以了,将fiddler的cer转为pem,然后复制粘贴到cacert.pem,成功抓包

然后用fiddler的AutoResponder自动响应请求,成功欺骗。



但是每次运行程序都要运行proxifier和fiddler,有点ugly。。
最后,欢迎各位大佬分享一下pyinstaller打包程序的逆向想法。
Reference
pyinstxtractor
pycdc

Fiddler抓包指南:结合Proxifier工具

免费评分

参与人数 10吾爱币 +16 热心值 +9 收起 理由
ABCD00 + 1 我很赞同!
TCQZ + 1 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
Hmily + 7 + 1 欢迎分析讨论交流,吾爱破解论坛有你更精彩!
yiwai2012 + 1 + 1 有个东西叫 sunny
wiken2024 + 1 + 1 用心讨论,共获提升!
superTian + 1 + 1 用心讨论,共获提升!
idying + 1 + 1 用心讨论,共获提升!
qweasdzxc52 + 1 + 1 我很赞同!
素颜朝天 + 1 + 1 我很赞同!
kuiur0810 + 1 + 1 用心讨论,共获提升!

查看全部评分

本帖被以下淘专辑推荐:

  • · 好帖|主题: 549, 订阅: 87

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

推荐
 楼主| 失神我醉了 发表于 2024-7-31 23:36 |楼主
时崎-狂三 发表于 2024-7-22 21:33
请问你的这一步

是如何进行的?将原包解包以后再添加证书以后,如何运行程序?如果可以回答将不胜感激。

解包只是为了分析程序逻辑,抓包是在原exe程序基础上的,pyinstall打包的exe本质上相当于压缩文件,程序运行后,项目用到的文件会解压到临时目录,一般为"C:\Users\<username>\AppData\Local\Temp\_MEIxxxxxx"
当然解包后的pyc文件其实也可以用python运行的。

免费评分

参与人数 1吾爱币 +2 热心值 +1 收起 理由
小朋友呢 + 2 + 1 我很赞同!

查看全部评分

推荐
Hou 发表于 2024-3-22 16:34
本帖最后由 Hou 于 2024-3-22 16:35 编辑

gpt这思路真不错,我前几天也卡在高版本pyc的问题 https://www.52pojie.cn/thread-1902049-1-1.html

另外pyc文件可以直接运行的,把核心位置的的字节码交给gpt译成py,把库文件补全然后重新用pyinstaller打包一下就完美了

但是我感觉只适用代码量较少的pyc,量多gpt估计就....
沙发
qsfz 发表于 2024-3-21 22:06
3#
敬而远之 发表于 2024-3-21 22:26
好在我用nuitka
4#
hqt 发表于 2024-3-22 01:58
有点没看懂 requests.get api都出了
为什么不直接删掉直接return True,9999999
5#
LXGZJ237 发表于 2024-3-22 07:22
hqt 发表于 2024-3-22 01:58
有点没看懂 requests.get api都出了
为什么不直接删掉直接return True,9999999

可能是不想修改代码,所以采用抓包的方式?
6#
winxpnt 发表于 2024-3-22 08:02
采用抓包的方式不错的
7#
mstheholy 发表于 2024-3-22 08:54
现在也就pyinstaller好逆向,其他打包方式试了下很难
8#
feng710 发表于 2024-3-22 09:00
ChatGPT太好用了
9#
cqcw 发表于 2024-3-22 09:01
好的。。。学习中,,,多学习。。
10#
space218 发表于 2024-3-22 09:10
行了,抽空我自己打包逆一下试试。
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-11-21 15:25

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

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