/* * Copyright (c) 2004 Andy Polyakov * * Build with: * * cl -Ox -GD -GF -Zl -MD -LD bypacc.c advapi32.lib kernel32.lib * * See http://fy.chalmers.se/~appro/nt/DLL_PRELOAD/ for further details. * */ #ifndef _M_IX86 #error "x86 is the only supported, at least for now..." #endif #ifndef _DLL #error "_DLL is not defined." #endif #pragma comment(linker,"/entry:DllMain@12") #pragma comment(linker,"/section:.text,erw") #pragma comment(linker,"/merge:.rdata=.text") #pragma comment(linker,"/merge:.data=.text") #define UNICODE #define _UNICODE #if defined(WIN32) && !defined(_WIN32) #define _WIN32 #endif #define _WIN32_WINNT 0x0500 #include #include #include #include #ifdef _WIN64 /* October 2002 Platform SDK is screwed up */ #define _RUNTIME_FUNCTION _RUNTIME_FUNCTION_ #define RUNTIME_FUNCTION RUNTIME_FUNCTION_ #define PRUNTIME_FUNCTION PRUNTIME_FUNCTION_ #endif #include #ifndef FILE_DIRECTORY_FILE /* Excerpt from /inc/wdm.h */ #define FILE_DIRECTORY_FILE 0x00000001 #define FILE_WRITE_THROUGH 0x00000002 #define FILE_SEQUENTIAL_ONLY 0x00000004 #define FILE_NO_INTERMEDIATE_BUFFERING 0x00000008 #define FILE_SYNCHRONOUS_IO_ALERT 0x00000010 #define FILE_SYNCHRONOUS_IO_NONALERT 0x00000020 #define FILE_NON_DIRECTORY_FILE 0x00000040 #define FILE_CREATE_TREE_CONNECTION 0x00000080 #define FILE_COMPLETE_IF_OPLOCKED 0x00000100 #define FILE_NO_EA_KNOWLEDGE 0x00000200 #define FILE_OPEN_FOR_RECOVERY 0x00000400 #define FILE_RANDOM_ACCESS 0x00000800 #define FILE_DELETE_ON_CLOSE 0x00001000 #define FILE_OPEN_BY_FILE_ID 0x00002000 #define FILE_OPEN_FOR_BACKUP_INTENT 0x00004000 #define FILE_NO_COMPRESSION 0x00008000 #endif static int NtCreateMagic, NtOpenMagic; static void *_NtCreateFile, *_NtOpenFile; #undef IN #define IN volatile static NTSTATUS NtCreateFile_ ( void *ra, OUT PHANDLE FileHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes, OUT PIO_STATUS_BLOCK IoStatusBlock, IN PLARGE_INTEGER AllocationSize OPTIONAL, IN ULONG FileAttributes, IN ULONG ShareAccess, IN ULONG CreateDisposition, IN ULONG CreateOptions, IN PVOID EaBuffer OPTIONAL, IN ULONG EaLength ) { #if 0 OutputDebugStringW(ObjectAttributes->ObjectName->Buffer); #endif if (CreateOptions & FILE_OPEN_FOR_BACKUP_INTENT) CreateOptions |= FILE_DIRECTORY_FILE; else CreateOptions |= FILE_OPEN_FOR_BACKUP_INTENT; return NtCreateMagic; } static NTSTATUS NtOpenFile_ ( void *ra, OUT PHANDLE FileHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes, OUT PIO_STATUS_BLOCK IoStatusBlock, IN ULONG ShareAccess, IN ULONG OpenOptions ) { #if 0 OutputDebugStringW(ObjectAttributes->ObjectName->Buffer); #endif if (OpenOptions & FILE_OPEN_FOR_BACKUP_INTENT) OpenOptions |= FILE_DIRECTORY_FILE; else OpenOptions |= FILE_OPEN_FOR_BACKUP_INTENT; return NtOpenMagic; } #define B8_SIZE 5 static unsigned int PatchSysCall(void *syscall,void *patch, unsigned int *magic) { unsigned char *entry=(unsigned char *)syscall; DWORD acc; #ifdef _M_IX86 if (entry[0] != 0xb8) /* mov eax,imm32 */ return 0; if (VirtualProtect(entry,B8_SIZE,PAGE_EXECUTE_WRITECOPY,&acc) == 0) { OutputDebugString(_T("PatchSysCall: Unable to modify the code segment")); return 0; } *magic=*((unsigned int *)(entry+1)); entry[0] = 0xe8; /* call relative */ *((unsigned int *)(entry+1)) = (unsigned char *)patch -(entry+B8_SIZE); VirtualProtect(entry,B8_SIZE,acc,&acc); FlushInstructionCache(GetCurrentProcess(),entry,B8_SIZE); #endif return *magic; } static void UnpatchSysCall(void *syscall,unsigned int *magic) { unsigned char *entry=(unsigned char *)syscall; DWORD acc; if (*magic==0) return; #ifdef _M_IX86 if (VirtualProtect(entry,B8_SIZE,PAGE_EXECUTE_WRITECOPY,&acc) == 0) { OutputDebugString(_T("UnpatchSysCall: Unable to modify the code segment")); return; } entry[0] = 0xb8; /* mov eax,imm32 */ *((unsigned int *)(entry+1)) = *magic; magic=0; VirtualProtect(entry,B8_SIZE,acc,&acc); FlushInstructionCache(GetCurrentProcess(),entry,B8_SIZE); #endif } BOOL WINAPI DllMain (HINSTANCE h, DWORD reason, LPVOID junk) { HMODULE hmod; TOKEN_PRIVILEGES pst[2], /* not really, but it does the trick... */ *priv=pst; HANDLE hProc; switch (reason) { case DLL_PROCESS_ATTACH: DisableThreadLibraryCalls(h); if (!(hmod=GetModuleHandle(_T("NTDLL.DLL")))) { OutputDebugString(_T("NTDLL.DLL not found?")); return FALSE; } _NtCreateFile=GetProcAddress(hmod,"NtCreateFile"), _NtOpenFile=GetProcAddress(hmod,"NtOpenFile"); CloseHandle(hmod); if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES | TOKEN_ADJUST_DEFAULT, &hProc)) { OutputDebugString(_T("Failed to OpenProcessToken")); return FALSE; } memset (pst,0,sizeof(pst)); if (!LookupPrivilegeValue(NULL, SE_BACKUP_NAME, &priv->Privileges[0].Luid)) { OutputDebugString(_T("Failed to lookup SE_BACKUP_NAME")); CloseHandle(hProc); return FALSE; } if (!LookupPrivilegeValue(NULL, SE_RESTORE_NAME, &priv->Privileges[1].Luid)) { OutputDebugString(_T("Failed to lookup SE_RESTORE_NAME")); CloseHandle(hProc); return FALSE; } priv->PrivilegeCount = 2; priv->Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; priv->Privileges[1].Attributes = SE_PRIVILEGE_ENABLED; if (!AdjustTokenPrivileges(hProc, FALSE, priv, 0, NULL, 0) || GetLastError() != ERROR_SUCCESS) { OutputDebugString(_T("Failed to AdjustTokenPrivileges")); CloseHandle(hProc); return FALSE; } CloseHandle(hProc); PatchSysCall(_NtCreateFile,NtCreateFile_,&NtCreateMagic); PatchSysCall(_NtOpenFile,NtOpenFile_,&NtOpenMagic); break; case DLL_PROCESS_DETACH: UnpatchSysCall(_NtCreateFile,&NtCreateMagic); UnpatchSysCall(_NtOpenFile,&NtOpenMagic); break; } return TRUE; }