diff options
Diffstat (limited to 'src/tools')
| -rw-r--r-- | src/tools/box32stack.c | 137 | ||||
| -rw-r--r-- | src/tools/box64stack.c | 10 | ||||
| -rw-r--r-- | src/tools/callback.c | 306 |
3 files changed, 369 insertions, 84 deletions
diff --git a/src/tools/box32stack.c b/src/tools/box32stack.c new file mode 100644 index 00000000..441b27ab --- /dev/null +++ b/src/tools/box32stack.c @@ -0,0 +1,137 @@ +#include <stdio.h> +#include <stdlib.h> +#include <stdint.h> +#include <string.h> +#include <sys/mman.h> + +#include "box64stack.h" +#include "box64context.h" +#include "elfloader.h" +#include "debug.h" +#include "emu/x64emu_private.h" +#include "emu/x64run_private.h" +#include "auxval.h" +#include "custommem.h" +#include "box32.h" + +static void PushString32(x64emu_t *emu, const char* s) +{ + int sz = strlen(s) + 1; + // round to 4 bytes boundary + R_ESP -= sz; + memcpy(from_ptrv(R_ESP), s, sz); +} + +static void Push32_32(x64emu_t *emu, uint32_t v) +{ + R_ESP -= 4; + *((uint32_t*)from_ptr(R_ESP)) = v; +} + + +EXPORTDYN +void SetupInitialStack32(x64emu_t *emu) +{ + // start with 0 + Push32_32(emu, 0); + // push program executed + PushString32(emu, emu->context->argv[0]); + uintptr_t p_arg0 = from_ptr(R_ESP); + // push envs + uintptr_t p_envv[emu->context->envc]; + for (int i=emu->context->envc-1; i>=0; --i) { + PushString32(emu, emu->context->envv[i]); + p_envv[i] = from_ptr(R_ESP); + } + // push args, also, free the argv[] string and point to the one in the main stack + uintptr_t p_argv[emu->context->argc]; + for (int i=emu->context->argc-1; i>=0; --i) { + PushString32(emu, emu->context->argv[i]); + p_argv[i] = R_ESP; + free(emu->context->argv[i]); + emu->context->argv[i] = (char*)p_argv[i]; + } + // align + uintptr_t tmp = from_ptr(R_ESP)&~(emu->context->stackalign-1); + memset((void*)tmp, 0, from_ptr(R_ESP)-tmp); + R_ESP=to_ptr(tmp); + + // push some AuxVector stuffs + PushString32(emu, "i686"); + uintptr_t p_i686 = from_ptr(R_ESP); + uintptr_t p_random = real_getauxval(25); + if(!p_random) { + for (int i=0; i<4; ++i) + Push32_32(emu, random()); + p_random = from_ptr(R_ESP); + } + // align + tmp = (R_ESP)&~(emu->context->stackalign-1); + memset((void*)tmp, 0, from_ptr(R_ESP)-tmp); + R_ESP=tmp; + + // push the AuxVector themselves + /* + 00: 00000000 + 03: 08048034 + 04: 00000020 + 05: 0000000b + 06: 00001000 + 07: f7fc0000 + 08: 00000000 + 09: 08049060 + 11: 000003e8 + 12: 000003e8 + 13: 000003e8 + 14: 000003e8 + 15: ffd8aa5b/i686 + 16: bfebfbff + 17: 00000064 + 23: 00000000 + 25: ffd8aa4b + 26: 00000000 + 31: ffd8bfeb/./testAuxVec + 32: f7fbfb40 + 33: f7fbf000 + */ + Push32_32(emu, 0); Push32_32(emu, 0); //AT_NULL(0)=0 + //Push32_32(emu, ); Push32_32(emu, 3); //AT_PHDR(3)=address of the PH of the executable + //Push32_32(emu, ); Push32_32(emu, 4); //AT_PHENT(4)=size of PH entry + //Push32_32(emu, ); Push32_32(emu, 5); //AT_PHNUM(5)=number of elf headers + Push32_32(emu, box64_pagesize); Push32_32(emu, 6); //AT_PAGESZ(6) + //Push32_32(emu, real_getauxval(7)); Push32_32(emu, 7); //AT_BASE(7)=ld-2.27.so start (in memory) + Push32_32(emu, 0); Push32_32(emu, 8); //AT_FLAGS(8)=0 + Push32_32(emu, R_EIP); Push32_32(emu, 9); //AT_ENTRY(9)=entrypoint + Push32_32(emu, from_ulong(real_getauxval(11))); Push32_32(emu, 11); //AT_UID(11) + Push32_32(emu, from_ulong(real_getauxval(12))); Push32_32(emu, 12); //AT_EUID(12) + Push32_32(emu, from_ulong(real_getauxval(13))); Push32_32(emu, 13); //AT_GID(13) + Push32_32(emu, from_ulong(real_getauxval(14))); Push32_32(emu, 14); //AT_EGID(14) + Push32_32(emu, p_i686); Push32_32(emu, 15); //AT_PLATFORM(15)=&"i686" + // Push HWCAP: + // FPU: 1<<0 ; VME: 1<<1 ; DE : 1<<2 ; PSE: 1<<3 ; TSC: 1<<4 ; MSR: 1<<5 ; PAE: 1<<6 ; MCE: 1<<7 + // CX8: 1<<8 ; APIC:1<<9 ; SEP: 1<<11; MTRR:1<<12; PGE: 1<<13; MCA: 1<<14; CMOV:1<<15 + // FCMOV:1<<16; MMX: 1<<23 + // OSFXR:1<<24; XMM: 1<<25;XMM2: 1<<26; AMD3D:1<<31 + Push32_32(emu, (1<<0) | (1<<1) | (1<<2) | (1<<3) | (1<<4) | (1<<8) | (1<<15) | (1<<16) | (1<<23) | (1<<25) | (1<<26)); + Push32_32(emu, 16); //AT_HWCAP(16)=... + //Push32_32(emu, sysconf(_SC_CLK_TCK)); Push32_32(emu, 17); //AT_CLKTCK(17)=times() frequency + Push32_32(emu, from_ulong(real_getauxval(23))); Push32_32(emu, 23); //AT_SECURE(23) + Push32_32(emu, p_random); Push32_32(emu, 25); //AT_RANDOM(25)=p_random + Push32_32(emu, 0); Push32_32(emu, 26); //AT_HWCAP2(26)=0 + Push32_32(emu, p_arg0); Push32_32(emu, 31); //AT_EXECFN(31)=p_arg0 + Push32_32(emu, emu->context->vsyscall); Push32_32(emu, 32); //AT_SYSINFO(32)=vsyscall + //Push32_32(emu, ); Push32_32(emu, 33); //AT_SYSINFO_EHDR(33)=address of vDSO + if(!emu->context->auxval_start) // store auxval start if needed + emu->context->auxval_start = (uintptr_t*)from_ptr(R_ESP); + + // push nil / envs / nil / args / argc + Push32_32(emu, 0); + for (int i=emu->context->envc-1; i>=0; --i) + Push32_32(emu, to_ptr(p_envv[i])); + emu->context->envv32 = R_ESP; + Push32_32(emu, 0); + for (int i=emu->context->argc-1; i>=0; --i) + Push32_32(emu, to_ptr(p_argv[i])); + emu->context->argv32 = R_ESP; + Push32_32(emu, emu->context->argc); +} diff --git a/src/tools/box64stack.c b/src/tools/box64stack.c index 7be31b4d..82dc9a63 100644 --- a/src/tools/box64stack.c +++ b/src/tools/box64stack.c @@ -42,9 +42,19 @@ void PushString(x64emu_t *emu, const char* s) memcpy((void*)R_RSP, s, sz); } +void SetupInitialStack32(x64emu_t *emu) +#ifndef BOX32 + { } +#else + ; +#endif EXPORTDYN void SetupInitialStack(x64emu_t *emu) { + if(box64_is32bits) { + SetupInitialStack32(emu); + return; + } // start with 0 Push64(emu, 0); // push program executed diff --git a/src/tools/callback.c b/src/tools/callback.c index 341a554d..661a3b13 100644 --- a/src/tools/callback.c +++ b/src/tools/callback.c @@ -12,43 +12,74 @@ #include "box64context.h" #include "box64stack.h" #include "dynarec.h" +#ifdef BOX32 +#include "box32.h" +#endif EXPORTDYN uint64_t RunFunction(uintptr_t fnc, int nargs, ...) { x64emu_t *emu = thread_get_emu(); - int align = (nargs>6)?(((nargs-6)&1)):0; - int stackn = align + ((nargs>6)?(nargs-6):0); - - Push64(emu, R_RBP); // push rbp - R_RBP = R_RSP; // mov rbp, rsp + #ifdef BOX32 + if(box64_is32bits) { + Push_32(emu, R_RBP); // push ebp + R_RBP = R_ESP; // mov ebp, esp - R_RSP -= stackn*sizeof(void*); // need to push in reverse order + R_ESP -= nargs*4; // need to push in reverse order - uint64_t *p = (uint64_t*)R_RSP; + ptr_t *p = (ptr_t*)from_ptrv(R_ESP); - va_list va; - va_start (va, nargs); - for (int i=0; i<nargs; ++i) { - if(i<6) { - int nn[] = {_DI, _SI, _DX, _CX, _R8, _R9}; - emu->regs[nn[i]].q[0] = va_arg(va, uint64_t); - } else { - *p = va_arg(va, uint64_t); + va_list va; + va_start (va, nargs); + for (int i=0; i<nargs; ++i) { + *p = va_arg(va, uint32_t); p++; } + va_end (va); + } else + #endif + { + int align = (nargs>6)?(((nargs-6)&1)):0; + int stackn = align + ((nargs>6)?(nargs-6):0); + + Push64(emu, R_RBP); // push rbp + R_RBP = R_RSP; // mov rbp, rsp + + R_RSP -= stackn*sizeof(void*); // need to push in reverse order + + uint64_t *p = (uint64_t*)R_RSP; + + va_list va; + va_start (va, nargs); + for (int i=0; i<nargs; ++i) { + if(i<6) { + int nn[] = {_DI, _SI, _DX, _CX, _R8, _R9}; + emu->regs[nn[i]].q[0] = va_arg(va, uint64_t); + } else { + *p = va_arg(va, uint64_t); + p++; + } + } + va_end (va); } - va_end (va); uintptr_t oldip = R_RIP; DynaCall(emu, fnc); if(oldip==R_RIP) { - R_RSP = R_RBP; // mov rsp, rbp - R_RBP = Pop64(emu); // pop rbp + #ifdef BOX32 + if(box64_is32bits) { + R_RSP = R_EBP; // mov esp, ebp + R_EBP = Pop_32(emu); // pop ebp + } + #endif + { + R_RSP = R_RBP; // mov rsp, rbp + R_RBP = Pop64(emu); // pop rbp + } } - uint64_t ret = R_RAX; + uint64_t ret = box64_is32bits?((uint64_t)R_EAX | ((uint64_t)R_EDX)<<32):R_RAX; return ret; } @@ -61,6 +92,27 @@ uint64_t RunFunctionFmt(uintptr_t fnc, const char* fmt, ...) int ni = 0; int ndf = 0; for (int i=0; fmt[i]; ++i) { + #ifdef BOX32 + if(box64_is32bits) + switch(fmt[i]) { + case 'd': + case 'I': + case 'U': nargs+=2; break; + case 'p': + case 'L': + case 'l': + case 'f': + case 'i': + case 'u': + case 'w': + case 'W': + case 'c': + case 'C': ++nargs; break; + default: + ++nargs; break; + } + else + #endif switch(fmt[i]) { case 'f': case 'd': if(ndf<8) ++ndf; else ++nargs; break; @@ -83,63 +135,116 @@ uint64_t RunFunctionFmt(uintptr_t fnc, const char* fmt, ...) ndf = 0; int align = nargs&1; int stackn = align + nargs; + int sizeof_ptr = sizeof(void*); + #ifdef BOX32 + if(box64_is32bits) { + Push_32(emu, R_EBP); // push ebp + R_RBP = R_ESP; // mov ebp, esp + sizeof_ptr = sizeof(ptr_t); + } else + #endif + { + Push64(emu, R_RBP); // push rbp + R_RBP = R_RSP; // mov rbp, rsp + } - Push64(emu, R_RBP); // push rbp - R_RBP = R_RSP; // mov rbp, rsp - - R_RSP -= stackn*sizeof(void*); // need to push in reverse order - - uint64_t *p = (uint64_t*)R_RSP; - - static const int nn[] = {_DI, _SI, _DX, _CX, _R8, _R9}; - #define GO(c, A, B, B2, C) case c: if(ni<6) emu->regs[nn[ni++]].A[0] = C va_arg(va, B2); else {*p = 0; *((B*)p) = va_arg(va, B2); ++p;}; break; - va_list va; - va_start (va, fmt); - for (int i=0; fmt[i]; ++i) { - switch(fmt[i]) { - case 'f': if(ndf<8) - emu->xmm[ndf++].f[0] = va_arg(va, double); // float are promoted to double in ... - else { - *p = 0; - *((float*)p) = va_arg(va, double); - ++p; - } - break; - case 'd': if(ndf<8) - emu->xmm[ndf++].d[0] = va_arg(va, double); - else { - *((double*)p) = va_arg(va, double); - ++p; - } - break; - GO('p', q, void*, void*, (uintptr_t)) - GO('i', sdword, int, int, ) - GO('u', dword, uint32_t, uint32_t, ) - GO('I', sq, int64_t, int64_t, ) - GO('U', q, uint64_t, uint64_t, ) - GO('L', q, uint64_t, uint64_t, ) - GO('l', sq, int64_t, int64_t, ) - GO('w', sword, int16_t, int, ) - GO('W', word, uint16_t, int, ) - GO('c', sbyte, int8_t, int, ) - GO('C', byte, uint8_t, int, ) - default: - printf_log(LOG_NONE, "Error, unhandled arg %d: '%c' in RunFunctionFmt\n", i, fmt[i]); - if(ni<6) emu->regs[nn[ni++]].q[0] = va_arg(va, uint64_t); else {*p = va_arg(va, uint64_t); ++p;}; - break; + R_RSP -= stackn*sizeof_ptr; // need to push in reverse order + + #ifdef BOX32 + if(box64_is32bits) { + ptr_t *p = (ptr_t*)from_ptrv(R_ESP); + + #define GO(c, B, B2, N) case c: *((B*)p) = va_arg(va, B2); p+=N; break + va_list va; + va_start (va, fmt); + for (int i=0; fmt[i]; ++i) { + switch(fmt[i]) { + GO('f', float, double, 1); + GO('d', double, double, 2); + case 'p': *((ptr_t*)p) = to_ptrv(va_arg(va, void*)); p+=1; break; + GO('i', int, int, 1); + GO('u', uint32_t, uint32_t, 1); + GO('I', int64_t, int64_t, 2); + GO('U', uint64_t, uint64_t, 2); + GO('L', uint32_t, uint64_t, 1); // long are 64bits on 64bits system + GO('l', int32_t, int64_t, 1); // but 32bits on 32bits system + GO('w', int16_t, int, 1); + GO('W', uint16_t, int, 1); + GO('c', int8_t, int, 1); + GO('C', uint8_t, int, 1); + default: + printf_log(LOG_NONE, "Error, unhandled arg %d: '%c' in RunFunctionFmt\n", i, fmt[i]); + *p = va_arg(va, uint32_t); + ++p; + break; + } } + #undef GO + va_end (va); + } else + #endif + { + uint64_t *p = (uint64_t*)R_RSP; + + static const int nn[] = {_DI, _SI, _DX, _CX, _R8, _R9}; + #define GO(c, A, B, B2, C) case c: if(ni<6) emu->regs[nn[ni++]].A[0] = C va_arg(va, B2); else {*p = 0; *((B*)p) = va_arg(va, B2); ++p;}; break; + va_list va; + va_start (va, fmt); + for (int i=0; fmt[i]; ++i) { + switch(fmt[i]) { + case 'f': if(ndf<8) + emu->xmm[ndf++].f[0] = va_arg(va, double); // float are promoted to double in ... + else { + *p = 0; + *((float*)p) = va_arg(va, double); + ++p; + } + break; + case 'd': if(ndf<8) + emu->xmm[ndf++].d[0] = va_arg(va, double); + else { + *((double*)p) = va_arg(va, double); + ++p; + } + break; + GO('p', q, void*, void*, (uintptr_t)) + GO('i', sdword, int, int, ) + GO('u', dword, uint32_t, uint32_t, ) + GO('I', sq, int64_t, int64_t, ) + GO('U', q, uint64_t, uint64_t, ) + GO('L', q, uint64_t, uint64_t, ) + GO('l', sq, int64_t, int64_t, ) + GO('w', sword, int16_t, int, ) + GO('W', word, uint16_t, int, ) + GO('c', sbyte, int8_t, int, ) + GO('C', byte, uint8_t, int, ) + default: + printf_log(LOG_NONE, "Error, unhandled arg %d: '%c' in RunFunctionFmt\n", i, fmt[i]); + if(ni<6) emu->regs[nn[ni++]].q[0] = va_arg(va, uint64_t); else {*p = va_arg(va, uint64_t); ++p;}; + break; + } + } + #undef GO + va_end (va); } - va_end (va); uintptr_t oldip = R_RIP; DynaCall(emu, fnc); if(oldip==R_RIP) { - R_RSP = R_RBP; // mov rsp, rbp - R_RBP = Pop64(emu); // pop rbp + #ifdef BOX32 + if(box64_is32bits) { + R_RSP = R_EBP; // mov esp, ebp + R_RBP = Pop_32(emu); // pop ebp + } + #endif + { + R_RSP = R_RBP; // mov rsp, rbp + R_RBP = Pop64(emu); // pop rbp + } } - uint64_t ret = R_RAX; + uint64_t ret = box64_is32bits?((uint64_t)R_EAX | ((uint64_t)R_EDX)<<32):R_RAX; return ret; } @@ -148,6 +253,10 @@ EXPORTDYN uint64_t RunSafeFunction(uintptr_t fnc, int nargs, ...) { x64emu_t * emu = thread_get_emu(); + if(box64_is32bits) { + printf_log(LOG_NONE, "Calling RunSafeFunction in 32bits\n"); + abort(); + } int align = (nargs>6)?(((nargs-6)&1)):0; int stackn = align + ((nargs>6)?(nargs-6):0); @@ -222,28 +331,48 @@ uint64_t RunSafeFunction(uintptr_t fnc, int nargs, ...) EXPORTDYN uint64_t RunFunctionWithEmu(x64emu_t *emu, int QuitOnLongJump, uintptr_t fnc, int nargs, ...) { - int align = (nargs>6)?(((nargs-6)&1)):0; - int stackn = align + ((nargs>6)?(nargs-6):0); - - Push64(emu, R_RBP); // push rbp - R_RBP = R_RSP; // mov rbp, rsp + #ifdef BOX32 + if(box64_is32bits) { + Push_32(emu, R_RBP); // push ebp + R_RBP = R_ESP; // mov ebp, esp - R_RSP -= stackn*sizeof(void*); // need to push in reverse order + R_ESP -= nargs*4; // need to push in reverse order - uint64_t *p = (uint64_t*)R_RSP; + ptr_t *p = (ptr_t*)from_ptrv(R_ESP); - va_list va; - va_start (va, nargs); - for (int i=0; i<nargs; ++i) { - if(i<6) { - int nn[] = {_DI, _SI, _DX, _CX, _R8, _R9}; - emu->regs[nn[i]].q[0] = va_arg(va, uint64_t); - } else { - *p = va_arg(va, uint64_t); + va_list va; + va_start (va, nargs); + for (int i=0; i<nargs; ++i) { + *p = va_arg(va, uint32_t); p++; } + va_end (va); + } else + #endif + { + int align = (nargs>6)?(((nargs-6)&1)):0; + int stackn = align + ((nargs>6)?(nargs-6):0); + + Push64(emu, R_RBP); // push rbp + R_RBP = R_RSP; // mov rbp, rsp + + R_RSP -= stackn*sizeof(void*); // need to push in reverse order + + uint64_t *p = (uint64_t*)R_RSP; + + va_list va; + va_start (va, nargs); + for (int i=0; i<nargs; ++i) { + if(i<6) { + int nn[] = {_DI, _SI, _DX, _CX, _R8, _R9}; + emu->regs[nn[i]].q[0] = va_arg(va, uint64_t); + } else { + *p = va_arg(va, uint64_t); + p++; + } + } + va_end (va); } - va_end (va); uintptr_t oldip = R_RIP; int old_quit = emu->quit; @@ -256,20 +385,29 @@ uint64_t RunFunctionWithEmu(x64emu_t *emu, int QuitOnLongJump, uintptr_t fnc, in if(oldip==R_RIP) { R_RSP = R_RBP; // restore stack only if EIP is the one expected (else, it means return value is not the one expected) - R_RBP = Pop64(emu); //Pop EBP + #ifdef BOX32 + if(box64_is32bits) + R_RBP = Pop_32(emu); //Pop EBP + else + #endif + R_RBP = Pop64(emu); //Pop EBP } emu->quit = old_quit; emu->flags.quitonlongjmp = oldlong; - return R_RAX; + return box64_is32bits?((uint64_t)R_EAX | ((uint64_t)R_EDX)<<32):R_RAX;; } EXPORTDYN uint64_t RunFunctionWindows(uintptr_t fnc, int nargs, ...) { x64emu_t *emu = thread_get_emu(); + if(box64_is32bits) { + printf_log(LOG_NONE, "Calling RunFunctionWindows in 32bits\n"); + abort(); + } int align = (nargs>4)?(((nargs-4)&1)):0; int stackn = align + ((nargs>4)?(nargs-4):0); |