#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 )
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
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
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++)
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