Python软件逆向-SE工具箱

原因

今天在网上看见以个SE工具箱,号称可以通过某人的qq、手机号或者微博进行反查信息,只需知道其中一个便可查询其他信息。我一看,这不就是一社工库吗,于是便想下载来看一下
image

结果发现这软件竟然收费,而且是用python写的
image

破解过程

解包

对exe进行解包用的是pyinstxtractor
下载地址:https://github.com/extremecoders-re/pyinstxtractor/releases/
下载完成后将压缩包进行解压,得到了一下文件
image
然后将要解包的exe放进这个目录
image
打开powershell进入当前目录输入

1
python .\pyinstxtractor.py <要解包程序的地址>

然后执行
image
这时在当前目录下便出现了一个新的文件夹
image

反编译

进入该文件夹,找到与exe文件同名的pyc文件,尝试使用uncompyle6进行反编译

1
2
pip install uncompyle6
uncompyle6 .\SE工具箱.pyc >so.py

这里的so.py是将反编译的结果保存至so.py这一文件
image
但是发现使用uncompyle6反编译失败,于是果断选择在网上寻找在线反编译工具

https://tool.lu/pyc/

反编译的到如下代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
#!/usr/bin/env python
# visit https://tool.lu/pyc/ for more information
# Version: Python 3.9

import threading
import win32api
import pyDes
from binascii import b2a_hex, a2b_hex
import base64
import requests
import re
import os
import random
import time
import PySimpleGUI as Sg
Des_Key = '12345678'
Des_IV = '00000000'
TYPE = 'DB'

class Register:

def __init__(self, TYPE):
self.TYPE = TYPE
self.Des_Key = Des_Key
self.Des_IV = Des_IV


def getCVolumeSerialNumber(self):
CVolumeSerialNumber = win32api.GetVolumeInformation('C:\\')[1]
if CVolumeSerialNumber:
return str(CVolumeSerialNumber)
return None


def DesEncrypt(self, str):
k = pyDes.des(self.Des_Key, pyDes.CBC, self.Des_IV, None, pyDes.PAD_PKCS5, **('pad', 'padmode'))
encryptStr = k.encrypt(str)
string = base64.b64encode(encryptStr)
return string


def DesDecrypt(self, string):
string = base64.b64decode(string)
k = pyDes.des(self.Des_Key, pyDes.CBC, self.Des_IV, None, pyDes.PAD_PKCS5, **('pad', 'padmode'))
decryptStr = k.decrypt(string)
return decryptStr


def Regist_New(self):
pass
# WARNING: Decompyle incomplete


def encryCode(self):
global serialnumber
rand = str(random.randrange(1, 1000))
serialnumber = self.getCVolumeSerialNumber()
content = str({
'stat': '',
'Serial': serialnumber,
'Random': rand,
'Type': self.TYPE })
encryptstr = self.DesEncrypt(content).decode('utf8')
return encryptstr


def checKey(self):
key = values['-key-']
# WARNING: Decompyle incomplete


def GetTime(self):
url = 'http://api.m.taobao.com/rest/api3.do?api=mtop.common.getTimestamp'
# WARNING: Decompyle incomplete


def CheckTimeTri(self):
if int(self.GetTime()) >= self.deadline:
os.remove('conf.bin')
return 403


