PhotoRec: improve jpg file recovery in brute-force mode

This commit is contained in:
Christophe Grenier 2010-04-27 09:03:05 +02:00
parent c1afbdf780
commit d88cbb2bb0
5 changed files with 1210 additions and 145 deletions

View file

@ -11,7 +11,7 @@ if USEQT
endif
sbin_PROGRAMS = testdisk photorec fidentify $(QPHOTOREC)
EXTRA_PROGRAMS =
EXTRA_PROGRAMS = photorecf
base_C = autoset.c common.c crc.c ewf.c fnctdsk.c hdaccess.c hdcache.c hdwin32.c hidden.c hpa_dco.c intrf.c iso.c log.c log_part.c misc.c msdos.c parti386.c partgpt.c partmac.c partsun.c partnone.c partxbox.c io_redir.c ntfs_io.c ntfs_utl.c partauto.c sudo.c unicode.c win32.c
base_H = alignio.h autoset.h common.h crc.h ewf.h fnctdsk.h hdaccess.h hdwin32.h hidden.h guid_cmp.h guid_cpy.h hdcache.h hpa_dco.h intrf.h iso.h iso9660.h lang.h log.h log_part.h misc.h types.h io_redir.h msdos.h ntfs_utl.h parti386.h partgpt.h partmac.h partsun.h partxbox.h partauto.h sudo.h unicode.h win32.h
@ -224,7 +224,7 @@ file_C = filegen.c \
file_xv.c \
file_zip.c
file_H = ext2.h filegen.h file_jpg.h file_sp3.h file_tar.h file_tiff.h file_txt.h list.h ole.h pe.h
file_H = ext2.h filegen.h file_jpg.h file_sp3.h file_tar.h file_tiff.h file_txt.h list.h ole.h pe.h suspend.h
photorec_C = photorec.c phcfg.c dir.c ext2grp.c ext2_dir.c ext2p.c fat_dir.c fatp.c file_found.c list.c ntfs_dir.c ntfsp.c sessionp.c setdate.c
@ -233,11 +233,13 @@ photorec_H = photorec.h phcfg.h dir.h ext2grp.h ext2p.h ext2_dir.h ext2_inc.h f
photorec_ncurses_C = addpart.c askloc.c chgtype.c chgtypen.c fat_cluster.c fat_unformat.c geometry.c hiddenn.c intrfn.c nodisk.c parti386n.c partgptn.c partmacn.c partsunn.c partxboxn.c pbanner.c pblocksize.c pdisksel.c pfree_whole.c phbf.c phbs.c phnc.c phrecn.c ppartsel.c
photorec_ncurses_H = addpart.h askloc.h chgtype.h chgtypen.h fat_cluster.h fat_unformat.h geometry.h hiddenn.h intrfn.h nodisk.h parti386n.h partgptn.h partmacn.h partsunn.h partxboxn.h pblocksize.h pdisksel.h pfree_whole.h pnext.h phbf.h phbs.h phnc.h phrecn.h ppartsel.h
photorec_SOURCES = phmain.c $(photorec_C) $(photorec_H) $(photorec_ncurses_C) $(photorec_ncurses_H) $(file_C) $(file_H) $(base_C) $(base_H) partgptro.c $(fs_C) $(fs_H) $(ICON_PHOTOREC)
photorec_SOURCES = phmain.c $(photorec_C) $(photorec_H) $(photorec_ncurses_C) $(photorec_ncurses_H) $(file_C) $(file_H) $(base_C) $(base_H) partgptro.c $(fs_C) $(fs_H) $(ICON_PHOTOREC) suspend_no.c
qphotorec_SOURCES = qmainrec.cpp qphotorec.cpp qphotorec.h chgtype.c chgtype.h $(photorec_C) $(photorec_H) $(file_C) $(file_H) $(base_C) $(base_H) partgptro.c $(fs_C) $(fs_H) $(ICON_PHOTOREC)
photorecf_SOURCES = phmain.c $(photorec_C) $(photorec_H) $(photorec_ncurses_C) $(photorec_ncurses_H) $(file_C) $(file_H) $(base_C) $(base_H) partgptro.c $(fs_C) $(fs_H) $(ICON_PHOTOREC) suspend.c
fidentify_SOURCES = fidentify.c common.c common.h phcfg.c phcfg.h setdate.c setdate.h $(file_C) $(file_H) log.c log.h crc.c crc.h fat_common.c
qphotorec_SOURCES = qmainrec.cpp qphotorec.cpp qphotorec.h chgtype.c chgtype.h $(photorec_C) $(photorec_H) $(file_C) $(file_H) $(base_C) $(base_H) partgptro.c $(fs_C) $(fs_H) $(ICON_PHOTOREC) suspend_no.c
fidentify_SOURCES = fidentify.c common.c common.h phcfg.c phcfg.h setdate.c setdate.h $(file_C) $(file_H) log.c log.h crc.c crc.h fat_common.c suspend_no.c
DISTCLEANFILES = *~ core

