Я пишу самоизменяющуюся программу; уже получил это работает. Я нашел эти две функции, но не уверен, что именно они делают, и мне нравится комментировать свой код.
размер страницы получается с помощью getpagesize
/*
* Defining variables:
* func - function in memory I'm using mprotect on
* offset - the offset in memory
* ptr - the pointer to the memory
*/
unsigned int offset = (unsigned int)( ((long)func) & (pagesize-1) );
unsigned char * ptr = (unsigned char *) ((long)func & (~(pagesize-1) ) );
Я обнаружил, что функция смещения используется для проверки выравнивания памяти. Я смутно знаю, что они делают, но не разница?
Благодарю.
Если предположить, pagesize
размер страницы, они используют битовые маски для вычисления указателя (ptr
) к началу страницы, содержащей func
и смещение (offset
) на этой странице в байтах.
Как pagesize
всегда будет степенью двойки, (pagesize-1)
все установлено. Смещение на странице — это последние 12 (например) битов (12 соответствует размеру страницы, равному 4k = 2 ^ 12), поэтому первый оператор очищает все биты, кроме последних 12, используя &
со всей битовой маской из 12 младших битов.
Вторая строка вычисляет указатель на саму страницу путем очистки последних 4 битов; с помощью логического обратного (~
) предыдущей битовой маски, затем &
, он очищает все остальные биты.
(Я предполагаю, что «размер страницы» — это размер страницы платформы, и это степень двойки — например, для x86 это 0x1000. Также я предполагаю, что «func» — это указатель на функцию, то есть код, который вы хотите менять).
«offset» содержит смещение страницы кода, тогда как «pthr» содержит виртуальный адрес, по которому отображается страница памяти, содержащая код.
Я предполагаю, что где-то в вашей программе создается новое виртуальное представление (с различными правами доступа, в частности, права на запись) страницы кода. Допустим, этот новый адрес хранится в «unsigned char * page2». Таким образом, код можно изменить, написав * (page2 + offset).