Domanda

The below code is expecting a binary file.

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

Therefore, I created the below shellfile.c that contains 19 bytes to test the above app

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

Compiled it, but the code is retrieving the below error:

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

Where is the issue exactly?

È stato utile?

Soluzione

The requirements for your shellcode are :

  • Length between 31 and 40
  • No zero byte (\x00) or strlen will fail
  • No '\n' byte (\x0A) or fgets will fail
  • No "/bin/sh" substring

Your first instruction is push $0 so the two first bytes of your shellcode is \x6A\x00.
The size of the buffer is 1 (strlen stops after a null byte).
That's why you have the error your shellcode is less than 30 bytes!.

Consider this shellcode, which is equivalent to yours, except push $1 to avoid 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)

Basically, this shellcode waits 2 seconds (and 1 nanosecond) and exits.
int 0x80 is a system call depending of eax value, more information here

You still have a problem, the length of this shellcode is 20 bytes.
You just have to add eleven NOP's (0x90) at the beginning (or at the end) to fill the requirement.

Try this :

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

If the program waits 2 seconds and successfully exits (with code 0), then the shellcode was executed.

If necessary, I can explain you how to code a shellcode which permits to get the rights of runshell program which is often the goal of this kind of exercice (and obviously the case here with the test on "/bin/sh").

Altri suggerimenti

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

fgets is only valid for \n-delimited lines in a text file. strlen is only valid for zero-terminated character strings. Neither is appropriate for this use.

Try fread() instead.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top