есть код на delphi Код (Text): function GetCallModuleName: string; var module : Cardinal; path : string; begin asm mov eax, [ebp+4] and eax, 0FFFFF000h @1: cmp word ptr [eax], 5A4Dh je @2 sub eax, 1000h jmp @1 @2: mov edx, [eax+3Ch] add edx, eax cmp dword ptr [edx], 4550h jne @1 mov module, eax end; SetLength(path, MAX_PATH); SetLength(path, GetModuleFileName(module, pchar(path), MAX_PATH)); Result := path; end; в итоге увидим имя модуля который вызвал эту функцию вопрос: как переделать функцию так, чтобы она возвращала имя модуля для функции в стеке на уровень ниже? то есть не для функции которая вызвала GetCallModuleName а для функции которая вызвала функцию которая вызвала GetCallModuleName
Если гарантированно есть стековые кадры (а они, судя по всему, есть), то так: Код (Text): mov eax, [ebp] mov eax, [eax+4] and eax, 0FFFFF000h
Както так: Код (Text): STACK_FRAME struct rEbp PVOID ? ; PSTACK_FRAME rEip PVOID ? STACK_FRAME ends PSTACK_FRAME typedef ptr STACK_FRAME Local LdrEntry:PLDR_DATA_TABLE_ENTRY mov ecx,NestingLevel mov ebx,ebp jecxz Ip assume ebx:PSTACK_FRAME @@: mov ebx,[ebx].rEbp loop @b Ip: invoke LdrFindEntryForAddress, [ebx].rEip, addr LdrEntry test eax,eax jnz Error
d2k9 RtlCaptureStackBackTrace() и RtlGetCallersAddress() сводятся к RtlWalkFrameChain(), а последняя сделана весьма хитрым образом. Проверяется вхождение адреса в проекцию не сканом базы данных загрузчика, а таблицы RtlpStkDllRanges в RtlpStkIsPointerInDllRange(), она заполняется сразу после проецирования модулей. Обычно это работает, но так всякие крипторы коих уже немеряно про эту переменную ничего не знают, посему функция будет лгать, хотя проекция модуля имеется и вход в лдр настроен. Следует использовать самостоятельную реализацию для бактрейса.