Skip to content

Instantly share code, notes, and snippets.

@poizan42
Last active January 4, 2020 23:26
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save poizan42/8ff01d3df80b1663afef775ca812b699 to your computer and use it in GitHub Desktop.
Save poizan42/8ff01d3df80b1663afef775ca812b699 to your computer and use it in GitHub Desktop.
Demonstration of running 32-bit code on WSL
SYS_EXIT_64 equ 60
SYS_EXIT_32 equ 1
section .data ; this is copied to a location below 2^32
global test32call_len
global test32call
BITS 64
test32call_len:
dq test32_end - test32call
test32call:
mov rax, rsp
mov rsp, rdi ; new stack
push rax ; save old stack
; This is for the return back from 32-bit land
mov eax, cs
lea rcx, [rel call32ret]
shld rax, rax, 32
or rax,rcx
push rax
; This is for the actual jump since x64 doesn't support far calls without a fixed address
push 0x23
lea rax, [rel start32]
push rax
o64 retf ; jump to 32-bit land
call32ret:
pop rsp ; restore old stack
ret
BITS 32
start32:
; Payload goes here
; == Note: Attempting a syscall here will make the process exit immediately with code 1 ==
; mov eax,SYS_EXIT_32
; mov ebx,1337
; int 0x80
mov eax, 0x003C
daa ; this is invalid in 64-bit mode
; eax should now be == 0x42 = 66
retf ; back to 64-bit land
test32_end:
#include <stddef.h>
#include <stdio.h>
#include <string.h>
#include <sys/mman.h>
extern void* test32call;
extern size_t test32call_len;
typedef int (*call32fn_t)(void* new_sp);
int main(int argc, char* argv[])
{
void* call32mem = mmap(0, test32call_len, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE | MAP_32BIT, -1, 0);
printf("call32 allocated at %p\n", call32mem);
memcpy(call32mem, &test32call, test32call_len);
printf("call32 code copied\n");
mprotect(call32mem, test32call_len, PROT_READ | PROT_EXEC);
printf("call32 code set executeable\n");
size_t stacksize = 1024*1024;
void* newstack = mmap(0, stacksize, PROT_READ | PROT_WRITE,
MAP_ANONYMOUS | MAP_PRIVATE | MAP_32BIT | MAP_STACK, -1, 0);
printf("32-bit stack allocated at %p\n", newstack);
call32fn_t call32 = (call32fn_t)call32mem;
int result = call32((char*)newstack + stacksize);
printf("Result from 32-bit code: %d\n", result);
return 0;
}
call32test: call32test.o call32.o
gcc -g $^ -o $@
call32test.o: call32test.c
gcc -g -c $< -o $@
call32.o: call32.asm
nasm -f elf64 call32.asm -o call32.o
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment