x86 сборка запихнуть OFFSET и мнемонику?

Я пытаюсь немного научиться ассемблеру, создавая небольшие программы на C в Visual Studio 2012 Express, а затем дизассемблируя их в Immunity Debugger. Но я явно столкнулся с чем-то, чего не понимаю:

012A13F0   68 58582A01      PUSH OFFSET Hello_Wo.??_C@_0M@KPLPPDAC@H>; ASCII "Hello World"
012A13F5   FF15 BC922A01    CALL DWORD PTR DS:[<&MSVCR110D.printf>]  ; MSVCR110.printf

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

Очевидно, первая инструкция помещает адрес в стек. Когда я отслеживаю адрес в дампе, он показывает мне область, содержащую несколько шестнадцатеричных чисел, составляющих строку Hello World. Я считаю, что это .data segment. Я прав?

А также; Я предполагаю, что Hello_Wo.??_C@_0M@... - это просто визуальная помощь, предоставленная мне отладчиком, чтобы я мог лучше понять, что это... Что-то...

Но что означает СМЕЩЕНИЕ в этой инструкции push? Я ничего не смог найти в Google по этому поводу.

Я также хотел бы спросить о другой инструкции ...

Насколько я понимаю, он пытается вызвать подпрограмму, используя 4-байтовое значение, расположенное по адресу DS:[102A92BC] (&MSVCR110D...), в качестве адреса вызова?

Отладчик говорит мне, что DS:[102A92BC] = 5C0A93A0. И этот диапазон памяти зарезервирован для MSVCR110 .text segment.

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

Не по теме: у меня есть последний вопрос, который немного глуп и не по теме, но я надеюсь, вы не возражаете: вы никогда не должны читать сегменты данных как дизассемблированный код. , ты? сегмент данных импорта сбил меня с толку при поиске 5C0A93A0.


person Volatile    schedule 13.07.2013    source источник
comment
Я не хочу добавлять ответ, так как я не уверен, что я полностью прав, но я попробую, надеюсь, это поможет нам начать; D 1) Не уверен, что с _C@_M @..., но все, что OFFSET говорит, это то, что это не выражение, а необработанное смещение (также может иметь какое-то отношение к базовому адресу, я посмотрю позже) 2. Причина печати в сегменте .text потому, что это импорт. Это относится к таблице переходов для MsVcr110.DLL. Ваша программа не может знать точный адрес или печатать заранее, поэтому он помещается здесь, когда программа запускается, и вместо этого вы вызываете его.   -  person AStupidNoob    schedule 14.07.2013
comment
3. Вы МОЖЕТЕ читать код из .text, но в большинстве (если не во всех) это не имеет смысла. Это просто то, что дизассемблер делает из данных там, обычно это просто данные, а дизассемблер выбрасывает мусор. Могут быть некоторые крайние случаи, когда некоторый код запускается из .text, но по соображениям безопасности я считаю, что он отображается в неисполняемую память. Еще раз посмотрю, я тут не профи, просто пытаюсь помочь.   -  person AStupidNoob    schedule 14.07.2013
comment
Итак, какой базовый адрес в этом отношении влияет на смещение?   -  person Volatile    schedule 14.07.2013
comment
Я не слишком уверен в синтаксисе OFFSET здесь, поэтому я бы поверил @johnfound на слово своему. Под базовым адресом я имел в виду адрес, по которому загружается раздел. Каждый раздел исполняемого файла отображается в виртуальную память, включая программный код. Если вы хотите сказать, перейти к функции, вы должны перейти к расположению функции В ПАМЯТИ. Итак, скажем, у нас есть функция по адресу .text+0x123456, а .text загружается по адресу 0x40000000 (== базовый адрес), тогда инструкция будет jmp 0x40123456, но дизассемблер удаляет этот базовый адрес, чтобы упростить чтение.   -  person AStupidNoob    schedule 14.07.2013
comment
Tbh, если вы посмотрите на код операции 68 58582A01, это даже не похоже на то, что «СМЕЩЕНИЕ» ни для чего не учитывается. Согласно (ref.x86asm.net/coder32.html), "68" — это просто код операции для простого толчка.   -  person Volatile    schedule 14.07.2013
comment
Это заставляет меня думать, что это то, что придумал отладчик. Я думаю, что @johnfound говорит о том, как он используется вместе с сегментами. Но он также говорит, что современные ОС используют плоскую модель памяти, что делает ее еще более странной... Поскольку нет никаких сегментов, которые можно было бы сместить, кроме того, что вы говорите. (базовый адрес)   -  person Volatile    schedule 14.07.2013
comment
Посмотрите здесь: hitxp.com/comp/pro/asm/120403.htm, кажется, это должно помочь вам кое-что прояснить!   -  person AStupidNoob    schedule 14.07.2013


