5d9aa02c07
- windows/win_card_reader.py: Windows-native card reader via the Raw Input API with a low-level keyboard-hook fallback. - windows/sign_exe.ps1: sign the built executable with a .pfx certificate. - windows/create_self_signed_cert.ps1: generate a self-signed cert for local testing (not trusted by Smart App Control). - windows/verify_sendinput_fix.py: verification helper for the SendInput foreground-unlock fix in run_win.py. - documentation/CODE_SIGNING_SMART_APP_CONTROL.md: signing guidance. - working_files/execute_playlist_retrieve.py, working_files/raw_server_playlist.json: playlist retrieval diagnostics. Note: windows/archive_list.txt and windows/build_last.txt are build output and were committed by request rather than by convention.
90 lines
3.4 KiB
Python
90 lines
3.4 KiB
Python
#!/usr/bin/env python3
|
|
"""Rigorous verification: is the fixed SendInput code in the compiled run_win?"""
|
|
import marshal
|
|
import types
|
|
import dis
|
|
from PyInstaller.archive.readers import CArchiveReader
|
|
|
|
EXE = r'dist\KiwySignagePlayer\KiwySignagePlayer.exe'
|
|
|
|
|
|
def collect_strings(code, acc):
|
|
for c in code.co_consts:
|
|
if isinstance(c, str):
|
|
acc.append(c)
|
|
elif isinstance(c, types.CodeType):
|
|
collect_strings(c, acc)
|
|
|
|
|
|
def collect_codes(code, acc):
|
|
acc.append(code)
|
|
for c in code.co_consts:
|
|
if isinstance(c, types.CodeType):
|
|
collect_codes(c, acc)
|
|
|
|
|
|
def main():
|
|
arc = CArchiveReader(EXE)
|
|
data = arc.extract('run_win')
|
|
code = marshal.loads(data)
|
|
|
|
all_codes = []
|
|
collect_codes(code, all_codes)
|
|
strings = []
|
|
collect_strings(code, strings)
|
|
|
|
# 1) c_ulonglong can ONLY come from the fixed code (old used c_ulong + POINTER)
|
|
has_c_ulonglong = any('c_ulonglong' in c.co_names for c in all_codes)
|
|
print(f'c_ulonglong in co_names of any code object: {has_c_ulonglong}')
|
|
|
|
# 2) INPUTUNION should be STORE_DEREF/STORE_NAME'd inside
|
|
# _force_foreground_sendinput (classes are defined in a closure,
|
|
# so they're stored via STORE_DEREF).
|
|
store_names = set()
|
|
for c in all_codes:
|
|
for instr in dis.get_instructions(c):
|
|
if instr.opname in ('STORE_NAME', 'STORE_FAST', 'STORE_DEREF'):
|
|
store_names.add(instr.argval)
|
|
print(f'INPUTUNION stored: {"INPUTUNION" in store_names}')
|
|
print(f'KEYBDINPUT stored: {"KEYBDINPUT" in store_names}')
|
|
print(f'MOUSEINPUT stored: {"MOUSEINPUT" in store_names}')
|
|
print(f'HARDWAREINPUT stored: {"HARDWAREINPUT" in store_names}')
|
|
|
|
# 3) The new code uses INPUT() + field assignment (type, u.ki.wVk, u.ki.dwFlags)
|
|
names = set()
|
|
for c in all_codes:
|
|
names.update(c.co_names)
|
|
print(f'Has "u" attribute usage: {"u" in names}')
|
|
|
|
# 4) string markers
|
|
print(f'string "undersized buffer": {any("undersized buffer" in s for s in strings)}')
|
|
print(f'string "real Win32 x64": {any("real Win32 x64" in s for s in strings)}')
|
|
print(f'string "ULONG_PTR": {any("ULONG_PTR" in s for s in strings)}')
|
|
|
|
# 5) Console-window fix in _find_kivy_hwnd: cellvars/freevars + tuple consts
|
|
find_kv = [c for c in all_codes if c.co_name == '_find_kivy_hwnd']
|
|
cell_vars = set()
|
|
for c in find_kv:
|
|
cell_vars.update(c.co_cellvars)
|
|
cell_vars.update(c.co_freevars)
|
|
enum_cb = [c for c in all_codes
|
|
if c.co_name == '_enum_cb' and 'SDL_CLASSES' in c.co_freevars]
|
|
tuple_strs = set()
|
|
for c in enum_cb:
|
|
for x in c.co_consts:
|
|
if isinstance(x, tuple):
|
|
tuple_strs.update(str(v) for v in x)
|
|
print(f'_find_kivy_hwnd cell/free vars (SDL_CLASSES/sdl_windows/our_pid): '
|
|
f'{"SDL_CLASSES" in cell_vars and "sdl_windows" in cell_vars and "our_pid" in cell_vars}')
|
|
print(f'console class excluded (ConsoleWindowClass in _enum_cb tuple): '
|
|
f'{"ConsoleWindowClass" in tuple_strs}')
|
|
|
|
verdict = has_c_ulonglong and 'INPUTUNION' in store_names
|
|
console_fix = ('SDL_CLASSES' in cell_vars and 'ConsoleWindowClass' in tuple_strs)
|
|
print(f'\nVerdict SendInput: {"FIX PRESENT" if verdict else "FIX ABSENT - rebuild needed"}')
|
|
print(f'Verdict console-hwnd: {"FIX PRESENT" if console_fix else "FIX ABSENT - rebuild needed"}')
|
|
|
|
|
|
if __name__ == '__main__':
|
|
main()
|