C 外壳代码和二进制文件

C 外壳代码和二进制文件,c,shellcode,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);

下面的代码需要一个二进制文件

#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;
}
已编译,但代码正在检索以下错误:

gcc -o codetest -g -ggdb codetest.c
./runshell testcode
your shellcode is less than 30 bytes!
Illegal Instruction 
问题到底在哪里?

fgets(buffer1、bufsz、fp);
fgets(buffer1, bufsz, fp);
...
if (strlen(buffer2)<30) 
    printf("your shellcode is less than 30 bytes!\n");
...
如果(strlen(buffer2)对外壳代码的要求是:

  • 长度在31到40之间
  • 任何零字节(
    \x00
    )或
    strlen
    都不会失败
  • 任何'\n'字节(
    \x0A
    )或
    fgets
    都不会失败
  • 否“/bin/sh”子字符串
您的第一条指令是
push$0
,因此外壳代码的前两个字节是
\x6A\x00

缓冲区的大小为
1
strlen
在空字节后停止)。
这就是为什么出现错误
您的外壳代码小于30字节!

考虑此外壳代码,它与您的外壳代码相同,只是
推送$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)
基本上,此外壳代码等待2秒(1纳秒)后退出。
int 0x80
是一个系统调用,取决于
eax

您仍然有问题,此外壳代码的长度为20字节。
您只需在开头(或结尾)添加十一个
NOP
0x90
)即可满足需求

试试这个:

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),则执行外壳代码


如果有必要,我可以向您解释如何编写外壳代码,以获得
runshell
程序的权限,这通常是此类练习的目标(显然,在这里测试
“/bin/sh”
).

我很好奇——您使用了什么命令来编译
shellfile.c
?gcc-o shellfile-g-ggdb shellfile.c这将是您的下一个问题。
shellfile
将是一个ELF文件,而不仅仅是一个x86指令流。您的意思是我必须从shellfile.c中提取操作码吗?在您修复
fgets()之后
,请阅读:我认为他无法修改此代码,我想创建满足代码条件的外壳代码是一种练习。@Michael即使他设法将正确的字节码放入缓冲区,当他尝试执行时,此尝试也会出错。@moooeeep,是的,因为该文件不只包含字节码流。@moooeeep
if(strlen(buffer2)>=40)
if(strlen(buffer2)<30)
@moooeeep,警告,而不是通知。这些条件验证外壳代码。
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