apprenticeharper / DeDRM_tools

DeDRM tools for ebooks
14.51k stars 1.5k forks source link

cannot fined decryption key?? #1980

Open medicine88 opened 2 years ago

medicine88 commented 2 years ago

hi dear friends.i have problem with file downloaded from IHS and techstreet and facing problems"cannot fined decryption key" error. i Urgent need to unlock my files.help me please

ElleKayEm commented 2 years ago

What type of file? What DRM?

medicine88 commented 2 years ago

PDF...Fileopen

ElleKayEm commented 2 years ago

That's not a DRM that these tools work with.

medicine88 commented 2 years ago

That's not a DRM that these tools work with.

????????????/ i download one pdf file from IHS and when exe plugin to remove DRM , "cannot fined decryption key..error

j-howell commented 2 years ago

FileOpen DRM removal is part of the "other tools" that were removed from DeDRM releases when apprenticeharper decided to only support the calibre plugins. It is still available in this repository at: https://github.com/apprenticeharper/DeDRM_tools/tree/master/Other_Tools/Tetrachroma_FileOpen_ineptpdf

As the ReadMe there says there is no support for this script. You are on your own.

medicine88 commented 2 years ago

FileOpen DRM removal is part of the "other tools" that were removed from DeDRM releases when apprenticeharper decided to only support the calibre plugins. It is still available in this repository at: https://github.com/apprenticeharper/DeDRM_tools/tree/master/Other_Tools/Tetrachroma_FileOpen_ineptpdf

As the ReadMe there says there is no support for this script. You are on your own.

i know.i use this script py.but not working for IHS benchmark files

leecher1337 commented 2 years ago

FileOpen implemented another "protection" layer by returning a few parameters:

Key Description
Nascv Version of encoding, 1=base64 encoded, 2=base64 and URLencoded
Nasct Timestamp (SystemTime.wMilliseconds)
Nasca rand() % 0x4000
Nasce 257
Nascd Data

The data containing Code=.. etc. is in Nascd and has to be decrypted via a static table. I implemented some simple C-code to demonstrate/describe the algorithm:

#include <stdlib.h>

/****************************************
 * Platform-dependent functions         *
 ****************************************/

#ifdef WIN32
#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
#include <wincrypt.h>

static HCRYPTPROV m_hProv;

/* MD5 */
struct MD5Context {
    HCRYPTHASH  hHash;
};
static void __forceinline MD5Init(struct MD5Context *ctx)
{
    CryptCreateHash(m_hProv, CALG_MD5, 0, 0, &ctx->hHash);
}
static void __forceinline MD5Update(struct MD5Context *ctx, BYTE *pbData, DWORD cbData)
{
    CryptHashData(ctx->hHash, pbData, cbData, 0);
}
static void __forceinline MD5Final(BYTE *pbData, struct MD5Context *ctx)
{
    DWORD cbData = 16;
    CryptGetHashParam(ctx->hHash, HP_HASHVAL, pbData, &cbData, 0);
    CryptDestroyHash(ctx->hHash);
}

unsigned char *base64_decode(char *pSrc, int cbSrc, unsigned long *pcbDest)
{
    DWORD dwSkip = 0, dwFlags = 0;
    unsigned char *pDest;

    if (!CryptStringToBinaryA((LPCSTR)pSrc, cbSrc, CRYPT_STRING_BASE64, NULL, pcbDest, &dwSkip, &dwFlags))
        return NULL;
    if (!(pDest = (unsigned char *)malloc(*pcbDest))) return NULL;
    if (!CryptStringToBinaryA((LPCSTR)pSrc, cbSrc, CRYPT_STRING_BASE64, pDest, pcbDest, &dwSkip, &dwFlags))
    {
        free(pDest);
        pDest = NULL;
    }
    return pDest;
}

char *urldecode(char *pszData)
{
    // TODO, FIXME: Implement
    return strdup(pszData);
}

static void platform_init(void)
{
    CryptAcquireContext(&m_hProv, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT);
}

