Skip to content

Commit

Permalink
[TOOLS] dmg2img.
Browse files Browse the repository at this point in the history
  • Loading branch information
foxlet committed Jul 31, 2019
0 parents commit 86380fd
Show file tree
Hide file tree
Showing 14 changed files with 2,361 additions and 0 deletions.
340 changes: 340 additions & 0 deletions COPYING

Large diffs are not rendered by default.

27 changes: 27 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
#CC = gcc
CFLAGS = -O2 -Wall
BIN_DIR = ${DESTDIR}/usr/bin

all: dmg2img vfdecrypt

dmg2img: dmg2img.c dmg2img.h mntcmd.h gpt.h dmg2img.o base64.o adc.o
$(CC) -s -o dmg2img dmg2img.o base64.o adc.o -L. -lz -lbz2

dmg2img.o: dmg2img.c dmg2img.h
$(CC) $(CFLAGS) -c dmg2img.c

base64.o: base64.c base64.h
$(CC) $(CFLAGS) -c base64.c

adc.o: adc.c adc.h
$(CC) $(CFLAGS) -c adc.c

vfdecrypt: vfdecrypt.c
$(CC) $(CFLAGS) -s -o vfdecrypt vfdecrypt.c -lcrypto

install: dmg2img vfdecrypt
mkdir -p ${BIN_DIR}
install -c -s -m 755 -o root -g root dmg2img vfdecrypt $(BIN_DIR)

clean:
rm -f dmg2img vfdecrypt *~ *.o core
124 changes: 124 additions & 0 deletions README
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@

DMG2IMG is a tool which allows converting Apple compressed dmg
archives to standard (hfsplus) image disk files.

This tool handles zlib and bzip2 compressed dmg images.


USAGE:
dmg2img [-l] [-p N] [-s] [-v] [-V] [-d] <input.dmg> [<output.img>]
or
dmg2img -i <input.dmg> -o <output.img>

It is derived from dmg2iso v0.2c by vu1tur <to@vu1tur.eu.org>


NOTES:

1. An equivalent command under Mac OS X would be:
hdiutil convert <input.dmg> -format UDTO -o <output.img>

2. Under linux, the image disk file can be mounted with the commands

modprobe hfsplus
mount -t hfsplus -o loop <output.img> /mnt

[normally, only 'root' might be able to do this]

3. Windows users should be able to open the image disk file with UltraISO.

Jean-Pierre Demailly <demailly@fourier.ujf-grenoble.fr>


COMPILATION:

The default included Makefile is for Linux/gcc. The development files
in zlib-dev and libbz2-dev are needed to compile dmg2img, and those
in openssl-dev are needed to compile vfdecrypt.


CHANGELOG:

1.0 3 August 2007
* Initial version

1.1 4 August 2008
* Fixed segfault bug occurring when decompressing certain dmg files
beyond the actual end of the file (due to not correctly setting
the size of the compressed parts ...)
* Added slightly modified vfdecrypt utility from
Weinmann-Appelbaum-Fromme in order to decrypt encrypted dmg files.

1.2 17 September 2008
* Fixed segfault bug due to buffer overflow (buffer sizes
incorrectly set, resulting in insufficient memory allocation).
* Fixed most compilation warnings - remaining ones are
irrelevant with standard compilers.

1.3 19 September 2008
* Further fixes which (hopefully) enable dmg2img to work on
dmg archives of arbitrary size, while reducing RAM usage a lot.
* A lot of thanks to Alfred E. Hegge and Randy Broman for testing
and reporting bugs.

1.4 5 April 2009
* Applied patch from Vladimir 'phcoder' Serbinenko which brings
correct handling of 64bit integers in koly signature and
plist data, and should enable dmg2img to work on huge
archives > 4GBytes (tested by 'phcoder').
* Added support for dmg archives involving bzip2 instead of zlib
compression (this has not received much testing yet, as those
archives are still unfrequent).
* Many thanks to Pierre Duhem for useful hints.

1.4.1 6 April 2009
* Fixed a bug in writing the output file that caused some DMG images
to convert to a broken unmountable IMG image.

1.5 8 April 2009
* Fixed a bug in parsing plist for image partitions.
* Added support for ADC-compressed dmg images.

1.5.1 11 April 2009
* Added missing zero block type.
* Small fixes and clean up.

1.6 15 April 2009
* Added support for dmg images that only have binary resource fork
but no XML plist.
* Refined koly block processing.
* Fixed a bug in finding the offset for the next compressed block
when offsets are defined relative to the current partition.
* Fixed broken progress indicator.
* Added detection of images with GUID Partition Table and respective
mount commands in linux.

1.6.1 12 August 2009
* Fixed a bug in handling large files on win32 systems.

1.6.2 24 March 2010
* Fixed a bug in processing a terminal block type.
* Added periodic flushing of debug log file.

1.6.3 07 April 2012
* Added option -l to list partitions
* Added option -p to extract only specific partition
* Added support for a rare case scenario of koly block being at the
the beginning of the image (thanks to Friik)

1.6.4 25 April 2012
* Compilation bugfix (Linux)

1.6.5 23 July 2013
* Fixed a bug in handling some types of dmg files

1.6.6 06 February 2017
* Fixed a crash on invalid block signature (thanks to Peter Wu)

1.6.7 09 February 2017
* Fixed buffer underrun (thanks to Peter Wu)
* Avoid truncating .img file when run to list partition
(thanks to Frederic Germain)
* Small fixes and cleanup

http://vu1tur.eu.org/dmg2img
114 changes: 114 additions & 0 deletions adc.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
#include "adc.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>