File diff suppressed because it is too large Load diff

326
src/suspend.c Normal file
View file

@ -0,0 +1,326 @@
/*
File: suspend.c
A suspending/resuming memory manager for libjpeg
Copyright (C) 2009 Christophe GRENIER <grenier@cgsecurity.org>
Copyright (C) 2008 Michael Cohen <scudette@users.sourceforge.net>, part of pyflag
This software 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; either version 2 of the License, or
(at your option) any later version.
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 the Free Software Foundation, Inc., 51
Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <stdio.h>
#ifdef HAVE_STDLIB_H
#include <stdlib.h>
#endif
#ifdef HAVE_STRING_H
#include <string.h>
#endif
// This should be large enough to handle most memory requests. On
// linux it can be rediculously large because the system will only
// actually allocate the memory when we write on it.
#define POOL_SIZE 4 * 1024 * 1024
#define AM_MEMORY_MANAGER /* we define jvirt_Xarray_control structs */
#ifdef HAVE_JPEGLIB_H
#include <jpeglib.h>
#endif
#include "types.h"
#include "common.h"
#include "log.h"
#if defined(HAVE_LIBJPEG) && defined(HAVE_JPEGLIB_H)
static void *alloc_small(j_common_ptr cinfo, int pool_id, size_t sizeofobject);
struct my_memory_mgr {
struct jpeg_memory_mgr pub; /* public fields */
// This is for libjpegs benefit:
jvirt_sarray_ptr virt_sarray_list;
jvirt_barray_ptr virt_barray_list;
JDIMENSION last_rowsperchunk; /* from most recent alloc_sarray/barray */
// All memory is allocated to this pool.
char *pool;
char *shadow_pool;
// A highwater mark for pool allocations
long pool_size;
// This is the very end of the allocated pool.
long total_space_allocated;
long total_space_shadowed;
};
typedef struct my_memory_mgr *my_mem_ptr;
#include "jerror.h"
#include "suspend.h"
#ifndef ALIGN_TYPE /* so can override from jconfig.h */
#define ALIGN_TYPE double
#endif
#ifndef MAX_ALLOC_CHUNK /* may be overridden in jconfig.h */
#define MAX_ALLOC_CHUNK 1000000000L
#endif
#define SIZEOF sizeof
/*
* The control blocks for virtual arrays.
* Note that these blocks are allocated in the "small" pool area.
* System-dependent info for the associated backing store (if any) is hidden
* inside the backing_store_info struct.
*/
struct jvirt_sarray_control {
JSAMPARRAY mem_buffer; /* => the in-memory buffer */
JDIMENSION rows_in_array; /* total virtual array height */
JDIMENSION samplesperrow; /* width of array (and of memory buffer) */
JDIMENSION maxaccess; /* max rows accessed by access_virt_sarray */
JDIMENSION rows_in_mem; /* height of memory buffer */
JDIMENSION rowsperchunk; /* allocation chunk size in mem_buffer */
JDIMENSION cur_start_row; /* first logical row # in the buffer */
JDIMENSION first_undef_row; /* row # of first uninitialized row */
boolean pre_zero; /* pre-zero mode requested? */
boolean dirty; /* do current buffer contents need written? */
boolean b_s_open; /* is backing-store data valid? */
jvirt_sarray_ptr next; /* link to next virtual sarray control block */
};
struct jvirt_barray_control {
JBLOCKARRAY mem_buffer; /* => the in-memory buffer */
JDIMENSION rows_in_array; /* total virtual array height */
JDIMENSION blocksperrow; /* width of array (and of memory buffer) */
JDIMENSION maxaccess; /* max rows accessed by access_virt_barray */
JDIMENSION rows_in_mem; /* height of memory buffer */
JDIMENSION rowsperchunk; /* allocation chunk size in mem_buffer */
JDIMENSION cur_start_row; /* first logical row # in the buffer */
JDIMENSION first_undef_row; /* row # of first uninitialized row */
boolean pre_zero; /* pre-zero mode requested? */
boolean dirty; /* do current buffer contents need written? */
boolean b_s_open; /* is backing-store data valid? */
jvirt_barray_ptr next; /* link to next virtual barray control block */
};
static void *alloc_small (j_common_ptr cinfo, int pool_id, size_t sizeofobject) {
struct my_memory_mgr *self = (struct my_memory_mgr *)(cinfo->mem);
char *obj_ptr = self->pool + self->total_space_allocated;
// log_info("allocating %u bytes\n", sizeofobject);
self->total_space_allocated += sizeofobject;
if(self->total_space_allocated > self->pool_size)
{
log_critical("suspend.c: no memory left\n");
return NULL;
}
return obj_ptr;
}
METHODDEF(JSAMPARRAY) alloc_sarray (j_common_ptr cinfo, int pool_id,
JDIMENSION samplesperrow, JDIMENSION numrows) {
JSAMPARRAY result;
JDIMENSION i;
result = (JSAMPARRAY) alloc_small(cinfo, pool_id, (size_t) (numrows * SIZEOF(JSAMPROW)));
for(i=0; i<numrows; i++) {
result[i] = (JSAMPROW) alloc_small(cinfo, pool_id,
(size_t) ((size_t) samplesperrow * SIZEOF(JSAMPLE)));
}
return result;
}
METHODDEF(jvirt_sarray_ptr) request_virt_sarray (j_common_ptr cinfo, int pool_id, boolean pre_zero,
JDIMENSION samplesperrow, JDIMENSION numrows,
JDIMENSION maxaccess) {
my_mem_ptr mem = (my_mem_ptr) cinfo->mem;
jvirt_sarray_ptr result;
result = (jvirt_sarray_ptr) alloc_small(cinfo, pool_id,
SIZEOF(struct jvirt_sarray_control));
result->mem_buffer = NULL;
result->rows_in_array = numrows;
result->samplesperrow = samplesperrow;
result->maxaccess = maxaccess;
result->pre_zero = pre_zero;
result->b_s_open = FALSE;
result->next = mem->virt_sarray_list;
mem->virt_sarray_list = result;
return result;
};
METHODDEF(void) realize_virt_arrays (j_common_ptr cinfo) {
my_mem_ptr mem = (my_mem_ptr) cinfo->mem;
long space_per_minheight, maximum_space, avail_mem;
long minheights, max_minheights;
jvirt_sarray_ptr sptr;
jvirt_barray_ptr bptr;
space_per_minheight = 0;
maximum_space = 0;
for (sptr = mem->virt_sarray_list; sptr != NULL; sptr = sptr->next) {
if (sptr->mem_buffer == NULL) { /* if not realized yet */
space_per_minheight += (long) sptr->maxaccess *
(long) sptr->samplesperrow * SIZEOF(JSAMPLE);
maximum_space += (long) sptr->rows_in_array *
(long) sptr->samplesperrow * SIZEOF(JSAMPLE);
}
}
for (bptr = mem->virt_barray_list; bptr != NULL; bptr = bptr->next) {
if (bptr->mem_buffer == NULL) { /* if not realized yet */
space_per_minheight += (long) bptr->maxaccess *
(long) bptr->blocksperrow * SIZEOF(JBLOCK);
maximum_space += (long) bptr->rows_in_array *
(long) bptr->blocksperrow * SIZEOF(JBLOCK);
}
}
if (space_per_minheight <= 0)
return; /* no unrealized arrays, no work */
/* Determine amount of memory to actually use */
avail_mem = maximum_space;
max_minheights = 1000000000L;
/* Allocate the in-memory buffers and initialize backing store as needed. */
for (sptr = mem->virt_sarray_list; sptr != NULL; sptr = sptr->next) {
if (sptr->mem_buffer == NULL) { /* if not realized yet */
minheights = ((long) sptr->rows_in_array - 1L) / sptr->maxaccess + 1L;
sptr->rows_in_mem = sptr->rows_in_array;
sptr->mem_buffer = alloc_sarray(cinfo, JPOOL_IMAGE,
sptr->samplesperrow, sptr->rows_in_mem);
sptr->rowsperchunk = mem->last_rowsperchunk;
sptr->cur_start_row = 0;
sptr->first_undef_row = 0;
sptr->dirty = FALSE;
}
}
for (bptr = mem->virt_barray_list; bptr != NULL; bptr = bptr->next) {
if (bptr->mem_buffer == NULL) { /* if not realized yet */
minheights = ((long) bptr->rows_in_array - 1L) / bptr->maxaccess + 1L;
bptr->rows_in_mem = bptr->rows_in_array;
bptr->mem_buffer = (JBLOCKARRAY)alloc_sarray(cinfo, JPOOL_IMAGE,
bptr->blocksperrow, bptr->rows_in_mem);
bptr->rowsperchunk = mem->last_rowsperchunk;
bptr->cur_start_row = 0;
bptr->first_undef_row = 0;
bptr->dirty = FALSE;
}
}
}
METHODDEF(JSAMPARRAY) access_virt_sarray (j_common_ptr cinfo, jvirt_sarray_ptr ptr,
JDIMENSION start_row, JDIMENSION num_rows,
boolean writable) {
if (writable)
ptr->dirty = TRUE;
return ptr->mem_buffer + (start_row - ptr->cur_start_row);
}
METHODDEF(void) free_pool (j_common_ptr cinfo, int pool_id) {
struct my_memory_mgr *self = (struct my_memory_mgr *)(cinfo->mem);
// log_info("Freeing pool\n");
// self->total_space_allocated = 0;
}
METHODDEF(void) self_destruct (j_common_ptr cinfo) {
struct my_memory_mgr *self = (struct my_memory_mgr *)(cinfo->mem);
//log_info("Destroying pool\n");
//free(self->pool);
//free(self->shadow_pool);
}
void suspend_memory(j_common_ptr cinfo) {
struct my_memory_mgr *self = (struct my_memory_mgr *)(cinfo->mem);
// log_info("Suspending at sector %u\n", sector);
memcpy(self->shadow_pool, self->pool, self->total_space_allocated);
self->total_space_shadowed = self->total_space_allocated;
};
int resume_memory(j_common_ptr cinfo)
{
struct my_memory_mgr *self = (struct my_memory_mgr *)(cinfo->mem);
// log_info("Resuming from sector %u (copying %lu bytes)\n", self->sector, self->total_space_shadowed);
memcpy(self->pool, self->shadow_pool, self->total_space_shadowed);
self->total_space_allocated = self->total_space_shadowed;
return 0;
};
GLOBAL(void) jinit_memory_mgr (j_common_ptr cinfo);
GLOBAL(void) jinit_memory_mgr (j_common_ptr cinfo)
{
static my_mem_ptr mem=NULL;
long max_to_use;
size_t test_mac;
cinfo->mem = NULL;
if ((SIZEOF(ALIGN_TYPE) & (SIZEOF(ALIGN_TYPE)-1)) != 0)
ERREXIT(cinfo, JERR_BAD_ALIGN_TYPE);
test_mac = (size_t) MAX_ALLOC_CHUNK;
if ((long) test_mac != MAX_ALLOC_CHUNK ||
(MAX_ALLOC_CHUNK % SIZEOF(ALIGN_TYPE)) != 0)
ERREXIT(cinfo, JERR_BAD_ALLOC_CHUNK);
max_to_use = 0;
if(mem == NULL)
mem = (struct my_memory_mgr *)MALLOC(sizeof(struct my_memory_mgr));
// Prepare our memory pools:
if(mem->pool == NULL)
mem->pool = (char *)MALLOC(POOL_SIZE);
if(mem->shadow_pool == NULL)
mem->shadow_pool = (char *)MALLOC(POOL_SIZE);
mem->pool_size = POOL_SIZE;
/* OK, fill in the method pointers */
mem->pub.alloc_small = alloc_small;
mem->pub.alloc_large = alloc_small;
mem->pub.alloc_sarray = alloc_sarray;
mem->pub.alloc_barray = alloc_sarray;
mem->pub.request_virt_sarray = request_virt_sarray;
mem->pub.request_virt_barray = request_virt_sarray;
mem->pub.realize_virt_arrays = realize_virt_arrays;
mem->pub.access_virt_sarray = access_virt_sarray;
mem->pub.access_virt_barray = access_virt_sarray;
mem->pub.free_pool = free_pool;
mem->pub.self_destruct = self_destruct;
/* Make MAX_ALLOC_CHUNK accessible to other modules */
mem->pub.max_alloc_chunk = MAX_ALLOC_CHUNK;
/* Initialize working state */
mem->pub.max_memory_to_use = max_to_use;
mem->virt_sarray_list = NULL;
mem->virt_barray_list = NULL;
mem->total_space_allocated = SIZEOF(struct my_memory_mgr);
/* Declare ourselves open for business */
cinfo->mem = & mem->pub;
}
#endif

2
src/suspend.h Normal file
View file

@ -0,0 +1,2 @@
void suspend_memory(j_common_ptr cinfo);
int resume_memory(j_common_ptr cinfo);

22
src/suspend_no.c Normal file
View file

@ -0,0 +1,22 @@
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#if defined(HAVE_LIBJPEG) && defined(HAVE_JPEGLIB_H)
#include <stdio.h>
#ifdef HAVE_STDLIB_H
#include <stdlib.h>
#endif
#include <jpeglib.h>
#include "suspend.h"
void suspend_memory(j_common_ptr cinfo) {
};
int resume_memory(j_common_ptr cinfo)
{
/* Can't resume */
return -1;
};
#endif