Есть программа следующего содержания: Код (Text): #include <stdio.h> main() { int* yPtr; int y = 5; yPtr = &y; printf("Address of y: %p\n",&y); printf("Value of yPtr: %p\n",yPtr); printf("Address of yPtr: %p\n",&yPtr); printf("%d %d\n",sizeof(int*),sizeof(int)); return 0; } Как видно, здесь только две локальные переменные, причем обе они занимают 4 байта, то есть DWORD. Но почему-то IDA кроме них, показывает еще одну, размером с байт. Код (Text): .text:00411A30 var_D8 ; что это такое? .text:00411A30 var_14 ;это - int y .text:00411A30 var_8 ; int* yPtr .text:00411A30 Вопрос: зачем она нужна? У Криса Касперски этот вопрос как-то не затрагивается. (Просмотренные книги: "Образ мышления - дизассемблер IDA" и "Искусство дизассемблирования"). Прилагаю pdb - файл
Arman сегенрь асм-листинг и посмотри, там можно включить генерацию комментов как правило, или выложи полностью текст main'a. pdb не надо,
Вот полный ассемблерный листинг функции main() Код (Text): main proc near ; CODE XREF: j_mainj var_D8 = byte ptr -0D8h var_14 = dword ptr -14h var_8 = dword ptr -8 push ebp mov ebp, esp sub esp, 0D8h push ebx push esi push edi lea edi, [ebp+var_D8] mov ecx, 36h mov eax, 0CCCCCCCCh rep stosd mov [ebp+var_14], 5 lea eax, [ebp+var_14] mov [ebp+var_8], eax lea eax, [ebp+var_14] push eax push offset aAddressOfYP ; "Address of y: %p\n" call j_printf add esp, 8 mov eax, [ebp+var_8] push eax push offset aValueOfYptrP ; "Value of yPtr: %p\n" call j_printf add esp, 8 lea eax, [ebp+var_8] push eax push offset aAddressOfYptrP ; "Address of yPtr: %p\n" call j_printf add esp, 8 push 4 push 4 push offset aDD ; "%d %d\n" call j_printf add esp, 0Ch xor eax, eax push edx mov ecx, ebp push eax lea edx, word_411AC6 call j__RTC_CheckStackVars pop eax pop edx pop edi pop esi pop ebx add esp, 0D8h cmp ebp, esp call j__RTC_CheckEsp mov esp, ebp pop ebp retn main endp
Arman Используется для проверки от всяких buffer overflows imho. С какими ключами собирали? Версия cl? P.S. hint:
1) Есть такая переменная окружения ENC_CMD Ключи можно в ней задать по другому. 2) Я привык доверять глазам, а не словам. Взял этот исходник и откомпилил под Интел Си и в МС СИ выдернутом из VS2003NET. Никаких рабочих ячеек и никаких проверок стека. 3) Ну видно же, что Var_D8 просто указывает на место в стеке, которое затирают CCCCCCCC - защита от сплойтов. А уж почему ключи порылись - это другой вопрос.
Arman Ну, от сплоитов-не-от-сплоитов, но суть в том, что при компиляции дебажной версии программы данный компилятор заполняет выделенную под локальные переменные память этими байтами (0xCC). Лайк, меньше неопределённости - проще отладка.
0CCh - это int3 Это на случай если вдруг управление будет передано на данные, сработает отладочное прерывание для вылавливания таких случаев. То что код компилировался в Debug - это 100%
Arman Какие ссылки : ты хоть раз в экзешник от Вижуала глядел. Для выравнивания всегда заполняют CC. Я когда первый раз увидел - испугался : думаю крутая защита, все INT 3 заполнено. А оказывается это просто прием такой, чтобы при ошибках прога не могла далеко уйти. На стеке ссылок на сам стек тоже тьма, т.ч. return запросто может в стек пойти. Поэтому заполняя стек ССССССС защищаемся слегка от ошибок, ну и параллельно от переполнения буфера, наверное. Лень анализировать, но думаю и еще пару "полезностей" можно найти.
Arman О заполнении байтом 0xCC: http://www.docsultant.com/site2/articles\debug_codes.html http://weseetips.com/2008/04/29/crt-debug-support-the-magic-memory-values/ MSDN: http://msdn.microsoft.com/en-us/library/aa270812(VS.60).aspx