{*******************************************************} { } { HandleSecurity } { } { Copyright (C) 2022 kku } { } {*******************************************************} unit HandleSecurity; interface uses Tocsg.Obj, System.SysUtils, System.Classes, SecureApp, Tocsg.WscApi, NetFwTypeLib_TLB; const TYPE_AV = 'AntiVirus'; TYPE_FIREWALL = 'Firewall'; TYPE_AS = 'AndtiSpyware'; // IGRNORE_AV = 'FortiClient'; type THandleSecurity = class(TTgObject) private sWinVer_: String; fwPolicy2_: INetFwPolicy2; AvList_, FwList_, AsList_: TSecureAppList; // IgrAvList_: TStringList; procedure UpdateAv(aList: TWSCProductEntList); procedure UpdateFw(aList: TWSCProductEntList); procedure UpdateAs(aList: TWSCProductEntList); public Constructor Create(sWinVer: String); Destructor Destroy; override; procedure Update(aList: TWSCProductEntList); function GetMainAv: TSecureApp; function GetMainFw: TSecureApp; function GetMainAs: TSecureApp; function HasV3: Boolean; property AvList: TSecureAppList read AvList_; property FwList: TSecureAppList read FwList_; property AsList: TSecureAppList read AsList_; end; implementation uses Tocsg.Safe, Condition, Tocsg.Strings, Tocsg.Convert, Tocsg.Exception, Tocsg.Firewall; { THandleSecurity } Constructor THandleSecurity.Create(sWinVer: String); var sIgrAv: String; begin Inherited Create; sWinVer_ := sWinVer; fwPolicy2_ := nil; // sIgrAv := IGRNORE_AV; // if IsIgnoreWinDependerAv then // SumString(sIgrAv, 'Defender', '|'); // IgrAvList_ := TStringList.Create; // SplitString(UpperCase(sIgrAv), '|', IgrAvList_); AvList_ := TSecureAppList.Create; FwList_ := TSecureAppList.Create; AsList_ := TSecureAppList.Create; AvList_.Add(TSecureApp.Create('Windows Defender', TYPE_AV, 'up-to-date', '', '', true)); FwList_.Add(TSecureApp.Create('Windows Firewall', TYPE_FIREWALL, 'up-to-date', '', '', true)); end; Destructor THandleSecurity.Destroy; begin FreeAndNil(AsList_); FreeAndNil(FwList_); FreeAndNil(AvList_); // FreeAndNil(IgrAvList_); Inherited; end; procedure THandleSecurity.Update(aList: TWSCProductEntList); begin if aList.Count = 0 then exit; case aList.Provider of WSC_SECURITY_PROVIDER_FIREWALL : UpdateFw(aList); WSC_SECURITY_PROVIDER_ANTIVIRUS : UpdateAv(aList); WSC_SECURITY_PROVIDER_ANTISPYWARE : UpdateAs(aList); end; end; procedure THandleSecurity.UpdateAv(aList: TWSCProductEntList); var sName, sStatus, sPath, sTime, sTemp: String; bState: Boolean; i, c: Integer; app: TSecureApp; begin sName := ''; sStatus := 'Out-Of-Date'; sPath := ''; sTime := ''; bState := false; try for i := 0 to aList.Count - 1 do begin sName := aList[i].sName; // FortiClient VPN이 잡히는 경우가 있다고 한다 25_0312 14:33:05 kku if (sName <> '') and sName.ToUpper.Contains('FORTICLIENT') then continue; bState := aList[i].nState = WSC_SECURITY_PRODUCT_STATE_ON; sStatus := BooleanToStr(aList[i].nStatus = WSC_SECURITY_PRODUCT_UP_TO_DATE, 'up-to-date', 'out-of-date'); sTime := aList[i].sStateTimestamp; if sName <> '' then begin if CUSTOMER_TYPE = CUSTOMER_METLIFE then begin // 메트라이프는 "CrowdStrike Falcon Sensor" 백신만 인식되도록 함 23_0213 16:17:34 kku app := TSecureApp.Create(sName, TYPE_AV, sStatus, sPath, sTime, bState); case AvList_.Count of 0 : ; 1 : if AvList_[0].Name.Contains('Defender') then AvList_.Clear; else begin for c := AvList_.Count - 1 downto 0 do begin if AvList_[c].Name = app.Name then AvList_.Delete(c); end; end; end; if app.Name.Contains('CrowdStrike') then AvList_.Add(app) else app.Free; end else if IsIgnoreWinDependerAv then begin app := TSecureApp.Create(sName, TYPE_AV, sStatus, sPath, sTime, bState); case AvList_.Count of 0 : ; 1 : if AvList_[0].Name.Contains('Defender') then AvList_.Clear; else begin for c := AvList_.Count - 1 downto 0 do begin if (AvList_[c].Name = app.Name) or (AvList_[c].Name.Contains('Defender') and app.Name.Contains('Defender')) then AvList_.Delete(c); end; end; end; if not app.Name.Contains('Defender') then AvList_.Add(app) else app.Free; end else begin app := TSecureApp.Create(sName, TYPE_AV, sStatus, sPath, sTime, bState); for c := 0 to AvList_.Count - 1 do if (AvList_[c].Name = app.Name) or (AvList_[c].Name.Contains('Defender') and app.Name.Contains('Defender')) then begin AvList_.Delete(c); break; end; AvList_.Add(app); end; end; end; except on E: Exception do ETgException.TraceException(Self, E, 'Fail .. UpdateAv()'); end; end; procedure THandleSecurity.UpdateFw(aList: TWSCProductEntList); var sName, sStatus, sPath, sTime, sTemp: String; bState: Boolean; i, c: Integer; app: TSecureApp; begin sName := ''; sStatus := 'Out-Of-Date'; sPath := ''; sTime := ''; bState := false; try for i := 0 to aList.Count - 1 do begin sName := aList[i].sName; bState := aList[i].nState = WSC_SECURITY_PRODUCT_STATE_ON; if bState and (sWinVer_ = '11') and sName.Contains('Microsoft') then begin // 윈도우 11에서 방화벽 설정 상태를 제대로 가져오지 못하는 문제가 확인됨 22_0826 13:45:00 kku if fwPolicy2_ = nil then fwPolicy2_ := CoNetFwPolicy2.Create; if fwPolicy2_ <> nil then bState := fwPolicy2_.FirewallEnabled[FW_PROFILE_PERSONAL] and fwPolicy2_.FirewallEnabled[FW_PROFILE_PUBLIC]; end; sStatus := BooleanToStr(aList[i].nStatus = WSC_SECURITY_PRODUCT_UP_TO_DATE, 'up-to-date', 'out-of-date'); sTime := aList[i].sStateTimestamp; if sName <> '' then begin app := TSecureApp.Create(sName, TYPE_FIREWALL, sStatus, sPath, sTime, bState); case FwList_.Count of 0 : ; 1 : if FwList_[0].Name.Contains('Windows Firewall') then FwList_.Clear; else begin for c := FwList_.Count - 1 downto 0 do begin if FwList_[c].Name = app.Name then begin FwList_.Delete(c); break; end; end; end; end; FwList_.Add(app); end; end; except on E: Exception do ETgException.TraceException(Self, E, 'Fail .. UpdateFw()'); end; end; procedure THandleSecurity.UpdateAs(aList: TWSCProductEntList); var sName, sStatus, sPath, sTime, sTemp: String; bState: Boolean; i, c: Integer; app: TSecureApp; begin sName := ''; sStatus := 'Out-Of-Date'; sPath := ''; sTime := ''; bState := false; try for i := 0 to aList.Count - 1 do begin sName := aList[i].sName; bState := aList[i].nState = WSC_SECURITY_PRODUCT_STATE_ON; sStatus := BooleanToStr(aList[i].nStatus = WSC_SECURITY_PRODUCT_UP_TO_DATE, 'up-to-date', 'out-of-date'); sTime := aList[i].sStateTimestamp; if sName <> '' then begin app := TSecureApp.Create(sName, TYPE_AS, sStatus, sPath, sTime, bState); case AsList_.Count of 0 : ; else begin for c := AsList_.Count - 1 downto 0 do begin if AsList_[c].Name = app.Name then begin AsList_.Delete(c); break; end; end; end; end; AsList_.Add(app); end; end; except on E: Exception do ETgException.TraceException(Self, E, 'Fail .. UpdateAs()'); end; end; function THandleSecurity.GetMainAv: TSecureApp; var i: Integer; begin Result := nil; case AvList_.Count of 0 : exit; 1 : Result := AvList_[0]; else begin // 다른 백신 활성화 값이 제대로 매치가 안되서 자꾸 Defender가 보이는 현상있음. 그래서 제외 22_0721 10:51:17 kku // step 1 : 백신 두개 이상이면 Defender는 후 순위로 가져온다 22_0707 08:45:12 kku // for i := 0 to AvList_.Count - 1 do // begin // if AvList_[i].IsState and not AvList_[i].Name.Contains('Defender') then // begin // Exit(AvList_[i]); // end; // end; // step 2 : 활성화 된 것 // for i := 0 to AvList_.Count - 1 do // begin // if AvList_[i].IsState then // begin // Exit(AvList_[i]); // end; // end; // step 3 : Defneder 아닌 것 for i := 0 to AvList_.Count - 1 do begin if not AvList_[i].Name.Contains('Defender') then begin Exit(AvList_[i]); end; end; // step 4 : 그냥 첫번째 Result := AvList_[0]; // if AvList_[0].Name.Contains('Defender') then // Exit(AvList_[0]) // else // Exit(AvList_[1]); end; end; end; function THandleSecurity.GetMainFw: TSecureApp; var i: Integer; begin Result := nil; case FwList_.Count of 0 : exit; 1 : Result := FwList_[0]; else begin for i := 0 to FwList_.Count - 1 do begin if FwList_[i].IsState then begin Exit(FwList_[i]); end; end; Result := FwList_[0]; end; end; end; function THandleSecurity.GetMainAs: TSecureApp; var i: Integer; begin Result := nil; case AsList_.Count of 0 : exit; 1 : Result := AsList_[0]; else begin for i := 0 to AsList_.Count - 1 do begin if AsList_[i].IsState then begin Exit(AsList_[i]); end; end; Result := AsList_[0]; end; end; end; function THandleSecurity.HasV3: Boolean; var i: Integer; begin try Result := false; for i := 0 to AvList_.Count - 1 do begin if Pos('V3', UpperCase(AvList_[i].Name)) > 0 then begin Result := true; exit; end; end; except on E: Exception do ETgException.TraceException(Self, E, 'Fail .. HasV3()'); end; end; end.