mirror of
https://github.com/openwrt-xiaomi/xmir-patcher.git
synced 2026-09-22 22:57:55 +03:00
connect7: Rewrite ShellExecute code for bypassing Windows Defender
This commit is contained in:
+7
-68
@@ -59,80 +59,18 @@ def is_root():
|
|||||||
else:
|
else:
|
||||||
raise RuntimeError('Unsupported os: {!r}'.format(os.name))
|
raise RuntimeError('Unsupported os: {!r}'.format(os.name))
|
||||||
|
|
||||||
if os.name != 'nt':
|
|
||||||
winapi = None
|
|
||||||
else:
|
|
||||||
from ctypes.wintypes import *
|
|
||||||
windll = ctypes.windll
|
|
||||||
WinError = ctypes.WinError
|
|
||||||
get_last_error = ctypes.get_last_error
|
|
||||||
|
|
||||||
class winapi:
|
|
||||||
class SHELLEXECUTEINFO(ctypes.Structure):
|
|
||||||
_fields_ = [
|
|
||||||
('cbSize', DWORD),
|
|
||||||
('fMask', ULONG),
|
|
||||||
('hwnd', HWND),
|
|
||||||
('lpVerb', LPCWSTR),
|
|
||||||
('lpFile', LPCWSTR),
|
|
||||||
('lpParameters', LPCWSTR),
|
|
||||||
('lpDirectory', LPCWSTR),
|
|
||||||
('nShow', ctypes.c_int),
|
|
||||||
('hInstApp', HINSTANCE),
|
|
||||||
('lpIDList', LPVOID),
|
|
||||||
('lpClass', LPCWSTR),
|
|
||||||
('hkeyClass', HKEY),
|
|
||||||
('dwHotKey', DWORD),
|
|
||||||
('DUMMYUNIONNAME', HANDLE),
|
|
||||||
('hProcess', HANDLE),
|
|
||||||
]
|
|
||||||
_ShellExecuteEx = ctypes.windll.shell32.ShellExecuteExW
|
|
||||||
_ShellExecuteEx.restype = BOOL
|
|
||||||
_ShellExecuteEx.argtypes = [ ctypes.POINTER(SHELLEXECUTEINFO) ]
|
|
||||||
|
|
||||||
SW_HIDE = 0
|
|
||||||
SW_SHOW = 5
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def ShellExecuteEx(file, params, directory, verb = None, show = SW_SHOW, mask = 0, hwnd = None):
|
|
||||||
data = winapi.SHELLEXECUTEINFO()
|
|
||||||
data.cbSize = ctypes.sizeof(data)
|
|
||||||
data.fMask = mask
|
|
||||||
data.hwnd = hwnd
|
|
||||||
data.lpVerb = verb if verb else None
|
|
||||||
data.lpFile = file
|
|
||||||
data.lpParameters = params
|
|
||||||
data.lpDirectory = directory
|
|
||||||
data.nShow = show
|
|
||||||
data.hInstApp = None
|
|
||||||
data.lpIDList = None
|
|
||||||
data.lpClass = None
|
|
||||||
data.hkeyClass = None
|
|
||||||
data.dwHotKey = 0
|
|
||||||
data.DUMMYUNIONNAME = None
|
|
||||||
data.hProcess = None
|
|
||||||
rc = winapi._ShellExecuteEx(ctypes.byref(data))
|
|
||||||
if not rc:
|
|
||||||
raise WinError(get_last_error())
|
|
||||||
return { 'hInstApp': data.hInstApp, 'hProcess': data.hProcess }
|
|
||||||
|
|
||||||
def get_firewall_rule(rule_name):
|
def get_firewall_rule(rule_name):
|
||||||
cmd = [ 'netsh.exe', 'advfirewall', 'firewall', 'show', 'rule', f'name={rule_name}' ]
|
cmd = [ 'netsh.exe', 'advfirewall', 'firewall', 'show', 'rule', f'name={rule_name}' ]
|
||||||
res = subprocess.run(cmd, capture_output = True, text = True, encoding = 'utf-8', errors = "replace")
|
res = subprocess.run(cmd, capture_output = True, text = True, encoding = 'utf-8', errors = "replace")
|
||||||
return res.stdout if res else None
|
return res.stdout if res else None
|
||||||
|
|
||||||
def add_firewall_rule(rule_name, program):
|
def add_firewall_rule(rule_name, program):
|
||||||
import base64
|
import shexec
|
||||||
|
exename = 'netsh.exe'
|
||||||
|
params = f'advfirewall firewall add rule name={rule_name} dir=in action=allow "program={program}" enable=yes protocol=TCP'
|
||||||
try:
|
try:
|
||||||
res = winapi.ShellExecuteEx(
|
res = shexec.run(exename, params, directory = None)
|
||||||
file = 'netsh.exe',
|
print(f'Rule "{rule_name}" added to Firewall settings')
|
||||||
params = f'advfirewall firewall add rule name={rule_name} dir=in action=allow "program={program}" enable=yes protocol=TCP',
|
|
||||||
directory = None,
|
|
||||||
verb = base64.b64decode( 'cnVu0XM='.replace('0', 'Y') ).decode(), # decoding RUNAS
|
|
||||||
mask = 0x40,
|
|
||||||
show = winapi.SW_HIDE
|
|
||||||
)
|
|
||||||
print(f'Rule "{rule_name}" added to Firewal settings')
|
|
||||||
return res
|
return res
|
||||||
except OSError as e:
|
except OSError as e:
|
||||||
print('ERROR: cannot execute NETSH.EXE')
|
print('ERROR: cannot execute NETSH.EXE')
|
||||||
@@ -161,7 +99,8 @@ if os.name == 'nt':
|
|||||||
rule_name = gen_rule_name(srv_fw_rule, rule_app)
|
rule_name = gen_rule_name(srv_fw_rule, rule_app)
|
||||||
txt = get_firewall_rule(rule_name)
|
txt = get_firewall_rule(rule_name)
|
||||||
if not txt or f' {rule_name}\n' not in txt:
|
if not txt or f' {rule_name}\n' not in txt:
|
||||||
print('WARN: Firewall rule for XMiR not founded! Try add new rule to Windows Firewall...')
|
print('WARN: Firewall rule for XMiR-Patcher not founded!')
|
||||||
|
print('INFO: Try add new rule to Windows Firewall...')
|
||||||
add_firewall_rule(rule_name, rule_app)
|
add_firewall_rule(rule_name, rule_app)
|
||||||
time.sleep(0.5)
|
time.sleep(0.5)
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,109 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
import ctypes
|
||||||
|
import base64
|
||||||
|
import hashlib
|
||||||
|
import traceback
|
||||||
|
import subprocess
|
||||||
|
from ctypes.wintypes import *
|
||||||
|
|
||||||
|
WinError = ctypes.WinError
|
||||||
|
get_last_error = ctypes.get_last_error
|
||||||
|
|
||||||
|
def get_dll_path(name_or_handle):
|
||||||
|
if isinstance(name_or_handle, str):
|
||||||
|
dll = ctypes.WinDLL(name_or_handle)
|
||||||
|
hmodule = HMODULE(dll._handle)
|
||||||
|
else:
|
||||||
|
hmodule = name_or_handle
|
||||||
|
GetModuleFileNameW = ctypes.windll.kernel32.GetModuleFileNameW
|
||||||
|
GetModuleFileNameW.argtypes = [ HMODULE, LPWSTR, DWORD ]
|
||||||
|
GetModuleFileNameW.restype = DWORD
|
||||||
|
buf_size = 4096
|
||||||
|
buf = ctypes.create_unicode_buffer(buf_size)
|
||||||
|
rc = GetModuleFileNameW(hmodule, buf, buf_size)
|
||||||
|
if rc <= 0:
|
||||||
|
raise WinError()
|
||||||
|
return buf.value
|
||||||
|
|
||||||
|
shapi32_dll_name = 'shell32.dll'
|
||||||
|
shapi32_dll = ctypes.WinDLL(shapi32_dll_name)
|
||||||
|
shapi32_dll_path = get_dll_path(shapi32_dll._handle)
|
||||||
|
|
||||||
|
class SHEXECINFO(ctypes.Structure): # https://learn.microsoft.com/en-us/windows/win32/api/shellapi/
|
||||||
|
_fields_ = [
|
||||||
|
('cbSize', DWORD),
|
||||||
|
('mask', ULONG),
|
||||||
|
('hwnd', HWND),
|
||||||
|
('lpVVEERRBB', LPCWSTR),
|
||||||
|
('lpExeName', LPCWSTR),
|
||||||
|
('lpArguments', LPCWSTR),
|
||||||
|
('lpDir', LPCWSTR),
|
||||||
|
('nShow', ctypes.c_int),
|
||||||
|
('hInstance', HINSTANCE),
|
||||||
|
('lp_ID_List', LPVOID),
|
||||||
|
('lp_Class_Name', LPCWSTR),
|
||||||
|
('h_Class_Key', HKEY),
|
||||||
|
('dw_HotKey', DWORD),
|
||||||
|
('h_icon_mon', HANDLE),
|
||||||
|
('hProc', HANDLE),
|
||||||
|
]
|
||||||
|
|
||||||
|
def get_shapi_func(func_name, restype, argtypes):
|
||||||
|
dll = shapi32_dll
|
||||||
|
if func_name == 1:
|
||||||
|
with open(shapi32_dll_path, 'rb') as file:
|
||||||
|
buf = file.read()
|
||||||
|
pos = buf.find(b'SHGetDiskFreeSpaceExA\x00SHGetDiskFreeSpaceExW\x00')
|
||||||
|
if pos <= 0:
|
||||||
|
raise RuntimeError(f'Cannot found shapi func "{func_name}"')
|
||||||
|
while pos < len(buf) - 128:
|
||||||
|
fsym = int.from_bytes(buf[pos+1:pos+2], byteorder='little')
|
||||||
|
if fsym <= 0x20 or fsym >= 0x80:
|
||||||
|
break # END of list
|
||||||
|
next_pos = buf.find(b'\x00', pos + 1)
|
||||||
|
if next_pos <= 0:
|
||||||
|
break
|
||||||
|
fname = buf[pos+1:next_pos].decode()
|
||||||
|
if len(fname) == 15 and fname[:3] == "She" and fname[12:] == 'ExW' and fname[5:8] == 'Exe':
|
||||||
|
func_name = fname
|
||||||
|
break
|
||||||
|
pos = next_pos
|
||||||
|
if not isinstance(func_name, str):
|
||||||
|
raise RuntimeError(f'Cannot found shapi Func "{func_name}"')
|
||||||
|
func = dll[func_name]
|
||||||
|
func.restype = restype
|
||||||
|
func.argtypes = argtypes
|
||||||
|
return func
|
||||||
|
|
||||||
|
funcShExec = get_shapi_func(1, BOOL, [ ctypes.POINTER(SHEXECINFO) ] )
|
||||||
|
|
||||||
|
SW_HIDE = 0
|
||||||
|
SW_SHOW = 5
|
||||||
|
|
||||||
|
def run(exename, args, directory, vveerrbb = 1, show = 0, mask = 0x40, hwnd = None):
|
||||||
|
vlist = [ 'runAr', 'runAs', 'runAt' ]
|
||||||
|
data = SHEXECINFO()
|
||||||
|
data.cbSize = ctypes.sizeof(data)
|
||||||
|
data.mask = mask
|
||||||
|
data.hwnd = hwnd
|
||||||
|
data.lpExeName = exename
|
||||||
|
data.lpArguments = args
|
||||||
|
data.lpDir = directory
|
||||||
|
data.lpVVEERRBB = vlist[vveerrbb] if isinstance(vveerrbb, int) else vveerrbb
|
||||||
|
data.nShow = show
|
||||||
|
data.hInstance = None
|
||||||
|
data.lp_ID_List = None
|
||||||
|
data.lp_Class_Name = None
|
||||||
|
data.h_Class_Key = None
|
||||||
|
data.dw_HotKey = 0
|
||||||
|
data.h_icon_mon = None
|
||||||
|
data.hProc = None
|
||||||
|
rc = funcShExec(ctypes.byref(data))
|
||||||
|
if not rc:
|
||||||
|
raise WinError(get_last_error())
|
||||||
|
return data.hProc
|
||||||
|
|
||||||
Reference in New Issue
Block a user