📄 fghook.cpp
字号:
// FGHOOK.cpp - main module for VxD FGHOOK
#define DEVICE_MAIN
#include "FGHOOK.h"
Declare_Virtual_Device(FGHOOK)
#undef DEVICE_MAIN
ppIFSFileHookFunc PrevHookProc=NULL; //Previos hook function.
KProtectedFileList protFileList;
KProtectedFileList recycledPathList; //Path of Recycle.
KHandleTable findHTable, openHTable;
KHotKey *pHotKey;
HANDLE hIniFile,hVM;
HANDLE hAppWnd=NULL; //Handle of win32 app.
char iniFilePath[MAX_PATH+1]="";
ParsedPath *pPPath;
BOOL bBusy, bAppReqBusy=FALSE; //bAppReqBusy--win32 app is about be write file.
WORD lastError=FG_ERR_SUCCESS;
UINT maxBakNum=DEF_MAX_BAK_NUM; //max backup file number.
//NOTICE: I don't know whether more than one object files will be linked properly,
//(And I haven't try it.) So I just include other cpp files in the main cpp file.
//This did not cause any problem.
#include "..\HookShr\KProtectedFileList.cpp"
#include "..\HookShr\HookCom.cpp"
#include "KHandleTable.cpp"
#include "KHotKey.cpp"
///////////////////////////////////////////////////////////////////
//Main interface:
FGHookVM::FGHookVM(VMHANDLE hVM) : VVirtualMachine(hVM) {}
FGHookThread::FGHookThread(THREADHANDLE hThread) : VThread(hThread) {}
BOOL FGHookDevice::OnSysDynamicDeviceInit()
{
#ifdef DEBUG
dout << "Hello from FGHook!" << endl;
#endif
bBusy=FALSE;
if(!(pPPath=(ParsedPath *)malloc(MAX_PATH*sizeof(WCHAR)+sizeof(ParsedPath))))
{
ErrorHandler(FG_ERR_NOT_ENOUGH_MEMORY);
ShellUnloadDevice();
return FALSE;
}
//Add recycled path.
int i;
char recycledPath[MAX_PATH]="A:\\RECYCLED\\*";
for(i=1; i<=32; i++) //Windows supports up to 32 drives.
{
recycledPath[0]=i+'A'-1;
recycledPathList.Add(recycledPath);
}
//intall key board hook:
pHotKey=new KHotKey;
pHotKey->hook();
return TRUE;
}
BOOL FGHookDevice::OnSysDynamicDeviceExit()
{
free(pPPath);
if(PrevHookProc)
IFSMgr_RemoveFileSystemApiHook(HookProc);
delete pHotKey;
#ifdef DEBUG
dout<<"Hook exit."<<endl;
#endif
return TRUE;
}
#ifdef DEBUG
void PrintUni(WCHAR *p, unsigned int len)
{
int i=0;
while(p[i] && i<len)
dout<<(char)p[i++];
dout<<endl;
i=0;
while(p[i] && i<len)
dout<<p[i++]<<" ";
dout<<endl;
}
#endif
DWORD FGHookDevice::OnW32DeviceIoControl(PIOCTLPARAMS pDIOCParams)
{
switch(pDIOCParams->dioc_IOCtlCode)
{
case DIOC_OPEN:
//SHELL_Message(pDIOCParams->dioc_hvm,MB_OK,"Device initialize.","FGHook message:",0,0,0);
break;
#ifdef DEBUG
case FG_DIOC_DEBUG:
break;
#endif
case FG_DIOC_INSTALL_HOOK:
#ifdef DEBUG
dout<<"Now install hook..."<<endl;
#endif
if((PrevHookProc=IFSMgr_InstallFileSystemApiHook(HookProc))==NULL)
ErrorHandler(FG_ERR_INSTALL_HOOK_FAIL);
protFileList.bDelBak=(UINT)pDIOCParams->dioc_InBuf & 0x1; //Get del & write proteciton options.
protFileList.bWriteBak=(((UINT)pDIOCParams->dioc_InBuf & 0x2)== 0x2);
break;
case FG_DIOC_UNINSTALL_HOOK:
if(PrevHookProc && IFSMgr_RemoveFileSystemApiHook(HookProc)==0)
PrevHookProc=NULL;
break;
case FG_DIOC_GET_HWND:
hAppWnd=*((HANDLE *)pDIOCParams->dioc_InBuf); //Retrieve hwnd of main window of win32 app.
break;
case FG_DIOC_FLUSH_PROTECTED_FILE_INFO: //==FG_DIOC_READ_PROTECTED_FILE_INFO
//Flush file information by reread from ini file.
protFileList.Empty();
if(pDIOCParams->dioc_InBuf)
strcpy(iniFilePath,(char *)pDIOCParams->dioc_InBuf);
else if(!*iniFilePath) strcpy(iniFilePath, "ProtFile.ini"); //default ini path.
#ifdef DEBUG
dout<<"INI Path:"<<iniFilePath<<endl;
#endif
ReadProtectedFileInfo(iniFilePath);
break;
case FG_DIOC_ADD_PROTECTED_FILE:
//Add new protected file.
protFileList.Add((PROTECTED_FILE *)pDIOCParams->dioc_InBuf);
break;
case FG_DIOC_REMOVE_PROTECTED_FILE:
protFileList.Remove((char *)pDIOCParams->dioc_InBuf);
break;
case FG_DIOC_EXTRA_INFO:
protFileList.bDelBak=(UINT)pDIOCParams->dioc_InBuf & 0x1; //Get del & write proteciton options.
protFileList.bWriteBak=(((UINT)pDIOCParams->dioc_InBuf & 0x2)== 0x2);
maxBakNum=(UINT)pDIOCParams->dioc_OutBuf;
break;
case FG_SET_DEVICE_BUSY:
bAppReqBusy=(BOOL)pDIOCParams->dioc_InBuf;
break;
}
_asm clc
return 0;
}
VOID FGHookDevice::PM_API_Entry(VMHANDLE hVM, CLIENT_STRUCT* pRegs)
{
}
//Hook Procedure: all protection is done though this function.
// Argument : pIFSFunc pfn
// address of the function which will perform this file operation.
// Argument : int fn
// number of the function which will perform this file operation.
// Argument : int CodePage
// current code page.
// Argument : pioreq pir
// It is the parameter to be passed to FSD function pfn.
// In many cases, pir->ir_ppath contain ParsedPath.
int _cdecl HookProc(pIFSFunc pfn, int fn, int Drive, int ResType, int CodePage, pioreq pir)
{
struct _QWORD res;
BOOL bLogHandle=FALSE; //Determine whether to add a handle to handle table(use in IFSFN_OPEN);
//bAppReqBusy: Win32 application of fileguard request busy. bBusy: used to prevent reentry.
if(bAppReqBusy || bBusy)
goto EXIT;
bBusy=TRUE;
if(protFileList.bIsHideOn && (fn==IFSFN_FILEATTRIB || fn==IFSFN_DIR || fn==IFSFN_SEARCH || fn==IFSFN_RENAME))
{
//Hide a file:
if(protFileList.IsUnderProtection(Drive, pir->ir_ppath, PT_HIDE))
{
bBusy=FALSE;
return (IFSFN_DIR? ERROR_PATH_NOT_FOUND : ERROR_FILE_NOT_FOUND);
}
}
switch(fn)
{
case IFSFN_DELETE:
{
//do delete protection:
if(!protFileList.bIsDelOn && !protFileList.bIsHideOn)
//If there is not protected file has protection type of PT_DELETE or PT_HIDE, skip.
break;
if(DoDeleteProtection(pir, Drive, CodePage)!=ERROR_SUCCESS)
{
bBusy=FALSE;
return pir->ir_error;
}
break;
} //case IFSFN_DELETE
case IFSFN_RENAME:
{
//prevent moving protected file to recycled.
if(!protFileList.bIsDelOn && !protFileList.bIsHideOn)
//If there is not protected file has protection type of PT_DELETE or PT_HIDE, skip.
break;
//Is the file being renamed to the recycle?
if(!recycledPathList.IsUnderProtection(Drive, pir->ir_ppath2)
|| DoDeleteProtection(pir, Drive, CodePage)==ERROR_SUCCESS)
break;
bBusy=FALSE;
return pir->ir_error;
} //case IFSFN_RENAME
case IFSFN_OPEN:
{
//If a file is opened with ACTION_REPLACEEXISTING, content of the file will be lost.
//so prevent this.
//And prevent opening hidden file.
//Determine whether or not to log open handle:
PROTECTED_FILE *pProtFile;
if(!(pProtFile=protFileList.IsUnderProtection(Drive, pir->ir_ppath)))
break;
else if(pProtFile->PF_type&(PT_READ|PT_DELETE))
bLogHandle=TRUE;
//determine whether the file is under protection.
if(!(protFileList.bIsHideOn || protFileList.bIsDelOn) || !(pProtFile=protFileList.IsUnderProtection(Drive, pir->ir_ppath, PT_DELETE|PT_HIDE)))
break;
if(!(ACTION_REPLACEEXISTING&pir->ir_options) && !(pProtFile->PF_type&PT_HIDE))
//the file is not to be hidden and it is not opened with ACTION_REPLACEEXISTING, skip.
break;
if(pProtFile->PF_type&PT_HIDE)
{
//protect hidden file.
bBusy=FALSE;
pir->ir_error=ERROR_FILE_NOT_FOUND;
return pir->ir_error;
}
else if(!protFileList.bDelBak)
{
//deny file operation.
ShellPostError(FG_ERR_WARNING, FG_WARN_PT_DELETE); //Send a warning.
bBusy=FALSE;
pir->ir_error=ERROR_ACCESS_DENIED;
return pir->ir_error;
}
//protect the file by rename it to *.BAK .
char pBCSPath[MAX_PATH+1];
UniToBCSPathEx((PUCHAR)pBCSPath,pir->ir_ppath->pp_elements,Drive,MAX_PATH,CodePage,&res);
if(FileRename(pBCSPath)==ERROR_SUCCESS)
{
//The file exists, so recreate it.
WORD error;
BYTE action;
HANDLE h=R0_OpenCreateFile(TRUE,pBCSPath,0,ATTR_NORMAL,ACTION_IFEXISTS_FAIL|ACTION_IFNOTEXISTS_CREATE,0,&error,&action);
R0_CloseFile(h,&error);
}
break;
} //case IFSFN_OPEN
case IFSFN_WRITE:
{
//do write protection.
if(!protFileList.bIsWriteOn)
//If there is not protected file has protection type of PT_WRITE, skip.
break;
//sometimes, a process writes zero bytes only to verify.
if(pir->ir_length==0) break;
//get full path.
int drive=Drive;
if(!GetFullNameByHandle(pir,drive,ResType,CodePage,pPPath, FALSE))
break;
//determine whether the file is under protection.
if(!protFileList.IsUnderProtection(drive, pPPath, PT_WRITE))
break;
if(!protFileList.bWriteBak)
{
//Deny write.
ShellPostError(FG_ERR_WARNING, FG_WARN_PT_WRITE); //Send a warning.
bBusy=FALSE;
pir->ir_error=ERROR_ACCESS_DENIED;
return pir->ir_error;
}
//protect the file by copying it to the .BAK file.
char pBCSPath[MAX_PATH+1];
UniToBCSPathEx((PUCHAR)pBCSPath,pPPath->pp_elements,Drive,MAX_PATH,CodePage,&res);
if(FileBackupByHandle(pir,drive,ResType,CodePage,pBCSPath)!=ERROR_SUCCESS && FileBackup(pBCSPath)!=ERROR_SUCCESS)
{
//if fail to back up the file then deny access.
bBusy=FALSE;
pir->ir_error=ERROR_ACCESS_DENIED;
return pir->ir_error;
}
break;
} //case IFSFN_WRITE
case IFSFN_READ:
{
//prevent process to read protected file.
//Read protection is not on or it is a pagging file.
if(!protFileList.bIsReadOn)
break;
//Get full path.
int drive=Drive;
if(!GetFullNameByHandle(pir,drive,ResType,CodePage,pPPath, FALSE))
break;
//determine whether the file is under protection.
if(!protFileList.IsUnderProtection(drive, pPPath, PT_READ))
break;
//deny read
ShellPostError(FG_ERR_WARNING, FG_WARN_PT_READ); //Send a warning.
bBusy=FALSE;
pir->ir_error=ERROR_ACCESS_DENIED;
return pir->ir_error;
break;
} //case IFSFN_READ
}
bBusy=FALSE;
EXIT:
int nRetVal=(*PrevHookProc)(pfn,fn,Drive,ResType,CodePage,pir);
//Win32 application of fileguard request busy.
if(bAppReqBusy)
return nRetVal;
//log open handle.
if(bLogHandle)
openHTable.Add(pir->ir_fh, Drive, pir->ir_ppath);
//if find or file is closed, delete the handle in handle table.
if(fn==IFSFN_FINDCLOSE)
findHTable.Delete(pir->ir_fh);
else if(fn==IFSFN_CLOSE && pir->ir_flags==CLOSE_FINAL)
openHTable.Delete(pir->ir_fh);
if(!bBusy && protFileList.bIsHideOn && !nRetVal && (fn==IFSFN_FINDNEXT || fn==IFSFN_FINDOPEN))
{
//Hide file in file operation FINDOPEN & FINDNEXT.
bBusy=TRUE;
int drive=Drive;
_WIN32_FIND_DATA *findData;
//Get search path:
switch(fn)
{
case IFSFN_FINDOPEN:
memcpy(pPPath, pir->ir_ppath, IFSPathSize(pir->ir_ppath)+sizeof(WCHAR));
findHTable.Add(pir->ir_fh, Drive, pPPath);
break;
case IFSFN_FINDNEXT:
if(!GetFullNameByHandle(pir, drive, ResType, CodePage, pPPath, TRUE))
{
bBusy=FALSE;
return nRetVal;
}
break;
}
//Now we will change the search path to file path which is found by FINDOPEN or FINDNEXT.
//get file directory from search path by removing the last component:
pPPath->pp_totalLength-=IFSLastElement(pPPath)->pe_length;
//get full path by adding file name to file directory.
findData=(_WIN32_FIND_DATA *)pir->ir_data;
IFSLastElement(pPPath)->pe_length=wstrlen(findData->cFileName)+sizeof(WCHAR);
memcpy(IFSLastElement(pPPath)->pe_unichars, findData->cFileName, IFSLastElement(pPPath)->pe_length);
StringUpper((WCHAR *)IFSLastElement(pPPath)->pe_unichars, IFSLastElement(pPPath)->pe_length-sizeof(WCHAR));
pPPath->pp_totalLength+=IFSLastElement(pPPath)->pe_length;
*(WCHAR *)((char *)pPPath+pPPath->pp_totalLength)=NULL;
//determine whether the file is under protection.
if(protFileList.IsUnderProtection(drive, pPPath, PT_HIDE))
{
bBusy=FALSE;
//now we are going to hide the protected file...
if(fn==IFSFN_FINDOPEN)
{
//if it is FINDOPEN operation, we should return the next file.
//using IFSMgr_Ring0_FileIO to find the next file.
_WIN32_FIND_DATA_BCS bcsFindData;
BOOL retVal;
retVal=R0_FindNextFile(pir->ir_fh, &bcsFindData, (PWORD)&pir->ir_error);
if(retVal)
{
//if the next file is found, convert _WIN32_FIND_DATA_BCS (the find data return by IFSMgr_Ring0_FileIO) to _WIN32_FIND_DATA ( the find data used by FS_FINDOPEN).
memcpy(pir->ir_data, &bcsFindData, sizeof(_WIN32_FIND_DATA_BCS)-sizeof(bcsFindData.cFileName)-sizeof(bcsFindData.cAlternateFileName));
BCSToUni(((_WIN32_FIND_DATA *)pir->ir_data)->cFileName, bcsFindData.cFileName, strlen((char *)bcsFindData.cFileName), CodePage, &res);
((_WIN32_FIND_DATA *)pir->ir_data)->cFileName[res.ddLower]=0;
BCSToUni(((_WIN32_FIND_DATA *)pir->ir_data)->cAlternateFileName, bcsFindData.cAlternateFileName, strlen((char *)bcsFindData.cAlternateFileName), CodePage, &res);
((_WIN32_FIND_DATA *)pir->ir_data)->cAlternateFileName[res.ddLower]=0;
}
return retVal;
}
else goto EXIT; //if it is FINDNEXT operation, go on to find next file.
}
bBusy=FALSE;
}
return nRetVal;
}
//Protected file on file delete, rename operation.
//Return value: return ERROR_SUCCESS indicates that the protected file has been back up, and
// the file operation can be continue. Otherwise the file operation should stop.
WORD DoDeleteProtection(ioreq *pir, int Drive, int CodePage)
{
struct _QWORD res;
char pBCSPath[MAX_PATH+1];
PROTECTED_FILE *pProtFile;
if(pir->ir_attr&FILE_FLAG_WILDCARDS || pir->ir_attr&FILE_FLAG_HAS_STAR)
{
//Deal with file name with wildcards.
//Convert from ParsedPath to BCS path.
UniToBCSPathEx((PUCHAR)pBCSPath, pir->ir_ppath->pp_elements, Drive, MAX_PATH, CodePage, &res);
//find first file.
_WIN32_FIND_DATA_BCS bcsFindData;
WORD error;
HANDLE hFind;
hFind=R0_FindFirstFile((PCHAR)pBCSPath, pir->ir_attr, &bcsFindData, &error);
CHAR pFindPath[MAX_PATH];
strcpy(pFindPath, pBCSPath);
_strupr(pFindPath);
while(error==ERROR_SUCCESS)
{
//Get full path by adding file name to file directory.
GetDir(pFindPath);
_strupr((PCHAR)bcsFindData.cFileName);
strcat(pFindPath, (PCHAR)bcsFindData.cFileName);
if((pProtFile=protFileList.IsUnderProtection(pFindPath, PT_DELETE|PT_HIDE))!=NULL)
{
if(pProtFile->PF_type&PT_HIDE)
{
//Protect hidden file.
pir->ir_error=ERROR_FILE_NOT_FOUND;
return pir->ir_error;
}
else if(protFileList.bDelBak)
{
//Deny delete.
if(!FileRename(pFindPath)==ERROR_SUCCESS) //Cannot rename the file, so deny access to the file.
return ERROR_ACCESS_DENIED;
}
else
{
//Back up on delete.
pir->ir_error=ERROR_ACCESS_DENIED;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -