unit ApiHookContents; interface uses Winapi.Windows, System.SysUtils, System.Classes, Winapi.WinSock2, StrUtils, GlobalDefine, AppCtrlDefine, BsoneUtil, BsoneDebug, FileHandleListUnit, ObexParserUnit; const CMD_RESULT_ALLOW = 300; IMAGE_EXTS = 'PNG|JPG|JPEG|GIF|PCX|BMP'; METHOD_BUFFERED = 0; FILE_READ_ACCESS = 1; FILE_WRITE_ACCESS = 2; //#define IOCTL_SCSI_PASS_THROUGH_DIRECT CTL_CODE(IOCTL_SCSI_BASE, 0x0405, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS) IOCTL_SCSI_BASE = $00000004; SCSI_IOCTL_DATA_OUT = 0; SCSI_IOCTL_DATA_IN = 1; SCSI_IOCTL_DATA_UNSPECIFIED = 2; IOCTL_SCSI_PASS_THROUGH_DIRECT = ( IOCTL_SCSI_BASE shl 16) or ((FILE_READ_ACCESS or FILE_WRITE_ACCESS) shl 14) or ($0405 shl 2) or METHOD_BUFFERED; //#define IOCTL_WPD_MESSAGE_READWRITE_ACCESS CTL_CODE(FILE_DEVICE_WPD, WPD_CONTROL_FUNCTION_GENERIC_MESSAGE, METHOD_BUFFERED, (FILE_READ_ACCESS | FILE_WRITE_ACCESS)) FILE_DEVICE_WPD = $00000040; WPD_CONTROL_FUNCTION_GENERIC_MESSAGE = $00000042; IOCTL_WPD_MESSAGE_READWRITE_ACCESS = ( FILE_DEVICE_WPD shl 16) or ((FILE_READ_ACCESS or FILE_WRITE_ACCESS) shl 14) or (WPD_CONTROL_FUNCTION_GENERIC_MESSAGE shl 2) or METHOD_BUFFERED; // ($0036C004) type SCSI_PASS_THROUGH_DIRECT = packed record Length: Word; // USHORT ScsiStatus: Byte; // UCHAR PathId: Byte; // UCHAR TargetId: Byte; // UCHAR Lun: Byte; // UCHAR CdbLength: Byte; // UCHAR SenseInfoLength: Byte; // UCHAR DataIn: Byte; // UCHAR Padding0: array[0..2] of Byte; DataTransferLength: DWORD; // ULONG TimeOutValue: DWORD; // ULONG DataBuffer: Pointer; // PVOID SenseInfoOffset: DWORD; // ULONG Cdb: array[0..15] of Byte; // UCHAR Cdb[16] end; PSCSI_PASS_THROUGH_DIRECT = ^SCSI_PASS_THROUGH_DIRECT; TApiHookContents = class public fileHandleList_: TFileHandleList; appType_: TCurAppType; constructor Create(AppType: TCurAppType); destructor Destroy; override; function CreateFileProc(hFile: THandle; lpFileName: LPCWSTR; dwDesiredAccess, dwShareMode: DWORD; lpSecurityAttributes: PSecurityAttributes; dwCreationDisposition, dwFlagsAndAttributes: DWORD; hTemplateFile: THandle): Boolean; stdcall; function CloseHandleProc(hFile: THandle): BOOL; stdcall; function ReadFileProc(hFile: THandle; lpBuffer: Pointer; nNumberOfBytesToRead: DWORD; lpNumberOfBytesRead: PDWORD; lpOverlapped: POverlapped): BOOL; stdcall; function DeviceIoControlProc(hDevice: THandle; dwIoControlCode: DWORD; lpInBuffer: Pointer; nInBufferSize: DWORD; lpOutBuffer: Pointer; nOutBufferSize: DWORD; lpBytesReturned: PDWORD; lpOverlapped: POverlapped): BOOL; stdcall; function CreateFileMappingProc(hReturnFile: THandle;hFile: THandle; lpFileMappingAttributes: PSecurityAttributes; flProtect: DWORD; dwMaximumSizeHigh: DWORD; dwMaximumSizeLow: DWORD; lpName: PWideChar): Boolean; stdcall; function WSASendProc(s: TSocket; lpBuffers: PWSABuf; dwBufferCount: DWORD; lpNumberOfBytesSent: PDWORD; dwFlags: DWORD; lpOverlapped: POverlapped;lpCompletionRoutine: LPWSAOVERLAPPED_COMPLETION_ROUTINE): Integer; stdcall; function GetPathFromHandle(hFile: THandle; out sPath: string): BOOL; stdcall; function GetDriveBusType(DriveLetter: WideChar): STORAGE_BUS_TYPE; function GetOffLineType(dwType: DWORD; dwBusType: DWORD; pwszPath: PWideChar): string; function GetFileReadBuffer(const path: string; pbuffer: PByte; buffersize: DWORD): Boolean; stdcall; function IsExceptionPath(const APath: string): Boolean; end; TFun_DeviceIoControl = function( hDevice: THandle; dwIoControlCode: DWORD; lpInBuffer: Pointer; nInBufferSize: DWORD; lpOutBuffer: Pointer; nOutBufferSize: DWORD; lpBytesReturned: PDWORD; lpOverlapped: POverlapped ): BOOL; stdcall; TFun_WSASend = function( s: TSocket; lpBuffers: PWSABuf; dwBufferCount: DWORD; lpNumberOfBytesSent: PDWORD; dwFlags: DWORD; lpOverlapped: POverlapped; lpCompletionRoutine: LPWSAOVERLAPPED_COMPLETION_ROUTINE ): Integer; stdcall; TFun_CreateFileMappingW = function( hFile: THandle; lpFileMappingAttributes: PSecurityAttributes; flProtect: DWORD; dwMaximumSizeHigh: DWORD; dwMaximumSizeLow: DWORD; lpName: PWideChar ): THandle; stdcall; function DeviceIoControlHook( hDevice: THandle; dwIoControlCode: DWORD; lpInBuffer: Pointer; nInBufferSize: DWORD; lpOutBuffer: Pointer; nOutBufferSize: DWORD; lpBytesReturned: PDWORD; lpOverlapped: POverlapped ): BOOL; stdcall; function CreateFileMappingWHook( hFile: THandle; lpFileMappingAttributes: PSecurityAttributes; flProtect: DWORD; dwMaximumSizeHigh: DWORD; dwMaximumSizeLow: DWORD; lpName: PWideChar ): THandle; stdcall; function WSASendHook( s: TSocket; lpBuffers: PWSABuf; dwBufferCount: DWORD; lpNumberOfBytesSent: PDWORD; dwFlags: DWORD; lpOverlapped: POverlapped; lpCompletionRoutine: LPWSAOVERLAPPED_COMPLETION_ROUTINE ): Integer; stdcall; function ReadFileHook( hFile: THandle; lpBuffer: Pointer; nNumberOfBytesToRead: DWORD; lpNumberOfBytesRead: PDWORD; lpOverlapped: POverlapped ): BOOL; stdcall; function CheckContentPolicy(curAppType: TCurAppType; FileUseBlock: TFileUseBlock; const sPath: string; var IntBlockNewFile: TIntBlockNewFile; var resultMsg: string): Boolean; function CheckExternalPolicy(Cmd: Integer; const Data: string): Boolean; function CheckAppPolicy(var FileUseBlock: TFileUseBlock; sPath: string; var IntBlockNewFile: TIntBlockNewFile): Boolean; procedure SendHeCopyMessage(curAppType: TCurAppType; cmd: DWORD; const sPath: string; bExistsFile: Boolean; deviceName: string; resultMsg: string); var ozDeviceIoControl: TFun_DeviceIoControl = nil; ozCreateFileMappingW: TFun_CreateFileMappingW = nil; ozWSASend: TFun_WSASend = nil; gApiHookContents_: TApiHookContents = nil; ghooked_: boolean = False; implementation uses BS1Hook, Tocsg.Packet, Tocsg.Files, DefineHelper, ApiHookFile, superobject; function CheckExternalPolicy(Cmd: Integer; const Data: string): Boolean; var SendCopyDataResult: int64; begin var hReceiver := FindWindow(PChar('TDlgeCrmHeMain'), nil); SendCopyDataResult:= SendCopyData(gAppHook.Helper.CtrlOpt.hRcvWnd, Cmd, Data); DVLOG('CheckExternalPolicy: hReceiver (%d), Result(%d)', [DWORD(hReceiver),DWORD(SendCopyDataResult)]); Result := SendCopyDataResult = CMD_RESULT_ALLOW; end; function CheckAppPolicy(var FileUseBlock: TFileUseBlock; sPath: string; var IntBlockNewFile: TIntBlockNewFile): Boolean; begin Result := True; // 2. ÆÄÀÏ °áÀç ½ÂÀÎ ¿©ºÎ üũ if gAppHook.Helper.CtrlOpt.bFileApproval then begin if CheckExternalPolicy(HPCMD_APPROVAL_FILE, sPath) then begin DVLOG('CheckAppPolicy: HPCMD_APPROVAL_FILE not FileUseBlock(%d)', [DWORD(FileUseBlock)]); if FileUseBlock = fubBlock then FileUseBlock := fubMonitor; Result := False; end else begin DVLOG('CheckAppPolicy: HPCMD_APPROVAL_FILE ok FileUseBlock(%d)', [DWORD(FileUseBlock)]); end; end; end; function CheckFileNamePolicy(const FilePath: string; var IntBlockNewFile: TIntBlockNewFile): Boolean; var OnlyFileName: string; SearchTarget, FormattedList: string; begin Result := False; DVLOG('ProcMon:CheckFileNamePolicy.. blockByFilename_use(%d)', [DWORD(IntBlockNewFile.blockByFilename_use)]); if not IntBlockNewFile.blockByFilename_use then Exit; OnlyFileName := ExtractFileName(FilePath); OnlyFileName := LowerCase(OnlyFileName); FormattedList := LowerCase(IntBlockNewFile.blockByFilename_list); SearchTarget := '|' + OnlyFileName + '|'; FormattedList := '|' + FormattedList + '|'; DVLOG('ProcMon:CheckFileNamePolicy.. SearchTarget(%s), FormattedList(%s)', [SearchTarget, FormattedList]); Result := Pos(SearchTarget, FormattedList) > 0; end; function CheckSizePolicy(FilePath: string; var IntBlockNewFile: TIntBlockNewFile): Boolean; begin Result:= False; DVLOG('ProcMon:CheckSizePolicy.. blockBySizeLimit_use(%d)', [DWORD(IntBlockNewFile.blockBySizeLimit_use)]); if IntBlockNewFile.blockBySizeLimit_use then begin var ullLimitSize: ULONGLONG := IntBlockNewFile.blockBySizeLimit_minMb * 1048576; if GetFileSize_path(FilePath) >= ullLimitSize then Result:= True; end else exit; end; function CheckSigPolicy(FilePath: string; var IntBlockNewFile: TIntBlockNewFile): Boolean; var sExt: string; sFounds: string; ExtList: TStringList; begin Result := False; DVLOG('ProcMon:CheckSigPolicy.. blockBySig_use(%d)', [DWORD(IntBlockNewFile.blockBySig_use)]); if not IntBlockNewFile.blockBySig_use then Exit; sFounds := IntBlockNewFile.blockBySig_list; if sFounds = '' then Exit; sExt := UpperCase(ExtractFileExt(FilePath)); if (Length(sExt) > 0) and (sExt[1] = '.') then Delete(sExt, 1, 1); ExtList:= TStringList.Create; try ExtList.StrictDelimiter := True; ExtList.Delimiter := '|'; ExtList.DelimitedText := UpperCase(sFounds); if ExtList.IndexOf(sExt) > -1 then begin Result := True; end; finally ExtList.Free; end; end; function CheckContentPolicy(curAppType: TCurAppType; FileUseBlock: TFileUseBlock; const sPath: string; var IntBlockNewFile: TIntBlockNewFile; var resultMsg: string): Boolean; var O: ISuperObject; bBasicBlocked: Boolean; bInitialMonitor: Boolean; begin Result := False; bBasicBlocked := False; bInitialMonitor := (FileUseBlock = fubMonitor); if not bInitialMonitor then begin if CheckSizePolicy(sPath, IntBlockNewFile) then begin bBasicBlocked := True; resultMsg := 'Blocked by file size policy.'; end else if CheckFileNamePolicy(sPath, IntBlockNewFile) then begin bBasicBlocked := True; resultMsg := 'Blocked by file name policy.'; end else if CheckSigPolicy(sPath, IntBlockNewFile) then begin bBasicBlocked := True; resultMsg := 'Blocked by file extension policy.'; end; end; if bBasicBlocked then begin O := SO; O.S['Path'] := sPath; O.I['Type'] := Integer(curAppType); O.S['MName'] := gAppHook.ModuleName; O.S['resultMsg'] := resultMsg; DVLOG('CheckContentPolicy: HPCMD_BLOCK resultMsg(%s)', [resultMsg]); if CheckExternalPolicy(HPCMD_BLOCK, O.AsString) then begin DVLOG('CheckContentPolicy: HPCMD_BLOCK ok FileUseBlock(%d)', [DWORD(FileUseBlock)]); end; Result := True; exit; end; if IntBlockNewFile.contentsFilter_use then begin O := SO; O.S['Path'] := sPath; O.I['Type'] := Integer(curAppType); O.S['MName'] := gAppHook.ModuleName; resultMsg := 'Contents Policy.'; if CheckExternalPolicy(HPCMD_CHECK_CONTENT, O.AsString) then begin Result := True; if bInitialMonitor then FileUseBlock := fubMonitor else FileUseBlock := fubBlock; DVLOG('CheckContentPolicy: HPCMD_CHECK_CONTENT ok FileUseBlock(%d)', [DWORD(FileUseBlock)]); end else begin Result := False; FileUseBlock := fubMonitor; DVLOG('CheckContentPolicy: HPCMD_CHECK_CONTENT not FileUseBlock(%d)', [DWORD(FileUseBlock)]); end; end else begin if not bInitialMonitor and not bBasicBlocked then FileUseBlock := fubMonitor; end; end; procedure SendHeCopyMessage(curAppType: TCurAppType; cmd: DWORD; const sPath: string; bExistsFile: Boolean; deviceName: string; resultMsg: string); var llInfo: LONGLONG; Send: ISendPacket; begin try case cmd of NOTI_HOOK_MONITOR_ATTACH, NOTI_HOOK_BLOCK_ATTACH : begin llInfo := Integer(curAppType); end; else llInfo := 0; end; Send := TTgPacket.Create(ACC_NOTI_MSG); Send.I['Noti'] := cmd; Send.S['FDeviceName'] := deviceName; Send.S['MdName'] := gAppHook.ModuleName; Send.I['PID'] := gAppHook.PID; Send.S['FPath'] := sPath; Send.I['FType'] := 1; Send.I['Info'] := llInfo; Send.S['ResultMsg'] := resultMsg; if (gAppHook.Helper.CtrlOpt.hRcvWnd <> 0) then begin SendCopyData(gAppHook.Helper.CtrlOpt.hRcvWnd, HPCMD_HOOK_NOTI, Send.ToJsonString); end; except // ... end; end; constructor TApiHookContents.Create(AppType: TCurAppType); begin inherited Create; appType_:= appType; gApiHookContents_ := Self; fileHandleList_:= TFileHandleList.Create; //ghooked_:= True; end; destructor TApiHookContents.Destroy; begin FreeAndNil(fileHandleList_); ghooked_:= False; inherited Destroy; end; function TApiHookContents.GetPathFromHandle(hFile: THandle; out sPath: string): BOOL; stdcall; var dwRet, dwRequiredSize: DWORD; Buffer: array[0..1024] of WideChar; begin sPath := ''; Result := FALSE; dwRequiredSize := 1024; SetLength(sPath, dwRequiredSize); dwRet := GetFinalPathNameByHandleW(hFile, PWideChar(sPath), dwRequiredSize, VOLUME_NAME_DOS); if (dwRet > 0) and (dwRet < MAX_PATH) then begin Result := TRUE; end else if dwRet > MAX_PATH then begin dwRequiredSize := dwRet; DVLOG('GetPathFromHandle, Buffer is too small. Required size: %d', [dwRequiredSize]); SetLength(sPath, dwRequiredSize); dwRet := GetFinalPathNameByHandleW(hFile, PWideChar(sPath), dwRequiredSize, VOLUME_NAME_DOS); if (dwRet > 0) and (dwRet < dwRequiredSize) then begin Result := TRUE; end else begin //µÎ ¹øÂ° ½Ãµµµµ ½ÇÆÐ DVLOG('GetPathFromHandle, GetFinalPathNameByHandleW failed on second attempt: hFile(%x), GE(%x)', [hFile, GetLastError()]); sPath := ''; Result := FALSE; end; end else begin DVLOG('GetPathFromHandle, GetFinalPathNameByHandleW failed with error: hFile(%x), GE(%x)', [hFile, GetLastError()]); Result := FALSE; end; if Result then begin if StartsText('\\?\UNC\', sPath) then begin // '\\?\UNC\Server\Share' -> '\\Server\Share' Delete(sPath, 1, 7); // '\\?\UNC' (7±ÛÀÚ) »èÁ¦ Insert('\', sPath, 1); // ¸Ç ¾Õ¿¡ '\' Ãß°¡ (°á°ú: \\Server...) end else if StartsText('\\?\', sPath) then begin Delete(sPath, 1, 4); // '\\?\' (4±ÛÀÚ) »èÁ¦ end; end; end; function TApiHookContents.GetDriveBusType(DriveLetter: WideChar): STORAGE_BUS_TYPE; var hDevice: THandle; Query: STORAGE_PROPERTY_QUERY; Sdh: STORAGE_DESCRIPTOR_HEADER; Psdd: PSTORAGE_DEVICE_DESCRIPTOR; cbBytesReturned: DWORD; VolumePath: string; WindowsDir: array[0..MAX_PATH] of Char; ReturnType: STORAGE_BUS_TYPE; bDriverMatch: Boolean; begin // ÃʱâÈ­ ReturnType := BusTypeUnknown; cbBytesReturned := 0; Psdd := nil; bDriverMatch := False; // 1. À©µµ¿ì µð·ºÅ丮 µå¶óÀ̺ê È®ÀÎ ·ÎÁ÷ FillChar(WindowsDir, SizeOf(WindowsDir), 0); GetWindowsDirectory(WindowsDir, Length(WindowsDir)); // 2. ÀåÄ¡ ÇÚµé ¿­±â // °æ·Î »ý¼º: \\.\C: VolumePath := Format('\\.\%s:', [DriveLetter]); hDevice := ozCreateFileW(PChar(VolumePath), 0, // Query Access FILE_SHARE_READ or FILE_SHARE_WRITE, nil, OPEN_EXISTING, 0, 0); if hDevice = INVALID_HANDLE_VALUE then begin Result := ReturnType; Exit; end; try FillChar(Query, SizeOf(Query), 0); Query.PropertyId := StorageDeviceProperty; Query.QueryType := PropertyStandardQuery; if not ozDeviceIoControl(hDevice, IOCTL_STORAGE_QUERY_PROPERTY, @Query, SizeOf(Query), @Sdh, SizeOf(Sdh), PDWORD(cbBytesReturned), nil) then begin Exit; end; GetMem(Psdd, Sdh.Size); try FillChar(Psdd^, Sdh.Size, 0); if not ozDeviceIoControl(hDevice, IOCTL_STORAGE_QUERY_PROPERTY, @Query, SizeOf(Query), Psdd, Sdh.Size, PDWORD(cbBytesReturned), nil) then begin Exit; end; ReturnType := Psdd^.BusType; finally if Assigned(Psdd) then FreeMem(Psdd); end; finally if hDevice <> INVALID_HANDLE_VALUE then ozCloseHandle(hDevice); end; Result := ReturnType; end; function TApiHookContents.GetOffLineType(dwType: DWORD; dwBusType: DWORD; pwszPath: PWideChar): string; var OffType: string; VolumePath: string; hDevice: THandle; DeviceType: DWORD; ulCharacteristics: ULONG; MupPath: string; begin OffType := ''; case dwType of DRIVE_REMOVABLE: begin // µå¶óÀÌºê °æ·Î »ý¼º (¿¹: C -> \\.\C:) if pwszPath <> nil then VolumePath := Format('\\.\%s:', [pwszPath[0]]) else Exit(''); OffType := 'removalbe'; // ÀåÄ¡ ÇÚµé ¿­±â hDevice := ozCreateFileW(PChar(VolumePath), 0, FILE_SHARE_READ or FILE_SHARE_WRITE, nil, OPEN_EXISTING, 0, 0); if hDevice = INVALID_HANDLE_VALUE then Exit(''); try if UtilGetDriveTypeAndCharacteristics(hDevice, DeviceType, ulCharacteristics) then begin // FILE_FLOPPY_DISKETTE(0x4) À̰í FILE_DEVICE_DISK(0x7) ÀÎÁö È®ÀÎ if ((ulCharacteristics and $4) <> 0) and (DeviceType = $7) then begin OffType := 'floppy'; end; end; finally ozCloseHandle(hDevice); end; Result := OffType; Exit; end; DRIVE_REMOTE: OffType := 'networkdriveout'; DRIVE_CDROM: OffType := 'cdrom'; DRIVE_FIXED: begin dwBusType:= DWORD(GetDriveBusType(pwszPath[0])); // FIXED À̸鼭 USB Bus TypeÀÌ¸é ¿ÜÀåÇϵå if dwBusType = DWORD(BusTypeUsb) then OffType := 'externalhdd'; end; DRIVE_NO_ROOT_DIR: begin // ³×Æ®¿öÅ© °æ·Î(\Device\Mup\) È®ÀÎ MupPath := '\Device\Mup\'; if StrLIComp(pwszPath, PChar(MupPath), Length(MupPath)) = 0 then begin OffType := 'networkdriveout'; end; end; end; Result := OffType; end; function TApiHookContents.GetFileReadBuffer(const path: string; pbuffer: PByte; buffersize: DWORD): Boolean; stdcall; var size: DWORD; fp: THandle; Retsize: DWORD; bReadSuccess: Boolean; begin Result := FALSE; fp := INVALID_HANDLE_VALUE; Retsize := 0; fp := ozCreateFileW(PChar(path), GENERIC_READ, FILE_SHARE_READ, nil, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0); if fp = INVALID_HANDLE_VALUE then Exit; try size := GetFileSize(fp, nil); if (size = 0) or (size = INVALID_FILE_SIZE) then Exit; if size < MIN_BUFFERSIZE then Exit; if @ozReadFile = nil then bReadSuccess := ReadFile(fp, pbuffer^, buffersize, Retsize, nil) else bReadSuccess := ozReadFile(fp, pbuffer, buffersize, @Retsize, nil); Result := TRUE; finally ozCloseHandle(fp); end; end; function TApiHookContents.IsExceptionPath(const APath: string): Boolean; begin Result:= True; if ContainsText(APath, 'AppData\Roaming\Microsoft\Windows\Recent') or ContainsText(APath, '\desktop.ini') or ContainsText(APath, 'ProgramData\Microsoft\Windows\AppRepository\Packages') or ContainsText(APath, 'AppData\Roaming\Microsoft\Internet Explorer\Quick Launch') or ContainsText(APath, 'AppData\Roaming\Microsoft\Windows\SendTo') or ContainsText(APath, 'AppData\Roaming\Microsoft\Windows\Themes\') or ContainsText(APath, 'AppData\Roaming\Mozilla\Firefox\Profiles') or ContainsText(APath, 'program files\windowsapps\microsoft') or ContainsText(APath, 'AppData\Local\') or ContainsText(APath, '\Program Files\Tocsg\') or ContainsText(APath, '\ProgramData\Tocsg\bs1') or ContainsText(APath, '\\.\MountPointManager') or ContainsText(APath, '\\.\Global\vmhgfs') or ContainsText(APath, 'C:\Windows\') or ContainsText(APath, '\\.\Pipe\') or ContainsText(APath, 'wpd_data_') then Exit; Result:= False; end; function TApiHookContents.CreateFileProc(hFile: THandle; lpFileName: LPCWSTR; dwDesiredAccess, dwShareMode: DWORD; lpSecurityAttributes: PSecurityAttributes; dwCreationDisposition, dwFlagsAndAttributes: DWORD; hTemplateFile: THandle): Boolean stdcall; var sPath: string; begin Result:= False; if (hFile = 0) or (hFile = INVALID_HANDLE_VALUE) then Exit; if (gAppHook.Helper.CtrlOpt.IntMtpBlockNewFile.mode = abkNone) or (gAppHook.Helper.CtrlOpt.IntBtBlockNewFile.mode = abkNone) or (gAppHook.Helper.CtrlOpt.IntUsbToUsbBlockNewFile.mode = abkNone) then Exit; if dwCreationDisposition = CREATE_NEW then Exit; if dwCreationDisposition = TRUNCATE_EXISTING then Exit; if (dwFlagsAndAttributes and FILE_FLAG_BACKUP_SEMANTICS) <> 0 then Exit; if (dwFlagsAndAttributes and FILE_ATTRIBUTE_DIRECTORY) <> 0 then Exit; if (dwFlagsAndAttributes and FILE_FLAG_DELETE_ON_CLOSE) <> 0 then Exit; //FILE_ATTRIBUTE_NO_SCRUB_DATA 0x00020000 µ¥ÀÌÅÍ ½ºÅ©·¯ºù if (dwFlagsAndAttributes and (FILE_FLAG_OVERLAPPED or $20000)) = (FILE_FLAG_OVERLAPPED or $20000) then //MTP ¿ÀÇ °æ·Î°¡ ÇØ´ç ŸÀÔÀÏ ‹š µé¾î¿È... Exit; if (appType_ = catFquirt) then //or (gbsHook_.processType_ = ptExplore) begin if dwFlagsAndAttributes = 0 then Exit; end; sPath:= lpFileName; if (Length(sPath) >= 2) and (sPath[1] = '.') and (sPath[2] = '\') then Exit; if StartsText(sPath, 'C:\WINDOWS\') then Exit; if EndsText('.dll', sPath) or EndsText('.exe', sPath) then Exit; if ContainsText(sPath, '\bs1dc.json') then Exit; if IsExceptionPath(sPath) then Exit; if (appType_ = catExplorer) then //or (gbsHook_.processType_ = ptExplore) begin //explorer mtp Àü¼ÛÀ϶§ ¾Æ·¡ÀÇ °ªÀ» »ç¿ë //(C:\1234.pdf), c(3), s(5), d(80000000), f(80) if (dwCreationDisposition <> OPEN_EXISTING) and (dwShareMode <> GENERIC_READ) and (dwDesiredAccess <> FILE_FLAG_WRITE_THROUGH) and (dwFlagsAndAttributes <> FILE_ATTRIBUTE_NORMAL) then begin Exit; end; end; DVLOG('_CreateFileW: hFile(%p), (%s), c(%x), s(%x), d(%x), f(%x)', [Pointer(hFile), PChar(sPath), dwCreationDisposition, dwShareMode, dwDesiredAccess, dwFlagsAndAttributes]); fileHandleList_.InsertHandle(hFile, sPath, dwDesiredAccess, dwShareMode, dwCreationDisposition, dwFlagsAndAttributes); end; function TApiHookContents.CloseHandleProc(hFile: THandle): BOOL; stdcall; begin Result:= False; fileHandleList_.DelHandle(hFile); end; function TApiHookContents.ReadFileProc( hFile: THandle; lpBuffer: Pointer; nNumberOfBytesToRead: DWORD; lpNumberOfBytesRead: PDWORD; lpOverlapped: POverlapped ): BOOL; stdcall; const INVALID_SET_FILE_POINTER = DWORD(-1); var sPath: string; dwError: DWORD; dwBytesRead: DWORD; handleInfo: TFileHandle; CurrentPos: DWORD; IsStartOfFile: Boolean; begin Result:= False; if (lpBuffer = nil) or (not ghooked_) then begin Result := ozReadFile(hFile, lpBuffer, nNumberOfBytesToRead, lpNumberOfBytesRead, lpOverlapped); Exit; end; if appType_ = catExplorer then begin Result := ozReadFile(hFile, lpBuffer, nNumberOfBytesToRead, lpNumberOfBytesRead, lpOverlapped); Exit; end; IsStartOfFile := False; if lpOverlapped <> nil then begin if (lpOverlapped.Offset = 0) and (lpOverlapped.OffsetHigh = 0) then IsStartOfFile := True; end else begin CurrentPos := SetFilePointer(hFile, 0, nil, FILE_CURRENT); if (CurrentPos <> INVALID_SET_FILE_POINTER) and (CurrentPos = 0) then IsStartOfFile := True; end; if not IsStartOfFile then begin Result := ozReadFile(hFile, lpBuffer, nNumberOfBytesToRead, lpNumberOfBytesRead, lpOverlapped); Exit; end; Result := ozReadFile(hFile, lpBuffer, nNumberOfBytesToRead, lpNumberOfBytesRead, lpOverlapped); dwError := GetLastError; dwBytesRead := 0; if Result then begin // µ¿±â È£Ãâ ¼º°ø ½Ã ÀÐÀº Å©±â ȹµæ if lpNumberOfBytesRead <> nil then dwBytesRead := lpNumberOfBytesRead^ else dwBytesRead := 0; end else begin if dwError = ERROR_IO_PENDING then begin if (lpOverlapped <> nil) and GetOverlappedResult(hFile, lpOverlapped^, dwBytesRead, FALSE) then begin end else begin Exit; end; end else begin Exit; end; end; if dwBytesRead = 0 then Exit; // DVLOG('ReadFileProc: hFile(%p), nNumberOfBytesToRead(%d)', [Pointer(hFile), nNumberOfBytesToRead]); if fileHandleList_.IsHandle(hFile, handleInfo) then begin sPath := handleInfo.path; handleInfo.Free; fileHandleList_.InsertBufferForHandle(hFile, sPath, lpBuffer, dwBytesRead); DVLOG('ReadFileProc: hFile(%p), sPath(%s), nNumberOfBytesToRead(%d), lpNumberOfBytesRead(%p)', [Pointer(hFile), PChar(sPath), nNumberOfBytesToRead, Pointer(lpNumberOfBytesRead)]); end; end; function TApiHookContents.DeviceIoControlProc( hDevice: THandle; dwIoControlCode: DWORD; lpInBuffer: Pointer; nInBufferSize: DWORD; lpOutBuffer: Pointer; nOutBufferSize: DWORD; lpBytesReturned: PDWORD; lpOverlapped: POverlapped ): BOOL; stdcall; var data: PByte; size: DWORD; sbuff: string; inSize: DWORD; i: Integer; fileHandle: TFilehandle; sPath: string; // var IniFile: TIniFile; // var bBlock: Boolean; // var bDump: Boolean; scsi: PSCSI_PASS_THROUGH_DIRECT; // policy: TProcessPolicy; // devicePolicy: TDeviceControlPolicy; deviceName: string; block: Boolean; FileUseBlock: TFileUseBlock; resultMsg: string; curAppType: TCurAppType; begin data := nil; size := nInBufferSize; sbuff := ''; inSize := 0; block:= False; resultMsg := ''; Result:= True; if not ghooked_ then begin Exit; end; if (hDevice = INVALID_HANDLE_VALUE) or (lpInBuffer = nil) or ( nInBufferSize < 32 ) then begin Exit; end; if (dwIoControlCode <> IOCTL_SCSI_PASS_THROUGH_DIRECT) and (dwIoControlCode <> IOCTL_WPD_MESSAGE_READWRITE_ACCESS) then begin Exit; end; var bBlockIf: Boolean := true; var IntBlockNewFile: TIntBlockNewFile; // DVLOG('DeviceIoControlProc: FileUseBlock(%d)',[DWORD(FileUseBlock)]); // if FileUseBlock = fubNone then // Exit; // DVLOG('DeviceIoControlProc: hDevice(%p) size(%d) dwIoControlCode(%x)', [Pointer(hDevice), size, dwIoControlCode]); case dwIoControlCode of IOCTL_SCSI_PASS_THROUGH_DIRECT: begin if appType_ = catLINKENGKM then begin deviceName:= 'usbTousb'; curAppType:= catLINKENGKM; IntBlockNewFile:= gAppHook.Helper.CtrlOpt.IntUsbToUsbBlockNewFile; end else if appType_ = catExplorer then begin deviceName:= 'cdrom'; curAppType:= catCdrom; IntBlockNewFile:= gAppHook.Helper.CtrlOpt.IntCdromBlockNewFile; end else Exit; if IntBlockNewFile.mode = abkNone then exit else if IntBlockNewFile.mode = abkBlock then FileUseBlock := fubBlock else FileUseBlock := fubMonitor; //DVLOG('DeviceIoControlProc: FileUseBlock(%d)',[DWORD(FileUseBlock)]); if FileUseBlock = fubNone then Exit; try scsi := nil; scsi := PSCSI_PASS_THROUGH_DIRECT(lpInBuffer); if (scsi.DataIn = SCSI_IOCTL_DATA_OUT) and (scsi.DataBuffer <> nil) then begin data := PByte(scsi.DataBuffer); size := scsi.DataTransferLength; DVLOG('DeviceIoControlProc: scsi.PathId(%d), scsi.ScsiStatus(%d), scsi.TargetId(%d), size(%d)', [DWORD(scsi.PathId), DWORD(scsi.ScsiStatus), DWORD(scsi.TargetId) , DWORD(size)]); end else begin Exit; end; except on E: Exception do DVLOG('DeviceIoControlProc: Error accessing DataBuffer: %s', [PChar(E.Message)]); end; end; IOCTL_WPD_MESSAGE_READWRITE_ACCESS: begin if appType_ <> catExplorer then Exit; deviceName:= 'mtp'; curAppType:= catMtp; IntBlockNewFile:= gAppHook.Helper.CtrlOpt.IntMtpBlockNewFile; if IntBlockNewFile.mode = abkNone then exit else if IntBlockNewFile.mode = abkBlock then FileUseBlock := fubBlock else FileUseBlock := fubMonitor; data := PByte(lpInBuffer); size := nInBufferSize; end; else begin Exit; end; end; try //sbuff := UtilGetBufferHex(data, size, 50); //DVLOG('_DeviceIoControl: hDevice(%p) size(%d) data(%s)', [Pointer(hDevice), size, PChar(sbuff)]); //if devicePolicy.dump_ = 1 then // UtilSaveBufferToFile('c:\MTPMon\dump', data, size); if fileHandleList_.IsBufferCompare('', data, size, fileHandle) then begin sPath:= fileHandle.path; DVLOG('DeviceIoControlProc: IsBufferCompare ok', []); if FileUseBlock = fubBlock then bBlockIf:= CheckAppPolicy(FileUseBlock, sPath, IntBlockNewFile); bBlockIf:= CheckContentPolicy(curAppType, FileUseBlock, sPath, IntBlockNewFile, resultMsg); if not bBlockIf then begin DVLOG('DeviceIoControlProc: MATCHING!!!!!ALLOW!!!!! hDevice(%p)!! (%s), Matched Path: %s', [Pointer(hDevice), deviceName, PChar(fileHandle.path)]); SendHeCopyMessage(curAppType, NOTI_HOOK_MONITOR_ATTACH, sPath, True, deviceName, resultMsg); DVLOG('DeviceIoControlProc: MATCHING!!!!!ALLOW!!!!! OK....', []); end else begin DVLOG('DeviceIoControlProc: MATCHING!!!!!BLOCK!!!!! hDevice(%p)!! (%s), Matched Path: %s', [Pointer(hDevice), deviceName, PChar(fileHandle.path)]); SendHeCopyMessage(curAppType, NOTI_HOOK_BLOCK_ATTACH, sPath, True, deviceName, resultMsg); DVLOG('DeviceIoControlProc: MATCHING!!!!!BLOCK!!!!! OK....', []); end; fileHandle.Free; if bBlockIf then begin if appType_ = catLINKENGKM then begin // SetLastError(ERROR_DEV_NOT_EXIST); if (lpOutBuffer <> nil) and (nOutBufferSize >= 3) then begin PByte(NativeUInt(lpOutBuffer) + 2)^ := 0; end; if lpBytesReturned <> nil then begin lpBytesReturned^ := nOutBufferSize; end; SetLastError(ERROR_SUCCESS); Result := True; end else SetLastError(ERROR_ACCESS_DENIED); Result:= False; Exit; end; end; except on E: Exception do DVLOG('DeviceIoControlProc: Exception: %s', [PChar(E.Message)]); end; end; function TApiHookContents.CreateFileMappingProc( hReturnFile: THandle; hFile: THandle; lpFileMappingAttributes: PSecurityAttributes; flProtect: DWORD; dwMaximumSizeHigh: DWORD; dwMaximumSizeLow: DWORD; lpName: PWideChar ): Boolean; stdcall; var handleInfo: TFileHandle; sPath: string; buf: array[0..MIN_BUFFERSIZE - 1] of Byte; CheckSize: Int64; FileSizeHigh: DWORD; FileSizeLow: DWORD; pMem: Pointer; ViewSize: SIZE_T; begin Result:= False; if not (flProtect in [PAGE_READONLY, PAGE_READWRITE, PAGE_WRITECOPY]) then Exit; sPath:= ''; if fileHandleList_.IsHandle(hFile, handleInfo) then begin sPath:= handleInfo.path; handleInfo.Free; end else if GetPathFromHandle(hFile, sPath) then begin end else begin DVLOG('CreateFileMappingProc: not find handle', []); end; if sPath = '' then Exit; if EndsText('.dll', sPath) or EndsText('.exe', sPath) then Exit; if IsExceptionPath(sPath) then Exit; CheckSize := (Int64(dwMaximumSizeHigh) shl 32) or dwMaximumSizeLow; if CheckSize = 0 then begin FileSizeLow := GetFileSize(hFile, @FileSizeHigh); if FileSizeLow = INVALID_FILE_SIZE then Exit; CheckSize := (Int64(FileSizeHigh) shl 32) or FileSizeLow; end; if CheckSize < MIN_BUFFERSIZE then ViewSize := CheckSize else ViewSize := MIN_BUFFERSIZE; if ViewSize = 0 then Exit; DVLOG('CreateFileMappingProc: hFile(%p), sPath(%s), CheckSize(%d), dwMaximumSizeLow(%d), flProtect(%x)', [Pointer(hFile), PChar(sPath), CheckSize, dwMaximumSizeLow, flProtect]); try pMem := MapViewOfFile(hReturnFile, FILE_MAP_READ, 0, 0, ViewSize); if pMem <> nil then begin try Move(pMem^, buf[0], ViewSize); fileHandleList_.InsertBufferForHandle(hFile, sPath, @buf, ViewSize); DVLOG('CreateFileMappingProc: Data Cached via Mapping: %s', [PChar(sPath)]); finally UnmapViewOfFile(pMem); end; end else begin // ¸ÅÇÎ ½ÇÆÐ ·Î±× (±ÇÇÑ ¹®Á¦ µî) DVLOG('CreateFileMappingProc: MapViewOfFile Failed code: %d', [GetLastError]); end; except on E: Exception do DVLOG('CreateFileMappingProc: Exception: %s', [PChar(E.Message)]); end; end; function TApiHookContents.WSASendProc( s: TSocket; lpBuffers: PWSABuf; dwBufferCount: DWORD; lpNumberOfBytesSent: PDWORD; dwFlags: DWORD; lpOverlapped: POverlapped; lpCompletionRoutine: LPWSAOVERLAPPED_COMPLETION_ROUTINE ): Integer; stdcall; var data: PByte; size: DWORD; sbuff: string; inSize: DWORD; i: Integer; fileHandle: TFilehandle; sPath: string; sin: sockaddr_in; sinlen: Integer; ip: array[0..99] of AnsiChar; sIp: string; // policy: TProcessPolicy; // devicePolicy: TDeviceControlPolicy; ObexPacket: TObexPacket; opCode: Byte; sName: string; FileUseBlock: TFileUseBlock; deviceName: string; IntBlockNewFile: TIntBlockNewFile; resultMsg: string; curAppType: TCurAppType; begin deviceName:= 'BlueTooth'; FillChar(sin, SizeOf(sin), 0); FillChar(ip, SizeOf(ip), 0); Result:= 0; if ( not ghooked_ ) or ( lpBuffers = nil )then begin Exit; end; if (appType_ = catFquirt) then begin IntBlockNewFile:= gAppHook.Helper.CtrlOpt.IntBtBlockNewFile; deviceName:= 'BlueTooth'; curAppType:= catFquirt; end else if (appType_ = catLINKENGKM) then begin IntBlockNewFile:= gAppHook.Helper.CtrlOpt.IntUsbToUsbBlockNewFile; deviceName:= 'UsbToUsb'; curAppType:= catLINKENGKM; end else Exit; if IntBlockNewFile.mode = abkNone then exit else if IntBlockNewFile.mode = abkBlock then FileUseBlock := fubBlock else FileUseBlock := fubMonitor; var bBlockIf: Boolean := true; DVLOG('WSASendProc: FileUseBlock(%d)',[DWORD(FileUseBlock)]); if FileUseBlock = fubNone then Exit; ObexPacket := TObexPacket.Create; try data:= PByte(lpBuffers.buf); size:= lpBuffers.len; if (data = nil) or (Size < MIN_BUFFERSIZE) then begin Exit; end; // sIp:= ''; opCode:= data[0]; // if (opCode <> $82) or (size < 32) then // begin // DVLOG('_WSASend, : sBuff(%s) size(%d)', [opCode, size]); // Result:= WSASendNext(s, lpBuffers, dwBufferCount, lpNumberOfBytesSent, dwFlags, lpOverlapped, lpCompletionRoutine); // Exit; // end; // sinlen := SizeOf(sockaddr_in); // // getpeername(s, sockaddr(sin), sinlen); // sIp:= inet_ntoa(sin.sin_addr); // for i := 0 to size - 1 do // sBuff := sBuff + IntToHex(data[i], 2); // DVLOG('_WSASend, : sBuff(%s) size(%d)', [sBuff, size]); ObexPacket.Parse(data, size); DVLOG('WSASendProc: ObexPacket.Parse End',[]); if ObexPacket.Name <> '' then begin // ÆÄ½ÌµÈ µ¥ÀÌÅ͸¦ ¼Ó¼ºÀ¸·Î ½±°Ô Á¢±ÙÇÕ´Ï´Ù. // Name Çì´õ (0x01) DVLOG('WSASendProc: --- OBEX ÆÐŶ ºÐ¼® ---',[]); DVLOG('WSASendProc: Opcode: $%02x, Packet Length: %d, File Name: %s', [ObexPacket.Opcode, ObexPacket.PacketLength, PChar(ObexPacket.Name)]); sName:= ObexPacket.Name; // Length Çì´õ (0xC3) DVLOG('WSASendProc: Total File Size: %d bytes', [ObexPacket.TotalLength]); // Body Çì´õ (0x49) if Length(ObexPacket.Body) > 0 then begin DVLOG('WSASendProc: Body Length: %d bytes', [Length(ObexPacket.Body)]); // DVLOG(HexDump(ObexPacket.Body)); // ¹Ùµð ³»¿ë ´ýÇÁ (ÇÊ¿ä½Ã) end; end; ObexPacket.Free; if fileHandleList_.IsBufferCompare(sName, data, size, fileHandle) then begin sPath:= fileHandle.path; DVLOG('WSASendProc: IsBufferCompare ok, nBlockSizeMB(%d), bUseContentFilter(%d), bFileApproval(%d)', [ gAppHook.Helper.CtrlOpt.nBlockSizeMB, DWORD(gAppHook.Helper.CtrlOpt.bUseContentFilter), DWORD(gAppHook.Helper.CtrlOpt.bFileApproval) ]); if FileUseBlock = fubBlock then begin bBlockIf:= CheckAppPolicy(FileUseBlock, sPath, IntBlockNewFile); end; bBlockIf:= CheckContentPolicy(curAppType, FileUseBlock, sPath, IntBlockNewFile, resultMsg); if not bBlockIf then begin DVLOG('WSASendProc: MATCHING!!!!!ALLOW!!!!! hDevice(%p)!!, Path: (%s)', [Pointer(s), PChar(fileHandle.path)]); SendHeCopyMessage(curAppType, NOTI_HOOK_MONITOR_ATTACH, sPath, True, deviceName, resultMsg); DVLOG('WSASendProc: MATCHING!!!!!ALLOW!!!!! OK....(%d)', [DWORD(bBlockIf)]); end else begin DVLOG('WSASendProc: MATCHING!!!!!BLOCK!!!!! hDevice(%p)!!, Path: (%s)', [Pointer(s), PChar(fileHandle.path)]); SendHeCopyMessage(curAppType, NOTI_HOOK_BLOCK_ATTACH, sPath, True, deviceName, resultMsg); DVLOG('WSASendProc: MATCHING!!!!!BLOCK!!!!! OK....(%d)', [DWORD(bBlockIf)]); end; fileHandle.Free; if bBlockIf then begin Result:= SOCKET_ERROR; Exit; end; end else begin DVLOG('WSASendProc: IsBufferCompare not match', []); end; except on E: Exception do DVLOG('WSASendProc: Exception: %s', [PChar(E.Message)]); end; Result:= 0; end; function ReadFileHook( hFile: THandle; lpBuffer: Pointer; nNumberOfBytesToRead: DWORD; lpNumberOfBytesRead: PDWORD; lpOverlapped: POverlapped ): BOOL; stdcall; begin if gApiHookContents_ = nil then begin Result:= ozReadFile(hFile, lpBuffer, nNumberOfBytesToRead, lpNumberOfBytesRead, lpOverlapped); Exit; end; Result:= gApiHookContents_.ReadFileProc(hFile, lpBuffer, nNumberOfBytesToRead, lpNumberOfBytesRead, lpOverlapped); end; function DeviceIoControlHook( hDevice: THandle; dwIoControlCode: DWORD; lpInBuffer: Pointer; nInBufferSize: DWORD; lpOutBuffer: Pointer; nOutBufferSize: DWORD; lpBytesReturned: PDWORD; lpOverlapped: POverlapped ): BOOL; stdcall; begin if gApiHookContents_ <> nil then begin Result:= gApiHookContents_.DeviceIoControlProc(hDevice, dwIoControlCode, lpInBuffer, nInBufferSize, lpOutBuffer, nOutBufferSize, lpBytesReturned, lpOverlapped); if not result then Exit; end; Result:= ozDeviceIoControl(hDevice, dwIoControlCode, lpInBuffer, nInBufferSize, lpOutBuffer, nOutBufferSize, lpBytesReturned, lpOverlapped); end; function CreateFileMappingWHook( hFile: THandle; lpFileMappingAttributes: PSecurityAttributes; flProtect: DWORD; dwMaximumSizeHigh: DWORD; dwMaximumSizeLow: DWORD; lpName: PWideChar ): THandle; stdcall; begin Result:= ozCreateFileMappingW(hFile, lpFileMappingAttributes, flProtect, dwMaximumSizeHigh, dwMaximumSizeLow, lpName); if (not ghooked_) or (Result = 0) or (Result = INVALID_HANDLE_VALUE) then Exit; if hFile = INVALID_HANDLE_VALUE then Exit; if gApiHookContents_ <> nil then gApiHookContents_.CreateFileMappingProc(Result, hFile, lpFileMappingAttributes, flProtect, dwMaximumSizeHigh, dwMaximumSizeLow, lpName); end; function WSASendHook( s: TSocket; lpBuffers: PWSABuf; dwBufferCount: DWORD; lpNumberOfBytesSent: PDWORD; dwFlags: DWORD; lpOverlapped: POverlapped; lpCompletionRoutine: LPWSAOVERLAPPED_COMPLETION_ROUTINE ): Integer; stdcall; begin if gApiHookContents_ <> nil then begin Result:= gApiHookContents_.WSASendProc(s, lpBuffers, dwBufferCount, lpNumberOfBytesSent, dwFlags, lpOverlapped, lpCompletionRoutine); if Result = SOCKET_ERROR then begin WSASetLastError(WSAECONNABORTED); Exit; DVLOG('WSASendHook: Block!!!!!!!!!!!!',[]); end; end; Result:= ozWSASend(s, lpBuffers, dwBufferCount, lpNumberOfBytesSent, dwFlags, lpOverlapped, lpCompletionRoutine); end; end.