Shellcode和二进制文件

时间:2013-09-23 16:51:08

标签: c shellcode

以下代码需要二进制文件。

#include <stdio.h>
#include <string.h>

#define bufsz 100

const char msg[] = "Usage: %s <shellcode file>\n";

static char buffer1[bufsz];
static char buffer2[bufsz];

void usage(char *self) {
    printf(msg, self);
    exit(1);
}

int main(int argc, char *argv[]) {
    FILE *fp;
    void (*funcptr)();

    if (argc != 2)
        usage(argv[0]);

    if ((fp = fopen(argv[1], "rb")) == NULL ) {
        printf("fail to open file: %s\n", argv[1]);
        exit(1);
    };

    fgets(buffer1, bufsz, fp);
    fclose(fp);

    strcpy(buffer2, buffer1);

    if (strlen(buffer2) >= 40)
        printf("your shellcode is too long! \n");

    if (strlen(buffer2) < 30)
        printf("your shellcode is less than 30 bytes!\n");

    if (strstr(buffer2, "/bin/sh"))
        printf("Malicious code detected!\n");

    funcptr = (void *) buffer2;
    (*funcptr)(); /* execute your shell code */

    return 0;
}

因此,我创建了包含19个字节的下面shellfile.c来测试上面的应用

int main(){
    /* push trick */
    __asm__("push $0;\n\
             push $2;\n\
             movl %esp, %ebx;\n\
             xorl %ecx, %ecx;\n\
             mov  $162, %al;\n\
             int  $0x80;\n\
             xorl %ebx, %ebx;\n\
             leal 0x1(%ebx), %eax;\n\
             int  $0x80;\n\               
             ");
    return 0;
    }

编译它,但代码正在检索以下错误:

gcc -o codetest -g -ggdb codetest.c
./runshell testcode
your shellcode is less than 30 bytes!
Illegal Instruction 

问题究竟在哪里?

2 个答案:

答案 0 :(得分:0)

fgets(buffer1, bufsz, fp);
...
if (strlen(buffer2)<30) 
    printf("your shellcode is less than 30 bytes!\n");

fgets仅对\n - 文本文件中的分隔行有效。 strlen仅对零终止字符串有效。两者都不适合这种用途。

请尝试使用fread()

答案 1 :(得分:0)

您的shellcode的要求是:

  • 长度在31到40之间
  • 没有零字节(\x00)或strlen将失败
  • 否'\ n'字节(\x0A)或fgets将失败
  • 没有“/ bin / sh”substring

您的第一条指令是push $0,因此shellcode的前两个字节为\x6A\x00 缓冲区的大小为1strlen在空字节后停止。) 这就是你有错误your shellcode is less than 30 bytes!的原因。

考虑这个shellcode,它等同于你的,除了push $1以避免空字节:

6A01          push $1              ;to avoid null byte
6A02          push $2
89E3          movl %esp, %ebx      ;ebx now points on top of stack
31C9          xorl %ecx, %ecx      ;ecx=0
B0A2          mov  $162, %al       ;eax=162
CD80          int  $0x80           ;call sys_nanosleep because eax=162 with arguments ebx and ecx (ebx={1,2} and ecx=NULL)
31DB          xorl %ebx, %ebx      ;ebx=0
678D4301      leal 0x1(%ebx), %eax ;eax=1
CD80          int $0x80            ;call sys_exit because eax=1, with code 0 (ebx value)

基本上,这个shellcode等待2秒(和1纳秒)并退出 int 0x80是系统调用,取决于eaxmore information here

你还有问题,这个shellcode的长度是20个字节 您只需在开头(或结尾)添加11个NOP0x90)即可填写要求。

试试这个:

echo -e '\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x6A\x01\x6A\x02\x89\xE3\x31\xC9\xB0\xA2\xCD\x80\x31\xDB\x67\x8D\x43\x01\xCD\x80' > shellcode.bin
./runshell shellcode.bin

如果程序等待2秒并成功退出(代码为0),则执行shellcode。

如果有必要,我可以向你解释如何编写一个shellcode,它允许获得runshell程序的权利,这通常是这种运动的目标(显然这里的情况是{{} { 1}})。