Загрузка необработанного кода из программы C

Я пишу программу, которая загружает и выполняет код из файла. Но у меня возникла проблема: системный вызов «запись» не работает. Код успешно загружается и выполняется, но не отображает текст на экране.

Программа, загружающая код:

#include < stdio.h >
#include < stdlib.h >

int main(int argc,char* argv[])
{
    unsigned int f_size = 0;
    unsigned char* code_buf = NULL;
    void (*func_call)(void) = NULL;

    if(argc < 2) 
    {
        printf("Usage: %s <FILE>\n",argv[0]);
        return 1;
    }

    FILE* fp = fopen(argv[1],"rb");
    if(!fp)
    {
        printf("Error while opening this file: %s\n",argv[1]);
        return 1;
    }

    unsigned int fsize = 0;
    fseek(fp,0,SEEK_END);
    fsize = ftell(fp);
    fseek(fp,0,SEEK_SET);
    if(fsize < 4)
    {
        printf("Code size must be > 4 bytes\n");
        return 1;
    }

    code_buf = (unsigned char*) malloc(sizeof(unsigned char)*fsize);
    if(fread(code_buf,fsize,1,fp)<1)
    {
        printf("Error while reading file: %s\n",argv[1]);
        free(code_buf);
        return 1;
    }
    func_call = (void (*)(void)) code_buf;

    printf("[EXEC] Binary is loaded\n"
           "\tFirst 2 bytes: 0x%x 0x%x\n"
           "\tLast 2 bytes: 0x%x 0x%x\n",
           code_buf[0],code_buf[1],
           code_buf[fsize-2],code_buf[fsize-1]);
    printf("[EXEC] Starting code...\n");
    (*func_call)();
    printf("[EXEC] Code executed!\n");

    free(code_buf);

    return 0;
}

код, который я пытаюсь выполнить этой программой (test.s):

.text
    movl    $4, %eax
    movl    $1, %ebx
    movl    $str, %ecx
    movl    $5, %edx
    int     $0x80
    jmp end
    str:
        .string "test\n"
    end:
    ret

Вот как я его компилирую:

 gcc -c test.s
 objcopy -O binary test.o test.bin

Решено, спасибо @Christoph

Есть рабочий код:

.text
    call start
    str:
        .string "test\n"
    start:
    movl    $4, %eax
    movl    $1, %ebx
    pop     %ecx
    movl    $5, %edx
    int     $0x80
    ret

person Alexey    schedule 23.02.2011    source источник
comment
когда вы говорите, что текст не отображается, вы имеете в виду, что он не печатает тест или даже не печатает строки [EXEC]?   -  person AShelly    schedule 23.02.2011
comment
+1 интересный вопрос, хотя я надеюсь, что он не используется для чего-то злонамеренного..   -  person BlueRaja - Danny Pflughoeft    schedule 23.02.2011
comment
помогает ли добавить -S к вызову objcopy?   -  person Christoph    schedule 23.02.2011
comment
-S не должно помочь - код ошибочен...   -  person Christoph    schedule 23.02.2011
comment
›когда вы говорите, что текст не отображается, вы имеете в виду, что он не печатает тест или даже не печатает строки [EXEC]? должен быть тест между [EXEC]   -  person Alexey    schedule 23.02.2011


Ответы (4)


Ваш подход не может работать: шеллкод должен быть независимым от позиции, но ваш код ссылается на абсолютный адрес str. Безусловный переход также может быть относительным или абсолютным: убедитесь, что вы получили относительную версию (коды операций EB и E9 на x86).

См. Техника написания переносимого кода оболочки для получения дополнительной информации.

person Christoph    schedule 23.02.2011
comment
Да, когда вы обычно компонуете и загружаете код (например, с помощью dlopen), одна из вещей, которую делает загрузчик, — это исправление ссылок на адреса в коде, чтобы они соответствовали тому месту, где они фактически загружаются в память. Загружая и выполняя код вручную, вам придется либо делать эти исправления вручную, либо придерживаться отказа от использования абсолютных адресов. - person bdk; 23.02.2011
comment
@Alexey: вы можете использовать call, чтобы поместить указатель инструкции в стек и таким образом получить адрес вашего шелл-кода (см. Листинг 11.1 в связанном документе) - person Christoph; 23.02.2011
comment
дайте ссылку, сэр :( - person VIII; 27.08.2020

Вы не указываете информацию о своем процессоре, но вы можете работать с битом NX. . Я бы ожидал, что ваш код выдаст SEGFAULT, а не завершится.

Именно это происходит на моем компьютере (Linux 2.6.32-28-generic #55-Ubuntu SMP Mon 10 Jan 23:42:43 UTC 2011 x86_64 GNU/Linux), работающем на Intel Xeon E5410.

person NPE    schedule 23.02.2011
comment
У меня отключен бит NX в ядре. Код всегда выполняется успешно, я запускал его около 30 раз (я также проверял его в gdb) - person Alexey; 23.02.2011

Одна вещь: вы должны открыть файл как двоичный файл.

FILE* fp = fopen(argv[1],"rb"); 
person AShelly    schedule 23.02.2011
comment
не имеет значения в системах POSIX: символ «b» не должен иметь никакого эффекта, но разрешен для соответствия стандарту ISO C. - person Christoph; 23.02.2011

Почему вы не используете файлы .so для динамической загрузки кода? Вы тестируете сценарий безопасности или действительно пытаетесь динамически загружать и запускать код?

Прочтите здесь о том, как компилировать код в виде .so, динамически загружать его в программу и выполнять из него экспортированные функции.

http://www.yolinux.com/TUTORIALS/LibraryArchives-StaticAndDynamic.html

person selbie    schedule 23.02.2011
comment
я хочу научиться загружать код вручную, просто для удовольствия (и, возможно, для тестирования шеллкода в будущем) - person Alexey; 23.02.2011