首页
社区
课程
招聘
[原创]国内某DRM产品的一些二次改进----告别中关村之二
2008-8-21 12:25 13783

[原创]国内某DRM产品的一些二次改进----告别中关村之二

2008-8-21 12:25
13783
1.改进了频繁打开文件造成的资源浪费
CCEBFileEngine::CCEBFileEngine(LPCTSTR pszFileName)
{
        if (!m_cebFile.Open(pszFileName, CFile::modeRead | CFile::shareDenyWrite))
                return;
        // CreateFileMapping
        m_hMapFile = CreateFileMapping((HANDLE)(m_cebFile.m_hFile),0,PAGE_WRITECOPY,0,0,NULL);
        if (m_hMapFile == NULL ||m_hMapFile == INVALID_HANDLE_VALUE)
        {
                return ;
        }
       
        m_pbFile = (LPBYTE)MapViewOfFile(m_hMapFile,FILE_MAP_COPY,0,0,0);
        if (m_pbFile == NULL)
        {
                CloseHandle(m_hMapFile);
                return ;
        }

        m_dwOriginFileSize = (DWORD)m_cebFile.GetLength();
       

        memcpy(&m_cfh,m_pbFile,sizeof(CEBFILEHEADER));
        char szCopyright[20];
        memcpy(szCopyright, m_cfh.szHeaderInfo, 11);
        szCopyright[11] = '\0';
        if (strcmp(szCopyright, CEB_FILEHEADER_COPYRIGHT) != 0)
        {
                ASSERT(FALSE);
                return;
        }
        m_strCopyright = szCopyright;

        if (m_cfh.szHeaderInfo[11] == 0 && m_cfh.szHeaderInfo[12] == 0 && m_cfh.szHeaderInfo[13] == 0)
        {
                // 表明这是CEB 3.0或更高的版本。
                m_nMajorVer = m_cfh.szHeaderInfo[CEBHEADER_MAJORVER_OFFSETPOS];
                m_nMinorVer = m_cfh.szHeaderInfo[CEBHEADER_MINORVER_OFFSETPOS];
        }
        else
        {
                // 否则为CEB 3.0以前的版本。
                char szVer[20];
                memcpy(szVer, m_cfh.szHeaderInfo, 16);
                szVer[16] = '\0';

                CString strVer = szVer;
                strVer = strVer.Right(4);
                CString strMajor = strVer.Left(1);
                CString strMinor = strVer.Right(2);
                m_nMajorVer = (BYTE)_ttoi(strMajor);
                m_nMinorVer = (BYTE)_ttoi(strMinor);

                // 这里防止一些老版本的CEB却写着3.0的版本号而导致后续的错误。
                if (m_nMajorVer >= 3)
                        m_nMajorVer = 2;
        }

        CEBINDEXITEM item;
        for (int i = 0; i < m_cfh.wIndexCount; i++)
        {
                memcpy(&item,
                        m_pbFile + sizeof(CEBFILEHEADER) + i*sizeof(CEBINDEXITEM),
                        sizeof(CEBINDEXITEM));
                m_aIndex.Add(item);
        }

        m_strFileName = pszFileName;
}

