Python GUI小工具

前记

打算学习一下python GUI编程

本来打算使用PyQt5,结果发现Qt Design默认的控件太少了(pywebview也可以)

转而使用python自带的Tkinter模块

程序功能

  1. 计算文件Hash,包括文件大小、md5、sha-1、sha-256);

  2. 通过virustotal api和微步API获取文件的一些基本信息,包括检测比(恶意/未检出)、卡巴斯基分类、文件类型、PEiD;

    (待完善)

    image-20220927093900904

具体代码

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
import hashlib
from tkinter.filedialog import *
from tkinter.ttk import *
import windnd
import requests
import json
import base64
import webbrowser


def VirusTotal(file_md5):
header = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:82.0) Gecko/20100101 Firefox/82.0',
'Connection': 'close',
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8',
'x-apikey': '*****************************************************' # api key
}
requests.packages.urllib3.disable_warnings()
# 检索有关文件的信息(by MD5)
string = requests.get('https://www.virustotal.com/api/v3/files/' + file_md5, headers=header, verify=False)
# print(string.text)
s = json.loads(string.text)
if len(string.text) > 1000:
E_VT.insert(0, str(s['data']['attributes']['last_analysis_stats']['malicious']) + '/' +
str(s['data']['attributes']['last_analysis_stats']['undetected']))
E_Type.insert(0, s['data']['attributes']['magic'])
try:
E_Ka.insert(0, s['data']['attributes']['last_analysis_results']['Kaspersky']['result'])
except:
E_Ka.insert(0, "无")
try:
E_PEiD.insert(0, s['data']['attributes']['packers']['PEiD'])
except:
E_PEiD.insert(0, "无")
else:
E_VT.insert(0, 'VT无结果')
E_Ka.insert(0, 'VT无结果')
E_PEiD.insert(0, 'VT无结果')
E_Type.insert(0, 'VT无结果')


def threatbook(file_sha256):
url = 'https://api.threatbook.cn/v3/file/report/multiengines'
params = {
'apikey': '******************************************', #api key
'sha256': file_sha256
}
response = requests.get(url, params=params)
#print(response.text)
s = json.loads(response.text)
if len(response.text) > 100:
E_TB.insert(0, str(s['data']['multiengines']['positives']) + '/' + str(s['data']['multiengines']['total2']))
E_level.insert(0, s['data']['multiengines']['threat_level'])
E_family.insert(0,
s['data']['multiengines']['malware_type'] + ' 、 ' + s['data']['multiengines']['malware_family'])
else:
E_TB.insert(0, '微步无结果')
E_level.insert(0, '微步无结果')
E_family.insert(0, '微步无结果')


# 计算文件大小
def Size(file):
size = os.path.getsize(file)
size = format(size, ',')
E_size.delete(0, END)
E_size.insert(0, size + '字节')


# 计算Hash
def Hash(file):
with open(file, 'rb') as fp:
data = fp.read()
file_md5 = hashlib.md5(data).hexdigest()
file_sha1 = hashlib.sha1(data).hexdigest()
file_sha256 = hashlib.sha256(data).hexdigest()
E_md5.delete(0, END)
E_md5.insert(0, file_md5)
E_sha1.delete(0, END)
E_sha1.insert(0, file_sha1)
E_sha256.delete(0, END)
E_sha256.insert(0, file_sha256)
E_VT.delete(0, END)
E_Ka.delete(0, END)
E_PEiD.delete(0, END)
E_Type.delete(0, END)
E_TB.delete(0, END)
E_level.delete(0, END)
E_family.delete(0, END)
win.update() # 更新窗口
if CheckVar1.get() == 1:
VirusTotal(file_md5)
if CheckVar2.get() == 1:
threatbook(file_sha256)


# 打开文件
def FileOpen():
file = askopenfilename(title='打开文件')
E.delete(0, END)
E.insert(0, str(file))
Size(file)
Hash(file)


# 拖拽打开文件
def Dragg(files):
file = '\n'.join((item.decode('gbk') for item in files))
E.delete(0, END)
E.insert(0, str(file))
Size(file)
Hash(file)


def VTOpen():
sha256 = E_sha256.get()
webbrowser.open('https://www.virustotal.com/gui/file/' + sha256, )

def TBOpen():
sha256 = E_sha256.get()
webbrowser.open('https://s.threatbook.com/report/file/' + sha256, )


win = Tk()
# 获取屏幕尺寸计算参数,使窗口显示再屏幕中央
screen_width = win.winfo_screenwidth()
screen_height = win.winfo_screenheight()
width = 550
height = 290
win_size = f'{width}x{height}+{round((screen_width - width) / 2)}+{round((screen_height - height) / 2)}' # round去掉小数
win.geometry(win_size)
win.resizable(height=False, width=False)
win.title('DEMO')

