简体   繁体   中英

Why can't i exit from shellcode with a syscall?

I try to make a Programm where you put in some assembled assembly in hex and run it. With simple instructions like int3 it works, but when I try to exit from the programm with a syscall it doesnt work. I assembled it with rasm2

mov eax, 1
mov ebx, 12
int 0x80

and then put it as an argument ./Programm b801000000bb0c000000cd80 1 but i get a segfault.

Here is my code:

#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <sys/mman.h>

char *base16dec(char *b16str) {
  size_t stingrlength = strlen(b16str);
  char *decodedstr = malloc(stingrlength / 2);
  for (size_t i = 0; i < stingrlength; i += 2) {
    u_int8_t num = 0;
    char stringIn[3];
    stringIn[0] = b16str[i];
    stringIn[1] = b16str[i+1];
    stringIn[2] = 0;
    sscanf(stringIn, "%hhx", &num);
    decodedstr[i/2] = (char) num;
  }
  return decodedstr;
}

this decodes the hex string

int main(int argc, char *argv[]) {
  char *dirstr = "XXXXXX";
  char dir[7];
  strcpy(dir, dirstr);
  int fd = mkstemp(dir);
  if (fd == -1) {
    dirstr = "/tmp/XXXXXX";
    char dir[12];
    strcpy(dir, dirstr);
    fd = mkstemp(dir);
  }
  unlink(dir);

this creates the tmp file where the assembly is stored

  char *stringIn;
  if (argc == 2) {
    stringIn = malloc(strlen(argv[1]));
    strcpy(stringIn, argv[1]);
  } else if (argc == 3) {
    u_int8_t num = 0;
    sscanf(argv[2], "%hhu", &num);
    if (num == 1) {
      char *done = base16dec(argv[1]);
      stringIn = malloc(strlen(done));
      strcpy(stringIn, done);
    } else {
      stringIn = malloc(strlen(argv[1]));
      strcpy(stringIn, argv[1]);
    }
  } else {
    stringIn = malloc(1024);
    scanf("%s", stringIn);
    char *done = base16dec(stringIn);
    stringIn = malloc(strlen(done));
    strcpy(stringIn, done);
  }

this parses and copies the input to stringIn

  ftruncate(fd, strlen(stringIn));
  u_int8_t *code = mmap(NULL, strlen(stringIn), PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE , fd, 0);

this expands the tmp file and makes it executable and creates a pointer to it named code

  for (int i = 0; i < 1024; i++) {
    code[i] = (u_int8_t) stringIn[i];
  }

this copies the assembly bytes into code

  #if __x86_64__
  __asm__(
    "mov %0, %%rbx\n"
    "jmp *%%rbx"
    :
    : "g" (code)
    : "memory"
  );
  #elif __i386__
  __asm__(
    "mov %0, %%ebx\n"
    "jmp *%%ebx"
    :
    : "r" (code)
  );
  #else
  #endif

this jumps to the the assembly

  return 0;
}

EDIT:

I can't debug the shellcode using gdb

I use 64bit Linux Mint

I tried to copy 0 using strcpy

Since this is a shellcode you can't have null bytes. In your code you have 2 movs with immediates that are padded to 32-bits

mov eax, 1
mov ebx, 12

Which encodes as B801 000000 BB0C 000000 , when C hits the null bytes it thinks the string has ended so it only ends up copying part of the instruction and then it executes garbage.

Instead you'll need to use:

xor eax, eax
inc eax
xor ebx, ebx
mov bl, 12

This will provide the values you want for your system call and does not encode as any null bytes.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM