- 注册时间
 - 2021-4-16
 
- 最后登录
 - 2024-3-7
 
- 在线时间
 - 2 小时
 
 
 
 
 
编程入门 
  
	- 龙马币
 - 40 
 
 
 
 
 | 
 
实现类似功能的代码很多,但是我这份没有参考到别人的代码,纯粹是看微软文档撸出来的。这个需求是源于我的一个比较复杂的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。 
 
 
 
- #include <windows.h>
 
 - #include <stdio.h>
 
 - #include <string.h>
 
 -  
 
 - #include "winapi.h"
 
 -  
 
 - #ifndef MIN
 
 - #define MIN(a, b) ((a) > (b) ? (b) : (a))
 
 - #endif
 
 -  
 
 - #define RVA(a) ((PVOID)((ULONG_PTR)hExecutable + (a)))
 
 - #define K32RVA(a) ((PVOID)((ULONG_PTR)hKernel32 + (a)))
 
 -  
 
 - #define API pContext->
 
 -  
 
 - typedef struct {
 
 -     union {
 
 - #ifdef _WIN64
 
 -         struct {
 
 -             DWORD64  Unused1:63;
 
 -             DWORD64  OrdinalIfSet:1;
 
 -         } Flag;
 
 -         DWORD64 Long;
 
 - #else
 
 -         struct {
 
 -             DWORD  Unused1:31;
 
 -             DWORD  OrdinalIfSet:1;
 
 -         } Flag;
 
 -         DWORD Long;
 
 - #endif
 
 -         WORD OrdinalNumber;
 
 -         DWORD NameAddress;
 
 -     } u;
 
 - } IMPORT_LOOKUP_DESC, *PIMPORT_LOOKUP_DESC;
 
 -  
 
 - typedef struct {
 
 -     LoadLibraryA_t LoadLibraryA;
 
 -     GetProcAddress_t GetProcAddress;
 
 -     GetModuleHandleA_t GetModuleHandleA;
 
 - } LINK_CONTEXT, *PLINK_CONTEXT;
 
 -  
 
 - typedef struct {
 
 -     DWORD Page;
 
 -     DWORD BlockSize;
 
 -     struct {
 
 -         WORD Offset:12;
 
 -         WORD Type:4;
 
 -     } TypeOffset[0];
 
 - } BASE_RELOCATION_BLOCK, *PBASE_RELOCATION_BLOCK;
 
 -  
 
 - HMODULE hExecutable = NULL;
 
 -  
 
 - int SDK_strcmp(const char *s1, const char *s2)
 
 - {
 
 -     while(*s1 && *s2) {
 
 -         if (*s1 != *s2)
 
 -             return -1;
 
 -         s1 ++;
 
 -         s2 ++;
 
 -     }
 
 -     return *s2 - *s1;
 
 - }
 
 -  
 
 - PVOID SDK_GetProcAddress(HMODULE hKernel32, const char *FuncName)
 
 - {
 
 -     PIMAGE_DOS_HEADER pDos = (PIMAGE_DOS_HEADER)hKernel32;
 
 -     PIMAGE_NT_HEADERS pNt = (PIMAGE_NT_HEADERS)((char *)pDos + pDos->e_lfanew);
 
 -  
 
 -     PIMAGE_EXPORT_DIRECTORY EDT = (PIMAGE_EXPORT_DIRECTORY)K32RVA(pNt->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress);
 
 -  
 
 -     // printf("DLL Name: %s\n", K32RVA(EDT->Name));
 
 -     // printf("Number Of Functions: %d\n", EDT->NumberOfFunctions);
 
 -     // printf("Number Of Names: %d\n", EDT->NumberOfNames);
 
 -  
 
 -     PDWORD ExportAddressTable = (PDWORD)MOD_RVA(EDT->AddressOfFunctions);
 
 -     PDWORD ExportNamePointerTable = (PDWORD)MOD_RVA(EDT->AddressOfNames);
 
 -     PWORD ExportOrdinalTable  = (PWORD)MOD_RVA(EDT->AddressOfNameOrdinals);
 
 -  
 
 -     for(size_t i = 0; i < EDT->NumberOfNames; i++)
 
 -     {
 
 -         PCHAR name = (PCHAR)MOD_RVA(ExportNamePointerTable[i]);
 
 -  
 
 -         if (SDK_strcmp(name, FuncName) == 0) {
 
 -             WORD Ordinal = ExportOrdinalTable[i];
 
 -             return (PVOID)MOD_RVA(ExportAddressTable[Ordinal]);
 
 -         }
 
 -     }
 
 -  
 
 -     return NULL;
 
 - }
 
 -  
 
 - void LinkDLL(PLINK_CONTEXT pContext, PIMAGE_IMPORT_DESCRIPTOR IDT)
 
 - {
 
 -     const char* DLLName = (const char*)RVA(IDT->Name);
 
 -     HMODULE hDLL = API GetModuleHandleA(DLLName);
 
 -  
 
 -     if (!hDLL) {
 
 -         hDLL = API LoadLibraryA(DLLName);
 
 -     }
 
 -  
 
 -     if (!hDLL) {
 
 -         return -1;
 
 -     }
 
 -  
 
 -     printf("** %s **\n", DLLName);
 
 -  
 
 -     PIMPORT_LOOKUP_DESC ILD = (PIMPORT_LOOKUP_DESC)RVA(IDT->OriginalFirstThunk);
 
 -     PULONG_PTR IAT = (PULONG_PTR)RVA(IDT->FirstThunk);
 
 -  
 
 -     while (ILD->u.Long) {
 
 -         if (!ILD->u.Flag.OrdinalIfSet) {
 
 -             *IAT = (ULONG_PTR) API GetProcAddress(hDLL, (PCSTR)RVA(ILD->u.NameAddress+2));
 
 -             printf("%s %p\n", RVA(ILD->u.NameAddress+2), *IAT);
 
 -         } else {
 
 -             *IAT = (ULONG_PTR) API GetProcAddress(hDLL, (PCSTR)MAKEINTRESOURCE(ILD->u.OrdinalNumber));
 
 -             printf("%d %p\n", RVA(ILD->u.OrdinalNumber), *IAT);
 
 -         }
 
 -         IAT ++;
 
 -         ILD ++;
 
 -     }
 
 - }
 
 -  
 
 - void RelocImage(PBASE_RELOCATION_BLOCK BRB, ptrdiff_t Difference)
 
 - {
 
 -     printf("Difference: %ld\n", Difference);
 
 -     for(size_t i = 0; i < (BRB->BlockSize - 8)/2; i++)
 
 -     {
 
 -         WORD Offset = BRB->TypeOffset[i].Offset;
 
 -         printf("0x%.4x\t%d ", Offset, BRB->TypeOffset[i].Type);
 
 -  
 
 -         switch(BRB->TypeOffset[i].Type) {
 
 -             case IMAGE_REL_BASED_ABSOLUTE:break; // The base relocation is skipped
 
 -             case IMAGE_REL_BASED_HIGHLOW: // TODO Not test yet
 
 -                 *(DWORD*)RVA(BRB->Page + Offset) += Difference;
 
 -                 break;
 
 -             case IMAGE_REL_BASED_DIR64:
 
 -                 printf("DIR64 %lx => ", *(ptrdiff_t*)RVA(BRB->Page + Offset));
 
 -                 *(ptrdiff_t*)RVA(BRB->Page + Offset) += Difference;
 
 -                 printf("%lx", *(ptrdiff_t*)RVA(BRB->Page + Offset));
 
 -                 break;
 
 -             default:
 
 -                 fprintf(stderr, "Not support this relocation type yet.");
 
 -                 abort();
 
 -                 break;
 
 -         }
 
 -         putchar('\n');
 
 -     }
 
 - }
 
 -  
 
 - #define LLRVA(a) ((PVOID)((char*)Image + (a)))
 
 -  
 
 - HMODULE SDK_LoadLibrary(PCSTR LibraryName)
 
 - {
 
 -     IMAGE_DOS_HEADER DosHdr;
 
 -     IMAGE_NT_HEADERS NtHdr;
 
 -     HMODULE hModule = NULL;
 
 -  
 
 -     FILE *libfp = fopen(LibraryName, "rb");
 
 -  
 
 -     if (!libfp)
 
 -         goto CLEAN;
 
 -  
 
 -     fread(&DosHdr, sizeof(IMAGE_DOS_HEADER), 1, libfp);
 
 -  
 
 -     fseek(libfp, DosHdr.e_lfanew, SEEK_SET);
 
 -     fread(&NtHdr, sizeof(IMAGE_NT_HEADERS), 1, libfp);
 
 -  
 
 -     PVOID Image = VirtualAlloc(NULL, NtHdr.OptionalHeader.SizeOfImage, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
 
 -     if (!Image)
 
 -         goto CLEAN;
 
 -  
 
 -     fseek(libfp, 0, SEEK_SET);
 
 -     fread(Image, NtHdr.OptionalHeader.SizeOfHeaders, 1, libfp);
 
 -  
 
 -     PIMAGE_NT_HEADERS pNt = (PIMAGE_NT_HEADERS)((char *)Image + DosHdr.e_lfanew);
 
 -  
 
 -     PIMAGE_SECTION_HEADER Sections = IMAGE_FIRST_SECTION(pNt);
 
 -  
 
 -     for(size_t i = 0; i < pNt->FileHeader.NumberOfSections; i++)
 
 -     {
 
 -         fseek(libfp, Sections[i].PointerToRawData, SEEK_SET);
 
 -         fread(LLRVA(Sections[i].VirtualAddress), Sections[i].SizeOfRawData, 1, libfp);
 
 -         printf("%s\n", Sections[i].Name);
 
 -     }
 
 -  
 
 -     hModule = (HMODULE)Image;
 
 - CLEAN:
 
 -     if (libfp)
 
 -         fclose(libfp);
 
 -     return hModule;
 
 - }
 
 -  
 
 - void SDK_FreeLibrary(HMODULE hModule)
 
 - {
 
 -     VirtualFree(hModule, 0, MEM_RELEASE);
 
 - }
 
 -  
 
 - int main(int argc, const char *argv[])
 
 - {
 
 -     LINK_CONTEXT Context;
 
 -  
 
 -     if (argc != 2) {
 
 -         fprintf(stderr, "Missing dll\n");
 
 -         return -1;
 
 -     }
 
 -  
 
 -     HMODULE hKernel32 = GetModuleHandleA("kernel32.dll");
 
 -      
 
 -     Context.LoadLibraryA = (LoadLibraryA_t)SDK_GetProcAddress(hKernel32, "LoadLibraryA");
 
 -     Context.GetProcAddress = (GetProcAddress_t)SDK_GetProcAddress(hKernel32, "GetProcAddress");
 
 -     Context.GetModuleHandleA = (GetModuleHandleA_t)SDK_GetProcAddress(hKernel32, "GetModuleHandleA");
 
 -  
 
 -     printf("LoadLibraryA\t\t%p\n", Context.LoadLibraryA);
 
 -     printf("GetProcAddress\t\t%p\n", Context.GetProcAddress);
 
 -     printf("GetModuleHandleA\t%p\n", Context.GetModuleHandleA);
 
 -  
 
 -     hExecutable = SDK_LoadLibrary(argv[1]);
 
 -  
 
 -     if (hExecutable == NULL) {
 
 -         fprintf(stderr, "Can not load dll\n");
 
 -         exit(-1);
 
 -     }
 
 -  
 
 -     PIMAGE_DOS_HEADER pDos = (PIMAGE_DOS_HEADER)hExecutable;
 
 -     PIMAGE_NT_HEADERS pNt = (PIMAGE_NT_HEADERS)((char *)pDos + pDos->e_lfanew);
 
 -  
 
 -     if ((PVOID)hExecutable != (PVOID)pNt->OptionalHeader.ImageBase) 
 
 -     {
 
 -  
 
 -         printf("Image Base: %p\n", pNt->OptionalHeader.ImageBase);
 
 -         printf("Loaded Base: %p\n", hExecutable);
 
 -  
 
 -         ptrdiff_t Difference = (ptrdiff_t)hExecutable - (ptrdiff_t)pNt->OptionalHeader.ImageBase;
 
 -  
 
 -         PBASE_RELOCATION_BLOCK BRB = (PBASE_RELOCATION_BLOCK)RVA(pNt->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress);
 
 -  
 
 -         while (BRB->BlockSize) {
 
 -             RelocImage(BRB, Difference);
 
 -             BRB = (PBASE_RELOCATION_BLOCK)((char*)BRB + BRB->BlockSize);
 
 -         }
 
 -     }
 
 -  
 
 -     PIMAGE_IMPORT_DESCRIPTOR IDT = (PIMAGE_IMPORT_DESCRIPTOR)RVA(pNt->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress);
 
 -     while (IDT->Name != 0) {
 
 -         LinkDLL(&Context, IDT);
 
 -         IDT ++;
 
 -     }
 
 -  
 
 -     ((void(*)(HMODULE,DWORD,PVOID))RVA(pNt->OptionalHeader.AddressOfEntryPoint))(hExecutable, DLL_PROCESS_ATTACH, NULL);
 
 -  
 
 -     SDK_FreeLibrary(hExecutable);
 
 -  
 
 -     return 0;
 
 - }
 
 
  复制代码 |   
 
 
 
 |