Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Code segment trickery / "Heaven's Gate" on Linux
global call_64_from_64
global call_32_from_64
global call_32_from_32
section .text
call_64_from_64:
mov rsi, rdi
mov rax, 1
mov rdi, 1
mov rdx, 44
syscall
ret
call_32_from_64:
push rbx
mov rax, 4
mov rbx, 1
mov rcx, rdi
mov rdx, 44
int 0x80
pop rbx
ret
call_32_from_32:
push rbx
; Stash stack
mov [_stack_stash], rsp
lea rsp, [rdi + 0x80]
; Stash "how to get back"
mov r9, 0x3300000000
or r9, _call32_return_64
push r9
push _call32_return_32
; Set up far return/jump
push 0x23
push _call_32_from_32
db 0x48 ; REX
retf
_call32_return_64:
mov rsp, [_stack_stash]
pop rbx
ret
section .bss
_stack_stash: resq 1
BITS 32
section .text
_call32_return_32:
add esp, 4
retf
_call_32_from_32:
mov eax, 4
mov ebx, 1
mov ecx, edi
mov edx, 44
int 0x80
ret
// nasm -f elf64 asmbits.asm
// gcc -no-pie -ggdb -Wall -O2 -o llgames llgames.c asmbits.o
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <sys/mman.h>
extern void call_64_from_64(void *buf);
extern void call_32_from_64(void *buf);
extern void call_32_from_32(void *buf);
int main(int argc, char **argv) {
printf("Hello world!\n");
char *buf = mmap(0, 4096, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_32BIT, -1, 0);
if (buf == MAP_FAILED) {
perror("mmap");
return -1;
}
printf("buf = %p\n", buf);
strcpy(buf + 0x0, "Hello from 64-bit syscall from 64-bit code\n");
strcpy(buf + 0x100, "Hello from 32-bit syscall from 64-bit code\n");
// strcpy(buf + 0x200, "Hello from 64-bit syscall from 32-bit code\n");
strcpy(buf + 0x300, "Hello from 32-bit syscall from 32-bit code\n");
call_64_from_64(buf + 0x0);
call_32_from_64(buf + 0x100);
call_32_from_32(buf + 0x300);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment