Windows File Protection
We take the file sfc_os.aaa and find the offset 0xece9 and the bytes there should be 0x33c040 which we nop to 90 90 90. We copy this file over sfc_os.dll in windows/system32 and windows/system32/dllcache.
We first search for a key called
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon and within this we find a key called SFCDisable. We then double click on this key and change the value from 0 to 0xffffffd9.
C:\windowsfileprotection
#include "windows.h"
#include <stdio.h>
typedef DWORD (WINAPI *tpfn)(DWORD dwUnknown0, PWCHAR pwszFile, DWORD dwUnknown1);
HMODULE h;
tpfn pfn;
void main()
{
h=LoadLibrary("sfc_os.dll");
pfn = (tpfn)GetProcAddress(h , (LPCSTR)5);
pfn(0,L"c:\\windows\\system32\\calc.exe",-1);
DeleteFile("c:\\windows\\system32\\calc.exe");
FreeLibrary(h);
}
We get the address of unnamed ordinal 5 from sfc_os.dll and call it. The second parameter is the name of the file. We then delete calc.exe and it does not come back again.
C:\pwdump2
z.bat
del s.dll
cl -c s.c
link /dll s.obj user32.lib
del p.exe
del *.obj
cl -c -W0 p.c
link p.obj /out:p.exe user32.lib advapi32.lib
s.c
#include <windows.h>
typedef DWORD (WINAPI *tpfn)();
int WINAPI DllMain(HINSTANCE hinstDLL,DWORD fdwReason,LPVOID lpvReserv)
{
if ( fdwReason == DLL_PROCESS_ATTACH)
{
char aa[100];
HMODULE h;
tpfn pfn;
h=LoadLibrary("sfc_os.dll");
pfn = (tpfn)GetProcAddress(h , (LPCSTR)2);
pfn();
//GetModuleFileName(0,aa,100);
//MessageBox(0,aa,"hi",0);
}
return 1;
}
p.c
#include <windows.h>
HANDLE hpid,htok,hthread;
DWORD i,pid;
TOKEN_PRIVILEGES priv;
void *p;
void main (int argc, char *argv[])
{
pid = atoi (argv[1]);
OpenProcessToken (-1,TOKEN_ADJUST_PRIVILEGES,&htok); // -1 is the psedu value returned by GetCurrentProcess
LookupPrivilegeValue (0, SE_DEBUG_NAME,&priv.Privileges[0].Luid); //14
priv.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
priv.PrivilegeCount = 1;
AdjustTokenPrivileges(htok,FALSE,&priv,0,0,0);
hpid = OpenProcess(PROCESS_ALL_ACCESS,0,pid);
p = VirtualAllocEx(hpid,0,50,MEM_COMMIT,PAGE_READWRITE);
WriteProcessMemory(hpid,p,(void *)"c:\\pwdump2\\s.dll",50,NULL);
hthread = CreateRemoteThread(hpid,0,0,(LPTHREAD_START_ROUTINE) GetProcAddress(GetModuleHandle("kernel32"),"LoadLibraryA"),p, 0, &i);
WaitForSingleObject(hthread,INFINITE);
}
p 1412
In p.c we pass the handle or process id of winlogon.exe which is always 1412 on my copy of XP. We want to load s.dll into the address space of winlogon using the createremotethread method. We run the method LoadLibrary in the remote process passing its address and also the address of p which is the string s.dll as a parameter. thus we run the method LoadLibrary in the process space of winlogin which in turn loads s.dll In DllMain of s.dll we call method 2 which terminates the thread that checks for protected directory changes.
a.c
#include <windows.h>
#include <stdio.h>
typedef struct _UNICODE_STRING
{
USHORT Length,MaximumLength;
PWSTR Buffer;
} UNICODE_STRING;
typedef UNICODE_STRING *PUNICODE_STRING;
typedef struct HandleInfo
{
ULONG Pid;
USHORT ObjectType,HandleValue;
PVOID ObjectPointer;
ULONG AccessMask;
} HANDLEINFO, *PHANDLEINFO;
typedef struct SystemHandleInfo
{
ULONG nHandleEntries;
HANDLEINFO HandleInfo[1];
} SYSTEMHANDLEINFO, *PSYSTEMHANDLEINFO;
long (NTAPI *pNtQuerySystemInformation)(int SystemInformationClass,PVOID SystemInformation,ULONG SystemInformationLength,PULONG ReturnLength);
long (NTAPI *pNtQueryObject)(HANDLE ObjectHandle,int ObjectInformationClass,PVOID ObjectInformation,ULONG ObjectInformationLength,PULONG ReturnLength);
TOKEN_PRIVILEGES tp,oldtp;
HINSTANCE hNtDll;
PSYSTEMHANDLEINFO pSystemHandleInfo;
ULONG i, dwSize,dwPid;
HANDLE hWinLogon,hCopy,hToken;
struct
{
UNICODE_STRING Name;
WCHAR Buffer[MAX_PATH + 1];
}ObjName;
void main()
{
dwPid = 1416;
hNtDll = LoadLibrary("ntdll.dll");
pNtQuerySystemInformation=(long (NTAPI *)(int,PVOID,ULONG,PULONG))GetProcAddress(hNtDll,"NtQuerySystemInformation");
pNtQueryObject = (long (NTAPI *)(HANDLE,int, PVOID, ULONG, PULONG))GetProcAddress(hNtDll, "NtQueryObject");
OpenProcessToken((HANDLE)-1, TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES, &hToken);
LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &tp.Privileges[0].Luid);
tp.PrivilegeCount = 1;
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
AdjustTokenPrivileges(hToken, FALSE, &tp, sizeof(TOKEN_PRIVILEGES),&oldtp, &dwSize);
hWinLogon = OpenProcess(PROCESS_DUP_HANDLE, 0, dwPid);
pSystemHandleInfo = (PSYSTEMHANDLEINFO) VirtualAlloc(NULL, 512000, MEM_COMMIT, PAGE_READWRITE);
pNtQuerySystemInformation(16,pSystemHandleInfo, 512000, &dwSize);
for (i = 0; i < pSystemHandleInfo->nHandleEntries; i++)
{
if (pSystemHandleInfo->HandleInfo[i].Pid == dwPid)
{
DuplicateHandle(hWinLogon,(HANDLE)pSystemHandleInfo->HandleInfo[i].HandleValue,(HANDLE)-1,&hCopy,0,FALSE,DUPLICATE_SAME_ACCESS);
pNtQueryObject(hCopy, 1, &ObjName, sizeof (ObjName),NULL);
if ( CompareStringW(0, NORM_IGNORECASE,ObjName.Buffer, -1, L"\\DEVICE\\HARDDISKVOLUME1\\WINDOWS\\SYSTEM32", -1) == CSTR_EQUAL)
{
printf("%S\n",ObjName.Buffer);
CloseHandle(hCopy);
DuplicateHandle (hWinLogon,(HANDLE) pSystemHandleInfo->HandleInfo[i].HandleValue,GetCurrentProcess(), &hCopy, 0, FALSE,DUPLICATE_CLOSE_SOURCE | DUPLICATE_SAME_ACCESS);
CloseHandle(hCopy);
}
}
}
}
cl a.c advapi32.lib
The above program closes all handles that Winlogon has opened for the Windows/system32 directory. We first use the NtQuerySystemInformation function to get at all the handles created by all the processes. The number 16 gives us this information. The nHandleEntries member gives us the number of handles and we first choose the handles owned by Winlogon. This program normally has a pid of 1408, 1412 or 1416 and hence set variable dwpid accordingly. Once we have the handle owned by y WinLogon we now need the name of the handle which we get by the function NtQueryObject where 1 means object name. These names are in Unicode and hence we use the Unicode string methods. The Duplicate is needed always as we are in one process and we cannot work with handles of another process unless we Duplicate the handle in our process. Adds more code. Thus the first duplicate handle is for getting the name of the handle, the second for closing it. Thus we use the extra hash define for permission DUPLICATE_CLOSE_SOURCE or else we cannot close it.
We run the program and then delete calc.exe for windows\system32. As the directory change notifications handles have been removed, the WFP will never be notified of any changes in the files and hence windows thinks that no file in windows\system32 has been changed even though we have.