2017-02-09 8 views
-2

Eh bien, basead dans ma dernière question:api indigène: RtlInitUnicodeString réaccorder personnages étranges

How build a path to file using Native Api and open with NtOpenFile api?

comme @Remy Lebeau a suggéré RtlInitUnicodeString() fonctionne très bien quand SourceString est de type:

'\??\c:\test.txt'.

Déjà dans ce cas-ci, après RtlInitUnicodeString() valeur tampon est toujours:

'dfᄸɟ\Device\HarddiskVolume2\Windows\SysWOW64\gdi32.dll', voir:

enter image description here

avec des personnages étranges au démarrage. Et de cette façon est clair que NtOpenFile() échouera.

Quelqu'un sait quelque chose pour résoudre ce problème, s'il vous plaît?

Voici ma dernière tentative:

uses 
    Winapi.Windows, 
    System.SysUtils, 
    System.Classes, 
    NtDll, 
    ntdll_; 

var 
hmod: HMODULE = 0 

type 

    { .: MEMORY_INFORMATION_CLASS :. } 

    _MEMORY_INFORMATION_CLASS = (MemoryBasicInformation, MemoryWorkingSetList, 
    MemoryMappedFilenameInformation, MemorySectionName, 
    MemoryBasicVlmInformation); 
    MEMORY_INFORMATION_CLASS = _MEMORY_INFORMATION_CLASS; 
    TMemoryInformationClass = MEMORY_INFORMATION_CLASS; 
    PMemoryInformationClass = ^TMemoryInformationClass; 

    { .: UNICODE STRING:. } 

    PUnicodeString = ^TUnicodeString; 

    TUnicodeString = packed record 
    Length: Word; 
    MaximumLength: Word; 
    Buffer: PWideChar; 
    end; 

/////////////////////////////////////////////////////////////////////////////// 

procedure UnhookPfn(pfn: Pointer); 
const 
OBJ_CASE_INSENSITIVE = $00000040; 
NtCurrentProcess = THandle(-1); 
var 
pinth: PImageNtHeaders32; 
StrUnicode : TNtUnicodeString 
Name: PUnicodeString; 
oa: TNtObjectAttributes; 
rcb: SIZE_T; 

begin 

