The _ReturnAddress intrinsic provides the address of the instruction in the calling function that will be executed after control returns to the caller.
返回调用当前函数的,下一个控制权获得者的指令.
如下列伪代码:
function A()
addr = _ReturnAddress()
return addr
end
function B()
i = 4
addr = A()
i = 3 // addr == &(i = 3)
end
通常辅助另外一个函数,就获得一个Model的名字。
GetModuleNameByAddr((DWORD)pRetAddr, szModuleName, _countof(szModuleName));
{
BOOL XX::GetModuleNameByAddr(DWORD dwAddr, char *szName, UINT cch)
{
typedef struct _PEB_LDR_DATA { // Size = 0x24
ULONG Length; // 00
BOOLEAN Initialized; // 04
PVOID SsHandle; // 08
LIST_ENTRY InLoadOrderModuleList; // 0C
LIST_ENTRY InMemoryOrderModuleList; // 14
LIST_ENTRY InInitializationOrderModuleList; // 1C
// void * EntryInProgress; // 24
} PEB_LDR_DATA, *PPEB_LDR_DATA;
szName[0] = 0;
void *PEB = NULL,
*Flink = NULL,
*p = NULL;
PEB_LDR_DATA *pLdr = NULL;
__asm
{
mov edx,fs:[0x30]
mov PEB,edx
}
pLdr = *(PEB_LDR_DATA **)((char *)PEB + 0x0c);
Flink = &pLdr->InLoadOrderModuleList;
p = pLdr->InLoadOrderModuleList.Flink;
__try
{
do
{
void *pBaseAddress = *(void **)((char *)p + 0x18);
assert(pBaseAddress && ((DWORD)pBaseAddress & 0xFFFF) == 0);
if (!pBaseAddress)
break;
wchar_t *lpwszFullName = *( ( wchar_t ** )( ( unsigned char * )p + 0x28 ) );
DWORD dwImageSize = *( ( DWORD * )( ( unsigned char * )p + 0x20 ) );
if (dwAddr >= (DWORD)pBaseAddress && dwAddr < (DWORD)pBaseAddress + dwImageSize)
{
wchar_t *lpwszName = lpwszFullName;
for (int i = 0; lpwszFullName[i] != 0; i++)
{
if (lpwszFullName[i] == L'\\')
lpwszName = lpwszFullName + i + 1;
}
::WideCharToMultiByte(CP_ACP, 0, lpwszName, -1, szName, cch, NULL, NULL);
break;
}
p = *( ( void ** )p);
} while ( Flink != p );
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
assert(0);
}
return szName[0] != 0;
}
}
_ReturnAddress 需要做内联属性,所以在调用前,需要
#pragma intrinsic(_ReturnAddress)
这里有个主意事项,内联函数和_ReturnAddress的返回值,如果把一个函数内联,那么_ReturnAddress就会相应的提升到上一个回溯堆栈中,
也就意味着返回地址是上一级的调用返回地址。