# base64图标
# win.iconbitmap('demo.ico')
temp = open('temp.ico', 'wb+')
base64_str = 'AAABAAEAICAAAAEAIACoEAAAFgAAACgAAAAgAAAAQAAAAAEAIAAAAAAAABAAAMMOAADDDgAAAAAAAAAAAAD///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////Tz///Lxf//xr///8bA///GwP//xsD//8bA///GwP//xsD//8bA///GwP//xsD//8bA///GwP//xsD//8bA///GwP//xsD//8bA///GwP//xsD//8bA///GwP//xsD//8bA///GwP//xr///9fS///+/v//////////////////+Pf//6CW//9VQf//Uj7//1I///9SP///Uj///1I+//9SPv//Uj7//1I+//9SPv//Uj7//1I+//9SPv//Uj7//1I+//9SPv//Uj7//1I+//9SPv//Uj7//1I+//9SPv//Uj7//1I///9PO///hHf///v7////////////////////////9fT//5iN//9QPP//TTn//046//9OO///Tzv//046//9OOv//Tjr//046//9OOv//Tjr//046//9OOv//Tjr//046//9OOv//Tjr//046//9OOv//Tjr//046//9OOv//Tjr//0s2//+Bc///+/v/////////////////////////////9PP//5SJ//9PO///TTn//1hF//+flP//ubH//7ev//+3r///t6///7ev//+3r///t6///7ev//+3r///t6///7ev//+3r///t6///7ev//+3r///uLD//6+m//9iUP//Sjb//4Jz///7+///////////////////////////////////8vH//5GE//9OOv//Tjr//4N1///r6f//////////////////////////////////////////////////////////////////////////////////8/L//3Bf//9JNf//gnP///v7////////////////////////////////////////8O///42A//9OOv//TTn//4Bx///n5P/////////////////////////////////////////////////////////////////////////////x7///b1///0k1//+Cc///+/v/////////////////////////////////////////////7+3//4l8//9NOf//TDj//4By///p5/////////////////////////////////////////////////////////////////////////Hv//9vX///STX//4Jz///7+///////////////////////////////////////////////////7Or//4V4//9NOf//TTn//4R1///r6f//////////////////////////////////////////////////////////////////8e///29f//9JNf//gnP///v7////////////////////////////////////////////////////////6uj//4J0//9NOf//TTn//4d6///u6//////////////////////////////////////////////////////////////x7///b1///0k1//+Cc///+/v/////////////////////////////////////////////////////////////6OX//35w//9MOP//Tjr//4t+///w7v////////////////////////////////////////////////////////Hv//9vX///STX//4Jz///7+///////////////////////////////////////////////////////////////////5eP//3ts//9MOP//Tjr//4+C///x8P//////////////////////////////////////////////////8e///29f//9JNf//gnP///v7////////////////////////////////////////////////////////////////////////4+D//3ho//9MOP//Tzv//5OG///z8v/////////////////////////////////////////////x7///b1///0k1//+Cc///+/v/////////////////////////////////////////////////////////////////////////////4d7//3pr//9NOf//Tzz//5aK///z8v////////////////////////////////////////Hv//9vX///STX//4Jz///7+///////////////////////////////////////////////////////////////////////////////////s6v//1E9//9MOP//W0n//9PO////////////////////////////////////////8e///29f//9JNf//gnP///v7/////////////////////////////////////////////////////////////////////////////8vF//9kUv//TDj//1ZD//+wp///+/r////////////////////////////////////////x7///b1///0k1//+Cc///+/v////////////////////////////////////////////////////////////////////////Pyf//ZVT//0s3//9VQf//rKP///z7//////////////////////////////////////////////Hv//9vX///STX//4Jz///7+///////////////////////////////////////////////////////////////////0s3//2dW//9LN///VkP//6uh///6+v//////////////////////////////////////////////////8e///29f//9JNf//gnP///v7/////////////////////////////////////////////////////////////9XQ//9qWf//Szf//1VB//+so///+/v////////////////////////////////////////////////////////x7///b1///0k1//+Cc///+/v////////////////////////////////////////////////////////Y1P//bVz//0s3//9TQP//qJ////v6//////////////////////////////////////////////////////////////Hv//9vX///STX//4Jz///7+///////////////////////////////////////////////////3Nf//3Bf//9LN///Uj///6Sa///5+f//////////////////////////////////////////////////////////////////8e///29f//9JNf//gnP///v7/////////////////////////////////////////////97b//9zY///Szf//1E+//+glv//+Pj////////////////////////////////////////////////////////////////////////x7///b1///0k1//+Cc///+/v////////////////////////////////////////h3v//dmb//0w3//9RPf//nZL///f2//////////////////////////////////////////////////////////////////////////////Hv//9vX///STX//4Jz///7+///////////////////////////////////5OH//3lq//9MOP//UDz//5aK///z8f///f3///z8///8/P///Pz///z8///8/P///Pz///z8///8/P///Pz///z8///8/P///Pz///z8///9/f//7uz//29e//9JNf//gnP///v7/////////////////////////////+fk//98bv//TTj//005//9UQf//gHL//4x///+Lfv//i37//4t+//+Lfv//i37//4t+//+Lfv//i37//4t+//+Lfv//i37//4t+//+Lfv//i37//4t+//+GeP//WUf//0o2//+Cc///+/v////////////////////////o5f//f3D//0w3//9NOP//TTn//004//9LNv//Sjb//0o2//9KNv//Sjb//0o2//9KNv//Sjb//0o2//9KNv//Sjb//0o2//9KNv//Sjb//0o2//9KNv//Sjb//0o2//9MOP//SjX//4Fy///7+///////////////////9PL//5aL//9gTv//YU///2FP//9hT///YU///2FP//9hT///YU///2FP//9hT///YU///2FP//9hT///YU///2FP//9hT///YU///2FP//9hT///YU///2FP//9hT///YU///2FP//9eTP//j4L///v7///////////////////49///4+D//+Lf///i3///4t///+Lf///i3///4t///+Lf///i3///4t///+Lf///i3///4t///+Lf///i3///4t///+Lf///i3///4t///+Lf///i3///4t///+Lf///i3///4t///+Lf///r6P///v7/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA='
imagedata = base64.b64decode(base64_str)
temp.write(imagedata)
temp.close()
win.iconbitmap('temp.ico')
os.remove('temp.ico')

