简单之检测函数返回地址是否合法(控制流防护的缺陷)

来源:互联网 发布:海关数据购买 天津 编辑:程序博客网 时间:2024/06/15 05:47
#include "stdafx.h"#pragma pack(1)typedef struct _FUNCTION_RETURN_INFO {ULONG_PTR lEspAddress;ULONG_PTR lReturnAddress;} FUNCTION_RETURN_INFO, *PFUNCTION_RETURN_INFO;#pragma pack()static PFUNCTION_RETURN_INFO g_lpFunctionReturnInfo = NULL;static bool _cdecl InintCheckReturnCount(size_t uFunctionCount){const size_t uMallocSize = uFunctionCount * sizeof(FUNCTION_RETURN_INFO);g_lpFunctionReturnInfo = (PFUNCTION_RETURN_INFO)malloc(uMallocSize);if (NULL == g_lpFunctionReturnInfo)return false;memset(g_lpFunctionReturnInfo, 0, uMallocSize);return true;}static void _cdecl PushReturnInfo(DWORD dwFunctionIndex, ULONG_PTR lEspAddress){if (0U == g_lpFunctionReturnInfo[dwFunctionIndex].lReturnAddress){CONST UCHAR * lpFunctionPtr = (CONST UCHAR *)*PULONG_PTR(lEspAddress - (sizeof(ULONG_PTR) * 2U + sizeof(DWORD)));g_lpFunctionReturnInfo[dwFunctionIndex].lEspAddress = lEspAddress;lpFunctionPtr = lpFunctionPtr + 3U; do {if (0x0E8 == *lpFunctionPtr){g_lpFunctionReturnInfo[dwFunctionIndex].lReturnAddress = (ULONG_PTR)&lpFunctionPtr[5];return;}else if (0x15FF == *PUSHORT(lpFunctionPtr)){g_lpFunctionReturnInfo[dwFunctionIndex].lReturnAddress = (ULONG_PTR)&lpFunctionPtr[6];return;}} while (++lpFunctionPtr);}}static void _cdecl CheckReturnAddress(DWORD dwFunctionIndex, DWORD dwParamSize){register ULONG_PTR lCurReturnAddress = 0U;lCurReturnAddress = *PULONG_PTR(g_lpFunctionReturnInfo[dwFunctionIndex].lEspAddress - (sizeof(ULONG_PTR) + dwParamSize));if (g_lpFunctionReturnInfo[dwFunctionIndex].lReturnAddress != lCurReturnAddress){_asm INT 0x03;}}#define  _ININTCR(c) InintCheckReturnCount((c))#define _CRBEGIN(i) \_asm push esp \_asm push (i) \_asm call PushReturnInfo \_asm add esp, 0x08#define _CREND(i) \_asm push dwParamSize \_asm push (i) \_asm call CheckReturnAddress \_asm add esp, 0x08#define _CRPARAM register DWORD dwParamSize = #define _FCRS(p) sizeof((p))#define _NCRS(p) + sizeof((p))enum _function_name_index {add_number_index,sub_number_index};int _cdecl add_number(int x, int y);int _cdecl add_number(int x, int y){/*函数内容部分;......*///只需定义在函数结尾处的return之上即可_CRPARAM(_FCRS(x)_NCRS(y));  //该函数所有参数大小和_CREND(add_number_index);return (x + y);}int main(){_ININTCR(2U);_CRBEGIN(add_number_index); //必须放在检测函数之前add_number(1, 1);return 0;}

0 0
原创粉丝点击