![]() |
eXeL@B —› Вопросы новичков —› Подскажите Asm |
Посл.ответ | Сообщение |
|
Создано: 12 октября 2013 22:03 · Личное сообщение · #1 sub esp,64h \\ Освобождаем память в стеке для переменных или чего либо еще. mov al,40 push ebx \ Толкаем стек Ebx push ebp \Толкаем стек Ebp push esi Толкаем стек Esi push edi Толкаем стек Edi mov [esp+74h+var_64],al \ в переменную var_64 загружается значение в al. Верно? Или в переменную по адресу esp+74h+var_64 мы заносим al. Как правильно спасибо! ![]() ![]() |
|
Создано: 12 октября 2013 22:09 · Личное сообщение · #2 |
|
Создано: 12 октября 2013 22:17 · Поправил: sivorog · Личное сообщение · #3 |
|
Создано: 12 октября 2013 22:18 · Поправил: reversecode · Личное сообщение · #4 |
|
Создано: 12 октября 2013 22:48 · Поправил: dosprog · Личное сообщение · #5 sivorog, > + текущее зн. var_64 -- var_64 не переменная, а константа, несмотря на то, что IDA её объявил как "var_64=byte ptr -64h" для индексации регистра EBP (или ESP, как в данном случае). А вот уже [var_64] - переменная. Просто так ИГ было удобнее, чем через "EQU" (и серьёзно экономится потом "пространство имён" при реассемблировании). Но задание констат через "=" - грубый приём в ассемблере, он влечёт за собой труднообнаружимые ошибки при случайном переопределении этой константы. А вот "EQU" не позволит случайно переопределить константу. ТС просто пытается модифицировать дизассемблерный листинг, и он наделает делОв с таким подходом. А вообще, всё это описано в любом учебнике по ассемблеру. Начинать нужно с программирования, а не с дизассемблирования, я так считаю. P.S. - reversecode, уточню, - "sub esp,64h" и следом "var_64" - это явно после IDA. Нужно понимать, как связаны между собой эти строчки, иначе будут подобные вопросы. Лучше начинать с простого. ![]() |
|
Создано: 13 октября 2013 14:23 · Личное сообщение · #6 Dimarik5 В квадратных скобках адрес задаётся, точнее смещение в сегменте(так как сегмент имеет нулевую базу, то смещение совпадает с линейным адресом). Исключение составляет инструкция LEA. [esp+74h+var_64] вообще бредовая запись. var_* обычно для bp-based, тоесть получается [esp + N + (ebp + M)]. Что это значит можно только гадать. ![]() |
|
Создано: 13 октября 2013 15:38 · Поправил: Модератор · Личное сообщение · #7 Dr0p пишет: [esp+74h+var_64] вообще бредовая запись. var_* обычно для bp-based, тоесть получается [esp + N + (ebp + M)]. Что это значит можно только гадать. ebp используется, чтобы иметь фиксированный адрес фрейма, тогда к стековой переменной из любой точки функции можно обращаться как ebp-varOffset. Если же обращаемся через esp, то последний сначала корректируется на начало фрейма, а потом от него также отсчитывается смещение переменной в фрейме: esp+(startESP-currentESP)-varOffset ![]() |
|
Создано: 13 октября 2013 16:01 · Личное сообщение · #8 |
|
Создано: 13 октября 2013 16:29 · Поправил: dosprog · Личное сообщение · #9 Уточню для внесения полной ясности. Два (основных) способа организации локальных переменных. 1) Один - стандартный. Этот генерируется большинством компиляторов: - - - - - - - - - - -- - - - - - - - -- - - - - - - >8 push ebp mov ebp,esp sub esp, LOCAL_VARIABLES_SIZE - - - - - - - - - - -- - - - - - - - --- - - - - - >8 -- тогда значение var_* для локальных переменных - отрицательное и минимальное значение имеет {-LOCAL_VARIABLES_SIZE} с базированием по EBP (он так и называется - "base pointer"). Для аргументов процедуры тогда - var_* всегда положительные. 2) А такой способ удобен при ручном программировании (и я видел такое после какого-то диковинного старинного компилятора 80-х годов): - - - - - - - - - - -- - - - - - - - -- - - - - - - >8 push ebp sub esp, LOCAL_VARIABLES_SIZE mov ebp,esp - - - - - - - - - - -- - - - - - - - --- - - - - - >8 -- тогда var_* - всегда положительные и для локальных переменных и для аргументов функции. Недостаток - заначение (*) для первого аргумента будет зависеть от (LOCAL_VARIABLES_SIZE+4*2). Достоинство - локальные переменные удобно описывать как STRUC. Это всё для FLAT модели, где все вызовы NEAR. При USE16 всё осложняется тем, что вызовы могут быть и FAR. В этих обоих способах область переменных задаётся регистром EBP как постоянное смещение в сегменте стека (с базой=0). И в том и в другом случае регистр EBP в процедуре изменяться не должен. Тогда IDA назначает корректные осмысленные имена для var_* и проблем нет. Такой способ организации стека, как в заголовке темы (третий способ), - извращение. Может применяться для обфускации ассемблерного текста. Адресация с переменной (esp) базой, зависящей от текущей наполненности стека. В данном конкретном случае [esp+74h+var_64] - это ячейка, в которой записан адрес возврата из процедуры ,это если всё-же принять, что var_64=-64h (иначе - да - это указатель в никуда). В младший байт этого адреса записывается 40. Но IDA такого не сгенерировал бы (я так думаю, не проверял). Интересующиеся могут провести эксперименты. --------------------------add----------------------------- P.S. - DenCoder в предыдущем посте как раз и осветил ошибочность моего последнего предположения. P.P.S - а также ClockMan в последующем. ![]() |
|
Создано: 13 октября 2013 16:41 · Личное сообщение · #10 dosprog пишет: Такой способ организации стека, как в заголовке темы, - извращение. Может применяться для обфускации ассемблерного текста. Файло из этой темы Смотрим функцию по адресу 00473E00 Asm Code:
IDA Code:
![]() ![]() ![]() ![]() ----- Чтобы правильно задать вопрос, нужно знать большую часть ответа. Р.Шекли. ![]() |
|
Создано: 13 октября 2013 16:45 · Поправил: dosprog · Личное сообщение · #11 |
|
Создано: 13 октября 2013 16:59 · Личное сообщение · #12 dosprog пишет: P.S. - DenCoder в предыдущем посте как раз и осветил последнее предположение Как бы это не предположение ![]() В настройках иды на вкладке Disassembly в груп-боксе Display disassembly line parts по умолчанию убран чек на Stack Pointer. Если поставить, то каждую строку с инструкцией будет предварять текущее относительное начала функции положение указателя стека. Оно сходится с тем же числом, что в инструкциях адресации локальных переменных в не ebp-based функциях ----- IZ.RU ![]() |
|
Создано: 13 октября 2013 22:36 · Личное сообщение · #13 |
|
Создано: 13 октября 2013 23:03 · Личное сообщение · #14 |
|
Создано: 13 октября 2013 23:18 · Поправил: dosprog · Личное сообщение · #15 rmn, насчёт вкусного - если с чем-то не согласны, напишите с чем. Увидели неточность - поправьте (если есть охота). А наезды взаимные неуместны. Dr0p, тут, по-моему, не в кривости IDA дело, а в том, что код писался вручную и намеренно не вполне аккуратно. А IDA-то справляется адекватно - ведь оттранслируется всё верно. ![]() |
|
Создано: 15 октября 2013 11:40 · Личное сообщение · #16 |
|
Создано: 15 октября 2013 16:19 · Личное сообщение · #17 dosprog > не в кривости IDA дело Именно в ней. Ида это шедевр, такого кривого дизасма нет нигде. ![]() |
|
Создано: 15 октября 2013 17:23 · Личное сообщение · #18 dosprog, Dr0p так а в чем кривость то? где вы там увидели обращение к локальным переменным и через esp и через ebp одновременно? Если компилятору регистров не хватило, он использует ebp как general purpose register и адресацию переменных через esp. Одновременное использование обоих регистров для адресации переменных возможно в случае, когда код пишет упоротый кодер на асме или дельфовый компилер такое может сгенерить: ebp указывает на общий фрейм top-level функции, а esp используется для адресации во фреймах вложенных функций. ![]() |
![]() |
eXeL@B —› Вопросы новичков —› Подскажите Asm |