c ++ - Hvad er der galt med min brug af ReadProcessMemory?

Indlæg af Hanne Mølgaard Plasc

Problem



Jeg har to processer, A og B.

A indlæser en DLL med kode, der læser nogle hukommelsessteder, mens B forsøger at læse de samme hukommelsessteder på A s hukommelse ved hjælp af ReadProcessMemory.


Jeg får de samme værdier, indtil jeg på et eller andet tidspunkt ikke gør det helt forvirrende. Jeg mangler noget, men jeg ved ikke hvad. Jeg håber du vil hjælpe mig med at finde den.


(I begge processorkoder er IMPORT\_TABLE\_OFFSET 1 og processBaseAdress startadressen til A s MZ-overskrift i proceshukommelsen).


En s DLL-kode:


printf("processBaseAddress: \%p
", processBaseAddress);
PIMAGE\_DOS\_HEADER dosHeaderP = processBaseAddress;
printf("ntHeaderP = \%p
", (PBYTE)dosHeaderP + dosHeaderP->e\_lfanew);
PIMAGE\_NT\_HEADERS ntHeader = ((PBYTE)dosHeaderP + dosHeaderP->e\_lfanew);
printf("optHeaderP = \%p
", &ntHeader->OptionalHeader);
IMAGE\_OPTIONAL\_HEADER optionalHeader = (ntHeader->OptionalHeader);
printf("oh.aoep = \%p
", optionalHeader.AddressOfEntryPoint);
printf("oh.cs = \%x
", optionalHeader.CheckSum);
printf("DataDirectory: \%p
", optionalHeader.DataDirectory);
IMAGE\_DATA\_DIRECTORY dataDirectory = (optionalHeader.DataDirectory[IMPORT\_TABLE\_OFFSET]);


B 's kode:
(hHandle er et håndtag til A)


#define VERIFY\_RPM(CALL\_ID, RPM\_CALL) {
    if(RPM\_CALL==0){
        printf("Error! ReadProcessMemory(): \%d. Call id: \%d.
",GetLastError(),CALL\_ID);
        exit(1);
    }
}
SIZE\_T bytesRead;
printf("processBaseAddress: \%p
", processBaseAddress);
VERIFY\_RPM(0, ReadProcessMemory(hProcess, processBaseAddress, &dosHeader, sizeof(dosHeader), &bytesRead));
PIMAGE\_NT\_HEADERS ntHeaderP = processBaseAddress + dosHeader.e\_lfanew;
printf("ntHeaderP = \%p
", ntHeaderP);
VERIFY\_RPM(1, ReadProcessMemory(hProcess, ntHeaderP, &ntHeader, sizeof(ntHeader), &bytesRead));
IMAGE\_OPTIONAL\_HEADER optionalHeader = ntHeader.OptionalHeader;
printf("oh.aoep = \%p
", optionalHeader.AddressOfEntryPoint);
printf("oh.cs = \%x
", optionalHeader.CheckSum);
printf("DataDirectory: \%p
", optionalHeader.DataDirectory);
VERIFY\_RPM(2, ReadProcessMemory(hProcess, optionalHeader.DataDirectory + IMPORT\_TABLE\_OFFSET, &dataDirectory, sizeof(dataDirectory), &bytesRead));


A s output:


processBaseAddress: 1C530000
ntHeaderP = 1C5300F0
optHeaderP = 1C530108
oh.aoep = 00001327
oh.cs = d6c7
DataDirectory: 0322F8E8


B 's output:


processBaseAddress: 1C530000
ntHeaderP = 1C5300F0
oh.aoep = 00001327
oh.cs = d6c7
DataDirectory: 001AEE3C
Error! ReadProcessMemory(): 299. Call id: 2.


Det er det samme til DataDirectory.

Bedste reference


fejl (ved forstand) er næste linje:


IMAGE\_OPTIONAL\_HEADER optionalHeader = (ntHeader->OptionalHeader);


med dette gør du kopi af IMAGE\_OPTIONAL\_HEADER. som resultat :


optionalHeader.DataDirectory


er adresse inde i denne kopi, men ikke inden for original IMAGE\_OPTIONAL\_HEADER inde i billedet. du har brug for brug


PIMAGE\_OPTIONAL\_HEADER poptionalHeader = &ntHeader->OptionalHeader;
PIMAGE\_DATA\_DIRECTORY dataDirectory = 
    &poptionalHeader->DataDirectory[IMAGE\_DIRECTORY\_ENTRY\_IMPORT];


og linje


ReadProcessMemory(hProcess, optionalHeader.DataDirectory + ..))


Selvfølgelig fejl fordi optionalHeader.DataDirectory - adresse i lokal kopi - har ingen mening i fjern proces. og DataDirectory er en del af IMAGE\_NT\_HEADERS - efter at du har læst det - du behøver ikke særskilt læsning til DataDirectory - du har allerede disse data inde i ntHeader


skal også forstå, at IMAGE\_NT\_HEADERS - dette er makroer, der udvides til IMAGE\_NT\_HEADERS32 eller IMAGE\_NT\_HEADERS64 baseret på din kodebit. men når du læser et andet billede - det kan have en anden bit-ness. så du skal altid kontrollere Magic medlem af IMAGE\_OPTIONAL\_HEADER for bestemt - brug 32 eller 64 bit struktur.


korrekt kode for at læse denne fjernbetjening kan se ud:


union {
    IMAGE\_DOS\_HEADER dosHeader;
    IMAGE\_NT\_HEADERS ntHeader;
    IMAGE\_NT\_HEADERS32 ntHeader32;
    IMAGE\_NT\_HEADERS64 ntHeader64;
};

if (ReadProcessMemory(hProcess, ImageBase, &dosHeader, sizeof(dosHeader), 0) &&
    dosHeader.e\_magic == IMAGE\_DOS\_SIGNATURE)
{
    if (ReadProcessMemory(hProcess, (PBYTE)ImageBase + dosHeader.e\_lfanew, 
        &ntHeader64, sizeof(ntHeader64), 0) &&
        ntHeader.Signature == IMAGE\_NT\_SIGNATURE)
    {
        PIMAGE\_DATA\_DIRECTORY dataDirectory = 0;

        switch (ntHeader.OptionalHeader.Magic)
        {
        case IMAGE\_NT\_OPTIONAL\_HDR32\_MAGIC:
            dataDirectory = ntHeader32.OptionalHeader.DataDirectory;
            break;
        case IMAGE\_NT\_OPTIONAL\_HDR64\_MAGIC:
            dataDirectory = ntHeader64.OptionalHeader.DataDirectory;
            break;
        }

        if (dataDirectory)
        {
            PIMAGE\_DATA\_DIRECTORY ImpDataDirectory = &dataDirectory[IMAGE\_DIRECTORY\_ENTRY\_IMPORT];
            DbgPrint("[\%x, \%x]
", ImpDataDirectory->Size, ImpDataDirectory->VirtualAddress);
        }
    }
}