Почему я не могу выйти из шелл-кода с помощью системного вызова? - PullRequest
0 голосов
/ 11 мая 2019

Я пытаюсь создать Программу, в которую вы помещаете какую-то собранную сборку в hex и запускаете ее. С простыми инструкциями, такими как int3, это работает, но когда я пытаюсь выйти из программы с помощью системного вызова, это не работает. Я собрал его с rasm2

mov eax, 1
mov ebx, 12
int 0x80

, а затем поставить его в качестве аргумента ./Programm b801000000bb0c000000cd80 1 но я получаю сегфо.

Вот мой код:

#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;
}

это декодирует шестнадцатеричную строку

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);

это создает файл tmp, в котором хранится сборка

  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);
  }

это анализирует и копирует ввод в stringIn

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

это расширяет файл tmp, делает его исполняемым и создает указатель на него с именем code

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

копирует байты сборки в 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

это переход к сборке

  return 0;
}

EDIT:

Я не могу отладить шелл-код с помощью gdb

Я использую 64-битную Linux Mint

Я пытался скопировать 0, используя strcpy

1 Ответ

1 голос
/ 17 мая 2019

Поскольку это шелл-код, вы не можете иметь нулевые байты.В вашем коде у вас есть 2 mov с немедленными значениями, которые дополняются 32-битными

mov eax, 1
mov ebx, 12

, что кодирует как B801 000000 BB0C 000000 , когда C достигает нуляБайт думает, что строка завершилась, поэтому он копирует только часть инструкции и выполняет мусор.

Вместо этого вам нужно будет использовать:

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

Это обеспечит значения, которые вы хотите для вашего системного вызова, и не будет кодироваться как нулевые байты.

...