{*******************************************************} { } { TgDrmHook } { } { Copyright (C) 2022 kku } { } {*******************************************************} unit TgDrmHook; interface uses System.SysUtils, System.Classes, Tocsg.DllEntry, Tocsg.CommonData, GlobalDefine, Winapi.Windows, Winapi.Messages, Winapi.ShellAPI, Tocsg.Trace, WinAPI.Foundation.Collections, System.Generics.Collections, Tocsg.DRM.Encrypt; type PDrmFileInfo = ^TDrmFileInfo; TDrmFileInfo = record hFile: THandle; sOrgPath, sDecPath: String; bModified: Boolean; Head: TTgDrmHead; end; TTgDrmHook = class(TTgDllEntry) private SharedData_: TTgFileMapping; hShellHook_: HHook; Trace_: TTgTrace; dtCreate_: TDateTime; // sPass_, sTgPNames_, sLogPath_: String; hRecentWnd_: HWND; bInitOk_, bUseBoxedApp_, bIsMsOffice_, bForceEncSave_: Boolean; // DrmFileList_: TStringList; DcDecPath_: TDictionary; bBlockCap_: Boolean; DrmExtList_: TStringList; DcDrmFI_: TDictionary; RecentDrmFI_: TDrmFileInfo; // MS¿ÀÇǽº ÀúÀå ÆÄÀÏ ¾Ïȣȭ¸¦ À§ÇÔ sRecentOpenFile_: String; ProcList_: TList; procedure Log(sLog: String); function InstallHook: Integer; function UnInstallHook: Integer; procedure AddInterceptAPI(var aProcDest: Pointer; aProcSrc, aProcHook: Pointer; sProcName: String); procedure DoInterceptCreate; procedure DoInterceptRemove; procedure OnBeforeLog(aSender: TObject); procedure OnAfterLog(aSender: TObject); function GetActive: Boolean; function GetRcvWnd: LONGLONG; procedure OnDrmFileNotify(Sender: TObject; const Item: PDrmFileInfo; Action: TCollectionNotification); public Constructor Create; Destructor Destroy; override; property Active: Boolean read GetActive; property RcvWnd: LONGLONG read GetRcvWnd; end; THandleStreamEx = class(THandleStream) protected llSize_: LONGLONG; function GetSize: Int64; override; public Constructor Create(aHandle: THandle; llSize: LONGLONG); end; TFun_CreateFileA = function(lpFileName: PAnsiChar; dwDesiredAccess, dwShareMode: DWORD; lpSecurityAttributes: PSecurityAttributes; dwCreationDisposition, dwFlagsAndAttributes: DWORD; hTemplateFile: THandle): THandle; stdcall; TFun_CreateFileW = function(lpFileName: PWideChar; dwDesiredAccess, dwShareMode: DWORD; lpSecurityAttributes: PSecurityAttributes; dwCreationDisposition, dwFlagsAndAttributes: DWORD; hTemplateFile: THandle): THandle; stdcall; TFun_CloseHandle = function(hFile: THandle): BOOL; stdcall; TFun_ReadFile = function(hFile: THandle; var Buffer; nNumberOfBytesToRead: DWORD; var lpNumberOfBytesRead: DWORD; lpOverlapped: POverlapped): BOOL; stdcall; TFun_WriteFile = function(hFile: THandle; const Buffer; nNumberOfBytesToWrite: DWORD; var lpNumberOfBytesWritten: DWORD; lpOverlapped: POverlapped): BOOL; stdcall; TFun_WriteFileEx = function(hFile: THandle; lpBuffer: Pointer; nNumberOfBytesToWrite: DWORD; const lpOverlapped: TOverlapped; lpCompletionRoutine: FARPROC): BOOL; stdcall; function InstallDrmHook: Integer; export; stdcall; function UnInstallDrmHook: Integer; export; stdcall; implementation uses BoxedAppSDK_Static, // BoxedAppSDK_DLL, DDetours, Vcl.Graphics, Vcl.Imaging.pngimage, Vcl.Imaging.jpeg, Tocsg.Safe, Tocsg.Path, Tocsg.Strings, Tocsg.Process, Winapi.DwmApi, Vcl.Forms, Tocsg.WndUtil, Tocsg.Exception, Tocsg.Encrypt, Tocsg.Shell, Tocsg.Files; var _TgDrmHook: TTgDrmHook = nil; _bLogProcessing: Boolean = false; _bInternalOpen: Boolean = false; ozCreateFileA: TFun_CreateFileA = nil; ozCreateFileW: TFun_CreateFileW = nil; ozCloseHandle: TFun_CloseHandle = nil; ozReadFile: TFun_ReadFile = nil; ozWriteFile: TFun_WriteFile = nil; ozWriteFileEx: TFun_WriteFileEx = nil; { THandleStreamEx } Constructor THandleStreamEx.Create(aHandle: THandle; llSize: LONGLONG); begin Inherited Create(aHandle); llSize_ := llSize; end; function THandleStreamEx.GetSize: Int64; begin Result := llSize_; end; function ProcessEncFile(sPath: String; dwDesiredAccess, dwShareMode: DWORD; lpSecurityAttributes: PSecurityAttributes; dwCreationDisposition, dwFlagsAndAttributes: DWORD; hTemplateFile: THandle): THandle; inline; var ms: TMemoryStream; // enc: TTgEncrypt; dec: TTgDrmDec; fh: THandleStreamEx; dwTemp: DWORD; sChkPath, sExt, sFName, sVirtualPath: String; hFile: THandle; llSize: LONGLONG; bDecSuccess: Boolean; h: HWND; // fs: TFileStream; pDrmFI: PDrmFileInfo; DrmHead: TTgDrmHead; i: Integer; begin Result := 0; case dwDesiredAccess of 0, $80, GENERIC_WRITE : exit; end; // if sPath.StartsWith('\??\') then // Delete(sPath, 1, 4); if Assigned(_TgDrmHook) and (not _bLogProcessing and not _bInternalOpen) then begin // if BoxedAppSDK_IsVirtualFile(PChar(sPath)) then // begin // sVirtualPath := sPath; // end else // if _TgDrmHook.DcDecPath_.ContainsKey(sPath) then // begin // sVirtualPath := _TgDrmHook.DcDecPath_[sPath]; // end else begin // if _TgDrmHook.sRecentOpenFile_ <> sPath then // begin // _TgDrmHook.sRecentOpenFile_ := sPath; // exit; // end; // _TgDrmHook.Log(Format('ProcessEncFile() .. Path=%s', [sPath])); sVirtualPath := ''; bDecSuccess := false; sFName := ExtractFileName(sPath); if sFName = '' then exit; if CompareText(sFName, 'desktop.ini') = 0 then exit; if _TgDrmHook.bIsMsOffice_ and sFName.StartsWith('~$') then exit; sExt := GetFileExt(sFName); if sExt = '' then exit; if _TgDrmHook.DrmExtList_.IndexOf(sExt) = -1 then exit; _TgDrmHook.Log(Format('Check Ext .. FName=%s, dwDesiredAccess=%X, ' + 'dwShareMode=%X, dwCreationDisposition=%X, dwFlagsAndAttributes=%X', [sFName, dwDesiredAccess, dwShareMode, dwCreationDisposition, dwFlagsAndAttributes])); // _TgDrmHook.Log(Format('Check Ext Success .. FName=%s', [sFName])); fh := nil; hFile := 0; try // hFile := ozCreateFileW( // PChar(sPath), // GENERIC_READ, FILE_SHARE_READ, nil, OPEN_EXISTING, 0, 0); // if (hFile = 0) or (hFile = INVALID_HANDLE_VALUE) then // exit; _bInternalOpen := true; ms := TMemoryStream.Create; try if _TgDrmHook.bIsMsOffice_ and (_TgDrmHook.RecentDrmFI_.sOrgPath <> '') and (CompareText(_TgDrmHook.RecentDrmFI_.sOrgPath, sPath) = 0) and not TTgEncrypt.CheckSign(sPath, SIG_DRM) then begin _TgDrmHook.RecentDrmFI_.sOrgPath := ''; if MoveFile_wait(sPath, sPath + '_tmp', 3) then begin var enc: TTgDrmEnc; Guard(enc, TTgDrmEnc.Create(sPath)); with _TgDrmHook.RecentDrmFI_.Head do begin if enc.SetHaed(PASS_DRM_HEAD, SIG_DRM, sEmpNo, sHostName, sPartName, sPgName, dwCustomerCode) then if enc.EncryptFromFile(PASS_DRM_DATA, sPath + '_tmp') then DeleteFile(PChar(sPath + '_tmp')); end; end; end; // if not GetFileSizeEx(hFile, llSize) then // exit; // if llSize = 0 then // exit; // Guard(fh, THandleStreamEx.Create(hFile, llSize)); // fs := TFileStream.Create(sPath, fmOpenRead or fmShareDenyNone); // _TgDrmHook.Log(Format('FileSize=%d', [fs.Size])); dec := TTgDrmDec.Create(sPath); try if not dec.CheckSig(SIG_DRM) then begin // _TgDrmHook.Log(Format('Fail .. CheckSign(), FName=%s', [sFName])); exit; end else begin _TgDrmHook.Log(Format('Success .. CheckSign(), FName=%s', [sFName])); end; if not dec.ExtrHead(PASS_DRM_HEAD) then begin _TgDrmHook.Log('Fail .. ExtrHead()'); exit; end; DrmHead := dec.Head; if not dec.DecryptToStream(PASS_DRM_DATA, ms) then begin _TgDrmHook.Log('Fail .. DecryptToStream()'); exit; end; finally FreeAndNil(dec); end; bDecSuccess := true; finally if hFile <> 0 then begin ozCloseHandle(hFile); hFile := 0; end; if bDecSuccess then begin // {$IF True} if _TgDrmHook.bUseBoxedApp_ then begin sVirtualPath := '@TgDRM\' + ExtractFilePath(sPath) + sFName; // sVirtualPath := ExtractFilePath(sPath) + Format('#%d_%s', [GetTickCount, sFName]); // °¡»ó ÆÄÀÏ »ý¼º hFile := BoxedAppSDK_CreateVirtualFile(PChar(sVirtualPath), GENERIC_WRITE, FILE_SHARE_READ, nil, CREATE_NEW, FILE_ATTRIBUTE_HIDDEN, 0); // GENERIC_WRITE, dwShareMode, lpSecurityAttributes, CREATE_NEW, dwFlagsAndAttributes {FILE_ATTRIBUTE_HIDDEN}, hTemplateFile); end else begin // sVirtualPath := ExtractFilePath(sPath) + Format('#1_%s', [sFName]); sVirtualPath := ExtractFilePath(sPath) + Format('#%d_%s', [GetTickCount, sFName]); // °¡»ó ÆÄÀÏ »ý¼º hFile := ozCreateFileW(PChar(sVirtualPath), GENERIC_WRITE or GENERIC_READ, 0, nil, CREATE_ALWAYS { CREATE_NEW } , FILE_ATTRIBUTE_HIDDEN or FILE_FLAG_DELETE_ON_CLOSE, 0); // FILE_ATTRIBUTE_HIDDEN, 0); // hFile := ozCreateFileW(PChar(sVirtualPath), GENERIC_WRITE or GENERIC_READ, 0, lpSecurityAttributes, dwCreationDisposition or CREATE_ALWAYS, // dwFlagsAndAttributes or FILE_FLAG_DELETE_ON_CLOSE, hTemplateFile); end; if (hFile <> 0) and (hFile <> INVALID_HANDLE_VALUE) then begin WriteFile(hFile, ms.Memory^, ms.Size, dwTemp, nil); if FileSeek(hFile, 0, 0) = 0 then Result := hFile else CloseHandle(hFile); // ExecutePath('C:\Program Files\Adobe\Acrobat DC\Acrobat\Acrobat.exe', '"' + sVirtualPath + '"'); // Result := 1; // _TgDrmHook.DcDecPath_.Add(sPath, sVirtualPath); // if _TgDrmHook.DrmFileList_.IndexOf(sFName) = -1 then // _TgDrmHook.DrmFileList_.Add(sFName); end; end; ms.Free; _bInternalOpen := false; end; except // .. sVirtualPath := ''; end; end; try if Result <> 0 then exit; if sVirtualPath <> '' then begin // Result := ozCreateFileW(PChar(sVirtualPath), dwDesiredAccess, 0, lpSecurityAttributes, dwCreationDisposition, // dwFlagsAndAttributes, hTemplateFile); Result := ozCreateFileW(PChar(sVirtualPath), dwDesiredAccess, 0, lpSecurityAttributes, dwCreationDisposition, dwFlagsAndAttributes or FILE_FLAG_DELETE_ON_CLOSE, hTemplateFile); // Result := ozCreateFileW(PChar(sVirtualPath), dwDesiredAccess, dwShareMode, lpSecurityAttributes, dwCreationDisposition, // dwFlagsAndAttributes, hTemplateFile); end; finally if (Result <> 0) and (Result <> INVALID_HANDLE_VALUE) then begin if _TgDrmHook.DcDrmFI_.ContainsKey(Result) then begin _TgDrmHook.Log('Fail .. ProcessEncFile() .. Already Handle??'); {$IFDEF DEBUG} ASSERT(false); {$ELSE} exit; {$ENDIF}; end; New(pDrmFI); ZeroMemory(pDrmFI, SizeOf(TDrmFileInfo)); pDrmFI.hFile := Result; pDrmFI.sOrgPath := sPath; pDrmFI.sDecPath := sVirtualPath; pDrmFI.Head := DrmHead; pDrmFI.bModified := true; _TgDrmHook.DcDrmFI_.Add(Result, pDrmFI); end; end; end; end; function ProcessNorFile(sPath: String; dwDesiredAccess, dwShareMode: DWORD; lpSecurityAttributes: PSecurityAttributes; dwCreationDisposition, dwFlagsAndAttributes: DWORD; hTemplateFile: THandle): THandle; inline; var sFName, sExt, sEncPath: String; pInfo: PDrmFileInfo; dec: TTgDrmDec; DrmHead: TTgDrmHead; begin Result := 0; exit; if _TgDrmHook.bIsMsOffice_ then begin _bInternalOpen := true; try sFName := ExtractFileName(sPath); if sFName = '' then exit; if not sFName.StartsWith('~$') then exit; sExt := GetFileExt(sFName); if sExt = '' then exit; if _TgDrmHook.DrmExtList_.IndexOf(sExt) = -1 then exit; _TgDrmHook.Log(Format('ProcessNorFile() .. 1sEncPath=%s', [ExtractFilePath(sPath) + sFName])); Delete(sFName, 1, 2); sEncPath := ExtractFilePath(sPath) + sFName; _TgDrmHook.Log(Format('ProcessNorFile() .. 2sEncPath=%s', [sEncPath])); if not FileExists(sEncPath) then exit; _TgDrmHook.Log('ProcessNorFile() .. 1'); dec := TTgDrmDec.Create(sEncPath); try if not dec.CheckSig(SIG_DRM) then exit; if not dec.ExtrHead(PASS_DRM_HEAD) then exit; DrmHead := dec.Head; finally dec.Free; end; _TgDrmHook.Log('ProcessNorFile() .. 2'); Result := ozCreateFileW(PChar(sPath), dwDesiredAccess, dwShareMode, lpSecurityAttributes, dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile); if (Result <> 0) and (Result <> INVALID_HANDLE_VALUE) then begin New(pInfo); ZeroMemory(pInfo, SizeOf(TDrmFileInfo)); pInfo.hFile := Result; pInfo.sOrgPath := sEncPath; pInfo.sDecPath := sPath; pInfo.Head := DrmHead; // pInfo.bModified := true; _TgDrmHook.DcDrmFI_.Add(Result, pInfo); _TgDrmHook.Log(Format('ProcessNorFile() .. Path=%s', [sPath])); end; finally _bInternalOpen := false; end; end; end; function ProcessCreateFile(sPath: String; dwDesiredAccess, dwShareMode: DWORD; lpSecurityAttributes: PSecurityAttributes; dwCreationDisposition, dwFlagsAndAttributes: DWORD; hTemplateFile: THandle): THandle; inline; begin Result := ProcessEncFile(sPath, dwDesiredAccess, dwShareMode, lpSecurityAttributes, dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile); if Result = 0 then begin Result := ProcessNorFile(sPath, dwDesiredAccess, dwShareMode, lpSecurityAttributes, dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile); if Result = 0 then Result := ozCreateFileW(PChar(sPath), dwDesiredAccess, dwShareMode, lpSecurityAttributes, dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile); end; end; function CreateFileAHook(lpFileName: PAnsiChar; dwDesiredAccess, dwShareMode: DWORD; lpSecurityAttributes: PSecurityAttributes; dwCreationDisposition, dwFlagsAndAttributes: DWORD; hTemplateFile: THandle): THandle; stdcall; begin // Result := ozCreateFileA(lpFileName, dwDesiredAccess, dwShareMode, lpSecurityAttributes, dwCreationDisposition, // dwFlagsAndAttributes, hTemplateFile); Result := ProcessCreateFile(StrPas(lpFileName), dwDesiredAccess, dwShareMode, lpSecurityAttributes, dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile); end; function CreateFileWHook(lpFileName: PWideChar; dwDesiredAccess, dwShareMode: DWORD; lpSecurityAttributes: PSecurityAttributes; dwCreationDisposition, dwFlagsAndAttributes: DWORD; hTemplateFile: THandle): THandle; stdcall; begin // Result := ozCreateFileW(lpFileName, dwDesiredAccess, dwShareMode, lpSecurityAttributes, dwCreationDisposition, // dwFlagsAndAttributes, hTemplateFile); Result := ProcessCreateFile(StrPas(lpFileName), dwDesiredAccess, dwShareMode, lpSecurityAttributes, dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile); end; function CloseHandleHook(hFile: THandle): BOOL; stdcall; var pInfo: PDrmFileInfo; enc: TTgDrmEnc; hs: THandleStreamEx; llSize: LONGLONG; ms: TMemoryStream; begin try if _TgDrmHook.DcDrmFI_.ContainsKey(hFile) then begin pInfo := _TgDrmHook.DcDrmFI_[hFile]; _bInternalOpen := true; _TgDrmHook.Log(Format('CloseHandleHook() .. ProcessEncHandle, OrgPath=%s', [pInfo.sOrgPath])); _TgDrmHook.Log(Format('CloseHandleHook() .. ProcessEncHandle, DecPath=%s', [pInfo.sDecPath])); try if _TgDrmHook.bForceEncSave_ or pInfo.bModified then begin if _TgDrmHook.bIsMsOffice_ then begin _TgDrmHook.RecentDrmFI_.sOrgPath := pInfo.sOrgPath; _TgDrmHook.RecentDrmFI_.Head := pInfo.Head; end else begin if not GetFileSizeEx(hFile, llSize) then begin _TgDrmHook.Log('CloseHandleHook() .. Fail .. GetFileSizeEx()'); exit; end; Guard(hs, THandleStreamEx.Create(hFile, llSize)); hs.Position := 0; Guard(enc, TTgDrmEnc.Create(pInfo.sOrgPath)); with pInfo.Head do begin if enc.SetHaed(PASS_DRM_HEAD, SIG_DRM, sEmpNo, sHostName, sPartName, sPgName, dwCustomerCode) then begin if enc.EncryptFromStream(PASS_DRM_DATA, hs) then _TgDrmHook.Log('CloseHandleHook() .. Success .. EncryptFromStream()') else _TgDrmHook.Log('CloseHandleHook() .. Fail .. EncryptFromStream()'); end else _TgDrmHook.Log('CloseHandleHook() .. Fail .. SetHaed()'); end; end; end else _TgDrmHook.Log(Format('CloseHandleHook() .. Not Modify.. DecPath=%s', [pInfo.sDecPath])); finally _TgDrmHook.DcDrmFI_.Remove(hFile); _bInternalOpen := false; end; end; Result := ozCloseHandle(hFile); except on E: Exception do ETgException.TraceException(E, 'Fail .. CloseHandleHook()'); end; end; function ReadFileHook(hFile: THandle; var Buffer; nNumberOfBytesToRead: DWORD; var lpNumberOfBytesRead: DWORD; lpOverlapped: POverlapped): BOOL; stdcall; begin _TgDrmHook.Log(Format('ReadFileHook() .. Postion=%d', [FileSeek(hFile, 0, 1)])); Result := ozReadFile(hFile, Buffer, nNumberOfBytesToRead, lpNumberOfBytesRead, lpOverlapped); end; function WriteFileHook(hFile: THandle; const Buffer; nNumberOfBytesToWrite: DWORD; var lpNumberOfBytesWritten: DWORD; lpOverlapped: POverlapped): BOOL; stdcall; begin Result := ozWriteFile(hFile, Buffer, nNumberOfBytesToWrite, lpNumberOfBytesWritten, lpOverlapped); if Result and _TgDrmHook.DcDrmFI_.ContainsKey(hFile) then // if _TgDrmHook.DcDrmFI_.ContainsKey(hFile) then begin _TgDrmHook.Log('WriteFileHook()'); _TgDrmHook.DcDrmFI_[hFile].bModified := true; end; end; function WriteFileExHook(hFile: THandle; lpBuffer: Pointer; nNumberOfBytesToWrite: DWORD; const lpOverlapped: TOverlapped; lpCompletionRoutine: FARPROC): BOOL; stdcall; begin Result := ozWriteFileEx(hFile, lpBuffer, nNumberOfBytesToWrite, lpOverlapped, lpCompletionRoutine); if Result and _TgDrmHook.DcDrmFI_.ContainsKey(hFile) then // if _TgDrmHook.DcDrmFI_.ContainsKey(hFile) then begin _TgDrmHook.Log('WriteFileExHook()'); _TgDrmHook.DcDrmFI_[hFile].bModified := true; end; end; function process_WH_SHELL(nCode: Integer; wParam: WPARAM; lParam: LPARAM): LRESULT; stdcall; begin if Assigned(_TgDrmHook) then begin try try if nCode >= HC_ACTION then case nCode of // HSHELL_ACCESSIBILITYSTATE : ; // Windows 2000/XP: accessibility »óŰ¡ º¯°æµÇ¾úÀ½ // HSHELL_APPCOMMAND : ; // Windows 2000/XP: »ç¿ëÀÚÀÇ ÀÔ·Â À̺¥Æ®¿¡ ÀÇÇØ¼­ WM_APPCOMMAND °¡ ¹ß»ýÇÑ °æ¿ì´Ù // HSHELL_ACTIVATESHELLWINDOW : ; // ½© ¸ÞÀÎ À©µµ¿ì°¡ Ȱ¼ºÈ­ µÇ¾î¾ß ÇÏ´Â °æ¿ì´Ù // HSHELL_GETMINRECT : ; // À©µµ¿ì°¡ ÃÖ¼ÒÈ­/ÃÖ´ëÈ­µÈ °æ¿ì´Ù // HSHELL_LANGUAGE : ; // Űº¸µå ¾ð¾î°¡ º¯°æµÇ°Å³ª »õ·Î¿î Űº¸µå ·¹À̾ƿôÀÌ ·ÎµåµÈ °æ¿ì´Ù // HSHELL_TASKMAN : ; // »ç¿ëÀÚ°¡ ŽºÅ© ¸®½ºÆ®¸¦ ¼±ÅÃÇÑ °æ¿ì´Ù. Å×½ºÆ®ÇØ º» °á°ú Ctrl + Esc ۸¦ ´©¸¥ °æ¿ì ÈÅ ÇÁ·Î½ÃÀú°¡ È£ÃâµÇ¾ú´Ù. ½ÃÀÛ ¹öưÀ» ´­·¶À» ¶§¿£ È£ÃâµÇÁö ¾Ê´Â´Ù HSHELL_WINDOWACTIVATED, // : ; // ž ·¹º§ À©µµ¿ìÀÇ È°¼ºÈ­ »óŰ¡ º¯°æµÈ °æ¿ì´Ù HSHELL_WINDOWCREATED, // : ; // ž ·¹º§ À©µµ¿ì°¡ »ý¼ºµÈ °æ¿ì´Ù. ÀÌ ÈÅÀÌ È£ÃâµÇ´Â ½ÃÁ¡¿¡ À©µµ¿ì´Â »ý¼ºµÈ »óÅ´٠HSHELL_REDRAW : // ŽºÅ©¹Ù¿¡ ÀÖ´Â À©µµ¿ì ŸÀÌÆ²ÀÌ »õ·Î ±×·ÁÁö´Â °æ¿ì´Ù begin // if _TgDrmHook.hRecentWnd_ <> wParam then // begin // _TgDrmHook.hRecentWnd_ := wParam; // if SetWindowDisplayAffinity(_TgDrmHook.hRecentWnd_, 1) then // _TgDrmHook.Log(Format('Success .. SetWindowDisplayAffinity(), Title="%s"', [GetWindowCaption(_TgDrmHook.hRecentWnd_)])) // end; end; HSHELL_WINDOWDESTROYED : ; // ž ·¹º§ À©µµ¿ì°¡ ÆÄ±«µÈ °æ¿ì´Ù. ÀÌ ÈÅÀÌ È£ÃâµÇ´Â ½ÃÁ¡¿¡ À©µµ¿ì´Â Á¸ÀçÇÑ´Ù HSHELL_WINDOWREPLACED : ; // Windows XP: ž ·¹º§ À©µµ¿ì°¡ ´ëü(replaced)µÈ °æ¿ì´Ù end; except exit; end; finally Result := CallNextHookEx(_TgDrmHook.hShellHook_, nCode, wParam, lParam); end; end else Result := 0; end; { TTgDrmHook } Constructor TTgDrmHook.Create; procedure GetStartTime; var ftCreate, ftExit, ftKernel, ftUser: TFileTime; nDosTime: Integer; begin dtCreate_ := 0; GetProcessTimes(GetCurrentProcess, ftCreate, ftExit, ftKernel, ftUser); if FileTimeToLocalFileTime(ftCreate, ftCreate) then if FileTimeToDosDateTime(ftCreate, LongRec(nDosTime).Hi, LongRec(nDosTime).Lo) then dtCreate_ := FileDateToDateTime(nDosTime); end; var AppList: TStringList; begin Inherited Create; ASSERT(_TgDrmHook = nil); _TgDrmHook := Self; bInitOk_ := false; bForceEncSave_ := false; bUseBoxedApp_ := false; GetStartTime; hShellHook_ := 0; sRecentOpenFile_ := ''; DrmExtList_ := TStringList.Create; DrmExtList_.CaseSensitive := false; SplitString(DRM_EXTS, '|', DrmExtList_); ProcList_ := TList.Create; DcDrmFI_ := TDictionary.Create; DcDrmFI_.OnValueNotify := OnDrmFileNotify; ZeroMemory(@RecentDrmFI_, SizeOf(RecentDrmFI_)); SharedData_ := TTgFileMapping.Create(MAP_FILENAME_APIHOOK, SizeOf(TSharedData)); if SharedData_.IsAvailable then begin // sPass_ := SharedData_.Data.sPass; sTgPNames_ := UpperCase(SharedData_.Data.sTgPNames); sLogPath_ := SharedData_.Data.sLogPath; end; // DrmFileList_ := TStringList.Create; // DrmFileList_.CaseSensitive := false; DcDecPath_ := TDictionary.Create; bBlockCap_ := false; Guard(AppList, TStringList.Create); AppList.CaseSensitive := false; Trace_ := nil; SplitString(sTgPNames_, '|', AppList); if AppList.IndexOf(ModuleName) <> -1 then begin var sMdName: String := LowerCase(ModuleName); // HWP´Â Áß°£ ÀúÀåÇÒ¶§ ¸¶´Ù ¹Ù·Î ÆÄÀÏ¿¡ ¾²Áö ¾Ê°í ÆÄÀÏ¿¡ ´ÝÈú¶§ ÆÄÀÏ¿¡ ¾´´Ù. // ±×·¡¼­ ÆÄÀϾ²±â ü±×°¡ µÇÁö ¾Ê¾Æ¼­ ÀÌ·¸°Ô ¹«Á¶°Ç ÀúÀå½Ã ¾Ïȣȭ ±â´ÉÀ» ON ÇÑ´Ù 22_1017 13:47:26 kku if (sMdName = 'winword.exe') or (sMdName = 'excel.exe') or (sMdName = 'powerpnt.exe') then bIsMsOffice_ := true else bForceEncSave_ := CompareText(ModuleName, 'hwp.exe') = 0; {$IFDEF DEBUG} Trace_ := TTgTrace.Create(ExtractFilePath(sLogPath_), ExtractFileName(sLogPath_)); Trace_.OnBeforeLog := OnBeforeLog; Trace_.OnAfterLog := OnAfterLog; {$ENDIF} bUseBoxedApp_ := CompareText('Acrobat.exe', ModuleName) = 0; // InstallHook; DoInterceptCreate; end; end; Destructor TTgDrmHook.Destroy; begin // UnInstallHook; DoInterceptRemove; _TgDrmHook := nil; FreeAndNil(SharedData_); if Trace_ <> nil then FreeAndNil(Trace_); // FreeAndNil(DrmFileList_); FreeAndNil(DcDecPath_); FreeAndNil(DcDrmFI_); FreeAndNil(ProcList_); FreeAndNil(DrmExtList_); Inherited; end; procedure TTgDrmHook.OnBeforeLog(aSender: TObject); begin _bLogProcessing := true; end; procedure TTgDrmHook.OnAfterLog(aSender: TObject); begin _bLogProcessing := false; end; function TTgDrmHook.GetActive: Boolean; begin try if SharedData_.IsAvailable then Result := SharedData_.Data.bActive else Result := false; except on E: Exception do ETgException.TraceException(Self, E, 'Fail .. GetActive()'); end; end; function TTgDrmHook.GetRcvWnd: LONGLONG; begin try if SharedData_.IsAvailable then Result := SharedData_.Data.llRcvWnd else Result := 0; except on E: Exception do ETgException.TraceException(Self, E, 'Fail .. GetRcvWnd()'); end; end; procedure TTgDrmHook.OnDrmFileNotify(Sender: TObject; const Item: PDrmFileInfo; Action: TCollectionNotification); begin if Action = cnRemoved then Dispose(Item); end; procedure TTgDrmHook.AddInterceptAPI(var aProcDest: Pointer; aProcSrc, aProcHook: Pointer; sProcName: String); begin if aProcDest = nil then begin aProcDest := InterceptCreate(aProcSrc, aProcHook); if aProcDest <> nil then begin Log(Format('>>> InterceptCreate() - %s <<<', [sProcName])); ProcList_.Add(@aProcDest); end else Log(Format('>>> Fail .. InterceptCreate() - %s <<<', [sProcName])); end; end; procedure TTgDrmHook.DoInterceptCreate; var bLoadBx: Boolean; // nTryCnt: Integer; Label LB_LoadBx; begin Log('DoInterceptCreate()'); DoInterceptRemove; Log('DoInterceptCreate() .. 0'); if bUseBoxedApp_ then begin Log('UseBoxedApp...'); // nTryCnt := 0; bLoadBx := false; LB_LoadBx : try // Init BoxedApp SDK BoxedAppSDK_SetContext('21f2f010-06e4-465f-af8f-cde6a3752c39'); Log('DoInterceptCreate() .. 1'); BoxedAppSDK_Init; Log('DoInterceptCreate() .. 2'); // Allow injection BoxedApp engine into child processes // BoxedAppSDK_EnableOption(DEF_BOXEDAPPSDK_OPTION__EMBED_BOXEDAPP_IN_CHILD_PROCESSES, TRUE); // BoxedAppSDK_EnableOption(DEF_BOXEDAPPSDK_OPTION__HIDE_VIRTUAL_FILES_FROM_FILE_DIALOG, TRUE); BoxedAppSDK_EnableOption(DEF_BOXEDAPPSDK_OPTION__ALL_CHANGES_ARE_VIRTUAL, TRUE); Log('DoInterceptCreate() .. 3'); bLoadBx := true; except Log('Fail .. BoxedAppSDK'); end; if not bLoadBx then begin Sleep(10); goto LB_LoadBx; end; end; AddInterceptAPI(@ozCreateFileA, @CreateFileA, @CreateFileAHook, 'CreateFileA'); AddInterceptAPI(@ozCreateFileW, @CreateFileW, @CreateFileWHook, 'CreateFileW'); AddInterceptAPI(@ozCloseHandle, @CloseHandle, @CloseHandleHook, 'CloseHandle'); // AddInterceptAPI(@ozReadFile, @ReadFile, @ReadFileHook, 'ReadFile'); AddInterceptAPI(@ozWriteFile, @WriteFile, @WriteFileHook, 'WriteFile'); AddInterceptAPI(@ozWriteFileEx, @WriteFileEx, @WriteFileExHook, 'WriteFileEx'); bInitOk_ := true; end; procedure TTgDrmHook.DoInterceptRemove; procedure RemoveAPI(var aProc: Pointer); inline; begin if aProc <> nil then begin InterceptRemove(aProc); aProc := nil; end; end; var i: Integer; begin if bInitOk_ then begin Log('DoInterceptRemove()'); for i := 0 to ProcList_.Count - 1 do RemoveAPI(ProcList_[i]^); ProcList_.Clear; // BoxedAppSDK_Exit; bInitOk_ := false; end; end; procedure TTgDrmHook.Log(sLog: String); begin if Trace_ <> nil then Trace_.T('(%s) %s', [ModuleName, sLog]); end; function TTgDrmHook.InstallHook: Integer; begin Log('InstallHook'); try hShellHook_ := SetWindowsHookEx(WH_SHELL, process_WH_SHELL, HInstance, 0); if hShellHook_ = 0 then begin Log('SetWindowsHookEx(WH_SHELL) fail!!'); Result := 2; exit; end; except exit; end; // if (hCbtHook_ <> 0) and (hShellHook_ <> 0) then Result := 0; // else // Result := -2; end; function TTgDrmHook.UnInstallHook: Integer; begin Log('UnInstallHook'); try if hShellHook_ <> 0 then begin Log('UnhookWindowsHookEx(ShellHook)'); UnhookWindowsHookEx(hShellHook_); hShellHook_ := 0; end; except hShellHook_ := 0; end; Result := 0; end; function InstallDrmHook: Integer; begin Result := -1; if Assigned(_TgDrmHook) then Result := _TgDrmHook.InstallHook; end; function UnInstallDrmHook: Integer; begin Result := -1; if Assigned(_TgDrmHook) then Result := _TgDrmHook.UnInstallHook; end; exports InstallDrmHook, UnInstallDrmHook; end.