В коде ассемблера, изменение указателя стека + переход -> segfault? - PullRequest
0 голосов
/ 02 мая 2018

Это первый раз, когда вы загружаете вопрос здесь. Я должен сделать функцию, которая:

  1. аргументы: целевая функция и глобальный массив
  2. набор регистров% ebp &% esp = массив
  3. установить регистр% eip = целевая функция
  4. с использованием asm , встроенный код сборки в C

Если я проигнорирую второе условие, это совсем не сложно:

void jump(unsigned int function);
void goal();

void main(){
    jump((unsigned int)goal); // call jump(goal)
}

void jump(unsigned int function){
    __asm__ __volatile__(
            "movl %0, %%eax;"
            "jmp %%eax" // jump to 'entry'
            ::"m"());
}

void goal(){ // desired destination of %eip
    printf("goal\n"); // if jmp instruction was successful, put 'goal'
    for(;;) { sleep(1); }
}

И это действительно ставит «цель».

Однако всякий раз, когда я пытаюсь изменить% esp &% ebp аналогичным образом, я терпел неудачу:

(основные изменения - просто объявление 'массива' и 2 строки в середине asm )

int array[100]; // target array
void jump(unsigned int function, unsigned int array);
void goal();

void main(){
    jump((unsigned int)goal, (unsigned int)array); // call jump(goal,array)
}

void jump(unsigned int function, unsigned int array){
    __asm__ __volatile__(
            "movl %0, %%eax;"
            "movl %1, %%ebx;"

            "movl %%ebx, %%esp;" // %esp = array
            "movl %%ebx, %%ebp;" // %ebp = array

            "jmp %%eax"
            ::"m"(function),"m"(array));
}

void goal(){
    printf("goal\n");
    for(;;) { sleep(1); }
}

Это делает ошибку сегментации.

Запись в файле .s функции 'goal' содержит пролог, как и все функции, т.е.

pushl %ebp
movl %esp, %ebp

Итак, мое первое предположение состояло в том, чтобы указать где-то, как глобальный массив, на% ebp или% esp, а затем выполнить push, pop или mov, чтобы вызвать ошибку сегмента.

Для проверки я изменил сборочную деталь следующим образом:

         __asm__ __volatile__(
         "movl %0, %%eax;"
         "movl %1, %%ebx;"
         "movl %%ebp, %%ecx;" // %ecx : backup of %ebp

         "movl %%ebx, %%esp;"
         "movl %%ebx, %%ebp;" // %esp & %ebp = 'array'

         "pushl %%ebp;"
         "movl %%esp, %%ebp;" // instructions as in the entry of 'goal'

         "movl %%ecx, %%esp;"
         "movl %%ecx, %%ebp;" // restore %esp & %ebp before jmp

         "jmp %%eax"
         ::"m"(function),"m"(array));

Так что% esp и% ebp указывают на «массив» и следуют инструкциям в «цели» перед jmp.

Удивительно, но ошибки сегментации не произошло, но при желании ставится «цель».

В итоге

  1. изменение% esp &% ebp не имеет значения.
  2. jmp также работает.
  3. но выполнение обоих делает ошибку сегментации.

Я гуглил и осматривался, особенно здесь, чтобы кто-то перенес это явление и нашел ответ. К сожалению ничего не нашел.

Надеюсь на помощь.

...