Фундаментальные основы хакерства




Идентификация конструктора и деструктора - часть 4


; освобождать особо нечего)

; таким образом, следующая функция – именно деструктор, а не что-нибудь еще

push   1

; количество байт для освобождения (необходимо для delete)

mov    ecx, esi

; готовим указатель this

call   __destructor

; вызываем деструктор

loc_0_401070:                     ; CODE XREF: main+25j

pop    esi

retn  

main         endp

__destructor proc near           ; CODE XREF: main+2Bp

; функция деструктора. Обратите внимание, что деструктор обычно вызывается

; из той же функции, что и delete (хотя так бывает и не всегда, но очень часто)

arg_0        = byte ptr  8

push   ebp

mov    ebp, esp

push   esi

mov    esi, ecx

call   Destructor

; вызываем функцию деструктора, определенную пользователем

test   [ebp+arg_0], 1

jz     short loc_0_40109A

push   esi

call   ??3@YAXPAX@Z ; operator delete(void *)

add    esp, 4

; освобождаем память, ранее выделенную объекту

loc_0_40109A:                     ; CODE XREF: __destructor+Fj

mov    eax, esi

pop    esi

pop    ebp

retn   4

__destructor endp

Листинг 39

::объекты в автоматической памяти или когда конструктор/деструктор идентифицировать невозможно. Если объект размещается в стеке (автоматической памяти), то никаких проверок успешности ее выделения не выполняется и вызов конструктора становится неотличим от вызова остальных функций. Аналогичная ситуация и с деструктором – стековая память автоматически освобождается по завершению функции, а вместе с ней умирает и сам объект безо всякого вызова delete (delete применяется только для удаления объектов из кучи).

Чтобы убедиться в этом, модифицируем функцию main нашего предыдущего примера следующим образом:

main()

{

MyClass zzz;

zzz.demo();

}

Листинг 40

Результат компиляции в общем случае должен выглядеть так:

main         proc near           ; CODE XREF: start+AFp

var_4        = byte ptr -4

; локальная переменная zzz – экземпляр объекта MyClass




Содержание  Назад  Вперед