Шелл-код в ARM дает сбой при вызове функцией, которая не является main () - PullRequest
1 голос
/ 05 августа 2020

Когда я выполняю шелл-код в основной функции, он работает нормально. Однако, когда я выполняю его другой функцией, вызываемой main, это вызовет ошибку сегментации. Насколько я знаю, вызов функции должен влиять на стек, а шелл-код должен находиться в куче. Что-то не так в моем коде?

Шелл-код генерируется matesploit, и я использую qemu-arm для запуска программы.

Код:

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

// msfvenom -p linux/armle/exec CMD=/bin/pwd -f c
unsigned char buf[] = 
"\x01\x30\x8f\xe2\x13\xff\x2f\xe1\x78\x46\x0a\x30\x01\x90\x01"
"\xa9\x92\x1a\x0b\x27\x01\xdf\x2f\x62\x69\x6e\x2f\x70\x77\x64";

void runShellCode(){
    unsigned char *pShellCode = (unsigned char *)calloc(1, 4096);
    memcpy(pShellCode, buf, sizeof(buf));
    (*(void(*)()) pShellCode)();
}

int main(int argc, char *argv[])
{
    // uncomment these lines it will work perfectly fine
    // unsigned char *pShellCode = (unsigned char *)calloc(1, 4096);
    // memcpy(pShellCode, buf, sizeof(buf));
    // (*(void(*)()) pShellCode)();

    runShellCode();
    return 0;
}

Командная команда для компиляции и запуска:

arm-linux-gnueabi-gcc test.c -o test_arm -static
qemu-arm test_arm

Код дизассемблирования шелл-кода (который неверен, поэтому я удаляю его)

Обновите код способом mmap (). Однако, если аргумент main () равен void, он работает нормально. Пока аргумент int argc, char *argv[], это вызовет SEGV.

#include <stdio.h>
#include <stdlib.h>
#include <memory.h>
#include <sys/mman.h>

// msfvenom -p linux/armle/exec CMD=/bin/pwd -f c
unsigned char buf[] = 
"\x01\x30\x8f\xe2\x13\xff\x2f\xe1\x78\x46\x0a\x30\x01\x90\x01"
"\xa9\x92\x1a\x0b\x27\x01\xdf\x2f\x62\x69\x6e\x2f\x70\x77\x64";

int main(int argc, char *argv[])
//int main(void)
{
    unsigned char *pShellCode = (unsigned char *)calloc(1, 4096);
    memcpy(pShellCode, buf, sizeof(buf));
    
    void (*sc) () = NULL;
    sc = mmap (0, 4096, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
    memcpy (sc, pShellCode, 4096);
    __builtin___clear_cache (sc, sc + sizeof(sc));
    sc();

    return 0;
}

1 Ответ

0 голосов
/ 05 августа 2020

опубликованный код приводит к:

untitled1.c:14:7: warning: ISO C forbids conversion of object pointer to function pointer type [-Wpedantic]

Linux / Unix specifici c:

You need a memory page with `write execute` permissions. 

See `mmap(2)` and `mprotect(2)`. 

Windows -specifi c:

`VirtualAlloc()` function to reserve memory 

`VirtualProtect()` function to mark as executable
applying, for instance, the `PAGE_EXECUTE_READ` flag.

you can cast the pointer to the allocated memory
to an appropriate function pointer type 
and just call the function. 

`VirtualFree()` function to clean up afterwards

относительно вашего раздела EDIT:

Исправленный код при запуске через компилятор приводит к:

gcc -ggdb3 -Wall -Wextra -Wconversion -pedantic -std=gnu11 -c "untitled1.c" -o "untitled1.o" (in directory: /home/richard/Documents/forum)
untitled1.c: In function ‘main’:
untitled1.c:18:8: warning: ISO C forbids assignment between function pointer and ‘void *’ [-Wpedantic]
     sc = mmap (0, 4096, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
        ^
untitled1.c:19:13: warning: ISO C forbids passing argument 1 of ‘memcpy’ between function pointer and ‘void *’ [-Wpedantic]
     memcpy (sc, pShellCode, 4096);
             ^~
In file included from /usr/include/memory.h:29:0,
                 from untitled1.c:3:
/usr/include/string.h:42:14: note: expected ‘void * restrict’ but argument is of type ‘void (*)()’
 extern void *memcpy (void *__restrict __dest, const void *__restrict __src,
              ^~~~~~
untitled1.c:20:37: warning: pointer to a function used in arithmetic [-Wpointer-arith]
     __builtin___clear_cache (sc, sc + sizeof(sc));
                                     ^
untitled1.c:20:30: warning: ISO C forbids passing argument 1 of ‘__builtin___clear_cache’ between function pointer and ‘void *’ [-Wpedantic]
     __builtin___clear_cache (sc, sc + sizeof(sc));
                              ^~
untitled1.c:20:30: note: expected ‘void *’ but argument is of type ‘void (*)()’
untitled1.c:20:34: warning: ISO C forbids passing argument 2 of ‘__builtin___clear_cache’ between function pointer and ‘void *’ [-Wpedantic]
     __builtin___clear_cache (sc, sc + sizeof(sc));
                                  ^~
untitled1.c:20:34: note: expected ‘void *’ but argument is of type ‘void (*)()’
untitled1.c:11:14: warning: unused parameter ‘argc’ [-Wunused-parameter]
 int main(int argc, char *argv[])
              ^~~~
untitled1.c:11:26: warning: unused parameter ‘argv’ [-Wunused-parameter]
 int main(int argc, char *argv[])
                          ^~~~
Compilation finished successfully.

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

Пожалуйста, прочтите исполняемые данные , чтобы получить представление о том, как выполнять данные.

...