Intereting Posts
Как избежать целостного продвижения в C? Когда память выделена локальным переменным в C Прототип функции в файле заголовка не соответствует определению, как его поймать? Рандомизировать строку в C Перегрузка free (), поэтому моя программа использует мои, а не систему Простое приложение C с использованием 50% процессора Есть ли какое-либо обходное решение для того, чтобы сделать член структуры каким-то «частным» в C? Разница между fclose и close segmentation fault с помощью strcpy Pthread – В чем разница между time.h :: sleep () и pthread.h :: pthread_yield ()? Какова цель этой линии? (Объявление функции) Функция для проверки, является ли строка ввода целым числом или числом с плавающей запятой? Ширина полосы пропускания L1: снижение эффективности на 50% с использованием адресов, которые отличаются на 4096 + 64 байта Получение pid и другой информации процесса из / proc / / status Поведение strtok_s с последовательными разделителями

Скопируйте функцию в память и выполните ее

Я хотел бы знать, как в C in можно скопировать содержимое функции в memroy и выполнить ее?

Я пытаюсь сделать что-то вроде этого:

typedef void(*FUN)(int *); char * myNewFunc; char *allocExecutablePages (int pages) { template = (char *) valloc (getpagesize () * pages); if (mprotect (template, getpagesize (), PROT_READ|PROT_EXEC|PROT_WRITE) == -1) { perror ("mprotect"); } } void f1 (int *v) { *v = 10; } // allocate enough spcae but how much ?? myNewFunc = allocExecutablePages(...) /* Copy f1 somewere else * (how? assume that i know the size of f1 having done a (nm -S foo.o)) */ ((FUN)template)(&val); printf("%i",val); 

Спасибо за ваши ответы

Вы, кажется, разобрались в части флагов защиты. Если вы знаете размер функции, теперь вы можете просто выполнить memcpy () и передать адрес f1 в качестве исходного адреса.

Одно большое предостережение заключается в том, что на многих платформах вы не сможете вызывать любые другие функции из того, который вы копируете (f1), поскольку относительные адреса жестко закодированы в двоичный код функции и перемещают его в другую местоположение, которое память может сделать, эти относительные адреса ухудшаются.

Это происходит, потому что функции 1 и function2 имеют одинаковый размер в памяти. Нам нужна длина функции2 для нашей memcopy, так что нужно сделать: int diff = (& main – & function2);

Вы заметите, что можете редактировать функцию 2 по своему вкусу, и она отлично работает!

Btw опрятный трюк. Unstallunate компилятор g ++ выдает неверное преобразование из void * в int … Но действительно с gcc он компилируется отлично;)

Измененные источники:

 //Hacky solution and simple proof of concept that works for me (and compiles without warning on Mac OS X/GCC 4.2.1): //fixed the diff address to also work when function2 is variable size #include "stdio.h" #include "stdlib.h" #include "string.h" #include  int function1(int x){ return x-5; } int function2(int x){ //printf("hello world"); int k=32; int l=40; return x+5+k+l; } int main(){ int diff = (&main - &function2); printf("pagesize: %d, diff: %d\n",getpagesize(),diff); int (*fptr)(int); void *memfun = malloc(4096); if (mprotect(memfun, 4096, PROT_READ|PROT_EXEC|PROT_WRITE) == -1) { perror ("mprotect"); } memcpy(memfun, (const void*)&function2, diff); fptr = &function1; printf("native: %d\n",(*fptr)(6)); fptr = memfun; printf("memory: %d\n",(*fptr)(6) ); fptr = &function1; printf("native: %d\n",(*fptr)(6)); free(memfun); return 0; } 

Выход:

Walter-Schrepperss-MacBook-Pro: cppWork wschrep $ gcc memoryFun.c Walter-Schrepperss-MacBook-Pro: cppWork wschrep $ ./a.out pagesize: 4096, diff: 35 native: 1 memory: 83 native: 1

Еще одно замечание – вызов printf будет segfault, потому что printf, скорее всего, не найден из-за неправильного адреса адреса …

Я много раз пробовал эту проблему в C и пришел к выводу, что ее невозможно выполнить, используя только язык C. Моим основным терном было найти длину функции для копирования.

Стандартный язык C не предоставляет никаких методов для получения длины функции. Однако для определения длины можно использовать язык ассемблера и «разделы». Как только длина будет найдена, копирование и выполнение легко.

Самое простое решение – создать или определить сегмент компоновщика, содержащий эту функцию. Напишите модуль языка ассемблера для расчета и публичного объявления длины этого сегмента. Используйте эту константу для размера функции.

Существуют и другие методы, которые include настройку компоновщика, например, предопределенные области или фиксированные местоположения и копирование этих местоположений.

Во встроенных системах земли большая часть кода, который копирует исполняемый файл в ОЗУ, записывается в сборку.

Это может быть решение для взлома. Не могли бы вы сделать фиктивную переменную или функцию непосредственно после функции (для копирования), получить адрес / функцию фиктивной переменной и затем выполнить адрес функции, чтобы сделать сумму арифметики с использованием адресов, чтобы получить размер функции? Это возможно, поскольку память распределяется линейно и упорядоченно (а не случайным образом). Это также сохранит функцию копирования в переносном режиме ANSI C, а не вникает в системный код сборки. Я считаю, что C является довольно гибким, нужно просто подумать.

Решение Hacky и простое доказательство концепции, которая работает для меня (и компилируется без предупреждения в Mac OS X / GCC 4.2.1):

 #include "stdio.h" #include "stdlib.h" #include "string.h" #include  int function1(int x){ return x-5; } int function2(int x){ return x+5; } int main(){ int diff = (&function2 - &function1); printf("pagesize: %d, diff: %d\n",getpagesize(),diff); int (*fptr)(int); void *memfun = malloc(4096); if (mprotect(memfun, 4096, PROT_READ|PROT_EXEC|PROT_WRITE) == -1) { perror ("mprotect"); } memcpy(memfun, (const void*)&function2, diff); fptr = &function1; printf("native: %d\n",(*fptr)(6)); fptr = memfun; printf("memory: %d\n",(*fptr)(6) ); fptr = &function1; printf("native: %d\n",(*fptr)(6)); free(memfun); return 0; }