Compi Opublikowano 3 Października 2013 Udostępnij Opublikowano 3 Października 2013 JPG Undeleter Autor: Daniel MazurWaga: 2mbOpis: Ostatnio z nudów postanowiłem podszkolić się w trochę niskopoziomowych sprawach związanych z komputerami itp. Rozmyślając, co tu można by było napisać wpadłem właśnie na taki pomysł. Programik ten jest w stanie odczytać usunięte jpgi z dysku, pendrive, karty pamięci (i chyba pamięci telefonu ale nie wiem :$). Obsługuje wszystkie wszystkie sygnatury jpegów, od standardowych po Canona. Po znalezieniu magicznego numeru program odczytuje kolejne 3,90MB dla pewnego odzyskania. Nie szuka stopki pliku. Małe info: Ten szalony program ma zaledwie 220 linijek kodu Nie grozi wam żadna utrata danych, gdyż ten program tylko czyta dysk, nic nie zapisując. Dlatego dla pewności proszę dać Save to... i wskazać gdzie ma zapisywać, koniecznie na innym dysku niż skanowany.Sposób użycia: Odpalamy program Klikamy Save to... i wybieramy miejsce poza skanowanym dyskiem Klikamy na dysk, który chcemy zeskanować Czekamy na efekty Dlaczego daje to w demach? Bo planuje rozszerzyć możliwości do większości znanych formatów plików + konfiguracji własnych Screeny: Download:https://gmclan.org/up3899_4_undeletah.html Jeśli znajdziesz buga, niezwłocznie mnie poinformuj. Odnośnik do komentarza Udostępnij na innych stronach Więcej opcji udostępniania...
Administratorzy gnysek Opublikowano 3 Października 2013 Administratorzy Udostępnij Opublikowano 3 Października 2013 Fajnie, jakby do tego był kod źródłowy aby uczyć wszystkich ;) Odnośnik do komentarza Udostępnij na innych stronach Więcej opcji udostępniania...
Compi Opublikowano 3 Października 2013 Autor Udostępnij Opublikowano 3 Października 2013 Ok ;) Na początek trochę teorii. Dużo plików ma nagłówki lub jakieś magiczne liczby w stylu 0xFEEDFACE itp, które charakteryzują format i pochodzenie. Dla przykład pliki JPG zaczynają się od 0xFFD8FFE* (gdzie * oznacza losowy znak, zależnie od producenta aparatu, 0 dla programów typu paint). Znając nagłowki/liczby można odkopać plik z gąszczu bajtów. Aby odnaleźć plik bo usunięciu lub logicznym uszkodzeniu pliku musimy dostać się do dysku tak jak do pliku. Tak jakbyśmy chcieli odczytać naraz całą zawartość. Jeśli ktoś korzystał z rodziny uniksów, to kojarzy że tam urządzenie są reprezentowane przez pliki w folderze dev (dysk to np. /dev/sda). W Windowsie jest ukryta kernelowa ścieżka która przechowuje urządzenia. Tych ścieżek jest kilka ale wszystkie mają podobne dowiązania. To tych ścieżek należy między innymi: \Device\Harddisk*\ \\?\PhysicalDrive* W starych windowsach \\.\C Gdy otworzymy taki dysk pozostaje tylko odczytywać po fragmencie do bufora i szukać w nim sygnatur. UWAGA! Jako że mam bardzo brzydki styl pisania i pełno nieużywanych zmiennych i zbędnych komentarzy, laik może mieć trudności. Przepraszam, że przedstawiam taki syfiasty kod, mea culpa GML unit main; {$mode objfpc}{$H+} interface uses Classes, SysUtils, FileUtil, BCPanel, BCLabel, BGRAImageList, BGRAFlashProgressBar, BGRAKnob, BCButton, Forms, Controls, Graphics, Dialogs, ComCtrls, StdCtrls, ExtCtrls, Windows; type { TForm1 } TForm1 = class(TForm) BCButton1: TBCButton; BCButton2: TBCButton; BCLabel1: TBCLabel; BCLabel2: TBCLabel; BCLabel3: TBCLabel; BCLabel4: TBCLabel; BCPanel1: TBCPanel; knob: TBGRAKnob; Label8: TLabel; pr1: TBGRAFlashProgressBar; BGRAImageList1: TBGRAImageList; Edit1: TEdit; Label1: TLabel; Label2: TLabel; Label3: TLabel; Label4: TLabel; Label5: TLabel; Label6: TLabel; Label7: TLabel; ListView: TListView; Memo1: TMemo; sdd1: TSelectDirectoryDialog; procedure BCButton1Click(Sender: TObject); procedure BCButton2Click(Sender: TObject); procedure Button1Click(Sender: TObject); procedure FormCreate(Sender: TObject); procedure ListViewClick(Sender: TObject); private { private declarations } public { public declarations } end; Type TCharArray = Array[0..MAX_PATH] of TCHAR; var Form1: TForm1; mountPoint : LPCTSTR; implementation {$R *.lfm} { TForm1 } function GetVolumeNameForVolumeMountPointA(lpszVolumeMountPoint: LPCTSTR; lpszVolumeName: LPCTSTR; cchBufferLength: DWORD): BOOL; stdcall; external 'kernel32'; Function LengthA(A: TCHARArray): Integer; Begin For Result := 0 To MAX_PATH Do if (A[Result] = #0) Then Exit; End; procedure czytaj(fraza:string); Var I : Integer; volumeDevicePath : TCHARArray; volumeDeviceHandle : HANDLE; extents : Record NumberOfDiskExtents: DWORD; Extents : Array[0..0] of Record DiskNumber : DWORD; StartingOffset: Int64; ExtentLength : Int64; End; End; returnedBytes : DWORD; diskNumber : DWORD; diskDevicePath : TCHARArray; diskDeviceHandle : HANDLE; buffer : Array[0..512] of char; bytesRead : DWORD; partitionIdentifier: Byte; ss:string; pattern:string; ii,jj:integer; size:integer; szukaj: shortstring; plik:TMemoryStream; znaleziono:boolean; jpgs,jpge:string; fps1,fps2,c:integer; Begin jpgs:=chr($FF)+chr($D8)+chr($FF); // Naglowek JPG jpge:=chr($FF)+chr($D9); plik:=TMemoryStream.Create(); plik.Clear; For I := 0 To MAX_PATH Do volumeDevicePath := #0; GetVolumeNameForVolumeMountPointA(mountPoint, volumeDevicePath, MAX_PATH); if not (GetLastError in [0, 234]) Then Begin ShowMessage('GetVolumeNameForVolumeMountPointA :: GetLastError = '+ inttostr(GetLastError)+ ' (device not found?)'); exit; End; volumeDevicePath[LengthA(volumeDevicePath)-1] := #0; volumeDeviceHandle := CreateFile(volumeDevicePath, GENERIC_READ, FILE_SHARE_READ or FILE_SHARE_WRITE or FILE_SHARE_DELETE, nil, OPEN_EXISTING, 0, 0); if (GetLastError <> 0) Then Begin ShowMessage('CreateFile :: GetLastError = '+inttostr(GetLastError)); exit; End; DeviceIoControl(volumeDeviceHandle, 5636096, nil, 0, @extents, sizeof(extents), returnedBytes, nil); if (GetLastError <> 0) Then Begin ShowMessage('DeviceIoControl :: GetLastError = '+inttostr(GetLastError)); exit; End; diskNumber := extents.Extents[0].DiskNumber; CloseHandle(volumeDeviceHandle); diskDevicePath := '\\?\PhysicalDrive'+IntToStr(diskNumber); diskDeviceHandle := CreateFile(diskDevicePath, GENERIC_READ, FILE_SHARE_READ , nil, OPEN_EXISTING, 0, 0); //or FILE_SHARE_WRITE or FILE_SHARE_DELETE SetFilePointer(diskDeviceHandle, 0, nil, FILE_BEGIN); form1.memo1.Lines.clear; form1.memo1.Lines.Add('Scan...'+DateTimeToStr(Now)); size:=round(DiskSize(form1.ListView.ItemIndex+3)/512); ShowMessage(inttostr(round(DiskSize(form1.ListView.ItemIndex+3)/(1024*1024)))+' megabytes to scan'); form1.pr1.MaxValue:=size; SetCurrentDir(form1.sdd1.FileName); plik.Size:=512; szukaj:=jpgs; c:=0; ii:=strtoint(form1.Edit1.Text)*2048; jj:=ii; repeat begin // fps1:=gettickcount(); {$ASMMODE INTEL} asm call gettickcount mov fps1,eax end; SetFilePointer(diskDeviceHandle, jj*512, nil, FILE_CURRENT); ReadFile(diskDeviceHandle, buffer, 512, bytesRead, nil); Form1.Caption :='Undeleter, bytes read at step: '+inttohex(bytesread,2); if bytesRead = 0 then begin ShowMessage('Physical I/O error'); exit; end; ii:=Pos(szukaj,buffer); if (ii>0) and (c=0) then begin Form1.Memo1.Lines.Add('JPG Marker at'+inttostr(round(jj/2048))+'mb +'+inttostr(ii)+' byte'); c:=1; end; if (c<8000) and (c>0) then begin if c>1 then ii:=1; plik.Write(buffer[ii-1],length(buffer)-ii); plik.Size:=plik.Size+512; inc(c); end; if c=8000 then begin Form1.Memo1.Lines.Add('Footer found'); plik.SaveToFile('img_'+inttohex(jj,2)+'.jpg'); plik.clear; c:=0;jj:=jj-7900; end; Application.Processmessages; end; inc(jj,1); if jj mod 1000=0 then begin form1.pr1.Value:=jj; form1.pr1.Hint:=inttostr(round(jj/2048)); fps2:=gettickcount; fps1:=fps2-fps1; fps2:=1000-fps1; fps1:=round(1000/(fps2-fps1)) ;//round((512*fps2)/1024); form1.knob.Value:=fps1; end; until jj=size ; Form1.Memo1.Lines.Add('END'+DateTimeToStr(Now)); end; procedure TForm1.FormCreate(Sender: TObject); var i : Integer; DriveType : Integer; ListItem: TListItem; Bufor:array[0..MAX_PATH] of Char; MaxCompLength, FileSystemFlags : DWORD; begin randomize; for I := Ord('A') to Ord('Z') do begin DriveType := GetDriveType(PChar(Chr(i) + ':\')); if not (DriveType = 0) and not (DriveType = 1) then begin GetVolumeInformation(PChar(Chr(i) + ':\'), Bufor, SizeOf(Bufor), nil, MaxCompLength, FileSystemFlags, nil, 0); ListItem := ListView.Items.Add; ListItem.Caption := Chr(i) + ':\' + ' ' + Bufor; if (DriveType = DRIVE_CDROM) then ListItem.ImageIndex := 1; if (DriveType = DRIVE_FIXED) then ListItem.ImageIndex := 0; if (DriveType = DRIVE_REMOVABLE) then ListItem.ImageIndex := 2; end; end; end; procedure TForm1.Button1Click(Sender: TObject); begin Memo1.Visible:=not memo1.visible; end; procedure TForm1.BCButton1Click(Sender: TObject); begin halt; end; procedure TForm1.BCButton2Click(Sender: TObject); begin if sdd1.execute then begin end; end; procedure TForm1.ListViewClick(Sender: TObject); var DirName: String; Sectors: DWORD; Bytes: DWORD; FreeClust: DWORD; TotalClust: DWORD; begin if listview.Selected.Caption='' then exit;; DirName := ListView.Selected.Caption[1]; if GetDiskFreeSpace(PChar(DirName + ':\'), Sectors, Bytes, FreeClust, TotalClust) then begin Label1.Caption := 'Sectors in clusters: ' + IntToStr(Sectors); Label2.Caption := 'Bytes in sector: ' + IntToStr(Bytes); Label3.Caption := 'Free clusters: ' + IntToStr(FreeClust); Label4.Caption := 'Clusters count: ' + IntToStr(TotalClust); mountpoint:= PChar(DirName + ':\'); czytaj('Windows'); end else begin end; end; end. Odnośnik do komentarza Udostępnij na innych stronach Więcej opcji udostępniania...
Rekomendowane odpowiedzi
Jeśli chcesz dodać odpowiedź, zaloguj się lub zarejestruj nowe konto
Jedynie zarejestrowani użytkownicy mogą komentować zawartość tej strony.
Zarejestruj nowe konto
Załóż nowe konto. To bardzo proste!
Zarejestruj sięZaloguj się
Posiadasz już konto? Zaloguj się poniżej.
Zaloguj się