Skip to content

Commit

Permalink
enhancement: Improved DMS support
Browse files Browse the repository at this point in the history
Check DMS input buffer under/overflow. Improved encrypted DMS support, some DMS files decode correctly (valid CRC) with more than 1 key but only 1 key returns correct data.
  • Loading branch information
midwan committed Nov 8, 2023
1 parent f6e04c4 commit 1f02844
Show file tree
Hide file tree
Showing 11 changed files with 87 additions and 105 deletions.
64 changes: 40 additions & 24 deletions src/archivers/dms/pfile.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -399,48 +399,48 @@ static USHORT Process_Track(struct zfile *fi, struct zfile *fo, UCHAR *b1, UCHAR



static USHORT Unpack_Track_2(UCHAR *b1, UCHAR *b2, USHORT pklen2, USHORT unpklen, UCHAR cmode, UCHAR flags){
static USHORT Unpack_Track_2(UCHAR *b1, UCHAR *b2, USHORT pklen1, USHORT pklen2, USHORT unpklen, UCHAR cmode, UCHAR flags){
switch (cmode){
case 0:
/* No Compression */
memcpy(b2,b1,(size_t)unpklen);
break;
case 1:
/* Simple Compression */
if (Unpack_RLE(b1,b2,unpklen)) return ERR_BADDECR;
if (Unpack_RLE(b1,b2, pklen1,unpklen)) return ERR_BADDECR;
break;
case 2:
/* Quick Compression */
if (Unpack_QUICK(b1,b2,pklen2)) return ERR_BADDECR;
if (Unpack_RLE(b2,b1,unpklen)) return ERR_BADDECR;
if (Unpack_QUICK(b1,b2,pklen1,pklen2)) return ERR_BADDECR;
if (Unpack_RLE(b2,b1,pklen2,unpklen)) return ERR_BADDECR;
memcpy(b2,b1,(size_t)unpklen);
break;
case 3:
/* Medium Compression */
if (Unpack_MEDIUM(b1,b2,pklen2)) return ERR_BADDECR;
if (Unpack_RLE(b2,b1,unpklen)) return ERR_BADDECR;
if (Unpack_MEDIUM(b1,b2,pklen1,pklen2)) return ERR_BADDECR;
if (Unpack_RLE(b2,b1,pklen2,unpklen)) return ERR_BADDECR;
memcpy(b2,b1,(size_t)unpklen);
break;
case 4:
/* Deep Compression */
if (Unpack_DEEP(b1,b2,pklen2)) return ERR_BADDECR;
if (Unpack_RLE(b2,b1,unpklen)) return ERR_BADDECR;
if (Unpack_DEEP(b1,b2,pklen1,pklen2)) return ERR_BADDECR;
if (Unpack_RLE(b2,b1,pklen2,unpklen)) return ERR_BADDECR;
memcpy(b2,b1,(size_t)unpklen);
break;
case 5:
case 6:
/* Heavy Compression */
if (cmode==5) {
/* Heavy 1 */
if (Unpack_HEAVY(b1,b2,flags & 7,pklen2)) return ERR_BADDECR;
if (Unpack_HEAVY(b1,b2,flags & 7,pklen1,pklen2)) return ERR_BADDECR;
} else {
/* Heavy 2 */
if (Unpack_HEAVY(b1,b2,flags | 8,pklen2)) return ERR_BADDECR;
if (Unpack_HEAVY(b1,b2,flags | 8,pklen1,pklen2)) return ERR_BADDECR;
}
if (flags & 4) {
memset(b1,0,unpklen);
/* Unpack with RLE only if this flag is set */
if (Unpack_RLE(b2,b1,unpklen)) return ERR_BADDECR;
if (Unpack_RLE(b2,b1,pklen2,unpklen)) return ERR_BADDECR;
memcpy(b2,b1,(size_t)unpklen);
}
break;
Expand Down Expand Up @@ -471,13 +471,14 @@ static USHORT Unpack_Track(UCHAR *b1, UCHAR *b2, USHORT pklen2, USHORT unpklen,
static USHORT pass;
int maybeencrypted;
int pwrounds;
UCHAR *tmp;
USHORT prevpass = 0;
int firstpass = -1;
UCHAR *tmp, *tmp_dms_text;
USHORT prevpass = pass;

if (passfound) {
if (number != 80)
dms_decrypt(b1, pklen1, b1);
r = Unpack_Track_2(b1, b2, pklen2, unpklen, cmode, flags);
r = Unpack_Track_2(b1, b2, pklen1, pklen2, unpklen, cmode, flags);
if (r == NO_PROBLEM) {
if (usum1 == dms_Calc_CheckSum(b2,(ULONG)unpklen))
return NO_PROBLEM;
Expand All @@ -490,19 +491,27 @@ static USHORT Unpack_Track(UCHAR *b1, UCHAR *b2, USHORT pklen2, USHORT unpklen,
passretries--;
pwrounds = 0;
maybeencrypted = 0;
tmp = (unsigned char*)malloc (pklen1);
tmp = xmalloc(UCHAR, pklen1);
tmp_dms_text = xmalloc(UCHAR, 0x3fc8);
memcpy (tmp, b1, pklen1);
memset(b2, 0, unpklen);
memcpy(tmp_dms_text, dms_text, 0x3fc8);
for (;;) {
r = Unpack_Track_2(b1, b2, pklen2, unpklen, cmode, flags);
r = Unpack_Track_2(b1, b2, pklen1, pklen2, unpklen, cmode, flags);
if (r == NO_PROBLEM) {
if (usum1 == dms_Calc_CheckSum(b2,(ULONG)unpklen)) {
passfound = maybeencrypted;
if (passfound)
write_log (_T("DMS: decryption key = 0x%04X\n"), prevpass);
err = NO_PROBLEM;
pass = prevpass;
break;
// if bootblock does not have "DOS", check other keys too
if (number > 0 || firstpass == pass || (b2[0] == 'D' && b2[1] == 'O' && b2[2] == 'S')) {
err = NO_PROBLEM;
pass = prevpass;
break;
}
if (firstpass < 0) {
firstpass = pass;
}
}
}
if (number == 80 || !enc) {
Expand All @@ -515,13 +524,20 @@ static USHORT Unpack_Track(UCHAR *b1, UCHAR *b2, USHORT pklen2, USHORT unpklen,
pass++;
dms_decrypt(b1, pklen1, tmp);
pwrounds++;
if (pwrounds == 65536) {
err = ERR_CSUM;
passfound = 0;
break;
if (pwrounds >= 65536) {
if (firstpass < 0) {
err = ERR_CSUM;
passfound = 0;
break;
}
pass = firstpass;
PWDCRC = pass;
dms_decrypt(b1, pklen1, tmp);
}
memcpy(dms_text, tmp_dms_text, 0x3fc8);
}
free (tmp);
xfree(tmp_dms_text);
xfree(tmp);
return err;
}

Expand Down
38 changes: 11 additions & 27 deletions src/archivers/dms/u_deep.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,18 +16,14 @@
#include "u_deep.h"
#include "getbits.h"


INLINE USHORT DecodeChar(void);
INLINE USHORT DecodePosition(void);
INLINE void update(USHORT c);
static USHORT DecodeChar(void);
static USHORT DecodePosition(void);
static void update(USHORT c);
static void reconst(void);


USHORT dms_deep_text_loc;
int dms_init_deep_tabs=1;



#define DBITMASK 0x3fff /* uses 16Kb dictionary */

#define F 60 /* lookahead buffer size */
Expand All @@ -37,7 +33,6 @@ int dms_init_deep_tabs=1;
#define R (T - 1) /* position of root */
#define MAX_FREQ 0x8000 /* updates tree when the */


static USHORT freq[T + 1]; /* frequency table */

static USHORT prnt[T + N_CHAR]; /* pointers to parent nodes, except for the */
Expand All @@ -46,8 +41,6 @@ static USHORT prnt[T + N_CHAR]; /* pointers to parent nodes, except for the */

static USHORT son[T]; /* pointers to child nodes (son[], son[] + 1) */



static void Init_DEEP_Tabs(void){
USHORT i, j;

Expand All @@ -69,9 +62,7 @@ static void Init_DEEP_Tabs(void){
dms_init_deep_tabs = 0;
}



USHORT Unpack_DEEP(UCHAR *in, UCHAR *out, USHORT origsize){
USHORT Unpack_DEEP(UCHAR *in, UCHAR *out, USHORT pklen1, USHORT origsize){
USHORT i, j, c;
UCHAR *outend;

Expand All @@ -93,12 +84,13 @@ USHORT Unpack_DEEP(UCHAR *in, UCHAR *out, USHORT origsize){

dms_deep_text_loc = (USHORT)((dms_deep_text_loc+60) & DBITMASK);

return 0;
}

in += pklen1;
if (dms_indata == in + 2 || dms_indata == in + 1 || dms_indata == in + 0) return 0;

return 1;
}

INLINE USHORT DecodeChar(void){
static USHORT DecodeChar(void){
USHORT c;

c = son[R];
Expand All @@ -115,9 +107,7 @@ INLINE USHORT DecodeChar(void){
return c;
}



INLINE USHORT DecodePosition(void){
static USHORT DecodePosition(void){
USHORT i, j, c;

i = GETBITS(8); DROPBITS(8);
Expand All @@ -128,8 +118,6 @@ INLINE USHORT DecodePosition(void){
return (USHORT) (c | i) ;
}



/* reconstruction of tree */

static void reconst(void){
Expand Down Expand Up @@ -167,11 +155,9 @@ static void reconst(void){
}
}



/* increment frequency of given code by one, and update tree */

INLINE void update(USHORT c){
static void update(USHORT c){
USHORT i, j, k, l;

if (freq[R] == MAX_FREQ) {
Expand Down Expand Up @@ -203,5 +189,3 @@ INLINE void update(USHORT c){
}
} while ((c = prnt[c]) != 0); /* repeat up to root */
}


2 changes: 1 addition & 1 deletion src/archivers/dms/u_deep.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@


USHORT Unpack_DEEP(UCHAR *, UCHAR *, USHORT);
USHORT Unpack_DEEP(UCHAR *, UCHAR *, USHORT, USHORT);

extern int dms_init_deep_tabs;
extern USHORT dms_deep_text_loc;
Expand Down
44 changes: 17 additions & 27 deletions src/archivers/dms/u_heavy.cpp
Original file line number Diff line number Diff line change
@@ -1,21 +1,19 @@

/*
* xDMS v1.3 - Portable DMS archive unpacker - Public Domain
* Written by Andre Rodrigues de la Rocha <adlroc@usa.net>
*
* Lempel-Ziv-Huffman decompression functions used in Heavy 1 & 2
* compression modes. Based on LZH decompression functions from
* UNIX LHA made by Masaru Oki
*
*/

* xDMS v1.3 - Portable DMS archive unpacker - Public Domain
* Written by Andre Rodrigues de la Rocha <adlroc@usa.net>
*
* Lempel-Ziv-Huffman decompression functions used in Heavy 1 & 2
* compression modes. Based on LZH decompression functions from
* UNIX LHA made by Masaru Oki
*
*/

#include "cdata.h"
#include "u_heavy.h"
#include "getbits.h"
#include "maketbl.h"


#define NC 510
#define NPT 20
#define N1 510
Expand All @@ -27,15 +25,12 @@ static USHORT c_table[4096], pt_table[256];
USHORT dms_lastlen, dms_np;
USHORT dms_heavy_text_loc;


static USHORT read_tree_c(void);
static USHORT read_tree_p(void);
INLINE USHORT decode_c(void);
INLINE USHORT decode_p(void);

static USHORT decode_c(void);
static USHORT decode_p(void);


USHORT Unpack_HEAVY(UCHAR *in, UCHAR *out, UCHAR flags, USHORT origsize){
USHORT Unpack_HEAVY(UCHAR *in, UCHAR *out, UCHAR flags, USHORT pklen1, USHORT origsize){
USHORT j, i, c, bitmask;
UCHAR *outend;

Expand Down Expand Up @@ -69,12 +64,13 @@ USHORT Unpack_HEAVY(UCHAR *in, UCHAR *out, UCHAR flags, USHORT origsize){
}
}

return 0;
}

in += pklen1;
if (dms_indata == in + 2 || dms_indata == in + 1 || dms_indata == in + 0) return 0;

return 1;
}

INLINE USHORT decode_c(void){
static USHORT decode_c(void){
USHORT i, j, m;

j = c_table[GETBITS(12)];
Expand All @@ -94,9 +90,7 @@ INLINE USHORT decode_c(void){
return j;
}



INLINE USHORT decode_p(void){
static USHORT decode_p(void){
USHORT i, j, m;

j = pt_table[GETBITS(8)];
Expand Down Expand Up @@ -126,8 +120,6 @@ INLINE USHORT decode_p(void){

}



static USHORT read_tree_c(void){
USHORT i,n;

Expand All @@ -149,8 +141,6 @@ static USHORT read_tree_c(void){
return 0;
}



static USHORT read_tree_p(void){
USHORT i,n;

Expand Down
2 changes: 1 addition & 1 deletion src/archivers/dms/u_heavy.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@


USHORT Unpack_HEAVY(UCHAR *, UCHAR *, UCHAR, USHORT);
USHORT Unpack_HEAVY(UCHAR *, UCHAR *, UCHAR, USHORT, USHORT);

extern USHORT dms_heavy_text_loc;

15 changes: 5 additions & 10 deletions src/archivers/dms/u_medium.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,27 +7,21 @@
*
*/


#include <string.h>

#include "cdata.h"
#include "u_medium.h"
#include "getbits.h"
#include "tables.h"


#define MBITMASK 0x3fff


USHORT dms_medium_text_loc;



USHORT Unpack_MEDIUM(UCHAR *in, UCHAR *out, USHORT origsize){
USHORT Unpack_MEDIUM(UCHAR *in, UCHAR *out, USHORT pklen1, USHORT origsize){
USHORT i, j, c;
UCHAR u, *outend;


initbitbuf(in);

outend = out+origsize;
Expand All @@ -52,7 +46,8 @@ USHORT Unpack_MEDIUM(UCHAR *in, UCHAR *out, USHORT origsize){
}
dms_medium_text_loc = (USHORT)((dms_medium_text_loc+66) & MBITMASK);

return 0;
}

in += pklen1;
if (dms_indata == in + 2 || dms_indata == in + 1 || dms_indata == in + 0) return 0;

return 1;
}
Loading

0 comments on commit 1f02844

Please sign in to comment.