4

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

#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;
}

因此,我创建了shellfile.c包含 19 个字节的以下内容来测试上述应用程序

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 

问题究竟出在哪里?

4

2 回答 2

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

fgets仅对\n文本文件中的 -delimited 行有效。strlen仅对以零结尾的字符串有效。两者都不适合这种用途。

试试fread()吧。

于 2013-09-23T16:56:58.520 回答
0

您的 shellcode 的要求是:

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

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

考虑一下这个 shellcode,它和你的一样,除了push $1要避免 null byte :

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是一个取决于eax值的系统调用,更多信息在这里

你还有一个问题,这个shellcode的长度是20字节。
您只需在开头(或结尾) 添加 11 个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),则执行 shellcode。

如有必要,我可以向您解释如何编写一个允许获得runshell程序权限的 shellcode,这通常是这种练习的目标(很明显,这里的测试就是这种情况"/bin/sh")。

于 2013-09-24T11:31:56.580 回答