Advertisement
Guest User

dll loader

a guest
Jun 26th, 2025
75
0
364 days
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 9.76 KB | None | 0 0
  1. #include <windows.h>
  2. #include <winnt.h>
  3. #include <stdio.h>
  4.  
  5. typedef BOOL(WINAPI *DllMainFunc)(HINSTANCE, DWORD, LPVOID);
  6.  
  7. // New helpers
  8. BOOL ProcessTLS(LPVOID imageBase);
  9. BOOL ApplySectionProtections(LPVOID imageBase);
  10. BOOL ProcessExceptionDirectory(LPVOID imageBase);
  11.  
  12. LPVOID LoadAndMapDLL(const char *dllPath);
  13. BOOL ApplyRelocations(LPVOID imageBase, ULONGLONG delta);
  14. BOOL ResolveImports(LPVOID imageBase);
  15.  
  16. int main(int argc, char *argv[])
  17. {
  18.     if (argc != 2)
  19.     {
  20.         printf("Usage: %s <path_to_dll>\n", argv[0]);
  21.         return 1;
  22.     }
  23.  
  24.     printf("Mapping\n");
  25.     LPVOID imageBase = LoadAndMapDLL(argv[1]);
  26.     if (!imageBase)
  27.     {
  28.         printf("[-] Failed to load DLL.\n");
  29.         return 1;
  30.     }
  31.  
  32.     PIMAGE_DOS_HEADER dos = (PIMAGE_DOS_HEADER)imageBase;
  33.     PIMAGE_NT_HEADERS nt = (PIMAGE_NT_HEADERS)((BYTE *)imageBase + dos->e_lfanew);
  34.     ULONGLONG delta = (ULONGLONG)imageBase - nt->OptionalHeader.ImageBase;
  35.  
  36.     printf("Relocations\n");
  37.     if (!ApplyRelocations(imageBase, delta))
  38.     {
  39.         printf("[-] Failed to apply relocations.\n");
  40.         VirtualFree(imageBase, 0, MEM_RELEASE);
  41.         return 1;
  42.     }
  43.  
  44.     printf("Imports\n");
  45.     if (!ResolveImports(imageBase))
  46.     {
  47.         printf("[-] Failed to resolve imports.\n");
  48.         VirtualFree(imageBase, 0, MEM_RELEASE);
  49.         return 1;
  50.     }
  51.  
  52.     printf("TLS\n");
  53.     if (!ProcessTLS(imageBase))
  54.     {
  55.         printf("[-] Failed to process TLS.\n");
  56.         VirtualFree(imageBase, 0, MEM_RELEASE);
  57.         return 1;
  58.     }
  59.  
  60.     printf("Sec protection\n");
  61.     if (!ApplySectionProtections(imageBase))
  62.     {
  63.         printf("[-] Failed to apply section protections.\n");
  64.         // Non‐fatal in many cases, so we continue
  65.     }
  66.  
  67.     printf("Exception Dir\n");
  68.     if (!ProcessExceptionDirectory(imageBase))
  69.     {
  70.         printf("[-] Warning: failed to register exception handlers.\n");
  71.     }
  72.  
  73.     // Call DllMain
  74.     printf("DLL Main\n");
  75.     DllMainFunc entry = (DllMainFunc)((BYTE *)imageBase + nt->OptionalHeader.AddressOfEntryPoint);
  76.     if (!entry((HINSTANCE)imageBase, DLL_PROCESS_ATTACH, NULL))
  77.     {
  78.         printf("[-] DllMain returned FALSE.\n");
  79.         VirtualFree(imageBase, 0, MEM_RELEASE);
  80.         return 1;
  81.     }
  82.  
  83.     printf("[+] DLL loaded, TLS callbacks run, and DllMain called successfully.\n");
  84.     return 0;
  85. }
  86.  
  87. LPVOID LoadAndMapDLL(const char *dllPath)
  88. {
  89.     HANDLE hFile = CreateFileA(dllPath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
  90.     if (hFile == INVALID_HANDLE_VALUE)
  91.         return NULL;
  92.  
  93.     HANDLE hMapping = CreateFileMappingA(hFile, NULL, PAGE_READONLY, 0, 0, NULL);
  94.     if (!hMapping)
  95.     {
  96.         CloseHandle(hFile);
  97.         return NULL;
  98.     }
  99.  
  100.     BYTE *fileData = (BYTE *)MapViewOfFile(hMapping, FILE_MAP_READ, 0, 0, 0);
  101.     if (!fileData)
  102.     {
  103.         CloseHandle(hMapping);
  104.         CloseHandle(hFile);
  105.         return NULL;
  106.     }
  107.  
  108.     PIMAGE_DOS_HEADER dos = (PIMAGE_DOS_HEADER)fileData;
  109.     if (dos->e_magic != IMAGE_DOS_SIGNATURE)
  110.         goto cleanup;
  111.  
  112.     PIMAGE_NT_HEADERS nt = (PIMAGE_NT_HEADERS)(fileData + dos->e_lfanew);
  113.     if (nt->Signature != IMAGE_NT_SIGNATURE)
  114.         goto cleanup;
  115.  
  116.     SIZE_T imageSize = nt->OptionalHeader.SizeOfImage;
  117.     LPVOID imageBase = VirtualAlloc(NULL, imageSize, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE);
  118.     if (!imageBase)
  119.         goto cleanup;
  120.  
  121.     // Copy headers
  122.     memcpy(imageBase, fileData, nt->OptionalHeader.SizeOfHeaders);
  123.  
  124.     // Copy sections
  125.     PIMAGE_SECTION_HEADER section = IMAGE_FIRST_SECTION(nt);
  126.     for (int i = 0; i < nt->FileHeader.NumberOfSections; i++, section++)
  127.     {
  128.         LPVOID dest = (BYTE *)imageBase + section->VirtualAddress;
  129.         LPVOID src = fileData + section->PointerToRawData;
  130.         memcpy(dest, src, section->SizeOfRawData);
  131.     }
  132.  
  133.     UnmapViewOfFile(fileData);
  134.     CloseHandle(hMapping);
  135.     CloseHandle(hFile);
  136.     return imageBase;
  137.  
  138. cleanup:
  139.     UnmapViewOfFile(fileData);
  140.     CloseHandle(hMapping);
  141.     CloseHandle(hFile);
  142.     return NULL;
  143. }
  144.  
  145. BOOL ApplyRelocations(LPVOID imageBase, ULONGLONG delta)
  146. {
  147.     if (delta == 0)
  148.         return TRUE;
  149.  
  150.     PIMAGE_DOS_HEADER dos = (PIMAGE_DOS_HEADER)imageBase;
  151.     PIMAGE_NT_HEADERS nt = (PIMAGE_NT_HEADERS)((BYTE *)imageBase + dos->e_lfanew);
  152.  
  153.     DWORD relocRVA = nt->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress;
  154.     DWORD relocSize = nt->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].Size;
  155.     if (!relocRVA || !relocSize)
  156.         return FALSE;
  157.  
  158.     PIMAGE_BASE_RELOCATION reloc = (PIMAGE_BASE_RELOCATION)((BYTE *)imageBase + relocRVA);
  159.     DWORD processed = 0;
  160.  
  161.     while (processed < relocSize)
  162.     {
  163.         DWORD count = (reloc->SizeOfBlock - sizeof(IMAGE_BASE_RELOCATION)) / sizeof(WORD);
  164.         WORD *list = (WORD *)((BYTE *)reloc + sizeof(IMAGE_BASE_RELOCATION));
  165.  
  166.         for (DWORD i = 0; i < count; i++)
  167.         {
  168.             WORD entry = list[i];
  169.             if ((entry >> 12) == IMAGE_REL_BASED_DIR64)
  170.             {
  171.                 ULONGLONG *patch = (ULONGLONG *)((BYTE *)imageBase + reloc->VirtualAddress + (entry & 0x0FFF));
  172.                 *patch += delta;
  173.             }
  174.         }
  175.         processed += reloc->SizeOfBlock;
  176.         reloc = (PIMAGE_BASE_RELOCATION)((BYTE *)reloc + reloc->SizeOfBlock);
  177.     }
  178.     return TRUE;
  179. }
  180.  
  181. BOOL ResolveImports(LPVOID imageBase)
  182. {
  183.     PIMAGE_DOS_HEADER dos = (PIMAGE_DOS_HEADER)imageBase;
  184.     PIMAGE_NT_HEADERS nt = (PIMAGE_NT_HEADERS)((BYTE *)imageBase + dos->e_lfanew);
  185.  
  186.     DWORD importRVA = nt->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress;
  187.     if (!importRVA)
  188.         return TRUE;
  189.  
  190.     PIMAGE_IMPORT_DESCRIPTOR desc = (PIMAGE_IMPORT_DESCRIPTOR)((BYTE *)imageBase + importRVA);
  191.     while (desc->Name)
  192.     {
  193.         char *dllName = (char *)((BYTE *)imageBase + desc->Name);
  194.         HMODULE hMod = LoadLibraryA(dllName);
  195.         if (!hMod)
  196.             return FALSE;
  197.  
  198.         PIMAGE_THUNK_DATA orig = (PIMAGE_THUNK_DATA)((BYTE *)imageBase + desc->OriginalFirstThunk);
  199.         PIMAGE_THUNK_DATA thunk = (PIMAGE_THUNK_DATA)((BYTE *)imageBase + desc->FirstThunk);
  200.  
  201.         for (; orig->u1.AddressOfData; orig++, thunk++)
  202.         {
  203.             FARPROC fn;
  204.             if (orig->u1.Ordinal & IMAGE_ORDINAL_FLAG)
  205.             {
  206.                 fn = GetProcAddress(hMod, (LPCSTR)(orig->u1.Ordinal & 0xFFFF));
  207.             }
  208.             else
  209.             {
  210.                 PIMAGE_IMPORT_BY_NAME ibn = (PIMAGE_IMPORT_BY_NAME)((BYTE *)imageBase + orig->u1.AddressOfData);
  211.                 fn = GetProcAddress(hMod, ibn->Name);
  212.             }
  213.             if (!fn)
  214.                 return FALSE;
  215.             thunk->u1.Function = (ULONGLONG)fn;
  216.         }
  217.         desc++;
  218.     }
  219.     return TRUE;
  220. }
  221.  
  222. // — TLS support —//
  223. BOOL ProcessTLS(LPVOID imageBase)
  224. {
  225.     PIMAGE_DOS_HEADER dos = (PIMAGE_DOS_HEADER)imageBase;
  226.     PIMAGE_NT_HEADERS nt = (PIMAGE_NT_HEADERS)((BYTE *)imageBase + dos->e_lfanew);
  227.     IMAGE_DATA_DIRECTORY dir = nt->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_TLS];
  228.     if (!dir.VirtualAddress)
  229.         return TRUE; // no TLS
  230.  
  231.     PIMAGE_TLS_DIRECTORY64 tls = (PIMAGE_TLS_DIRECTORY64)((BYTE *)imageBase + dir.VirtualAddress);
  232.  
  233.     // Copy raw TLS template to the newly-allocated TLS area
  234.     PVOID tlsDataStart = (BYTE *)imageBase + (SIZE_T)tls->StartAddressOfRawData - nt->OptionalHeader.ImageBase;
  235.     SIZE_T tlsSize = tls->EndAddressOfRawData - tls->StartAddressOfRawData;
  236.     memcpy((PVOID)tls->StartAddressOfRawData, tlsDataStart, tlsSize);
  237.  
  238.     // Run all callbacks with PROCESS_ATTACH
  239.     PIMAGE_TLS_CALLBACK *cb = (PIMAGE_TLS_CALLBACK *)tls->AddressOfCallBacks;
  240.     for (; cb && *cb; cb++)
  241.     {
  242.         (*cb)((PVOID)imageBase, DLL_PROCESS_ATTACH, NULL);
  243.     }
  244.     return TRUE;
  245. }
  246.  
  247. // — Section memory protections —//
  248. BOOL ApplySectionProtections(LPVOID imageBase)
  249. {
  250.     PIMAGE_DOS_HEADER dos = (PIMAGE_DOS_HEADER)imageBase;
  251.     PIMAGE_NT_HEADERS nt = (PIMAGE_NT_HEADERS)((BYTE *)imageBase + dos->e_lfanew);
  252.     PIMAGE_SECTION_HEADER sec = IMAGE_FIRST_SECTION(nt);
  253.  
  254.     for (int i = 0; i < nt->FileHeader.NumberOfSections; i++, sec++)
  255.     {
  256.         DWORD oldProt, newProt = 0;
  257.         BOOL exec = (sec->Characteristics & IMAGE_SCN_MEM_EXECUTE) != 0;
  258.         BOOL read = (sec->Characteristics & IMAGE_SCN_MEM_READ) != 0;
  259.         BOOL write = (sec->Characteristics & IMAGE_SCN_MEM_WRITE) != 0;
  260.  
  261.         if (exec)
  262.         {
  263.             if (write)
  264.                 newProt = PAGE_EXECUTE_READWRITE;
  265.             else if (read)
  266.                 newProt = PAGE_EXECUTE_READ;
  267.             else
  268.                 newProt = PAGE_EXECUTE;
  269.         }
  270.         else
  271.         {
  272.             if (write)
  273.                 newProt = PAGE_READWRITE;
  274.             else if (read)
  275.                 newProt = PAGE_READONLY;
  276.             else
  277.                 newProt = PAGE_NOACCESS;
  278.         }
  279.  
  280.         VirtualProtect((BYTE *)imageBase + sec->VirtualAddress,
  281.                        sec->Misc.VirtualSize, newProt, &oldProt);
  282.     }
  283.     return TRUE;
  284. }
  285.  
  286. // — Exception directory (64-bit only) —//
  287. BOOL ProcessExceptionDirectory(LPVOID imageBase)
  288. {
  289. #ifdef _WIN64
  290.     PIMAGE_DOS_HEADER dos = (PIMAGE_DOS_HEADER)imageBase;
  291.     PIMAGE_NT_HEADERS64 nt = (PIMAGE_NT_HEADERS64)((BYTE *)imageBase + dos->e_lfanew);
  292.     IMAGE_DATA_DIRECTORY dir = nt->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXCEPTION];
  293.     if (!dir.VirtualAddress || !dir.Size)
  294.         return TRUE;
  295.  
  296.     // Register the runtime function table for SEH
  297.     RUNTIME_FUNCTION *table = (RUNTIME_FUNCTION *)((BYTE *)imageBase + dir.VirtualAddress);
  298.     ULONG count = dir.Size / sizeof(RUNTIME_FUNCTION);
  299.     if (!RtlAddFunctionTable(table, count, (DWORD64)imageBase))
  300.         return FALSE;
  301. #endif
  302.     return TRUE;
  303. }
  304.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement