Hi Cesar, I'm new to Go but have been a Win32 programmer for a very long 
time. It sounds like you've written a DLL in Go and you are attempting to 
call LoadLibrary() in your DLL's entry point. The entry point is generally 
known as DllMain() and it's a very restricted environment in terms of which 
APIs may be called while running in DllMain(). From 
https://learn.microsoft.com/en-us/windows/win32/dlls/dllmain:

"Warning - There are significant limits on what you can safely do in a DLL 
entry point. See General Best Practices 
<https://learn.microsoft.com/en-us/windows/win32/dlls/dynamic-link-library-best-practices>
 
for specific Windows APIs that are unsafe to call in DllMain. If you need 
anything but the simplest initialization then do that in an initialization 
function for the DLL. You can require applications to call the 
initialization function after DllMain has run and before they call any 
other functions in the DLL."

And the "General Best Practices" doc linked there states:

"You should never perform the following tasks from within DllMain 
<https://learn.microsoft.com/en-us/windows/win32/dlls/dllmain>:Call 
LoadLibrary 
<https://learn.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-loadlibrarya>
 
or LoadLibraryEx 
<https://learn.microsoft.com/en-us/windows/desktop/api/LibLoaderAPI/nf-libloaderapi-loadlibraryexa>
 
(either directly or indirectly). This can cause a deadlock or a crash."

Hope this helps,
Marc
On Saturday, February 4, 2023 at 7:13:24 PM UTC-5 Cesar López wrote:

> When I use the library on a simple C program with LoadLibraryA(), it works 
> properly but with the DLL loaded in a virtual memory page happens something 
> different, it gets stuck in WaitForSingleObject after running the exported 
> method.
>
> I did all the base relocations and proper IAT refactor, even when the 
> image module gets loaded in the prefered address the following happens:
>
> I initialize the go runtime by running fist the entrypoint of the DLL 
> (after IAT and base relocations), it runs properly and the returns to the 
> main C program, after that I parse the EAT looking for the exported 
> function i.e OnProcessAttach, after locating the export by it's ordinal / 
> name I tried to execute it (process receives no arguments, and returns 
> nothing), and it starts running, then starts calling to 
> RtlInitializeCriticalSection and follows the system calls, after that it 
> just gets in a deadlock on WaitSingleObject (inside the go DLL), with 
> LastStatus C000000D (STATUS_INVALID_PARAMETER) -but the exported function 
> doesn't receives any argument-
>
> Go DLL
>
> 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() {}
>
>
> C code:
>
>
>     // 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++;
>     }
>
>     FARPROC entrypoint2 = ((DWORD_PTR)dllBase + 
> ntHeaders->OptionalHeader.AddressOfEntryPoint);
>     (*entrypoint2)();
>
>         // Locate exported OnProcessAttach function in EAT
>         IMAGE_DATA_DIRECTORY exportsDirectory = 
> ntHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT];
>         PIMAGE_EXPORT_DIRECTORY exportsDescriptor = 
> (PIMAGE_EXPORT_DIRECTORY)(exportsDirectory.VirtualAddress + 
> (DWORD_PTR)dllBase);
>         DWORD numberOfNames = exportsDescriptor->NumberOfNames;
>
>         PDWORD exportAddressTable = (PDWORD)((DWORD_PTR)dllBase + 
> exportsDescriptor->AddressOfFunctions);
>         PWORD nameOrdinalsPointer = (PWORD)((DWORD_PTR)dllBase + 
> exportsDescriptor->AddressOfNameOrdinals);
>         PDWORD exportNamePointerTable = (PDWORD)((DWORD_PTR)dllBase + 
> exportsDescriptor->AddressOfNames);
>
>         char procedureName[] = { 
> 'O','n','P','r','o','c','e','s','s','A','t','t','a','c','h', 0 };
>         int nameIndex = 0;
>         for (nameIndex = 0; nameIndex < numberOfNames; nameIndex++)
>         {
>             char* name = (char*)((unsigned char*)dllBase + 
> exportNamePointerTable[nameIndex]);
>             if (strncmp(procedureName, name, 15) == 0)
>             {
>                 WORD ordinal = nameOrdinalsPointer[nameIndex];
>                 PDWORD targetFunctionAddress = (PDWORD)((unsigned 
> char*)dllBase + exportAddressTable[ordinal]);
>                FARPROC entrypoint = targetFunctionAddress;
>                (*entrypoint)();
>             }
>         }
> }
>

-- 
You received this message because you are subscribed to the Google Groups 
"golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to golang-nuts+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/golang-nuts/488b1bad-d5aa-4981-bcd5-c85a9c6e6706n%40googlegroups.com.

Reply via email to