Last active
January 4, 2020 23:26
-
-
Save poizan42/8ff01d3df80b1663afef775ca812b699 to your computer and use it in GitHub Desktop.
Demonstration of running 32-bit code on WSL
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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: |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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