11

I'm writing a program that loads and executes code from file. But i got a problem: "write" syscall does not work. Code successfully loads and executes, but does not display any text on the screen.

Program that loads code:

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

code that i trying to execute by this program (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

Here is how i compile it:

 gcc -c test.s
 objcopy -O binary test.o test.bin

Solved, thanks to @Christoph

There are working code:

.text
    call start
    str:
        .string "test\n"
    start:
    movl    $4, %eax
    movl    $1, %ebx
    pop     %ecx
    movl    $5, %edx
    int     $0x80
    ret
Ethan Heilman
  • 16,347
  • 11
  • 61
  • 88
Alexey
  • 113
  • 6

4 Answers4

9

Your approach can't work: shellcode must be position-independant, but your code refers to the absolute address str. The unconditional jump can also be either relative or absolute: make sure you get the relative verison (opcodes EB and E9 on x86).

See The Technique of Writing Portable Shell Code for more information.

Christoph
  • 164,997
  • 36
  • 182
  • 240
  • 1
    Yes, when you normally link and load code (eg, with dlopen), one of the things the loader does is fix up the address references in the code to match where those are actually loaded into memory. Loading and executing the code manually, you will have to either do these fix ups manually, or stick to not using absolute addresses. – bdk Feb 23 '11 at 18:55
  • @Alexey: you can use `call` to push the instruction pointer to the stack and get the address of your shellcode this way (see Listing 11.1 in the linked doc) – Christoph Feb 23 '11 at 19:11
  • link down sir :( – Febriyanto Nugroho Aug 27 '20 at 02:36
3

You don't specify the details of your CPU, but you might be running afoul of the NX bit. I would expect your code to SEGFAULT though rather than run to completion.

This is precisely what happens on my box (Linux 2.6.32-28-generic #55-Ubuntu SMP Mon Jan 10 23:42:43 UTC 2011 x86_64 GNU/Linux) running on Intel Xeon E5410.

NPE
  • 486,780
  • 108
  • 951
  • 1,012
  • 1
    I have NX bit disabled in kernel. Code always executes successfully, i ran it about 30 times ( i also checked it in gdb) – Alexey Feb 23 '11 at 18:33
2

One thing: you should open the file as binary.

FILE* fp = fopen(argv[1],"rb"); 
AShelly
  • 34,686
  • 15
  • 91
  • 152
  • 3
    doesn't matter on POSIX systems: "The character 'b' shall have no effect, but is allowed for ISO C standard conformance." – Christoph Feb 23 '11 at 18:33
1

Why are you not using .so files to dynamically load your code? Are you testing a security scenario or really trying to dynamically load and run code?

Read here on how to compile code as a .so, load it dynamically within a program, and execute exported functions out of it.

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

selbie
  • 100,020
  • 15
  • 103
  • 173
  • i want to learn how to load code manually, just for fun (and maybe for shellcode testing in future) – Alexey Feb 23 '11 at 18:41