Contenu | Rechercher | Menus

Annonce

Si vous avez des soucis pour rester connecté, déconnectez-vous puis reconnectez-vous depuis ce lien en cochant la case
Me connecter automatiquement lors de mes prochaines visites.

À propos de l'équipe du forum.

#26 Le 23/04/2020, à 14:43

Nuliel

Re : [Résolu] extraire des octets d'un tableau de char (C++)

Oui, bootsector c'est le premier secteur de ma partition ntfs, ici il a pour longueur 512 octets

Hors ligne

#27 Le 23/04/2020, à 15:02

Nuliel

Re : [Résolu] extraire des octets d'un tableau de char (C++)

Je te conseille plutôt https://en.wikipedia.org/wiki/NTFS que j'utilise comme référence.

Sinon, la version en python 3 que je viens de faire rapidement (je ne dénigre pas le C++, c'est juste que j'ai plus l'habitude de coder en python)

class NTFS_boot_sector:
    def __init__(self, partition, offset = 0):
        with open(partition, "rb") as file:
            file.seek(offset)
            file.seek(3)
            self.oem_id=file.read(8)
            self.bytes_per_sector=int.from_bytes(file.read(2), "little")
            self.sector_per_cluster=int.from_bytes(file.read(1), "little")
            file.seek(34)
            self.mft_cluster_number=int.from_bytes(file.read(8), "little")
            self.mftmirr_cluster_number=int.from_bytes(file.read(8), "little")
            self.bytes_or_Clusters_Per_File_Record_Segment=int.from_bytes(file.read(1), "little") # seems to be x0c so 12 clusters in a file record segment
            print(self.bytes_or_Clusters_Per_File_Record_Segment)
            file.seek(445)
            self.end_of_sector_Marker=file.read(2)

    def extractMFT(self, partition, destination, offset = 0):
        with open(partition, "rb") as file:
            file.seek(offset+self.mft_cluster_number*self.sector_per_cluster*self.bytes_per_sector)
            


boot_sector= NTFS_boot_sector("bootsector")

Dernière modification par Nuliel (Le 23/04/2020, à 15:19)

Hors ligne

#28 Le 23/04/2020, à 15:11

NicoApi73

Re : [Résolu] extraire des octets d'un tableau de char (C++)

Je vais essayer de te faire pour ce soir quelque chose d'équivalent en C++ (grigouille ira peut être plus vite que moi smile )

Une classe NTFS_boot_sector, chargeant le secteur
Un attribut, le secteur (un string de 512 octets)
un assesseur, prenant en argument le champ (donné par son offset)

Pour moi, on peut soit charger le fichier, soit y accéder à chaque fois que l'on veut une donnée.

Hors ligne

#29 Le 23/04/2020, à 15:14

Nuliel

Re : [Résolu] extraire des octets d'un tableau de char (C++)

Merci beaucoup pour l'aide, là je suis vraiment perdu!
Si cela peut aider, voici mon fichier bootsector:

naziel@naziel-ThinkPad-X220:~/NTFS_Utility$ hexdump -C bootsector 
00000000  eb 52 90 4e 54 46 53 20  20 20 20 00 02 08 00 00  |.R.NTFS    .....|
00000010  00 00 00 00 00 f8 00 00  3f 00 ff 00 00 a8 03 00  |........?.......|
00000020  00 00 00 00 80 00 80 00  1d 67 51 74 00 00 00 00  |.........gQt....|
00000030  00 00 0c 00 00 00 00 00  02 00 00 00 00 00 00 00  |................|
00000040  f6 00 00 00 01 00 00 00  70 e4 75 8e 29 76 8e b4  |........p.u.)v..|
00000050  00 00 00 00 fa 33 c0 8e  d0 bc 00 7c fb 68 c0 07  |.....3.....|.h..|
00000060  1f 1e 68 66 00 cb 88 16  0e 00 66 81 3e 03 00 4e  |..hf......f.>..N|
00000070  54 46 53 75 15 b4 41 bb  aa 55 cd 13 72 0c 81 fb  |TFSu..A..U..r...|
00000080  55 aa 75 06 f7 c1 01 00  75 03 e9 dd 00 1e 83 ec  |U.u.....u.......|
00000090  18 68 1a 00 b4 48 8a 16  0e 00 8b f4 16 1f cd 13  |.h...H..........|
000000a0  9f 83 c4 18 9e 58 1f 72  e1 3b 06 0b 00 75 db a3  |.....X.r.;...u..|
000000b0  0f 00 c1 2e 0f 00 04 1e  5a 33 db b9 00 20 2b c8  |........Z3... +.|
000000c0  66 ff 06 11 00 03 16 0f  00 8e c2 ff 06 16 00 e8  |f...............|
000000d0  4b 00 2b c8 77 ef b8 00  bb cd 1a 66 23 c0 75 2d  |K.+.w......f#.u-|
000000e0  66 81 fb 54 43 50 41 75  24 81 f9 02 01 72 1e 16  |f..TCPAu$....r..|
000000f0  68 07 bb 16 68 52 11 16  68 09 00 66 53 66 53 66  |h...hR..h..fSfSf|
00000100  55 16 16 16 68 b8 01 66  61 0e 07 cd 1a 33 c0 bf  |U...h..fa....3..|
00000110  0a 13 b9 f6 0c fc f3 aa  e9 fe 01 90 90 66 60 1e  |.............f`.|
00000120  06 66 a1 11 00 66 03 06  1c 00 1e 66 68 00 00 00  |.f...f.....fh...|
00000130  00 66 50 06 53 68 01 00  68 10 00 b4 42 8a 16 0e  |.fP.Sh..h...B...|
00000140  00 16 1f 8b f4 cd 13 66  59 5b 5a 66 59 66 59 1f  |.......fY[ZfYfY.|
00000150  0f 82 16 00 66 ff 06 11  00 03 16 0f 00 8e c2 ff  |....f...........|
00000160  0e 16 00 75 bc 07 1f 66  61 c3 a1 f6 01 e8 09 00  |...u...fa.......|
00000170  a1 fa 01 e8 03 00 f4 eb  fd 8b f0 ac 3c 00 74 09  |............<.t.|
00000180  b4 0e bb 07 00 cd 10 eb  f2 c3 0d 0a 41 20 64 69  |............A di|
00000190  73 6b 20 72 65 61 64 20  65 72 72 6f 72 20 6f 63  |sk read error oc|
000001a0  63 75 72 72 65 64 00 0d  0a 42 4f 4f 54 4d 47 52  |curred...BOOTMGR|
000001b0  20 69 73 20 63 6f 6d 70  72 65 73 73 65 64 00 0d  | is compressed..|
000001c0  0a 50 72 65 73 73 20 43  74 72 6c 2b 41 6c 74 2b  |.Press Ctrl+Alt+|
000001d0  44 65 6c 20 74 6f 20 72  65 73 74 61 72 74 0d 0a  |Del to restart..|
000001e0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
000001f0  00 00 00 00 00 00 8a 01  a7 01 bf 01 00 00 55 aa  |..............U.|
00000200

Hors ligne

#30 Le 23/04/2020, à 15:18

kevlar

Re : [Résolu] extraire des octets d'un tableau de char (C++)

Pour info, je te montre comment j'ai écrit une fonction pour décrypter le format de fichier de mS Word (de Word 1.x à 2003, depuis 2007 c'est plus facile) ; çà va faire écho à ta source en Python. Je ne donne qu'un extrait, mais l'intérêt c'est de montrer comment je vérifie dans l'en-tête du fichier la présence d'octets "magiques" qui permettent de vérifier que l'on a bien affaire à un fichier Ms-Word. C'est, il me semble, un peu ce que tu veux faire pour le NTFS.

Je commence par déclarer le buffer qui sera dynamique (j'épargne la liste des autres variables, faciles à comprendre) :

  gchar *str=NULL, *buffer;

voici un extrait dans le quel je lis l'ordre dans lequel sont rangés les mots de 16 bits, et j'ai pour çà besoin de faire une vérification de la présence de deux octets "magiques" à une position connue de l'en-tête du fichier. Tu noteras comment je transtype entre un "char" et la représentation hexadécimale.

 /* we compute the size before dynamically allocate buffer */
  glong prev = ftell(inputFile);   
  fseek(inputFile, 0L, SEEK_END);
  glong sz = ftell(inputFile);
  fseek(inputFile, prev, SEEK_SET);
  /* we allocate the buffer */
  if(sz<=0)
    return NULL;
  buffer = g_malloc0(sz*sizeof(gchar)+sizeof(gchar));
  if(buffer==NULL)
    return NULL;
  /* we start the file reading in Binary mode : it's better for future parsing */
  fileSize = fread(buffer, sizeof(gchar), sz, inputFile);
  fclose(inputFile);
  /* the word coding MUST be in little endian ! */
  if(!(buffer[28]=0xFE)&&(buffer[29]==0xFF)) {
        printf("* can't proceed : file coded in Big endian mode ! \n");
        g_free(buffer);
        return NULL;
  }

après je ne développe pas, il faut savoir que le format Ms-word (avant 2007) est en lui-même une table d'allocation de fichiers (FAT) virtuelle, et qu'en fait pour décrypter le contenu il faut d'abord reconstruire les (oui c'est un pluriel) Tables d'allocation intégrées. Probable que tu auras à affronter les mêmes problèmes pour lire une arborescence NTFS, si c'est le cas ... bon courage !

Hors ligne

#31 Le 23/04/2020, à 19:20

Nuliel

Re : [Résolu] extraire des octets d'un tableau de char (C++)

Merci pour ton exemple kevlar.
Effectivement lire le premier secteur permet de vérifier les octets magiques (c'est le champ oem_id ainsi que le marqueur de fin), mais l'autre intérêt est de trouver l'emplacement de la MFT (là où on trouve l'emplacement des fichiers, des dossiers, le dernier accès , si le fichier est dans la MFT ou à l'extérieur ....). S'il ne pouvait y avoir qu'une table d'allocation de fichiers, ça pourrait m'arranger big_smile

En fait, mon but est de faire un programme qui utilise la table d'allocation des fichiers pour définir les zones de copie que ddrescue doit sauver (l'idée étant qu'on puisse demander à récupérer le dossier utilisateur, et que ddrescue puisse essayer de récupérer seulement les documents dans le dossier utilisateur)
Ce programme sera utilisé sur un disque défectueux

Dernière modification par Nuliel (Le 23/04/2020, à 19:21)

Hors ligne

#32 Le 24/04/2020, à 00:22

NicoApi73

Re : [Résolu] extraire des octets d'un tableau de char (C++)

Peux tu m'envoyer par mail ton fichier bootsector STP?

Hors ligne

#33 Le 24/04/2020, à 10:33

Nuliel

Re : [Résolu] extraire des octets d'un tableau de char (C++)

C'est bon, je te l'ai envoyé

Hors ligne

#34 Le 24/04/2020, à 11:35

NicoApi73

Re : [Résolu] extraire des octets d'un tableau de char (C++)

ok, ça a l'air de fonctionner.

J'ai pris le tableau de ton lien wikipedia en entrée, chaque colonne délimitée par un ; et chaque ligne par un retour chariot \n (fichier csv)


config.csv

0x00 ;3 bytes ;0xEB5290 ;JMP instruction ;Causes execution to continue after the data structures in this boot sector. 
0x03 ;8 bytes ;NTFS    Word NTFS followed by four trailing spaces (0x20) ;OEM ID ;This is the magic cookie that indicates this is an NTFS file system. 
0x0B ;2 bytes ;0x0200 ;Bytes per sector ;The number of bytes in a disk sector. 
0x0D ;1 byte ;0x08 ;Sectors Per Cluster ;The number of sectors in a cluster. If the value is greater than 0x80, the amount of sectors is 2 to the power of the absolute value of considering this field to be negative. 
0x0E ;2 bytes ;0x0000 ;Reserved Sectors, unused ;How much space is reserved by the OS at the start of disk. This is always 9. 
0x10 ;3 bytes ;0x000000 ;Unused ;This field is always 0 
0x13 ;2 bytes ;0x0000 ;Unused by NTFS ;This field is always 0 
0x15 ;1 byte ;0xF8 ;Media Descriptor ;The type of drive. 0xF8 is used to denote a hard drive (in contrast to the several sizes of floppy). 
0x16 ;2 bytes ;0x0000 ;Unused ;This field is always 0 
0x18 ;2 bytes ;0x003F ;Sectors Per Track ;The number of disk sectors in a drive track. 
0x1A ;2 bytes ;0x00FF ;Number Of Heads ;The number of heads on the drive. 
0x1C ;4 bytes ;0x0000003F ;Hidden Sectors ;The number of sectors preceding the partition. 
0x20 ;4 bytes ;0x00000000 ;Unused ;Not used by NTFS 
0x24 ;4 bytes ;0x00800080 ;Unused ;Not used by NTFS 
0x28 ;8 bytes ;0x00000000007FF54A ;Total sectors ;The partition size in sectors. 
0x30 ;8 bytes ;0x0000000000000004 ;$MFT cluster number ;The cluster that contains the Master File Table 
0x38 ;8 bytes ;0x000000000007FF54 ;$MFTMirr cluster number ;The cluster that contains a backup of the Master File Table 
0x40 ;1 byte ;0xF6 ;Bytes or Clusters Per File Record Segment ;A positive value denotes the number of clusters in a File Record Segment. A negative value denotes the amount of bytes in a File Record Segment, in which case the size is 2 to the power of the absolute value. (0xF6 = -10 → 210 = 1024). 
0x41 ;3 bytes ;0x000000 ;Unused ;This field is not used by NTFS 
0x44 ;1 byte ;0x01 ;Bytes or Clusters Per Index Buffer ;A positive value denotes the number of clusters in an Index Buffer. A negative value denotes the amount of bytes and it uses the same algorithm for negative numbers as the "Bytes or Clusters Per File Record Segment." 
0x45 ;3 bytes ;0x000000 ;Unused ;This field is not used by NTFS 
0x48 ;8 bytes ;0x1C741BC9741BA514 ;Volume Serial Number ;A unique random number assigned to this partition, to keep things organized. 
0x50 ;4 bytes ;0x00000000 ;Checksum, unused ;Supposedly a checksum. 
0x54 ;426 bytes ;;Bootstrap Code ;The code that loads the rest of the operating system. This is pointed to by the first 3 bytes of this sector. 
0x01FE ;2 bytes ;0xAA55 ;End-of-sector Marker ;This flag indicates that this is a valid boot sector. 

Makefile :

CC=g++
CFLAGS=-W -Wall -std=c++11
LDFLAGS=
EXEC=boot

all: $(EXEC)

boot: boot_sector.o main.o boot_field.o
	$(CC) -o boot boot_sector.o main.o boot_field.o $(LDFLAGS)

boot_sector.o: boot_sector.cpp boot_sector.h boot_field.h
	$(CC) -o boot_sector.o -c boot_sector.cpp $(CFLAGS)

boot_field.o: boot_field.cpp boot_field.h
	$(CC) -o boot_field.o -c boot_field.cpp $(CFLAGS)

main.o: main.cpp boot_sector.h boot_field.h
	$(CC) -o main.o -c main.cpp $(CFLAGS)

clean:
	rm -rf *.o

main.cpp (pour l'exemple)

#include <iostream>
#include <string>

#include "boot_sector.h"
#include "boot_field.h"

#define OEM_ID 2
#define EOS_MARKER 25

using namespace std;

int main ()
{
	NTFS_boot_field bf_OEM_ID ("config.csv",OEM_ID);
	NTFS_boot_field bf_EOS ("config.csv",EOS_MARKER);
	NTFS_boot_sector bs ("bootsector");
	string field_content1,field_content2;
	
	if (bs.is_valid())
	{
		field_content1 = bs.getField(bf_OEM_ID);
		field_content2 = bs.getField(bf_EOS);
	}
	cout << "OEM_ID start : " << bf_OEM_ID.start() << " Size : " << bf_OEM_ID.size() << "\n";
	cout << "OEM_ID content : \'" << field_content1 << "\'\n";
	cout << "EOS_MARKER start : " << bf_EOS.start() << " Size : " << bf_EOS.size() << "\n";
	cout << "EOS_MARKER content : \'" << field_content2 << "\'\n";
}

boot_sector.h

#ifndef BOOT_SECTOR_H_
#define BOOT_SECTOR_H_

#include <string>
#include "boot_field.h"

class NTFS_boot_sector
{
	private :
	std::string boot_sector;
	int consistency;
	
	public :
	NTFS_boot_sector(std::string);
	std::string getField (NTFS_boot_field);
	
	int is_valid();
};

#endif

boot_sector.cpp

#include "boot_sector.h"
#include "boot_field.h"

#include <fstream>


using namespace std;

/**********************************************************************
 * Constructor using file name containing boot content                *
 * ********************************************************************/

NTFS_boot_sector::NTFS_boot_sector(string filename)
{
	ifstream file(filename, ios::binary);
	
	consistency = true;
	if (file.is_open())
	{
		// Load boot sector
		for (int i = 0;i<BOOT_SECTOR_SIZE;i++)
		{
			char c;
			
			if (file.eof())
			{
				consistency = false; //ensure that file is at least 512 Bytes
				break;
			}
			file.get(c);
			boot_sector.push_back(c);
		}
		file.close();
	}
	else
		consistency = false;
}

/**********************************************************************
 * Public method providing the content of the given field             *
 * ********************************************************************/

string NTFS_boot_sector::getField (NTFS_boot_field field)
{
	string field_content;
	
	if (field.is_valid ())		
		for (int i = field.start();i<field.start()+field.size() && i<BOOT_SECTOR_SIZE;i++)
			field_content.push_back(boot_sector[i]);
		
	return field_content;
}

/**********************************************************************
 * Public method ensuring that the content of the boot is at least    *
 * long enough                                                        *
 * ********************************************************************/

int NTFS_boot_sector::is_valid ()
{
	return consistency;
}

boot_field.h

#ifndef BOOT_FIELD_H_
#define BOOT_FIELD_H_

#include <string>
#include <vector>
#include <fstream>

#define BOOT_SECTOR_SIZE 512

class NTFS_boot_field
{
	private :
	std::vector<std::string> field_content;
	int consistency;
	
	char read_field (std::ifstream &);
	
	public :
	NTFS_boot_field(std::string,int);
	int start ();
	int size ();
	std::string field_value (int );
	
	int is_valid();
};

#endif

boot_field.cpp

#include "boot_field.h"
#include <fstream>

using namespace std;

/**********************************************************************
 * Constructor, using field as index. Can be overloaded             *
 * ********************************************************************/

NTFS_boot_field::NTFS_boot_field(string filename,int field_number) // first field index = 1
{
	ifstream file(filename, ios::binary);

	consistency = true;
	if (file.is_open())
	{
		for (int i = 0;i<=field_number;i++)
		{
			char c = '0';
			
			
			if (file.eof())
				break;
			if (i == field_number -1)
			{
				// register each field (end of row = \n)
				do
					c = read_field (file);
				while (c != '\n' && !file.eof());
			}
			
			if (i == field_number)
			{
				c = read_field (file); // store next field byte offset to calculate field lengh. If not, then already set to BOOT_SECTOR_SIZE
				if (c != ';')
					field_content[field_content.size ()-1] = "0x0200"; // Last field
				break;
			}
							
			while (!file.eof() && c != '\n')
				file.get (c);
		}
		file.close();
	}
	else
		consistency = false;
}

/**********************************************************************
 * Read all the fields and store them in a vector of string          *
 * ********************************************************************/

char NTFS_boot_field::read_field (ifstream & file)
{
	char c = '0';
	
	field_content.resize (field_content.size()+1);
	file.get (c);
	while (c != ';' && c != '\n' && !file.eof())
	{
		field_content[field_content.size ()-1].push_back (c);
		file.get (c);
	}
	return c;
}

/**********************************************************************
 * Return the starting adress of the field                            *
 * ********************************************************************/

int NTFS_boot_field::start ()
{
	return stoul (field_content[0],nullptr,16);
}

/**********************************************************************
 * Return the size of the field                                       *
 * ********************************************************************/

int NTFS_boot_field::size ()
{
	return stoul(field_content[field_content.size ()-1],nullptr,16) - stoul (field_content[0],nullptr,16);
}

/**********************************************************************
 * Return if the field is valide or not                               *
 * ********************************************************************/

int NTFS_boot_field::is_valid()
{
	return consistency;
}

/**********************************************************************
 * Return the field value                                             *
 * ********************************************************************/

string NTFS_boot_field::field_value (int index)
{
	if ((unsigned int)index < field_content.size ())
		return field_content[index];
	return "";
}

Hors ligne

#35 Le 24/04/2020, à 13:30

NicoApi73

Re : [Résolu] extraire des octets d'un tableau de char (C++)

J'étais embêté pour convertir un entier au format hexa mis dans un string. J'ai trouvé la solution. Voici les 2 fichiers modifiés :

boot_field.h

#ifndef BOOT_FIELD_H_
#define BOOT_FIELD_H_

#include <string>
#include <vector>
#include <fstream>

#define BOOT_SECTOR_SIZE 512

class NTFS_boot_field
{
	private :
	std::vector<std::string> field_content;
	int consistency;
	
	char read_field (std::ifstream &);
	
	public :
	NTFS_boot_field(std::string,int);
	int start ();
	int size ();
	std::string field_value (int );
	
	int is_valid();
};

std::string ito_hex_string( const unsigned int );

#endif

boot_field.cpp :

#include "boot_field.h"
#include <fstream>
#include <sstream>

using namespace std;

/**********************************************************************
 * Constructor, using field as index. Can be overloaded             *
 * ********************************************************************/

NTFS_boot_field::NTFS_boot_field(string filename,int field_number) // first field index = 1
{
	ifstream file(filename, ios::binary);

	consistency = true;
	if (file.is_open())
	{
		for (int i = 0;i<=field_number;i++)
		{
			char c = '0';
			
			
			if (file.eof())
				break;
			if (i == field_number -1)
			{
				// register each field (end of row = \n)
				do
					c = read_field (file);
				while (c != '\n' && !file.eof());
			}
			
			if (i == field_number)
			{
				c = read_field (file); // store next field byte offset to calculate field lengh. If not, then already set to BOOT_SECTOR_SIZE
				if (c != ';')
					field_content[field_content.size ()-1] = ito_hex_string (BOOT_SECTOR_SIZE); // Last field
				break;
			}
							
			while (!file.eof() && c != '\n')
				file.get (c);
		}
		file.close();
	}
	else
		consistency = false;
}

/**********************************************************************
 * Read all the fields and store them in a vector of string          *
 * ********************************************************************/

char NTFS_boot_field::read_field (ifstream & file)
{
	char c = '0';
	
	field_content.resize (field_content.size()+1);
	file.get (c);
	while (c != ';' && c != '\n' && !file.eof())
	{
		field_content[field_content.size ()-1].push_back (c);
		file.get (c);
	}
	return c;
}

/**********************************************************************
 * Return the starting adress of the field                            *
 * ********************************************************************/

int NTFS_boot_field::start ()
{
	return stoul (field_content[0],nullptr,16);
}

/**********************************************************************
 * Return the size of the field                                       *
 * ********************************************************************/

int NTFS_boot_field::size ()
{
	return stoul(field_content[field_content.size ()-1],nullptr,16) - stoul (field_content[0],nullptr,16);
}

/**********************************************************************
 * Return if the field is valide or not                               *
 * ********************************************************************/

int NTFS_boot_field::is_valid()
{
	return consistency;
}

/**********************************************************************
 * Return the field value                                             *
 * ********************************************************************/

string NTFS_boot_field::field_value (int index)
{
	if ((unsigned int)index < field_content.size ())
		return field_content[index];
	return "";
}

/**********************************************************************
 * Convert an interger to a string in hex format                      *
 * ********************************************************************/

string ito_hex_string( const unsigned int i ) 
{
    stringstream s;
    
    s << "0x" << std::hex << i;
    return s.str();
}

Hors ligne

#36 Le 24/04/2020, à 14:10

Nuliel

Re : [Résolu] extraire des octets d'un tableau de char (C++)

Merci NicoApi73, je vais décortiquer ton code pour bien le comprendre.

Hors ligne

#37 Le 24/04/2020, à 16:08

NicoApi73

Re : [Résolu] extraire des octets d'un tableau de char (C++)

Je connais peu la bibliothèque standard. Il est possible de simplifier fortement ce que j'ai fait. Je te proposerai des mises à jour, ça devrait également améliorer la compréhension wink

Hors ligne

#38 Le 24/04/2020, à 20:48

NicoApi73

Re : [Résolu] extraire des octets d'un tableau de char (C++)

J'ai simplifié des choses en utilisant les possibilités de la bibliothèque standard :

boot_sector.cpp

#include "boot_sector.h"
#include "boot_field.h"

#include <fstream>

using namespace std;

/**********************************************************************
 * Constructor using file name containing boot content                *
 * ********************************************************************/

NTFS_boot_sector::NTFS_boot_sector(string filename)
{
	ifstream file(filename, ios::binary);
	
	consistency = false;
	
	if (file.is_open())
	{
		file.seekg (0, file.end);
		if (file.tellg() == BOOT_SECTOR_SIZE)
		{
			char buffer[BOOT_SECTOR_SIZE];
			
			file.seekg (0, file.beg);
			file.read (buffer,BOOT_SECTOR_SIZE);
			boot_sector.assign (buffer,BOOT_SECTOR_SIZE);
			consistency = true;
		}		
		file.close();
	}
}

/**********************************************************************
 * Public method providing the content of the given field             *
 * ********************************************************************/

string NTFS_boot_sector::getField (NTFS_boot_field field)
{
	if (field.is_valid ())
		return boot_sector.substr (field.start(),field.size());
		
	return "";
}

/**********************************************************************
 * Public method ensuring that the content of the boot is at least    *
 * long enough                                                        *
 * ********************************************************************/

int NTFS_boot_sector::is_valid ()
{
	return consistency;
}

boot_field.h

#ifndef BOOT_FIELD_H_
#define BOOT_FIELD_H_

#include <string>
#include <vector>
#include <fstream>

#define BOOT_SECTOR_SIZE 512
#define SEPARATOR ';'

class NTFS_boot_field
{
	private :
	std::vector<std::string> field_content;
	int consistency;

	void read_field (std::string);
	
	public :
	NTFS_boot_field(std::string,int);
	int start ();
	int size ();
	std::string field_value (int );
	
	int is_valid();
};

std::string ito_hex_string( const unsigned int );

#endif

boot_field.cpp

#include "boot_field.h"
#include <fstream>
#include <sstream>

using namespace std;

/**********************************************************************
 * Constructor, using field as index. Can be overloaded             *
 * ********************************************************************/

NTFS_boot_field::NTFS_boot_field(string filename,int field_number) // first field index = 1
{
	ifstream file(filename, ios::binary);

	consistency = false;
	if (file.is_open())
	{
		for (int i = 0;i<=field_number;i++)
		{
			string line;
			
			if (file.eof())
				break;
			if (i == field_number)
			{
				getline (file,line,SEPARATOR); // Extract next field only containing next address
				if (line.size() == 0)
					line = ito_hex_string (BOOT_SECTOR_SIZE); // Last field reach
				read_field (line);
				consistency = true;
				break;
			}
			getline (file,line);
			if (i == field_number -1)
				read_field (line);
			else
				line.clear ();
		}
		file.close();
	}
}

/**********************************************************************
 * Read all the fields and store them in a vector of string          *
 * ********************************************************************/

void NTFS_boot_field::read_field (string line)
{
	while (line.size () > 0)
	{
		field_content.resize (field_content.size()+1);
		field_content[field_content.size ()-1] = line.substr (0,line.find(SEPARATOR));
		if ((int)line.find(SEPARATOR) != (int)line.npos)
			line.erase (0,line.find(SEPARATOR)+1);
		else
			line.clear ();
	}
}

/**********************************************************************
 * Return the starting adress of the field                            *
 * ********************************************************************/

int NTFS_boot_field::start ()
{
	return stoul (field_content[0],nullptr,16);
}

/**********************************************************************
 * Return the size of the field                                       *
 * ********************************************************************/

int NTFS_boot_field::size ()
{
	return stoul(field_content[field_content.size ()-1],nullptr,16) - stoul (field_content[0],nullptr,16);
}

/**********************************************************************
 * Return if the field is valide or not                               *
 * ********************************************************************/

int NTFS_boot_field::is_valid()
{
	return consistency;
}

/**********************************************************************
 * Return the field value                                             *
 * ********************************************************************/

string NTFS_boot_field::field_value (int index)
{
	if ((unsigned int)index < field_content.size ())
		return field_content[index];
	return "";
}

/**********************************************************************
 * Convert an interger to a string in hex format                      *
 * ********************************************************************/

string ito_hex_string( const unsigned int i ) 
{
    stringstream s;
    
    s << "0x" << std::hex << i;
    return s.str();
}

Hors ligne

#39 Le 24/04/2020, à 21:56

Nuliel

Re : [Résolu] extraire des octets d'un tableau de char (C++)

Merci!
Je ne comprends pas pour l'utilisation de getline: pourquoi séparer par rapport à ; ou /n vu que les champs sont de taille fixe?

Dernière modification par Nuliel (Le 24/04/2020, à 21:56)

Hors ligne

#40 Le 24/04/2020, à 22:47

NicoApi73

Re : [Résolu] extraire des octets d'un tableau de char (C++)

Je lis la configuration du fichier config.csv.

Une ligne correspond à la description d'un champ et contient 5 colonnes (tableau dans wikipedia). Les cellules n'ont pas de nombre de caractères fixe.

Chaque ligne est délimitée par un retour chariot \n, chaque colonne par un ;

Avec getline je lis une ligne complète, puis je sépare avec substr en utilisant le ;

En fait pour ce que tu veux ce que tu as décrit, seules les informations du le premier champ (Byte offset) de la ligne concernée et le premier de la suivante sont intéressants. Ils permettent de déterminer où se trouve l'information dans le fichier de boot. J'ai extrait toutes les informations si tu souhaites les exploiter par la suite (tu peux par exemple faire une routine pour comparer la valeur retournée avec la valeur typique...

Hors ligne

#41 Le 25/04/2020, à 11:08

NicoApi73

Re : [Résolu] extraire des octets d'un tableau de char (C++)

Le site que j'utilise pour la description de ce que met à disposition la bibliothèque standard : http://www.cplusplus.com/reference/

Hors ligne

#42 Le 25/04/2020, à 11:11

Nuliel

Re : [Résolu] extraire des octets d'un tableau de char (C++)

Merci beaucoup!

Hors ligne

#43 Le 25/04/2020, à 12:11

NicoApi73

Re : [Résolu] extraire des octets d'un tableau de char (C++)

La version où tu ne charges pas le fichier binaire en mémoire :
boot_sector.h

#ifndef BOOT_SECTOR_H_
#define BOOT_SECTOR_H_

#include <string>
#include "boot_field.h"

class NTFS_boot_sector
{
	private :
	int consistency;
	std::string myfile;
	
	public :
	NTFS_boot_sector(std::string);
	std::string getField (NTFS_boot_field);
	
	int is_valid();
};

#endif

boot_sector.cpp

#include "boot_sector.h"
#include "boot_field.h"

#include <fstream>

using namespace std;

/**********************************************************************
 * Constructor using file name containing boot content                *
 * ********************************************************************/

NTFS_boot_sector::NTFS_boot_sector(string filename)
{
	ifstream file(filename, ios::binary);
	
	myfile = filename;
	
	consistency = false;
	
	if (file.is_open())
	{
		file.seekg (0, file.end);
		if (file.tellg() == BOOT_SECTOR_SIZE)
			consistency = true;
		file.close();
	}
}

/**********************************************************************
 * Public method providing the content of the given field             *
 * ********************************************************************/

string NTFS_boot_sector::getField (NTFS_boot_field field)
{
	ifstream file(myfile, ios::binary);
	string field_content;
		
	if (field.is_valid () && consistency && file.is_open())
	{
		char * buffer = new char [field.size ()];
		
		file.seekg (field.start());
		file.read (buffer,field.size ());
		field_content.assign (buffer,field.size ());
		delete[] buffer;
		file.close ();
	}
	return field_content;
}

/**********************************************************************
 * Public method ensuring that the content of the boot is at least    *
 * long enough                                                        *
 * ********************************************************************/

int NTFS_boot_sector::is_valid ()
{
	return consistency;
}

Il est possible de garder le fichier ouvert en le gardant en attribut.

EDIT : correction sur libération de la mémoire

Dernière modification par NicoApi73 (Le 25/04/2020, à 15:47)

Hors ligne

#44 Le 25/04/2020, à 13:19

Nuliel

Re : [Résolu] extraire des octets d'un tableau de char (C++)

Nickel ! Comme ça je pourrai l'adapter à l'analyse de la MFT qui peut peser assez lourd.

Je me suis attaqué à la partie création du fichier de log ddrescue pour copier la MFT sous forme de fichier, mais il faut que je continue de me documenter (je ne savais pas que la MFT pouvait être elle même fragmentée)

Hors ligne

#45 Le 25/04/2020, à 13:57

NicoApi73

Re : [Résolu] extraire des octets d'un tableau de char (C++)

Dans string NTFS_boot_sector::getField (NTFS_boot_field field) j'avais oublié de libérer la mémoire du buffer, j'ai rajouté delete buffer (il faudrait peut être s'assurer que le pointeur n'est pas null avant de le faire d’ailleurs)

Hors ligne

#46 Le 25/04/2020, à 14:19

grigouille

Re : [Résolu] extraire des octets d'un tableau de char (C++)

Il y une fuite de mémoire.


Debian (xfce) 12
HP LaserJet M1132 MFP

Hors ligne

#47 Le 25/04/2020, à 14:40

NicoApi73

Re : [Résolu] extraire des octets d'un tableau de char (C++)

grigouille a écrit :

Il y une fuite de mémoire.

C'est possible. Le seul endroit où je fais directement une allocation dynamique est dans string NTFS_boot_sector::getField (NTFS_boot_field field).  J'avais oublié de libérer la mémoire et j'ai corrigé en début d'après-midi, tout dépend à quelle heure tu as pris les sources.

Le reste est géré par la bibliothèque standard. J'ai fait l'hypothèse que les objets sont nettoyés au moment de leur destruction.

Hors ligne

#48 Le 25/04/2020, à 15:14

grigouille

Re : [Résolu] extraire des octets d'un tableau de char (C++)

La fuite mémoire est toujours là.


Debian (xfce) 12
HP LaserJet M1132 MFP

Hors ligne

#49 Le 25/04/2020, à 15:24

NicoApi73

Re : [Résolu] extraire des octets d'un tableau de char (C++)

Je ne vois pas où.

Hors ligne

#50 Le 25/04/2020, à 15:28

grigouille

Re : [Résolu] extraire des octets d'un tableau de char (C++)

Tu alloues un tableau "buffer". Pour le déallouer :

delete [] buffer;

Debian (xfce) 12
HP LaserJet M1132 MFP

Hors ligne