unit BsoneMtpHook; interface uses Windows, Winapi.ShellAPI, System.Classes, Generics.Collections, Generics.Defaults, System.IOUtils, System.SysUtils, System.SyncObjs, System.StrUtils, IniFiles, Winapi.WinSock2, System.Math, winapi.WinInet, SuperObject, madCodeHook, madStrings, madTypes, DefineHelper, GlobalDefine, BsoneDebug, FileHandleListUnit, Bs1ContentsFlowPolicyUnit, ObexParserUnit, ApiHookExplorer, BsoneUtil; const 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; type TBsoneMtpHook = class public installpath_: string; currentPath_: string; processName_: string; processType_: TProcessType; fileHandleList_: TFileHandleList; policy_: TPolicyManager; constructor Create(h: HMODULE); destructor Destroy; override; function HookInit(h: HMODULE): integer; stdcall; function HookCleanup(): Integer; stdcall; function GetPathFromHandle(hFile: THandle; out sPath: string): BOOL; stdcall; end; TCreateFileW = function( lpFileName: LPCWSTR; dwDesiredAccess, dwShareMode: DWORD; lpSecurityAttributes: PSecurityAttributes; dwCreationDisposition, dwFlagsAndAttributes: DWORD; hTemplateFile: THandle ): THandle; stdcall; TCreateFileA = function( lpFileName: PAnsiChar; dwDesiredAccess, dwShareMode: DWORD; lpSecurityAttributes: PSecurityAttributes; dwCreationDisposition, dwFlagsAndAttributes: DWORD; hTemplateFile: THandle ): THandle; stdcall; TCloseHandle = function(hObject: THandle): BOOL; stdcall; TDeviceIoControl = function( hDevice: THandle; dwIoControlCode: DWORD; lpInBuffer: Pointer; nInBufferSize: DWORD; lpOutBuffer: Pointer; nOutBufferSize: DWORD; lpBytesReturned: PDWORD; lpOverlapped: POverlapped ): BOOL; stdcall; TReadFile = function( hFile: THandle; lpBuffer: Pointer; nNumberOfBytesToRead: DWORD; lpNumberOfBytesRead: PDWORD; lpOverlapped: POverlapped ): BOOL; stdcall; TSend = function(s: TSocket; buf: PAnsiChar; len: Integer; flags: Integer): Integer; stdcall; TWriteFile = function( hFile: THandle; const Buffer; nNumberOfBytesToWrite: DWORD; lpNumberOfBytesWritten: PDWORD; lpOverlapped: POverlapped ): BOOL; stdcall; TWSASend = function( s: TSocket; lpBuffers: PWSABuf; dwBufferCount: DWORD; lpNumberOfBytesSent: PDWORD; dwFlags: DWORD; lpOverlapped: POverlapped; lpCompletionRoutine: LPWSAOVERLAPPED_COMPLETION_ROUTINE ): Integer; stdcall; TCreateFileMappingW = function( hFile: THandle; lpFileMappingAttributes: PSecurityAttributes; flProtect: DWORD; dwMaximumSizeHigh: DWORD; dwMaximumSizeLow: DWORD; lpName: PWideChar ): THandle; stdcall; function _CreateFileW(lpFileName: LPCWSTR; dwDesiredAccess, dwShareMode: DWORD; lpSecurityAttributes: PSecurityAttributes; dwCreationDisposition, dwFlagsAndAttributes: DWORD; hTemplateFile: THandle): THandle; stdcall; function _CloseHandle(hObject: THandle): BOOL; stdcall; function _DeviceIoControl( hDevice: THandle; dwIoControlCode: DWORD; lpInBuffer: Pointer; nInBufferSize: DWORD; lpOutBuffer: Pointer; nOutBufferSize: DWORD; lpBytesReturned: PDWORD; lpOverlapped: POverlapped ): BOOL; stdcall; function _ReadFile( hFile: THandle; lpBuffer: Pointer; nNumberOfBytesToRead: DWORD; lpNumberOfBytesRead: PDWORD; lpOverlapped: POverlapped ): BOOL; stdcall; function _CreateFileMappingW( hFile: THandle; lpFileMappingAttributes: PSecurityAttributes; flProtect: DWORD; dwMaximumSizeHigh: DWORD; dwMaximumSizeLow: DWORD; lpName: PWideChar ): THandle; stdcall; function _WSASend( s: TSocket; lpBuffers: PWSABuf; dwBufferCount: DWORD; lpNumberOfBytesSent: PDWORD; dwFlags: DWORD; lpOverlapped: POverlapped; lpCompletionRoutine: LPWSAOVERLAPPED_COMPLETION_ROUTINE ): Integer; stdcall; function _send(s: TSocket; const buf: PAnsiChar; len: Integer; flags: Integer): Integer; stdcall; function _WriteFile( hFile: THandle; const Buffer: Pointer; nNumberOfBytesToWrite: DWORD; lpNumberOfBytesWritten: PDWORD; lpOverlapped: POverlapped ): BOOL; stdcall; function SendUI(block: Boolean; deviceName: string; sPath: string ; dPath: string): BOOL; stdcall; var gbsHook_: TBsoneMtpHook = nil; ghooked_: boolean = False; implementation var CreateFileWNext: TCreateFileW = nil; CreateFileANext: TCreateFileA = nil; CloseHandleNext: TCloseHandle = nil; DeviceIoControlNext: TDeviceIoControl = nil; CreateFileMappingWNext: TCreateFileMappingW = nil; WSASendNext: TWSASend = nil; ReadFileNext: TReadFile = nil; sendNext: TSend = nil; WriteFileNext: TWriteFile = nil; gProcessMap: TDictionary; function SendUI(block: Boolean; deviceName: string; sPath: string ; dPath: string): BOOL; stdcall; var hReceiver: HWND; begin hReceiver := FindWindow(PChar(BS1DC_CLASS_NAME), nil); var state: LRESULT; if hReceiver <> 0 then begin var O: ISuperObject := SO; O.S['T'] := deviceName; O.S['S'] := sPath; O.S['D'] := dPath; O.I['E'] := 1; O.B['B'] := block; O.B['N'] := true; // ³×Æ®¿öÅ© ÆÄÀÏ? state:= SendCopyData(hReceiver, HPCMD_FILE_OPERATION_NOTI, O.AsJSon); LOG('ProcMon: SendCopyData : %d', [DWORD(state)]); end else begin LOG('ProcMon: hReceiver not find window.......', []); end; end; constructor TBsoneMtpHook.Create(h: HMODULE); var buffer: array[0..MAX_PATH - 1] of WideChar; processPolicy: TProcessPolicy; begin inherited Create; GetModuleFileName(0, buffer, MAX_PATH); processName_:= TPath.GetFileName(buffer); var process := TPath.GetFileNameWithoutExtension(processName_).ToUpper; gProcessMap := TDictionary.Create; gProcessMap.Add('FSQUIRT', ptFquirt); gProcessMap.Add('EXPLORER', ptExplore); gProcessMap.Add('CMD', ptCmd); gProcessMap.Add('LINKENGKM', ptLINKENGKM); // LinkEngKM if not gProcessMap.TryGetValue(process, processType_) then begin processType_:= ptNone; Exit; end; // if not (SameText(processName_, 'explorer.exe') //Common(MTP) // or SameText(processName_, 'fsquirt.exe') or SameText(processName_, 'cmd.exe')) then //BlueToot policy_:= TPolicyManager.Create('C:\DeviceLock\bs1dc.json', processName_); policy_.GetPolicy; if policy_.CurrentProcessPolicy = nil then Exit; processPolicy:= policy_.CurrentProcessPolicy; for var s in processPolicy.DeviceTypes do LOG('TBsoneMtpHook.Create, : %s (%s)', [processName_, s]); gbsHook_ := Self; fileHandleList_:= TFileHandleList.Create; HookInit(h); if processType_ = ptExplore then begin LOG('TBsoneMtpHook.Create, : (%s), InstallFileOperationHooks', [processName_]); InstallFileOperationHooks; end; ghooked_:= True; end; destructor TBsoneMtpHook.Destroy; begin ghooked_:= False; UninstallFileOperationHooks; HookCleanup; FreeAndNil(fileHandleList_); FreeAndNil(gProcessMap); FreeAndNil(Policy_); gbsHook_ := nil; inherited Destroy; end; function TBsoneMtpHook.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; LOG('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 //µÎ ¹øÂ° ½Ãµµµµ ½ÇÆÐ LOG('GetPathFromHandle, GetFinalPathNameByHandleW failed on second attempt: hFile(%x), GE(%x)', [hFile, GetLastError()]); sPath := ''; Result := FALSE; end; end else begin LOG('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 TBsoneMtpHook.HookInit(h: HMODULE): integer; stdcall; begin CollectHooks; HookAPI('kernelbase.dll', 'CreateFileW', @_CreateFileW, @CreateFileWNext); HookAPI('kernelbase.dll', 'CloseHandle', @_CloseHandle, @CloseHandleNext); HookAPI('kernel32.dll', 'WriteFile', @_WriteFile, @WriteFileNext); HookAPI('kernelbase.dll', 'DeviceIoControl', @_DeviceIoControl, @DeviceIoControlNext); HookAPI('kernelbase.dll', 'CreateFileMappingW', @_CreateFileMappingW, @CreateFileMappingWNext); HookAPI('kernelbase.dll', 'ReadFile', @_ReadFile, @ReadFileNext); HookAPI('Ws2_32.dll', 'WSASend', @_WSASend, @WSASendNext); FlushHooks; LOG('HookInit, processName(%s)--', [PChar(processName_)]); end; function TBsoneMtpHook.HookCleanup(): Integer; stdcall; begin LOG('HookCleanup, --', []); end; function 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)); // // ÀÔ·ÂµÈ µå¶óÀÌºê ¹®ÀÚ°¡ À©µµ¿ì ¼³Ä¡ µå¶óÀ̺ê¿Í °°ÀºÁö È®ÀÎ (´ë¼Ò¹®ÀÚ ±¸ºÐ ¾øÀÌ ºñ±³ÇÏ·Á¸é UpCase ÇÊ¿ä) // if UpCase(WindowsDir[0]) = UpCase(DriveLetter) then // begin // if g_driverletter = DriveLetter then // begin // bDriverMatch := True; // end // else // begin // bDriverMatch := False; // // µð¹ö±× ·Î±× Ãâ·Â // DebugLog(Format('GetDriveBusType: Driver MisMatch PreDrive(%s) CurrentDrive(%s)!! Get Try BusType', // [g_driverletter, DriveLetter])); // end; // // // ÇöÀç µå¶óÀÌºê ¹®ÀÚ Ä³½Ì // g_driverletter := DriveLetter; // end; // // ij½ÌµÈ µå¶óÀ̺ê¿Í ÀÏÄ¡Çϸé Unknown ¸®ÅÏ (C++ ·ÎÁ÷ ±×´ë·Î ¹Ý¿µ) // if bDriverMatch then // begin // Result := BusTypeUnknown; // Exit; // end; // 2. ÀåÄ¡ ÇÚµé ¿­±â // °æ·Î »ý¼º: \\.\C: VolumePath := Format('\\.\%s:', [DriveLetter]); hDevice := CreateFileWNext(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 DeviceIoControlNext(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 DeviceIoControlNext(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 CloseHandleNext(hDevice); end; Result := ReturnType; end; function 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 := CreateFileWNext(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 CloseHandleNext(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 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 := CreateFileWNext(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 @ReadFileNext = nil then bReadSuccess := ReadFile(fp, pbuffer^, buffersize, Retsize, nil) else bReadSuccess := ReadFileNext(fp, pbuffer, buffersize, @Retsize, nil); Result := TRUE; finally CloseHandleNext(fp); end; end; function _CreateFileW(lpFileName: LPCWSTR; dwDesiredAccess, dwShareMode: DWORD; lpSecurityAttributes: PSecurityAttributes; dwCreationDisposition, dwFlagsAndAttributes: DWORD; hTemplateFile: THandle): THandle; stdcall; var sPath: string; begin sPath := lpFileName; Result := CreateFileWNext(lpFileName, dwDesiredAccess, dwShareMode, lpSecurityAttributes, dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile); if not ghooked_ then Exit; if (Result = 0) or (Result = INVALID_HANDLE_VALUE) then begin // LOG('_CreateFileW: INVALID_HANDLE_VALUE (%s)', [PChar(sPath)]); Exit; end; if dwCreationDisposition = CREATE_NEW then Exit; if dwCreationDisposition = TRUNCATE_EXISTING then Exit; // if (dwDesiredAccess and GENERIC_READ) = 0 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 (gbsHook_.processType_ = ptFquirt) then //or (gbsHook_.processType_ = ptExplore) begin if dwFlagsAndAttributes = 0 then Exit; end; if (Length(sPath) >= 2) and (sPath[1] = '.') and (sPath[2] = '\') then Exit; if StartsText('C:\WINDOWS\', sPath) then Exit; if SameText(ExtractFileExt(sPath), '.dll') then Exit; if ContainsText(sPath, '\bs1dc.json') then Exit; if ContainsText(sPath, '\\.\MountPointManager') then Exit; if gbsHook_.policy_.IsExceptionPath(sPath) then Exit; // if ContainsText(sPath, 'AppData\Roaming\Microsoft\Windows\Recent') or // ContainsText(sPath, '\desktop.ini') or // ContainsText(sPath, 'ProgramData\Microsoft\Windows\AppRepository\Packages') or // ContainsText(sPath, 'AppData\Local\Microsoft\Windows\Caches') or // ContainsText(sPath, 'AppData\Roaming\Microsoft\Internet Explorer\Quick Launch') or // ContainsText(sPath, 'AppData\Roaming\Microsoft\Windows\SendTo') or // ContainsText(sPath, 'AppData\Local\Microsoft\Windows\INetCache') or // ContainsText(sPath, 'AppData\Local\Microsoft\Windows\Explorer') or // ContainsText(sPath, 'AppData\Roaming\Microsoft\Windows\Themes\') or // ContainsText(sPath, 'AppData\Local\Packages\') or // ContainsText(sPath, 'wpd_data_') then // Exit; // var isTarget := ContainsText(sPath, 'mgkim.vmw11\Desktop\mtptest\'); // if isTarget then // begin LOG('_CreateFileW: (%p), (%s), dwCreationDisposition(%x), dwShareMode(%x), dwDesiredAccess(%x), dwFlagsAndAttributes(%x)', [Pointer(Result), PChar(sPath), dwCreationDisposition, dwShareMode, dwDesiredAccess, dwFlagsAndAttributes]); gbsHook_.fileHandleList_.InsertHandle(Result, sPath, dwDesiredAccess, dwShareMode, dwCreationDisposition, dwFlagsAndAttributes); // end; end; function _CreateFileMappingW( hFile: THandle; lpFileMappingAttributes: PSecurityAttributes; flProtect: DWORD; dwMaximumSizeHigh: DWORD; dwMaximumSizeLow: DWORD; lpName: PWideChar ): THandle; stdcall; var handleInfo: TFileHandle; sPath: string; buf: array[0..MIN_BUFFERSIZE - 1] of Byte; policy: TProcessPolicy; bufSize: DWORD; CheckSize: Int64; FileSizeHigh: DWORD; FileSizeLow: DWORD; pMem: Pointer; begin Result:= CreateFileMappingWNext(hFile, lpFileMappingAttributes, flProtect, dwMaximumSizeHigh, dwMaximumSizeLow, lpName); if (not ghooked_) or (Result = 0) then Exit; if hFile = INVALID_HANDLE_VALUE then Exit; sPath:= ''; if gbsHook_.fileHandleList_.IsHandle(hFile, handleInfo) then begin sPath:= handleInfo.path; handleInfo.Free; end else if gbsHook_.GetPathFromHandle(hFile, sPath) then begin end else begin LOG('_CreateFileMappingW, not find handle', []); end; if sPath = '' then Exit; if ContainsText(sPath, '\bs1dc.json') then Exit; if gbsHook_.policy_.IsExceptionPath(sPath) then Exit; // if ContainsText(sPath, 'AppData\Roaming\Microsoft\Windows\Recent') or // ContainsText(sPath, '\desktop.ini') or // ContainsText(sPath, 'ProgramData\Microsoft\Windows\AppRepository\Packages') or // ContainsText(sPath, 'AppData\Local\Microsoft\Windows\Caches') or // ContainsText(sPath, 'AppData\Roaming\Microsoft\Internet Explorer\Quick Launch') or // ContainsText(sPath, 'AppData\Roaming\Microsoft\Windows\SendTo') or // ContainsText(sPath, 'AppData\Local\Microsoft\Windows\INetCache') or // ContainsText(sPath, 'wpd_data_') 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 Exit; LOG('_CreateFileMappingW, hFile(%p), sPath(%s), dwMaximumSizeLow(%d), flProtect(%x)', [Pointer(hFile), PChar(sPath), dwMaximumSizeLow, flProtect]); // bufSize:= Sizeof(buf); // if GetFileReadBuffer(sPath, @buf, bufSize) then // begin // gbsHook_.fileHandleList_.InsertBufferForHandle(hFile, sPath, @buf, Sizeof(buf)); // end // else // LOG('_CreateFileMappingW, GetFileReadBuffer Fail!!', []); try // FILE_MAP_READ ±ÇÇÑÀ¸·Î ¾ÕºÎºÐ(MIN_BUFFERSIZE)¸¸ ¸ÅÇÎ pMem := MapViewOfFile(Result, FILE_MAP_READ, 0, 0, MIN_BUFFERSIZE); if pMem <> nil then begin try // ¸Þ¸ð¸® ³»¿ëÀ» ¹öÆÛ·Î º¹»ç Move(pMem^, buf[0], MIN_BUFFERSIZE); // ¸®½ºÆ®¿¡ µî·Ï // (ÁÖÀÇ: InsertBufferForHandle ³»ºÎ¿¡¼­ bufÀÇ º¹»çº»À» ¸¸µé¾î¾ß ¾ÈÀüÇÔ) gbsHook_.fileHandleList_.InsertBufferForHandle(hFile, sPath, @buf, MIN_BUFFERSIZE); LOG('_CreateFileMappingW Data Cached via Mapping: %s', [PChar(sPath)]); finally UnmapViewOfFile(pMem); end; end else begin // ¸ÅÇÎ ½ÇÆÐ ·Î±× (±ÇÇÑ ¹®Á¦ µî) LOG('_CreateFileMappingW: MapViewOfFile Failed code: %d', [GetLastError]); end; except on E: Exception do LOG('_CreateFileMappingW Exception: %s', [PChar(E.Message)]); end; end; function _ReadFile( 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 // 1. ±âº» À¯È¿¼º °Ë»ç if (lpBuffer = nil) or (not ghooked_) then begin Result := ReadFileNext(hFile, lpBuffer, nNumberOfBytesToRead, lpNumberOfBytesRead, lpOverlapped); Exit; end; // 2. Ž»ö±â ¿¹¿Ü ó¸® (ÇÊ¿ä ½Ã À¯Áö) if gbsHook_.processType_ = ptExplore then begin Result := ReadFileNext(hFile, lpBuffer, nNumberOfBytesToRead, lpNumberOfBytesRead, lpOverlapped); Exit; end; // --------------------------------------------------------------------------- // [¿äûÇϽŠºÎºÐ] ÆÄÀÏÀÇ ½ÃÀÛÁ¡(Offset 0)ÀÎÁö È®ÀÎ // --------------------------------------------------------------------------- IsStartOfFile := False; if lpOverlapped <> nil then begin // [Case A] ºñµ¿±â(Overlapped) I/O: ±¸Á¶Ã¼ÀÇ Offset Çʵ带 È®ÀÎÇØ¾ß ÇÔ // Offset°ú OffsetHigh°¡ µÑ ´Ù 0À̾î¾ß ÁøÂ¥ 0¹øÁöÀÓ if (lpOverlapped.Offset = 0) and (lpOverlapped.OffsetHigh = 0) then IsStartOfFile := True; end else begin // [Case B] µ¿±â(Synchronous) I/O: SetFilePointer·Î ÇöÀç À§Ä¡ È®ÀÎ // 0, nil, FILE_CURRENT -> À§Ä¡ À̵¿ ¾øÀÌ ÇöÀç À§Ä¡¸¸ ¹Ýȯ CurrentPos := SetFilePointer(hFile, 0, nil, FILE_CURRENT); // ¿¡·¯°¡ ¾Æ´Ï°í, À§Ä¡°¡ 0ÀÌ¸é ½ÃÀÛÁ¡ÀÓ if (CurrentPos <> INVALID_SET_FILE_POINTER) and (CurrentPos = 0) then IsStartOfFile := True; end; // [ÇÙ½É] ½ÃÀÛ ºÎºÐÀÌ ¾Æ´Ï¸é -> ±×³É ÀÐ°í ³¡³¿ (°Ë»ç ÆÐ½º) if not IsStartOfFile then begin Result := ReadFileNext(hFile, lpBuffer, nNumberOfBytesToRead, lpNumberOfBytesRead, lpOverlapped); Exit; end; // --------------------------------------------------------------------------- // [¿©±â¼­ºÎÅÍ´Â Offset 0ÀÏ ¶§¸¸ ½ÇÇàµÊ] // --------------------------------------------------------------------------- // 3. ¿øº» API È£Ãâ Result := ReadFileNext(hFile, lpBuffer, nNumberOfBytesToRead, lpNumberOfBytesRead, lpOverlapped); dwError := GetLastError; // 4. ÀÐÀº µ¥ÀÌÅÍ Å©±â È®ÀÎ (ºñµ¿±â ´ë±â ¹®Á¦ ÇØ°á ¹öÀü) dwBytesRead := 0; if Result then begin // µ¿±â È£Ãâ ¼º°ø ½Ã ÀÐÀº Å©±â ȹµæ if lpNumberOfBytesRead <> nil then dwBytesRead := lpNumberOfBytesRead^ else dwBytesRead := 0; end else begin // ½ÇÆÐ ¶Ç´Â Pending »óÅ if dwError = ERROR_IO_PENDING then begin // ºñµ¿±â¶óµµ ÀÌ¹Ì ¿Ï·áµÇ¾ú´ÂÁö 'Áï½Ã' È®ÀÎ (´ë±â ½Ã°£ ¾øÀÌ) if (lpOverlapped <> nil) and GetOverlappedResult(hFile, lpOverlapped^, dwBytesRead, FALSE) then begin // ¿Ï·áµÊ -> µ¥ÀÌÅÍ Ä¸Ã³ ÁøÇà end else begin // ¾ÆÁ÷ ÁøÇà Áß(Pending) -> ÈÄÅ·¿¡¼­ ±â´Ù¸®¸é ·º °É¸®¹Ç·Î ¿©±â¼­ Æ÷±âÇÏ°í ¸®ÅÏ Exit; end; end else begin // ÁøÂ¥ ¿¡·¯ -> ¸®ÅÏ Exit; end; end; // ÀÐÀº µ¥ÀÌÅͰ¡ ¾øÀ¸¸é ÆÐ½º if dwBytesRead = 0 then Exit; // 5. ÇÚµé ij½Ã È®ÀÎ ¹× µ¥ÀÌÅÍ Ä¸Ã³ // (ÀÌ¹Ì Offset 0ÀÓÀÌ È®ÀεǾúÀ¸¹Ç·Î ¾È½ÉÇϰí ĸó) if gbsHook_.fileHandleList_.IsHandle(hFile, handleInfo) then begin sPath := handleInfo.path; handleInfo.Free; // LOG('_ReadFile [Offset 0]: %s, Bytes: %d', [PChar(sPath), dwBytesRead]); // ½ÇÁ¦ ÀÐÀº Å©±â(dwBytesRead)¸¸Å­ ¹öÆÛ ĸó gbsHook_.fileHandleList_.InsertBufferForHandle(hFile, sPath, lpBuffer, dwBytesRead); LOG('_ReadFile, hFile(%p), sPath(%s), nNumberOfBytesToRead(%d), lpNumberOfBytesRead(%p)', [Pointer(hFile), PChar(sPath), nNumberOfBytesToRead, Pointer(lpNumberOfBytesRead)]); end; end; //function _ReadFile(hFile: THandle; lpBuffer: Pointer; nNumberOfBytesToRead: DWORD; lpNumberOfBytesRead: PDWORD; lpOverlapped: POverlapped): BOOL; stdcall; //var // sPath: string; // dwError: DWORD; // state: DWORD; // dwValue: DWORD; // handleInfo: TFileHandle; // // lFilePointer: DWORD; // firstOffset: DWORD; // totalsize: DWORD; // IsStartOfFile: Boolean; //begin // // if (lpBuffer = nil) and (not ghooked_) then // begin // Result := ReadFileNext(hFile, lpBuffer, nNumberOfBytesToRead, lpNumberOfBytesRead, lpOverlapped); // Exit; // end; // // if gbsHook_.processType_ = ptExplore then // begin // Result := ReadFileNext(hFile, lpBuffer, nNumberOfBytesToRead, lpNumberOfBytesRead, lpOverlapped); // Exit; // end; // // totalsize:= GetFileSize( hFile, 0 ); // if (nNumberOfBytesToRead < MIN_BUFFERSIZE) and (totalsize > MIN_BUFFERSIZE ) then // begin // // Result := ReadFileNext(hFile, lpBuffer, nNumberOfBytesToRead, lpNumberOfBytesRead, lpOverlapped); // Exit; // end; // // IsStartOfFile := False; // // lFilePointer:= 0; // lFilePointer:= SetFilePointer(hFile, 0, nil, FILE_CURRENT); // // Result := ReadFileNext(hFile, lpBuffer, nNumberOfBytesToRead, lpNumberOfBytesRead, lpOverlapped); // dwError:= GetLastError; // //// if lFilePointer <> 0 then //// Exit; // // if Result = False then // begin // //// gbsHook_.GetPathFromHandle(hFile, sPath);. //// LOG('_ReadFilePost, hFile(%p), dwError(%x), lpOverlapped(%p)', [Pointer(hFile), dwError, Pointer(lpOverlapped)]); // // if dwError = ERROR_IO_PENDING then // begin // if lpOverlapped <> nil then // begin // if (lpOverlapped.hEvent = THandle(nil)) then // Exit; // // state := WaitForSingleObject(lpOverlapped.hEvent, 1000); // Result := GetOverlappedResult(hFile, lpOverlapped^, dwValue, FALSE); // LOG('_ReadFilePost, hFile(%p), dwValue(%d), lpOverlapped(%p)', [Pointer(hFile), dwValue, Pointer(lpOverlapped)]); // if (lpNumberOfBytesRead <> nil) then // begin // lpNumberOfBytesRead^ := dwValue; // end; // // if dwValue = 0 then // Exit; // // end; // end // else if dwError <> ERROR_SUCCESS then // begin // Exit; // end; // end; // // if gbsHook_.fileHandleList_.IsHandle(hFile, handleInfo) then // begin // sPath:= handleInfo.path; // handleInfo.Free; //// LOG('_ReadFile, IsHandle (%p)', [Pointer(hFile)]); // end //// else if gbsHook_.GetPathFromHandle(hFile, sPath) then //// begin //// LOG('_ReadFile, GetPathFromHandle', []); //// if gbsHook_.policy_.IsExceptionPath(sPath) then //// Exit; //// end // else // begin //// LOG('_ReadFile, not find handle (%p), GE(%x)', [Pointer(hFile), GetLastError]); // Exit; // end; // // LOG('_ReadFile, hFile(%p), sPath(%s), nNumberOfBytesToRead(%d), lpNumberOfBytesRead(%p), lFilePointer(%d), totalsize(%d)', // [Pointer(hFile), PChar(sPath), nNumberOfBytesToRead, Pointer(lpNumberOfBytesRead), lFilePointer, totalsize]); // // gbsHook_.fileHandleList_.InsertBufferForHandle(hFile, sPath, lpBuffer, nNumberOfBytesToRead); // //end; function _WriteFile( hFile: THandle; const Buffer: Pointer; nNumberOfBytesToWrite: DWORD; lpNumberOfBytesWritten: PDWORD; lpOverlapped: POverlapped ): BOOL; stdcall; Label Cleanup; var sPath: string; handleInfo: TFileHandle; dwOffset: DWORD; dwDriveType: DWORD; deviceName: string; devicePolicy: TDeviceControlPolicy; sbuff: string; fileHandle: TFilehandle; bustype: DWORD; block: Boolean; begin sPath:= ''; dwOffset:= 0; block:= False; //bustype:= DWORD(BusTypeUnknown); if (not ghooked_) or ( Buffer = nil ) then goto Cleanup; if (hFile = INVALID_HANDLE_VALUE) or (hFile = 0) then goto Cleanup; if (gbsHook_.processType_ <> ptExplore) and (gbsHook_.processType_ <> ptCmd) then goto Cleanup; if nNumberOfBytesToWrite < MIN_BUFFERSIZE then goto Cleanup; LOG('_WriteFile, hFile (%p), nNumberOfBytesToWrite (%d), (%p)', [Pointer(hFile), nNumberOfBytesToWrite, Pointer(lpOverlapped)]); /// Write µÇ´Â ÆÄÀÏÀÇ Ã¹¹øÂ° ¿ÀÇÁ¼ÂÀÇ ¹öÆÛ¸¸ ºñ±³ÇÑ´Ù. ¼Óµµ ¹®Á¦ if lpOverlapped = nil then begin dwOffset:= SetFilePointer( hFile, 0, nil, FILE_CURRENT ); if (dwOffset <> DWORD(-1)) and ( dwOffset <> 0 ) then goto Cleanup; end else begin if lpOverlapped.Offset <> 0 then goto Cleanup; end; if gbsHook_.GetPathFromHandle(hFile, sPath) then begin dwDriveType:= UtilGetDriveTypeEx(sPath); LOG('_WriteFile, GetPathFromHandle(%s), dwDriveType(%d)', [sPath, dwDriveType]); end else if gbsHook_.fileHandleList_.IsHandle(hFile, handleInfo) then begin sPath:= handleInfo.path; dwDriveType:= handleInfo.drivetype; handleInfo.Free; LOG('_WriteFile, IsHandle (%p)(%s)(%d)', [Pointer(hFile), sPath, dwDriveType]); end else begin LOG('_WriteFile, not find handle (%p), GE(%x)', [Pointer(hFile), GetLastError]); goto Cleanup; end; // if (dwDriveType = DRIVE_UNKNOWN) or (dwDriveType = DRIVE_FIXED) then // begin // Result:= WriteFileNext(hFile, Buffer, nNumberOfBytesToWrite, lpNumberOfBytesWritten, lpOverlapped); // Exit; // end; if ContainsText(sPath, '\CD Burning') or ContainsText(sPath, '\AppData\Local\Microsoft\Windows\Burn\Burn\') or ContainsText(sPath, '\AppData\Local\Microsoft\Windows\Burn\Burn1\') then begin dwDriveType:= DRIVE_CDROM; deviceName:= 'cdrom'; end; if gbsHook_.policy_.IsExceptionPath(sPath) then goto Cleanup; deviceName:= GetOffLineType(dwDriveType, bustype, PChar(sPath)); // if not gbsHook_.policy_.GetDeviceControlPolicy(deviceName, devicePolicy) then goto Cleanup; LOG('_WriteFile, hFile(%p), deviceName(%s), sPath(%s), nNumberOfBytesToWrite(%d)', [Pointer(hFile), deviceName, PChar(sPath), nNumberOfBytesToWrite]); try sbuff := UtilGetBufferHex(Buffer, nNumberOfBytesToWrite, 20); LOG('_WriteFile: data(%s)', [PChar(sbuff)]); if gbsHook_.fileHandleList_.IsBufferCompare('', Buffer, nNumberOfBytesToWrite, fileHandle) then begin sPath:= fileHandle.path; if devicePolicy.policy_ = 1 then begin if UtilIsFileSizeOverBlockSize(sPath, devicePolicy.fileSize_) then begin block:= True; end; end; SendUI(block, deviceName, sPath, sPath); if block then LOG('_WriteFile: MATCHING!!!!!!!!!!BLOCK!!!!!!!!!!!!! (%s), Matched Path: %s', [deviceName, PChar(fileHandle.path)]) else LOG('_WriteFile: MATCHING!!!!!!!!!!ALLOW!!!!!!!!!!!!! (%s), Matched Path: %s', [deviceName, PChar(fileHandle.path)]); fileHandle.Free; if block then begin SetLastError(ERROR_ACCESS_DENIED); Result := False; Exit; end; end; except on E: Exception do LOG('_WriteFile: Exception: %s', [PChar(E.Message)]); end; Cleanup: Result:= WriteFileNext(hFile, Buffer, nNumberOfBytesToWrite, lpNumberOfBytesWritten, lpOverlapped); end; function _CloseHandle(hObject: THandle): BOOL; stdcall; begin if not ghooked_ then begin Result := CloseHandleNext(hObject); Exit; end; gbsHook_.fileHandleList_.DelHandle(hObject); Result := CloseHandleNext(hObject); end; function _DeviceIoControl( hDevice: THandle; dwIoControlCode: DWORD; lpInBuffer: Pointer; nInBufferSize: DWORD; lpOutBuffer: Pointer; nOutBufferSize: DWORD; lpBytesReturned: PDWORD; lpOverlapped: POverlapped ): BOOL; stdcall; //const // IniPath = 'c:\MTPMon\policy.ini'; 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; begin data := nil; size := nInBufferSize; sbuff := ''; inSize := 0; block:= False; if not ghooked_ then begin Result := DeviceIoControlNext(hDevice, dwIoControlCode, lpInBuffer, nInBufferSize, lpOutBuffer, nOutBufferSize, lpBytesReturned, lpOverlapped); Exit; end; if (hDevice = INVALID_HANDLE_VALUE) or (lpInBuffer = nil) or ( nInBufferSize < 32 ) then begin Result := DeviceIoControlNext(hDevice, dwIoControlCode, lpInBuffer, nInBufferSize, lpOutBuffer, nOutBufferSize, lpBytesReturned, lpOverlapped); Exit; end; if (dwIoControlCode <> IOCTL_SCSI_PASS_THROUGH_DIRECT) and (dwIoControlCode <> IOCTL_WPD_MESSAGE_READWRITE_ACCESS) then begin Result := DeviceIoControlNext(hDevice, dwIoControlCode, lpInBuffer, nInBufferSize, lpOutBuffer, nOutBufferSize, lpBytesReturned, lpOverlapped); Exit; end; // LOG('_DeviceIoControl: hDevice(%p) size(%d) dwIoControlCode(%x)', [Pointer(hDevice), size, dwIoControlCode]); gbsHook_.policy_.GetPolicy; policy:= gbsHook_.policy_.CurrentProcessPolicy; case dwIoControlCode of IOCTL_SCSI_PASS_THROUGH_DIRECT: begin if gbsHook_.processType_ = ptLINKENGKM then deviceName:= 'usbTousb' else deviceName:= 'cdrom'; if not gbsHook_.policy_.GetDeviceControlPolicy(deviceName, devicePolicy) then begin Result := DeviceIoControlNext(hDevice, dwIoControlCode, lpInBuffer, nInBufferSize, lpOutBuffer, nOutBufferSize, lpBytesReturned, lpOverlapped); Exit; end; try scsi := nil; scsi := PSCSI_PASS_THROUGH_DIRECT(lpInBuffer); // LOG('_DeviceIoControl, : scsi.DataIn(%d)', [DWORD(scsi.DataIn)]); if (scsi.DataIn = SCSI_IOCTL_DATA_OUT) and (scsi.DataBuffer <> nil) then begin data := PByte(scsi.DataBuffer); size := scsi.DataTransferLength; // if (gbsHook_.processType_ = ptLINKENGKM) and (size = 112) then // begin // Result := DeviceIoControlNext(hDevice, dwIoControlCode, lpInBuffer, // nInBufferSize, lpOutBuffer, nOutBufferSize, lpBytesReturned, lpOverlapped); // Exit; // end; LOG('_DeviceIoControl, 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 Result := DeviceIoControlNext(hDevice, dwIoControlCode, lpInBuffer, nInBufferSize, lpOutBuffer, nOutBufferSize, lpBytesReturned, lpOverlapped); Exit; end; except on E: Exception do LOG('_DeviceIoControl, Error accessing DataBuffer: %s', [PChar(E.Message)]); end; end; IOCTL_WPD_MESSAGE_READWRITE_ACCESS: begin deviceName:= 'mtp'; if not gbsHook_.policy_.GetDeviceControlPolicy(deviceName, devicePolicy) then begin Result := DeviceIoControlNext(hDevice, dwIoControlCode, lpInBuffer, nInBufferSize, lpOutBuffer, nOutBufferSize, lpBytesReturned, lpOverlapped); Exit; end; data := PByte(lpInBuffer); size := nInBufferSize; end; else begin Result := DeviceIoControlNext(hDevice, dwIoControlCode, lpInBuffer, nInBufferSize, lpOutBuffer, nOutBufferSize, lpBytesReturned, lpOverlapped); Exit; end; end; try sbuff := UtilGetBufferHex(data, size, 50); LOG('_DeviceIoControl: hDevice(%p) size(%d) data(%s)', [Pointer(hDevice), size, PChar(sbuff)]); if devicePolicy.dump_ = 1 then UtilSaveBufferToFile('c:\MTPMon\dump', data, size); if gbsHook_.fileHandleList_.IsBufferCompare('', data, size, fileHandle) then begin sPath:= fileHandle.path; if devicePolicy.policy_ = 1 then begin if UtilIsFileSizeOverBlockSize(sPath, devicePolicy.fileSize_) then begin block:= True; end; end; SendUI(block, deviceName, sPath, sPath); if block then LOG('_DeviceIoControl: MATCHING!!!!!!!!!!BLOCK!!!!!!!!!!!!! hDevice(%p)!! (%s), Matched Path: %s', [Pointer(hDevice), deviceName, PChar(fileHandle.path)]) else LOG('_DeviceIoControl: MATCHING!!!!!!!!!!ALLOW!!!!!!!!!!!!! hDevice(%p)!! (%s), Matched Path: %s', [Pointer(hDevice), deviceName, PChar(fileHandle.path)]); fileHandle.Free; if block then begin SetLastError(ERROR_ACCESS_DENIED); Result := False; Exit; end; end; except on E: Exception do LOG('_DeviceIoControl: Exception: %s', [PChar(E.Message)]); end; Result := DeviceIoControlNext(hDevice, dwIoControlCode, lpInBuffer, nInBufferSize, lpOutBuffer, nOutBufferSize, lpBytesReturned, lpOverlapped); end; function _WSASend( 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; block: Boolean; begin block:= False; FillChar(sin, SizeOf(sin), 0); FillChar(ip, SizeOf(ip), 0); if ( not ghooked_ ) or ( lpBuffers = nil )then begin Result:= WSASendNext(s, lpBuffers, dwBufferCount, lpNumberOfBytesSent, dwFlags, lpOverlapped, lpCompletionRoutine); Exit; end; if (gbsHook_.processType_ <> ptFquirt) and (gbsHook_.processType_ <> ptLINKENGKM) then begin Result:= WSASendNext(s, lpBuffers, dwBufferCount, lpNumberOfBytesSent, dwFlags, lpOverlapped, lpCompletionRoutine); Exit; end; gbsHook_.policy_.GetPolicy; if gbsHook_.policy_.CurrentProcessPolicy = nil then begin Result:= WSASendNext(s, lpBuffers, dwBufferCount, lpNumberOfBytesSent, dwFlags, lpOverlapped, lpCompletionRoutine); Exit; end; policy:= gbsHook_.policy_.CurrentProcessPolicy; if not gbsHook_.policy_.GetDeviceControlPolicy('bluetooth', devicePolicy) then begin Result:= WSASendNext(s, lpBuffers, dwBufferCount, lpNumberOfBytesSent, dwFlags, lpOverlapped, lpCompletionRoutine); Exit; end; ObexPacket := TObexPacket.Create; try data:= PByte(lpBuffers.buf); size:= lpBuffers.len; if (data = nil) or (Size < MIN_BUFFERSIZE) then begin Result:= WSASendNext(s, lpBuffers, dwBufferCount, lpNumberOfBytesSent, dwFlags, lpOverlapped, lpCompletionRoutine); Exit; end; sIp:= ''; opCode:= data[0]; // if (opCode <> $82) or (size < 32) then // begin // LOG('_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); LOG('_WSASend, : sBuff(%s) size(%d)', [sBuff, size]); ObexPacket.Parse(data, size); // 2. ÆÄ½ÌµÈ µ¥ÀÌÅ͸¦ ¼Ó¼ºÀ¸·Î ½±°Ô Á¢±ÙÇÕ´Ï´Ù. Log('_WSASend, --- OBEX ÆÐŶ ºÐ¼® ---',[]); Log('_WSASend, Opcode: $%02x, Packet Length: %d', [ObexPacket.Opcode, ObexPacket.PacketLength]); // Name Çì´õ (0x01) Log('_WSASend, File Name: %s', [PChar(ObexPacket.Name)]); sName:= ObexPacket.Name; // Length Çì´õ (0xC3) Log('_WSASend, Total File Size: %d bytes', [ObexPacket.TotalLength]); // Body Çì´õ (0x49) if Length(ObexPacket.Body) > 0 then begin Log('_WSASend, Body Length: %d bytes', [Length(ObexPacket.Body)]); // Log(HexDump(ObexPacket.Body)); // ¹Ùµð ³»¿ë ´ýÇÁ (ÇÊ¿ä½Ã) end; ObexPacket.Free; if gbsHook_.fileHandleList_.IsBufferCompare(sName, data, size, fileHandle) then begin sPath:= fileHandle.path; if devicePolicy.policy_ = 1 then begin if UtilIsFileSizeOverBlockSize(sPath, devicePolicy.fileSize_) then begin block:= True; end; end; SendUI(block, 'bluetooth', sPath, sPath); if block then LOG('_WSASend: MATCHING!!!!!BLOCK!!!!! hDevice(%p)!! (bluetooth) %d, %d, Matched Ip : (%s), Path: (%s)', [Pointer(s), devicePolicy.policy_, devicePolicy.fileSize_, PChar(sIp), PChar(fileHandle.path)]) else LOG('_WSASend: MATCHING!!!!!ALLOW!!!!! hDevice(%p)!! (bluetooth) %d, %d, Matched Ip : (%s), Path: %s', [Pointer(s), devicePolicy.policy_, devicePolicy.fileSize_, PChar(sIp), PChar(fileHandle.path)]); fileHandle.Free; if block then begin WSASetLastError(WSAECONNABORTED); Result := SOCKET_ERROR; Exit; end; end; except on E: Exception do LOG('_WSASend: Exception: %s', [PChar(E.Message)]); end; Result:= WSASendNext(s, lpBuffers, dwBufferCount, lpNumberOfBytesSent, dwFlags, lpOverlapped, lpCompletionRoutine); end; function _send(s: TSocket; const buf: PAnsiChar; len: Integer; flags: Integer): Integer; stdcall; var sBuff: string; size: DWORD; data: PByte; begin if (not ghooked_) or (gbsHook_.processType_ <> ptLINKENGKM) then begin Result := sendNext(s, buf, len, flags); Exit; end; if (len > 0) and (buf <> nil) then begin size:= Min(len, 100); data:= PByte(buf); for var i := 0 to size - 1 do sBuff := sBuff + IntToHex(data[i], 2); LOG('_send: sBuff(%s)', [PChar(sBuff)]); end; Result := sendNext(s, buf, len, flags); end; end.