# 文件拖拽
windnd.hook_dropfiles(win, func=Dragg)

Label(win, text='文件名:').grid(row=0)
E = Entry(win, width=50)
E.grid(row=0, column=1, columnspan=4)
btn = Button(win, text='选择', command=FileOpen).grid(row=0, column=6)

Label(win, text='大小:').grid(row=1)
E_size = Entry(win, width=50)
E_size.grid(row=1, column=1, columnspan=5)

Label(win, text='MD5:').grid(row=2)
E_md5 = Entry(win, width=50)
E_md5.grid(row=2, column=1, columnspan=5)

Label(win, text='SHA-1:').grid(row=3)
E_sha1 = Entry(win, width=50)
E_sha1.grid(row=3, column=1, columnspan=5)
CheckVar1 = IntVar()
CheckVar1.set(1)
C1 = Checkbutton(win, text="VirusTotal API", variable=CheckVar1)
C1.grid(row=3, column=6, columnspan=5)

Label(win, text='SHA-256:').grid(row=4)
E_sha256 = Entry(win, width=50)
E_sha256.grid(row=4, column=1, columnspan=5)
CheckVar2 = IntVar()
C1 = Checkbutton(win, text="threatbook API", variable=CheckVar2)
C1.grid(row=4, column=6, columnspan=5)

Label(win, text='--------VirusTotal API-------').grid(row=5, column=3)

Label(win, text='引擎检测:').grid(row=6)
E_VT = Entry(win, width=10)
E_VT.grid(row=6, column=1, columnspan=5, sticky=W)

Label(win, text='Kaspersky:').grid(row=6, column=2, columnspan=3)
E_Ka = Entry(win, width=30)
E_Ka.grid(row=6, column=4, columnspan=3, sticky=W)

Label(win, text='类型:').grid(row=7)
E_Type = Entry(win, width=50)
E_Type.grid(row=7, column=1, columnspan=5)
btn_vt = Button(win, text='Open VT', command=VTOpen).grid(row=7, column=6, rowspan=2)

Label(win, text='PEiD:').grid(row=8)
E_PEiD = Entry(win, width=50)
E_PEiD.grid(row=8, column=1, columnspan=5)

Label(win, text='--------threatbook API-------').grid(row=9, column=3)

Label(win, text='引擎检测:').grid(row=10)
E_TB = Entry(win, width=10)
E_TB.grid(row=10, column=1, columnspan=5, sticky=W)

Label(win, text='检测结果:').grid(row=10, column=2, columnspan=3)
E_level = Entry(win, width=30)
E_level.grid(row=10, column=4, columnspan=3, sticky=W)

Label(win, text='类型及家族:').grid(row=11)
E_family = Entry(win, width=50)
E_family.grid(row=11, column=1, columnspan=5)
btn_vt = Button(win, text='访问微步', command=TBOpen).grid(row=11, column=6, rowspan=2)

win.mainloop()

使用pyinstaller打包成exe

1
pyinstaller -i *.ico -F -c main.py --noconsole

总结

刚开始接触使用起来还算可以,就是画界面太麻烦了

工具还有很大的完善空间,加入各种api

like https://github.com/alexandreborges/malwoverview

还有就是python打包exe是真的大


Python GUI小工具
http://wangchenchina.github.io/2022/09/27/Python-GUI小工具/
作者
Demo
发布于
2022年9月27日
许可协议