922 lines
29 KiB
Plaintext
922 lines
29 KiB
Plaintext
{*******************************************************}
|
|
{ }
|
|
{ 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<TSharedData>;
|
|
hShellHook_: HHook;
|
|
Trace_: TTgTrace;
|
|
dtCreate_: TDateTime;
|
|
// sPass_,
|
|
sTgPNames_,
|
|
sLogPath_: String;
|
|
hRecentWnd_: HWND;
|
|
bInitOk_,
|
|
bUseBoxedApp_,
|
|
bIsMsOffice_,
|
|
bForceEncSave_: Boolean;
|
|
// DrmFileList_: TStringList;
|
|
DcDecPath_: TDictionary<String,String>;
|
|
bBlockCap_: Boolean;
|
|
DrmExtList_: TStringList;
|
|
DcDrmFI_: TDictionary<THandle,PDrmFileInfo>;
|
|
RecentDrmFI_: TDrmFileInfo; // MS오피스 저장 파일 암호화를 위함
|
|
|
|
sRecentOpenFile_: String;
|
|
|
|
ProcList_: TList<PPointer>;
|
|
|
|
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<PPointer>.Create;
|
|
DcDrmFI_ := TDictionary<THandle,PDrmFileInfo>.Create;
|
|
DcDrmFI_.OnValueNotify := OnDrmFileNotify;
|
|
ZeroMemory(@RecentDrmFI_, SizeOf(RecentDrmFI_));
|
|
|
|
SharedData_ := TTgFileMapping<TSharedData>.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<String,String>.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.
|