Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /* *****************************************************************************
- * pp20.dll v1.0.9.4 - decrunch PowerPacker encrypted data files with password
- * by Stuart Caie / Peace^Testaware - this software is in the Public Domain
- * *****************************************************************************
- *
- * Website: https://testaware.wordpress.com/
- *
- * Version history
- * 0.4 18-Sep-2003 : by Stuart Caie
- * - first basic release
- *
- * 1.0.9.1 12-Nov-2008 : by Peace^Testaware
- * - source adapted to Dev-C++ 4.9.9.2
- * - support for AMOS(Pro) PPbk format
- * - added ppDecrunchFile()
- * - added ppDecrunchMemory()
- * - added ppGetDecrunchSize()
- * - added ppGetCrunchMode()
- * - removed ppLoadData()
- * - changed PPERR_<CODE> to negative values
- * - improved PPMODE_<CODE> constants
- * - improved macro SwapLong(ptr)
- * - included example source for PureBasic
- *
- * 1.0.9.2 13-Nov-2008 : by Peace^Testaware
- * - ppDecrunch, ppDecrypt now subfunctions
- *
- * 1.0.9.3 16-Nov-2008 : by Peace^Testaware
- * - support for PowerPacker v1.x format (very old)
- *
- * 1.0.9.4 21-Nov-2008 : by Peace^Testaware
- * - added ppEncodeMemory
- * ****************************************************************************/
- #include "dll.h"
- #include <windows.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #define PPERR_OK (0) /* no error */
- #define PPERR_ARGS (-1) /* bad arguments to function */
- #define PPERR_OPEN (-2) /* error opening file */
- #define PPERR_READ (-3) /* error reading from file */
- #define PPERR_SEEK (-4) /* error seeking in file */
- #define PPERR_NOMEMORY (-5) /* out of memory */
- #define PPERR_DATAFORMAT (-6) /* error in data format */
- #define PPERR_PASSWORD (-7) /* bad or missing password */
- #define PPERR_DECRUNCH (-8) /* error decrunching data */
- #define PPMODE_PP11 (0x50503131)
- #define PPMODE_PP20 (0x50503230)
- #define PPMODE_PPBK (0x5050626B) /* AMOS PPbk Bank */
- #define PPMODE_PPLS (0x50504C53)
- #define PPMODE_PX20 (0x50583230)
- #define PP_READ_BITS(nbits, var) do { \
- bit_cnt = (nbits); (var) = 0; \
- while (bits_left < bit_cnt) { \
- if (buf < src) return 0; /* out of source bits */ \
- bit_buffer |= *--buf << bits_left; \
- bits_left += 8; \
- } \
- bits_left -= bit_cnt; \
- while (bit_cnt--) { \
- (var) = ((var) << 1) | (bit_buffer & 1); \
- bit_buffer >>= 1; \
- } \
- } while (0)
- #define PP_BYTE_OUT(byte) do { \
- if (out <= dest) return 0; /* output overflow */ \
- *--out = (byte); written++; \
- } while (0)
- #define SwapLong(ptr) ((ptr[0] << 24) | (ptr[1] << 16) | (ptr[2] << 8) | ptr[3])
- /* *****************************************************************************
- * SIZE = ppGetDecrunchSize(*src, src_len)
- * *****************************************************************************
- * calculates the decrunched size of crunched buffer
- * -----------------------------------------------------------------------------
- * APTR *src = buffer of PowerPacker crunched datas
- * DWORD src_len = size in bytes of *src
- * -----------------------------------------------------------------------------
- * SIZE = size of decrunched buffer, else #PPERR_<CODE>
- * ****************************************************************************/
- DLLIMPORT int ppGetDecrunchSize(unsigned char *src, unsigned int src_len)
- {
- int dest_len = PPERR_DATAFORMAT;
- unsigned int mode;
- if (!src || !src_len) return PPERR_ARGS;
- mode = SwapLong(src);
- if ((mode == PPMODE_PP11) || (mode == PPMODE_PP20) || (mode == PPMODE_PPBK) ||
- (mode == PPMODE_PPLS) || (mode == PPMODE_PX20)) {
- dest_len = (src[src_len-4] << 16) | (src[src_len-3] << 8) | src[src_len-2]; }
- return dest_len;
- }
- /* *****************************************************************************
- * MODE = ppGetCrunchMode(*src)
- * *****************************************************************************
- * returns the crunchmode of crunched buffer
- * -----------------------------------------------------------------------------
- * APTR *src = buffer of PowerPacker crunched datas
- * -----------------------------------------------------------------------------
- * MODE = #PPMODE_<CODE> detected format
- * ****************************************************************************/
- DLLIMPORT int ppGetCrunchMode(unsigned char *src)
- {
- int mode;
- if (src == NULL) return PPERR_ARGS;
- /* detect format, decrypt if necessary */
- switch SwapLong(src) {
- case PPMODE_PP11: mode = PPMODE_PP11; break; /* PP11 */
- case PPMODE_PP20: mode = PPMODE_PP20; break; /* PP20 */
- case PPMODE_PPBK: mode = PPMODE_PPBK; break; /* PPbk */
- case PPMODE_PPLS: mode = PPMODE_PPLS; break; /* PPLS */
- case PPMODE_PX20: mode = PPMODE_PX20; break; /* PX20 */
- default:
- mode = PPERR_DATAFORMAT;
- }
- return mode;
- }
- /* *****************************************************************************
- * ERR = ppDecrunchMemory(*src, *dest, src_len, dest_len [,password])
- * *****************************************************************************
- * decrunch PowerPacker crunched buffer, also encrypt by given password
- * -----------------------------------------------------------------------------
- * APTR *src = buffer of PowerPacker crunched datas
- * APTR *dest = buffer to store encrypted/decrunched datas
- * DWORD src_len = size in bytes of *src
- * DWORD dest_len = size in bytes of decrunched buffer (=ppGetDecrunchSize())
- * CHAR password = Password (max. 16 chars only!) to encrypt datas in *src
- * -----------------------------------------------------------------------------
- * ERR = #PPERR_OK -> buffer decrunched
- * ****************************************************************************/
- DLLIMPORT int ppDecrunchMemory(unsigned char *src, unsigned char *dest,
- unsigned int src_len, unsigned int dest_len, unsigned char *password)
- {
- int err = PPERR_OK, eff;
- if (!src || !dest || !src_len || !dest_len) return PPERR_ARGS;
- /* detect format, decrypt if necessary */
- switch SwapLong(src) {
- case PPMODE_PP11: eff = 4; break; /* PP11 */
- case PPMODE_PP20: eff = 4; break; /* PP20 */
- case PPMODE_PPBK: eff = 20; break; /* PPbk */
- case PPMODE_PPLS: eff = 8; break; /* PPLS */
- case PPMODE_PX20: eff = 6; /* PX20 */
- if (!password || (ppCalcChecksum(password) != ((src[4]<<8)|src[5])))
- err = PPERR_PASSWORD;
- else
- ppDecrypt(&src[10], src_len-14, ppCalcPasskey(password));
- break;
- default:
- err = PPERR_DATAFORMAT;
- }
- if (err) { return err; }
- if (!ppDecrunch(&src[eff], dest, src_len-(eff+8), dest_len)) {
- err = PPERR_DECRUNCH; }
- return err;
- }
- /* *****************************************************************************
- * ERR = ppEncodeMemory(*src, *dest, src_len, dest_len, passkey [,*restore])
- * *****************************************************************************
- * encrypt and decrunch crunched buffer by given passkey
- * -----------------------------------------------------------------------------
- * APTR *src = buffer of PowerPacker encrypted PX20 datas
- * APTR *dest = buffer to copy encrypted/decrunched datas
- * DWORD src_len = size in bytes of *src
- * DWORD dest_len = size in bytes of decrunched buffer (=ppGetDecrunchSize())
- * ULONG passkey = 32 bit-key to encrypt datas in *src
- * APTR *restore = optional: clone of *src to restore buffer if wrong passkey
- * -----------------------------------------------------------------------------
- * ERR = #PPERR_OK -> all done
- * ****************************************************************************/
- DLLIMPORT int ppEncodeMemory(unsigned char *src, unsigned char *dest,
- unsigned int src_len, unsigned int dest_len,
- unsigned int passkey, unsigned char *restore)
- {
- int err = PPERR_OK, eff;
- if (!src || !dest || !src_len || !dest_len) return PPERR_ARGS;
- /* detect format, only for encrypted data (PX20) */
- switch SwapLong(src) {
- case PPMODE_PX20: eff = 6; /* PX20 */
- passkey &= 0xFFFFFFFF;
- ppDecrypt(&src[10], src_len-14, passkey);
- break;
- default:
- err = PPERR_DATAFORMAT;
- }
- /* error: no encrypted datas in *src */
- if (err) { return err; }
- if (!ppDecrunch(&src[eff], dest, src_len-(eff+8), dest_len)) {
- /* if restore buffer is set, copy into *src (recommended!) */
- if ((restore) != NULL) {
- memmove(src, restore, src_len);
- }
- err = PPERR_PASSWORD;
- }
- return err;
- }
- /* *****************************************************************************
- * ERR = ppDecrunchFile(*filename, *savename [,password])
- * *****************************************************************************
- * decrunch given file direct to a new file
- * -----------------------------------------------------------------------------
- * APTR *filename = name of file with PowerPacker packed datas
- * APTR *savename = filename to store encrypted/decrunched datas
- * CHAR password = optional: (max. 16 chars only!) to encrypt datas
- * -----------------------------------------------------------------------------
- * ERR = #PPERR_OK -> all done
- * ****************************************************************************/
- DLLIMPORT int ppDecrunchFile(unsigned char *filename, unsigned char *savename,
- unsigned char *password)
- {
- unsigned char *src = NULL, *dest, *amos;
- unsigned int srclen, destlen;
- int err = PPERR_OK, eff;
- FILE *fh;
- HANDLE hFile;
- if (!filename || !savename) return PPERR_ARGS;
- /* open file, find out srclen, allocate src and read file */
- if ((fh = fopen(filename, "rb"))) {
- if ((fseek(fh, 0, SEEK_END) == 0) &&
- (srclen = (unsigned int) ftell(fh)) &&
- (fseek(fh, 0, SEEK_SET) == 0))
- {
- if ((src = malloc(srclen))) {
- if (fread(src, 1, srclen, fh) != srclen) {
- free(src); err = PPERR_READ;
- }
- }
- else err = PPERR_NOMEMORY;
- }
- else err = PPERR_SEEK;
- fclose(fh);
- }
- else err = PPERR_OPEN;
- if (err) return err;
- fclose(fh);
- /* detect format, decrypt if necessary */
- switch SwapLong(src) {
- case PPMODE_PP11: eff = 4; break; /* PP11 */
- case PPMODE_PP20: eff = 4; break; /* PP20 */
- case PPMODE_PPBK: eff = 20; break; /* PPbk */
- case PPMODE_PPLS: eff = 8; break; /* PPLS */
- case PPMODE_PX20: eff = 6; /* PX20 */
- if (!password || (ppCalcChecksum(password) != ((src[4]<<8)|src[5])))
- err = PPERR_PASSWORD;
- else
- ppDecrypt(&src[10], srclen-14, ppCalcPasskey(password));
- break;
- default:
- err = PPERR_DATAFORMAT;
- }
- if (err) {
- free(src);
- return err;
- }
- /* allocate memory for decrunch buffer, then decrunch */
- destlen = (src[srclen-4] << 16) | (src[srclen-3] << 8) | src[srclen-2];
- if ((dest = malloc(destlen))) {
- if (!ppDecrunch(&src[eff], dest, srclen-(eff+8), destlen))
- err = PPERR_DECRUNCH;
- else
- hFile = CreateFile(savename, GENERIC_WRITE, 0, 0, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
- if (hFile != INVALID_HANDLE_VALUE) {
- switch SwapLong(src) {
- case PPMODE_PPBK: eff = 8; break; /* AMOS PPbk Bank = 8 Bytes ID String */
- default:
- eff = 0;
- }
- DWORD dwWritten;
- if (WriteFile(hFile, &dest[eff], destlen-eff, &dwWritten, NULL)) {
- if ((destlen-eff) != (dwWritten)) { err = PPERR_DECRUNCH; }
- }
- CloseHandle(hFile);
- }
- }
- if (src) { free(src); }
- if (dest) { free(dest); }
- return err;
- }
- /* *****************************************************************************
- * CKSUM = ppCalcChecksum(password)
- * *****************************************************************************
- * calculate a 16 bit checksum of given password, needed to control PX20 cksum
- * -----------------------------------------------------------------------------
- * CHAR password = max. 16 chars
- * -----------------------------------------------------------------------------
- * CKSUM = 16 bit checksum of password
- * ****************************************************************************/
- DLLIMPORT int ppCalcChecksum(unsigned char *password)
- {
- unsigned int cksum = 0;
- unsigned char c, shift;
- /* for each byte in the password */
- while ((c = *password++)) {
- /* barrel-shift the 16 bit checksum right by [c] bits */
- shift = c & 0x0F;
- if (shift) cksum = (cksum >> shift) | (cksum << (16-shift));
- /* add c to the cksum, with 16 bit wrap */
- cksum = (cksum + c) & 0xFFFF;
- }
- return cksum;
- }
- /* *****************************************************************************
- * PWKEY = ppCalcPasskey(password)
- * *****************************************************************************
- * calculate a 32 bit checksum of given password, needed to crack crypted buffer
- * -----------------------------------------------------------------------------
- * CHAR password = max. 16 chars
- * -----------------------------------------------------------------------------
- * PWKEY = 32 bit passkey of password
- * ****************************************************************************/
- DLLIMPORT int ppCalcPasskey(unsigned char *password)
- {
- unsigned int key = 0;
- unsigned char c;
- /* for each byte in the password */
- while ((c = *password++)) {
- /* rotate 32 bit key left by one bit */
- key = (key << 1) | (key >> (32-1));
- key &= 0xFFFFFFFF;
- /* add c to the key, with 32 bit wrap */
- key = (key + c) & 0xFFFFFFFF;
- /* swap lower and upper 16 bits */
- key = (key << 16) | (key >> 16);
- key &= 0xFFFFFFFF;
- }
- return key;
- }
- /* *****************************************************************************
- * INT ppDecrunch(*src, *dest, src_len, dest_len)
- * *****************************************************************************
- * intern: 1 all decrunched, 0 = error occured
- * -----------------------------------------------------------------------------
- * APTR *src = buffer of PowerPacker encrypted PX20 datas
- * APTR *dest = buffer to copy encrypted/decrunched datas
- * DWORD src_len = size in bytes of *src
- * DWORD dest_len = size in bytes of decrunched buffer
- * ****************************************************************************/
- int ppDecrunch(unsigned char *src, unsigned char *dest, unsigned int src_len,
- unsigned int dest_len)
- {
- unsigned char *buf, *out, *dest_end, *off_lens, bits_left = 0, bit_cnt;
- unsigned int bit_buffer = 0, x, todo, offbits, offset, written = 0;
- if (src == NULL || dest == NULL) return 0;
- /* set up input and output pointers */
- off_lens = src; src = &src[4];
- buf = &src[src_len];
- out = dest_end = &dest[dest_len];
- /* skip the first few bits */
- PP_READ_BITS(src[src_len + 3], x);
- /* while there are input bits left */
- while (written < dest_len)
- {
- PP_READ_BITS(1, x);
- if (x == 0)
- {
- /* bit==0: literal, then match. bit==1: just match */
- todo = 1; do { PP_READ_BITS(2, x); todo += x; } while (x == 3);
- while (todo--) { PP_READ_BITS(8, x); PP_BYTE_OUT(x); }
- /* should we end decoding on a literal, break out of the main loop */
- if (written == dest_len) break;
- }
- /* match: read 2 bits for initial offset bitlength / match length */
- PP_READ_BITS(2, x);
- offbits = off_lens[x];
- todo = x+2;
- if (x == 3) {
- PP_READ_BITS(1, x);
- if (x == 0) offbits = 7;
- PP_READ_BITS(offbits, offset);
- do { PP_READ_BITS(3, x); todo += x; } while (x == 7); }
- else {
- PP_READ_BITS(offbits, offset);
- }
- if (&out[offset] >= dest_end) return 0; /* match_overflow */
- while (todo--) { x = out[offset]; PP_BYTE_OUT(x); }
- }
- /* all output bytes written without error */
- return 1;
- }
- /* *****************************************************************************
- * VOID ppDecrypt(*data, len, key)
- * *****************************************************************************
- * intern: decrypt buffer with given passkey
- * -----------------------------------------------------------------------------
- * APTR *data = buffer of PowerPacker encrypted PX20 datas
- * DWORD len = size in bytes of *data
- * ULONG key = 32 bit key (=ppCalcPasskey())
- * ****************************************************************************/
- void ppDecrypt(unsigned char *data, unsigned int len, unsigned int key)
- {
- unsigned char k0 = (key >> 24) & 0xFF;
- unsigned char k1 = (key >> 16) & 0xFF;
- unsigned char k2 = (key >> 8) & 0xFF;
- unsigned char k3 = (key ) & 0xFF;
- len = ((len + 3) >> 2) - 1;
- /* to replicate unofficial powerpacker.library v37.3 bug, uncomment line */
- len &= 0xFFFF;
- /* XOR data with key */
- do {
- *data++ ^= k0;
- *data++ ^= k1;
- *data++ ^= k2;
- *data++ ^= k3;
- } while (len--);
- }
- BOOL APIENTRY DllMain (HINSTANCE hInst /* Library instance handle. */ ,
- DWORD reason /* Reason this function is being called. */ ,
- LPVOID reserved /* Not used. */ )
- {
- switch (reason)
- {
- case DLL_PROCESS_ATTACH:
- break;
- case DLL_PROCESS_DETACH:
- break;
- case DLL_THREAD_ATTACH:
- break;
- case DLL_THREAD_DETACH:
- break;
- }
- /* Returns TRUE on success, FALSE on failure */
- return TRUE;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement