{*******************************************************} { } { CrmUtil } { } { Copyright (C) 2022 kku } { } {*******************************************************} unit CrmUtil; interface uses IdHTTP, System.Classes, Winapi.Windows; function GetRandomString(nLen: Integer): String; function GetADUserName: String; function GetUserNameFromExplorer: String; function VerifyEmpNo(sSvrUrl: String; aHTTP: TIdHTTP; sEmpNo: String): Boolean; function GetEmpNoInfo(sSvrUrl: String; aHTTP: TIdHTTP; sEmpNo: String): String; function GetQuarantineInfo(sSvrUrl: String; aHTTP: TIdHTTP; sHostInfo: String): String; function ExtrTextFromImage(sImgPath: String; aAngle: Extended = 0): String; function SendData(h: HWND; dwCmd: DWORD; const sData: String): LONGLONG; // KBIZ에서 엑셀이 한번에 재대로 실행 안되는 현상이 있어서 작성 procedure ExcelCheckAndHideRun(sUserSid: String); implementation uses Tocsg.Registry, System.SysUtils, Tocsg.Exception, Tocsg.Process, Condition, Tocsg.Trace, Tocsg.WTS, Tocsg.Safe, Tocsg.Path, GlobalDefine, Tocsg.WinInfo, IdMultipartFormData, superobject, Tocsg.Files, Tocsg.Shell, Tocsg.Graphic, Winapi.Messages, DefineHelper, Tocsg.Strings; var _DoGetInfoCount: Integer = 0; function GetRandomString(nLen: Integer): String; const arrRanChar: array [0..13] of Char = ('a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'x', 't', 'z', 'u', 'l', 'k'); var i: Integer; begin Result := ''; if nLen = 0 then Randomize; for i := 1 to nLen do Result := Result + arrRanChar[Random(13)]; end; function GetADUserName: String; var sAdHostName: String; begin Result := ''; // AD 환경에서 호스트명(컴퓨터 이름)을 다르게 가져오도록 보완 (김경덕프로 요청, 다이이찌산쿄) 22_0629 09:37:23 kku // 주의 : 비밀번호 취약상태 점검때는 사용하면 안된다. 이렇게 하면 로그온정보 제대로 가져올 수 없음 sAdHostName := GetRegValueAsString(HKEY_LOCAL_MACHINE, 'SOFTWARE\Microsoft\Windows\CurrentVersion\Group Policy\DataStore\Machine\0', 'szTargetName'); // 보완 24_0108 12:57:40 kku if sAdHostName = '' then sAdHostName := GetRegValueAsString(HKEY_LOCAL_MACHINE, 'SYSTEM\CurrentControlSet\Control\ComputerName\ActiveComputerName', 'ComputerName'); if sAdHostName <> '' then begin var sUser: String := ''; var sRegKey: String := GetRegRecentUserSid; if sRegKey <> '' then begin sUser := Trim(GetRegValueAsString(HKEY_USERS, sRegKey + '\Volatile Environment', 'USERNAME')); if sUser = '' then sUser := GetUserNameFromReg(sRegKey); if sUser = '' then TTgTrace.T('RecentUserSid = %s', [sRegKey]); end else TTgTrace.T('Fail .. GetADUserName()'); if sUser = '' then begin sUser := WTS_GetCurrentUserName; // 패스워드 취약점검 안하면 사용자 계정 상관없어서 이렇게 처리 22_0705 14:38:37 kku if sUser = '' then TTgTrace.T('Fail?? WTS_GetCurrentUserName()'); // AD 환경에서 실패하는것을 확인함. 다시 실행하면 되는 경우 있음 22_0721 15:43:52 kku end; Result := sAdHostName + '\' + sUser; exit; end; end; function GetUserNameFromExplorer: String; var PList: TProcessEntList; pEnt: PProcessEntInfo; PidList: TProcessIdList; i: Integer; begin if IsUseLocalHostName then begin // 로컬 호스트네임으로 가져오도록 고정 24_0321 10:04:54 kku var sCom: String := GetRegValueAsString(HKEY_LOCAL_MACHINE, 'SYSTEM\ControlSet001\Control\ComputerName\ComputerName', 'ComputerName'); var sUser: String := GetRegValueAsString(HKEY_USERS, GetRegRecentUserSid + '\Volatile Environment', 'USERNAME'); // 카스퍼스키 계정 프록시? 기능 때문에 제대로 계정 정보를 가져올수 없다... // GetUserNameFromReg() 로도 계정 권한이 "%SystemRoot%\ServiceProfiles\ksnproxy" 로 확인됨 24_0327 15:47:43 kku if sUser = '' then sUser := WTS_GetCurrentUserName; if (sCom <> '') and (sUser <> '') then begin Result := sCom + '\' + sUser; exit; end; end; if IsUseActiveDirectory then // and IsSkipPwd then begin Result := GetADUserName; if Result <> '' then exit; end; Result := GetDomainUserNameFromReg; if Result <> '' then exit; try Guard(PidList, TProcessIdList.Create); if GetProcessPidsByName('explorer.exe', PidList) > 0 then begin Guard(PList, TProcessEntList.Create); PList.UpdateProcessList; for i := 0 to PidList.Count - 1 do begin pEnt := PList.GetProcInfoByPid(PidList[i]); if pEnt <> nil then begin Result := Trim(pEnt.sOwner); if Result = '\\\' then Result := ''; if Result <> '' then begin DeleteFile(PChar(GetRunExePathDir + LOG_RESTART)); exit; end; end; end; end; if Result = '' then begin var sPath: String := GetRunExePathDir + LOG_RESTART; if FileExists(sPath) then begin // 다시 시작했는데도 안되면.. 그냥 일반적으로 구해준다. 22_0613 08:16:07 kku DeleteFile(PChar(sPath)); Result := GetComName + '\' + WTS_GetCurrentUserName; TTgTrace.T('Fail .. GetUserNameFromExplorer(), Restart.. UserName="%s"', [Result]); end else begin Inc(_DoGetInfoCount); TTgTrace.T('Fail .. GetUserNameFromExplorer(), TryCount=%d', [_DoGetInfoCount]); if _DoGetInfoCount > 5 then begin var sName: String := GetUserNameFromReg; if sName = '' then begin TTgTrace.T('Fail .. GetUserNameFromExplorer(), Terminate..'); WriteLnFileEndUTF8(sPath, Format('[%s] Fail .. GetUserNameFromExplorer()', [DateTimeToStr(Now)])); TerminateProcess(GetCurrentProcess, 900); end else Result := GetComName + '\' + sName; end; end; end; except on E: Exception do begin Result := GetComName + '\' + WTS_GetCurrentUserName; ETgException.TraceException(E, 'Fail .. GetUserNameFromExplorer()'); end; end; end; function VerifyEmpNo(sSvrUrl: String; aHTTP: TIdHTTP; sEmpNo: String): Boolean; var ss: TStringStream; nOldTM1, nOldTM2: Integer; O: ISuperObject; begin Result := false; try if CUSTOMER_TYPE = CUSTOMER_CNSCERT then begin // CNSCERT는 인사연동을 하지 않기 때문에 사번 패턴만 검증함 22_0711 16:14:43 kku Result := IsCheckEmpNoCNSCERT(sEmpNo); exit; end; nOldTM1 := aHTTP.ReadTimeout; nOldTM2 := aHTTP.ConnectTimeout; try // sSvrUrl := StringReplace(sSvrUrl, 'agentLogRequests.do', 'agentEmpNoChecks.do', [rfReplaceAll]); // sSvrUrl := StringReplace(sSvrUrl, 'agentLogRequest.do', 'agentEmpNoCheck.do', [rfReplaceAll]); sSvrUrl := StringReplace(sSvrUrl, 'agentLogRequests.do', 'agentEmpInfo.do', [rfReplaceAll]); sSvrUrl := StringReplace(sSvrUrl, 'agentLogRequest.do', 'agentEmpInfos.do', [rfReplaceAll]); Guard(ss, TStringStream.Create('{\"Request : HeartBeat\"}', TEncoding.UTF8)); aHTTP.Request.ContentType := 'application/json; charset=utf-8'; aHTTP.Request.CustomHeaders.Clear; // 메인에서 DRM 처리도 같이 해주고 있기 때문에 초기화 해줘야 한다 22_0602 08:25:35 kku aHTTP.Request.CustomHeaders.Values['requestType'] := sEmpNo; // Result := aHTTP.Post(sSvrUrl, ss) = 'true'; O := SO(aHTTP.Post(sSvrUrl, ss)); Result := O.S['result'] = 'true'; finally aHTTP.ReadTimeout := nOldTM1; aHTTP.ConnectTimeout := nOldTM2; end; except {$IFDEF TRACE1} on E: Exception do ETgException.TraceException(Self, E, Format('Fail .. VerifyEmpNo(), RqType=%s', [sRqType])); {$ENDIF} end; end; function GetEmpNoInfo(sSvrUrl: String; aHTTP: TIdHTTP; sEmpNo: String): String; var ss: TStringStream; nOldTM1, nOldTM2: Integer; begin Result := ''; try nOldTM1 := aHTTP.ReadTimeout; nOldTM2 := aHTTP.ConnectTimeout; try if CUSTOMER_TYPE = CUSTOMER_CNSCERT then begin // CNSCERT는 인사연동을 하지 않기 때문에 사번 패턴만 검증함 22_0711 16:14:43 kku if IsCheckEmpNoCNSCERT(sEmpNo) then Result := 'true'; exit; end; if Pos('agentLogRequests.do', sSvrUrl) = 0 then begin sSvrUrl := sSvrUrl + 'agentEmpInfo.do'; end else begin sSvrUrl := StringReplace(sSvrUrl, 'agentLogRequests.do', 'agentEmpInfo.do', [rfReplaceAll]); sSvrUrl := StringReplace(sSvrUrl, 'agentLogRequest.do', 'agentEmpInfos.do', [rfReplaceAll]); end; Guard(ss, TStringStream.Create('{\"Request : HeartBeat\"}', TEncoding.UTF8)); aHTTP.Request.ContentType := 'application/json; charset=utf-8'; aHTTP.Request.CustomHeaders.Clear; // 메인에서 DRM 처리도 같이 해주고 있기 때문에 초기화 해줘야 한다 22_0602 08:25:35 kku aHTTP.Request.CustomHeaders.Values['requestType'] := sEmpNo; Result := aHTTP.Post(sSvrUrl, ss); finally aHTTP.ReadTimeout := nOldTM1; aHTTP.ConnectTimeout := nOldTM2; end; except // on E: Exception do // raise Exception.Create(E.Message); {$IFDEF TRACE1} on E: Exception do ETgException.TraceException(Self, E, Format('Fail .. GetEmpNoInfo(), RqType=%s', [sRqType])); {$ENDIF} end; end; function GetQuarantineInfo(sSvrUrl: String; aHTTP: TIdHTTP; sHostInfo: String): String; var ss: TStringStream; nOldTM1, nOldTM2: Integer; begin Result := ''; try nOldTM1 := aHTTP.ReadTimeout; nOldTM2 := aHTTP.ConnectTimeout; try sSvrUrl := StringReplace(sSvrUrl, 'agentLogRequests.do', 'getQuarantineFileInfo.do', [rfReplaceAll]); sSvrUrl := StringReplace(sSvrUrl, 'agentLogRequest.do', 'getQuarantineFileInfo.do', [rfReplaceAll]); Guard(ss, TStringStream.Create('{\"Request : HeartBeat\"}', TEncoding.UTF8)); // Guard(ss, TStringStream.Create(sEmpNo, TEncoding.UTF8)); aHTTP.Request.ContentType := 'application/json; charset=utf-8'; aHTTP.Request.CustomHeaders.Clear; // 메인에서 DRM 처리도 같이 해주고 있기 때문에 초기화 해줘야 한다 22_0602 08:25:35 kku aHTTP.Request.CustomHeaders.Values['requestType'] := sHostInfo; // gMgSvc.AgentModel.AgentId; Result := aHTTP.Post(sSvrUrl, ss); finally aHTTP.ReadTimeout := nOldTM1; aHTTP.ConnectTimeout := nOldTM2; end; except // on E: Exception do // raise Exception.Create(E.Message); {$IFDEF TRACE1} on E: Exception do ETgException.TraceException(Self, E, Format('Fail .. GetQuarantineInfo(), RqType=%s', [sRqType])); {$ENDIF} end; end; function ExtrTextFromImage(sImgPath: String; aAngle: Extended = 0): String; var sOcr, sOutPath, sTempPath: String; StrList: TStringList; begin Result := ''; sTempPath := ''; sOcr := GetRunExePathDir + DIR_CONF + EXE_OCR; if not FileExists(sOcr) then sOcr := GetRunExePathDir + EXE_OCR; if FileExists(sOcr) then begin sOutPath := sOcr[1] + ':\ProgramData\HE\Task\' + ExtractFileName(sImgPath) + '.$xt'; if ForceDirectories(ExtractFilePath(sOutPath)) then begin if aAngle <> 0 then begin sTempPath := CutFileExt(sImgPath) + 'R18.png'; if RotatePngFile(sImgPath, sTempPath, aAngle) then sImgPath := sTempPath; end; try ExecuteAppWaitUntilTerminate(sOcr, Format('"%s" "%s"', [sImgPath, sOutPath]), SW_HIDE); finally if sTempPath <> '' then DeleteFile(sTempPath); end; if FileExists(sOutPath) then begin Result := ExtractTextSafe(sOutPath); DeleteFile(sOutPath); end; end; end; end; function SendData(h: HWND; dwCmd: DWORD; const sData: String): LONGLONG; var CopyData: TCopyDataStruct; begin CopyData.dwData := dwCmd; CopyData.cbData := (Length(sData) + 1) * 2; CopyData.lpData := PChar(sData); Result := SendMessage(h, WM_COPYDATA, 0, NativeInt(@CopyData)); end; procedure ExcelCheckAndHideRun(sUserSid: String); var sPath: String; begin if GetProcessPidByName('excel.exe') <> 0 then exit; sPath := '';//GetRegValueAsString(HKEY_USERS, sUserSid + '\Software\Microsoft\Windows\CurrentVersion\Extensions', 'xlsx'); if (sPath = '') or not FileExists(sPath) then begin sPath := GetRegValueAsString(HKEY_CLASSES_ROOT, 'dqyfile\DefaultIcon', ''); if sPath <> '' then begin var nPos: Integer := Pos(',', sPath); if nPos > 0 then Delete(sPath, nPos, Length(sPath) - nPos + 1); if not FileExists(sPath) then exit; end; end; {$IFDEF DEBUG} ExecutePath_hide(sPath); {$ELSE} var O: ISuperObject := SO; O.I['Cmd'] := HPCMD_EXECUTE_FILE; O.S['Path'] := sPath; O.B['Hide'] := true; SaveJsonObjToFile(O, GetRunExePathDir + DIR_CONF + DAT_PARAM); var sHlpExe: String := GetRunExePathDir + DIR_CONF + EXE_HLP; ExecuteAppAsUser('explorer.exe', sHlpExe, '', SW_HIDE); {$ENDIF} end; end.