unit ProcessSoftcampDRM; interface uses Winapi.Windows; const {$IFDEF WIN64} DLL_SCDRM_DSCSLINK = 'DSCSLink64.dll'; DLL_SCDRM_DSCAN = 'DSScan64.dll'; DIR_SC = 'Softcamp\SDS\x64\'; {$ELSE} DLL_SCDRM_DSCSLINK = 'DSCSLink.dll'; DLL_SCDRM_DSCAN = 'DSScan.dll'; DIR_SC = 'Softcamp\SDS\'; {$ENDIF} SIGN_SOFTCAMP_DRM: array [0..6] of Byte = ($53, $43, $44, $53, $41, $30, $30); // SCDSA00 시작됨 // 수정 25_0219 11:13:51 kku // $53, $43, $44, $53, $41, $30, $30, $34, $00, $00, $52, $00, $20, $88); // SCDSA00 시작됨 // 수정 23_1221 11:02:43 kku // ($53, $43, $44, $53, $41, $30, $30, $34, $00, $00, $52, $00, $20, $88, $F1, $53); // SCDSA004 시작됨 SCDRM_STATE_NOAGENT = 0; SCDRM_STATE_LOGOFF = 1; SCDRM_STATE_LOGON = 2; type // DSCSLink.dll TDSCheckDSAgent = function: Integer; cdecl; TDSCSForceDecryptFile = function(sSrcPath, sDestPath: PAnsiChar) : Integer; cdecl; TDSCSDecryptFile = function(sSrcPath, sDestPath: PAnsiChar) : Integer; cdecl; TDSCSDacEncryptFileV2 = function(sSrcPath: PWideChar): Integer; cdecl; TDSCSGradeEncryptFile = function(sSrcPath, sGradeId: PAnsiChar): Integer; cdecl; TDSCSIsEncryptedFile = function(sPath: PAnsiChar) : Integer; cdecl; TDSCSSetAcl = procedure(hWndServer: HWND; sCateId, sAcl: PAnsiChar; nForceEncMode: Integer); cdecl; TDSCSGetGradeID = function(sSrcPath, sGradeId: PAnsiChar): Integer; cdecl; TDSCSInstall = procedure; cdecl; TDSCSRelease = procedure; cdecl; TDSCSAppliedGetAcl = function(nAclIndex: Integer): Integer; cdecl; function DSCheckDSAgent: Integer; function DSCSForceDecryptFile(sSrcPath, sDestPath: AnsiString): Integer; function DSCSDecryptFile(sSrcPath, sDestPath: AnsiString): Integer; function DSCSGradeEncryptFile(sSrcPath, sGradeId: AnsiString): Integer; function DSCSDacEncryptFileV2(sSrcPath: WideString): Integer; function DSCSIsEncryptedFile(sPath: AnsiString) : Integer; procedure DSCSSetAcl(hWndServer: HWND; sCateId, sAcl: AnsiString; nForceEncMode: Integer); function DSCSGetGradeID(sSrcPath: AnsiString; sGradeId: PAnsiChar): Integer; procedure DSCSInstall; procedure DSCSRelease; function DSCSAppliedGetAcl(nAclIndex: Integer): Integer; type // DSScan.dll TDS_IsEncrypted = function(sSrcPath: PWideChar): Boolean; cdecl; TDS_DecryptFile = function(sSrcpath: PWideChar): THandle; cdecl; TDS_GetDecryptedFileName = function(hFile: THandle; sDecPath: PWideChar; nPathSize: UINT): DWORD; cdecl; TDS_Finalize = function(hFile: THandle; bCured: Boolean): DWORD; cdecl; TDS_IsLogin = function: Boolean; cdecl; // DSScan.dll function ExistsSoftCampScanModule: Boolean; // 다른 DRM 유무 확인 명령과 이름을 맞추기 위해 이렇게 추가 14_0617 09:37:00 sunk function DS_IsEncrypted(sSrcPath: WideString): Boolean; function DS_IsLoadDLL: Boolean; function DS_DecryptFile(sSrcpath: WideString): THandle; //function DS_GetDecryptedFileName(hFile: THandle; sDecPath: WideString; nPathSize: UINT): DWORD; function DS_GetDecryptedFileName(hFile: THandle; sDecPath: PWideChar; nPathSize: UINT): DWORD; function DS_Finalize(hFile: THandle; bCured: Boolean): DWORD; function DS_IsLogin: Boolean; implementation uses System.SysUtils, Tocsg.Path; // DSScan.dll ------------------------------------------------------------------ var hScDrm_CSLink: THandle = 0; _fnDSCheckDSAgent: TDSCheckDSAgent = nil; _fnDSCSForceDecryptFile: TDSCSForceDecryptFile = nil; _fnDSCSDecryptFile: TDSCSDecryptFile = nil; _fnDSCSGradeEncryptFile: TDSCSGradeEncryptFile = nil; _fnDSCSDacEncryptFileV2: TDSCSDacEncryptFileV2 = nil; _fnDSCSIsEncryptedFile: TDSCSIsEncryptedFile = nil; _fnDSCSSetAcl: TDSCSSetAcl = nil; _fnDSCSGetGradeID: TDSCSGetGradeID = nil; _fnDSCSInstall: TDSCSInstall = nil; _fnDSCSRelease: TDSCSRelease = nil; _fnDSCSAppliedGetAcl: TDSCSAppliedGetAcl = nil; function InitScDRM_CSLink_Procedure: Boolean; var sPath: String; begin if hScDrm_CSLink = 0 then begin sPath := GetRunExePathDir + DLL_SCDRM_DSCSLINK; if not FileExists(sPath) then sPath := GetWindowsDir + DLL_SCDRM_DSCSLINK; // for HEC if not FileExists(sPath) then sPath := GetRunExePathDir + DLL_SCDRM_DSCSLINK; hScDrm_CSLink := LoadLibrary(PChar(sPath)); if hScDrm_CSLink <> 0 then begin @_fnDSCheckDSAgent := GetProcAddress(hScDrm_CSLink, 'DSCheckDSAgent'); @_fnDSCSForceDecryptFile := GetProcAddress(hScDrm_CSLink, 'DSCSForceDecryptFile'); @_fnDSCSDecryptFile := GetProcAddress(hScDrm_CSLink, 'DSCSDecryptFile'); @_fnDSCSDacEncryptFileV2 := GetProcAddress(hScDrm_CSLink, 'DSCSDacEncryptFileV2'); @_fnDSCSIsEncryptedFile := GetProcAddress(hScDrm_CSLink, 'DSCSIsEncryptedFile'); @_fnDSCSSetAcl := GetProcAddress(hScDrm_CSLink, 'DSCSSetAcl'); @_fnDSCSGetGradeID := GetProcAddress(hScDrm_CSLink, 'DSCSGetGradeID'); @_fnDSCSInstall := GetProcAddress(hScDrm_CSLink, 'DSCSInstall'); @_fnDSCSRelease := GetProcAddress(hScDrm_CSLink, 'DSCSRelease'); @_fnDSCSAppliedGetAcl := GetProcAddress(hScDrm_CSLink, 'DSCSAppliedGetAcl'); end; end; Result := hScDrm_CSLink <> 0; end; // DS Client Agent 실행 유,무 및 로그인 유.무 체크 함수 // 0: DS Client Agent가 실행 되지 않은 상태 // 1: DS Client Agent 실행 상태이며 로그아웃 상태 // 2: DS Client Agent 실행 상태이며 로그인 상태 function DSCheckDSAgent: Integer; begin Result := 0; if InitScDRM_CSLink_Procedure and Assigned(_fnDSCheckDSAgent) then Result := _fnDSCheckDSAgent; end; // 로컬 시스템에 있는 파일을 강제적으로 복호화 API (외부 반출용) // 0: 복호화 실패 // 1: 복호화 성공 // 3: 문서보안 클라이언트 아웃 상태 function DSCSForceDecryptFile(sSrcPath, sDestPath: AnsiString) : Integer; begin Result := 0; if InitScDRM_CSLink_Procedure and Assigned(_fnDSCSForceDecryptFile) then Result := _fnDSCSForceDecryptFile(PAnsiChar(sSrcPath), PAnsiChar(sDestPath)); end; // 0: 복호화 실패 1: 복호화 성공 3: 문서보안 로그아웃 상태이거나 실행되지 않은 상태 4: Parameter Error function DSCSDecryptFile(sSrcPath, sDestPath: AnsiString) : Integer; begin Result := 0; if InitScDRM_CSLink_Procedure and Assigned(_fnDSCSDecryptFile) then Result := _fnDSCSDecryptFile(PAnsiChar(sSrcPath), PAnsiChar(sDestPath)); end; // 0: 암호화 실패, 1: 암호화 성공, 2: 지원하지 않는 확장자, 3: 문서보안 클라이언트 아웃 상태 function DSCSGradeEncryptFile(sSrcPath, sGradeId: AnsiString): Integer; begin Result := 0; if InitScDRM_CSLink_Procedure and Assigned(_fnDSCSGradeEncryptFile) then Result := _fnDSCSGradeEncryptFile(PAnsiChar(sSrcPath), PAnsiChar(sGradeId)); end; // 0: 암호화 실패, 1: 암호화 성공, 2: 지원하지 않는 확장자, 3: 문서보안 클라이언트 아웃 상태 function DSCSDacEncryptFileV2(sSrcPath: WideString): Integer; begin Result := 0; if InitScDRM_CSLink_Procedure and Assigned(_fnDSCSDacEncryptFileV2) then Result := _fnDSCSDacEncryptFileV2(PWideChar(sSrcPath)); end; // 파라미터 값으로 전달한 파일명에 대하여 암호화된 문서인지 체크하는 함수 // -1: C/S 연동 모듈 로드 실패 // 0: 일반 문서 // 1: 암호화된 문서 function DSCSIsEncryptedFile(sPath: AnsiString): Integer; begin Result := -1; if InitScDRM_CSLink_Procedure and Assigned(_fnDSCSIsEncryptedFile) then Result := _fnDSCSIsEncryptedFile(PAnsiChar(sPath)); end; // 권한 적용 API // hWndServer : DLL 로드 한 프로세스 윈도우 핸들 // sCateId : 시스템 보안에 대한 권한 참조 범주 아이디 // sAcl : 시스템 보안에 대한 강제 권한 적용 "0000" 포맷의 4비트 사용 1bit – 편집, 2bit – 캡쳐, 3bit – 인쇄, 4bit – 마킹 // nForceEncMode : 시스템에서 다운로드 하는 파일에 대하여 암호화 수행 방식 (1 – 전체그룹으로 암호화, 0 – 범주로 암호화 procedure DSCSSetAcl(hWndServer: HWND; sCateId, sAcl: AnsiString; nForceEncMode: Integer); begin if InitScDRM_CSLink_Procedure and Assigned(_fnDSCSSetAcl) then _fnDSCSSetAcl(hWndServer, PAnsiChar(sCateId), PAnsiChar(sAcl), nForceEncMode); end; // 첫 번째 파라미터의 파일(Full path)의 등급 아이디를 두 번째 파라미터 버퍼에 저장 // 0: 실패 1: 성공 3: 문서보안 로그아웃 상태이거나 실행되지 않은 상태 function DSCSGetGradeID(sSrcPath: AnsiString; sGradeId: PAnsiChar): Integer; begin Result := 0; if InitScDRM_CSLink_Procedure and Assigned(_fnDSCSGetGradeID) then Result := _fnDSCSGetGradeID(PAnsiChar(sSrcPath), sGradeId); end; // CS 연동 시작(해당 프로세스에 대하여 Hooking Start) procedure DSCSInstall; begin if InitScDRM_CSLink_Procedure and Assigned(_fnDSCSInstall) then _fnDSCSInstall; end; // CS 연동 해제 // DSCSRelease API사용 후 다시 권한제어를 위해서는 DSCSSecuArea, CSSetAcl API를 다시 호출해야함 procedure DSCSRelease; begin if InitScDRM_CSLink_Procedure and Assigned(_fnDSCSRelease) then _fnDSCSRelease; end; function DSCSAppliedGetAcl(nAclIndex: Integer): Integer; begin Result := -1; if InitScDRM_CSLink_Procedure and Assigned(_fnDSCSAppliedGetAcl) then Result := _fnDSCSAppliedGetAcl(nAclIndex); end; // DSScan.dll ------------------------------------------------------------------ var hScDrm_Scan: THandle = 0; _fnDS_IsEncrypted: TDS_IsEncrypted; _fnDS_DecryptFile: TDS_DecryptFile; _fnDS_GetDecryptedFileName: TDS_GetDecryptedFileName; _fnDS_Finalize: TDS_Finalize; _fnDS_IsLogin: TDS_IsLogin; function InitScDRM_Scan_Procedure: Boolean; var sWinDir, sPath: String; begin if hScDrm_Scan = 0 then begin sWinDir := GetWindowsDir; sPath := sWinDir + DIR_SC + DLL_SCDRM_DSCAN; if not FileExists(sPath) then begin sPath := sWinDir + DLL_SCDRM_DSCAN; if not FileExists(sPath) then sPath := GetRunExePathDir + DLL_SCDRM_DSCAN; end; hScDrm_Scan := LoadLibrary(PChar(sPath)); if hScDrm_Scan <> 0 then begin @_fnDS_IsEncrypted := GetProcAddress(hScDrm_Scan, 'DS_IsEncrypted'); @_fnDS_DecryptFile := GetProcAddress(hScDrm_Scan, 'DS_DecryptFile'); @_fnDS_GetDecryptedFileName := GetProcAddress(hScDrm_Scan, 'DS_GetDecryptedFileName'); @_fnDS_Finalize := GetProcAddress(hScDrm_Scan, 'DS_Finalize'); @_fnDS_IsLogin := GetProcAddress(hScDrm_Scan, 'DS_IsLogin'); end; end; Result := hScDrm_Scan <> 0; end; function ExistsSoftCampScanModule: Boolean; begin Result := InitScDRM_Scan_Procedure; end; // 파일이 암호화된 파일인지 검사 function DS_IsEncrypted(sSrcPath: WideString): Boolean; begin Result := false; if InitScDRM_Scan_Procedure and Assigned(_fnDS_IsEncrypted) then Result := _fnDS_IsEncrypted(PWideChar(sSrcPath)); end; function DS_IsLoadDLL: Boolean; begin Result := InitScDRM_Scan_Procedure and Assigned(_fnDS_IsEncrypted); end; // 파일을 복호화한다 // 성공할 경우 NULL이 아닌값을 리턴 (파일 핸들), 실패 시 0 function DS_DecryptFile(sSrcpath: WideString): THandle; begin Result := 0; if InitScDRM_Scan_Procedure and Assigned(_fnDS_DecryptFile) then Result := _fnDS_DecryptFile(PWideChar(sSrcPath)); end; // 복호화된 파일패스를 받는다. // Path를 Copy하는데 필요한 크기를 리턴, 에러인 경우 0을 리턴 //function DS_GetDecryptedFileName(hFile: THandle; sDecPath: WideString; nPathSize: UINT): DWORD; function DS_GetDecryptedFileName(hFile: THandle; sDecPath: PWideChar; nPathSize: UINT): DWORD; begin Result := 0; if InitScDRM_Scan_Procedure and Assigned(_fnDS_GetDecryptedFileName) then Result := _fnDS_GetDecryptedFileName(hFile, sDecPath, nPathSize); // Result := _fnDS_GetDecryptedFileName(hFile, PWideChar(sDecPath), nPathSize); end; // 모든 작업을 종료하며 h가 무효화 된다. 할당했던 메모리 해제, 임시로 생성했던 파일삭제 // 성공할 경우 ERROR_SUCCESS를 리턴 function DS_Finalize(hFile: THandle; bCured: Boolean): DWORD; begin Result := 1; if InitScDRM_Scan_Procedure and Assigned(_fnDS_Finalize) then Result := _fnDS_Finalize(hFile, bCured); end; // 문서보안 로그인이 되어있는지 확인 function DS_IsLogin: Boolean; begin Result := false; if InitScDRM_Scan_Procedure and Assigned(_fnDS_IsLogin) then Result := _fnDS_IsLogin; end; end.