首页
社区
课程
招聘
[原创]ceb2pdf的可移植代码(不完全,哥不太会ida)
发表于: 2017-6-12 18:25 8987

[原创]ceb2pdf的可移植代码(不完全,哥不太会ida)

2017-6-12 18:25
8987

// ceb2pdf.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include "CEBFileEngine.h"
#include <iostream>
#include <string>
#include <vector>
using namespace std;

#include <openssl/evp.h>
#include <openssl/rsa.h>
#pragma comment(lib, "libeay32.lib")


#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif


unsigned char key1 [0x40] =
{
    0x91, 0x43, 0x7c, 0xd8, 0x3d, 0x07, 0x22, 0xce, 0x41, 0x0b, 0xd9, 0x6c, 0xa8, 0x0c, 0xff, 0x34,
    0x89, 0x5a, 0x31, 0x5e, 0x25, 0x12, 0x8b, 0xc3, 0x25, 0x29, 0xd5, 0xf6, 0x14, 0xe4, 0x50, 0x97,
    0xe1, 0x2e, 0x45, 0x0c, 0x68, 0xda, 0xf1, 0xad, 0x8d, 0x8e, 0x74, 0x0a, 0xb7, 0x08, 0x56, 0x4f,
    0x4f, 0x31, 0x7b, 0x80, 0x12, 0xc4, 0x48, 0x56, 0xde, 0x56, 0x7d, 0x58, 0x52, 0x24, 0x97, 0xdb
};
unsigned char key2 [0x40] =
{
    0xf3, 0x84, 0xff, 0x17, 0xa8, 0x16, 0x5a, 0x0e, 0xce, 0xb0, 0xa5, 0x26, 0xf5, 0x44, 0x12, 0xa9,
    0x9a, 0x88, 0xec, 0x69, 0x68, 0xb5, 0xe1, 0x4f, 0xaf, 0x7a, 0x08, 0xbe, 0xe9, 0x2f, 0xfd, 0xe3,
    0x5b, 0x18, 0xc5, 0x46, 0x97, 0xd8, 0x6e, 0xcc, 0x63, 0x97, 0x00, 0xe6, 0x42, 0xbc, 0x91, 0x75,
    0x7e, 0x52, 0x2d, 0xc5, 0xef, 0x4c, 0x95, 0xcc, 0xd7, 0x46, 0xd2, 0xd2, 0x59, 0xdb, 0x00, 0xc5
};

/////////////////////////////////////////////////////////////////////////////
enum
{
    TYPE_3DES_OFB = 1,
    TYPE_3DES_CFB = 2,
    TYPE_3DES_CTS = 3,
    TYPE_IDEA_OFB = 4,
    TYPE_IDEA_CFB = 5,
    TYPE_IDEA_CTS = 6,
    TYPE_RC5_OFB = 7,
    TYPE_RC5_CFB = 8,
    TYPE_RC5_CTS = 9,
    TYPE_RC4_OFB = 10,
    TYPE_RC4_CFB = 11,
    TYPE_RC4_CTS = 12,
    TYPE_CAST256_OFB = 13,
    TYPE_CAST256_CFB = 14,
    TYPE_CAST256_CTS = 15
};

int des_decrypt(int nEncryptStyle, char* pKey, char * szInput, int nInLen, unsigned char *szOutput)
{
    int iOutLen = 0;
    int iTmpLen = 0;        
    char iv[8] = {0};
    // 初始化iv值,应该为输入密码的前8个字节
    memcpy(iv, pKey, 8);
    // 初始化,用到什么加密方式由EVP_des_ede3_ecb()决定的,
    // 如果改为其他加密方式,只要改这个就可以了。    
    EVP_CIPHER_CTX ctx;        
    EVP_CIPHER_CTX_init(&ctx);  
    switch (nEncryptStyle)
    {
    case TYPE_3DES_OFB:
        EVP_EncryptInit_ex(&ctx, EVP_des_ede3_ofb(),
            NULL,
            (const unsigned char *)pKey,
            (const unsigned char *)iv);        //加密    
        break;
    case TYPE_3DES_CFB:
        EVP_EncryptInit_ex(&ctx, EVP_des_ede3_cfb8(),
            NULL,
            (const unsigned char *)pKey,
            (const unsigned char *)iv);        //加密    
        break;
    case TYPE_3DES_CTS:
        break;
    case TYPE_IDEA_OFB:
        break;    
    case TYPE_IDEA_CFB:
        break;    
    case TYPE_IDEA_CTS:
        break;    
    case TYPE_RC5_OFB:
        break;
    case TYPE_RC5_CFB:
        break;
    case TYPE_RC5_CTS:
        break;
    case TYPE_RC4_OFB:
    case TYPE_RC4_CFB:
    case TYPE_RC4_CTS:
    case TYPE_CAST256_OFB:
    case TYPE_CAST256_CFB:
    case TYPE_CAST256_CTS:
    default:
        return 0;
    }

    if(!EVP_EncryptUpdate(&ctx, (unsigned char*)szOutput, &iOutLen, (const unsigned char *)szInput, nInLen))    
    {        
        EVP_CIPHER_CTX_cleanup(&ctx);        
        return 0;    
    }   //结束加密    
    if(!EVP_EncryptFinal_ex(&ctx, (unsigned char *)(szOutput + iOutLen), &iTmpLen))    
    {        
        EVP_CIPHER_CTX_cleanup(&ctx);        
        return 0;    
    }        
    iOutLen += iTmpLen;      
    EVP_CIPHER_CTX_cleanup(&ctx);
    return iOutLen;
}

