├── README.md ├── X86Call.asm ├── X86Call.cpp ├── X86Call.h ├── X86Call_deprecated.asm └── X86Call_deprecated.cpp /README.md: -------------------------------------------------------------------------------- 1 | # X86Call 2 | Enables x64 applications(native or wow64) to call any x86 function through a special function called X86Call 3 | 4 | For more infomation, see https://github.com/rwfpl/rewolf-wow64ext/ 5 | 6 | -------------------------------------------------------------------------------- /X86Call.asm: -------------------------------------------------------------------------------- 1 | X86_Start MACRO 2 | LOCAL xx, rt 3 | call $+5 4 | xx equ $ 5 | mov dword ptr [rsp + 4], 23h 6 | add dword ptr [rsp], rt - xx 7 | retf 8 | rt: 9 | ENDM 10 | 11 | X86_End MACRO 12 | db 6Ah, 33h ; push 33h 13 | db 0E8h, 0, 0, 0, 0 ; call $+5 14 | db 83h, 4, 24h, 5 ; add dword ptr [esp], 5 15 | db 0CBh ; retf 16 | ENDM 17 | 18 | .data 19 | brsp qword 0 20 | brdi qword 0 21 | brbp qword 0 22 | brax qword 0 23 | 24 | .code 25 | _x86call PROC 26 | push rsp 27 | push rdi 28 | push rbp 29 | 30 | X86_Start 31 | 32 | ;PUSH EBP 33 | db 55h 34 | mov ebp, esp 35 | 36 | ;db 0cch 37 | ;SUB ESP,DWORD PTR SS:[ESP-8] 38 | db 2bh, 64h, 24h, 0f8h 39 | 40 | ;CALL DWORD PTR SS:[ESP-4] 41 | db 0ffh, 54h, 24h, 0fch 42 | 43 | mov esp, ebp 44 | ;PUSH EBP 45 | db 5Dh 46 | 47 | X86_End 48 | 49 | pop rbp 50 | pop rdi 51 | pop rsp 52 | 53 | ret 54 | _x86call ENDP 55 | 56 | _x86push PROC 57 | ;RCX、RDX、R8、R9 58 | ;XMM0、XMM1、XMM2、XMM3 59 | 60 | sub rsp, rcx 61 | mov dword ptr [rsp], edx 62 | add rsp, rcx 63 | ret 64 | _x86push ENDP 65 | 66 | END 67 | -------------------------------------------------------------------------------- /X86Call.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | * X86Call Library 1.0.0.0 4 | * 5 | * Copyright (c) 2016 rrrfff 6 | * https://github.com/rrrfff/X86Call 7 | * 8 | * This program is free software: you can redistribute it and/or modify 9 | * it under the terms of the GNU Lesser General Public License as published 10 | * by the Free Software Foundation, either version 3 of the License, or 11 | * (at your option) any later version. 12 | * 13 | * This program is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU Lesser General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU Lesser General Public License 19 | * along with this program. If not, see . 20 | * 21 | */ 22 | #include "X86Call.h" 23 | #include 24 | #include 25 | #include 26 | 27 | //------------------------------------------------------------------------- 28 | 29 | extern "C" DWORD32 _x86call(); 30 | extern "C" DWORD64 _x86push(DWORD32 offset, DWORD32 val); 31 | 32 | //------------------------------------------------------------------------- 33 | 34 | DWORD32 __cdecl X86Call(DWORD32 func, int argc, ...) 35 | { 36 | const DWORD32 rsp_reserved = 32; // avail stack start [esp - rsp_reserved] 37 | _x86push(rsp_reserved + 4, 4 + sizeof(DWORD32) + argc * sizeof(DWORD32)); // arguments count 38 | _x86push(rsp_reserved + 4 + (argc + 1) * sizeof(DWORD32), func); // function 39 | va_list args; 40 | va_start(args, argc); 41 | while (--argc >= 0) { 42 | _x86push(rsp_reserved + 8 + argc * sizeof(DWORD32), va_arg(args, DWORD32));; 43 | } 44 | va_end(args); 45 | 46 | return _x86call(); 47 | } 48 | -------------------------------------------------------------------------------- /X86Call.h: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | * X86Call Library 1.0.0.0 4 | * 5 | * Copyright (c) 2016 rrrfff 6 | * https://github.com/rrrfff/X86Call 7 | * 8 | * This program is free software: you can redistribute it and/or modify 9 | * it under the terms of the GNU Lesser General Public License as published 10 | * by the Free Software Foundation, either version 3 of the License, or 11 | * (at your option) any later version. 12 | * 13 | * This program is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU Lesser General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU Lesser General Public License 19 | * along with this program. If not, see . 20 | * 21 | */ 22 | #include 23 | 24 | //------------------------------------------------------------------------- 25 | 26 | extern DWORD32 __cdecl X86Call(DWORD32 func, int argc, ...); 27 | -------------------------------------------------------------------------------- /X86Call_deprecated.asm: -------------------------------------------------------------------------------- 1 | X86_Start MACRO 2 | LOCAL xx, rt 3 | call $+5 4 | xx equ $ 5 | mov dword ptr [rsp + 4], 23h 6 | add dword ptr [rsp], rt - xx 7 | retf 8 | rt: 9 | ENDM 10 | 11 | X86_End MACRO 12 | db 6Ah, 33h ; push 33h 13 | db 0E8h, 0, 0, 0, 0 ; call $+5 14 | db 83h, 4, 24h, 5 ; add dword ptr [esp], 5 15 | db 0CBh ; retf 16 | ENDM 17 | 18 | .data 19 | brsp qword 0 20 | brdi qword 0 21 | brbp qword 0 22 | brax qword 0 23 | 24 | .code 25 | _x86call PROC 26 | mov rax, offset x86start 27 | jmp x86ret 28 | 29 | x86start: 30 | mov brsp, rsp 31 | mov brdi, rdi 32 | mov brbp, rbp 33 | 34 | X86_Start 35 | 36 | mov esp, 11111111h 37 | mov ebp, esp 38 | db 40h dup(90h) 39 | db 89h, 04h, 24h ;mov dword ptr [esp], eax 40 | 41 | X86_End 42 | 43 | mov rax, brax 44 | mov rbp, brbp 45 | mov rdi, brdi 46 | mov rsp, brsp 47 | 48 | x86ret: 49 | ret 50 | _x86call ENDP 51 | 52 | _rsp PROC 53 | mov rax, rsp 54 | sub rax, 8 ;reserved for switch 55 | ret 56 | _rsp ENDP 57 | 58 | END 59 | -------------------------------------------------------------------------------- /X86Call_deprecated.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | //------------------------------------------------------------------------- 4 | 5 | #pragma pack(1) 6 | typedef struct X86_STUB 7 | { 8 | char op_rsp[3]; // rsp 9 | DWORD addr_rsp; 10 | char op_rdi[3]; // rdi 11 | DWORD addr_rdi; 12 | char op_rbp[3]; // rbp 13 | DWORD addr_rbp; 14 | 15 | // x86 start 16 | char op_call_1[5]; // call next line 17 | char op_mov_23h[8]; // mov dword ptr [rsp+4],23h 18 | char op_add_10h[7]; // add dword ptr [rsp],10h 19 | char op_retf_1[1]; // retf 20 | 21 | // x86 code 22 | char op_esp[1]; // mov esp, 11111111h 23 | DWORD addr_esp; 24 | char op_ebp[2]; // mov ebp, esp 25 | char op_nop[0x40]; // dynamicly generated code 26 | char op_eax_rev[3]; // mov dword ptr ss:[esp], eax 27 | 28 | // x86 end 29 | char op_push_33h[2]; // push 33h 30 | char op_call_2[5]; // call next line 31 | char op_add_5[4]; // add dword ptr[rsp], 5 32 | char op_retf_2[1]; // retf 33 | 34 | char op_rax_rev[3]; // rax rev 35 | DWORD addr_rax_rev; 36 | char op_rbp_rev[3]; // rbp rev 37 | DWORD addr_rbp_rev; 38 | char op_rdi_rev[3]; // rdi rev 39 | DWORD addr_rdi_rev; 40 | char op_rsp_rev[3]; // rsp rev 41 | DWORD addr_rsp_rev; 42 | 43 | char op_ret; // ret 44 | 45 | public: 46 | typedef struct X86_STACK 47 | { 48 | DWORD64 rax; // x86 return value 49 | DWORD64 rbp; 50 | DWORD64 rdi; 51 | DWORD64 rsp; 52 | } *PX86_STACK; 53 | 54 | X86_STUB *reloc(DWORD64 esp) { 55 | assert(this != nullptr); 56 | auto stack = reinterpret_cast(esp - sizeof(X86_STACK)); 57 | 58 | this->addr_rsp = static_cast(reinterpret_cast(&stack->rsp) - reinterpret_cast(&this->op_rdi)); 59 | this->addr_rdi = static_cast(reinterpret_cast(&stack->rdi) - reinterpret_cast(&this->op_rbp)); 60 | this->addr_rbp = static_cast(reinterpret_cast(&stack->rbp) - reinterpret_cast(&this->op_call_1)); 61 | this->addr_rax_rev = static_cast(reinterpret_cast(&stack->rax) - reinterpret_cast(&this->op_rbp_rev)); 62 | this->addr_rbp_rev = static_cast(reinterpret_cast(&stack->rbp) - reinterpret_cast(&this->op_rdi_rev)); 63 | this->addr_rdi_rev = static_cast(reinterpret_cast(&stack->rdi) - reinterpret_cast(&this->op_rsp_rev)); 64 | this->addr_rsp_rev = static_cast(reinterpret_cast(&stack->rsp) - reinterpret_cast(&this->op_ret)); 65 | this->addr_esp = static_cast(esp - sizeof(X86_STACK)); 66 | return this; 67 | } 68 | } *PX86_STUB; 69 | #pragma pack() 70 | 71 | //------------------------------------------------------------------------- 72 | 73 | static PX86_STUB AllocateX86Stack(_Out_ DWORD64 *stackBase, _In_opt_ DWORD64 sp = 0x10000ULL, _In_opt_ DWORD64 size = 0x10000ULL) 74 | { 75 | if (sp == 0) goto __alloc_random_address; 76 | 77 | while (sp < 0xFFFFFFFFULL) { 78 | MEMORY_BASIC_INFORMATION m; 79 | VirtualQuery(reinterpret_cast(sp), &m, sizeof(m)); 80 | if (m.State != MEM_FREE) { 81 | // 64kb aligned 82 | if (m.AllocationBase && m.RegionSize) { 83 | sp = reinterpret_cast(m.AllocationBase) + Utility::round_up(m.RegionSize, 0x10000ULL); 84 | } else { 85 | sp += 0x10000ULL; 86 | } //if 87 | 88 | continue; 89 | } //if 90 | 91 | __alloc_random_address: 92 | auto p = VirtualAlloc(reinterpret_cast(sp), size, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); 93 | if (p != nullptr) { 94 | *stackBase = reinterpret_cast(p) + size; 95 | return reinterpret_cast(p); 96 | } //if 97 | } //for 98 | 99 | return nullptr; 100 | } 101 | 102 | //------------------------------------------------------------------------- 103 | 104 | extern "C" LPVOID _x86call(); 105 | extern "C" DWORD64 _rsp(); 106 | 107 | //------------------------------------------------------------------------- 108 | 109 | extern "C" DWORD32 __cdecl X86Call(DWORD64 func, bool stdcall, int argc, ...) 110 | { 111 | PX86_STUB x86; 112 | DWORD64 stack; 113 | BOOL isWow64; 114 | IsWow64Process(GetCurrentProcess(), &isWow64); 115 | if (isWow64) { 116 | x86 = AllocateX86Stack(&stack, 0, sizeof(*x86)); 117 | stack = _rsp(); 118 | } else { 119 | x86 = AllocateX86Stack(&stack); 120 | } //if 121 | 122 | memcpy(x86, _x86call(), sizeof(*x86)); 123 | x86->reloc(stack); 124 | 125 | auto nops = x86->op_nop; 126 | auto insc = argc * 5; 127 | auto espc = static_cast(argc * sizeof(DWORD32)); 128 | 129 | va_list args; 130 | va_start(args, argc); 131 | while (--argc >= 0) { 132 | nops[argc * 5] = '\x68'; // x86 push 133 | *reinterpret_cast(&nops[argc * 5 + 1]) = va_arg(args, DWORD32); 134 | } 135 | va_end(args); 136 | 137 | //nops[insc++] = '\xCC'; 138 | 139 | nops[insc] = '\xE8'; // x86 call 140 | *reinterpret_cast(&nops[insc + 1]) = static_cast(func - reinterpret_cast(&nops[insc + 5])); 141 | insc += 5; 142 | 143 | if (!stdcall){ 144 | nops[insc] = '\x83'; // add esp 145 | nops[insc + 1] = '\xC4'; 146 | nops[insc + 2] = espc; 147 | insc += 3; 148 | } //if 149 | 150 | assert(insc < _countof(x86->op_nop)); 151 | if (_countof(x86->op_nop) - insc >= 6){ 152 | nops[insc] = '\xEB'; // skip nop, jmp 153 | nops[insc + 1] = static_cast(x86->op_eax_rev - &nops[insc + 2]); 154 | //insc += 2; 155 | } //if 156 | 157 | auto ret = reinterpret_cast(x86)(); 158 | if (x86) { 159 | VirtualFree(x86, 0, MEM_RELEASE); 160 | } //if 161 | return static_cast(reinterpret_cast(ret)); 162 | } 163 | 164 | //------------------------------------------------------------------------- 165 | 166 | extern "C" __declspec(dllexport) DWORD64 __stdcall X86CallTest(DWORD64 x86_func) 167 | { 168 | return X86Call(x86_func, false, 3, 2, 4, 6); 169 | } 170 | 171 | //------------------------------------------------------------------------- 172 | 173 | int WINAPI DllMain( _In_ HINSTANCE, _In_ DWORD, _In_ LPVOID) 174 | { 175 | return TRUE; 176 | } 177 | --------------------------------------------------------------------------------