当不是'main()'的函数调用时,ARM中的Shellcode崩溃

时间:2020-08-05 15:14:03

标签: c arm shellcode

当我在main函数中执行shellcode时,它工作正常。但是,当我通过main调用的其他函数执行它时,会导致分段错误。据我所知,函数调用应该影响堆栈,而shellcode应该在堆中。我的代码有问题吗?

shellcode是由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;
}

要编译和运行的cmd:

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

shellcode的反汇编代码(这是不正确的,因此我将其删除)


使用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 :(得分:0)

发布的代码导致:

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

特定于Linux / Unix:

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

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

特定于Windows:

`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

关于您的“编辑”部分:

修改后的代码在通过编译器运行时会导致:

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.

即使编译器输出:编译成功完成这并不意味着结果代码是正确的。这是什么意思是编译器为每个“警告”替换了一些“变通方法”。这并不意味着结果就是您想要的。

请阅读executable data,以获取有关如何执行数据的一些想法。

相关问题