int rsa_decrypt(unsigned char * szInput, int nInLen, unsigned char *szOutput)
{
    RSA *rsa = NULL;

    if (!szInput || !szOutput)
    {
        return 0;
    }
    rsa = RSA_new();
    BIGNUM *ret, *a, *b, *c;
    BN_CTX *ctx = NULL;
    if ((ctx = BN_CTX_new()) == NULL)
        return NULL;
    BN_CTX_start(ctx);
    ret  = BN_new();
    a  = BN_new();
    b  = BN_new();
    c  = BN_new();
    a->dmax = 16;
    b->dmax = 16;
    c->dmax = nInLen/4;
    a->top = 16;
    b->top = 16;
    c->top = nInLen/4;

    a->d = (BN_ULONG*)key1;
    b->d = (BN_ULONG*)key2;
    c->d = (BN_ULONG*)szInput;
    size_t nOutLen = 0;
    if (!rsa->meth->bn_mod_exp(ret, c, b, a, ctx,rsa->_method_mod_n))
    {
        goto _Exit;
    }
    nOutLen = ret->d[0];
    memcpy(szOutput, (void*)&(ret->d[1]), nOutLen);
_Exit:
    BN_clear_free(ret);
    a->d = NULL;
    b->d = NULL;
    c->d = NULL;
    BN_clear_free(a);
    BN_clear_free(b);
    BN_clear_free(c);
    BN_CTX_free(ctx);
    RSA_free(rsa);
    return (int)nOutLen;

}

typedef struct __tagRC4KEY
{      
    BYTE state[256];       
    BYTE x;        
    BYTE y;
} RC4KEY;

class CRC4CryptoEngine
{
public:
    CRC4CryptoEngine() {}
    virtual ~CRC4CryptoEngine() {}

protected:
    RC4KEY m_RC4Key;     // RC4的加密/解密密钥

public:
    void RC4Crypto(LPBYTE lpbyCryptoText, DWORD dwTextLen)
    {
        BYTE byT, byX, byY;
        BYTE byXorIndex;

        BYTE *pbyState;

        byX = m_RC4Key.x;
        byY = m_RC4Key.y;

        pbyState = &m_RC4Key.state[0];
        for (DWORD dwCounter = 0; dwCounter < dwTextLen; dwCounter++)
        {
            byX = (BYTE)(((int)byX + 1) % 256);
            byY = (BYTE)(((int)pbyState[byX] + byY) % 256);

            byT = pbyState[byX];
            pbyState[byX] = pbyState[byY];
            pbyState[byY] = pbyState[byT];

            byXorIndex = (BYTE)(((int)pbyState[byX] + pbyState[byY]) % 256);
            lpbyCryptoText[dwCounter] ^= pbyState[byXorIndex];
        }               

        m_RC4Key.x = byX;
        m_RC4Key.y = byY;
    }


    void InitialRC4Crypto(LPBYTE lpbyKey, BYTE byKeyLen)    // 初始化
    {
        // Create Seed
        BYTE pbySeed[256];

        for (BYTE i = 0; i < byKeyLen; i++)
        {
            pbySeed[i]  = lpbyKey[i];
            pbySeed[i] |= 0xAA;
        }

        // Prepare RC4 Key
        BYTE byT;
        BYTE byIndex1 = 0;
        BYTE byIndex2 = 0;
        BYTE byCounter;
        BYTE *pbyState;

        pbyState = &m_RC4Key.state[0];
        byCounter = 0;
        while (TRUE)
        {
            pbyState[byCounter] = byCounter;
            if (byCounter == 255)
                break;
            else
                byCounter++;
        }                

        m_RC4Key.x = 0;
        m_RC4Key.y = 0;

        byCounter = 0;
        while (TRUE)
        {
            byIndex2 = (BYTE)(((int)pbySeed[byIndex1] + pbyState[byCounter] + byIndex2) % 256);

            byT = pbyState[byCounter];
            pbyState[byCounter] = pbyState[byIndex2];
            pbyState[byIndex2] = byT;

            byIndex1 = (BYTE)(((int)byIndex1 + 1) % byKeyLen);

            if (byCounter == 255)
                break;
            else
                byCounter++;
        }
    }

    
};

BOOL SetKeyFromCEBFile(CCEBFileEngine& cfe,
    const CEBINDEXITEM& itemAlgorithmID,
    const CEBINDEXITEM& itemKey,
    int& nKeyLength,
    DWORD& dwAlgorithmID,
    BYTE* pPdfKey)
{
    BOOL bRet = FALSE;
    DWORD dwAlgorithmIDOffset = itemAlgorithmID.dwOffsetPos;
    DWORD dwAlgorithmIDLength = itemAlgorithmID.dwDataBlockLength;

    DWORD dwKeyOffset = itemKey.dwOffsetPos;    
    DWORD dwKeyLength = itemKey.dwDataBlockLength;

    if (dwAlgorithmIDLength != sizeof(DWORD))
        return bRet;

    DWORD dwTemp;
    if(!AfxIsValidAddress(cfe.m_pbFile + dwAlgorithmIDOffset,dwAlgorithmIDLength,FALSE))
        return bRet;
    memcpy(&dwTemp,cfe.m_pbFile + dwAlgorithmIDOffset, dwAlgorithmIDLength);
    dwAlgorithmID = dwTemp;

    // 读对称密钥
    BYTE* pKey = new BYTE[dwKeyLength];
    memcpy(pKey,cfe.m_pbFile + dwKeyOffset,dwKeyLength);
    if ((dwAlgorithmID & 0x80000000) != 0)
    {
        // 密钥进行加密了        
        dwAlgorithmID -= 0x80000000;                    
        int nLen = 0;
        if (nLen = rsa_decrypt(pKey, dwKeyLength, pPdfKey))
        {
            if (nLen < 32)
            {
                nKeyLength = nLen;
                bRet = TRUE;
            }
        }
    }
    else
    {
        if (dwKeyLength <= 32)
        {
            memcpy(pPdfKey, pKey, dwKeyLength);
            bRet = TRUE;
        }
        nKeyLength = dwKeyLength;
    }
    delete[] pKey;
    pKey = NULL;
    return bRet;
}

BOOL ceb2pdf(LPCSTR pszCebFileName, LPCSTR pszPdfFileNme = NULL)
{

    BOOL bRet = FALSE;
    if(!pszCebFileName)
        return bRet;

    CString strBookName;
    DWORD dwNodeCount = 0;
    BOOL bKeyExist = FALSE;
    BOOL bAlgorithmIDExist = FALSE;
    BYTE m_pPDFContentStreamKey[32] = {0};
    int m_nPDFContentStreamKeyLength = 24;
    DWORD m_dwPDFContentStreamAlgorithmID = 0;
    CCEBFileEngine cfe(pszCebFileName);
    if (cfe.GetIndexCount() <= 0)
    {
        cfe.Close();
        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);
    }
    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)
    {

        DWORD dwFileSize = (DWORD)cfe.m_cebFile.GetLength();


        if (dwFileSize < dwRC4KeyOffset + dwRC4KeyLength
            ||dwFileSize < dwPDFDataOffset + dwPDFDataLength)
        {
            cfe.Close();
            return FALSE;
        }

        BYTE* pRC4Key = NULL;
        // 得到RC4密钥
        pRC4Key = cfe.m_pbFile + dwRC4KeyOffset;

        CRC4CryptoEngine objTmpRC4;
        objTmpRC4.InitialRC4Crypto(pRC4Key, (BYTE)dwRC4KeyLength);
        CRC4CryptoEngine objRC4;

        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.RC4Crypto(pBuffer + nCount*65536, dwLen);
            if (dwPDFDataLength < 65536)
            {
                break;
            }
            dwPDFLen -= dwLen;
            nCount++;
        }


        if (m_dwPDFContentStreamAlgorithmID)
        {

            // 解密stream和endstream之间的内容
            DWORD dwStream = 0;
            DWORD dwEndStream = 0;
            DWORD i = 0;
            BYTE *pDeCode = new BYTE[256];
            while (1)
            {
                for (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)
                {
                    cfe.Close();
                    return FALSE;
                }
                dwStream = i;

                for (i = dwStream; i < dwPDFDataLength; i++)
                {
                    if (pBuffer[i] == 'e' && !memcmp(&pBuffer[i],"endstream",9) )
                    {
                        break;
                    }
                }
                if (!i)
                {
                    cfe.Close();
                    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;
                    des_decrypt(m_dwPDFContentStreamAlgorithmID,
                        (char*)(&m_pPDFContentStreamKey[0]),
                        (char*)&(pBuffer[dwStream+6+m*256]),
                        n,
                        pDeCode);
                    memcpy(&(pBuffer[dwStream+6+m*256]),pDeCode,n);
                    nBufLen -= 256;
                    m++;
                }
                dwStream = dwEndStream+9;

            }

            delete[] pDeCode;
            pDeCode = NULL;

            //    去掉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;

            // 用0x20填充
            memset(&pBuffer[nEN_Start], 0x20, nEN_End - nEN_Start);
        }

        CString strPDFFileName = pszPdfFileNme;
        CString strCEBFileName = pszCebFileName;
        if (strPDFFileName.IsEmpty())
        {
            strPDFFileName = strCEBFileName.Left(strCEBFileName.GetLength() - 4);
            strPDFFileName += ".pdf";

        }
        // 修改文件打开方式为禁止写!防止有的ceb内部文件名一样,创建同名文件而出现错误!
        DeleteFile(strPDFFileName);
        if (1)
        {
            CFile pdffile;
            if (!pdffile.Open(strPDFFileName,
                CFile::modeReadWrite|CFile::shareDenyWrite|CFile::modeCreate))
            {
                cfe.Close();
                return FALSE;
            }
            pdffile.SeekToBegin();
            pdffile.Write(pBuffer,dwPDFDataLength);
            pdffile.Close();
            cfe.Close();
            return TRUE;
        }
    }
    cfe.Close();
    return bRet;
}


