2016-06-20 51 views
0

Die Frage ist ziemlich geradlinig, was ich versuche, die Umwegfunktionen meines Prozesses wiederherzustellen.Wiederherstellen umgebender Bibliotheksfunktionen

Wenn ich Umleitung sagen, meine ich die übliche jmp Anweisung an einen unbekannten Ort.

Zum Beispiel, wenn die ntdll.dll Export NtOpenProcess() nicht umgeleitet wird, sind die ersten 5 Bytes der Anweisung der Funktion in Richtung mov eax, *.

(Die * Offset in Abhängigkeit von der Betriebssystem-Version.)

Wenn es detoured wird, dass mov eax, * in schaltet sich ein jmp.

Was ich versuche ihr Bytes zu tun ist, wiederherstellen, was sie ursprünglich waren vor irgendwelchen Speichermodifikationen.

Meine Idee war zu versuchen, die Informationen zu lesen, die ich brauche, von der Festplatte, nicht aus dem Speicher, aber ich weiß nicht, wie das geht, da ich nur ein Anfänger bin.

Jede Hilfe oder Erklärung ist sehr willkommen, wenn ich mein Problem nicht richtig erkläre bitte sagen Sie mir!

Antwort

0

Ich fand es heraus herauszufinden.

Beispiel für NtOpenProcess. Anstatt die Bytes wiederherzustellen, entschied ich mich, stattdessen über sie zu springen.

Zuerst müssen wir die Basis von ntdll definieren.

/* locate ntdll */ 
#define NTDLL _GetModuleHandleA("ntdll.dll") 

Sobald wir das getan haben, sind wir gut zu gehen. GetOffsetFromRva berechnet den Offset der Datei basierend auf der Adresse und dem Modulkopf, die an ihn übergeben werden.

Wir nennen dies, um uns den Dateioffset zu holen, den wir brauchen, um die ursprünglichen Bytes der Funktion zu finden.

DWORD GetExportPhysicalAddress(HMODULE hmModule, char* szExportName) 
{ 
    if (!hmModule) 
    { 
     return 0; 
    } 

    DWORD dwModuleBaseAddress = (DWORD)hmModule; 

    IMAGE_DOS_HEADER* pHeaderDOS = (IMAGE_DOS_HEADER *)hmModule; 
    if (pHeaderDOS->e_magic != IMAGE_DOS_SIGNATURE) 
    { 
     return 0; 
    } 

    IMAGE_NT_HEADERS * pHeaderNT = (IMAGE_NT_HEADERS *)(dwModuleBaseAddress + pHeaderDOS->e_lfanew); 
    if (pHeaderNT->Signature != IMAGE_NT_SIGNATURE) 
    { 
     return 0; 
    } 

    /* get the export virtual address through a custom GetProcAddress function. */ 
    void* pExportRVA = GetProcedureAddress(hmModule, szExportName); 

    if (pExportRVA) 
    { 
     /* convert the VA to RVA... */ 
     DWORD dwExportRVA = (DWORD)pExportRVA - dwModuleBaseAddress; 

     /* get the file offset and return */ 
     return GetOffsetFromRva(pHeaderNT, dwExportRVA); 
    } 

    return 0; 
} 

Mit der Funktion, die uns den Dateioffset holt, können wir jetzt die ursprünglichen Exportbytes lesen.

Und wir können den syscall-Index von der mov-Anweisung abrufen, die ursprünglich in den ersten 5 Bytes des Exports auf x86 platziert wurde.

DWORD GetSyscallIndex(char* szFunctionName) 
{ 
    BYTE buffer[5]; 
    ReadExportFunctionBytes(NTDLL, szFunctionName, buffer, 5); 
    if (!buffer) 
    { 
     return 0; 
    } 

    return BytesToDword(buffer + 1); 
} 

Holen Sie sich die NtOpenProcess-Adresse und fügen Sie 5 zum Trampolin hinzu.

DWORD _ptrNtOpenProcess = (DWORD) GetProcAddress(NTDLL, "NtOpenProcess") + 5; 
DWORD _oNtOpenProcess = GetSyscallIndex("NtOpenProcess"); 

Der wiederhergestellte/rekonstruierte NtOpenProcess.

__declspec(naked) NTSTATUS NTAPI _NtOpenProcess 
(
    _Out_ PHANDLE   ProcessHandle, 
    _In_  ACCESS_MASK  DesiredAccess, 
    _In_  POBJECT_ATTRIBUTES ObjectAttributes, 
    _In_opt_ PCLIENT_ID   ClientId 
) { 
    __asm 
    { 
     mov eax, [_oNtOpenProcess] 
     jmp dword ptr ds : [_ptrNtOpenProcess] 
    } 
} 

Nennen wir es.

int main() 
{ 
    printf("NtOpenProcess %x index: %x\n", _ptrNtOpenProcess, _oNtOpenProcess); 

    uint32_t pId = 0; 
    do 
    { 
     pId = GetProcessByName("notepad.exe"); 
     Sleep(200); 

    } while (pId == 0); 

    OBJECT_ATTRIBUTES oa; 
    CLIENT_ID cid; 
    cid.UniqueProcess = (HANDLE)pId; 
    cid.UniqueThread = 0; 
    InitializeObjectAttributes(&oa, NULL, 0, NULL, NULL); 

    HANDLE hProcess; 
    NTSTATUS ntStat; 

    ntStat = _NtOpenProcess(&hProcess, PROCESS_ALL_ACCESS, &oa, &cid); 

    if (!NT_SUCCESS(ntStat)) 
    { 
     printf("Couldn't open the process. NTSTATUS: %d", ntStat); 
     return 0; 
    } 

    printf("Successfully opened the process."); 

    /* clean up. */ 
    NtClose(hProcess); 

    getchar(); 
    return 0; 
}