How to write and execute PURE machine code manually without containers like EXE or ELF?

Можно использовать эти Stopwatch, предполагая использование.NET 2.0 или более новые.

System.Diagnostics.Stopwatch.StartNew();

Stopwatch класс также имеет общедоступное поле IsHighResolution только для чтения, которое сообщит, основан ли секундомер на счетчике производительности с высоким разрешением. Если не, это основано на системном таймере.

я не уверен, что это берет для секундомера, чтобы быть основанным на счетчике производительности с высоким разрешением. Существуют некоторые вызовы API, но я фигурирую, не использует ли секундомер высокое разрешение, то API, вероятно, не там.

49
задан Ciro Santilli 新疆改造中心法轮功六四事件 23 May 2015 в 03:08
поделиться

1 ответ

Реальный Машинный код

, Что необходимо запустить тест: Linux x86 или x64 (в моем случае, я использую Ubuntu x64)

Позволяют нам Запуститься

, Этот блок (x86) перемещает значение 666 в регистр eax:

movl $666, %eax
ret

Позволяют нам сделать двоичное представление из него:

код операции movl (movl mov с размером операнда 32) в двоичном файле = 1011

Инструкция , ширина в двоичном файле = 1

Регистр , eax в двоичном файле = 000

, Номер 666 в двоичном файле на 32 бита со знаком = 00000000 00000000 00000010 10011010

666 преобразован в [1 147], прямой порядок байтов = 10011010 00000010 00000000 00000000

, Инструкция мочит (возврат) в двоичном файле, = 11000011

Поэтому наконец, наши чистые двоичные инструкции будут похожи на это:

1011(movl)1(width)000(eax)10011010000000100000000000000000(666) 11000011(ret)

Соединение всего этого:

1011100010011010000000100000000000000000
11000011

Для выполнения его двоичный код должен быть помещен в страницу памяти с полномочиями выполнения, мы можем сделать то использование следующего кода C:

#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/mman.h>

/* Allocate size bytes of executable memory. */
unsigned char *alloc_exec_mem(size_t size)
{
    void *ptr;

    ptr = mmap(0, size, PROT_READ | PROT_WRITE | PROT_EXEC,
               MAP_PRIVATE | MAP_ANON, -1, 0);

    if (ptr == MAP_FAILED) {
            perror("mmap");
            exit(1);
    }

    return ptr;
}

/* Read up to buffer_size bytes, encoded as 1's and 0's, into buffer. */
void read_ones_and_zeros(unsigned char *buffer, size_t buffer_size)
{
    unsigned char byte = 0;
    int bit_index = 0;
    int c;

    while ((c = getchar()) != EOF) {
            if (isspace(c)) {
                    continue;
            } else if (c != '0' && c != '1') {
                    fprintf(stderr, "error: expected 1 or 0!\n");
                    exit(1);
            }

            byte = (byte << 1) | (c == '1');
            bit_index++;

            if (bit_index == 8) {
                    if (buffer_size == 0) {
                            fprintf(stderr, "error: buffer full!\n");
                            exit(1);
                    }
                    *buffer++ = byte;
                    --buffer_size;
                    byte = 0;
                    bit_index = 0;
            }
    }

    if (bit_index != 0) {
            fprintf(stderr, "error: left-over bits!\n");
            exit(1);
    }
}

int main()
{
    typedef int (*func_ptr_t)(void);

    func_ptr_t func;
    unsigned char *mem;
    int x;

    mem = alloc_exec_mem(1024);
    func = (func_ptr_t) mem;

    read_ones_and_zeros(mem, 1024);

    x = (*func)();

    printf("function returned %d\n", x);

    return 0;
}

Источник: https://www.hanshq.net/files/ones-and-zeros_42.c

Мы можем скомпилировать его использование:

gcc source.c -o binaryexec

Для выполнения его:

./binaryexec

Затем мы передаем первые наборы инструкций:

1011100010011010000000100000000000000000

нажимают Enter

и передают инструкцию по возврату:

11000011

нажимают Enter

наконец ctrl+d, чтобы закончить программу и получить вывод:

функция возвратилась 666

1
ответ дан 7 November 2019 в 11:48
поделиться
Другие вопросы по тегам:

Похожие вопросы: