2016-10-26 5 views
1

Я студент CS, изучающий сборку IA-32. Для проекта нам был предоставлен исполняемый файл для программы. Мы можем использовать objdump и другие инструменты для проверки двоичных файлов, но не можем видеть исходный код. Программа принимает входную строку и сравнивает ее с другой тайной строкой. Если две строки: не то же самое, программа отключает будильник, и я перехватываю задание. Это было бы веселое задание ... если бы TA потрудилась ответить на мои вопросы ... Gr12 ...Чтение кода сборки IA32 - определение скрытой строки?

Так что если вы не возражаете, чтобы дать мне несколько указателей, я бы хотел спросить форум, если Я на правильном пути. Когда я бегу objdump -d CODE на код, исполняемый, я могу развернуть и увидеть это в основной функции():

08048a44 <main>: 
... 
8048af6: e8 d0 08 00 00   call 80493cb <get_string> 
8048afb: 89 04 24    mov %eax,(%esp) 
8048afe: e8 ad 00 00 00   call 8048bb0 <test_string> 

Я достаточно уверен, что get_string() получает строку от пользователя - его, вероятно, функция упаковщик для fscanf() или что-то - и тогда указатель на эту строку сохраняется в регистре %eax. Следующая строка перемещает указатель на %esp, затем вызывает test_string(). Вот этот код:

08048bb0 <test_string>: 
8048bb0: 83 ec 1c    sub $0x1c,%esp 
8048bb3: c7 44 24 04 6c a4 04 movl $0x804a46c,0x4(%esp) 
8048bba: 08 
8048bbb: 8b 44 24 20    mov 0x20(%esp),%eax 
8048bbf: 89 04 24    mov %eax,(%esp) 
8048bc2: e8 bd 04 00 00   call 8049084 <cmp_strings> 
8048bc7: 85 c0     test %eax,%eax 
8048bc9: 74 05     je  8048bd0 <test_string+0x20> 
8048bcb: e8 bc 07 00 00   call 804938c <alarm> 
8048bd0: 83 c4 1c    add $0x1c,%esp 
8048bd3: c3      ret  

Вот что я думаю, что происходит ...

08048bb0 <test_string>: 
8048bb0: sub $0x1c,%esp   // Adjusts %esp for new function 
8048bb3: movl $0x804a46c,0x4(%esp) // test_string is stored at $0x804a46c; move that pointer into %esp 
8048bba:        // ??? 
8048bbb: mov 0x20(%esp),%eax  // Moves test_string ptr to %eax 
8048bbf: mov %eax,(%esp)   // Moves test_string ptr to %esp - not sure why...? 
8048bc2: call 8049084 <cmp_strings> // Calls cmp_strings(), probably with %eax and %esp as argument strings 
8048bc7: test %eax,%eax    // %eax is the returned value 
8048bc9: je  8048bd0 <test_string+0x20> // Should we jump to alarm()? 
8048bcb: call 804938c <alarm>  // If we reach here, I flunk 
8048bd0: add $0x1c,%esp   // restores %esp to original value 
8048bd3: ret       // exits 

Так что ... если я прав, строка # 2 является важным здесь. Я подозреваю, что строка тайны хранится в памяти адреса $0x804a46c. Но я не уверен. Отмечу также, что, когда я использую инструмент строк, я вижу это:

[linux]$ strings -t x CODE | grep 46c 
    246c My dog has fleas. 
[linux]$ 

Это многообещающая ... но не убедительно. Адрес памяти $0x804a46c не 246c.

Итак ... извинения за длинный пост, но могут ли люди сказать мне, если я на правильном пути? Любое понимание или мудрость чрезвычайно оценены!

Большое спасибо! -RAO

+2

Используйте 'objdump', чтобы увидеть строку по указанному адресу. 'strings' дает вам смещения файлов, а не виртуальные адреса. Разумеется, вы также можете перевести их, если посмотреть на заголовки разделов, снова используя 'objdump'. – Jester

+1

«Код операции тайны» по адресу '8048bba' является лишь частью предыдущей инструкции. Вероятно, он был включен в следующую строку, потому что кодировка команд настолько длинная. Обратите внимание, что значение в инструкции равно '0x804a46c', а' 6c' 'a4' и' 04' все указаны в предыдущей строке. – davmac

+0

@ davmac: yup, точно вправо. Обычно я использую 'objdump -drwC', чтобы избежать этого (' -w' означает «широкий» и помещает все байты для инструкции в той же строке, независимо от ширины столбца). –

ответ

3

Если есть какая-то отладочная обманка, то cmp_strings() принимает только два аргумента, которые указаны внутри test_string(). Естественно, что оба они являются строками, а первая строка берется из постоянного местоположения 0x804a46c, тогда как вторая (указатель на нее, конечно, не сама строка) является параметром test_string(). Непосредственно перед вызовом, стек выглядит следующим образом:

 |_______________| 