void DoCmd(std::string& strCmd)
{
    if (strCmd == "help")
    {
        cout <<endl<< "用法:"<<endl<<endl<<"convert[c]  cebfile  pdffile" << endl<<endl;
        cout <<"1.输入输出文件名路径不能有空格!" << endl <<endl;
        cout <<"2.输出文件名可以忽略,默认生成同名pdf文件!" << endl <<endl;
        cout <<"3.convert命令可以用c代替!" << endl <<endl;
        return;
    }
    std::vector<std::string> str_list; // 存放分割后的字符串
    size_t comma_n = 0;
    do
    {
        std::string tmp_s = "";
        comma_n = strCmd.find( " " );
        if( -1 == comma_n )
        {
            tmp_s = strCmd.substr( 0, strCmd.length() );
            str_list.push_back( tmp_s );
            break;
        }
        tmp_s = strCmd.substr( 0, comma_n );
        strCmd.erase(0, comma_n+1);
        str_list.push_back( tmp_s );
    }
    while(true);

    size_t i = str_list.size();
    if ((str_list[0] == "convert" || str_list[0] == "c")&& i >= 2)
    {
        BOOL bRet = FALSE;
        if (i == 2)
        {
            bRet = ceb2pdf(str_list[1].data());
        }
        else
        {
            bRet = ceb2pdf(str_list[1].data(), str_list[2].data());
        }


        if (bRet)
        {
            cout<<endl<<"done!"<<endl<<endl;
        }
        else
        {
            cout<<endl<<"error!"<<endl<<endl;
        }
    }
    else
    {
        cout <<endl<< "Please type \"help\" to usag and type \"exit\" to exit." << endl<<endl;

    }
    return ;
}


int _tmain(int argc, _TCHAR* argv[])
{
#if 0
    printf("将要转换的pdf文件是%s\n\n",argv[1]);
    // system("PAUSE");
    //// 成功返回1,失败返回0
    BOOL bRet = ceb2pdf("1.ceb");
    printf("\n转换结果:    %d\n\n",bRet);
    //system("PAUSE");
    return 0;
#else
    string strCmd;
    char buf[1024] = {0};
    while ( strCmd != "quit" && strCmd!= "exit")
    {
        cout << "ceb2pdf>" ;
        gets_s(buf);
        strCmd = buf;
        DoCmd(strCmd);
    }
    return 0;
#endif
}


[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

收藏
免费 0
支持
分享
最新回复 (4)
雪    币: 201
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
这不是转换电子书的东西么,高级啊。
2017-7-17 12:29
0
雪    币: 220
活跃值: (243)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
如何获取CEBFileEngine.h、evp.h、rsa.h和libeay32.lib?
2020-5-3 11:19
0
雪    币: 259
活跃值: (283)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
转换成pdf的源码?
2020-5-3 16:18
0
雪    币: 24
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
5
正好需要Ceb转Pdf,调试完成后编译可用,多谢
2023-2-23 14:54
0
游客
登录 | 注册 方可回帖
返回
//