从C程序加载原始代码

时间:2011-02-23 18:01:01

标签: c linux assembly system-calls shellcode

我正在编写一个程序,用于加载和执行文件中的代码。 但是我遇到了一个问题:“写”系统调用不起作用。 代码成功加载并执行,但屏幕上不显示任何文本。

加载代码的程序:

#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

4 个答案:

答案 0 :(得分:9)

您的方法不起作用:shellcode必须与位置无关,但您的代码指的是绝对地址str。无条件跳转也可以是相对的或绝对的:确保你获得相对的verison(x86上的操作码EB和E9)。

有关详细信息,请参阅The Technique of Writing Portable Shell Code

答案 1 :(得分:3)

您没有指定CPU的详细信息,但可能与NX bit发生冲突。我希望你的代码能够进入SEGFAULT而不是完成。

这正是在我的盒子上运行的(Linux 2.6.32-28-generic#55-Ubuntu SMP Mon Jan 10 23:42:43 UTC 2011 x86_64 GNU / Linux)在Intel Xeon E5410上运行。

答案 2 :(得分:2)

有一件事:您应该将文件打开为二进制文件。

FILE* fp = fopen(argv[1],"rb"); 

答案 3 :(得分:1)

为什么不使用.so文件动态加载代码?您是在测试安全方案还是真的尝试动态加载和运行代码?

在这里阅读如何将代码编译为.so,在程序中动态加载它,并从中执行导出的函数。

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