* Copyright (c) 2018 Google, Inc. All rights reserved.
* Copyright (c) 2005-2008 VMware, Inc. All rights reserved.
* **********************************************************/
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* * Neither the name of VMware, Inc. nor the names of its contributors may be
* used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL VMWARE, INC. OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
* DAMAGE.
*/
* - we'll test here by hooking kernel32.dll and secur32.dll (LoadLibrary)
*/
* just to be sure
*
* FIXME: need to get this test also to be done like initapc.dll.c so that
* this all happens BEFORE we take control
**/
#include "tools.h"
#include <windows.h>
#define NAKED __declspec(naked)
enum { HOOK_SIZE = 0x1000 };
* NTSTATUS LdrLoadDll(LPCWSTR path_name, DWORD flags,
* PUNICODE_STRING libname, HMODULE* hModule)
*/
NAKED
hooker4()
{
__asm {
pusha
pushf
}
__asm {
popf
popa
}
__asm {
ret 4*4;
}
}
NAKED
hooker5()
{
__asm {
pusha
pushf
}
__asm {
popf
popa
}
__asm {
ret 5*4;
}
}
void
do_hook(const char *hook_dll, const char *hookfn, int args, int use_call)
{
HANDLE target_dll = GetModuleHandle(hook_dll);
unsigned char *hooktarget = (char *)GetProcAddress(target_dll, hookfn);
DWORD old_code1;
DWORD old_code2;
DWORD size = HOOK_SIZE;
DWORD prev = 0xbadcde;
int res;
DWORD pc_rel_target;
enum { op_JMP = 0xe9 };
enum { op_CALL = 0xe8 };
void *trampoline_target;
if (use_call)
args += 1;
if (hooktarget == NULL) {
print("BAD: couldn't find %s!%s\n", hook_dll, hookfn);
}
old_code1 = *(DWORD *)hooktarget;
old_code2 = *(DWORD *)(hooktarget + 1);
switch (args) {
case 4: trampoline_target = hooker4; break;
case 5: trampoline_target = hooker5; break;
default: print("BAD args\n");
}
__try {
*hooktarget = 0xba;
print("bad: why is this writable?\n");
} __except (EXCEPTION_EXECUTE_HANDLER) {
print("ok: can't write\n");
}
res = VirtualProtect(hooktarget, size, PAGE_EXECUTE_READWRITE, &prev);
print("VirtualProtect(%s!%s[" PFX "],%d,PAGE_EXECUTE_READWRITE,prev) = %d GLE=" PFMT
" prev=" PFMT "\n",
hook_dll, hookfn, (hooktarget , 0), size,
(res , 0), GetLastError(), prev);
#ifdef VERBOSE
print("before hooking %s = %02x %02x %02x %02x %02x\n", hookfn, hooktarget[0],
hooktarget[1], hooktarget[2], hooktarget[3], hooktarget[4]);
#endif
pc_rel_target = (DWORD)trampoline_target -
((DWORD)hooktarget + 5);
__try {
*hooktarget = use_call ? op_CALL : op_JMP;
*(DWORD *)(hooktarget + 1) = pc_rel_target;
#ifdef VERBOSE
print("after hooking %s = %02x %02x %02x %02x %02x\n", hookfn, hooktarget[0],
hooktarget[1], hooktarget[2], hooktarget[3], hooktarget[4]);
#endif
if (*(DWORD *)(hooktarget + 1) != pc_rel_target)
print("there be witches! what happened to my write?\n");
else
print("hooked %s\n", hookfn);
*(DWORD *)hooktarget = old_code1;
*(DWORD *)(hooktarget + 1) = old_code2;
print("restored old code\n");
} __except (EXCEPTION_EXECUTE_HANDLER) {
print("bad: can't write, though made writable\n");
}
res = VirtualProtect(hooktarget, size, PAGE_EXECUTE_READ, &prev);
print("VirtualProtect(%s[" PFX "],%d,PAGE_EXECUTE_READ,...) = %d GLE=" PFMT "\n",
hookfn, (hooktarget , 0), size, (res , 0),
GetLastError());
print("old permissions ...prev=" PFMT ")\n", prev);
__try {
*hooktarget = 0xba;
print("bad: why is this writable?\n");
} __except (EXCEPTION_EXECUTE_HANDLER) {
print("ok: can't write\n");
}
print("all should be good\n");
}
int
main()
{
INIT();
print("ready to hook\n");
do_hook("kernel32.dll", "GetProcessHeaps", 4, 1);
* same page as _SEH_prolog on xpsp2 machines.
* Don't forget to update the proc name in .template as well.
*/
#if 0
do_hook("kernel32.dll", "Sleep", 4, 0);
#else
do_hook("kernel32.dll", "VirtualQueryEx", 4, 0);
#endif
print("loading secur32\n");
LoadLibrary("secur32.dll");
do_hook("secur32.dll", "LsaLogonUser", 4, 0);
do_hook("secur32.dll", "MakeSignature", 4, 1);
* on each of 4 calls to do_hook
* should get app_modify_pretend_writes = 24
* FIXME: how to scrape a log for this?
*/
print("hooking done with\n");
}