Concatener une chaine de quelques Mo [Résolu]

Signaler
Messages postés
1812
Date d'inscription
mardi 31 mai 2005
Statut
Membre
Dernière intervention
26 octobre 2010
-
Messages postés
7668
Date d'inscription
samedi 5 novembre 2005
Statut
Membre
Dernière intervention
22 août 2014
-
Violent Ken
Salut à tous.
Dans le cadre d'une opération de sanitization d'un disque dur, j'aurais eu besoin de créer un buffer de plusieurs Mo complètement aléatoire (chaque caractère de la string doit être aléatoire entre &H00 et &HFF)

Je dois donc faire une énorme concaténation de plusieurs millions de caractères.
J'ai par exemple çà pour le moment :

           For y = 1 To curPos2 - curPos1 + 1
               z = Int(Rnd * l1) + l2
               s = s & Chr$(z)
               If (y Mod 500) = 0 Then DoEvents  'rend la main de tps en tps
           Next y, ----
By Renfield
Bon, bien évidemment, si je concatene 2 millions (pour 2Mo) de caractères comme çà, je vais mettre 10 ans...

Rien que pour 100000 caractères (buffer de 100Ko) sans DoEvents et sans Random (concaténation triviale de "0") :

Option Explicit

Private Declare Function GetTickCount Lib "kernel32.dll" () As Long

Private Sub Command1_Click()
Dim s As String
Dim x As Long
Dim lTim As Long

   lTim = GetTickCount
   s = vbNullString
   
   For x = 1 To 100000
       s = s & "0"
   Next x
   
   Me.Caption = CStr(GetTickCount - lTim)

End Sub , ----
By Renfield
je met déjà 3.5 secondes.... alors avec du DoEvents, avec du Random et 2M caractères, c'est mort !

Evidemment, en subdivisant mes opérations de concaténation, je gagne ENORMEMENT de temps :

Option Explicit

Private Declare Function GetTickCount Lib "kernel32.dll" () As Long

Private Sub Command1_Click()
Dim s(100) As String
Dim y As Long
Dim s2 As String
Dim x As Long
Dim lTim As Long

   lTim = GetTickCount
   s2 = vbNullString
   
   For y = 1 To 100
       s(y) = vbNullString
       For x = 1 To 1000
           s(y) = s(y) & "0"
       Next x
       s2 = s2 & s(y)
   Next y
   
   Me.Caption = CStr(GetTickCount - lTim) & "  " & CStr(Len(s2))

End Sub , ----
By Renfield
ne met plus que 0.1 seconde.
Ce n'est malheureusement pas suffisant...

Quelqu'un aurait une idée pour optimiser la chose ?
Merci, @+

Hex Editor VB

39 réponses

Messages postés
21041
Date d'inscription
jeudi 23 janvier 2003
Statut
Modérateur
Dernière intervention
21 août 2019
29
http://brunews.com/bnAlloc.zip



Prends (2,5 Ko) et dis moi que j'enlève.

Fais un Declare bnAlloc2MoAlea Lib .... As Long
aucun param, il te retourne le pointeur sur les 2 Mo ALLOUES par la fonction. Tu te sers de cette valeur pour WriteFile (2eme param) mais tu n'en modifies JAMAIS la valeur.
Dès que plus besoin, tu appelles la: Declare Sub bnFreeAlloc Lib...(ByVal pmem As Long) pour libérer la mémoire.

ciao...
BruNews, MVP VC++
Messages postés
21041
Date d'inscription
jeudi 23 janvier 2003
Statut
Modérateur
Dernière intervention
21 août 2019
29
LE CODE:

