{*******************************************************} { } { ManagerHook } { } { Copyright (C) 2022 kku } { } {*******************************************************} unit ManagerHook; interface uses Tocsg.Obj, System.SysUtils, System.Classes, Winapi.Windows, Tocsg.CommonData, Tocsg.Thread, Tocsg.Process, Winapi.Messages, GlobalDefine, Tocsg.WndUtil, AppCtrlServer, System.SyncObjs, AppCtrlDefine, System.Generics.Collections, Tocsg.Process.IPC, ManagerModel, DDispLogo, Tocsg.Win32; {$IFDEF DEBUG} // {$DEFINE _HOOK_TEST_} {$ENDIF} const PIPE_NAME = 'BS1@230316'; // PIPE_NAME = 'BS1@260107'; BS1HOOK_IPCMESSAGE_STRING = 'ipcBs1MhCtrl'; type PAppInfoEnt = ^TAppInfoEnt; TAppInfoEnt = record dwPid: DWORD; hMain: HWND; end; TDcAppInfo = TDictionary; TManagerHook = class(TTgObject) private CS_: TCriticalSection; ThdAppMon_: TThdProcessWatch; ThdWndMon_: TThdActiveWndMon; ProcList_: TProcessEntList; PidList_: TProcessIdList; TgAppList_, TgAppList_mad_, TgAppExList_, DrmAppList_, WebAppList_, PrintAppList_, CaptureBlockApps_: TStringList; sTgApps_, sTgApps_mad_, sConfDir_, sLogPath_, sHlpExe_, sDllPath_, sDll32Path_, // sDllPathPdf_, sPrtWaterSupportApp_: String; bIsWow64_: Boolean; DcApp_: TDcAppInfo; // madCodeHook 관련 bUse_madCodeHook_: Boolean; mtx_madCode_: TTgMutex; Server_: TAppCtrlServer; DefHookOpt_: TAppCtrlOpt; procedure Lock; procedure Unlock; function IsTgApp(sPName: String): Boolean; procedure DelTgApp(sPName: String); function GetCtrlOpt(pEnt: PCMEnt): TAppCtrlOpt; procedure OnSendCtrlOpt(pEnt: PCMEnt); procedure OnAppNotify(aSender: TThdProcessWatch; pEnt: PPwEnt; aKind: TProcessWatchKind); procedure OnWndNotify(aSender: TObject; hActiveWnd: HWND); procedure SafeFreeClient; procedure StopHookWatch; procedure ClearHook(bMore: Boolean = false); procedure FreeMon; procedure OnAppInfoNotify(Sender: TObject; const Item: PAppInfoEnt; Action: TCollectionNotification); procedure UpdatePreLoadInfo; procedure SendWndCaptureBlock(hPipe: THandle; hTg: HWND; bVal: Boolean); function IsAcrobat(sPName: String): Boolean; function IsTgApp_mad(sPName: String): Boolean; procedure AddPid(dwPid: DWORD); function HasPid(dwPid: DWORD): Boolean; procedure DelPid(dwPid: DWORD); procedure Start_madCodeHookInjection; procedure Stop_madCodeHookInjection; public DrmAccessKind, DrmModifyKind: TDrmAccessKind; bPrtCollect, bPrintSecu, bPrintWater, bDrmAttachAble, bFileApproval, bIgrNetPathAB, bOpenDetect, bCaptureBlockApps: Boolean; WebbAB, OutlookAB, EtcAppAB: TAttachBlockPolicy; sEtcABApps, sWaterExcepts, sCaptureBlockApps, CaptureBlockUrls: String; CaptureBlockUrlKind: TBlockKind; MtpBlockKind: TUsbBlockKind; MtpRoExp, PrtNameH: String; PrtWaterCfg: TPrtWaterCfg; ShFileCrMon: TShFileCrMon; OutFileBlockMB, WebFileBlockMB, AppFileBlockMB: Integer; Constructor Create; Destructor Destroy; override; function IsChangeHookPolicy(aPO: TPrefModel): Boolean; function SetCaptureBlock(hTg: HWND; bVal: Boolean): Boolean; procedure UpdateHookTarget; procedure StartHookWatch; end; function RefinePrintHookAppList(aList: TStringList): Boolean; implementation uses Tocsg.WinInfo, Tocsg.Path, ManagerService, Tocsg.Exception, Tocsg.Shell, Tocsg.Strings, Condition, System.IniFiles, Tocsg.Safe, Tocsg.Packet, Vcl.Forms, Tocsg.Json, Tocsg.Registry, Tocsg.Trace, madCodeHook, superobject; function RefinePrintHookAppList(aList: TStringList): Boolean; var n: Integer; sTemp: String; begin Result := false; if IsHD then begin // 아래한글 프린트 워터마크는 다른 보안프로그램으로 처리하기 때문에 예외 요청함 23_1018 17:11:05 kku n := aList.IndexOf('hwp.exe'); if n <> -1 then begin aList.Delete(n); Result := true; end; end else begin case CUSTOMER_TYPE of CUSTOMER_WELFNI, CUSTOMER_WELFND : begin n := aList.IndexOf('notepad.exe'); if n <> -1 then begin aList.Delete(n); Result := true; end; end; end; end; sTemp := gMgSvc.PrefModel.PrtWaterAppHig; if sTemp <> '' then begin var StrList: TStringList; Guard(StrList, TStringList.Create); SplitString(sTemp, '|', StrList, false, true); var i: Integer; for i := 0 to StrList.Count - 1 do begin n := aList.IndexOf(StrList[i]); if n <> -1 then begin aList.Delete(n); Result := true; end; end; end; end; { TManagerHook } Constructor TManagerHook.Create; var // sTextOutDir, sTextOutApp: String; ini: TIniFile; sPath, sTemp: String; n: Integer; begin Inherited Create; // _Trace('Create() ..'); CS_ := TCriticalSection.Create; bUse_madCodeHook_ := IsUse_madCodeHook; sDllPath_ := GetRunExePathDir + DIR_CONF + DLL_HOOK; if not FileExists(sDllPath_) then sDllPath_ := GetRunExePathDir + DLL_HOOK; sDll32Path_ := GetRunExePathDir + DIR_CONF + DLL_HOOK32; if not FileExists(sDll32Path_) then sDll32Path_ := GetRunExePathDir + DLL_HOOK32; // sDllPathPdf_ := GetRunExePathDir + DIR_CONF + DLL_HOOK_PDF; // if not FileExists(sDllPathPdf_) then // sDllPathPdf_ := GetRunExePathDir + DLL_HOOK_PDF; Server_ := nil; mtx_madCode_ := nil; sLogPath_ := CutFileExt(GetRunExePath) + '.log'; sHlpExe_ := GetRunExePathDir + DIR_CONF + EXE_HP; sConfDir_ := GetRunExePathDir + DIR_CONF; sTgApps_ := ''; sTgApps_mad_ := ''; sCaptureBlockApps := ''; bCaptureBlockApps := false; OutFileBlockMB := 0; WebFileBlockMB := 0; AppFileBlockMB := 0; // sTextOutDir := ''; sTextOutApp := GetRunExePathDir + DIR_CONF + EXE_OCR; if not FileExists(sTextOutApp) then sTextOutApp := ''; ZeroMemory(@PrtWaterCfg, SizeOf(PrtWaterCfg)); ZeroMemory(@ShFileCrMon, SizeOf(ShFileCrMon)); sTemp := sLogPath_[1] + ':\ProgramData\HE\'; ZeroMemory(@DefHookOpt_, SizeOf(DefHookOpt_)); DefHookOpt_.hRcvWnd := gMgSvc.RcvHwnd; DefHookOpt_.sTaskDir := sTemp + 'Desk\'; DefHookOpt_.dwCustomerType := CUSTOMER_TYPE; DefHookOpt_.sDrmPass := GetMK(false); // DefHookOpt_.sTextOutApp := sTextOutApp; // DefHookOpt_.sTextOutDir := sTextOutDir; DefHookOpt_.nFontSize := 175; DefHookOpt_.nLineCount := 4; ForceDirectories(DefHookOpt_.sTaskDir); // DefHookOpt_.sPrintWaterTxt := gMgSvc.EmpNo + '/' + gMgSvc.NicService.GetIP + '/' + FormatDateTime('yyyy-mm-dd', Now); DefHookOpt_.sAipPath := gMgSvc.GetAipPath; // if IsPrintWaterBoth and not IsPrintWaterHookForce then // DefHookOpt_.sPrintWaterImg := '*HB*|' + gMgSvc.PrefModel.PrtNameH; if IsPrintWaterHook and not IsHD then DefHookOpt_.sPrtEmfOutDir := sTemp + 'PrtCol\'; // if IsPrtSpl2Pdf then // begin // sPrtWaterSupportApp_ := '*' + EXE_HE;// + '|*' + EXE_CS; // end else begin case CUSTOMER_TYPE of CUSTOMER_GEC, CUSTOMER_HDENG : sPrtWaterSupportApp_ := RPINT_SUPPORT_APPS_HEC; else sPrtWaterSupportApp_ := PRINT_SUPPORT_APPS; end; sPath := GetProgramFilesDir + DIR_TG + INI_FORCEHE; if FileExists(sPath) then begin try Guard(ini, TIniFile.Create(sPath)); sPrtWaterSupportApp_ := sPrtWaterSupportApp_ + '|' + ini.ReadString('Force', 'PrtWaterApp', ''); // sTextOutDir := IncludeTrailingPathDelimiter(ini.ReadString('Test', 'HookOutDir', '')); DefHookOpt_.fWmTran := ini.ReadFloat('Force', 'WmTran', 0.0); except // .. end; end; end; if IsPrintWaterHookAppUp then sPrtWaterSupportApp_ := sPrtWaterSupportApp_ + '|' + APP_WEB_BROWSERS; sTemp := gMgSvc.PrefModel.PrtWaterAppH; if sTemp <> '' then sPrtWaterSupportApp_ := sPrtWaterSupportApp_ + '|' + sTemp; ProcList_ := TProcessEntList.Create;; ProcList_.DetailInfo := false; PidList_ := TProcessIdList.Create; DcApp_ := TDcAppInfo.Create; DcApp_.OnValueNotify := OnAppInfoNotify; TgAppList_ := TStringList.Create; TgAppList_.CaseSensitive := false; TgAppList_mad_ := TStringList.Create; TgAppList_mad_.CaseSensitive := false; TgAppExList_ := TStringList.Create; TgAppExList_.CaseSensitive := false; DrmAppList_ := TStringList.Create; DrmAppList_.CaseSensitive := false; {$IFNDEF _HOOK_TEST_} if not NotUseDRM and not bUse_madCodeHook_ then SplitString(DRM_SUPPORT_APPS, '|', DrmAppList_); {$ENDIF} WebAppList_ := TStringList.Create; WebAppList_.CaseSensitive := false; SplitString(WEB_BROWSERS, '|', WebAppList_); PrintAppList_ := TStringList.Create; PrintAppList_.CaseSensitive := false; // if IsPrintWaterHook or IsPrintWaterBoth or IsPrtSpl2Pdf then // 프린트 마스킹도 필요 24_0524 10:06:27 kku if IsPrintWaterHook then // 프린트 마스킹도 필요 24_0524 10:06:27 kku SplitString(sPrtWaterSupportApp_, '|', PrintAppList_, false, true); if RefinePrintHookAppList(PrintAppList_) then sPrtWaterSupportApp_ := ListToDelimitedText(PrintAppList_, '|'); CaptureBlockApps_ := TStringList.Create; CaptureBlockApps_.CaseSensitive := false; ThdAppMon_ := nil; ThdWndMon_ := nil; bIsWow64_ := IsWow64; end; Destructor TManagerHook.Destroy; begin // _Trace('Destroy() ..'); StopHookWatch; FreeAndNil(CaptureBlockApps_); FreeAndNil(PrintAppList_); FreeAndNil(WebAppList_); FreeAndNil(DrmAppList_); FreeAndNil(TgAppExList_); FreeAndNil(TgAppList_mad_); FreeAndNil(TgAppList_); FreeAndNil(DcApp_); FreeAndNil(PidList_); FreeAndNil(ProcList_); if Server_ <> nil then FreeAndNil(Server_); if mtx_madCode_ <> nil then FreeAndNil(mtx_madCode_); Inherited; FreeAndNil(CS_); end; function TManagerHook.IsChangeHookPolicy(aPO: TPrefModel): Boolean; var PPO: TPrefModel; begin PPO := gMgSvc.PrefModel; Result := (aPO.DrmAccessKind <> DrmAccessKind) or (aPO.DrmModifyKind <> DrmModifyKind) or (aPO.IsDrmAttAble <> bDrmAttachAble) or ((aPO.Print.PrintKind <> pkNone) and not bPrintSecu) or ((aPO.Print.PrintKind = pkNone) and bPrintSecu) or (IsPrintWaterHook and ((aPO.IsPrtCollectThum or IsApproveSupport) <> bPrtCollect)) or ((aPO.Print.PrintWater <> pwNone) and (aPO.Print.sWaterExcepts <> sWaterExcepts)) or // ( (IsPrintWaterHook or not FileExists(sConfDir_ + EXE_SPL) or IsPrintWaterBoth or IsPrtSpl2Pdf) and ( (IsPrintWaterHook or not FileExists(sConfDir_ + EXE_SPL)) and ( ((aPO.Print.PrintWater <> pwNone) and not bPrintWater) or ((aPO.Print.PrintWater = pwNone) and bPrintWater) ) ) or (aPO.Print.sWaterExcepts <> sWaterExcepts) or (aPO.bCaptureBlockApps_ <> bCaptureBlockApps) or (aPO.CaptureBlockApps <> sCaptureBlockApps) or (aPO.OutFileBlockMB <> OutFileBlockMB) or (aPO.WebFileBlockMB <> WebFileBlockMB) or (aPO.AppFileBlockMB <> AppFileBlockMB) or (aPO.EtcAB.Kind <> EtcAppAB.Kind) or ((aPO.EtcABApps + '|' + aPO.EtcAbLogList) <> sEtcABApps) or (aPO.OutlookAB.Kind <> OutlookAB.Kind) or (aPO.WebbAB.Kind <> WebbAB.Kind) or (aPO.EtcAB.bPopup <> EtcAppAB.bPopup) or (aPO.EtcAB.bReadBlock <> EtcAppAB.bReadBlock) or (aPO.EtcAB.bWriteBlock <> EtcAppAB.bWriteBlock) or (aPO.EtcAB.bCollectTxt <> EtcAppAB.bCollectTxt) or (aPO.EtcAB.bCollectFile <> EtcAppAB.bCollectFile) or (aPO.EtcAB.ContentFilter.bActive <> EtcAppAB.ContentFilter.bActive) or (aPO.EtcAB.ContentFilter.sPatterns <> EtcAppAB.ContentFilter.sPatterns) or (aPO.EtcAB.ContentFilter.nHitLimit <> EtcAppAB.ContentFilter.nHitLimit) or (aPO.OutlookAB.bPopup <> OutlookAB.bPopup) or (aPO.OutlookAB.bReadBlock <> OutlookAB.bReadBlock) or (aPO.OutlookAB.bWriteBlock <> OutlookAB.bWriteBlock) or (aPO.OutlookAB.bCollectTxt <> OutlookAB.bCollectTxt) or (aPO.OutlookAB.bCollectFile <> OutlookAB.bCollectFile) or (aPO.OutlookAB.ContentFilter.bActive <> OutlookAB.ContentFilter.bActive) or (aPO.OutlookAB.ContentFilter.sPatterns <> OutlookAB.ContentFilter.sPatterns) or (aPO.OutlookAB.ContentFilter.nHitLimit <> OutlookAB.ContentFilter.nHitLimit) or (aPO.WebbAB.bPopup <> WebbAB.bPopup) or (aPO.WebbAB.bReadBlock <> WebbAB.bReadBlock) or (aPO.WebbAB.bWriteBlock <> WebbAB.bWriteBlock) or (aPO.WebbAB.bCollectTxt <> WebbAB.bCollectTxt) or (aPO.WebbAB.bCollectFile <> WebbAB.bCollectFile) or (aPO.WebbAB.ContentFilter.bActive <> WebbAB.ContentFilter.bActive) or (aPO.WebbAB.ContentFilter.sPatterns <> WebbAB.ContentFilter.sPatterns) or (aPO.WebbAB.ContentFilter.nHitLimit <> WebbAB.ContentFilter.nHitLimit) or ((IsApproveSupport and aPO.ExFApproval) <> bFileApproval) or (PPO.OpenDetect <> bOpenDetect) or (PPO.IgrNetPathAB <> bIgrNetPathAB) or (aPO.ShFileCrMon.nKind <> ShFileCrMon.nKind) or (aPO.ShFileCrMon.sExpLst <> ShFileCrMon.sExpLst) or (aPO.CaptureBlockUrlKind <> CaptureBlockUrlKind) or (aPO.CaptureBlockUrls <> CaptureBlockUrls) or ( (aPO.MtpBlockKind <> MtpBlockKind) and ( (aPO.MtpBlockKind = ubkReadOnly) or (MtpBlockKind = ubkReadOnly) ) ) or (MtpRoExp <> aPO.MtpExcept) or (PrtNameH <> PPO.PrtNameH) or not CompareMem(@PrtWaterCfg, @aPO.PrtWaterCfg, SizeOf(PrtWaterCfg)); end; procedure TManagerHook.SendWndCaptureBlock(hPipe: THandle; hTg: HWND; bVal: Boolean); var Send: ISendPacket; begin try Send := TTgPacket.Create(ACC_SET_CAPTURE_BLOCK); Send.Toss := hPipe; Send.I['Wnd'] := hTg; Send.B['Block'] := bVal; Server_.SendPacket(Send); except on E: Exception do ETgException.TraceException(Self, E, 'Fail .. SendWndCaptureBlock()'); end; end; function TManagerHook.IsAcrobat(sPName: String): Boolean; begin Result := (CompareText(sPName, 'Acrobat.exe') = 0) or (CompareText(sPName, 'AcroCEF.exe') = 0) or (CompareText(sPName, 'AcroRd32.exe') = 0) end; function TManagerHook.IsTgApp_mad(sPName: String): Boolean; begin Lock; try Result := TgAppList_mad_.IndexOf(sPName) <> -1; finally Unlock; end; end; procedure TManagerHook.AddPid(dwPid: DWORD); begin Lock; try if PidList_.IndexOf(dwPid) = -1 then PidList_.Add(dwPid); finally Unlock; end; end; function TManagerHook.HasPid(dwPid: DWORD): Boolean; begin Lock; try Result := PidList_.IndexOf(dwPid) <> -1; finally Unlock; end; end; procedure TManagerHook.DelPid(dwPid: DWORD); var i: Integer; begin Lock; try i := PidList_.IndexOf(dwPid); if i <> -1 then PidList_.Delete(i); finally Unlock; end; end; function TManagerHook.SetCaptureBlock(hTg: HWND; bVal: Boolean): Boolean; var dwPid: DWORD; pEnt: PCMEnt; Send: ISendPacket; begin Result := false; try dwPid := GetProcessPIDFromWndHandle(hTg); if dwPid = 0 then exit; if DcApp_.ContainsKey(dwPid) and (Server_ <> nil) and (Server_.Connected) then begin pEnt := Server_.GetCMEEntByPID(dwPid); if pEnt = nil then exit; if pEnt.bCapBlock <> bVal then begin pEnt.bCapBlock := bVal; Result := true; SendWndCaptureBlock(pEnt.hPipe, hTg, bVal); end; end; except on E: Exception do ETgException.TraceException(Self, E, 'Fail .. SetCaptureBlock()'); end; end; // DRM 등 DLL Injection 후 바로 인식해야 하는 정보를 모아서 미리 파일로 저장해서 공유 // TTgFileMapping 사용 안함 25_0205 16:20:06 kku procedure TManagerHook.UpdatePreLoadInfo; var O, OEtc, OApp: ISuperObject; PO: TPrefModel; StrList: TStringList; sAppName: string; i: Integer; begin PO := gMgSvc.ModePolicy; O := SO; O.I['CT'] := CUSTOMER_TYPE; O.I['RcvWnd'] := gMgSvc.RcvHwnd; O.B['PrtSecu'] := bPrintSecu; O.B['bPrtWater'] := bPrintWater; O.B['PrtCol'] := bPrtCollect; O.I['DAK'] := Integer(PO.DrmAccessKind); O.I['DMK'] := Integer(PO.DrmModifyKind); O.S['AS'] := GetMK(false); O.S['EmpNo'] := gMgSvc.EmpNo; O.S['UName'] := gMgSvc.UName; if gMgSvc.DeptName <> '' then O.S['Dept'] := gMgSvc.DeptName else O.S['Dept'] := PO.DeptName; O.S['IP'] := gMgSvc.NicService.GetIP; O.S['EmfDir'] := DefHookOpt_.sPrtEmfOutDir; O.S['TskDir'] := DefHookOpt_.sTaskDir; O.O['ShFileCrMon'] := TTgJson.ValueToJsonObject(PO.ShFileCrMon); //mgkim madcodehook bluetooth fsqu.. 을 위한 추가 정책 저장 // EtcAB 설정을 담을 객체 생성 OEtc := SO; if (PO.EtcAB.Kind <> abkNone) and (sEtcABApps <> '') then begin StrList := TStringList.Create; try StrList.CaseSensitive := False; SplitString(sEtcABApps, '|', StrList); // 앱 목록 분리 for i := 0 to StrList.Count - 1 do begin sAppName := ChangeFileExt(StrList[i], ''); if sAppName = '' then Continue; // 개별 앱의 정책을 담을 객체 OApp := SO; // 해당 앱의 정책 결정 로직 case PO.EtcAB.Kind of abkBlock: OApp.I['FileUseBlock'] := Integer(fubBlock); abkLog: OApp.I['FileUseBlock'] := Integer(fubMonitor); else OApp.I['FileUseBlock'] := Integer(fubNone); end; // 예외 리스트(White-list) 체크: 차단 대상이지만 로그 목록에 있다면 모니터링으로 변경 if (OApp.I['FileUseBlock'] = Integer(fubBlock)) and (Pos(UpperCase(sAppName), UpperCase(PO.EtcAbLogList)) > 0) then begin OApp.I['FileUseBlock'] := Integer(fubMonitor); end; // 세부 정책 하위 할당 OApp.B['bUseContentFilter'] := PO.EtcAB.ContentFilter.bActive; OApp.B['bReadBlock'] := PO.EtcAB.bReadBlock; OApp.B['bWriteBlock'] := PO.EtcAB.bWriteBlock; OApp.I['nBlockSizeMB'] := AppFileBlockMB; // 앱 이름을 Key로 하여 전체 리스트에 추가 OEtc.O[UpperCase(sAppName)] := OApp; end; finally StrList.Free; end; end; O.O['EtcABApps'] := OEtc; SaveJsonObjToFile(O, GetRunExePathDir + DIR_CONF + 'noenc_hpli.dat'); SaveJsonObjToEncFile(O, GetRunExePathDir + DIR_CONF + 'hpli.dat', '9live@u'); end; procedure TManagerHook.Lock; begin CS_.Acquire; end; procedure TManagerHook.Unlock; begin CS_.Release; end; function TManagerHook.IsTgApp(sPName: String): Boolean; begin try Lock; try Result := TgAppList_.IndexOf(sPName) <> -1; finally Unlock; end; except on E: Exception do ETgException.TraceException(Self, E, 'Fail .. IsTgApp()'); end; end; procedure TManagerHook.DelTgApp(sPName: String); var n: Integer; begin try Lock; try n := TgAppList_.IndexOf(sPName); if n <> -1 then TgAppList_.Delete(n); finally Unlock; end; except on E: Exception do ETgException.TraceException(Self, E, 'Fail .. DelTgApp()'); end; end; function TManagerHook.GetCtrlOpt(pEnt: PCMEnt): TAppCtrlOpt; var PO: TPrefModel; StrList: TStringList; i: Integer; begin try PO := gMgSvc.ModePolicy; UpdatePreLoadInfo; _Trace(Format('GetCtrlOpt, dwPid(%d)', [pEnt.dwPid])); // 최신 정보로 업데이트 되도록 위치 이동 25_1126 14:55:52 kku DefHookOpt_.sAccount := gMgSvc.Account; DefHookOpt_.sAcName := GetUserNameFromReg; DefHookOpt_.sAcSSid := gMgSvc.RecentUserSid; DefHookOpt_.sUName := gMgSvc.UName; DefHookOpt_.sEmpNo := gMgSvc.EmpNo; // 이름 변경되게 하면... 불안하다.. if gMgSvc.DeptName <> '' then DefHookOpt_.sDeptName := ExtrLastDelimiterStr(gMgSvc.DeptName, ';') else if gMgSvc.PrefModel.DeptName <> '' then DefHookOpt_.sDeptName := ExtrLastDelimiterStr(gMgSvc.PrefModel.DeptName, ';'); Result := DefHookOpt_; if DcApp_.ContainsKey(pEnt.dwPid) then Result.hMainWnd := DcApp_[pEnt.dwPid].hMain; // Result.sEmpNo := gMgSvc.EmpNo; // 이름 변경되게 하면... 불안하다.. // Result.sDeptName := ExtrLastDelimiterStr(ModePolicy.DeptName, ';'); if NotUseDRM then begin Result.DrmAccessKind := dakNone; Result.DrmModifyKind := dakNone; end else begin Result.DrmAccessKind := DrmAccessKind; Result.DrmModifyKind := DrmModifyKind; end; // if gClient <> nil then // Result.hTagWnd := gClient.GetSelfWnd // else // Result.hTagWnd := 0; Result.bDrmAttachAble := bDrmAttachAble; Result.sIpAddr := gMgSvc.NicService.GetIP; if PrintAppList_.IndexOf(pEnt.sPName) <> -1 then begin Result.bPrintSecu := bPrintSecu; Result.bPrintWater := bPrintWater; Result.bPrtCollect := bPrtCollect; // Result.bPrintWaterExp := bprin Result.bIsTest := true; // gMgSvc.IsHecDev; // todo : 정리 필요 23_1025 16:35:50 kku if Result.bPrintWater then begin if IsHD then Result.sPrintWaterExp := 'Adobe|' + sWaterExcepts // Adobe PDF Converter에서 워터마크 문제 발생 23_1220 10:34:40 kku else Result.sPrintWaterExp := sWaterExcepts; end; end; if WebAppList_.IndexOf(pEnt.sPName) <> -1 then begin // 크롬, 엣지 등에서는 백그라운드 프로세스 때문에 꼬여서 제대로 동작하지 않는다.. // ThdWebUrl.pas 에서 처리 하도록 보완 25_0324 11:08:24 kku // if Result.hMainWnd <> 0 then // begin // if ModePolicy.CaptureBlockUrlKind = bkAll then // begin // Result.hCltWnd := Result.hMainWnd; // SendWndCaptureBlock(pEnt.hPipe, Result.hMainWnd, true); // end else // SendWndCaptureBlock(pEnt.hPipe, Result.hMainWnd, false); // end else // _Trace('WB : Not found main window', 4); if (Result.hMainWnd <> 0) and (PO.CaptureBlockUrlKind = bkNone) then begin pEnt.bCapBlock := false; Result.hCltWnd := 0; SendWndCaptureBlock(pEnt.hPipe, Result.hMainWnd, false); end; if PO.WebbAB.Kind <> abkNone then begin case PO.WebbAB.Kind of abkNone : ; abkBlock : Result.FileUseBlock := fubBlock; // abkPopup, abkLog : Result.FileUseBlock := fubMonitor; abkUrlBlock, abkUrlAllow : begin Result.FileUseBlock := fubBlock; Result.bCheckUrl := true; end; end; if Result.FileUseBlock <> fubNone then begin if not gMgSvc.IsNewApi and (PO.WebbAB.Kind <> abkBlock) and not PO.WebbAB.bPopup then Result.FileUseBlock := fubMonitor; Result.bUseContentFilter := PO.WebbAB.ContentFilter.bActive; Result.bReadBlock := PO.WebbAB.bReadBlock; Result.bWriteBlock := PO.WebbAB.bWriteBlock; Result.nBlockSizeMB := WebFileBlockMB; end; end; end; // 아웃룩 첨부 차단은 후킹으로 사용하지 않음 24_0829 16:19:48 kku // if (ModePolicy.OutlookAB.Kind <> abkNone) and (CompareText('Outlook.exe', pEnt.sPName) = 0) then // begin // case ModePolicy.OutlookAB.Kind of // abkNone : Result.FileUseBlock := fubNone; // abkBlock : Result.FileUseBlock := fubBlock; //// abkPopup, // abkLog : // begin // if IsOutlookABMonitorHook then // Result.FileUseBlock := fubMonitor // else // Result.FileUseBlock := fubNone;//Result.FileUseBlock := fubMonitor; // 플러그인에서 처리하도록 한다 24_0326 15:09:10 kku // end; // end; // // if Result.FileUseBlock <> fubNone then // begin // Result.bUseContentFilter := ModePolicy.OutlookAB.ContentFilter.bActive; // Result.bReadBlock := ModePolicy.OutlookAB.bReadBlock; // Result.bWriteBlock := ModePolicy.OutlookAB.bWriteBlock; // Result.nBlockSizeMB := OutFileBlockMB; // end; // end; if (PO.EtcAB.Kind <> abkNone) and (sEtcABApps <> '') then begin Guard(StrList, TStringList.Create); StrList.CaseSensitive := false; SplitString(sEtcABApps, '|', StrList); if (StrList.IndexOf(pEnt.sPName) <> -1) or (TgAppExList_.IndexOf(pEnt.sPName) <> -1) then begin case PO.EtcAB.Kind of abkNone : ; abkBlock : Result.FileUseBlock := fubBlock; // abkPopup, abkLog : Result.FileUseBlock := fubMonitor; end; if (Result.FileUseBlock = fubBlock) and (Pos(UpperCase(pEnt.sPName), UpperCase(PO.EtcAbLogList)) > 0) then Result.FileUseBlock := fubMonitor; if Result.FileUseBlock <> fubNone then begin Result.bUseContentFilter := PO.EtcAB.ContentFilter.bActive; Result.bReadBlock := PO.EtcAB.bReadBlock; Result.bWriteBlock := PO.EtcAB.bWriteBlock; Result.nBlockSizeMB := AppFileBlockMB; end; end; end; // 화면 캡쳐방지 프로그램 적용 추가 23_0327 14:38:41 kku if bCaptureBlockApps and (CaptureBlockApps_.IndexOf(pEnt.sPName) <> -1) and DcApp_.ContainsKey(pEnt.dwPid) then Result.hCltWnd := DcApp_[pEnt.dwPid].hMain else Result.hCltWnd := 0; // {$IFDEF DEBUG} // PrtWaterCfg.bActive := true; // PrtWaterCfg.sTopText := 'top'; // PrtWaterCfg.sBotText := 'bottom'; // PrtWaterCfg.nTopSize := 20; // PrtWaterCfg.nBotSize := 20; // PrtWaterCfg.nTopPos := 2; // PrtWaterCfg.nBotPos := 2; // {$ENDIF} Result.PrtWaterCfg := PrtWaterCfg; Result.ShFileCrMon := ShFileCrMon; // MTP 읽기만 기능 추가 24_0304 15:02:28 kku Result.bMtpWB := (PO.MtpBlockKind = ubkReadOnly) and (CompareText('explorer.exe', pEnt.sPName) = 0); Result.sMtpRoExp := MtpRoExp; Result.bFileApproval := bFileApproval; Result.bIgrNetPathAB := bIgrNetPathAB; Result.bOpenDetect := bOpenDetect; // if IsPrintWaterBoth and not IsPrintWaterHookForce then // Result.sPrintWaterImg := '*HB*|' + PrtNameH // else Result.sPrintWaterImg := '' ; except on E: Exception do ETgException.TraceException(Self, E, 'Fail .. GetCtrlOpt()'); end; end; procedure TManagerHook.OnSendCtrlOpt(pEnt: PCMEnt); var Send: ISendPacket; Opt: TAppCtrlOpt; bOldCapBlock: Boolean; begin try AddPid(pEnt.dwPid); bOldCapBlock := pEnt.bCapBlock; Opt := GetCtrlOpt(pEnt); pEnt.bCapBlock := Opt.hCltWnd <> 0; if pEnt.bCapBlock <> bOldCapBlock then begin if pEnt.bCapBlock then gMgSvc.SendEventLog(URI_USER_ACTION, PREVENT_CAPTURE_WINDOW, pEnt.sPName) else gMgSvc.SendEventLog(URI_USER_ACTION, RELEASE_CAPTURE_WINDOW, pEnt.sPName); end; Send := TTgPacket.Create(ACC_SET_POLICY); Send.Toss := pEnt.hPipe; Send.O['Opt'] := TTgJson.ValueToJsonObject(Opt); Server_.SendPacket(Send); except on E: Exception do ETgException.TraceException(Self, E, 'Fail .. OnSendCtrlOpt()'); end; end; procedure TManagerHook.OnAppNotify(aSender: TThdProcessWatch; pEnt: PPwEnt; aKind: TProcessWatchKind); var nIdx: Integer; pApp: PAppInfoEnt; sPPName: String; begin case aKind of pwkUnknown : {$IFDEF DEBUG} ASSERT(false) {$ENDIF}; pwkInit, pwkExecute : begin sPPName:= GetProcessNameByPid(pEnt.dwPPid); if DrmAppList_.IndexOf(pEnt.sPName) <> -1 then begin if bUse_madCodeHook_ then exit; if NotUseDRM then exit; if DrmAccessKind = dakNone then // 열람 권한 없으면 무시 23_0503 08:06:03 kku exit; if (CompareText('excel.exe', pEnt.sPName) = 0) or (CompareText('WINWORD.exe', pEnt.sPName) = 0) or (CompareText('POWERPNT.exe', pEnt.sPName) = 0) then begin // 파워포인트등 외부 객체로 불러오는 경우 무시한다 (중소기업중앙회) 24_0503 09:22:23 kku // 워드, 파워포인트에서 엑셀 차트 삽입할때도 무시 25_0723 17:37:27 kku // 객체불로오기 일경우 아래의 부모프로세스로 부터 실행 되서 Hang 걸리는 현상 발생 (에스오에스랩) 251215 mgkim if (CompareText('svchost.exe', sPPName) = 0) or (CompareText('WINWORD.EXE', sPPName) = 0) or (CompareText('POWERPNT.EXE', sPPName) = 0) or (CompareText('excel.EXE', sPPName) = 0) then begin _Trace('InjectModule(2) ..object doc PName="%s", PID=%d, sPPName="%s"', [pEnt.sPName, pEnt.dwPid, sPPName], 3); exit; end; end; end else if TgAppExList_.IndexOf(pEnt.sPName) = -1 then exit; if CompareText(pEnt.sPName, 'MSEDGEWEBVIEW2.EXE') = 0 then begin if sPPName = '' then exit; if (CompareText(sPPName, 'OLK.EXE') <> 0) and (CompareText(sPPName, 'MS-TEAMS.EXE') <> 0) then exit; if (CompareText(sPPName, 'MS-TEAMS.EXE') = 0) and not IsTgApp('MS-TEAMS.EXE') then exit; if (CompareText(sPPName, 'OLK.EXE') = 0) and not IsTgApp('OLK.EXE') then exit; end; // if IsAcrobat(pEnt.sPName) then // 이거만 따로 처리 했는데 다시 원복. 나중에 안정화 확인 시 삭제 필요 25_1215 17:30:18 kku // begin // if InjectModule(pEnt.dwPid, sDllPathPdf_, @bIsWow64_) > 0 then // begin // _Trace('InjectModule(2) .. PName="%s", PID=%d', [pEnt.sPName, pEnt.dwPid], 3); // end else begin // if FileExists(sHlpExe_) then // begin // ExecutePath(sHlpExe_, Format('-hook2 %d', [pEnt.dwPid])); // _Trace('InjectModule32(2) .. PName="%s", PID=%d', [pEnt.sPName, pEnt.dwPid], 3); // end; // end; // end else begin if InjectModule(pEnt.dwPid, sDllPath_, @bIsWow64_) > 0 then begin //부모프로세스정보도 확인할 수 있게 로그 추가251215 mgkim _Trace('InjectModule() .. PName="%s", PID=%d, sPPName="%s"', [pEnt.sPName, pEnt.dwPid, sPPName], 3); //_Trace('InjectModule() .. PName="%s", PID=%d', [pEnt.sPName, pEnt.dwPid], 3); end else begin // Sleep(500); if FileExists(sHlpExe_) then begin // ExecuteAppWaitUntilTerminate(sHlpExe, Format('-hook %d', [pEnt.dwPid]), 5000); ExecutePath(sHlpExe_, Format('-hook %d', [pEnt.dwPid])); _Trace('InjectModule32() .. PName="%s", PID=%d', [pEnt.sPName, pEnt.dwPid], 3); end; // _Trace('Fail .. InjectModule() .. PName="%s"', [pEnt.sPName], 3); end; end; AddPid(pEnt.dwPid); if not DcApp_.ContainsKey(pEnt.dwPid) then begin New(pApp); pApp.dwPid := pEnt.dwPid; pApp.hMain := 0; DcApp_.Add(pEnt.dwPid, pApp); end; end; pwkTerminated : begin DelPid(pEnt.dwPid); if DcApp_.ContainsKey(pEnt.dwPid) then DcApp_.Remove(pEnt.dwPid); end; end; end; procedure TManagerHook.OnWndNotify(aSender: TObject; hActiveWnd: HWND); var dwPid: DWORD; sPName: String; pEnt: PProcessEntInfo; StrList: TStringList; pApp: PAppInfoEnt; ArchKind: TExeArchitectKind; procedure ProcessNextWork; var pCEnt: PCMEnt; begin if DcApp_.ContainsKey(pEnt.dwPid) then begin pApp := DcApp_[pEnt.dwPid]; // DRM 처리 프로세스는 여기로 옮 23_0327 15:21:22 kku if pApp.hMain = 0 then begin pApp.hMain := hActiveWnd; pCEnt := Server_.GetCMEEntByPID(pEnt.dwPid); if pCEnt <> nil then OnSendCtrlOpt(pCEnt); end else if pApp.hMain <> hActiveWnd then begin pCEnt := Server_.GetCMEEntByPID(pEnt.dwPid); if (pCEnt <> nil) and pCEnt.bCapBlock then begin // 캡처 방지. 추가된 윈도우 처리 23_0511 10:17:08 kku SendWndCaptureBlock(pCEnt.hPipe, hActiveWnd, true); end; end; end else begin New(pApp); pApp.dwPid := pEnt.dwPid; pApp.hMain := hActiveWnd; DcApp_.Add(pEnt.dwPid, pApp); if bUse_madCodeHook_ then begin // 뒤늣게 핸들이 구해지고 캡쳐 방지 상태면... pCEnt := Server_.GetCMEEntByPID(dwPid); if pCEnt <> nil then begin pCEnt.bCapBlock := bCaptureBlockApps and (CaptureBlockApps_.IndexOf(pCEnt.sPName) <> -1); if pCEnt.bCapBlock then SendWndCaptureBlock(pCEnt.hPipe, hActiveWnd, pCEnt.bCapBlock); // 많이 버벅여서 차단할때만 수행하는걸로 end; end; end; end; function Injecttion_madCodeHook(dwPid: DWORD; sDllPath: String): Boolean; var hProcess: THandle; begin Result := false; hProcess := OpenProcess(PROCESS_ALL_ACCESS, false, dwPid); if hProcess <> 0 then begin Result := InjectLibraryW(PChar(sDllPath), hProcess); CloseHandle(hProcess); end; end; begin try dwPid := GetProcessPIDFromWndHandle(hActiveWnd); if dwPid = 0 then exit; if HasPid(dwPid) then begin pEnt := ProcList_.GetProcInfoByPid(dwPid); if pEnt <> nil then ProcessNextWork; exit; end; ProcList_.UpdateProcessList; pEnt := ProcList_.GetProcInfoByPid(dwPid); if pEnt <> nil then begin sPName := ExtractFileName(pEnt.sModuleFileName); if bUse_madCodeHook_ and IsTgApp_mad(sPName) then exit; if not IsTgApp(sPName) then begin // AddPid(dwPid); exit; end; // if ForceDirectories(sTaskDir_) then // begin // var sPath: String := sTaskDir_ + 'vokee.$inf'; // if FileExists(sPath) then // DeleteFile(PChar(sPath)); // Guard(StrList, TStringList.Create); // StrList.Add(IntToStr(dwPid)); // StrList.Add(IntToStr(hActiveWnd)); // StrList.SaveToFile(sPath); // end; if CompareText('BizboxAMessenger.exe', sPName) = 0 then begin // 더존 메신저는 32비트 ProgramFiles에 설치되어 있고, // ArchKind 값도 eak32 확인되는데... 64bit DLL을 붙여야 동작한다 25_1015 13:58:28 kku ArchKind := eak64; end else ArchKind := GetExeFileArchitectFromePath(pEnt.sModuleFileName); case ArchKind of eakNoExe : begin // if IsAcrobat(sPName) then // 이거만 따로 처리 했는데 다시 원복. 나중에 안정화 확인 시 삭제 필요 25_1215 17:30:18 kku // begin // if InjectModule(dwPid, sDllPathPdf_, @bIsWow64_) > 0 then // begin // _Trace('InjectModule(2) .. PName="%s", PID=%d .. 1', [sPName, dwPid], 3); // AddPid(dwPid); // end else begin // if FileExists(sHlpExe_) then // begin // _Trace('InjectModule32(2) .. PName="%s", PID=%d .. 1', [sPName, dwPid], 3); // ExecutePath(sHlpExe_, Format('-hook2 %d', [dwPid])); // AddPid(dwPid); // end; // _Trace('Fail .. InjectModule(2) .. PName="%s", PID=%d .. 1', [sPName, dwPid], 3); // end; // end else begin if bUse_madCodeHook_ then begin if Injecttion_madCodeHook(dwPid, sDllPath_) then begin _Trace('InjectModule(mh) .... PName="%s", PID=%d .. 1', [sPName, dwPid], 3); AddPid(dwPid); end else if Injecttion_madCodeHook(dwPid, sDll32Path_) then begin _Trace('InjectModule32(mh) .... PName="%s", PID=%d .. 1', [sPName, dwPid], 3); AddPid(dwPid); end; end else begin if InjectModule(dwPid, sDllPath_, @bIsWow64_) > 0 then begin _Trace('InjectModule() .. PName="%s", PID=%d .. 1', [sPName, dwPid], 3); AddPid(dwPid); end else begin if FileExists(sHlpExe_) then begin _Trace('InjectModule32() .. PName="%s", PID=%d .. 1', [sPName, dwPid], 3); ExecutePath(sHlpExe_, Format('-hook %d', [dwPid])); AddPid(dwPid); end; _Trace('Fail .. InjectModule() .. PName="%s", PID=%d .. 1', [sPName, dwPid], 3); end; end; end; end; eak32 : begin if (IsUseEncOnlyAIP or gMgSvc.FirstAip) and (CompareText(sPName, 'MSIP.Viewer.exe') = 0) then begin // 얘는 왜 64bit인데 32로 잡히는지... 23_1019 15:23:07 kku if bUse_madCodeHook_ then begin if Injecttion_madCodeHook(dwPid, sDllPath_) then begin _Trace('InjectModule(mh) .... PName="%s", PID=%d .. 2', [sPName, dwPid], 3); AddPid(dwPid); end; end else begin if InjectModule(dwPid, sDllPath_, @bIsWow64_) > 0 then begin _Trace('InjectModule() .... PName="%s", PID=%d .. 2', [sPName, dwPid], 3); AddPid(dwPid); end; end; end else if FileExists(sHlpExe_) then begin if bUse_madCodeHook_ then begin if Injecttion_madCodeHook(dwPid, sDll32Path_) then begin _Trace('InjectModule32(mh) .... PName="%s", PID=%d .. 2', [sPName, dwPid], 3); AddPid(dwPid); end; end else begin if IsAcrobat(sPName) then begin _Trace('InjectModule32(2) ... PName="%s", PID=%d .. 2', [sPName, dwPid], 3); ExecutePath(sHlpExe_, Format('-hook2 %d', [dwPid])); end else begin //_Trace('InjectModule32() ... PName="%s", PID=%d .. 2', [sPName, dwPid], 3); ExecutePath(sHlpExe_, Format('-hook %d', [dwPid])); end; AddPid(dwPid); end; end; // else // _Trace('Fail .. Not found exe .. HlpExe="%s"', [sHlpExe_]); end; eak64 : begin // if IsAcrobat(sPName) then // 이거만 따로 처리 했는데 다시 원복. 나중에 안정화 확인 시 삭제 필요 25_1215 17:30:18 kku // begin // if InjectModule(dwPid, sDllPathPdf_, @bIsWow64_) >0 then // begin // _Trace('InjectModule(2) .. PName="%s", PID=%d .. 3', [sPName, dwPid], 3); // AddPid(dwPid); // end; // end else begin if bUse_madCodeHook_ then begin if Injecttion_madCodeHook(dwPid, sDllPath_) then begin _Trace('InjectModule(mh) .... PName="%s", PID=%d .. 3', [sPName, dwPid], 3); AddPid(dwPid); end; end else begin if InjectModule(dwPid, sDllPath_, @bIsWow64_) >0 then begin _Trace('InjectModule() .. PName="%s", PID=%d .. 3', [sPName, dwPid], 3); AddPid(dwPid); end; end; end; end; // else // _Trace('Fail .. InjectModule() ... PName="%s"', [sPName]); end; ProcessNextWork; end; except on E: Exception do ETgException.TraceException(Self, E, 'Fail .. OnWndNotify()'); end; end; procedure TManagerHook.FreeMon; begin try if ThdAppMon_ <> nil then begin ThdAppMon_.OnProcessWatchNotify := nil; FreeAndNil(ThdAppMon_); end; if ThdWndMon_ <> nil then begin ThdWndMon_.OnActiveWndNotify := nil; FreeAndNil(ThdWndMon_); end; PidList_.Clear; DcApp_.Clear; except on E: Exception do ETgException.TraceException(Self, E, 'Fail .. FreeMon()'); end; end; procedure TManagerHook.OnAppInfoNotify(Sender: TObject; const Item: PAppInfoEnt; Action: TCollectionNotification); begin if Action = cnRemoved then Dispose(Item); end; procedure TManagerHook.UpdateHookTarget; var PPO, PO: TPrefModel; sABApps: String; EtcABl, WebbABl, OutlookABl: TAttachBlockPolicy; enum: TEnumerator; Send: ISendPacket; begin try PPO := gMgSvc.PrefModel; PO := gMgSvc.ModePolicy; DrmAccessKind := PO.DrmAccessKind; DrmModifyKind := PO.DrmModifyKind; bPrintSecu := PO.Print.PrintKind <> pkNone; bPrtCollect := IsPrintWaterHook and (PO.IsPrtCollectThum or IsApproveSupport); // bPrintWater := (IsPrintWaterHook or not FileExists(sConfDir_ + EXE_SPL) or IsPrintWaterBoth or IsPrtSpl2Pdf ) and (ModePolicy.Print.PrintWater <> pwNone); bPrintWater := (IsPrintWaterHook or not FileExists(sConfDir_ + EXE_SPL)) and (PO.Print.PrintWater <> pwNone); sWaterExcepts := PO.Print.sWaterExcepts; bDrmAttachAble := PO.IsDrmAttAble; WebbAB := PO.WebbAB; OutlookAB := PO.OutlookAB; EtcAppAB := PO.EtcAB; sEtcABApps := PO.EtcABApps + '|' + PO.EtcAbLogList; CaptureBlockUrlKind := PO.CaptureBlockUrlKind; CaptureBlockUrls := PO.CaptureBlockUrls; MtpBlockKind := PO.MtpBlockKind; MtpRoExp := PO.MtpExcept; PrtNameH := PPO.PrtNameH; PrtWaterCfg := PO.PrtWaterCfg; ShFileCrMon := PO.ShFileCrMon; bFileApproval := IsApproveSupport and PO.ExFApproval; bIgrNetPathAB := PPO.IgrNetPathAB; bOpenDetect := PPO.OpenDetect; OutFileBlockMB := PO.OutFileBlockMB; WebFileBlockMB := PO.WebFileBlockMB; AppFileBlockMB := PO.AppFileBlockMB; if DefHookOpt_.sTaskDir <> '' then ForceDirectories(DefHookOpt_.sTaskDir); // sABApps := DRM_SUPPORT_APPS + '|' + PRINT_SUPPERT_APPS; // if IsPrintWaterHook or IsPrintWaterBoth or IsPrtSpl2Pdf then if bUse_madCodeHook_ then begin sTgApps_mad_ := ''; if not NotUseDRM then sTgApps_mad_ := DRM_SUPPORT_APPS; sTgApps_mad_:= sTgApps_mad_ + '|FSQUIRT.exe'; if IsPrintWaterHook then begin sABApps := sPrtWaterSupportApp_; // if CUSTOMER_TYPE = CUSTOMER_SHCI then // sABApps := StrsReplace(sABApps, ['excel.exe', 'winword.exe', 'POWERPNT.EXE'], ''); // madHook 적용 안되도록 빼준다.. 25_0122 19:57:16 kku SumString(sTgApps_mad_, sABApps, '|'); end; // if CUSTOMER_TYPE = CUSTOMER_SHCI then // sABApps := 'EXCEL.EXE|WINWORD.EXE|POWERPNT.EXE' // 기존 방식으로 훅 되도록 여기에 추가 // else sABApps := ''; end else if IsPrintWaterHook then sABApps := sPrtWaterSupportApp_ else sABApps := ''; EtcABl := PO.EtcAB; if (EtcABl.Kind <> abkNone) and (PO.EtcABApps <> '') then SumString(sABApps, sEtcABApps, '|'); WebbABl := PO.WebbAB; if (WebbABl.Kind <> abkNone) or (PO.CaptureBlockUrlKind <> bkNone) then SumString(sABApps, WEB_BROWSERS, '|'); OutlookABl := PO.OutlookAB; if (OutlookABl.Kind <> abkNone) and IsOutlookABMonitorHook then SumString(sABApps, 'outlook.exe', '|'); if sCaptureBlockApps <> PO.CaptureBlockApps then begin sCaptureBlockApps := PO.CaptureBlockApps; SplitString(sCaptureBlockApps, '|', CaptureBlockApps_); end; bCaptureBlockApps := PO.bCaptureBlockApps_; if bCaptureBlockApps then SumString(sABApps, sCaptureBlockApps, '|'); if (MtpBlockKind = ubkReadOnly) or (ShFileCrMon.nKind <> 0) then SumString(sABApps, 'explorer.exe', '|'); _Trace(Format(' sABApps .. [%s]', [sABApps]), 1); if sABApps <> sTgApps_ then begin TgAppExList_.Clear; sTgApps_ := sABApps; SplitString(sTgApps_, '|', TgAppList_, false, true); SplitString(sTgApps_mad_, '|', TgAppList_mad_, false, true); if CUSTOMER_TYPE = CUSTOMER_KBIZ then DelTgApp('excel.exe'); // iexplore.exe는 Injection 하지 않음. 25_0808 13:20:16 kku // 신한신용정보에서 iexplore.exe 을 Injection 하면 인트라넷망 로그인할때 인증 실패 현상 확인됨 DelTgApp('iexplore.exe'); DelTgApp('msedgewebview2.exe'); if (TgAppList_.IndexOf('olk.exe') <> -1) or (TgAppList_.IndexOf('ms-teams.exe') <> -1) then TgAppExList_.Add('msedgewebview2.exe'); var i: Integer; var sPName: String; for i := TgAppList_.Count - 1 downto 0 do if (TgAppList_[i].Length > 0) and (TgAppList_[i][1] = '*') then begin sPName := TgAppList_[i]; TgAppList_.Delete(i); Delete(sPName, 1, 1); if TgAppExList_.IndexOf(sPName) = -1 then TgAppExList_.Add(sPName); end; end; {$IFDEF _HOOK_TEST_} TgAppList_.Clear; TgAppList_.Add('msedge.exe'); {$ENDIF} if Server_ <> nil then begin Guard(enum, Server_.GetCMEntEnumrator); while enum.MoveNext do begin Send := TTgPacket.Create(ACC_SET_POLICY); Send.Toss := enum.Current.hPipe; Send.O['Opt'] := TTgJson.ValueToJsonObject(GetCtrlOpt(enum.Current)); Server_.SendPacket(Send); end; end; except on E: Exception do ETgException.TraceException(Self, E, 'Fail .. UpdateHookTarget()'); end; end; procedure MadHookIpcMessageCallback(name: PAnsiChar; messageBuf: pointer; messageLen: dword; answerBuf: pointer; answerLen: dword; context: pointer); stdcall; var buf: string; begin SetString(buf, PAnsiChar(messageBuf), messageLen); TTgTrace.T('[MH] %s', [buf], 1); end; procedure TManagerHook.Start_madCodeHookInjection; var bSuccess: Boolean; sConfDir, sDataDir: String; begin try bSuccess := false; try if sTgApps_mad_ = '' then begin _Trace('Start_madCodeHookInjection() .. Fail .. GlobalHook 대상 프로세스를 찾을 수 없음 ..', 1); exit; end; mtx_madCode_ := TTgMutex.Create(MUTEX_MH); if mtx_madCode_.MutexState = msCreateOk then begin // if not CreateIpcQueue(PAnsiChar(BS1HOOK_IPCMESSAGE_STRING), MadHookIpcMessageCallback) then // begin // _Trace('[BS1HOOK] please don''t start me twice'); // exit; // end; if not LoadInjectionDriver(BS1HOOK_DRIVERTAG, BS1HOOK_DRIVERNAME32, BS1HOOK_DRIVERNAME64) then begin _Trace(Format('[BS1HOOK] loading driver failed error....(%d)', [GetLastError])); end; sConfDir := GetRunExePathDir + DIR_CONF; {$IFDEF DEBUG} sDataDir := sConfDir; {$ELSE} sDataDir := sConfDir[1] + ':\ProgramData\Tocsg\bs1\'; if not ForceDirectories(sDataDir) then begin _Trace('[BS1HOOK] Fail .. createDir'); exit; end; if not FileExists(sDataDir + DLL_HOOK32) then begin if not CopyFile(PChar(sConfDir + DLL_HOOK32), PChar(sDataDir + DLL_HOOK32), false) then begin _Trace('[BS1HOOK] Fail .. copyFile(1)'); exit; end; end; if not FileExists(sDataDir + DLL_HOOK) then begin if not CopyFile(PChar(sConfDir + DLL_HOOK), PChar(sDataDir + DLL_HOOK), false) then begin _Trace('[BS1HOOK] Fail .. copyFile(2)'); exit; end; end; if not FileExists(sDataDir + 'CI.bmp') and FileExists(sConfDir + 'CI.bmp') then begin if not CopyFile(PChar(sConfDir + 'CI.bmp'), PChar(sDataDir + 'CI.bmp'), false) then begin _Trace('[BS1HOOK] Fail .. copyFile(3)'); // exit; end; end; {$ENDIF} // if not InjectLibraryW(BS1HOOK_DRIVERTAG, PChar(sDataDir + DLL_HOOK32), ALL_SESSIONS, INJECT_METRO_APPS, PChar(sTgApps_mad_), 'bds.exe|WinDbgX.exe|Dbgview.exe|werfault.exe|RuntimeBroker.exe|SystemSettings.exe') then if not InjectLibraryW(BS1HOOK_DRIVERTAG, PChar(sDataDir + DLL_HOOK32), ALL_SESSIONS, INJECT_METRO_APPS, PChar(sTgApps_mad_), nil) then begin _Trace(Format('[BS1HOOK] InjectLibrary fail DLL_NAME32 INJECT_METRO_APPS...(%d)', [GetLastError])); exit; end; // if not InjectLibraryW(BS1HOOK_DRIVERTAG, PChar(sDataDir + DLL_HOOK), ALL_SESSIONS, INJECT_METRO_APPS, PChar(sTgApps_mad_), EXE_HE + '|bds.exe|AppCtrl.exe|ShellExperienceHost.exe|backgroundTaskHost.exe|WinDbgX.exe|Dbgview.exe|werfault.exe|RuntimeBroker.exe|SystemSettings.exe') then if not InjectLibraryW(BS1HOOK_DRIVERTAG, PChar(sDataDir + DLL_HOOK), ALL_SESSIONS, INJECT_METRO_APPS, PChar(sTgApps_mad_), nil) then begin _Trace(Format('[BS1HOOK] InjectLibrary fail DLL_NAME64 INJECT_METRO_APPS...(%d)', [GetLastError])); exit; end; bSuccess := true; end; finally if not bSuccess then begin // DestroyIpcQueue(PAnsiChar(BS1HOOK_IPCMESSAGE_STRING)); if mtx_madCode_ <> nil then FreeAndNil(mtx_madCode_); _Trace('GlobalHook .. Fail', 1); end else _Trace('GlobalHook .. OK', 1) end; except on E: Exception do ETgException.TraceException(Self, E, 'Fail .. Start_madCodeHookInjection()'); end; end; procedure TManagerHook.Stop_madCodeHookInjection; var sConfDir: String; begin try if mtx_madCode_ <> nil then begin sConfDir := GetRunExePathDir + DIR_CONF; // UninjectLibraryW(BS1HOOK_DRIVERTAG, PChar(sConfDir + DLL_HOOK), ALL_SESSIONS, INJECT_METRO_APPS, 'notepad++.exe', EXE_HE + '|ShellExperienceHost.exe|backgroundTaskHost.exe|Taskmgr.exe|SystemInformer.exe|dbgview.exe|werfault.exe|RuntimeBroker.exe|SystemSettings.exe'); // UninjectLibraryW(BS1HOOK_DRIVERTAG, PChar(sConfDir + DLL_HOOK32), ALL_SESSIONS, INJECT_METRO_APPS, 'notepad++.exe', '|AppCtrl.exe|Taskmgr.exe|SystemInformer.exe|dbgview.exe|werfault.exe|RuntimeBroker.exe|SystemSettings.exe'); // UninjectLibraryW(BS1HOOK_DRIVERTAG, PChar(sConfDir + DLL_HOOK), ALL_SESSIONS, INJECT_METRO_APPS, nil, nil); // UninjectLibraryW(BS1HOOK_DRIVERTAG, PChar(sConfDir + DLL_HOOK32), ALL_SESSIONS, INJECT_METRO_APPS, nil, nil); // UninjectAllLibrariesW(BS1HOOK_DRIVERTAG); // Sleep(3000); // Log(Format('[BS1HOOK] StopInject...1. 0', [])); // finally unload the injection driver if not StopInjectionDriver(BS1HOOK_DRIVERTAG) then _Trace('[BS1HOOK] stopping driver failed...'); // DestroyIpcQueue(PAnsiChar(BS1HOOK_IPCMESSAGE_STRING)); FreeAndNil(mtx_madCode_); end; except on E: Exception do ETgException.TraceException(Self, E, 'Fail .. Stop_madCodeHookInjection()'); end; end; procedure OffExcelDDE; var sVal: String; begin sVal := UpperCase(GetRegValueAsString(HKEY_CLASSES_ROOT, 'Excel.Sheet.12\shell\Open\command', '')); if (sVal <> '') and sVal.ToUpper.Contains('/DDE') then begin sVal := StrsReplace(sVal, ['/dde'], ''); if Pos('"%1"', sVal) = 0 then sVal := Trim(sVal) + ' "%1"'; SetRegValueString(HKEY_CLASSES_ROOT, 'Excel.Sheet.12\shell\Open\command', '', sVal); DelRegValue(HKEY_CLASSES_ROOT, 'Excel.Sheet.12\shell\Open\command', 'command'); // 삭제, ZN=BV5!!!!4!!!!MKKSKEXCELFILES>]-Z5HW$L[8QEZZR4_X=$ 요렇게 이상한값 들었음 end; sVal := UpperCase(GetRegValueAsString(HKEY_CLASSES_ROOT, 'Excel.Sheet.8\shell\Open\command', '')); if (sVal <> '') and sVal.ToUpper.Contains('/DDE') then begin sVal := StrsReplace(sVal, ['/dde'], ''); if Pos('"%1"', sVal) = 0 then sVal := Trim(sVal) + ' "%1"'; SetRegValueString(HKEY_CLASSES_ROOT, 'Excel.Sheet.8\shell\Open\command', '', sVal); DelRegValue(HKEY_CLASSES_ROOT, 'Excel.Sheet.8\shell\Open\command', 'command'); // 삭제, ZN=BV5!!!!4!!!!MKKSKEXCELFILES>]-Z5HW$L[8QEZZR4_X=$ 요렇게 이상한값 들었음 end; sVal := UpperCase(GetRegValueAsString(HKEY_CLASSES_ROOT, 'Excel.CSV\shell\Open\command', '')); if (sVal <> '') and sVal.ToUpper.Contains('/DDE') then begin sVal := StrsReplace(sVal, ['/dde'], ''); if Pos('"%1"', sVal) = 0 then sVal := Trim(sVal) + ' "%1"'; SetRegValueString(HKEY_CLASSES_ROOT, 'Excel.CSV\shell\Open\command', '', sVal); DelRegValue(HKEY_CLASSES_ROOT, 'Excel.CSV\shell\Open\command', 'command'); // 삭제, ZN=BV5!!!!4!!!!MKKSKEXCELFILES>]-Z5HW$L[8QEZZR4_X=$ 요렇게 이상한값 들었음 end; end; procedure TManagerHook.StartHookWatch; begin try if Server_ = nil then begin ClearHook; Server_ := TAppCtrlServer.Create(gMgSvc.RcvHwnd); Server_.OnSendCtrlOpt := OnSendCtrlOpt; if Server_.ActiveNp(PIPE_NAME, true) then begin Server_.ConnectNp; end; UpdateHookTarget; UpdatePreLoadInfo; OffExcelDDE; if bUse_madCodeHook_ then Start_madCodeHookInjection; ThdAppMon_ := TThdProcessWatch.Create(false); ThdAppMon_.OnProcessWatchNotify := OnAppNotify; ThdAppMon_.StartThread; ThdWndMon_ := TThdActiveWndMon.Create(false); ThdWndMon_.OnActiveWndNotify := OnWndNotify; ThdWndMon_.StartThread; // SetSharedData; end; except on E: Exception do ETgException.TraceException(Self, E, 'Fail .. StartHookWatch()'); end; end; procedure TManagerHook.ClearHook(bMore: Boolean = false); begin // try // if FileExists(sHlpExe_) then // ExecutePath_hide(sHlpExe_, '-clearhook'); // // EjectModuleFromPath(sDllPath_ + '|' + sDllPathPdf_); // if bMore then // begin // Sleep(1000); // EjectModuleFromPath(sDllPath_ + '|' + sDllPathPdf_); // end; // except // on E: Exception do // ETgException.TraceException(Self, E, 'Fail .. ClearHook()'); // end; end; procedure TManagerHook.SafeFreeClient; var nTO: Integer; NpClient: TTgNpClient; begin try if Server_ <> nil then begin if Server_.CountEnt = 0 then begin // 음... CreatePipeInstance() 이후에 한번도 연결되지 않고 파이프를 초기화 하면 // 프로그램이 크러쉬 되는 문제가 있다... // 그래서 최소 한번은 연결될 수 있도록 조치함...23_0412 16:56:56 kku Guard(NpClient, TTgNpClient.Create(PIPE_NAME)); if NpClient.Connect then begin // NpClient.Disconnect; end; end; // 안전 제거를 위해 종료를 미리 알림 23_0315 14:02:46 kku // Server_.SendPacket(TTgPacket.Create(ACC_SAFE_TERMINATE_CLIENT)); // // nTO := 0; // while (Server_.CountEnt > 0) and (nTO < 10) do // begin // Inc(nTO); // Sleep(500); // Application.ProcessMessages; // end; FreeAndNil(Server_); end; except on E: Exception do ETgException.TraceException(Self, E, 'Fail .. SafeFreeClient()'); end; end; procedure TManagerHook.StopHookWatch; var enum: TEnumerator; Send: ISendPacket; hProcess: THandle; begin try FreeMon; if bUse_madCodeHook_ then begin // if Server_ <> nil then // begin // Guard(enum, Server_.GetCMEntEnumrator); // while enum.MoveNext do // begin // Send := TTgPacket.Create(ACC_GOODBYE); // Send.Toss := enum.Current.hPipe; // Server_.SendPacket(Send); // end; // Sleep(1000); // end; Stop_madCodeHookInjection; if Server_ <> nil then FreeAndNil(Server_); end else begin ClearHook(true); end; SafeFreeClient; except on E: Exception do ETgException.TraceException(Self, E, 'Fail .. StopHookWatch()'); end; end; end.