Ответы (1)


В архитектуре x86 каждый адрес состоит из двух частей — сегмента и смещения. Таким образом, OFFSET просто означает, что смещение адреса некоторой переменной "Hello_Wo.??_C@_0M@KPLPPDAC@H" помещается в стек. Эта директива взята из синтаксиса MASM, где «передача переменной» означает передачу значения переменной, а «передача переменной смещения» означает отправку смещения переменной.

Упомянутые ".data" и ".text" - это не сегменты, а разделы. Это совершенно другое. Раздел — это просто часть исполняемого файла, которая имеет отдельную защиту памяти. Компиляторы C/C++ обычно используют ".text" для программного кода. Не спрашивайте меня, почему.

В современных операционных системах защищенного режима используется плоская модель памяти. Это означает, что весь код и данные помещаются в один большой сегмент, поэтому вам никогда не придется работать с регистрами сегментов DS, ES и т. д. Их значениями управляет ОС.

P.S. Начинать изучение языка ассемблера с реверсирования программ на языке HLL — не лучшая стратегия.

Лучше попробуйте прочитать и написать какой-нибудь нативный ассемблерный код. В Интернете есть много мест, где вы можете скачать такие примеры - очень простые и очень сложные, в зависимости от вашего прогресса. Я бы предложил использовать FASM. Существует доска объявлений с массой полезной информации и людьми, которые могут ответить на ваши вопросы.

person johnfound    schedule 13.07.2013
comment
Помимо изучения ассемблера, я хотел бы научиться читать дизассемблирование, производимое Windows. Поможет ли мне в этом изучение FASM/NASM? Или я должен изучать ассемблер, одновременно дизассемблируя программы HLL? - person Volatile; 14.07.2013
comment
Могу я спросить, что вы подразумеваете под офсетом? Вы имеете в виду разыменование указателя? Так как он следовал по запушенной локации в дампе и это приводило к Hello World, а Hello World не может быть в стеке (там, где переменная), я не понимаю, что вы имеете в виду под the offset of the address of some variable[i.e the location of a variable] is pushed in the stack? - person AStupidNoob; 14.07.2013
comment
@AStupidNoob Я на самом деле не знаю, что означает разыменование указателя. Каждая переменная имеет некоторый адрес. В архитектуре x86 адрес состоит из двух чисел — сегмента и смещения. Смещение — это просто смещение от начала сегмента. В плоской модели памяти (Windows, Linux и т. д.) вся доступная программе память размещается в одном единственном сегменте, поэтому программа работает только со смещениями ячеек памяти. В этом случае вы можете предположить, что смещение совпадает с адресом. - person johnfound; 14.07.2013
comment
Все, что я имел в виду под разыменованием указателя, это просто получение значения в этом месте, т. е. если apples равно 0x40123456 и есть значение 255 по адресу 0x40123456, то разыменование apples дает 255, потому что яблоки — это указатель на 255. Насколько я знаю, для сегмента и смещения нет двух ОТДЕЛЬНЫХ чисел: возможно, в исполняемом файле, но в памяти база сегмента добавляется к смещению, чтобы получить только один адрес. Итак, как PUSH OFFSET somevariablehere приходит к проталкиванию смещения Hello World в .data, если адрес somevariablehere находится в стеке - person AStupidNoob; 14.07.2013
comment
@Volatile Для чтения дизассемблирования, созданного Windows, ознакомьтесь с двухчастным руководством Мэтта Just Enough Assembly Language to Get By, написанным еще в 1998 году для MSJ. Часть 1 на microsoft.com/msj/0298/hood0298.aspx и часть 2 по адресу microsoft.com/msj/0698/hood0698.aspx. - person Marc Sherman; 19.07.2013