if ((RtlPcToFileHeader(pfn, @hmod)) <> (NtNotImplementedPointer)) then 
    begin 

    pinth := RtlImageNtHeader(hmod); 

    GetMem(Name, SizeOf(Name)); 

    FillChar(Name^,SizeOf(Name),#0); 

    if (0 <= NtQueryVirtualMemory(NtCurrentProcess, Pointer(hmod), 
     Integer(MemoryMappedFilenameInformation), Pointer(Name), MAX_PATH * SizeOf(WCHAR), 
     @rcb)) then 
    begin 

     RtlInitUnicodeString(@StrUnicode, PWideChar(Name)); 
     InitializeObjectAttributes(@oa, @StrUnicode, OBJ_CASE_INSENSITIVE, 0, nil); 

    end; 
    FreeMem(Name); 
end; 

{ ::: Usage ::: } 

/// ///////////////////////////////////////////////////////////////////////////// 
var 
BitBltAddr: Pointer; 

begin 
    try 
    hmod := GetModuleHandle('Gdi32.dll'); 
    BitBltAddr := GetProcAddress(hmod, 'BitBlt'); 
    UnhookPfn(BitBltAddr); 
    except 
    on E: Exception do 
     Writeln(E.ClassName, ': ', E.Message); 
    end; 
    Readln; 

end. 

NtDll.pas

ntdll_.pas

EDITION 1:(suggestion @RbMm)

procedure UnhookPfn(pfn: Pointer); 
const 
    OBJ_CASE_INSENSITIVE = $00000040; 
    NtCurrentProcess = THandle(-1); 
var 
    pinth: PImageNtHeaders32; 
    Name: PUnicodeString; 
    rcb: SIZE_T; 
    iosb: TIoStatusBlock; 
    oa: TNtObjectAttributes; 
    StrPath : TNtUnicodeString; 

begin 

    if ((RtlPcToFileHeader(pfn, @hmod)) <> (NtNotImplementedPointer)) then 
    begin 

    pinth := RtlImageNtHeader(hmod); 

    GetMem(Name, SizeOf(Name)); 

    FillChar(Name^,SizeOf(Name),#0); 

    if (0 <= NtQueryVirtualMemory(NtCurrentProcess, Pointer(hmod), 
     Integer(MemoryMappedFilenameInformation), Pointer(Name), MAX_PATH * SizeOf(WCHAR), // Name buffer = '\Device\HarddiskVolume2\Windows\SysWOW64\gdi32.dll' 
     @rcb)) then 
    begin 

     InitializeObjectAttributes(@oa, @Name, OBJ_CASE_INSENSITIVE, 0, nil); // buffer of ObjectName = 'strange character' 

    end; 

enter image description here

EDITION 2:

La solution finale à ce trouble comme l'a dit @RbMm était:

InitializeObjectAttributes(@oa, Name, OBJ_CASE_INSENSITIVE, 0, nil);

+0

Extrayez ce qui est nécessaire et incluez-le dans la question. J'ai posté ce lien plusieurs fois: [mcve]. Pouvez-vous confirmer si vous l'avez lu ou non? Lisez aussi ceci: http://sscce.org/ –

+0

Enfin, pour la N-ième fois, pourquoi utilisez-vous l'API native? –

+0

@DavidHeffernan, [parce que a été suggéré à cet utilisateur Luiz Eduardo] (http://stackoverflow.com/questions/41928081/how-restore-inline-hook) utiliser native api pour cette tâche. –

Répondre

0

Delphi a déjà un type PUnicodeString qui est différent du votre PUnicodeString le code est en train de définir. Pensez à utiliser plus de noms de types uniques.

Mais le plus important, les données d'entrée que vous passez à RtlInitUnicodeString() est garage complet. Vous allouez dynamiquement une instance de l'enregistrement TUnicodeString en utilisant la mauvaise taille, puis transmettez cet enregistrement où une chaîne de caractères est attendue.

Modifier ceci:

var 
    Name: PUnicodeString; 

GetMem(Name, SizeOf(Name)); 
FillChar(Name^,SizeOf(Name),#0); 
NtQueryVirtualMemory(..., Pointer(Name), MAX_PATH * SizeOf(WCHAR), ...) 
RtlInitUnicodeString(@StrUnicode, PWideChar(Name)); 
FreeMem(Name); 

à ceci:

var 
    Name: array[0..MAX_PATH-1] of WideChar; 

FillChar(Name,SizeOf(Name),#0); 
NtQueryVirtualMemory(..., @Name, SizeOf(Name), ...) 
RtlInitUnicodeString(@StrUnicode, Name); 

Ou, si vous souhaitez utiliser l'allocation dynamique:

var 
    Name: array of WideChar; 

SetLength(Name, MAX_PATH); 
FillChar(Name[0], Length(Name) * SizeOf(WideChar), #0); 
NtQueryVirtualMemory(..., PWideChar(Name), Length(Name) * SizeOf(WideChar), ...) 
RtlInitUnicodeString(@StrUnicode, PWideChar(Name)); 

Mise à jour: Il se en dehors que la sortie de NtQueryVirtualMemory(MemoryMappedFilenameInformation) est une structure MEMORY_MAPPED_FILE_NAME_INFORMATION, qui contient une UNICODE_STRING en elle:

#define _MAX_OBJECT_NAME 1024/sizeof (WCHAR) 

typedef struct _MEMORY_MAPPED_FILE_NAME_INFORMATION { 
    UNICODE_STRING Name; 
    WCHAR Buffer [_MAX_OBJECT_NAME]; 
} MEMORY_MAPPED_FILE_NAME_INFORMATION, *PMEMORY_MAPPED_FILE_NAME_INFORMATION; 

Donc, vous ne même pas besoin de déclarer votre propre à tous les variables TUnicodeString, il suffit d'utiliser celui qui vous est fourni , et laissez NtQueryVirtualMemory() le remplir comme nécessaire:

const 
    _MAX_OBJECT_NAME = 1024 div sizeof(WCHAR); 

type 
    ... 

    { .: MEMORY_MAPPED_FILE_NAME_INFORMATION :. } 

    _MEMORY_MAPPED_FILE_NAME_INFORMATION = record 
    Name: TUnicodeString; 
    Buffer: array[0.._MAX_OBJECT_NAME-1] of WCHAR; 
    end; 
    MEMORY_MAPPED_FILE_NAME_INFORMATION = _MEMORY_MAPPED_FILE_NAME_INFORMATION; 
    TMemoryMappedFileNameInfo = MEMORY_MAPPED_FILE_NAME_INFORMATION; 
    PMemoryMappedFileNameInfo = ^TMemoryMappedFileNameInfo; 

... 

procedure UnhookPfn(pfn: Pointer); 
const 
    OBJ_CASE_INSENSITIVE = $00000040; 
    NtCurrentProcess = THandle(-1); 
var 
    pinth: PImageNtHeaders32; 
    fni: TMemoryMappedFileNameInfo; 
    oa: TNtObjectAttributes; 
    rcb: SIZE_T; 
begin 
    if (RtlPcToFileHeader(pfn, @hmod) <> NtNotImplementedPointer) then 
    begin 
    pinth := RtlImageNtHeader(hmod); 

    FillChar(fni, SizeOf(fni), #0); 
    fni.Name.Buffer := fni.Buffer; 
    fni.Name.Length := 0; 
    fni.Name.MaximumLength := SizeOf(fni.Buffer); 

    if (0 <= NtQueryVirtualMemory(NtCurrentProcess, Pointer(hmod), Integer(MemoryMappedFilenameInformation), @fni, SizeOf(fni), @rcb)) then 
    begin 
     InitializeObjectAttributes(@oa, @fni.Name, OBJ_CASE_INSENSITIVE, 0, nil); 
     // use oa as needed... 
    end; 
    end; 
end; 
+0

tampon pour quel point 'PWideChar (Name)' - déjà formées en tant que chaîne unicode. donc appelez 'RtlInitUnicodeString (@StrUnicode, PWideChar (Name));' - est une erreur. mais je ne sais pas comment écrire ceci sur Delphes. 'Name' ->' UNICODE_STRING' mais pas 'WCHAR' – RbMm

+0

Activité vampirique détectée –

+1

Guy, si vous ne voulez pas d'aide, s'il vous plaît, ne plaisante pas. –