|
Oggi mi sono costruito un applicativo per prelevare i dati contenuti nel
Protected Storage. Cosaaa???? Si beehhh in pratica li dentro ci sono ad esempio
i nomi utente e le password dei moduli delle pagine web (naturalmente nel caso
in cui il salvataggio delle informazioni sui moduli sia abilitato: Internet
Explorer -> Strumenti -> Opzioni internet -> Contenuto -> Informazioni personali).
1. Concetti base
Il servizio di Protected Storage viene usato da Windows per salvare in forma
criptata informazioni quali ad esempio password in Internet Explorer, etc..
Chiaramente non vi è una documentazione ufficiale delle librerie che si occupano
di tali operazione ma fortunatamente l'obiettivo non è così ostico come potrebbe
sembrare. Nel seguito vedremo appunto come decriptare le informazioni contenute
nel Protected Storage.
1.1 Struttura del Protected Storage
La figura seguente esprime in maniera chiara l'organizzazione del Protected
Storage
Protected storage provider contiene vari elementi della categoria
Type. Ogni elemento della categoria Type contiene elementi della
categoria SubType. Ogni elemento della categoria SubType contiene
elementi della categoria Item. Ogni elemento della categoria Item
contiene i dati (tra i quali ci sono ad esempio utenze e password, etc...)
2. Implementazione
Il fulcro di tutto è la dll pstorec.dll che implementa la COM
Interface denominata IPStore. Inoltre esporta le seguenti 2 funzioni:
PStoreCreateInstance
PStoreEnumProviders
N.B. useremo solo PStoreCreateInstance.
2.1 Importare la Type Library relativa alla dll pstorec.dll
Come prima cosa occorre eseguire
regsvr32 pstorec.dll
e poi si può procedere alla solita maniera ossia da Delphi: Project -->
Import Type Library

