Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[elf2bin] Segmentation fault #251

Open
enty8080 opened this issue Aug 10, 2023 · 2 comments
Open

[elf2bin] Segmentation fault #251

enty8080 opened this issue Aug 10, 2023 · 2 comments

Comments

@enty8080
Copy link

Hello,

I wrote a simple code, that should execute binary file from buffer (this code is based on mettle/src/process.c):

#include <sys/types.h>
#include <sys/auxv.h>

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>

struct bin_info {
    off_t start_function;
    off_t dynamic_linker_info;
    char magic_number[4];
} __attribute__((packed));

void exec_image(char *image, size_t image_len)
{
    void (*e_entry)(long *, long *);
    long stack[9] = {0};
    long *dynv;

    struct bin_info *image_info = (struct bin_info*)(image + image_len - sizeof(*image_info));
    e_entry = (void *)(image + image_info->start_function);

    stack[0] = 1;
    stack[1] = (intptr_t)"libc.so";
    stack[2] = 0;

    stack[3] = (intptr_t)"LANG=C";
    stack[4] = 0;

    stack[5] = AT_BASE; stack[6] = (intptr_t)image;
    stack[7] = AT_NULL; stack[8] = 0;

    dynv = (void *)(image + image_info->dynamic_linker_info);

    printf("%s: jumping to %p loaded at %p\n", __FUNCTION__, e_entry, image);
    e_entry(stack, dynv);
}

int main(int argc, char *argv[])
{
    if (argc < 2)
    {
        fprintf(stderr, "usage: %s <file>\n", argv[0]);
        return 1;
    }

    FILE *file = fopen(argv[1], "rb");

    if (file == NULL)
        return 1;

    fseek(file, 0L, SEEK_END);
    size_t size = ftell(file);
    rewind(file);

    unsigned char *image = malloc(size);
    if (image == NULL)
        return 1;

    fread(image, sizeof(unsigned char), size, file);

    exec_image(image, size);

    free(image);
    fclose(file);

    return 0;
}

Then I compile this script using gcc main.c -o main

Target is a simple program which should print Hello, world!. I compile it using x86_64-linux-musl-gcc test.c -o test -static -pie -Wl,-z,max-page-size=4096 and then turn it to binary using elf2bin test test.bin.

After executing ./main test.bin I got SEGFAULT:

exec_image: jumping to 0x563d26c378b8 loaded at 0x563d26c37490
Segmentation fault

How can I fix this and what am I doing wrong?
And is there any way to pass an argument of int to main function of test.bin?

@timwr
Copy link
Contributor

timwr commented Aug 11, 2023

try change malloc(size); to mmap(0, size, PROT_EXEC | PROT_READ | PROT_WRITE, MAP_ANON | MAP_SHARED, -1, 0); ?

@enty8080
Copy link
Author

@timwr Yeah, I tried this. Still segmentation fault.

Code I ran:

#include <sys/types.h>
#include <sys/mman.h>
#include <sys/auxv.h>

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>

struct bin_info {
    off_t start_function;
    off_t dynamic_linker_info;
    char magic_number[4];
} __attribute__((packed));

void exec_image(char *image, size_t image_len)
{
    void (*e_entry)(long *, long *);
    long stack[9] = {0};
    long *dynv;

    struct bin_info *image_info = (struct bin_info*)(image + image_len - sizeof(*image_info));
    e_entry = (void *)(image + image_info->start_function);

    stack[0] = 1;
    stack[1] = (intptr_t)"libc.so";
    stack[2] = 0;

    stack[3] = (intptr_t)"LANG=C";
    stack[4] = 0;

    stack[5] = AT_BASE; stack[6] = (intptr_t)image;
    stack[7] = AT_NULL; stack[8] = 0;

    dynv = (void *)(image + image_info->dynamic_linker_info);

    printf("%s: jumping to %p loaded at %p\n", __FUNCTION__, e_entry, image);
    e_entry(stack, dynv);
}

int main(int argc, char *argv[])
{
    if (argc < 2)
    {
        fprintf(stderr, "usage: %s <file>\n", argv[0]);
        return 1;
    }

    FILE *file = fopen(argv[1], "rb");

    if (file == NULL)
        return 1;

    fseek(file, 0L, SEEK_END);
    size_t size = ftell(file);
    rewind(file);

    unsigned char *image = mmap(0, size, PROT_EXEC | PROT_READ | PROT_WRITE, MAP_ANON | MAP_SHARED, -1, 0);
    if (image == NULL)
        return 1;

    fread(image, sizeof(unsigned char), size, file);

    exec_image(image, size);

    munmap(image, size);
    fclose(file);

    return 0;
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants