Testaware

pp20.dll v1.0.9.4 (x86)

Aug 27th, 2017
212
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. /* *****************************************************************************
  2.  * pp20.dll v1.0.9.4 - decrunch PowerPacker encrypted data files with password
  3.  * by Stuart Caie / Peace^Testaware - this software is in the Public Domain
  4.  * *****************************************************************************
  5.  *
  6.  * Website: https://testaware.wordpress.com/
  7.  *
  8.  * Version history
  9.  * 0.4       18-Sep-2003 : by Stuart Caie
  10.  *                       - first basic release
  11.  *
  12.  * 1.0.9.1   12-Nov-2008 : by Peace^Testaware
  13.  *                       - source adapted to Dev-C++ 4.9.9.2
  14.  *                       - support for AMOS(Pro) PPbk format
  15.  *                       - added ppDecrunchFile()
  16.  *                       - added ppDecrunchMemory()
  17.  *                       - added ppGetDecrunchSize()
  18.  *                       - added ppGetCrunchMode()
  19.  *                       - removed ppLoadData()
  20.  *                       - changed PPERR_<CODE> to negative values
  21.  *                       - improved PPMODE_<CODE> constants
  22.  *                       - improved macro SwapLong(ptr)
  23.  *                       - included example source for PureBasic
  24.  *
  25.  * 1.0.9.2   13-Nov-2008 : by Peace^Testaware
  26.  *                       - ppDecrunch, ppDecrypt now subfunctions
  27.  *
  28.  * 1.0.9.3   16-Nov-2008 : by Peace^Testaware
  29.  *                       - support for PowerPacker v1.x format (very old)
  30.  *
  31.  * 1.0.9.4   21-Nov-2008 : by Peace^Testaware
  32.  *                       - added ppEncodeMemory
  33.  * ****************************************************************************/
  34.  
  35. #include "dll.h"
  36. #include <windows.h>
  37. #include <stdio.h>
  38. #include <stdlib.h>
  39. #include <string.h>
  40.  
  41. #define PPERR_OK           (0)  /* no error                  */
  42. #define PPERR_ARGS         (-1) /* bad arguments to function */
  43. #define PPERR_OPEN         (-2) /* error opening file        */
  44. #define PPERR_READ         (-3) /* error reading from file   */
  45. #define PPERR_SEEK         (-4) /* error seeking in file     */
  46. #define PPERR_NOMEMORY     (-5) /* out of memory             */
  47. #define PPERR_DATAFORMAT   (-6) /* error in data format      */
  48. #define PPERR_PASSWORD     (-7) /* bad or missing password   */
  49. #define PPERR_DECRUNCH     (-8) /* error decrunching data    */
  50.  
  51. #define PPMODE_PP11        (0x50503131)
  52. #define PPMODE_PP20        (0x50503230)
  53. #define PPMODE_PPBK        (0x5050626B)  /* AMOS PPbk Bank   */
  54. #define PPMODE_PPLS        (0x50504C53)
  55. #define PPMODE_PX20        (0x50583230)
  56.  
  57. #define PP_READ_BITS(nbits, var) do {                            \
  58.   bit_cnt = (nbits); (var) = 0;                                  \
  59.   while (bits_left < bit_cnt) {                                  \
  60.     if (buf < src) return 0; /* out of source bits */            \
  61.     bit_buffer |= *--buf << bits_left;                           \
  62.     bits_left += 8;                                              \
  63.   }                                                              \
  64.   bits_left -= bit_cnt;                                          \
  65.   while (bit_cnt--) {                                            \
  66.     (var) = ((var) << 1) | (bit_buffer & 1);                     \
  67.     bit_buffer >>= 1;                                            \
  68.   }                                                              \
  69. } while (0)
  70.  
  71. #define PP_BYTE_OUT(byte) do {                                   \
  72.   if (out <= dest) return 0; /* output overflow */               \
  73.   *--out = (byte); written++;                                    \
  74. } while (0)
  75.  
  76. #define SwapLong(ptr) ((ptr[0] << 24) | (ptr[1] << 16) | (ptr[2] << 8) | ptr[3])
  77.  
  78.  
  79. /* *****************************************************************************
  80.  * SIZE = ppGetDecrunchSize(*src, src_len)
  81.  * *****************************************************************************
  82.  * calculates the decrunched size of crunched buffer
  83.  * -----------------------------------------------------------------------------
  84.  * APTR  *src    = buffer of PowerPacker crunched datas
  85.  * DWORD src_len = size in bytes of *src
  86.  * -----------------------------------------------------------------------------
  87.  * SIZE = size of decrunched buffer, else #PPERR_<CODE>
  88.  * ****************************************************************************/
  89. DLLIMPORT int ppGetDecrunchSize(unsigned char *src, unsigned int src_len)
  90. {
  91.           int dest_len = PPERR_DATAFORMAT;
  92.           unsigned int mode;
  93.  
  94.           if (!src || !src_len) return PPERR_ARGS;
  95.  
  96.           mode   = SwapLong(src);
  97.  
  98.           if ((mode == PPMODE_PP11) || (mode == PPMODE_PP20) || (mode == PPMODE_PPBK) ||
  99.              (mode == PPMODE_PPLS) || (mode == PPMODE_PX20)) {
  100.              dest_len = (src[src_len-4] << 16) | (src[src_len-3] << 8) | src[src_len-2]; }
  101.  
  102.           return dest_len;
  103. }
  104.  
  105. /* *****************************************************************************
  106.  * MODE = ppGetCrunchMode(*src)
  107.  * *****************************************************************************
  108.  * returns the crunchmode of crunched buffer
  109.  * -----------------------------------------------------------------------------
  110.  * APTR *src = buffer of PowerPacker crunched datas
  111.  * -----------------------------------------------------------------------------
  112.  * MODE = #PPMODE_<CODE> detected format
  113.  * ****************************************************************************/
  114. DLLIMPORT int ppGetCrunchMode(unsigned char *src)
  115. {
  116.           int mode;
  117.  
  118.           if (src == NULL) return PPERR_ARGS;
  119.  
  120.           /* detect format, decrypt if necessary */
  121.           switch SwapLong(src) {
  122.                  case PPMODE_PP11: mode = PPMODE_PP11; break; /* PP11 */
  123.                  case PPMODE_PP20: mode = PPMODE_PP20; break; /* PP20 */
  124.                  case PPMODE_PPBK: mode = PPMODE_PPBK; break; /* PPbk */
  125.                  case PPMODE_PPLS: mode = PPMODE_PPLS; break; /* PPLS */
  126.                  case PPMODE_PX20: mode = PPMODE_PX20; break; /* PX20 */
  127.                  default:
  128.                          mode = PPERR_DATAFORMAT;
  129.                          }
  130.           return mode;
  131. }
  132.  
  133. /* *****************************************************************************
  134.  * ERR = ppDecrunchMemory(*src, *dest, src_len, dest_len [,password])
  135.  * *****************************************************************************
  136.  * decrunch PowerPacker crunched buffer, also encrypt by given password
  137.  * -----------------------------------------------------------------------------
  138.  * APTR  *src     = buffer of PowerPacker crunched datas
  139.  * APTR  *dest    = buffer to store encrypted/decrunched datas
  140.  * DWORD src_len  = size in bytes of *src
  141.  * DWORD dest_len = size in bytes of decrunched buffer (=ppGetDecrunchSize())
  142.  * CHAR  password = Password (max. 16 chars only!) to encrypt datas in *src
  143.  * -----------------------------------------------------------------------------
  144.  * ERR = #PPERR_OK -> buffer decrunched
  145.  * ****************************************************************************/
  146. DLLIMPORT int ppDecrunchMemory(unsigned char *src, unsigned char *dest,
  147.           unsigned int src_len, unsigned int dest_len, unsigned char *password)
  148. {
  149.           int err = PPERR_OK, eff;
  150.  
  151.           if (!src || !dest || !src_len || !dest_len) return PPERR_ARGS;
  152.  
  153.           /* detect format, decrypt if necessary */
  154.           switch SwapLong(src) {
  155.                  case PPMODE_PP11: eff =  4; break; /* PP11 */
  156.                  case PPMODE_PP20: eff =  4; break; /* PP20 */
  157.                  case PPMODE_PPBK: eff = 20; break; /* PPbk */
  158.                  case PPMODE_PPLS: eff =  8; break; /* PPLS */
  159.                  case PPMODE_PX20: eff =  6;        /* PX20 */
  160.                       if (!password || (ppCalcChecksum(password) != ((src[4]<<8)|src[5])))
  161.                          err = PPERR_PASSWORD;
  162.                       else
  163.                          ppDecrypt(&src[10], src_len-14, ppCalcPasskey(password));
  164.                          break;
  165.                  default:
  166.                          err = PPERR_DATAFORMAT;
  167.                          }
  168.  
  169.           if (err) { return err; }
  170.  
  171.           if (!ppDecrunch(&src[eff], dest, src_len-(eff+8), dest_len)) {
  172.              err = PPERR_DECRUNCH; }
  173.  
  174.           return  err;
  175. }
  176.  
  177. /* *****************************************************************************
  178.  * ERR = ppEncodeMemory(*src, *dest, src_len, dest_len, passkey [,*restore])
  179.  * *****************************************************************************
  180.  * encrypt and decrunch crunched buffer by given passkey
  181.  * -----------------------------------------------------------------------------
  182.  * APTR  *src     = buffer of PowerPacker encrypted PX20 datas
  183.  * APTR  *dest    = buffer to copy encrypted/decrunched datas
  184.  * DWORD src_len  = size in bytes of *src
  185.  * DWORD dest_len = size in bytes of decrunched buffer (=ppGetDecrunchSize())
  186.  * ULONG passkey  = 32 bit-key to encrypt datas in *src
  187.  * APTR  *restore = optional: clone of *src to restore buffer if wrong passkey
  188.  * -----------------------------------------------------------------------------
  189.  * ERR = #PPERR_OK -> all done
  190.  * ****************************************************************************/
  191. DLLIMPORT int ppEncodeMemory(unsigned char *src, unsigned char *dest,
  192.           unsigned int src_len, unsigned int dest_len,
  193.           unsigned int passkey, unsigned char *restore)
  194. {
  195.           int err = PPERR_OK, eff;
  196.  
  197.           if (!src || !dest || !src_len || !dest_len) return PPERR_ARGS;
  198.  
  199.           /* detect format, only for encrypted data (PX20) */
  200.           switch SwapLong(src) {
  201.                  case PPMODE_PX20: eff =  6;        /* PX20 */
  202.                       passkey &= 0xFFFFFFFF;
  203.                       ppDecrypt(&src[10], src_len-14, passkey);
  204.                       break;
  205.                  default:
  206.                          err = PPERR_DATAFORMAT;
  207.                          }
  208.  
  209.           /* error: no encrypted datas in *src */
  210.           if (err) { return err; }
  211.  
  212.           if (!ppDecrunch(&src[eff], dest, src_len-(eff+8), dest_len)) {
  213.              /* if restore buffer is set, copy into *src (recommended!) */
  214.              if ((restore) != NULL) {
  215.                            memmove(src, restore, src_len);
  216.                            }
  217.              err = PPERR_PASSWORD;
  218.              }
  219.  
  220.           return  err;
  221. }
  222.  
  223. /* *****************************************************************************
  224.  * ERR = ppDecrunchFile(*filename, *savename [,password])
  225.  * *****************************************************************************
  226.  * decrunch given file direct to a new file
  227.  * -----------------------------------------------------------------------------
  228.  * APTR *filename = name of file with PowerPacker packed datas
  229.  * APTR *savename = filename to store encrypted/decrunched datas
  230.  * CHAR password  = optional: (max. 16 chars only!) to encrypt datas
  231.  * -----------------------------------------------------------------------------
  232.  * ERR = #PPERR_OK -> all done
  233.  * ****************************************************************************/
  234. DLLIMPORT int ppDecrunchFile(unsigned char *filename, unsigned char *savename,
  235.           unsigned char *password)
  236. {
  237.           unsigned char *src = NULL, *dest, *amos;
  238.           unsigned int srclen, destlen;
  239.           int err = PPERR_OK, eff;
  240.           FILE *fh;
  241.           HANDLE hFile;
  242.  
  243.           if (!filename || !savename) return PPERR_ARGS;
  244.  
  245.           /* open file, find out srclen, allocate src and read file */
  246.           if ((fh = fopen(filename, "rb"))) {
  247.                if ((fseek(fh, 0, SEEK_END) == 0) &&
  248.                   (srclen = (unsigned int) ftell(fh)) &&
  249.                   (fseek(fh, 0, SEEK_SET) == 0))
  250.                   {
  251.                   if ((src = malloc(srclen))) {
  252.                      if (fread(src, 1, srclen, fh) != srclen) {
  253.                         free(src); err = PPERR_READ;
  254.                         }
  255.                      }
  256.                      else err = PPERR_NOMEMORY;
  257.                   }
  258.                   else err = PPERR_SEEK;
  259.                        fclose(fh);
  260.                }
  261.                else err = PPERR_OPEN;
  262.                      
  263.                if (err) return err;
  264.  
  265.                fclose(fh);
  266.  
  267.                /* detect format, decrypt if necessary */
  268.                switch SwapLong(src) {
  269.                       case PPMODE_PP11: eff =  4; break; /* PP11 */
  270.                       case PPMODE_PP20: eff =  4; break; /* PP20 */
  271.                       case PPMODE_PPBK: eff = 20; break; /* PPbk */
  272.                       case PPMODE_PPLS: eff =  8; break; /* PPLS */
  273.                       case PPMODE_PX20: eff =  6;        /* PX20 */
  274.                            if (!password || (ppCalcChecksum(password) != ((src[4]<<8)|src[5])))
  275.                               err = PPERR_PASSWORD;
  276.                            else
  277.                                ppDecrypt(&src[10], srclen-14, ppCalcPasskey(password));
  278.                                break;
  279.                       default:
  280.                               err = PPERR_DATAFORMAT;
  281.                               }
  282.  
  283.                if (err) {
  284.                   free(src);
  285.                   return err;
  286.                }
  287.  
  288.                /* allocate memory for decrunch buffer, then decrunch */
  289.                destlen = (src[srclen-4] << 16) | (src[srclen-3] << 8) | src[srclen-2];
  290.                if ((dest = malloc(destlen))) {
  291.                   if (!ppDecrunch(&src[eff], dest, srclen-(eff+8), destlen))
  292.                      err = PPERR_DECRUNCH;
  293.                   else
  294.                      hFile = CreateFile(savename, GENERIC_WRITE, 0, 0, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
  295.                      if (hFile != INVALID_HANDLE_VALUE) {
  296.                         switch SwapLong(src) {
  297.                                case   PPMODE_PPBK: eff = 8; break; /* AMOS PPbk Bank = 8 Bytes ID String */
  298.                         default:
  299.                                 eff = 0;
  300.                                 }
  301.                         DWORD dwWritten;
  302.                         if (WriteFile(hFile, &dest[eff], destlen-eff, &dwWritten, NULL)) {
  303.                            if ((destlen-eff) != (dwWritten)) { err = PPERR_DECRUNCH; }
  304.                            }
  305.                         CloseHandle(hFile);
  306.                      }
  307.                   }
  308.  
  309.                if (src) { free(src); }
  310.                if (dest) { free(dest); }
  311.  
  312.           return err;
  313. }
  314.  
  315. /* *****************************************************************************
  316.  * CKSUM = ppCalcChecksum(password)
  317.  * *****************************************************************************
  318.  * calculate a 16 bit checksum of given password, needed to control PX20 cksum
  319.  * -----------------------------------------------------------------------------
  320.  * CHAR password = max. 16 chars
  321.  * -----------------------------------------------------------------------------
  322.  * CKSUM = 16 bit checksum of password
  323.  * ****************************************************************************/
  324. DLLIMPORT int ppCalcChecksum(unsigned char *password)
  325. {
  326.           unsigned int cksum = 0;
  327.           unsigned char c, shift;
  328.  
  329.           /* for each byte in the password */
  330.           while ((c = *password++)) {
  331.                 /* barrel-shift the 16 bit checksum right by [c] bits */
  332.                 shift = c & 0x0F;
  333.                 if (shift) cksum = (cksum >> shift) | (cksum << (16-shift));
  334.                    /* add c to the cksum, with 16 bit wrap */
  335.                    cksum = (cksum + c) & 0xFFFF;
  336.           }
  337.  
  338.           return cksum;
  339. }
  340.  
  341. /* *****************************************************************************
  342.  * PWKEY = ppCalcPasskey(password)
  343.  * *****************************************************************************
  344.  * calculate a 32 bit checksum of given password, needed to crack crypted buffer
  345.  * -----------------------------------------------------------------------------
  346.  * CHAR password = max. 16 chars
  347.  * -----------------------------------------------------------------------------
  348.  * PWKEY = 32 bit passkey of password
  349.  * ****************************************************************************/
  350. DLLIMPORT int ppCalcPasskey(unsigned char *password)
  351. {
  352.           unsigned int key = 0;
  353.           unsigned char c;
  354.  
  355.           /* for each byte in the password */
  356.           while ((c = *password++)) {
  357.                 /* rotate 32 bit key left by one bit */
  358.                 key = (key << 1) | (key >> (32-1));
  359.                 key &= 0xFFFFFFFF;
  360.  
  361.                 /* add c to the key, with 32 bit wrap */
  362.                 key = (key + c) & 0xFFFFFFFF;
  363.  
  364.                 /* swap lower and upper 16 bits */
  365.                 key = (key << 16) | (key >> 16);
  366.                 key &= 0xFFFFFFFF;
  367.           }
  368.  
  369.           return key;
  370. }
  371.  
  372. /* *****************************************************************************
  373.  * INT ppDecrunch(*src, *dest, src_len, dest_len)
  374.  * *****************************************************************************
  375.  * intern: 1 all decrunched, 0 = error occured
  376.  * -----------------------------------------------------------------------------
  377.  * APTR  *src     = buffer of PowerPacker encrypted PX20 datas
  378.  * APTR  *dest    = buffer to copy encrypted/decrunched datas
  379.  * DWORD src_len  = size in bytes of *src
  380.  * DWORD dest_len = size in bytes of decrunched buffer
  381.  * ****************************************************************************/
  382. int ppDecrunch(unsigned char *src, unsigned char *dest, unsigned int src_len,
  383.                unsigned int dest_len)
  384. {
  385.           unsigned char *buf, *out, *dest_end, *off_lens, bits_left = 0, bit_cnt;
  386.           unsigned int bit_buffer = 0, x, todo, offbits, offset, written = 0;
  387.  
  388.           if (src == NULL || dest == NULL) return 0;
  389.  
  390.           /* set up input and output pointers */
  391.           off_lens = src; src = &src[4];
  392.           buf = &src[src_len];
  393.  
  394.           out = dest_end = &dest[dest_len];
  395.  
  396.           /* skip the first few bits */
  397.           PP_READ_BITS(src[src_len + 3], x);
  398.  
  399.           /* while there are input bits left */
  400.           while (written < dest_len)
  401.                 {
  402.                 PP_READ_BITS(1, x);
  403.                 if (x == 0)
  404.                    {
  405.                    /* bit==0: literal, then match. bit==1: just match */
  406.                    todo = 1; do { PP_READ_BITS(2, x); todo += x; } while (x == 3);
  407.                    while (todo--) { PP_READ_BITS(8, x); PP_BYTE_OUT(x); }
  408.  
  409.                    /* should we end decoding on a literal, break out of the main loop */
  410.                    if (written == dest_len) break;
  411.                    }
  412.  
  413.                 /* match: read 2 bits for initial offset bitlength / match length */
  414.                 PP_READ_BITS(2, x);
  415.                 offbits = off_lens[x];
  416.                 todo = x+2;
  417.                 if (x == 3) {
  418.                    PP_READ_BITS(1, x);
  419.                    if (x == 0) offbits = 7;
  420.                       PP_READ_BITS(offbits, offset);
  421.                       do { PP_READ_BITS(3, x); todo += x; } while (x == 7); }
  422.                    else {
  423.                       PP_READ_BITS(offbits, offset);
  424.                    }
  425.                    if (&out[offset] >= dest_end) return 0; /* match_overflow */
  426.                    while (todo--) { x = out[offset]; PP_BYTE_OUT(x); }
  427.                 }
  428.  
  429.           /* all output bytes written without error */
  430.           return 1;
  431. }
  432.  
  433. /* *****************************************************************************
  434.  * VOID ppDecrypt(*data, len, key)
  435.  * *****************************************************************************
  436.  * intern: decrypt buffer with given passkey
  437.  * -----------------------------------------------------------------------------
  438.  * APTR  *data = buffer of PowerPacker encrypted PX20 datas
  439.  * DWORD len   = size in bytes of *data
  440.  * ULONG key   = 32 bit key (=ppCalcPasskey())
  441.  * ****************************************************************************/
  442. void ppDecrypt(unsigned char *data, unsigned int len, unsigned int key)
  443. {
  444.           unsigned char k0 = (key >> 24) & 0xFF;
  445.           unsigned char k1 = (key >> 16) & 0xFF;
  446.           unsigned char k2 = (key >>  8) & 0xFF;
  447.           unsigned char k3 = (key      ) & 0xFF;
  448.  
  449.           len = ((len + 3) >> 2) - 1;
  450.  
  451.           /* to replicate unofficial powerpacker.library v37.3 bug, uncomment line */
  452.           len &= 0xFFFF;
  453.  
  454.           /* XOR data with key */
  455.           do {
  456.              *data++ ^= k0;
  457.              *data++ ^= k1;
  458.              *data++ ^= k2;
  459.              *data++ ^= k3;
  460.           } while (len--);
  461. }
  462.  
  463.  
  464. BOOL APIENTRY DllMain (HINSTANCE hInst     /* Library instance handle. */ ,
  465.                        DWORD reason        /* Reason this function is being called. */ ,
  466.                        LPVOID reserved     /* Not used. */ )
  467. {
  468.     switch (reason)
  469.     {
  470.       case DLL_PROCESS_ATTACH:
  471.         break;
  472.  
  473.       case DLL_PROCESS_DETACH:
  474.         break;
  475.  
  476.       case DLL_THREAD_ATTACH:
  477.         break;
  478.  
  479.       case DLL_THREAD_DETACH:
  480.         break;
  481.     }
  482.  
  483.     /* Returns TRUE on success, FALSE on failure */
  484.     return TRUE;
  485. }
RAW Paste Data