├── 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 |
--------------------------------------------------------------------------------