int adc_decompress(int in_size, unsigned char *input, int avail_size, unsigned char *output, int *bytes_written)
{
if (in_size == 0)
return 0;
bool output_full = false;
unsigned char *inp = input;
unsigned char *outp = output;
int chunk_type;
int chunk_size;
int offset;
int i;

while (inp - input < in_size) {
chunk_type = adc_chunk_type(*inp);
switch (chunk_type) {
case ADC_PLAIN:
chunk_size = adc_chunk_size(*inp);
if (outp + chunk_size - output > avail_size) {
output_full = true;
break;
}
memcpy(outp, inp + 1, chunk_size);
inp += chunk_size + 1;
outp += chunk_size;
break;

case ADC_2BYTE:
chunk_size = adc_chunk_size(*inp);
offset = adc_chunk_offset(inp);
if (outp + chunk_size - output > avail_size) {
output_full = true;
break;
}
if (offset == 0) {
memset(outp, *(outp - offset - 1), chunk_size);
outp += chunk_size;
inp += 2;
} else {
for (i = 0; i < chunk_size; i++) {
memcpy(outp, outp - offset - 1, 1);
outp++;
}
inp += 2;
}
break;

case ADC_3BYTE:
chunk_size = adc_chunk_size(*inp);
offset = adc_chunk_offset(inp);
if (outp + chunk_size - output > avail_size) {
output_full = true;
break;
}
if (offset == 0) {
memset(outp, *(outp - offset - 1), chunk_size);
outp += chunk_size;
inp += 3;
} else {
for (i = 0; i < chunk_size; i++) {
memcpy(outp, outp - offset - 1, 1);
outp++;
}
inp += 3;
}
break;
}
if (output_full)
break;
}
*bytes_written = outp - output;
return inp - input;
}

int adc_chunk_type(char _byte)
{
if (_byte & 0x80)
return ADC_PLAIN;
if (_byte & 0x40)
return ADC_3BYTE;
return ADC_2BYTE;
}

int adc_chunk_size(char _byte)
{
switch (adc_chunk_type(_byte)) {
case ADC_PLAIN:
return (_byte & 0x7F) + 1;
case ADC_2BYTE:
return ((_byte & 0x3F) >> 2) + 3;
case ADC_3BYTE:
return (_byte & 0x3F) + 4;
}
return -1;
}

int adc_chunk_offset(unsigned char *chunk_start)
{
unsigned char *c = chunk_start;
switch (adc_chunk_type(*c)) {
case ADC_PLAIN:
return 0;
case ADC_2BYTE:
return ((((unsigned char)*c & 0x03)) << 8) + (unsigned char)*(c + 1);
case ADC_3BYTE:
return (((unsigned char)*(c + 1)) << 8) + (unsigned char)*(c + 2);
}
return -1;
}
15 changes: 15 additions & 0 deletions adc.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#include <stdio.h>
#include <unistd.h>

#define ADC_PLAIN 0x01
#define ADC_2BYTE 0x02
#define ADC_3BYTE 0x03

#define bool short
#define true 1
#define false 0

int adc_decompress(int in_size, unsigned char *input, int avail_size, unsigned char *output, int *bytes_written);
int adc_chunk_type(char _byte);
int adc_chunk_size(char _byte);
int adc_chunk_offset(unsigned char *chunk_start);
90 changes: 90 additions & 0 deletions base64.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
/*
* DMG2ISO base64.cc
*
* Copyright (c) 2004 vu1tur <to@vu1tur.eu.org> This program is free software; you
* can redistribute it and/or modify it under the terms of the GNU General
* Public License as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc., 51
* Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/

#include "base64.h"
#include <stdlib.h>

bool is_base64(const char c)
{
if ((c >= 'A' && c <= 'Z') ||
(c >= 'a' && c <= 'z') ||
(c >= '0' && c <= '9') ||
c == '+' ||
c == '/' ||
c == '=')
return true;
return false;
}

void cleanup_base64(char *inp, const unsigned int size)
{
char *tinp1, *tinp2;
unsigned int i;
tinp1 = inp;
tinp2 = inp;
for (i = 0; i < size; i++) {
if (is_base64(*tinp2)) {
*tinp1++ = *tinp2++;
} else {
*tinp1 = *tinp2++;
}
}
*(tinp1) = 0;
}

unsigned char decode_base64_char(const char c)
{
if (c >= 'A' && c <= 'Z')
return c - 'A';
if (c >= 'a' && c <= 'z')
return c - 'a' + 26;
if (c >= '0' && c <= '9')
return c - '0' + 52;
if (c == '+')
return 62;
if (c == '=')
return 0;
return 63;
}

void decode_base64(const char *inp, unsigned int isize,
char *out, unsigned int *osize)
{
char *tinp = (char *)inp;
char *tout;
unsigned int i;

*osize = isize / 4 * 3;
if (inp != out) {
tout = (char *)malloc(*osize);
out = tout;
} else {
tout = tinp;
}
for (i = 0; i < (isize >> 2); i++) {
*tout = decode_base64_char(*tinp++) << 2;
*tout++ |= decode_base64_char(*tinp) >> 4;
*tout = decode_base64_char(*tinp++) << 4;
*tout++ |= decode_base64_char(*tinp) >> 2;
*tout = decode_base64_char(*tinp++) << 6;
*tout++ |= decode_base64_char(*tinp++);
}
if (*(tinp - 1) == '=')
(*osize)--;
if (*(tinp - 2) == '=')
(*osize)--;
}
Loading

0 comments on commit 86380fd

Please sign in to comment.