看流星社区

 找回密码
 注册账号
零基础辅助入门教学 原创 高清 专业课程售后(每日解答)
零基础辅助入门教学 原创 高清 专业课程售后(每日解答)
零基础辅助入门教学 原创 高清 专业课程售后(每日解答)
零基础辅助入门教学 原创 高清 专业课程售后(每日解答)
零基础辅助入门教学 原创 高清 专业课程售后(每日解答)
零基础辅助入门教学 原创 高清 专业课程售后(每日解答)
赞助广告位 请点击这里联系站长 QQ20209081
赞助广告位 请点击这里联系站长 QQ20209081
赞助广告位 请点击这里联系站长 QQ20209081
查看: 199|回复: 0

分享一个简短的内存加载DLL EXE

[复制链接]
发表于 2019-6-17 14:32:15 | 显示全部楼层 |阅读模式

实现类似功能的代码很多,但是我这份没有参考到别人的代码,纯粹是看微软文档撸出来的。这个需求是源于我的一个比较复杂的x86_64 shellcode,需要实现的功能很多,依赖也很多。因此用传统的方法弄的shellcode很不方便。于是我想着直接用dll/exe当作shellcode,写一个简短的linker控制在0x1000字节以内,将linker直接填在PE头处,调用时直接call头部的linker实现dll/exe的self link并执行。需求已经测试通过,完整项目不能发出来,但是可以跟大家分享验证阶段的测试代码。

主要原理:
SDK_GetProcAddress 解析kernel32拿到LoadLibraryA和GetProcAddress供linker使用。如果不是裸的代码,这里不需要。
SDK_LoadLibrary 解析dos头和nt头,并将section展开到内存。
RelocImage  进行image base重定向
LinkDLL  加载和连接依赖的dll

这里并没有处理TLS和32位的支持。这个有机会再说吧。