__declspec(naked) long* __stdcall bnAlloc2MoAlea()
{
  __asm {
    push    PAGE_READWRITE
    push    MEM_COMMIT or MEM_RESERVE or MEM_TOP_DOWN
    push    2097152 ;// 2 Mo
    push    0
    call    dword ptr VirtualAlloc
    test    eax, eax
    je      short allocEXIT
    push    edi
    push    eax
    push    ebx
    mov     edi, eax          ;// EDI = *pdt
    mov     ebx, 131072       ;// NBR TOURS DE 16 OCTETS
    rdtsc
    mov     edx, eax          ;// EDX = seedRand
    mov     ecx, 214013
    sub     edi, 4
  nextNBR:
    mov     eax, edx
    mul     ecx
    add     eax, 2531011
    add     edi, 4
    mov     edx, eax          ;// seedRand
    ror     eax, 16
    add     eax, 7979999
    mov     [edi], eax
   
    mov     eax, edx
    mul     ecx
    add     eax, 2531011
    add     edi, 4
    mov     edx, eax          ;// seedRand
    ror     eax, 16
    add     eax, 7979999
    mov     [edi], eax
   
    mov     eax, edx
    mul     ecx
    add     eax, 2531011
    add     edi, 4
    mov     edx, eax          ;// seedRand
    ror     eax, 16
    add     eax, 7979999
    mov     [edi], eax
   
    mov     eax, edx
    mul     ecx
    add     eax, 2531011
    add     edi, 4
    mov     edx, eax          ;// seedRand
    ror     eax, 16
    add     eax, 7979999
   
    dec     ebx
    mov     [edi], eax
    jnz     short nextNBR
    pop     ebx
    pop     eax               ;// POINTEUR ORIGINAL
    pop     edi
allocEXIT:
    ret     0
  }
}

ciao...
BruNews, MVP VC++
Messages postés
7668
Date d'inscription
samedi 5 novembre 2005
Statut
Membre
Dernière intervention
22 août 2014
26
Bonjour,

Je ne vais pas te parler de la théorie des crètes (qui te montrerait que cette "sanitization" ne protège hélàs pas vraiment)...

Bon ! revenons à nos moutons :

Au lieu de concaténer 0 par 0 en allant chaque fois à la fin de ta chaine :
Tu ne gagnerais pas plus de temps à utiliser String ?
Messages postés
1812
Date d'inscription
mardi 31 mai 2005
Statut
Membre
Dernière intervention
26 octobre 2010
1
Violent Ken
Salut,

Ah ok ;)
Je me suis mal exprimé : j'ai fait un petit bench avec des concaténations de "0" pour tester la vitesse de multiples concaténation.

Mais en fait, mon code pour la sanitization s'effectue en 3 passes :
- passe 1 ==> on remplit de &H55 (01010101 en binaire)
- passe 2 ==> on remplit de &HAA (le complémentaire en binaire)
- passe 3 ==> c'est là qu'on remplit aléatoirement avec une concaténation de caractères tirés au hasard.

@+

Hex Editor VB
Messages postés
1812
Date d'inscription
mardi 31 mai 2005
Statut
Membre
Dernière intervention
26 octobre 2010
1
Violent Ken
J'ai trouvé un bout de documentation : mon processus de sanitization est de type e ("Overwrite all addressable locations with a character, its complement, then a random character".) : http://www.hipaadvisory.com/tech/disksan.htm#aC'est donc dans la 3eme passe que je doit faire un enregistrement aléatoire de chaque byte de tout le fichier/disque... et c'est là que j'aurais besoin d'optimiser l'algorithme qui est censé créer un buffer aléatoire.

@+

Hex Editor VB
Messages postés
21041
Date d'inscription
jeudi 23 janvier 2003
Statut
Modérateur
Dernière intervention
21 août 2019
29
C'est quoi le but des 2 premières passes si tu réécris tout le buffer en valeurs aléatoires ?
J'ai du lire en diagonale tes explications plus haut...

ciao...
BruNews, MVP VC++
Messages postés
1812
Date d'inscription
mardi 31 mai 2005
Statut
Membre
Dernière intervention
26 octobre 2010
1
Violent Ken

Salut,
tout d'abord le buffer ne sert qu'à être passé en paramètre de l'API WriteFile pour écrire dans le fichier/disque les informations souhaitées. Donc le buffer lui tout seul n'a bien sur aucun besoin d'être écrit trois fois de suite.

Passe 1 ==> création d'un buffer avec uniquement des &H55, puis écriture de ce buffer dans le fichier/disque
Passe 2 ==> création d'un buffer avec uniquement des &HAA, puis écriture de ce buffer dans le fichier/disque
Passe 3 ==> création d'un buffer aléatoire puis écriture dans le fichier/disque.

La sanitization s'effectue en plusieurs passes pour obtenir un résultat correct.

Dans mon cas, j'ai choisi d'appliquer 3 passes comme décrit plus haut. C'est pas moi qui ai choisi, c'est un standart DoD (Department of Defense) ==> voir http://www.hipaadvisory.com/tech/disksan.htm

Et c'est donc dans la troisième passe que je cherche un moyen de créer une string aléatoire de manière optimisée.