ESP: | <your string> | <-- cmp_strings() 1st arg 
+04: | 0x804a46c | <-- cmp_strings() 2nd arg 
+08: |  ...  | 
+0C: |  ...  | 
+10: |  ...  | 
+14: |  ...  | 
+18: |  ...  | 
+1C: | return adress | <-- ESP at the start of test_string() 
+20: | <your string> | <-- test_string() 1st arg 
+24: |  ...  | 

Вы можете проверить «секретные» содержимое строки непосредственно во время выполнения с помощью GDB (который, вообще говоря, необходимо, так как код не показан здесь может переписать). Только break *0x8048bc2, run, а затем x/sb 0x804a46c.

+0

Да, вот и все! x/sb 0x804a46c «У моей собаки есть блохи». Отлично спасибо! Вы также дали мне хорошее руководство по команде GDB x, которую я предвижу, используя много в ближайшем будущем. Благодаря! – Pete

+0

@Pete: Кстати, GDB может быть более интерактивным, чем по умолчанию.Используйте 'gdb --tui', и когда он запустится, введите' layout asm', чтобы увидеть сборку. – hidefromkgb

2

Следующая строка перемещает указатель на% esp, а затем вызывает test_string(). Значение

mov %eax,(%esp) хранит в eax в памяти, адресованной esp, то есть. в верхней части стека. Чтобы скопировать этот указатель в esp, вам нужно будет сделать mov %eax, %esp, и это не очень хорошая идея, так как ss:esp используется в качестве указателя стека процессором.

movl $0x804a46c,0x4(%esp) // test_string is stored at $0x804a46c; move that pointer into %esp

Снова "в esp" является неточным на уровне быть совершенно неправильно. Это записывает значение 0x804a46c в память по адресу esp+4, поэтому, если бы вы выбрали pop значений из стека, это было бы второе значение, которое было бы выбрано (справа «под» верхней частью стека).

mov 0x20(%esp),%eax // Moves test_string ptr to %eax

Нагрузки "входной строки указатель" в eax. Это от eax впереди call <test_string>. Вы, вероятно, имели в виду это и писали неправильный комментарий?

mov %eax,(%esp) // Moves test_string ptr to %esp - not sure why...?

сохраняет его на «вершине стека», так что если вы начнете совать значения из стека здесь, вы бы первый поп входной указатель строки, а затем это значение 0x804a46c , См. Ответ hidefromkgb для искусства содержимого стека ASCII.

Тогда это очень вероятно, что call 8049084 <cmp_strings> выбирает эти два указателя из стека в качестве аргументов, делает что-то, и возвращает ноль для правильной строки (как любое ненулевое возвращаемое значение будет сделать следующий je терпят неудачу, и вызвать call <alarm>.

Вы, вероятно, следует принять быстрый взгляд на cmp_strings тоже, чтобы увидеть, если это обычный C-подобный strcmp или как она может возвращать ноль.

И как Jester отметил, что должно быть возможно objdump также, что мистик 0x804a46c контента. Если это какая-то ранняя задача, это, вероятно, будет ng в раздел данных с легко читаемыми строковыми данными.

Если это будет более сложная задача, она также может указывать на сегмент кода на поддельные инструкции, которые образуют некоторую строку .. или, в конечном итоге, даже не поддельные инструкции (хотя для создания значимого кода asm, который также образует некоторую короткую строку, нет тривиально на x86 ... например, я использовал, чтобы добавить «PED» в начало моих 256-битных интросов .com-файлов, он просто путает бит стек, не влияя на остальную часть моего вступления ... и на конкурс кодирования одного размера Я использовал xlat, указывая на код, чтобы получить разыгранный рисунок, чтобы нарисовать флаг Греции в 51 bytes).

+0

Спасибо Ped7g, это отличная деталь. Я медленно и мучительно участвую в том, что, хотя синтаксис IA-32 выглядит просто, его действительно трудно следовать и легко ошибиться. Я скопировал все ваши комментарии в свои заметки. :) – Pete

+0

@Pete Я лично предпочитаю синтаксис Intel (особенно вариант NASM). Но я боюсь, что вы не можете свободно выбирать. Хотя objdump может быть сконфигурирован для создания диалекта Intel на языке GNU: http://stackoverflow.com/a/10362655/4271923 Но убедитесь, что он не укусит вас позже в классе, когда вы все равно будете применены к AT & T? Также, если вы изучаете это как первый ASM, возможно, AT & T не повредит. (Я изучал x86 по месяцам/годам кодирования на другом процессоре, а синтаксис Intel выглядел знакомым) – Ped7g

+0

Хммммм ... хорошая пища для размышлений. Честно говоря, я полный новичок в IA-32 и только узнал об objdump два дня назад. Я работаю с синтаксисом, который ставится передо мной, не совсем понимая, откуда он. Мне придется больше подумать над этим. Благодаря! – Pete

Смежные вопросы