S. |
Here is yet another DLL_PRELOAD Windows module which
allows commodity programs executed by privileged user to bypass
access control mechanisms [therefore the name: BYPass
ACcess Control]. With this module pre-loaded you
[being a privileged user!] can traverse directories, open files and
manipulate ACLs on NTFS objects without regard to their effective
permissions. This is achieved by "unlocking" the Backup privilege
for current process and patching a system call to open all files
"for Backup." This is essentially what NTBACKUP.EXE
does... A reminder that DLL_PRELOAD works only with programs linked
with USER32.DLL is due here. Because
[X]CACLS.EXE are not linked with it and don't
work:-( So don't ask... Explorer works fine, but it's tricky to
pre-load the module on temporary need-for-a-moment basis. I
personally recommend [and stick to] following procedure:
- open Folder Options control panel
View pane and make sure you "Launch
folder windows in a separate process,"
- close all folder views and double-check that you have only
one explorer.exe process left running,
- open Command Prompt window and issue "set
DLL_PRELOAD=bypacc.dll" command followed by
"explorer,"
- at this point you should have unconstrained Explorer
window...
- proceed to step 2 when done!
 |
bypacc.c
|
/*
* 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;
}
|
|
|