Rumah  >  Artikel  >  pembangunan bahagian belakang  >  Pemuatan reflektif DLL janaan CGO

Pemuatan reflektif DLL janaan CGO

王林
王林ke hadapan
2024-02-08 21:00:13450semak imbas

反射加载 CGO 生成的 DLL

Kandungan soalan

Hanya ingin mencuba pemuatan dll reflektif, jadi saya menulis kotak mesej ringkas:

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() {}

Saya menghasilkan dll (hanya kotak mesej dengan cgo/golang) menggunakan arahan berikut pergi bina --buildmode=c-shared main.go

Apabila memuatkan dll menggunakan loadlibrary() dan menjalankan fungsi yang dieksport onprocessattach, ia berfungsi (kotak mesej muncul), tetapi apabila cuba melaksanakan pemuatan reflektif dll, dengan menyelesaikan penempatan semula dan menyelesaikan iats, ia tidak berfungsi. Nampaknya penempatan semula asas dilakukan dan iat ditetapkan kepada bahagian kosong pada .rdata yang digunakan untuk memulakan masa jalan pergi (dimulakan dalam titik masuk pengepala nt) Berikut ialah coretan kod yang saya gunakan untuk menyelesaikan isu import:

// 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++;
    }

Selepas melakukan ini, saya menyelesaikan masalah makan mencari fungsi onprocessattach, menjalankannya secara langsung jelas tidak berfungsi kerana masa jalan pergi tidak dimulakan, tetapi cuba untuk memulakannya menyebabkan program ranap, seperti yang dinyatakan di atas. Ia memberikan exception_access_violation kerana blok bait yang tidak sah cuba dibaca.

Pembubaran pintu masuk: mov rax, qdword ptr ds:[alamat] mov dword ptr ds:[rax]

Seperti alamat di tempat pembuangan, ia kelihatan kosong 00 00 00 00 00 00 00 00 00 [..]

Walaupun dll asal memang ada nilai 90 2b c5 ea 01 [...]

Saya tahu saya sedang menetapkan bait ini pada .rdata kepada null tetapi tidak dapat memahami mengapa ini berlaku semasa melakukan penempatan semula, mungkin masa jalanan pergi tidak sesuai untuk perkara yang saya cuba lakukan? Atau sesuatu yang lain?


Jawapan Betul


Penyelesaian Saya hanya terlupa untuk menyiarkan penyelesaian di sini Ralat muncul pada baris berikut

ReadProcessMemory(GetCurrentProcess(), (LPCVOID)((DWORD_PTR)dllBase, relocationRVA), &addressToPatch, sizeof(DWORD_PTR), NULL);

Itu hanya kesilapan jari, simbol sepatutnya ditambah dan bukannya koma, sebab itu ia membatalkan alamat.

Atas ialah kandungan terperinci Pemuatan reflektif DLL janaan CGO. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan:
Artikel ini dikembalikan pada:stackoverflow.com. Jika ada pelanggaran, sila hubungi admin@php.cn Padam