headers = {
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.25 Safari/537.36 Core/1.70.3877.400 QQBrowser/10.8.4506.400' }

def SeTool():
global phone, phonediqu, lolName, lolDaqu, qqlm, weibo, qq, qq, phone, weibo

def qqMsg():
global phone, phonediqu, lolName, lolDaqu, qqlm
print('正在查询...')
url = 'https://www.hmily.vip/api/qb/?qq=' + str(qq)
html = requests.get(url, headers, **('url', 'headers'))
if html.json()['code'] == 1:
phone = html.json()['phone']
phonediqu = html.json()['phonediqu']
lolName = html.json()['lolName']
lolDaqu = html.json()['lolDaqu']
qqlm = html.json()['qqlm']


def phoneMsg():
global qq, phonediqu, weibo
print('正在查询...')
url3 = 'https://hmily.vip/api/phone/?phone=' + str(phone)
html = requests.get(url3, headers, **('url', 'headers'))
if html.json()['code'] == 1:
qq = html.json()['qq']
phonediqu = html.json()['phonediqu']
weibo = html.json()['weibo']


def wbMsg():
global phone, phonediqu
print('正在查询...')
url3 = 'https://www.hmily.vip/api/wb/?id=' + str(weibo)
html = requests.get(url3, headers, **('url', 'headers'))
if html.json()['code'] == 1:
phone = html.json()['phone']
phonediqu = html.json()['phonediqu']

layout = [
[
Sg.T('查询结果:')],
[
Sg.Multiline('查询需要时间,提交后请耐心等待结果\n', (70, 20), '-show-', True, **('size', 'key', 'autoscroll'))],
[
Sg.T('说明:请选择与输入号码相对应的查询方式', '-text-', 'white', **('key', 'text_color'))],
[
Sg.T('请输入查询号码'),
Sg.In('-content-', **('key',))],
[
Sg.T('请选择查询方式')] + (lambda .0: [ Sg.Radio(i, 1, i, **('group_id', 'key')) for i in .0 ])(('qq号', '手机号', '微博UID')),
[
Sg.B('确认提交'),
Sg.B('清空')]]
window = Sg.Window('SE工具箱', layout)
flag = Sg.popup_ok_cancel('免责声明:请勿把软件用在违法犯罪途径!\n造成的一切后果本作者概不负责\n如若同意请点击ok进入软件', '提示', ('黑体', 13), **('title', 'font'))
if flag == 'Cancel':
os._exit(0)
(event, values) = window.read(300)
if res2 == 3 or res1 == 3:
res = Reg.CheckTimeTri()
if res == 403:
Sg.popup('软件使用时间已到期\n请重新购买登录码', '提示', ('黑体', 13), **('title', 'font'))

if event == '确认提交' and values['-content-'] != '':
phone = '没有查询到'
phonediqu = '没有查询到'
lolName = '没有查询到'
lolDaqu = '没有查询到'
qqlm = '没有查询到'
weibo = '没有查询到'
qq = '没有查询到'
message = ''
msg = ''
t = time.strftime('%Y/%m/%d %H:%M:%S', time.localtime())
if values['qq号']:
qq = values['-content-']
message = window['-show-'].get()
window['-show-'].update('')
t1 = threading.Thread(qqMsg, **('target',))
t1.start()
t1.join()
if phone == '没有查询到':
msg = f'''\n时间: {t}\nQQ号码: {qq}\n未查到任何信息! \n'''
else:
msg = f'''\n查询成功!\n时间: {t}\nQQ号码: {qq}\n手机号码: {phone}\n地区: {phonediqu}\nLOL账号: {lolName}\nLOL大区: {lolDaqu}\nQQ密码: {qqlm}\n '''
elif values['手机号']:
phone = values['-content-']
message = window['-show-'].get()
window['-show-'].update('')
t2 = threading.Thread(phoneMsg, **('target',))
t2.start()
t2.join()
if qq == '没有查询到':
msg = f'''\n时间: {t}\n手机号码: {phone}\n未查到任何信息! \n'''
else:
msg = f'''\n查询成功!\n时间: {t}\n手机号码: {phone}\n地区: {phonediqu}\nQQ账号: {qq}\n微博ID: {weibo}\n'''
elif values['微博UID']:
weibo = values['-content-']
message = window['-show-'].get()
window['-show-'].update('')
wbMsg()
if phone == '没有查询到':
msg = f'''\n时间: {t}\n微博ID: {weibo}\n未查到任何信息! \n'''
else:
msg = f'''\n查询成功!\n时间: {t}\n微博ID: {weibo}\n手机号码: {phone}\n地区: {phonediqu}\n'''
else:
window['-show-'].update('请选择一个查询方式,点击提交后请耐心等待查询结果')
window['-show-'].update(message + '\n' + msg)
window['-content-'].update('')
if event == '清空':
window['-show-'].update('')
if event is None:
pass

window.close()

Reg = Register(TYPE)
res1 = Reg.Regist_New()
deadline = ''
res2 = ''
if res1 in (1, 2, 3):
SeTool()
elif res1 == 4:
Sg.popup('登陆码验证失败 请重新输入', '提示', ('黑体', 13), **('title', 'font'))
if res1 == 5:
Sg.popup('请勿非法获得验证文件!', '提示', ('黑体', 13), **('title', 'font'))
entryCode = Reg.encryCode()
layout = [
[
Sg.Text('输入你的登录码后进入软件', ('黑体', 13), **('font',))],
[
Sg.Text('机器码:', True, (7, 1), ('黑体', 12), **('enable_events', 'size', 'font')),
Sg.InputText(entryCode, '-serial-', **('key',))],
[
Sg.Text('登录码:', (7, 1), ('黑体', 12), **('size', 'font')),
Sg.InputText('', '-key-', **('key',))],
[
Sg.Button('确认', ('微软雅黑', 9), **('font',)),
Sg.Button('退出', ('微软雅黑', 9), **('font',)),
Sg.Text('点我购买登录码', ((200, 10), (0, 0)), True, '#fff200', **('pad', 'enable_events', 'text_color'))]]
window1 = Sg.Window('SE工具箱', layout)
(event, values) = window1.read()
if event == None:
pass
elif event == '确认' and values['-key-'] != '':
res2 = Reg.checKey()
if res2 == 1:
Sg.popup('登录成功!', ('黑体', 12), **('font',))
window1.close()
SeTool()
elif res2 == 3:
timeArry = time.localtime(Reg.deadline / 1000)
Sg.popup(f'''登录成功!到期时间\n{time.strftime('%Y/%m/%d %H:%M:%S', timeArry)}''', ('黑体', 13), **('font',))
window1.close()
SeTool()
elif res2 == 5:
Sg.popup('登陆码验证失败 请重新输入', '提示', ('黑体', 12), **('title', 'font'))
if event == '退出':
pass
elif event == '点我购买登录码':
Sg.popup('购买登录码20R\n联系QQ:2900548175\n微信号:tangmin903', '提示', ('黑体', 12), **('title', 'font'))
continue
window1.close()
return None

结果

然后翻阅源码发现如下几个接口:

THE END