void func() { char buf[5]; printf("enter buff: "); ... } void main() { func(); printf("exit..."); } компилю прогу, смотрю в иде func: подскажите пожалуйста, почему после вызова func под buf выделяется 0Ch байт а не 08h , ведь по идее должно выделяться ближайшее значение кратное 4 (т.к. для ускорения доступа к данным компилятор размещает по адресам кратным четырем..) , так ведь? получается это компилятор так сделал? почему он посчитал все-таки не 8 а C зачем он так много выделил?
Code (Text): .text:00401000 sub_401000 proc near ; CODE XREF: sub_401050+3p .text:00401000 .text:00401000 var_C = byte ptr -0Ch .text:00401000 var_4 = dword ptr -4 .text:00401000 .text:00401000 push ebp .text:00401001 mov ebp, esp .text:00401003 sub esp, 0Ch .text:00401006 mov eax, dword_40D000 .text:0040100B xor eax, ebp .text:0040100D mov [ebp+var_4], eax .text:00401010 push offset aEnterBuff ; "enter buff: " .text:00401015 call sub_401295 .text:0040101A add esp, 4 .text:0040101D push offset aHyi ; "hyi: " .text:00401022 call sub_401295 .text:00401027 add esp, 4 .text:0040102A lea eax, [ebp+var_C] .text:0040102D push eax .text:0040102E call sub_40127F .text:00401033 add esp, 4 .text:00401036 mov ecx, [ebp+var_4] .text:00401039 xor ecx, ebp .text:0040103B call sub_40135A .text:00401040 mov esp, ebp .text:00401042 pop ebp .text:00401043 retn .text:00401043 sub_401000 endp
Code (Text): ; установка кукиса .text:00401006 mov eax, dword_40D000 ; mov eax, [_security_cookie] .text:0040100B xor eax, ebp .text:0040100D mov [ebp+var_4], eax ; проверка кукиса .text:00401036 mov ecx, [ebp+var_4] .text:00401039 xor ecx, ebp .text:0040103B call sub_40135A ; call __security_check_cookie Ключевые слова: /GS, _security_cookie, __security_check_cookie.
Sol_Ksacap про кукисы спасибо большое за информацию, я так понял это защита функции от переполнения буфера средствами компилятора только вот даже без функции, в моем случае это gets()(.text:0040102E call sub_40127F ), прога выделяет все равно 0Сh байт под буфер
Имеешь в виду, что даже если убрать вызов функции gets(), компилятор всё равно вставит gs-кукис? Т.е. интересует алгоритм, по которому vc вставляет подобную защиту? VC Team Blog on GS cookies – описано текущее положение (vc9) и будущее (vc10). Если интересует, как можно эту защиту отключить, то можно воспользовать ключ "/GS-". Если же мы неверно распарсили пост и имелось в виду что-то другое, то желательно переформулировать и выложить дизасм-листинг.
не так выразился) имею ввиду то что если убрать gets() то кукисов нет - это очевидно (уже), т.к. нечего защищащать, с ключом /GS разобрался, это кстати интересная штука, можно использовать уязвимые функции а компилятор сам защитит все переполнения вставив кукисы... я имел ввиду что в функции: void func() { char buf[5]; } памяти выделяется 0Ch именно под буфер размером 5, это просто особенность такая компилятора? а так же если buf[2000] то выделяется 7D8 что равно 2008 , т.е на 8 байт больше, чем размер буфера просто насколько мне известно из умных книг) размер выделяемой памяти должен быть кратен четырем естественно в большую сторону, т.е. когда я вижу буфер скажем размера 7D8 в IDA, то не имея исходника я предполагаю что программист задавал буфер размер которого в пределах 7D5..7D8 - и это абсолютно неверно!, и получается что размер буфера на самом деле был 7D0
Может и особенность. У нас такой особенности не замечено хотя. Code (Text): C:\Users\Mal\Desktop>type test.cpp void DoBuf(char*); void func5() { char buf[5]; DoBuf(buf); } void func2000() { char buf[2000]; DoBuf(buf); } C:\Users\Mal\Desktop>cl /Ox /c /GS- test.cpp Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 15.00.30729.01 for 80x86 Copyright (C) Microsoft Corporation. All rights reserved. test.cpp C:\Users\Mal\Desktop>dumpbin /disasm test.obj Microsoft (R) COFF/PE Dumper Version 9.00.30729.01 Copyright (C) Microsoft Corporation. All rights reserved. Dump of file test.obj File Type: COFF OBJECT ?func5@@YAXXZ (void __cdecl func5(void)): 00000000: 83 EC 08 sub esp,8 00000003: 8D 04 24 lea eax,[esp] 00000006: 50 push eax 00000007: E8 00 00 00 00 call ?DoBuf@@YAXPAD@Z 0000000C: 83 C4 0C add esp,0Ch 0000000F: C3 ret ?func2000@@YAXXZ (void __cdecl func2000(void)): 00000010: 81 EC D0 07 00 00 sub esp,7D0h 00000016: 8D 04 24 lea eax,[esp] 00000019: 50 push eax 0000001A: E8 00 00 00 00 call ?DoBuf@@YAXPAD@Z 0000001F: 81 C4 D4 07 00 00 add esp,7D4h 00000025: C3 ret
а у меня подругому во втором случае Code (Text): void func() { char buf[2000]; printf("enter buff: "); gets(buf); } cl /I "d:\Program Files\Microsoft Visual Studio 9.0\VC\Include" /I "D:\Program Files\Microsoft SDKs\Windows\v6.0A\Include" /c /GS- %1.cpp 00401000 /$ 55 PUSH EBP 00401001 |. 8BEC MOV EBP,ESP 00401003 |. 81EC D0070000 SUB ESP,7D0 00401009 |. 68 50B14000 PUSH func.0040B150 ; ASCII "enter buff: " 0040100E |. E8 62020000 CALL func.00401275 00401013 |. 83C4 04 ADD ESP,4 00401016 |. 8D85 30F8FFFF LEA EAX,DWORD PTR SS:[EBP-7D0] 0040101C |. 50 PUSH EAX ; /Arg1 0040101D |. E8 3D020000 CALL func.0040125F ; \func.0040125F 00401022 |. 83C4 04 ADD ESP,4 00401025 |. 8BE5 MOV ESP,EBP 00401027 |. 5D POP EBP 00401028 \. C3 RETN а если компилировать без /GS- Code (Text): 00401000 /$ 55 PUSH EBP 00401001 |. 8BEC MOV EBP,ESP 00401003 |. 81EC D8070000 SUB ESP,7D8 00401009 |. A1 00D04000 MOV EAX,DWORD PTR DS:[40D000] 0040100E |. 33C5 XOR EAX,EBP 00401010 |. 8945 FC MOV DWORD PTR SS:[EBP-4],EAX 00401013 |. 68 50B14000 PUSH func.0040B150 ; ASCII "enter buff: " 00401018 |. E8 68020000 CALL func.00401285 0040101D |. 83C4 04 ADD ESP,4 00401020 |. 8D85 28F8FFFF LEA EAX,DWORD PTR SS:[EBP-7D8] 00401026 |. 50 PUSH EAX ; /Arg1 00401027 |. E8 43020000 CALL func.0040126F ; \func.0040126F 0040102C |. 83C4 04 ADD ESP,4 0040102F |. 8B4D FC MOV ECX,DWORD PTR SS:[EBP-4] 00401032 |. 33CD XOR ECX,EBP 00401034 |. E8 11030000 CALL func.0040134A 00401039 |. 8BE5 MOV ESP,EBP 0040103B |. 5D POP EBP 0040103C \. C3 RETN вообщем лишние 8 байт в данном случае из-за ключа GS )