@+



Hex Editor VB
Messages postés
7668
Date d'inscription
samedi 5 novembre 2005
Statut
Membre
Dernière intervention
22 août 2014
26
Bonjour Brunews,
Les 2 premières passes ne sont pas inutiles : elles servent à diminuer le nombre des crètes résiduelles (il devrait en faire au moins 10, d'ailleurs)

La 3ème passe (écriture aléatoire) contribue également à "brouiller les cartes", en effet.


Il reste (mais c'est un autre sujet) qu'on en était en France (il y a 5 ans) à pouvoir continuer à lire les crètes après 10 passes et que je ne sais pas à combien nous en sommes aujourd'hui... Les crètes ? elles résultent tout simplement du fait que la tête de lecture/écriture ne peut, pour des raisons purement mécaniques, avoir toujours la même exacte position.... C'est la raison pour laquelle on utilise en général des procédés de démagnétisation à l'aide d'un gros electro-aimant (le tout sacrément arrimé, notamment le disque lui-même) lorsque les informations à protéger sont sensibles.

Je vois mal comment, dans de telles conditions (écritures aléatoires) Il pourrait accélérer les choses.

Mais la vitesse importe-t-elle vraiment pour une telle opération ?
Les plans d'urgence que j'ai connus prévoyaient TOUS l'extraction du disque et sa destruction à la masse (carrément). Le disque dur était dans cette malheureuse perspective placé dans un tiroir extractibe et... la masse (hé oui) était toute proche, toujours prête ...(ce n'est pas une plaisanterie jmfienne, loin de là...)
Messages postés
21041
Date d'inscription
jeudi 23 janvier 2003
Statut
Modérateur
Dernière intervention
21 août 2019
29
OK OK j'ai compris ton affaire.

Regarde ici, tu as le modèle:
http://www.vbfrance.com/code.aspx?ID=33938
dans le fichier CodAsmC.txt tu verras la fonction RemplirLongAlea(), devrait difficilement dépasser les 2/100 s pour remplir 2 Mo.
Suffit de compiler ça en dll et tu l'appelles depuis VB.

ciao...
BruNews, MVP VC++
Messages postés
21041
Date d'inscription
jeudi 23 janvier 2003
Statut
Modérateur
Dernière intervention
21 août 2019
29
jmf -> je confirme, j'ai matraqué des vieux disques à moi avant de les virer.
Second avantage de cette méthode, ça défoule et c'est moins nuisible que le valium.

ciao...
BruNews, MVP VC++
Messages postés
1812
Date d'inscription
mardi 31 mai 2005
Statut
Membre
Dernière intervention
26 octobre 2010
1
Violent Ken
Héhé oui, ce n'est pas une plaisanterie, d'ailleurs le procédé numéro m (DOD 5220.22-M) est très clair : "Destroy - Disintegrate, incinerate, pulverize, shred, or melt".

On peut également utiliser le "degausser" : http://gfx.ibas.com/data_erasure/degausser/degausser_DG02.jpg (champ magnétique puissant).

Enfin, si l'on se limite à des processus logiciels (écritures en multi passes), le problème est de créer cette fameuse string aléatoire.
Parce que pour 1Go, il y a près de 2 millions de secteurs de disque (de 512)... donc il faudrait par exemple 1.36 millions de chaines aléatoires de 512 octets pour un simple DivX...

Brunews ==> je vais regarder ta source et essayer de la compiler, merci bien !

@+

Hex Editor VB
Messages postés
7741
Date d'inscription
mercredi 1 septembre 2004
Statut
Membre
Dernière intervention
24 septembre 2014
38
Juste une petite info en passant, pour l'effacement de données sur support magnétique (tout support, pas seulement les disques durs), il existe plusieurs "normes" essentiellement développer par les départements de défences des pays, USA en tete.

Les plus utilisées dans les logiciels publics et professionels sont les alogorithmes PseudoRandom Data (1 passe de données aléatoires), DoD 5220.22-M (3 passes), DoD 5220.22-M / ECE (7 passes) et même jusqu'à 35 passes pour l'algo de Gutmann, voire plus.

Mais ce qui n'est pas dit dans les différents logiciels d'effacement (comme Blancco DataCleaner ou WinEraser, ou autre) c'est que malgrés ces réécritures certaines données peuvent toujours etre récupérées par la methode de lecture des cretes.

Cela est compliqué, long et cher puisque cela necessite de démonter le disque dur en salle blanche et de lire chaque plateau avec des appareils spécialisés. Cela ne se fait qu'en laboratoire hyperspécialisés.
Evidement plus il y aura eu d'écriture moins de données seront récupérées et plus de temps il faudra, Mais tout n'est jamais completement effacer.

D'ailleurs Jacques, il existe un de ces labo pas très loin de chez toi je crois bien.

---- Sevyc64  (alias Casy) ----<hr size="2" width="100%" /># LE PARTAGE EST NOTRE FORCE #
Messages postés
21041
Date d'inscription
jeudi 23 janvier 2003
Statut
Modérateur
Dernière intervention
21 août 2019
29
Quelle différence d'écrire des séries de 0 ou autres nombres ? ça écrasera toujours ce qui se trouvait avant, non ?

ciao...
BruNews, MVP VC++
Messages postés
1812
Date d'inscription
mardi 31 mai 2005
Statut
Membre
Dernière intervention
26 octobre 2010
1
Violent Ken
casy ==> Merci pour ces précisions !

Brunews ==> Aucune idée, je ne fais que suivre les protocoles de sanitization du département de la défense américain (DOD 5220.22-M).
Donc trois passes (un char, son complémentaire en binaire, et aléatoire).

Si quelqu'un peut nous en dire plus, je suis également preneur ^^

@+

Hex Editor VB
Messages postés
7741
Date d'inscription
mercredi 1 septembre 2004
Statut
Membre
Dernière intervention
24 septembre 2014
38
Essayer des logiciels comme Easy Recovery ou Stellar Phoenix ou GetDataBack et vous serait surpris des résultats.

J'ai encore fait une demo il y a 2 semaines avec EasyRecovery sur un disque qui venait d'etre formaté, environ 85% des données ont pus etre récupérées dont des fichiers qui avaient été effacés depuis plusieurs semaines avant le formatage.

---- Sevyc64  (alias Casy) ----<hr size="2" width="100%" /># LE PARTAGE EST NOTRE FORCE #
Messages postés
7668
Date d'inscription
samedi 5 novembre 2005
Statut
Membre
Dernière intervention
22 août 2014
26
Bonsoir Casy,
Hé Hé !
Et encore, çà, c'est encore assez gentil...
Tu prends maintenant le même disque, le mets sur une machine dotée d'UNIX... et tu "tricotes" un joli maillot...
Messages postés
1812
Date d'inscription
mardi 31 mai 2005
Statut
Membre
Dernière intervention
26 octobre 2010
1
Violent Ken
Héhé oui, les logiciels de récupération sont puissants... d'ailleurs je me demande bien comment ils fonctionnent ?

Sinon, pour la récupération "bas de gamme" (la récupération des fichiers qui n'ont pas été overwrite par un autre) il est toujour possible de récupèrer les emplacements des fichiers supprimés dans la MFT (voir http://www.vbfrance.com/codes/ACCES-DIRECT-DISQUE_32480.aspx) et de recréer ensuite le fichier par lecture dans le disque (CreateFile, ReadFile, SetFilePointerEx...)
Mais bon ! Si un secteur a été modifé sur le disque à l'emplacement du fichier, c'est mort....(-__-)'

Enfin bon, c'est la seule "récupération de fichier" qui me semble possible de coder en VB6 !

@+

Hex Editor VB
Messages postés
1812
Date d'inscription
mardi 31 mai 2005
Statut
Membre
Dernière intervention
26 octobre 2010
1
Violent Ken

 


En fait, la concaténation de deux millions de strings est impossible avec des '&'.
Il n'y a qu'à essayer ce code pour s'en convaincre :



Option Explicit

Private Sub Form_Load()
Dim x As Long
Dim s As String

   For x = 1 To 2000000
       If (x Mod 1000) = 0 Then
           DoEvents
           Beep
       End If
       s = s & "0"
   Next x
End Sub ,

----

Hex Editor VB
Messages postés
21041
Date d'inscription
jeudi 23 janvier 2003
Statut
Modérateur
Dernière intervention
21 août 2019
29
Je te fais la dll, tu testeras.

ciao...
BruNews, MVP VC++
Messages postés
1812
Date d'inscription
mardi 31 mai 2005
Statut
Membre
Dernière intervention
26 octobre 2010
1
Violent Ken
Ok, encore mieux pour la vitesse ! Merci bien ;)

Hex Editor VB