220 lines
5.6 KiB
C++
220 lines
5.6 KiB
C++
// Bs1Drm4c.cpp : 이 파일에는 'main' 함수가 포함됩니다. 거기서 프로그램 실행이 시작되고 종료됩니다.
|
|
//
|
|
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <stdint.h>
|
|
#include <stdlib.h>
|
|
#include <time.h>
|
|
|
|
#include "aes.hpp"
|
|
|
|
#define DRM_VER 2
|
|
#define MAX_HEAD_STR 260
|
|
#define PASS_DRM_HEAD "#df12mf8(zfq@"
|
|
#define PASS_DRM_DATA "M}[8k(Ga1/<;LE1j&q"
|
|
#define SIG_DRM "ToCSG"
|
|
|
|
#define UNIX_EPOCH 25569.0 // Unix Epoch (1970년 1월 1일)을 Julian Date 기준으로 계산한 값
|
|
#define SECONDS_IN_A_DAY 86400.0 // 하루에 포함된 초의 수
|
|
|
|
#pragma pack(push, 1)
|
|
typedef struct {
|
|
uint16_t wVer;
|
|
uint32_t dwCustomerCode;
|
|
char sEmpNo[MAX_HEAD_STR];
|
|
char sHostName[MAX_HEAD_STR];
|
|
char sPartName[MAX_HEAD_STR];
|
|
char sPgName[MAX_HEAD_STR];
|
|
char sReserve1[MAX_HEAD_STR];
|
|
char sReserve2[MAX_HEAD_STR];
|
|
double dtEnc;
|
|
//uint64_t dtEnc;
|
|
} TTgDrmHead; // size = 1574
|
|
#pragma pack(pop)
|
|
|
|
int StrKeyToBitPadding(const char* sKey, uint8_t** aBuf)
|
|
{
|
|
int nResult = 0;
|
|
int nBit = 256;
|
|
char cFillChar = '*';
|
|
|
|
*aBuf = (uint8_t*)malloc(nBit);
|
|
if (*aBuf == NULL)
|
|
return nResult;
|
|
|
|
memset(*aBuf, cFillChar, nBit);
|
|
|
|
int nKeyLen = strlen(sKey);
|
|
if (nKeyLen > nBit) {
|
|
memcpy(*aBuf, sKey, nBit);
|
|
}
|
|
else {
|
|
memcpy(*aBuf, sKey, nKeyLen);
|
|
}
|
|
|
|
nResult = nBit * 8;
|
|
return nResult;
|
|
}
|
|
|
|
bool CheckSig(FILE* fs)
|
|
{
|
|
int nLen = strlen(SIG_DRM);
|
|
char* pBuf = (char*)malloc(nLen);
|
|
if (pBuf == NULL)
|
|
return false;
|
|
|
|
fseek(fs, 0, SEEK_SET);
|
|
if (nLen != fread(pBuf, 1, nLen, fs))
|
|
{
|
|
free(pBuf);
|
|
return false;
|
|
}
|
|
|
|
bool bResult = memcmp(pBuf, SIG_DRM, nLen) == 0;
|
|
free(pBuf);
|
|
|
|
return bResult;
|
|
}
|
|
|
|
void CutTail(char* src)
|
|
{
|
|
char* pos = strstr(src, "§+");
|
|
if (pos == NULL)
|
|
{
|
|
pos = strstr(src, "짠+");
|
|
if (pos == NULL)
|
|
return;
|
|
}
|
|
|
|
int nPos = pos - src;
|
|
src[nPos] = '\0';
|
|
}
|
|
|
|
time_t DelphiDateTimeToUnixTimestamp(double dt)
|
|
{
|
|
return (time_t)((dt - UNIX_EPOCH) * SECONDS_IN_A_DAY);
|
|
}
|
|
|
|
bool ExtrHead(FILE* fs, TTgDrmHead* aHead)
|
|
{
|
|
int nLen = sizeof(TTgDrmHead); // 1574
|
|
//int nEncLen = nLen - (nLen % 16) - 16;
|
|
//int nDum = nLen - nEncLen;
|
|
/*if (nLen % 16)
|
|
nLen += 16 - (nLen % 16);*/
|
|
|
|
uint8_t* pBuf = (uint8_t*)malloc(nLen);
|
|
if (pBuf == NULL)
|
|
return false;
|
|
memset(pBuf, 0, sizeof(nLen));
|
|
|
|
if (nLen != fread(pBuf, 1, nLen, fs))
|
|
{
|
|
free(pBuf);
|
|
return false;
|
|
}
|
|
|
|
uint8_t* pKey = NULL;
|
|
if (0 == StrKeyToBitPadding(PASS_DRM_HEAD, &pKey))
|
|
{
|
|
free(pBuf);
|
|
return false;
|
|
}
|
|
|
|
uint8_t IV[AES_BLOCKLEN];
|
|
memcpy(IV, pKey, AES_BLOCKLEN);
|
|
|
|
AES_ctx ctx;
|
|
memset(&ctx, 0, sizeof(ctx));
|
|
AES_init_ctx_iv(&ctx, pKey, IV);
|
|
//AES_init_ctx(&ctx, pKey);
|
|
|
|
AES_CBC_decrypt_buffer(&ctx, pBuf, nLen);
|
|
//if (nDum > 0)
|
|
//{
|
|
// if (nDum != fread(&pBuf[nEncLen], 1, nDum, fs))
|
|
// {
|
|
// free(pBuf);
|
|
// return false;
|
|
// }
|
|
//}
|
|
|
|
memcpy(aHead, pBuf, nLen);
|
|
CutTail(aHead->sEmpNo);
|
|
CutTail(aHead->sHostName);
|
|
CutTail(aHead->sPartName);
|
|
CutTail(aHead->sPgName);
|
|
|
|
FILE* ff = NULL;
|
|
fopen_s(&ff, "C:\\taskToCSG\\eCrmHE\\Utils\\EXE_Bs1Drm4c\\x64\\Debug\\test.dat", "wb");
|
|
fwrite(pBuf, 1, nLen, ff);
|
|
fclose(ff);
|
|
|
|
free(pBuf);
|
|
|
|
return true;
|
|
}
|
|
|
|
int main(int argc, char* argv[])
|
|
{
|
|
//printf("msg - %s, size - %d", argv[0], sizeof(uint16_t));
|
|
|
|
FILE* fs = NULL;
|
|
//char* path = argv[1];
|
|
char sPath[] = "C:\\taskToCSG\\eCrmHE\\Utils\\EXE_Bs1Drm4c\\x64\\Debug\\워터마크 샘플_enc.pdf"; // argv[1];
|
|
|
|
try
|
|
{
|
|
if (0 != fopen_s(&fs, sPath, "rb"))
|
|
{
|
|
printf("Fail .. FileOpen(), Path = %s\n", sPath);
|
|
return 1;
|
|
}
|
|
|
|
if (false == CheckSig(fs))
|
|
{
|
|
fclose(fs);
|
|
printf("Fail .. CheckSig(), Path = %s\n", sPath);
|
|
return 1;
|
|
}
|
|
|
|
TTgDrmHead head;
|
|
memset(&head, 0, sizeof(head));
|
|
if (false == ExtrHead(fs, &head))
|
|
{
|
|
fclose(fs);
|
|
printf("Fail .. ExtrHead(), Path = %s\n", sPath);
|
|
return 1;
|
|
}
|
|
|
|
printf("Ver = %d, HostName = %s\n", head.wVer, head.sHostName);
|
|
|
|
//time_t unixTimestamp = DelphiDateTimeToUnixTimestamp(head.dtEnc);
|
|
//struct tm ts;
|
|
//gmtime_s(&ts, &unixTimestamp);
|
|
////if (0 == gmtime_s(&ts, &unixTimestamp))
|
|
////{
|
|
// char buffer[80];
|
|
// strftime(buffer, sizeof(buffer), "%Y-%m-%d %H:%M:%S", &ts);
|
|
// printf("Date and Time: %s\n", buffer);
|
|
////}
|
|
|
|
fclose(fs);
|
|
}
|
|
catch (const char* e) {
|
|
printf("Exception: %s\n", e);
|
|
}
|
|
}
|
|
|
|
// 프로그램 실행: <Ctrl+F5> 또는 [디버그] > [디버깅하지 않고 시작] 메뉴
|
|
// 프로그램 디버그: <F5> 키 또는 [디버그] > [디버깅 시작] 메뉴
|
|
|
|
// 시작을 위한 팁:
|
|
// 1. [솔루션 탐색기] 창을 사용하여 파일을 추가/관리합니다.
|
|
// 2. [팀 탐색기] 창을 사용하여 소스 제어에 연결합니다.
|
|
// 3. [출력] 창을 사용하여 빌드 출력 및 기타 메시지를 확인합니다.
|
|
// 4. [오류 목록] 창을 사용하여 오류를 봅니다.
|
|
// 5. [프로젝트] > [새 항목 추가]로 이동하여 새 코드 파일을 만들거나, [프로젝트] > [기존 항목 추가]로 이동하여 기존 코드 파일을 프로젝트에 추가합니다.
|
|
// 6. 나중에 이 프로젝트를 다시 열려면 [파일] > [열기] > [프로젝트]로 이동하고 .sln 파일을 선택합니다.
|