Fixed the return values of a hook getting corrupted if another hook was called during the execution of the current hook (from Mr.Stalin)

Added a fix to prevent hook scripts from being executed when the depth limit is exceeded, or the hook is called recursively.
This commit is contained in:
NovaRain
2018-12-01 22:09:18 +08:00
parent db2c366376
commit c1b6e35a3f
3 changed files with 65 additions and 39 deletions
+53 -21
View File
@@ -8,14 +8,20 @@ namespace sfall
constexpr int maxArgs = 16; constexpr int maxArgs = 16;
constexpr int maxDepth = 8; constexpr int maxDepth = 8;
DWORD args[maxArgs]; // current hook arguments struct {
DWORD oldargs[maxArgs * maxDepth]; DWORD hookID;
DWORD* argPtr; DWORD argCount;
DWORD rets[16]; // current hook return values DWORD cArg;
DWORD cRet;
DWORD oldArgs[maxArgs];
DWORD oldRets[maxRets];
} savedArgs[maxDepth];
DWORD firstArg = 0; static DWORD callDepth;
DWORD callDepth; static DWORD currentRunHook = -1;
DWORD lastCount[maxDepth];
DWORD args[maxArgs]; // current hook arguments
DWORD rets[maxRets]; // current hook return values
DWORD argCount; DWORD argCount;
DWORD cArg; // how many arguments were taken by current hook script DWORD cArg; // how many arguments were taken by current hook script
@@ -52,19 +58,25 @@ bool LoadHookScript(const char* name, int id) {
} }
void _stdcall BeginHook() { void _stdcall BeginHook() {
if (callDepth <= maxDepth) { if (callDepth && callDepth <= maxDepth) {
if (callDepth) { // save all values of the current hook if another hook was called during the execution of the current hook
lastCount[callDepth - 1] = argCount; int cDepth = callDepth - 1;
memcpy(&oldargs[maxArgs * (callDepth - 1)], args, maxArgs * sizeof(DWORD)); savedArgs[cDepth].hookID = currentRunHook;
} savedArgs[cDepth].argCount = argCount; // number of arguments of the current hook
argPtr = args; savedArgs[cDepth].cArg = cArg; // current count of taken arguments
for (DWORD i = 0; i < callDepth; i++) { savedArgs[cDepth].cRet = cRet; // number of return values for the current hook
argPtr += lastCount[i]; memcpy(&savedArgs[cDepth].oldArgs, args, argCount * sizeof(DWORD)); // values of the arguments
} if (cRet) memcpy(&savedArgs[cDepth].oldRets, rets, cRet * sizeof(DWORD)); // return values
// for debugging
/*dlog_f("Saved cArgs/cRet: %d / %d(%d)\n", DL_HOOK, savedArgs[cDepth].argCount, savedArgs[cDepth].cRet, cRetTmp);
for (unsigned int i = 0; i < maxArgs; i++) {
dlog_f("Saved Args/Rets: %d / %d\n", DL_HOOK, savedArgs[cDepth].oldArgs[i], ((i < maxRets) ? savedArgs[cDepth].oldRets[i] : -1));
}*/
} }
callDepth++; callDepth++;
#ifndef NDEBUG #ifndef NDEBUG
dlog_f("Begin running hook, current depth: %d\n", DL_HOOK, callDepth); dlog_f("Begin running hook, current depth: %d, current executable hook: %d\n", DL_HOOK, callDepth, currentRunHook);
#endif #endif
} }
@@ -81,7 +93,15 @@ static void _stdcall RunSpecificHookScript(HookScript *hook) {
void _stdcall RunHookScript(DWORD hook) { void _stdcall RunHookScript(DWORD hook) {
cRet = 0; cRet = 0;
if (hooks[hook].size()) { if (hooks[hook].size()) {
dlog_f("Running hook %d, which has %0d entries attached\n", DL_HOOK, hook, hooks[hook].size()); if (callDepth > 1) {
if (hook == currentRunHook || callDepth > 8) {
fo::func::debug_printf("\n[SFALL] The hook ID: %d cannot be executed.", hook);
dlog_f("The hook %d cannot be executed due to exceeded depth limit or recursive calls\n", DL_MAIN, hook);
return;
}
}
currentRunHook = hook;
dlog_f("Running hook %d, which has %0d entries attached, depth: %d\n", DL_HOOK, hook, hooks[hook].size(), callDepth);
for (int i = hooks[hook].size() - 1; i >= 0; i--) { for (int i = hooks[hook].size() - 1; i >= 0; i--) {
RunSpecificHookScript(&hooks[hook][i]); RunSpecificHookScript(&hooks[hook][i]);
} }
@@ -92,12 +112,24 @@ void _stdcall RunHookScript(DWORD hook) {
void _stdcall EndHook() { void _stdcall EndHook() {
#ifndef NDEBUG #ifndef NDEBUG
dlog_f("End running hook, current depth: %d\n", DL_HOOK, callDepth); dlog_f("End running hook %d, current depth: %d\n", DL_HOOK, currentRunHook, callDepth);
#endif #endif
callDepth--; callDepth--;
if (callDepth && callDepth <= maxDepth) { if (callDepth && callDepth <= maxDepth) {
argCount = lastCount[callDepth - 1]; // restore all saved values of the previous hook
memcpy(args, &oldargs[maxArgs * (callDepth - 1)], maxArgs * sizeof(DWORD)); int cDepth = callDepth - 1;
currentRunHook = savedArgs[cDepth].hookID;
argCount = savedArgs[cDepth].argCount;
cArg = savedArgs[cDepth].cArg;
cRet = cRetTmp = savedArgs[cDepth].cRet; // also restore current count of the number of return values
memcpy(args, &savedArgs[cDepth].oldArgs, argCount * sizeof(DWORD));
if (cRet) memcpy(rets, &savedArgs[cDepth].oldRets, cRet * sizeof(DWORD));
// for debugging
/*dlog_f("Restored cArgs/cRets: %d / %d(%d)\n", DL_HOOK, argCount, cRet, cRetTmp);
for (unsigned int i = 0; i < maxArgs; i++) {
dlog_f("Restored Args/Rets: %d / %d\n", args[i], ((i < maxRets) ? rets[i] : -1));
}*/
} }
} }
-6
View File
@@ -27,14 +27,8 @@ struct HookScript {
extern std::vector<HookScript> hooks[]; extern std::vector<HookScript> hooks[];
extern DWORD args[]; // current hook arguments extern DWORD args[]; // current hook arguments
extern DWORD oldargs[];
extern DWORD* argPtr;
extern DWORD rets[]; // current hook return values extern DWORD rets[]; // current hook return values
extern DWORD firstArg;
extern DWORD callDepth;
extern DWORD lastCount[];
extern DWORD argCount; extern DWORD argCount;
extern DWORD cArg; // how many arguments were taken by current hook script extern DWORD cArg; // how many arguments were taken by current hook script
extern DWORD cRet; // how many return values were set by current hook script extern DWORD cRet; // how many return values were set by current hook script