Самоизменяющийся код [C ++] - PullRequest
5 голосов
/ 26 апреля 2011

Я читал статью в журнале взломщиков кодов о самоизменяющемся коде, и там был фрагмент кода:

void Demo(int (*_printf) (const char *,...))
{ 
      _printf("Hello, OSIX!n"); 
      return; 
} 
int main(int argc, char* argv[]) 
{ 
  char buff[1000]; 
  int (*_printf) (const char *,...); 
  int (*_main) (int, char **); 
  void (*_Demo) (int (*) (const char *,...)); 
  _printf=printf; 
  int func_len = (unsigned int) _main ­- (unsigned int) _Demo; 
  for (int a=0; a<func_len; a++) 
    buff[a] = ((char *) _Demo)[a]; 
  _Demo = (void (*) (int (*) (const char *,...))) &buff[0]; 
  _Demo(_printf); 
  return 0; 
}

Этот код предположительно выполняет Demo () в стеке. Я понимаю большую часть кода, но часть, в которой они присваивают func_len, смущает меня. Насколько я могу судить, они вычитают один адрес случайного указателя из другого адреса случайного указателя.

Кто-то хочет объяснить?

Ответы [ 2 ]

7 голосов
/ 26 апреля 2011

Код опирается на знание компоновки функций от компилятора - что может быть ненадежно с другими компиляторами.

Строка func_len, однажды исправленная, чтобы включить -, который был первоначальноотсутствует, определяет длину функции Demo путем вычитания адреса в _Demo (который должен содержать начальный адрес Demo()) из адреса в _main (который должен содержать начальный адресmain()).Предполагается, что это длина функции Demo, которая затем копируется побайтно в буфер buff.Затем адрес buff преобразуется в указатель на функцию, а затем вызывается функция.Однако, поскольку ни _Demo, ни _main на самом деле не инициализированы, код является крайне ошибочным.Кроме того, не ясно, что unsigned int достаточно большой, чтобы точно удерживать указатели;приведение, вероятно, должно быть к uintptr_t из <stdint.h> или <inttypes.h>.

Это работает, если ошибки исправлены, если предположения о расположении кода верны, если код не зависит от позициикод, и если нет защиты от выполнения пространства данных.Это ненадежно, непереносимо и не рекомендуется.Но это иллюстрирует, если это работает, что код и данные очень похожи.

Я помню, как выполнял похожий трюк между двумя процессами, копировал функцию из одной программы в общую память и затем выполнял другую программу.эта функция из общей памяти.Это было около четверти века назад, но техника была похожа и «работала» для машины, на которой она была опробована.С тех пор мне никогда не приходилось использовать технику, слава богу!

5 голосов
/ 26 апреля 2011

В этом коде используются неинициализированные переменные _main и _Demo, поэтому он не может работать вообще.Даже если они имели в виду что-то другое, они, вероятно, предполагали определенное упорядочение функций в памяти.

Мое мнение: не верьте этой статье.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...