ed otteniamo la Unit di Import il cui nome di default è PSTORECLib_TLB.pas.
2.2 Inizio
Come prima cosa dobbiamo crearci una Unit che contiene la dichiarazione della
funzione PStoreCreateInstance (funzione esportata da pstorec.dll).
Nella stessa Unit inseriremo anche la dichiarazione dell'api CoTaskMemFree
(deallocazione di memoria nel contesto della tecnologia COM; opposto di
CoTaskMemAlloc che effettua una allocazione) esportata da ole32.dll.
unit Pstoreclib;
interface
uses
Windows, PSTORECLib_TLB;
function PStoreCreateInstance(
var ppProvider: IPStore;
pProviderID: PGUID;
pReserved: Pointer;
dwFlags: DWORD): HRESULT; stdcall;
procedure CoTaskMemFree(
pv: Pointer); stdcall;
var
DLLHandle: THandle;
implementation
const
pstorec = 'pstorec.dll';
ole32 = 'ole32.dll';
{$IFDEF DYNAMIC_LINK}
var
_PStoreCreateInstance: Pointer;
function PStoreCreateInstance;
begin
GetProcedureAddress(_PStoreCreateInstance, pstorec, 'PStoreCreateInstance');
asm
mov esp, ebp
pop ebp
jmp [_PStoreCreateInstance]
end;
end;
{$ELSE}
function PStoreCreateInstance; external pstorec name 'PStoreCreateInstance';
{$ENDIF DYNAMIC_LINK}
{$IFDEF DYNAMIC_LINK}
var
_CoTaskMemFree;
function CoTaskMemFree;
begin
GetProcedureAddress(_CoTaskMemFree, ole32, 'CoTaskMemFree');
asm
mov esp, ebp
pop ebp
jmp [_CoTaskMemFree]
end;
end;
{$ELSE}
procedure CoTaskMemFree; external ole32 name 'CoTaskMemFree';
{$ENDIF DYNAMIC_LINK}
end.
Bene, la Unit di import della type library e questa Unit: si può dire che abbiamo tutto. Andiamo quindi direttamente ai paragrafi successivi per vedere finalmente come ottenere le informazioni sul Protected Storage. 2.3 Operazione base La prima cosa da fare quando si vuole esplorare il Protected Storage è chiamare la funzione PStoreCreateInstance
var
FProvider: IPStore;
ProviderID: PGUID;
...
PStoreCreateInstance(FProvider, ProviderID, nil, 0);
Otteniamo in questo modo un reference alla IPStore Interface (FProvider) ed il GUID del Protected Storage Provider (ProviderId). Una volta fatto questo si possono ottenere tutte le altre informazioni. 2.4 Informazioni sul Protected Storage Provider Per ottenere informazioni sul Provider possiamo usare la seguente procedura
//dalla Unit di import PSTORECLib_TLB
(* PUserType1 = ^_PST_PROVIDERINFO; {*}
_PST_PROVIDERINFO = packed record
cbSize: LongWord;
ID: TGUID;
Capabilities: LongWord;
szProviderName: PWideChar;
end;*)
//
procedure ProviderInfo(FProvider: IPStore);
var
ppInfo: PUserType1;
begin
FProvider.GetInfo(ppInfo);
//scrivo l'informazione ottenuta ad esempio in un campo Memo su una Form
Form1.Memo1.Lines.Add(ppInfo.szProviderName);
end;
2.5 Enumerare i TYPE I TYPE possono essere rappresentati in 2 modi: 1) GUID 2) Nome Di seguito la procedura per enumerare i TYPE rappresentandoli sia tramite GUID sia tramite Nome
function Type_Name(pType: TGUID): string;
var
pst: PUserType3;
begin
pst := nil;
FProvider.GetTypeInfo(0, pType, pst, 0);
Result := String(pst^.szDisplayName);
CoTaskMemFree(pst);
end;
procedure ElencoTypes(FProvider: IPStore);
var
ppEnumTypes: IEnumPStoreTypes;
NroElementiRestituiti: Cardinal;
GUID_Type: TGUID;
begin
FProvider.EnumTypes(0, 0, ppEnumTypes);
NroElementiRestituiti := 0;
repeat
ppEnumTypes.Next(1, GUID_Type, NroElementiRestituiti);
if NroElementiRestituiti > 0 then
begin
Form1.Memo1.Lines.Add(GUIDToString(GUID_Type)+ '---' +
Type_Name(GUID_Type));
end;
until NroElementiRestituiti = 0;
end;
2.6 Enumerare i SUBTYPE Come nel caso dei TYPE, anche i SUBTYPE sono rappresentabili sia tramite GUID sia tramite Nome
function SubType_Name(pType, pSubType: TGUID): string;
var
pst: PUserType3;
begin
pst := nil;
FProvider.GetSubtypeInfo(0, pType, pSubType, pst, 0);
Result := String(pst^.szDisplayName);
CoTaskMemFree(pst);
end;
procedure ElencoSubTypes(FProvider: IPStore; GUID_Type: TGUID);
var
ppEnumSubTypes: IEnumPStoreTypes;
NroElementiRestituiti: Cardinal;
GUID_SubType: TGUID;
begin
FProvider.EnumSubTypes(0, GUID_Type, 0, ppEnumSubTypes);
NroElementiRestituiti := 0;
repeat
ppEnumSubTypes.Next(1, GUID_SubType, NroElementiRestituiti);
if NroElementiRestituiti > 0 then
begin
Form1.Memo1.Lines.Add(' ' + GUIDToString(GUID_SubType)+ '---' +
SubType_Name(GUID_Type, GUID_SubType));
end;
until NroElementiRestituiti = 0;
end;
2.7 Enumerare gli ITEM e DATA associato ad ognuno di essi
function Item_Data(FProvider: IPStore;
GUID_Type: TGUID;
GUID_SubType: TGUID;
Item_Name: PWideChar): string;
var
DimData: Cardinal;
Data: PByte1;
pstpi: _PST_PROMPTINFO;
i: Cardinal;
StringaDati: string;
begin
DimData := 0;
Data := nil;
pstpi.cbSize := SizeOf(_PST_PROMPTINFO);
pstpi.dwPromptFlags := 4;
pstpi.hwndApp := 0;
pstpi.szPrompt := '';
FProvider.ReadItem(0,
GUID_Type,
GUID_SubType,
StringToOleStr(Item_Name),
DimData,
Data,
pstpi,
0);
while i < DimData do
begin
if (PByte(Integer(Data) + i)^ < $20) or (PByte(Integer(Data) + i)^ > $7F) then
StringaDati := StringaDati + '*'
else
StringaDati := StringaDati + pChar(Integer(Data) + i)^;
Inc(i, 2);
end;
CoTaskMemFree(Data);
Result := StringaDati;
end;
procedure ElencoItems(FProvider: IPStore; GUID_Type: TGUID; GUID_SubType: TGUID);
var
ppEnumItems: IEnumPStoreItems;
NroElementiRestituiti: Cardinal;
Item_Name: PWideChar;
begin
FProvider.EnumItems(0, GUID_Type, GUID_SubType, 0, ppEnumItems);
NroElementiRestituiti := 0;
repeat
ppEnumItems.Next(1, Item_Name, NroElementiRestituiti);
if NroElementiRestituiti > 0 then
begin
Form1.Memo1.Lines.Add(' ' + ' ' + String(Item_Name));
Form1.Memo1.Lines.Add(' ' + ' ' + ' ' +
Item_Data(FProvider, GUID_Type, GUID_SubType, Item_Name));
end;
until NroElementiRestituiti = 0;
end;
3. Locazione del Protected Storage Come ultima cosa è doveroso dire che il Protected Storage è contenuto nel registro nella chiave seguente
HKCU\Software\Microsoft\Protected Storage System Provider
Si fa riferimento al Current User: infatti il Protected Storage è associato all'utente e ne esiste uno per ogni account. ProtStorageViewer.7z
|