Mega Code Archive

 
Categories / Delphi / System
 

NTFS Alternate Data Streams Dir Listing

Title: NTFS Alternate Data Streams Dir Listing Question: In article 4143 Milad Efterkharian demonstrates the operation of W2K/XP NTFS "Alternate Data Streams". In essence it is possible to hide data in ADS by methods such as Memo1.Lines.SaveToFile('c:\temp\MyFile.Txt:MyHide'); and Retrieve such data as Memo1.Lines.LoadFrom('c:\temp\MyFile.txt:MyHide'); This is fine as long as you know the name of the ADS. There are not many tools that will list these hidden ADS files, even Windows Explorer does not list them. This function will list ADS file names of a given file in a string list. The objects property of the list contains the file size. eg. GetFileADSNames('c:\temp\MyFile.txt',Listbox1.Items); ... c:\temp\myfile,txt:mike ... c:\temp\myfile.txt:gary ... etc. iFileSize : integer; for i := 0 to Listbox1.Items.Count - 1 do begin iFileSize := integer(Listbox1.Items.Objects[i]); ..... ..... end; Search the web for "Alternate Data Streams" for more information on this topic. Answer: uses Windows; // =============================================================== // Load a string list with ADS (Alternate Data Stream) names // the integer(AList.Object[?]) contains the File Size // =============================================================== procedure GetFileADSNames(const AFileName : string; AList : TStrings); var hHandle : THandle; sName : string; iNumRead,iLo,iHi : DWORD; pCtx : pointer; pBuffer,pBytePtr : PByte; pWsi : PWin32StreamID absolute pBuffer; wszStreamName: array[0..MAX_PATH] of widechar; begin AList.BeginUpdate; AList.Clear; GetMem(pBuffer,4096); pCtx := nil; hHandle := CreateFile(PChar(AFileName),GENERIC_READ,0,nil,OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS,0); if (hHandle INVALID_HANDLE_VALUE) then begin while true do begin // We are at the start of a stream header. read it. pBytePtr := pBuffer; if BackupRead(hHandle,pBytePtr,20,iNumRead, false,true,pCtx) then begin if iNumRead = 0 then break else begin // Can we get a stream name ? sName := ''; if pWsi.dwStreamNameSize 0 then begin FillChar(wszStreamName,SizeOf(wszStreamName),0); if BackupRead(hHandle,@(wszStreamName[0]),pWsi.dwStreamNameSize, iNumRead,false,true,pCtx) then begin if iNumRead pWsi.dwStreamNameSize then break else begin // Yep, have a name, convert from WideChar sName := WideCharToString(wszStreamName); // Clean up Name if sName '' then begin sName := copy(sName,2,length(sName)); sName := ':' + copy(sName,1,pos(':',sName) - 1); end; AList.AddObject(AFileName + sName,TObject(pWsi.Size)); end; end else break; end; // Skip to start of next stream data if pWsi.Size 0 then BackupSeek(hHandle,high(DWORD),high(DWORD),iLo,iHi,@pCtx); end; end else break; end; // Release the context BackupRead(hHandle,pBuffer,0,iNumRead,true,false,pCtx); CloseHandle(hHandle); end; FreeMem(pBuffer); AList.EndUpdate; end;