2.采用了PDFLib的dll的DLL2LIB后的静态库,整合到一个exe中,避免了发布程序的臃肿.
BOOL CEyueteuApp::InitInstance()
{
       
//         const
//                 unsigned char sSource [13] = {
//                 0x26, 0x22, 0x08, 0x77, 0x32, 0xC5, 0x00, 0x43, 0xF9, 0x74, 0x81, 0xEB, 0xB9
//         };
//         BYTE* pOutBuffer = NULL;
//         long nBufLen = 0;
//         DWORD dwRet = Base64Encode((const BYTE*)(LPCSTR)sSource, 13,0,
//                 &pOutBuffer, &nBufLen);
//         free(pOutBuffer);
       

//         SKINMAGICTRIAL_DllMain(GetModuleHandle(NULL), DLL_PROCESS_ATTACH, NULL);
//         VERIFY( 1 == InitSkinMagicLib( AfxGetInstanceHandle(), "" ,
//                         NULL,
//                         NULL ) );
//         VERIFY( 1 == LoadSkinFromResource(m_hInstance,MAKEINTRESOURCE(xpblue),_T("SKIN")));       
//     SetDialogSkin("Dialog");
        PDFLIB_DllMain(GetModuleHandle(NULL), DLL_PROCESS_ATTACH, NULL);

3.界面采用XT12.0.0的静态库,挂接一个VISTA的皮肤,同样把皮肤内嵌进exe

CEyueteuDlg::CEyueteuDlg(CWnd* pParent /*=NULL*/)
: CDialog(CEyueteuDlg::IDD, pParent)
{
    //{{AFX_DATA_INIT(CEyueteuDlg)
    m_Range = 0;
    m_Pos = 0;
    m_strJobInfo = _T("0个文件已转换/0个文件待转换");
    m_bBookName = TRUE;
    m_strSavePath = _T("");
    m_bLocal = TRUE;
    m_bNoEncrypt = FALSE;
        m_bOnline = FALSE;
        m_bBookMake = TRUE;
        m_bWater = TRUE;
        m_bDemo = FALSE;
        //}}AFX_DATA_INIT
    // Note that LoadIcon does not require a subsequent DestroyIcon in Win32
    m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
    m_pdwThreadId = NULL;
    m_phThread = NULL;
    m_arrStrFileName.RemoveAll();
    m_dwJobCount = 0;
    m_dwEndJobCount = 0;
#ifdef CEB2PDF
        // 释放为临时文件加载
        TCHAR szTempPath[_MAX_PATH];
        GetTempPath(_MAX_PATH, szTempPath);
        CString strSkinName = szTempPath;
        strSkinName += _T("\\Vista.cjstyles");
        //   Load   the   user-defined   resource.
        HMODULE m_hInstance = AfxGetApp()->m_hInstance;
        HRSRC hExeFile =   ::FindResource(m_hInstance,MAKEINTRESOURCE(VISTA),_T("SKIN"));   
        HGLOBAL hRes   =   ::LoadResource(m_hInstance,   hExeFile);   
        DWORD dwSize   =   ::SizeofResource(m_hInstance,   hExeFile);   
       
        if   (hRes != NULL)   
        {   
                UINT   FAR*   lpnRes   =   (UINT   FAR*)::LockResource(hRes);   
                CFile   file(strSkinName,   CFile::modeCreate   |   CFile::modeWrite);   
                file.WriteHuge(lpnRes,   dwSize);   
                file.Flush();   
                ::FreeResource(hRes);   
        }
        XTPSkinManager()->LoadSkin(strSkinName);
        DeleteFile(strSkinName);
#endif
}

4.采用多线程解码以及更新界面现实
void CEyueteuDlg::OnOK()
{

        VIRTUALIZER_MUTATE1_START

#ifndef CEB2PDF
        ::MessageBox(0,
                "\n\n\nDemo版本只能转换部分未加密的ceb,  .  \n\n",
                "注意",
                MB_OK|MB_ICONWARNING);
#endif
   UpdateData();
   VIRTUALIZER_END

    if (m_btnNew.GetCheck() == 1)
    {
        HANDLE hFile = NULL;
        if (m_strSavePath.IsEmpty() ||
            (hFile = CreateFile(m_strSavePath + "\\temp",
            GENERIC_WRITE,         
            FILE_SHARE_WRITE,      
            NULL,                  
            CREATE_ALWAYS,         
            FILE_ATTRIBUTE_NORMAL,
            NULL)) == INVALID_HANDLE_VALUE)
        {
            MessageBox("保存路径错误,请重新选择或者输入!","错误");
            m_strSavePath.Empty();
            m_ctlEdit.SetFocus();
            UpdateData(FALSE);
            return;
        }
        else
        {
            CloseHandle(hFile);
            DeleteFile(m_strSavePath + "\\temp");
        }
    }
   
    m_strJobInfo = _T("0个文件已转换/0个文件待转换");
    m_dwJobCount = 0;
    m_dwEndJobCount = 0;
    CString strFilter;
    strFilter.LoadString(IDS_OPENFILE_FILTER);               
    CFileDialog *dlgFileOpen = new CFileDialog(TRUE,
        _T("*.ceb"),
        NULL,
        OFN_ALLOWMULTISELECT|OFN_HIDEREADONLY|OFN_EXPLORER|OFN_FILEMUSTEXIST,
        strFilter);
   
    TCHAR *pszFileList = new TCHAR[MAXLENGTH_FILENAMEBUFFER];
    dlgFileOpen->m_ofn.lpstrFile = pszFileList;
    dlgFileOpen->m_ofn.lpstrFile[0] = _T('\0');
    dlgFileOpen->m_ofn.nMaxFile = MAXLENGTH_FILENAMEBUFFER;
    dlgFileOpen->m_ofn.lStructSize = sizeof(OPENFILENAME);
        dlgFileOpen->m_ofn.Flags |= OFN_SHOWHELP;
    if (dlgFileOpen->DoModal() == IDOK)
    {
                CString strFileName;
                POSITION posFile = dlgFileOpen->GetStartPosition();
                int nCount =0;
                m_arrStrFileName.RemoveAll();
                while (posFile)
                {
                        strFileName = dlgFileOpen->GetNextPathName(posFile);
                        m_arrStrFileName.Add(strFileName);
                        nCount++;
                }
                m_dwJobCount = nCount;
                m_dwEndJobCount = 0;
                m_pdwThreadId = new DWORD[nCount];
                m_phThread = new HANDLE[nCount];
                PTHREADARG m_pArg;
               
                for (int i = 0; i < nCount;i++)
                {
                        m_pArg = new THREADARG;
                        m_pArg->dwThreadId = i;
                        m_pArg->pThis = this;
                        m_pArg->strFileName = m_arrStrFileName[i];
                        m_phThread[i] = CreateThread(
                                NULL,                                // default security attributes
                                0,                                        // use default stack size  
                                ThreadProc,                        // thread function
                                m_pArg,                                // argument to thread function
                                CREATE_SUSPENDED,                                        // use default creation flags
                                &m_pdwThreadId[i]);   // returns the thread identifier
                       
                        // Check the return value for success.
                       
                        if (m_phThread[i] == NULL)
                        {
                                ExitProcess(i);
                        }
                        SetThreadPriority(m_phThread[i],THREAD_PRIORITY_LOWEST);
                        ResumeThread(m_phThread[i]);
                }
                GetDlgItem(IDOK)->EnableWindow(FALSE);
                GetDlgItem(IDCANCEL)->EnableWindow(FALSE);
                m_Range = (short)m_dwJobCount;
                m_ctlProgress.SetRange(0,m_Range);
                m_strJobInfo.Format("%d个文件已转换/%d个文件待转换",m_dwEndJobCount,m_dwJobCount);
    }
    m_ctlProgress.SetStep(1);
    m_ctlProgress.SetPos(0);
   
    delete[] pszFileList;
    delete dlgFileOpen;
    UpdateData(FALSE);
    Invalidate(FALSE);
   
}

DWORD WINAPI CEyueteuDlg::ThreadProc( LPVOID lpParam )
{
    PTHREADARG pArg = (PTHREADARG)lpParam;
    CString strFileName = pArg->strFileName;
    CEyueteuDlg *pThis = pArg->pThis;
    if(!pThis->OpenDoc(strFileName))
    {
        pThis->PostMessage(WM_ENDJOB,1,(LPARAM)lpParam);
    }
    else
        pThis->PostMessage(WM_ENDJOB,0,(LPARAM)lpParam);
    return 0;
}

LRESULT CEyueteuDlg::OnEndJobMessage(WPARAM wParam, LPARAM lParam)
{
PTHREADARG pArg = NULL;
        switch(wParam)
    {
    case -2:
                {
                        m_Pos = (int)lParam;
                        for (int i = 0; i < m_Pos;i++)
                        {
                                m_ctlProgress.StepIt();
                        }
                        return 0;
                }
    case -1:
                m_Range += (short)lParam;
                m_ctlProgress.SetRange(0,m_Range);
                return 0;
    case 1:
                {               
                        pArg = (PTHREADARG)lParam;
                        MessageBox(pArg->strFileName,"转换错误!",MB_OK|MB_ICONERROR);
                }
                break;
    case 2:
                {
                        CString str = (LPCSTR)lParam;
                        MessageBoxA(str,"创建文件失败!",MB_OK|MB_ICONERROR);
                        return 0;
                }
        case 3:
                {
                        m_strJobInfo = "解码原始ceb数据......";
                        UpdateData(FALSE);
                }
                return 0;
        case 4:
                {
                        m_strJobInfo = " 生成pdf书签 ......";
                        UpdateData(FALSE);
                }
                return 0;
    default:
                break;
    }
        pArg = (PTHREADARG)lParam;
        if (pArg)
        {
                CloseHandle(m_phThread[pArg->dwThreadId]);
                delete pArg;

        }
    if(++m_dwEndJobCount == m_dwJobCount)
    {
                delete [] m_phThread;
                m_phThread = NULL;
                delete [] m_pdwThreadId;
                m_pdwThreadId = NULL;
                GetDlgItem(IDOK)->EnableWindow(TRUE);
                GetDlgItem(IDCANCEL)->EnableWindow(TRUE);
    }       
    m_strJobInfo.Format("%d个文件已转换/%d个文件待转换",m_dwEndJobCount,m_dwJobCount);
    m_ctlProgress.StepIt();
    UpdateData(FALSE);
    //        Invalidate(FALSE);
    return 0;
}

5.手工增加水印和书签,这部分尤其自豪,曾经请教一个pdf高手,跟我要5万,经过长达15天的不断尝试各类pdf的sdk和lib,最终采用PDFLib的sdk完成.
                // 添加书签和水印以及文档信息,采用PDFLib 7.0.3 注册版
                /* create a new PDFlib object */
                PDF  *p = NULL;
                char optlist[256] = {0};
                char BookMakerName[256] = {0};
                HGLOBAL hRes = 0;
                unsigned char * imagedata;
                int image;
               
                if ((p = PDF_new()) == (PDF *) 0)
                {
                        printf("Couldn't create PDFlib object (out of memory)!\n");
                        return(2);
                }
               
                PDF_TRY(p)
                {
                        if (PDF_begin_document(p, (LPSTR)(LPCSTR)strPDFFileName, 0, ""/*compatibility=1.5*/) == -1)
                        {
                                printf("Error: %s\n", PDF_get_errmsg(p));
                                PDF_delete(p);
                                return(2);
                        }
                        // 设置文档 信息
                        if (m_strBookName.IsEmpty())
                        {
                                int nTemp = strPDFFileName.ReverseFind('\\');
                                nTemp = strPDFFileName.GetLength() - nTemp;
                                m_strBookName = strPDFFileName.Right(nTemp-1);
                        }
                        PDF_set_info(p, "Title", m_strBookName);
                        PDF_set_info(p, "Keywords", "此文档由ceb2pdf专业版3.9生成,详细信息请联系QQ:694285177");
                       
                        PDF_create_pvf(p,
                                "ceb2pdf",
                                0,pBuffer,dwPDFDataLength,0);
                       
                       
                        // 添加水印
                        if (m_bWater)
                        {
                                HRSRC hExeFile = ::FindResource(AfxGetApp()->m_hInstance,MAKEINTRESOURCE(IDR_LOG),_T("log"));   
                                hRes = ::LoadResource(AfxGetApp()->m_hInstance,   hExeFile);   
                                DWORD dwSize   =   ::SizeofResource(AfxGetApp()->m_hInstance,   hExeFile);   
                                if   (hRes != NULL)   
                                {   
                                        imagedata = (PBYTE)::LockResource(hRes);
                                }       
                                PDF_create_pvf(p, "/pvf/image", 0, imagedata, dwSize, "");
                                /* Load the image from the PVF */
                                image = PDF_load_image(p, "auto", "/pvf/image", 0, "");
                                if (image == -1)
                                {
                                        printf("Error: %s\n", PDF_get_errmsg(p));
                                        PDF_delete(p);
                                        if (imagedata)
                                        {
                                                free((void *) imagedata);
                                        }
                                        return(2);
                                }                                       
                        }
                       
                        int manual = PDF_open_pdi_document(p, "ceb2pdf", 0, "");
                        if (manual == -1)
                        {
                                printf("Error: %s\n", PDF_get_errmsg(p));
                                return(2);
                        }
                        /* Get the number of pages in the input document */
                        VMProtectBegin
                                UINT endpage = (int) PDF_pcos_get_number(p, manual, "/Root/Pages/Count");
                        if (m_bDemo)
                        {
                                endpage /= 5;
                        }
                       

                        VMProtectEnd
                        UINT NodeID = 0;        //
                        int ParentNodeID = 0;
                        PDF_set_parameter(p, "pdiwarning", "true");
                       
                        if (pNodeList)
                        {
                                if (m_bBookMake)
                                {
#ifdef CEB2PDF
                                        PostMessage(WM_ENDJOB,(WPARAM)-1,dwNodeCount);
#endif
                                        PostMessage(WM_ENDJOB,(WPARAM)4,0);
                                }
                        }
                        for ( UINT pageno= 1; pageno <= endpage; pageno++)
                        {
                                int page = PDF_open_pdi_page(p, manual, pageno, "");
                               
                                if (page == -1)
                                {
                                        fprintf(stderr, "Error: %s\n", PDF_get_errmsg(p));
                                }
                               
                                /* Dummy page size; will be adjusted later */
                                PDF_begin_page_ext(p, 10, 10, "");
                                // 添加水印
                                if (m_bWater)
                                {
                                        PDF_fit_image(p, image, 0, 0, "scale 0.5");
                                }
                                // 添加书签
                                if (pNodeList)
                                {
                                        if (m_bBookMake)
                                        {
                                                /* Create a bookmark with the file name */
                                                while ((pNodeList+NodeID)->dwDestPage == pageno)
                                                {
#ifdef CEB2PDF
                                                        PostMessage(WM_ENDJOB,(WPARAM)-2,1);
#endif
                                                        int ParentNodeID = (pNodeList+NodeID)->wParentNodeID;
                                                       
                                                        sprintf(BookMakerName,"%s",(pNodeList+NodeID)->szText);
                                                        sprintf(optlist,
                                                                "parent=%d destination {type fixed} textcolor {rgb 0 0 0}",
                                                                ParentNodeID);
                                                        strPDFFileName = optlist;
                                                        if (!ParentNodeID)
                                                        {
                                                                strPDFFileName += " fontstyle=bold";
                                                        }
                                                       
                                                        PDF_create_bookmark(p, BookMakerName, 0,(LPSTR)(LPCSTR)strPDFFileName);
                                                        NodeID++;
                                                        if (NodeID == dwNodeCount)
                                                        {
                                                                break;
                                                        }
                                                }
                                        }
                                }
                               
                               
                                /* Place the imported page on the output page, and
                                * adjust the page size
                                */
                               
                                PDF_fit_pdi_page(p, page, 0, 0, "adjustpage");
                                PDF_end_page_ext(p, "");
                                PDF_close_pdi_page(p, page);
                               
                        }
                        if (m_bWater)
                        {
                                /* Delete the virtual file to free the allocated memory */
                                PDF_delete_pvf(p, "/pvf/image", 0);
                                ::FreeResource(hRes);   
                               
                        }
                        PDF_close_pdi_document(p, manual);
                        PDF_end_document(p, "");
                        PDF_delete(p);

                }
                PDF_CATCH(p)
                {
                        printf("PDFlib exception occurred in pdflib_cs2 sample:\n");
                        printf("[%d] %s: %s\n",
                                PDF_get_errnum(p), PDF_get_apiname(p), PDF_get_errmsg(p));
                        PDF_delete(p);
                        return(2);
                }
               
                delete [] pNodeList;
               
                PostMessage(WM_ENDJOB,(WPARAM)-2,dwPDFDataLength/(1024*100) - nTemp);
                bRet = TRUE;
        }
       