以下代码用mingw-w64编译,可加载运行vs和mingw-w64编译出来的pe。



  1. #include <windows.h>
  2. #include <stdio.h>
  3. #include <string.h>

  4. #include "winapi.h"

  5. #ifndef MIN
  6. #define MIN(a, b) ((a) > (b) ? (b) : (a))
  7. #endif

  8. #define RVA(a) ((PVOID)((ULONG_PTR)hExecutable + (a)))
  9. #define K32RVA(a) ((PVOID)((ULONG_PTR)hKernel32 + (a)))

  10. #define API pContext->

  11. typedef struct {
  12.     union {
  13. #ifdef _WIN64
  14.         struct {
  15.             DWORD64  Unused1:63;
  16.             DWORD64  OrdinalIfSet:1;
  17.         } Flag;
  18.         DWORD64 Long;
  19. #else
  20.         struct {
  21.             DWORD  Unused1:31;
  22.             DWORD  OrdinalIfSet:1;
  23.         } Flag;
  24.         DWORD Long;
  25. #endif
  26.         WORD OrdinalNumber;
  27.         DWORD NameAddress;
  28.     } u;
  29. } IMPORT_LOOKUP_DESC, *PIMPORT_LOOKUP_DESC;

  30. typedef struct {
  31.     LoadLibraryA_t LoadLibraryA;
  32.     GetProcAddress_t GetProcAddress;
  33.     GetModuleHandleA_t GetModuleHandleA;
  34. } LINK_CONTEXT, *PLINK_CONTEXT;

  35. typedef struct {
  36.     DWORD Page;
  37.     DWORD BlockSize;
  38.     struct {
  39.         WORD Offset:12;
  40.         WORD Type:4;
  41.     } TypeOffset[0];
  42. } BASE_RELOCATION_BLOCK, *PBASE_RELOCATION_BLOCK;

  43. HMODULE hExecutable = NULL;

  44. int SDK_strcmp(const char *s1, const char *s2)
  45. {
  46.     while(*s1 && *s2) {
  47.         if (*s1 != *s2)
  48.             return -1;
  49.         s1 ++;
  50.         s2 ++;
  51.     }
  52.     return *s2 - *s1;
  53. }

  54. PVOID SDK_GetProcAddress(HMODULE hKernel32, const char *FuncName)
  55. {
  56.     PIMAGE_DOS_HEADER pDos = (PIMAGE_DOS_HEADER)hKernel32;
  57.     PIMAGE_NT_HEADERS pNt = (PIMAGE_NT_HEADERS)((char *)pDos + pDos->e_lfanew);

  58.     PIMAGE_EXPORT_DIRECTORY EDT = (PIMAGE_EXPORT_DIRECTORY)K32RVA(pNt->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress);

  59.     // printf("DLL Name: %s\n", K32RVA(EDT->Name));
  60.     // printf("Number Of Functions: %d\n", EDT->NumberOfFunctions);
  61.     // printf("Number Of Names: %d\n", EDT->NumberOfNames);

  62.     PDWORD ExportAddressTable = (PDWORD)MOD_RVA(EDT->AddressOfFunctions);
  63.     PDWORD ExportNamePointerTable = (PDWORD)MOD_RVA(EDT->AddressOfNames);
  64.     PWORD ExportOrdinalTable  = (PWORD)MOD_RVA(EDT->AddressOfNameOrdinals);

  65.     for(size_t i = 0; i < EDT->NumberOfNames; i++)
  66.     {
  67.         PCHAR name = (PCHAR)MOD_RVA(ExportNamePointerTable[i]);

  68.         if (SDK_strcmp(name, FuncName) == 0) {
  69.             WORD Ordinal = ExportOrdinalTable[i];
  70.             return (PVOID)MOD_RVA(ExportAddressTable[Ordinal]);
  71.         }
  72.     }

  73.     return NULL;
  74. }

  75. void LinkDLL(PLINK_CONTEXT pContext, PIMAGE_IMPORT_DESCRIPTOR IDT)
  76. {
  77.     const char* DLLName = (const char*)RVA(IDT->Name);
  78.     HMODULE hDLL = API GetModuleHandleA(DLLName);

  79.     if (!hDLL) {
  80.         hDLL = API LoadLibraryA(DLLName);
  81.     }

  82.     if (!hDLL) {
  83.         return -1;
  84.     }

  85.     printf("** %s **\n", DLLName);

  86.     PIMPORT_LOOKUP_DESC ILD = (PIMPORT_LOOKUP_DESC)RVA(IDT->OriginalFirstThunk);
  87.     PULONG_PTR IAT = (PULONG_PTR)RVA(IDT->FirstThunk);

  88.     while (ILD->u.Long) {
  89.         if (!ILD->u.Flag.OrdinalIfSet) {
  90.             *IAT = (ULONG_PTR) API GetProcAddress(hDLL, (PCSTR)RVA(ILD->u.NameAddress+2));
  91.             printf("%s %p\n", RVA(ILD->u.NameAddress+2), *IAT);
  92.         } else {
  93.             *IAT = (ULONG_PTR) API GetProcAddress(hDLL, (PCSTR)MAKEINTRESOURCE(ILD->u.OrdinalNumber));
  94.             printf("%d %p\n", RVA(ILD->u.OrdinalNumber), *IAT);
  95.         }
  96.         IAT ++;
  97.         ILD ++;
  98.     }
  99. }

  100. void RelocImage(PBASE_RELOCATION_BLOCK BRB, ptrdiff_t Difference)
  101. {
  102.     printf("Difference: %ld\n", Difference);
  103.     for(size_t i = 0; i < (BRB->BlockSize - 8)/2; i++)
  104.     {
  105.         WORD Offset = BRB->TypeOffset[i].Offset;
  106.         printf("0x%.4x\t%d ", Offset, BRB->TypeOffset[i].Type);

  107.         switch(BRB->TypeOffset[i].Type) {
  108.             case IMAGE_REL_BASED_ABSOLUTE:break; // The base relocation is skipped
  109.             case IMAGE_REL_BASED_HIGHLOW: // TODO Not test yet
  110.                 *(DWORD*)RVA(BRB->Page + Offset) += Difference;
  111.                 break;
  112.             case IMAGE_REL_BASED_DIR64:
  113.                 printf("DIR64 %lx => ", *(ptrdiff_t*)RVA(BRB->Page + Offset));
  114.                 *(ptrdiff_t*)RVA(BRB->Page + Offset) += Difference;
  115.                 printf("%lx", *(ptrdiff_t*)RVA(BRB->Page + Offset));
  116.                 break;
  117.             default:
  118.                 fprintf(stderr, "Not support this relocation type yet.");
  119.                 abort();
  120.                 break;
  121.         }
  122.         putchar('\n');
  123.     }
  124. }

  125. #define LLRVA(a) ((PVOID)((char*)Image + (a)))

  126. HMODULE SDK_LoadLibrary(PCSTR LibraryName)
  127. {
  128.     IMAGE_DOS_HEADER DosHdr;
  129.     IMAGE_NT_HEADERS NtHdr;
  130.     HMODULE hModule = NULL;

  131.     FILE *libfp = fopen(LibraryName, "rb");

  132.     if (!libfp)
  133.         goto CLEAN;

  134.     fread(&DosHdr, sizeof(IMAGE_DOS_HEADER), 1, libfp);

  135.     fseek(libfp, DosHdr.e_lfanew, SEEK_SET);
  136.     fread(&NtHdr, sizeof(IMAGE_NT_HEADERS), 1, libfp);

  137.     PVOID Image = VirtualAlloc(NULL, NtHdr.OptionalHeader.SizeOfImage, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
  138.     if (!Image)
  139.         goto CLEAN;

  140.     fseek(libfp, 0, SEEK_SET);
  141.     fread(Image, NtHdr.OptionalHeader.SizeOfHeaders, 1, libfp);

  142.     PIMAGE_NT_HEADERS pNt = (PIMAGE_NT_HEADERS)((char *)Image + DosHdr.e_lfanew);

  143.     PIMAGE_SECTION_HEADER Sections = IMAGE_FIRST_SECTION(pNt);

  144.     for(size_t i = 0; i < pNt->FileHeader.NumberOfSections; i++)
  145.     {
  146.         fseek(libfp, Sections[i].PointerToRawData, SEEK_SET);
  147.         fread(LLRVA(Sections[i].VirtualAddress), Sections[i].SizeOfRawData, 1, libfp);
  148.         printf("%s\n", Sections[i].Name);
  149.     }

  150.     hModule = (HMODULE)Image;
  151. CLEAN:
  152.     if (libfp)
  153.         fclose(libfp);
  154.     return hModule;
  155. }

  156. void SDK_FreeLibrary(HMODULE hModule)
  157. {
  158.     VirtualFree(hModule, 0, MEM_RELEASE);
  159. }

  160. int main(int argc, const char *argv[])
  161. {
  162.     LINK_CONTEXT Context;

  163.     if (argc != 2) {
  164.         fprintf(stderr, "Missing dll\n");
  165.         return -1;
  166.     }

  167.     HMODULE hKernel32 = GetModuleHandleA("kernel32.dll");
  168.      
  169.     Context.LoadLibraryA = (LoadLibraryA_t)SDK_GetProcAddress(hKernel32, "LoadLibraryA");
  170.     Context.GetProcAddress = (GetProcAddress_t)SDK_GetProcAddress(hKernel32, "GetProcAddress");
  171.     Context.GetModuleHandleA = (GetModuleHandleA_t)SDK_GetProcAddress(hKernel32, "GetModuleHandleA");

  172.     printf("LoadLibraryA\t\t%p\n", Context.LoadLibraryA);
  173.     printf("GetProcAddress\t\t%p\n", Context.GetProcAddress);
  174.     printf("GetModuleHandleA\t%p\n", Context.GetModuleHandleA);

  175.     hExecutable = SDK_LoadLibrary(argv[1]);

  176.     if (hExecutable == NULL) {
  177.         fprintf(stderr, "Can not load dll\n");
  178.         exit(-1);
  179.     }

  180.     PIMAGE_DOS_HEADER pDos = (PIMAGE_DOS_HEADER)hExecutable;
  181.     PIMAGE_NT_HEADERS pNt = (PIMAGE_NT_HEADERS)((char *)pDos + pDos->e_lfanew);

  182.     if ((PVOID)hExecutable != (PVOID)pNt->OptionalHeader.ImageBase)
  183.     {

  184.         printf("Image Base: %p\n", pNt->OptionalHeader.ImageBase);
  185.         printf("Loaded Base: %p\n", hExecutable);

  186.         ptrdiff_t Difference = (ptrdiff_t)hExecutable - (ptrdiff_t)pNt->OptionalHeader.ImageBase;

  187.         PBASE_RELOCATION_BLOCK BRB = (PBASE_RELOCATION_BLOCK)RVA(pNt->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress);

  188.         while (BRB->BlockSize) {
  189.             RelocImage(BRB, Difference);
  190.             BRB = (PBASE_RELOCATION_BLOCK)((char*)BRB + BRB->BlockSize);
  191.         }
  192.     }

  193.     PIMAGE_IMPORT_DESCRIPTOR IDT = (PIMAGE_IMPORT_DESCRIPTOR)RVA(pNt->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress);
  194.     while (IDT->Name != 0) {
  195.         LinkDLL(&Context, IDT);
  196.         IDT ++;
  197.     }

  198.     ((void(*)(HMODULE,DWORD,PVOID))RVA(pNt->OptionalHeader.AddressOfEntryPoint))(hExecutable, DLL_PROCESS_ATTACH, NULL);

  199.     SDK_FreeLibrary(hExecutable);

  200.     return 0;
  201. }
复制代码
点击按钮快速添加回复内容: 支持 高兴 激动 给力 加油 苦寻 生气 回帖 路过 感恩
您需要登录后才可以回帖 登录 | 注册账号

本版积分规则

小黑屋|手机版|Archiver|看流星社区 |网站地图

GMT+8, 2019-11-12 06:48

Powered by Kanliuxing X3.4

© 2010-2019 kanliuxing.com

快速回复 返回顶部 返回列表