Maison > développement back-end > Golang > le corps du texte

Chargement réfléchissant des DLL générées par CGO

王林
Libérer: 2024-02-08 21:00:13
avant
462 Les gens l'ont consulté

反射加载 CGO 生成的 DLL

Contenu de la question

Je voulais juste essayer le chargement de DLL par réflexion, j'ai donc écrit une simple boîte de message :

package main
import "c"
import (
    "unsafe"
    "syscall"
)

//export onprocessattach
func onprocessattach() {
    const (
        null  = 0
        mb_ok = 0
    )
    caption := "hola"
    title := "desdegoo"
    ret, _, _ := syscall.newlazydll("user32.dll").newproc("messageboxw").call(
        uintptr(null),
        uintptr(unsafe.pointer(syscall.stringtoutf16ptr(caption))),
        uintptr(unsafe.pointer(syscall.stringtoutf16ptr(title))),
        uintptr(mb_ok))

    if ret != 1 {
        return
    }
    return
}

func main() {}
Copier après la connexion

J'ai généré une DLL (juste une boîte de message avec cgo/golang) en utilisant la commande suivante allez build --buildmode=c-shared main.go

Lors du chargement de la DLL à l'aide de loadlibrary() et de l'exécution de la fonction exportée onprocessattach, cela fonctionne (une boîte de message apparaît), mais lorsque vous essayez d'implémenter le chargement réfléchissant de la DLL, en résolvant les relocalisations et en résolvant iats, cela ne fonctionne pas. Il semble qu'une relocalisation de base soit effectuée et iat est défini sur une section vide sur .rdata qui est utilisée pour initialiser le runtime go (initialisé dans le point d'entrée de l'en-tête nt) Voici l'extrait de code que j'ai utilisé pour résoudre le problème d'importation :

// resolve base relocations
    IMAGE_DATA_DIRECTORY relocations = ntHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC];
    DWORD_PTR relocationTable = relocations.VirtualAddress + (DWORD_PTR)dllBase;
    DWORD relocationsProcessed = 0;


    while (relocationsProcessed < relocations.Size)
    {
        PBASE_RELOCATION_BLOCK relocationBlock = (PBASE_RELOCATION_BLOCK)(relocationTable + relocationsProcessed);
        relocationsProcessed += sizeof(BASE_RELOCATION_BLOCK);
        DWORD relocationsCount = (relocationBlock->BlockSize - sizeof(BASE_RELOCATION_BLOCK)) / sizeof(BASE_RELOCATION_ENTRY);
        PBASE_RELOCATION_ENTRY relocationEntries = (PBASE_RELOCATION_ENTRY)(relocationTable + relocationsProcessed);
        for (DWORD i = 0; i < relocationsCount; i++)
        {
            relocationsProcessed += sizeof(BASE_RELOCATION_ENTRY);
            if (relocationEntries[i].Type == 0)
            {
                continue;
            }


            DWORD_PTR relocationRVA = relocationBlock->PageAddress + relocationEntries[i].Offset;
            DWORD_PTR addressToPatch = 0;
            ReadProcessMemory(GetCurrentProcess(), (LPCVOID)((DWORD_PTR)dllBase, relocationRVA), &addressToPatch, sizeof(DWORD_PTR), NULL);
            addressToPatch += deltaImageBase;
            memcpy((PVOID)((DWORD_PTR)dllBase + relocationRVA), &addressToPatch, sizeof(DWORD_PTR));
        }
    }
    
    // resolve IAT
    PIMAGE_IMPORT_DESCRIPTOR importDescriptor = NULL;
    IMAGE_DATA_DIRECTORY importsDirectory = ntHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT];
    importDescriptor = (PIMAGE_IMPORT_DESCRIPTOR)(importsDirectory.VirtualAddress + (DWORD_PTR)dllBase);
    LPCSTR libraryName = "";
    HMODULE library = NULL;


    while (importDescriptor->Name != NULL)
    {
        libraryName = (LPCSTR)importDescriptor->Name + (DWORD_PTR)dllBase;
        library = LoadLibraryA(libraryName);
        if (library)
        {
            PIMAGE_THUNK_DATA thunk = NULL;
            thunk = (PIMAGE_THUNK_DATA)((DWORD_PTR)dllBase + importDescriptor->FirstThunk);
            while (thunk->u1.AddressOfData != NULL)
            {
                if (IMAGE_SNAP_BY_ORDINAL(thunk->u1.Ordinal))
                {
                    LPCSTR functionOrdinal = (LPCSTR)IMAGE_ORDINAL(thunk->u1.Ordinal);
                    thunk->u1.Function = (DWORD_PTR)GetProcAddress(library, functionOrdinal);
                }
                else {
                    PIMAGE_IMPORT_BY_NAME functionName = (PIMAGE_IMPORT_BY_NAME)((DWORD_PTR)dllBase + thunk->u1.AddressOfData);
                    DWORD_PTR functionAddress = (DWORD_PTR)GetProcAddress(library, functionName->Name);
                    thunk->u1.Function = functionAddress;
                }
                ++thunk;
            }
        }
        importDescriptor++;
    }
Copier après la connexion

Après avoir fait cela, j'ai résolu le problème de manger en recherchant la fonction onprocessattach, l'exécuter directement ne fonctionne évidemment pas car le runtime go n'est pas initialisé, mais essayer de l'initialiser provoque le crash du programme, comme mentionné ci-dessus. Il donne exception_access_violation car un bloc d'octets non valide est tenté d'être lu.

Démontage du point d'entrée : mov rax, qdword ptr ds :[adresse] mov dword ptr ds :[rax]

Selon l'adresse dans la décharge, elle semble vide 00 00 00 00 00 00 00 00 00 [..]

Bien que la DLL d'origine ait de la valeur 90 2b c5 ch 01 [...]

Je sais que je définis ces octets sur le .rdata sur null, mais je n'arrive pas à comprendre pourquoi cela se produit lors d'une relocalisation, peut-être que le runtime go n'est pas adapté à ce que j'essaie de faire ? Ou autre chose?


Réponse correcte


Solution J'ai juste oublié de poster la solution ici L'erreur apparaît sur la ligne suivante

ReadProcessMemory(GetCurrentProcess(), (LPCVOID)((DWORD_PTR)dllBase, relocationRVA), &addressToPatch, sizeof(DWORD_PTR), NULL);
Copier après la connexion

C'était juste une erreur de doigt, le symbole aurait dû être ajouté à la place de la virgule, c'est pour cela que cela invalidait l'adresse.

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

source:stackoverflow.com
Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal
À propos de nous Clause de non-responsabilité Sitemap
Site Web PHP chinois:Formation PHP en ligne sur le bien-être public,Aidez les apprenants PHP à grandir rapidement!