BOOL CEyueteuDlg::OpenDoc(LPCTSTR pszFileName)
{
       
        CATALOGNODE *pNodeList = FALSE;
        DWORD dwNodeCount = 0;
        BOOL bKeyExist = FALSE;
    BOOL bAlgorithmIDExist = FALSE;
        BOOL bRet = FALSE;
    BYTE m_pPDFContentStreamKey[32] = {0};
    int m_nPDFContentStreamKeyLength = 24;
    DWORD m_dwPDFContentStreamAlgorithmID = 0;
        VIRTUALIZER_MUTATE1_START
    CCEBFileEngine cfe(pszFileName);
    if (cfe.GetIndexCount() <= 0)
                return FALSE;

    // 查找PDF内容流stream的加密key和加密算法
        CEBINDEXITEM itemEncryptKey;
    CEBINDEXITEM itemEncryptAlgorithmID;               
    bKeyExist = cfe.FindIndexItem(CEB_INDEXTYPE_CSENCRYPTKEY, NULL, itemEncryptKey);       
    bAlgorithmIDExist = cfe.FindIndexItem(CEB_INDEXTYPE_CSENCRYPTALGORITHMID, NULL, itemEncryptAlgorithmID);
   
    if (bKeyExist && bAlgorithmIDExist)
    {
                bRet = SetKeyFromCEBFile(cfe,
                        itemEncryptAlgorithmID,
                        itemEncryptKey,
                        m_nPDFContentStreamKeyLength,
                        m_dwPDFContentStreamAlgorithmID,
            m_pPDFContentStreamKey);
    }
    else if (!bKeyExist && !bAlgorithmIDExist)
    {
                CEBINDEXITEM itemDRM;       
                BOOL bItemExist = FALSE;
                bItemExist = cfe.FindIndexItem(CEB_INDEXTYPE_DRMMETHOD, NULL, itemDRM);
                if (m_bOnline) // 在线浏览
                        bRet =  SetKeyFromCEBVoucher_3(pszFileName,
                        m_nPDFContentStreamKeyLength,
                        m_dwPDFContentStreamAlgorithmID,
                        m_pPDFContentStreamKey);
                else
                {
                        BYTE* pDate = new BYTE[itemDRM.dwDataBlockLength];
                        memcpy(pDate,cfe.m_pbFile + itemDRM.dwOffsetPos,itemDRM.dwDataBlockLength);
                        if ((int)(*pDate) == 1)        // 购买的图书
                        {
                                bRet = SetKeyFromCEBVoucher_1(pszFileName,
                                        m_nPDFContentStreamKeyLength,
                                        m_dwPDFContentStreamAlgorithmID,
                                        m_pPDFContentStreamKey);
                               
                        }
                        else if((int)(*pDate) == 2) // 借阅的图书
                        {
                                bRet = SetKeyFromCEBVoucher_2(pszFileName,
                                        m_nPDFContentStreamKeyLength,
                                        m_dwPDFContentStreamAlgorithmID,
                                        m_pPDFContentStreamKey);
                               
                        }
                        delete[] pDate;
                       
                }
    }
    if (!bRet)
    {
                cfe.Close();
                return FALSE;
    }
   
    CEBINDEXITEM itemIndex;
    DWORD dwPDFDataLength(0), dwPDFDataOffset(0);
    DWORD dwRC4KeyLength(0), dwRC4KeyOffset(0);
   
    BOOL bPDFDataExist = FALSE;
    BOOL bRC4KeyExist = FALSE;
    if (cfe.FindIndexItem(CEB_INDEXTYPE_PDFDATA, NULL, itemIndex))
    {
                dwPDFDataOffset = itemIndex.dwOffsetPos;
                dwPDFDataLength = itemIndex.dwDataBlockLength;
                bPDFDataExist = TRUE;
    }
   
    if (cfe.FindIndexItem(CEB_INDEXTYPE_RC4KEY, NULL, itemIndex))
    {
                dwRC4KeyOffset = itemIndex.dwOffsetPos;
                dwRC4KeyLength = itemIndex.dwDataBlockLength;
                bRC4KeyExist = TRUE;               
    }
    // CreatePDFFile
    bRet = FALSE;
    if (bPDFDataExist && bRC4KeyExist)
    {
                CFile pdffile;
                CString strPDFFileName = pszFileName;
//                strPDFFileName.MakeLower();
                // 保存到自定义目录
                if (!m_strSavePath.IsEmpty())
                {
                        int nTemp = strPDFFileName.GetLength() - strPDFFileName.ReverseFind('\\');
                        strPDFFileName = strPDFFileName.Right(nTemp);
                        strPDFFileName = m_strSavePath + strPDFFileName;                       
                }
                // 用ceb的内部书名替代原文件名
                if (m_bBookName)
                {
                        CEBBOOKINFOA bi;
                        if (cfe.GetBookInfo(bi))
                        {
                                if (lstrlen(bi.szBookTitle))
                                {
                                        CString strTemp(bi.szBookTitle);
                                        strTemp.Replace(0x2f,'_');
                                        strTemp.Replace('\\','_');
                                        strTemp.Replace(0x0a,'_');
                                        strTemp.Replace(0x0d,'_');
                                        m_strBookName = strTemp;
                                       
                                        int nTemp = strPDFFileName.ReverseFind('\\');
                                        strPDFFileName = strPDFFileName.Left(nTemp+1);
                                        strPDFFileName += strTemp;
                                       
                                }
                        }
                }
                if (m_bNoEncrypt)
                {
                        if (bKeyExist && bAlgorithmIDExist)
                        {
                                TCHAR szBuf[80];
                                wsprintf(szBuf,
                                        "要转换的文件已经是未加密的!");
                                SendMessage(WM_ENDJOB,2,(LPARAM)(szBuf));
                                return TRUE;
                               
                        }
                       
                        strPDFFileName.Insert(strPDFFileName.ReverseFind('\\') + 1,"未加密_");
                        strPDFFileName += ".ceb";
                }
                else
                {
                        strPDFFileName.TrimRight(".ceb");
                        strPDFFileName += ".pdf";
                }
                //                        strPDFFileName += ".pdf";
                // 修改文件打开方式为禁止写!防止有的ceb内部文件名一样,创建同名文件而出现错误!
                DeleteFile(strPDFFileName);

                if (!pdffile.Open(strPDFFileName,
                        CFile::modeReadWrite|CFile::shareDenyWrite|CFile::modeCreate))
                {
                        TCHAR szBuf[80];
                        LPVOID lpMsgBuf;
                        DWORD dw = GetLastError();
                       
                        FormatMessage(
                                FORMAT_MESSAGE_ALLOCATE_BUFFER |
                                FORMAT_MESSAGE_FROM_SYSTEM,
                                NULL,
                                dw,
                                MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
                                (LPTSTR) &lpMsgBuf,
                                0, NULL );
                       
                        wsprintf(szBuf,
                                "创建%s的PDF文件发生错误!\r错误号: %d\r错误信息: %s",
                                pszFileName,dw, lpMsgBuf);
                        LocalFree(lpMsgBuf);
                        SendMessage(WM_ENDJOB,2,(LPARAM)(szBuf));               
                        cfe.Close();
                        return TRUE;
                }
                DWORD dwFileSize = cfe.m_cebFile.GetLength();
                // #ifndef CEB2PDF
                //                 if (dwFileSize > 1024*10000)
                //                 {
                //                         return FALSE;
                //                 }
                // #endif
               
                // 转成未加密的ceb
                if (m_bNoEncrypt)
                {
#ifdef CEB2PDF
                        if (bKeyExist && bAlgorithmIDExist)
                                return FALSE;
                        // ceb Head
                        pdffile.Write(cfe.m_pbFile,16);
                        // 插件数据的新长度
                        DWORD dwTemp = DWORD(*(cfe.m_pbFile + 16));
                        dwTemp += 0x22;
                        pdffile.Write(&dwTemp,4);
                        // 插件的新数目
                        dwTemp = WORD(*(cfe.m_pbFile + 16 + 4));
                        dwTemp += 2;
                        pdffile.Write(&dwTemp,2);
                        // 插件数据,新增17 * 2 个字节,
                        // RC4 Key
                        ZeroMemory(&itemIndex,sizeof(itemIndex));
                        itemIndex.byIndexType = 4;
                        itemIndex.dwOffsetPos = dwFileSize + 17*2;
                        itemIndex.dwDataBlockLength = 64;
                        pdffile.Write(&itemIndex,17);
                        // 加密方法
                        ZeroMemory(&itemIndex,sizeof(itemIndex));
                        itemIndex.byIndexType = 5;
                        itemIndex.dwOffsetPos = dwFileSize + 17*2 + 64;
                        itemIndex.dwDataBlockLength = 4;
                        pdffile.Write(&itemIndex,17);
                       
                        dwTemp = DWORD(*(cfe.m_pbFile + 16 + 4));
                        for (DWORD n = 0; n < dwTemp; n++)
                        {
                                memcpy(&itemIndex,cfe.m_pbFile + 22 +n*17,17);
                                itemIndex.dwOffsetPos += 17*2;
                                if (itemIndex.byIndexType ==0x0a)// 去掉DRM标识
                                {
                                        itemIndex.byIndexType =0xFE;
                                }
                                pdffile.Write(&itemIndex,17);
                        }
                        // 原来的pdf内核数据
                        pdffile.Write(cfe.m_pbFile + 22 + dwTemp*17,dwFileSize- 22  - dwTemp*17 );
                        // 必须将密钥加密,否则不能在Reader中打印!
                        BYTE *pDecryptKey = NULL;
                        int nLen = 0;
                        if (!EncryptKey(m_pPDFContentStreamKey, 24, pDecryptKey, nLen))
                        {
                                // 加密出错
                                TCHAR szBuf[80];
                                wsprintf(szBuf,
                                        "加密Key错误!");
                                SendMessage(WM_ENDJOB,2,(LPARAM)(szBuf));
                                return TRUE;
                               
                        }
                       
                        pdffile.Write(pDecryptKey,nLen);
                        m_dwPDFContentStreamAlgorithmID += 0x80000000;
                        pdffile.Write(&m_dwPDFContentStreamAlgorithmID,4);
                        free(pDecryptKey);
                        pdffile.Close();
                        cfe.Close();
                        return TRUE;
#endif                       
                }
               
                if (dwFileSize < dwRC4KeyOffset + dwRC4KeyLength
                        ||dwFileSize < dwPDFDataOffset + dwPDFDataLength)
                {
                        cfe.Close();
                        return FALSE;
                }
                VIRTUALIZER_END

                        BYTE* pRC4Key = NULL;
                // 得到RC4密钥
                pRC4Key = cfe.m_pbFile + dwRC4KeyOffset;
               
                CRC4CryptoEngine objTmpRC4;
                objTmpRC4.InitialRC4Crypto(pRC4Key, (BYTE)dwRC4KeyLength);
                CRC4CryptoEngine objRC4;
               
                int nTemp = dwPDFDataLength/(1024*100);
                SendMessage(WM_ENDJOB,(WPARAM)-1,nTemp);
                nTemp = 0;
                LPBYTE pBuffer = cfe.m_pbFile + dwPDFDataOffset;                               
               
                DWORD dwLen = 0,dwPDFLen = dwPDFDataLength;
                int nCount = 0;
                while (dwPDFLen > 0)
                {
                        dwLen = 65536;
                        if (dwPDFLen < 65536)
                        {
                                dwLen = dwPDFLen;
                        }
                        memcpy(&objRC4, &objTmpRC4, sizeof(CRC4CryptoEngine));
                        objRC4.RC4Decrypt(pBuffer + nCount*65536, dwLen);
                        if (dwPDFDataLength < 65536)
                        {
                                break;
                        }
                        dwPDFLen -= dwLen;
                        nCount++;
                }
// #if defined(_DEBUG)
//                 pdffile.Write(cfe.m_pbFile + dwPDFDataOffset,dwPDFDataLength);
//                 CString strTempFileName = pdffile.GetFileName();
//                 CopyFile(strTempFileName,strTempFileName + ".temp",0);
// #endif
               
               
                // 解密stream和endstream之间的内容
                PostMessage(WM_ENDJOB,(WPARAM)3,0);
                DWORD dwStream = 0;
                DWORD dwEndStream = 0;
                BYTE *pDeCode = new BYTE[256];
                while (1)
                {
                        for (DWORD i = dwStream; i < dwPDFDataLength; i++)
                        {
                                if (pBuffer[i] == 's' && !memcmp(&pBuffer[i],"stream",6) &&
                                        pBuffer[i-1] != 'd')
                                {
                                        break;
                                }
                        }
                        if (i >= dwPDFDataLength)
                        {
                                break;
                        }
                        if (!i)
                        {
                                return FALSE;
                        }
                        dwStream = i;
                       
                        for (i = dwStream; i < dwPDFDataLength; i++)
                        {
                                if (pBuffer[i] == 'e' && !memcmp(&pBuffer[i],"endstream",9) )
                                {
                                        break;
                                }
                        }
                        if (!i)
                        {
                                return FALSE;
                        }
                        if (i >= dwPDFDataLength)
                        {
                                break;
                        }
                        dwEndStream = i;
                       
                        while(1)
                        {
                                if(pBuffer[dwStream++ +6] == 0x0a)
                                {
                                        break;
                                }
                               
                        }
                        int nBufLen = dwEndStream-dwStream;
                        nBufLen -= 6;
                        DWORD m =0;
                        while(nBufLen>0)
                        {
                                int n=0;
                                if (nBufLen>256)
                                {
                                        n = 256;
                                }
                                else
                                        n = nBufLen;
                                EN_EncryptData(0,
                                        m_dwPDFContentStreamAlgorithmID,
                                        m_pPDFContentStreamKey,
                                        m_nPDFContentStreamKeyLength,
                                        &(pBuffer[dwStream+6+m*256]),
                                        n,
                                        pDeCode,
                                        m_pPDFContentStreamKey,
                                        m_nPDFContentStreamKeyLength);
                                memcpy(&(pBuffer[dwStream+6+m*256]),pDeCode,n);
                                nBufLen -= 256;
                                m++;
                        }
                        dwStream = dwEndStream+9;
                        DWORD nTemp1 = dwStream/(1024*100);
                        DWORD nTemp2 = nTemp1-nTemp;
                        nTemp = nTemp1;
                        if (nTemp2)
                        {
                                PostMessage(WM_ENDJOB,(WPARAM)-2,nTemp2);
                        }
                       
                }
               
                delete[] pDeCode;
               
                //        去掉PDF中的加密标示
                dwPDFLen = dwPDFDataLength;
                while (dwPDFLen--)
                {
                        if (pBuffer[dwPDFLen]=='E'&&pBuffer[dwPDFLen+1]=='n')
                        {
                                dwPDFLen --;
                                break;                               
                        }
                }
                DWORD nEN_Start = dwPDFLen;
               
                while (pBuffer[dwPDFLen++] != 0x0D)
                {
                        ;
                }
                DWORD nEN_End = dwPDFLen;
               
                memcpy(&pBuffer[nEN_Start],&pBuffer[nEN_End],dwPDFDataLength-nEN_End);
               
                dwPDFDataLength = dwPDFDataLength - nEN_End+nEN_Start;
//                pdffile.SetLength(dwPDFDataLength);
                // PDF 降版本,供后续程序操作
//                pBuffer[7] = '4';

//                pdffile.Seek(0,CFile::begin);
//                pdffile.Write(pBuffer,dwPDFDataLength);
                pdffile.Close();

[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

收藏
点赞0
打赏
分享
最新回复 (21)
雪    币: 609
活跃值: (212)
能力值: ( LV12,RANK:441 )
在线值:
发帖
回帖
粉丝
yangjt 10 2008-8-21 12:28
2
0
坐在前排支持你~~
雪    币: 215
活跃值: (11)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
caocunt 2008-8-21 12:37
3
0
1.本程序防御曾经采用过WL,VM等加壳手段,后来在水印部分采用图片方式,校验水印图片的MD5值来解密关键的加解密函数.
2.pdf还是很好玩的,也很有前途,在这个过程中学了很多东西,但是我不想研究下去了.
3.起码我教会了一个单位如何保护自己的产品.
4.第3篇我将放出我最为得意的一个产品的整个工程.里面涉及到了我这几年学会的任何知识,也算是一个总结和结束.
雪    币: 134
活跃值: (142)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
xievazi 2008-8-21 13:17
4
0
试问出路?
继续搞技术?
改行?(30多了都)
回你那原来的城市堕落?
雪    币: 622
活跃值: (65)
能力值: ( LV13,RANK:290 )
在线值:
发帖
回帖
粉丝
dge 6 2008-8-21 15:07
5
0
俺也决定离开北京了,哈哈。回山东发展。
雪    币: 6073
活跃值: (2236)
能力值: (RANK:1060 )
在线值:
发帖
回帖
粉丝
forgot 26 2008-8-21 16:56
6
0
WL VM都能逆出源码,强大到biangbiangsheng
雪    币: 846
活跃值: (221)
能力值: (RANK:570 )
在线值:
发帖
回帖
粉丝
笨笨雄 14 2008-8-21 19:12
7
0
最近离开北京的人很多。。。唉。。。
雪    币: 134
活跃值: (142)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
xievazi 2008-8-21 20:07
8
0
看韦小宝看多了吧
雪    币: 622
活跃值: (65)
能力值: ( LV13,RANK:290 )
在线值:
发帖
回帖
粉丝
dge 6 2008-8-21 20:11
9
0
小宝与康熙......
雪    币: 325
活跃值: (97)
能力值: ( LV13,RANK:530 )
在线值:
发帖
回帖
粉丝
foxabu 13 2008-8-21 22:08
10
0
是不是可以直接把vm的代码 nop 也可以运行?
雪    币: 400
活跃值: (239)
能力值: ( LV9,RANK:170 )
在线值:
发帖
回帖
粉丝
marswu 4 2008-8-21 22:42
11
0
期待楼主第3篇!!
雪    币: 2314
活跃值: (129)
能力值: (RANK:410 )
在线值:
发帖
回帖
粉丝
shellwolf 10 2008-8-22 08:43
12
0
虽然不懂,支持下。
雪    币: 479
活跃值: (25)
能力值: ( LV8,RANK:130 )
在线值:
发帖
回帖
粉丝
dttom 3 2008-8-22 20:40
13
0
楼主,看了你两篇文章,虽然不懂,但是支持一下
技术上做到现在也是不容易的,现在放弃很可惜
雪    币: 186
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
piebald 2008-8-23 21:38
14
0
ceb转PDF麻?
什么时候走,小弟我送你一程吧。
小弟搞嵌入方面驱动开发。
雪    币: 396
活跃值: (1078)
能力值: ( LV9,RANK:970 )
在线值:
发帖
回帖
粉丝
simonzh2000 24 2008-8-24 02:26
15
0
请坚持, 一路走好.
雪    币: 225
活跃值: (88)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
rock 2008-8-29 11:20
16
0
好东西,收藏了。
主要代码都放出了,楼主能放出整个工程吗?
雪    币: 332
活跃值: (479)
能力值: ( LV9,RANK:330 )
在线值:
发帖
回帖
粉丝
laoqian 8 2008-8-29 14:25
17
0
后来在水印部分采用图片方式,校验水印图片的MD5值来解密关键的加解密函数.
这个感兴趣,看来只有注册版才能爆破掉了
雪    币: 263
活跃值: (10)
能力值: ( LV9,RANK:210 )
在线值:
发帖
回帖
粉丝
fonge 5 2008-8-29 19:45
18
0
图片只是改掉了某张图片的数个字节,嘎嘎~~
雪    币: 201
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
waklin 2008-8-30 11:38
19
0
支持,代码不错,不过注释太少~
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
uldm 2009-1-8 17:11
20
0
问一下:
EN_EncryptData(0,
          m_dwPDFContentStreamAlgorithmID,
          m_pPDFContentStreamKey,
          m_nPDFContentStreamKeyLength,
          &(pBuffer[dwStream+6+m*256]),
          n,
          pDeCode,
          m_pPDFContentStreamKey,
          m_nPDFContentStreamKeyLength);
这函数是不是跟版本有关!
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
uldm 2009-1-8 17:11
21
0
LZ真是天才!
雪    币: 213
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
xxyyzasabc 2009-2-15 10:46
22
0
VM也能还原 膜拜!
游客
登录 | 注册 方可回帖
返回