- 注册时间
- 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;
- }
复制代码 |
|