static void platform_exit(void)
{
    CryptReleaseContext(m_hProv, 0);
}
#else
#include "md5.c"
// TODO: Implement/link base64_decode Linux
static void platform_init(void) { }
static void platform_exit(void) { }
char *urldecode(char *pszData)
{
    // TODO, FIXME: Implement
    return strdup(pszData);
}
#endif

/****************************************
 * Tables                               *
 ****************************************/
unsigned char hash_tbl[] =
{
    0xD2, 0x8A, 0x81, 0x66, 0x90, 0xDE, 0x49, 0x98, 0x90, 0xDE,
    0x49, 0x98, 0x94, 0xB1, 0x06, 0x0B, 0xA8, 0xF5, 0xED, 0xAF,
    0x3E, 0xC9, 0x8A, 0xB4, 0x1C, 0x90, 0x23, 0x2B, 0x48, 0x73,
    0x2D, 0x5B, 0x07, 0xE8, 0x03, 0x4D, 0x9C, 0x6E, 0x4C, 0xB0,
    0x16, 0x18, 0x93, 0x30, 0x84, 0x92, 0x9D, 0xBA, 0xD4, 0xDB,
    0x8C, 0xAB, 0x7F, 0xCE, 0x17, 0xDB, 0x7E, 0x50, 0xE3, 0x70,
    0x6D, 0xF5, 0x00, 0x93, 0xD4, 0xDB, 0x8C, 0xAB, 0xE9, 0x21,
    0xC6, 0x58, 0x6C, 0x52, 0x3D, 0x5F, 0x54, 0x4F, 0xEF, 0xD9,
    0x66, 0x10, 0xAF, 0xB4, 0x37, 0x39, 0x22, 0x83, 0x75, 0xAB,
    0x4A, 0xCB, 0xC1, 0xA5, 0x5F, 0xD6, 0xCE, 0xB9, 0xC7, 0xC6,
    0x5F, 0xA8, 0x1B, 0x92, 0xA2, 0xDD, 0x0F, 0xA0, 0x1C, 0x36,
    0x34, 0x21, 0x7C, 0x63, 0xBC, 0xA3, 0x95, 0xD9, 0x8F, 0x8C,
    0x55, 0xB7, 0x52, 0xA3, 0xC7, 0x6D, 0x5F, 0x88, 0x83, 0x72,
    0x5A, 0x45, 0x41, 0xA8, 0x80, 0x33, 0x80, 0xF1, 0xA3, 0x34,
    0x08, 0x0F, 0x80, 0x8E, 0xD9, 0x2D, 0x1D, 0x65, 0xC4, 0xB9,
    0x6A, 0x4C, 0x48, 0x5E, 0x19, 0x69, 0x90, 0x18, 0x91, 0xD5,
    0x82, 0x2F, 0x67, 0x61, 0xD3, 0x5E, 0x67, 0xF2, 0xF8, 0x84,
    0xDD, 0xB6, 0xDB, 0xD7, 0x8C, 0xD5, 0x7F, 0x7E, 0x43, 0x65,
    0xE2, 0x4B, 0xDA, 0xD1, 0x1A, 0xB1, 0xDD, 0x3A, 0x8C, 0x10,
    0xC2, 0x69, 0x5E, 0x87, 0x0A, 0x5B, 0x64, 0xDC, 0x0C, 0x1B,
    0x98, 0xF4, 0x03, 0x41, 0x00, 0x7C, 0x5E, 0x31, 0xBA, 0x0B,
    0xE5, 0x4E, 0x98, 0x51, 0xE2, 0x06, 0x74, 0x89, 0x3C, 0x53,
    0x23, 0xC1, 0xFB, 0xAB, 0x85, 0x8B, 0x58, 0xDB, 0x09, 0x92,
    0xE6, 0xD6, 0xF8, 0xFD, 0x46, 0x7C, 0xB4, 0x65, 0xF3, 0x29,
    0x8A, 0x0B, 0x63, 0x09, 0x61, 0x3D, 0xC9, 0x6B, 0x9B, 0xCE,
    0x45, 0x05, 0xC2, 0x3E, 0x8B, 0xC5, 0x7A, 0x07, 0xC2, 0x6A,
    0xD7, 0x72, 0x10, 0xDE, 0x3A, 0x1F, 0xC8, 0x26, 0xAB, 0xB1,
    0xFD, 0xE3, 0x55, 0xDD, 0x65, 0x5C, 0x10, 0x9E, 0x7C, 0x87,
    0x0C, 0x22, 0xF9, 0xC3, 0xE9, 0x4D, 0xAB, 0x9B
};

static void swap_param_chars(unsigned char *a1, unsigned char *a2)
{
    unsigned char c;

    c = *a1;
    *a1 = *a2;
    *a2 = c;
}

static void scramble_hash(unsigned char *pHash, int cbHash, unsigned char *pDest)
{
    int i, j;
    unsigned char c;

    for (i = 0; i < 256; i++) pDest[i] = i;
    *((unsigned short*)&pDest[i]) = 0;
    for (i = 0, j = 0, c = 0; i < 256; i++)
    {
        c += pDest[i] + pHash[j];
        swap_param_chars(&pDest[i], &pDest[c]);
        j = (j + 1) % cbHash;
    }
}

static void DecodeNascd(unsigned char *pszNascdDecoded, int cbNascdDecoded, unsigned char *pHash)
{
    int i;
    unsigned char c, d, *p, *q;
    if (cbNascdDecoded <= 0) return;

    c = pHash[256];
    d = pHash[257];
    for (i = 0; i < cbNascdDecoded; c++, i++)
    {
        p = &pHash[c + 1];
        q = &pHash[(unsigned char)(*p + d)];
        d += *p;
        swap_param_chars(p, q);
        pszNascdDecoded[i] ^= pHash[(unsigned char)(*p + *q)];
    }
    pHash[256] = c;
    pHash[257] = d;
}

void GenerateKey(unsigned char *pszNascdDecoded, int cbNascdDecoded, int dwNascv, int dwNasca)
{
    struct MD5Context md5;
    unsigned char hash[16], buf[258];

    MD5Init(&md5);
    if (dwNascv == 1 || dwNascv == 2)
        MD5Update(&md5, &hash_tbl[dwNasca % 256], 12);
    MD5Final(hash, &md5);

    scramble_hash(hash, 16, buf);
    DecodeNascd(pszNascdDecoded, cbNascdDecoded, buf);
}

/* Decode NAS values to string
 *
 * Parameters:
 *  pszResult - Buffer to fill with decding result
 *  dwNasvc   - Nascv value
 *  dwNascs   - Nasca value
 *  pszNascd  - Nascd string
 * Returns:
 *  TRUE on success, FALSE if Nascv is incorrect
 */
BOOL KeyFromNas(unsigned char *pszResult, int dwNascv, int dwNasca, char *pszNascd)
{
    unsigned long cbNascd;
    unsigned char *pszNascdDecoded;

    if (dwNascv > 2) return FALSE;
    if (dwNascv == 2)
    {
        char *pszDecoded = urldecode(pszNascd);
        pszNascdDecoded = base64_decode(pszDecoded, strlen(pszDecoded), &cbNascd);
        free(pszDecoded);
    }
    else
    {
        pszNascdDecoded = base64_decode(pszNascd, strlen(pszNascd), &cbNascd);
    }
    GenerateKey(pszNascdDecoded, cbNascd, dwNascv, dwNasca);
    memcpy(pszResult, pszNascdDecoded, cbNascd);
    free(pszNascdDecoded);
    return TRUE;
}

Sample usage (not using valid data here):

int main(int argc, char **argv)
{
    unsigned char szResult[512] = { 0 };
    platform_init();
    KeyFromNas(szResult, 2, 12950, "Id...");
    platform_exit();
        printf("%s", szResult);
        return 0;
}

Implementing this in python and adding it to the script is left as an exercise to the reader.

WeAreLegion999 commented 1 year ago

was this layer added on FileOpen v998?

leecher1337 commented 1 year ago

Not sure in which version it was added, but it's present in recent versions.

asi2233 commented 10 months ago

@leecher1337 Could you please update "ineptpdf_8.4.51.pyw" accordingly? I have a PDF from IHS that is displaying an error stating "cannot find decryption key". Thank you.

leecher1337 commented 10 months ago

Sorry, I'm unable to do this as it is written in python, you need to find someone capable of this strange programming language.