XFE Git
XFE Studio Git
Git 首页 全局搜索
XFE 主站 文档 NuGet

XFESystem

【Rust】XFE系统,基于Rust和汇编

公开
关注 0 Fork 0 Star 0
UTF-8
"""Test the production #DE decoder in a freestanding Windows DLL, not a guest."""
import argparse
import ctypes
import hashlib
import json
from pathlib import Path
import struct


FIELDS = 'r15 r14 r13 r12 r11 r10 r9 r8 rsi rdi rbp rdx rcx rbx rax vector error rip cs rflags rsp ss'.split()


class Frame(ctypes.Structure):
    _fields_ = [(field, ctypes.c_uint64) for field in FIELDS]


def main(dll_path):
    library = ctypes.CDLL(str(dll_path.resolve()))
    decode = library.XfeRuntimeClassifyDivideFault
    decode.argtypes = [ctypes.POINTER(Frame), ctypes.POINTER(ctypes.c_uint32)]
    decode.restype = ctypes.c_int
    checks = 0

    def test(opcode, registers=None, overflow=False, valid=True, tail=b''):
        nonlocal checks
        instructions = ctypes.create_string_buffer(opcode + tail)
        frame = Frame()
        frame.rip = ctypes.addressof(instructions)
        for name, value in (registers or {}).items():
            setattr(frame, name, value)
        code = ctypes.c_uint32(0)
        result = decode(ctypes.byref(frame), ctypes.byref(code))
        assert result == int(valid), (opcode.hex(), result)
        if valid:
            assert code.value == (0xC0000095 if overflow else 0xC0000094), (opcode.hex(), hex(code.value))
        checks += 1

    test(bytes.fromhex('f7f9'), {'rcx': 0})
    test(bytes.fromhex('f7f9'), {'rcx': 0xFFFFFFFF}, overflow=True)
    test(bytes.fromhex('48f7fe'), {'rsi': 0xFFFFFFFFFFFFFFFF}, overflow=True)
    test(bytes.fromhex('49f7fc'), {'r12': 0})
    test(bytes.fromhex('49f7fc'), {'r12': 0xFFFFFFFFFFFFFFFF}, overflow=True)
    test(bytes.fromhex('66f7fb'), {'rbx': 0x10000})  # Width truncates to BX.
    test(bytes.fromhex('66f7fb'), {'rbx': 0xFFFF}, overflow=True)
    test(bytes.fromhex('f6fc'), {'rax': 0x0100}, overflow=True)  # AH without REX.
    test(bytes.fromhex('f6fc'), {'rax': 0x0001})
    test(bytes.fromhex('40f6fc'), {'rsp': 0x0100})  # REX selects SPL, not AH.
    test(bytes.fromhex('40f6fc'), {'rsp': 1}, overflow=True)
    test(bytes.fromhex('41f6f9'), {'r9': 1}, overflow=True)
    test(bytes.fromhex('48f7f3'), {'rbx': 1}, overflow=True)  # Unsigned DIV too.
    test(bytes.fromhex('48f7f3'), {'rbx': 0})
    test(bytes.fromhex('f73d00000000'), tail=struct.pack('<I', 0))
    test(bytes.fromhex('f73d00000000'), tail=struct.pack('<I', 0xFFFFFFFF), overflow=True)
    test(bytes.fromhex('48f73d00000000'), tail=struct.pack('<Q', 0xFFFFFFFFFFFFFFFF), overflow=True)

    operand = ctypes.c_uint64(1)
    address = ctypes.addressof(operand)
    test(bytes.fromhex('48f73b'), {'rbx': address}, overflow=True)
    test(bytes.fromhex('48f77b80'), {'rbx': address + 128}, overflow=True)  # Signed disp8.
    test(bytes.fromhex('48f7bb00020000'), {'rbx': address - 512}, overflow=True)
    test(bytes.fromhex('48f73cf3'), {'rbx': address - 40, 'rsi': 5}, overflow=True)  # SIB *8.
    test(bytes.fromhex('4af73c23'), {'rbx': address - 64, 'r12': 64}, overflow=True)  # REX.X R12.
    test(bytes.fromhex('49f77d00'), {'r13': address}, overflow=True)

    kernel = ctypes.WinDLL('kernel32', use_last_error=True)
    kernel.VirtualAlloc.argtypes = [ctypes.c_void_p, ctypes.c_size_t, ctypes.c_ulong, ctypes.c_ulong]
    kernel.VirtualAlloc.restype = ctypes.c_void_p
    kernel.VirtualFree.argtypes = [ctypes.c_void_p, ctypes.c_size_t, ctypes.c_ulong]
    kernel.VirtualFree.restype = ctypes.c_int
    low = kernel.VirtualAlloc(0x50000000, 4096, 0x3000, 4)
    assert low == 0x50000000, ctypes.get_last_error()
    try:
        ctypes.c_uint32.from_address(low).value = 1
        test(bytes.fromhex('f73c25') + struct.pack('<I', low), overflow=True)  # No SIB base.
        test(bytes.fromhex('6741f738'), {'r8': 0xFFFF000000000000 | low}, overflow=True)  # 32-bit address.
    finally:
        assert kernel.VirtualFree(low, 0, 0x8000), ctypes.get_last_error()

    test(bytes.fromhex('90'), valid=False)
    test(bytes.fromhex('f7c0'), valid=False)
    test(bytes.fromhex('66') * 15, valid=False)
    assert decode(None, ctypes.byref(ctypes.c_uint32())) == 0
    checks += 1
    result = {'Kind': 'XfeHardwareDivideDecoderHostProof', 'Passed': True, 'Checks': checks,
              'GuestExecutionVerified': False, 'DllSha256': hashlib.sha256(dll_path.read_bytes()).hexdigest()}
    (dll_path.parent / 'Result.json').write_text(json.dumps(result, indent=2), encoding='utf-8')
    print(json.dumps(result))


if __name__ == '__main__':
    parser = argparse.ArgumentParser(description=__doc__)
    parser.add_argument('dll', type=Path)
    args = parser.parse_args()
    main(args.dll)