Проблемы с пониманием логики сборки - PullRequest
2 голосов
/ 06 апреля 2020

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

Из того, что я могу понять, эта программа сначала проверяет ввод строки, используя scanf, и проверяет, указан ли 1 аргумент. Установив точку останова и проверив значение регистра eax, я могу видеть вводимое значение, которое я ввожу, поэтому мне кажется, что я должен искать это для сравнения с чем-то другим. Затем программа перемещает некоторые вещи и сравнивает значение регистра eax с двоичным значением 0x52b = 1323. Однако я попытался использовать это значение в качестве входных данных, и оно не работает, поэтому мне интересно, неправильно ли я понимаю логи c за этой программой.

Я был бы очень признателен за любую помощь / совет!

Обновлено (я не уверен, правильно ли это):

  • Программа принимает 1 входной аргумент, сохраняет в регистре eax. Взрывается, если не вводится 1 аргумент.
  • Затем программа выполняет mov 0x1c(%esp),%eax, что по существу делает eax = [esp + 0x1c] (не перезаписывает ли это ввод программы?)
  • Затем программа выполняет lea (%eax,%eax,2),%eax что по существу делает eax = eax + eax * 2
  • Наконец, программа делает cmp $0x52b,%eax, который сравнивает значение в регистре eax с 0x52b.
0x08048bd0 <+0>:     sub    $0x2c,%esp
0x08048bd3 <+3>:     movl   $0x0,0x1c(%esp)
0x08048bdb <+11>:    lea    0x1c(%esp),%eax
0x08048bdf <+15>:    mov    %eax,0x8(%esp)
0x08048be3 <+19>:    movl   $0x804a644,0x4(%esp)
0x08048beb <+27>:    mov    0x30(%esp),%eax
0x08048bef <+31>:    mov    %eax,(%esp)
0x08048bf2 <+34>:    call   0x8048870 <__isoc99_sscanf@plt>
0x08048bf7 <+39>:    cmp    $0x1,%eax
0x08048bfa <+42>:    je     0x8048c01 <phase_1+49>
0x08048bfc <+44>:    call   0x8049363 <explode_bomb>
0x08048c01 <+49>:    mov    0x1c(%esp),%eax
0x08048c05 <+53>:    lea    (%eax,%eax,2),%eax
0x08048c08 <+56>:    cmp    $0x52b,%eax
0x08048c0d <+61>:    je     0x8048c14 <phase_1+68>
0x08048c0f <+63>:    call   0x8049363 <explode_bomb>
0x08048c14 <+68>:    add    $0x2c,%esp
0x08048c17 <+71>:    ret  

1 Ответ

2 голосов
/ 06 апреля 2020

В 32-битном x86 аргументы передаются в стек в соответствии с соглашением о вызовах cdecl IA32 (для получения дополнительной информации см. эту вики-страницу ).

Ваша phase_1 функция вызывает sscanf(), передавая аргументы здесь:

0x08048bdb <+11>:    lea    0x1c(%esp),%eax
0x08048bdf <+15>:    mov    %eax,0x8(%esp)
0x08048be3 <+19>:    movl   $0x804a644,0x4(%esp)
0x08048beb <+27>:    mov    0x30(%esp),%eax
0x08048bef <+31>:    mov    %eax,(%esp)

Вкратце:

sscanf(esp + 0x30, 0x804a644, esp + 0x1c);

Что должно быть что-то вроде:

int var_on_stack;
sscanf(user_input, "%d", &var_on_stack); 
// user_input starts at esp + 0x30
// &var_on_stack == esp + 0x1c

Первый аргумент (user_input), вероятно, был передан в качестве аргумента функции phase_1, и он, вероятно, содержит данные, которые были ранее прочитаны.

Значение 0x804a644 является адресом формата строка, которая передается в scanf(), я предполагаю, что это что-то вроде "%d", потому что значение обрабатывается как целое число впоследствии. Вы можете проверить, что находится по адресу 0x804a644 с помощью x/s 0x804a644, чтобы точно узнать, что такое строка формата (а также понять тип читаемой переменной).

После этого эти две инструкции:

0x08048c01 <+49>:    mov    0x1c(%esp),%eax
0x08048c05 <+53>:    lea    (%eax,%eax,2),%eax

Получите отсканированное значение из стека в eax, а затем умножьте его на 3 (что lea в конечном итоге приведет к eax = eax*2 + eax).

После этого значение сравнивается с 0x52b. Поэтому вам нужно ввести 0x52b/3, то есть 1323/3, то есть 441.

...