diff --git a/.gitignore b/.gitignore index dc90cac..6c55631 100644 --- a/.gitignore +++ b/.gitignore @@ -14,6 +14,7 @@ src/**/screenshot/* src/**/release/* src/**/debug/* src/**/bin/* +src/**/sample/* util/asset/** util/bin/** util/script/** diff --git a/src/memdll/Makefile b/src/memdll/Makefile index 16932fe..d155b9a 100644 --- a/src/memdll/Makefile +++ b/src/memdll/Makefile @@ -61,7 +61,6 @@ libwinpe: libwinpe.c @echo \#\#building $@ ... $(CC) $< -o $(PREFIX)/$@$(ARCH_POSTFIX)$(DLL_EXT) \ -shared $(CFLAGS) $(LDFLAGS) $(INCS) $(LIBS) $(LIBDIRS) - rm -rf $(PREFIX)/*.exp win_injectmemdll_shellcodestub: win_injectmemdll.c libwinpe python $@.py $< \ @@ -73,6 +72,7 @@ win_injectmemdll: win_injectmemdll_shellcodestub libwinpe $(CC) $(PREFIX)/_$(ARCH_POSTFIX)$@.c \ -o $(PREFIX)/$@$(ARCH_POSTFIX)$(EXE_EXT)\ -llibwinpe$(ARCH_POSTFIX) \ + -Wno-undefined-inline \ $(CFLAGS) $(LDFLAGS) $(INCS) $(LIBS) $(LIBDIRS) .PHONY: all clean prepare libwinpe win_injectmemdll \ No newline at end of file diff --git a/src/memdll/libwinpe.def b/src/memdll/libwinpe.def new file mode 100644 index 0000000..e69de29 diff --git a/src/memdll/win_injectmemdll.c b/src/memdll/win_injectmemdll.c index c1ea7e6..66ee5d1 100644 --- a/src/memdll/win_injectmemdll.c +++ b/src/memdll/win_injectmemdll.c @@ -4,16 +4,24 @@ */ #include +#include #include "winpe.h" +#define DUMP(path, addr, size)\ + FILE *_fp = fopen(path, "wb");\ + fwrite(addr, 1, size, _fp);\ + fclose(_fp) + // these functions are stub function, will be filled by python -unsigned char g_oepshellcode[] = {0x90}; -unsigned char g_memiatshellcode[] = {0x90}; +unsigned char g_oepinit_code[] = {0x90}; +unsigned char g_membindiat_code[] = {0x90}; +unsigned char g_memfindexp_code[] = {0x90}; void _oepshellcode(void *mempe_exe, void *mempe_dll, void *shellcode, PIMAGE_SECTION_HEADER psecth, DWORD orgoeprva) { // PE struct declear +#define FUNC_SIZE 0x200 void *mempe; PIMAGE_DOS_HEADER pDosHeader; PIMAGE_NT_HEADERS pNtHeader; @@ -28,13 +36,15 @@ void _oepshellcode(void *mempe_exe, void *mempe_dll, PIMAGE_IMPORT_BY_NAME pFuncName = NULL; // bind the pointer to buffer - size_t end = sizeof(g_oepshellcode); - size_t *pexeoepva = (size_t*)(g_oepshellcode + end - 6*sizeof(size_t)); - size_t *pdllbase = (size_t*)(g_oepshellcode + end - 5*sizeof(size_t)); - size_t *pdlloepva = (size_t*)(g_oepshellcode + end - 4*sizeof(size_t)); - size_t *pmemiatbind = (size_t*)(g_oepshellcode + end - 3*sizeof(size_t)); - size_t *pexeloadlibrarya = (size_t*)(g_oepshellcode + end - 2*sizeof(size_t)); - size_t *pexegetprocessaddress = (size_t*)(g_oepshellcode + end - 1*sizeof(size_t)); + size_t oepinit_end = sizeof(g_oepinit_code); + size_t memiatbind_start = FUNC_SIZE; + size_t memfindexp_start = memiatbind_start + FUNC_SIZE; + size_t *pexeoepva = (size_t*)(g_oepinit_code + oepinit_end - 6*sizeof(size_t)); + size_t *pdllbase = (size_t*)(g_oepinit_code + oepinit_end - 5*sizeof(size_t)); + size_t *pdlloepva = (size_t*)(g_oepinit_code + oepinit_end - 4*sizeof(size_t)); + size_t *pmemiatbind = (size_t*)(g_oepinit_code + oepinit_end - 3*sizeof(size_t)); + size_t *pexeloadlibrarya = (size_t*)(g_oepinit_code + oepinit_end - 2*sizeof(size_t)); + size_t *pexegetprocessaddress = (size_t*)(g_oepinit_code + oepinit_end - 1*sizeof(size_t)); // get the information of exe mempe = mempe_exe; @@ -46,12 +56,8 @@ void _oepshellcode(void *mempe_exe, void *mempe_dll, pImpEntry = &pDataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT]; pImpDescriptor = (PIMAGE_IMPORT_DESCRIPTOR)(mempe + pImpEntry->VirtualAddress); size_t exeimagebase = pOptHeader->ImageBase; - DWORD exeoeprva = pOptHeader->AddressOfEntryPoint; - DWORD exeloadlibrarya_rva = winpe_memfindiat( - mempe, "kernel32.dll", "LoadLibraryA"); - DWORD exegetprocessaddress_rva = winpe_memfindiat( - mempe, "kernel32.dll", "GetProcAddress"); - + size_t shellcodebase = exeimagebase + psecth->VirtualAddress; + // get the information of dll mempe = mempe_dll; pDosHeader = (PIMAGE_DOS_HEADER)mempe; @@ -65,14 +71,22 @@ void _oepshellcode(void *mempe_exe, void *mempe_dll, // fill the address table *pexeoepva = exeimagebase + orgoeprva; *pdllbase = dllimagebase; - *pdlloepva = dllimagebase + dlloeprva; - *pmemiatbind = exeimagebase + psecth->VirtualAddress + end; - *pexeloadlibrarya = exeimagebase + exeloadlibrarya_rva; - *pexegetprocessaddress = exeimagebase + exegetprocessaddress_rva; + *pdlloepva = dllimagebase + pOptHeader->AddressOfEntryPoint; + *pmemiatbind = shellcodebase + memiatbind_start; + *pexeloadlibrarya = exeimagebase + + (size_t)(winpe_memfindiat(mempe_exe, + "kernel32.dll", "LoadLibraryA") - mempe_exe); + *pexegetprocessaddress = sizeof(size_t) > 4 ? + shellcodebase + memfindexp_start : // x64 + exeimagebase + (size_t)(winpe_memfindiat(mempe_exe, // x86 + "kernel32.dll", "GetProcAddress") - mempe_exe); // copy to the target - memcpy(shellcode, g_oepshellcode, sizeof(g_oepshellcode)); - memcpy(shellcode + end, g_memiatshellcode, sizeof(g_memiatshellcode)); + memcpy(shellcode , g_oepinit_code, sizeof(g_oepinit_code)); + memcpy(shellcode + memiatbind_start, + g_membindiat_code, sizeof(g_membindiat_code)); + memcpy(shellcode + memfindexp_start, + g_memfindexp_code, sizeof(g_memfindexp_code)); } int injectdll_mem(const char *exepath, @@ -111,7 +125,7 @@ int injectdll_mem(const char *exepath, strcpy((char*)secth.Name, ".module"); winpe_noaslr(mempe_exe); winpe_appendsecth(mempe_exe, §h); - DWORD orgoeprva = winpe_setoep(mempe_exe, secth.VirtualAddress); + DWORD orgoeprva = winpe_oepval(mempe_exe, secth.VirtualAddress); winpe_memreloc(mempe_dll, imgbase_exe + secth.VirtualAddress + SHELLCODE_SIZE); _oepshellcode(mempe_exe, mempe_dll, shellcode, §h, orgoeprva); @@ -129,16 +143,53 @@ int injectdll_mem(const char *exepath, return 0; } -int main(int argc, char *argv[]) +void test_exp() { - char outpath[MAX_PATH]; + // test loadlibrary, getprocaddress + HMODULE hmod = NULL; + size_t exprva = 0; + size_t expva = 0; + void* func = NULL; + + hmod = LoadLibraryA("kernel32.dll"); + assert(hmod!=NULL); + expva = (size_t)GetProcAddress(hmod, "LoadLibraryA"); + exprva = (size_t)winpe_memfindexp(hmod, "LoadLibraryA") - (size_t)hmod; + func = winpe_memforwardexp(hmod, exprva, LoadLibraryA, (PFN_GetProcAddress)winpe_memfindexp); + assert(exprva!=0 && (size_t)func==expva && func!=NULL); + expva = (size_t)GetProcAddress(hmod, "InitializeSListHead"); + exprva = (size_t)winpe_memfindexp(hmod, "InitializeSListHead") - (size_t)hmod; + func = winpe_memforwardexp(hmod, exprva, LoadLibraryA, (PFN_GetProcAddress)winpe_memfindexp); + assert(exprva!=0 && (size_t)func==expva && func!=NULL); + expva = (size_t)GetProcAddress(hmod, "GetSystemTimeAsFileTime"); + exprva = (size_t)winpe_memfindexp(hmod, "GetSystemTimeAsFileTime") - (size_t)hmod; + func = winpe_memforwardexp(hmod, exprva, LoadLibraryA, (PFN_GetProcAddress)winpe_memfindexp); + assert(exprva!=0 && (size_t)func==expva && func!=NULL); +} + +void test_memdll(char *dllpath) +{ + size_t mempesize = 0; + void *mempe = winpe_memload_file(dllpath, &mempesize, TRUE);; + assert(mempe!=0 && mempesize!=0); + winpe_membindiat(mempe, LoadLibraryA, (PFN_GetProcAddress)winpe_memfindexp); + winpe_memLoadLibrary(mempe); + free(mempe); +} + +int main(int argc, char *argv[]) +{ +#ifdef _DEBUG + test_exp(); + if(argc>3) test_memdll(argv[2]); +#endif if(argc < 3) { printf("usage: win_injectmemdll exepath dllpath [outpath]\n"); printf("v0.2, developed by devseed\n"); return 0; } - + char outpath[MAX_PATH]; if(argc >= 4) strcpy(outpath, argv[3]); else strcpy(outpath, "out.exe"); return injectdll_mem(argv[1], argv[2], outpath); diff --git a/src/memdll/win_injectmemdll_shellcodestub.py b/src/memdll/win_injectmemdll_shellcodestub.py index 9ae1909..e561365 100644 --- a/src/memdll/win_injectmemdll_shellcodestub.py +++ b/src/memdll/win_injectmemdll_shellcodestub.py @@ -7,7 +7,7 @@ import lief from keystone import Ks, KS_ARCH_X86, KS_MODE_32, KS_MODE_64 -def gen_oepshellcode32(): +def gen_oepinit_code32(): ks = Ks(KS_ARCH_X86, KS_MODE_32) code_str = f""" // for relative address, get the base of addr @@ -15,6 +15,7 @@ def gen_oepshellcode32(): lea ebx, [eax-5]; // bind iat + push eax; // rvaaddr = 0 lea eax, [ebx + exegetprocessaddress]; mov eax, [eax]; // iat mov eax, [eax]; // iat->addr @@ -27,7 +28,7 @@ def gen_oepshellcode32(): mov eax, [eax]; // dllbase value push eax; call [ebx + memiatbind]; - add esp, 0xC; + add esp, 0x10; // call dll oep, for dll entry xor eax, eax; @@ -53,12 +54,12 @@ def gen_oepshellcode32(): exeloadlibrarya: nop;nop;nop;nop; exegetprocessaddress: nop;nop;nop;nop; """ - print("gen_oepshellcode32", code_str) + print("gen_oepinit_code32", code_str) payload, _ = ks.asm(code_str) print("payload: ", [hex(x) for x in payload]) return payload -def gen_oepshellcode64(): +def gen_oepinit_code64(): ks = Ks(KS_ARCH_X86, KS_MODE_64) code_str = f""" // for relative address, get the base of addr @@ -71,8 +72,7 @@ def gen_oepshellcode64(): // bind iat lea r8, [rbx + exegetprocessaddress]; - mov r8, [r8]; // iat - mov r8, [r8]; // iat->addr + mov r8, [r8]; // winpe_memfindexp lea rdx, [rbx + exeloadlibrarya]; mov rdx, [rdx]; // iat mov rdx, [rdx]; // iat->addr @@ -106,7 +106,7 @@ def gen_oepshellcode64(): exeloadlibrarya: nop;nop;nop;nop;nop;nop;nop;nop; exegetprocessaddress: nop;nop;nop;nop;nop;nop;nop;nop; """ - print("gen_oepshellcode64", code_str) + print("gen_oepinit_code64", code_str) payload, _ = ks.asm(code_str) print("payload: ", [hex(x) for x in payload]) return payload @@ -115,41 +115,58 @@ def gen_oepshellcode64(): def inject_shellcodestubs(srcpath, libwinpepath, targetpath): pedll = lief.parse(libwinpepath) pedll_oph = pedll.optional_header - memiatfunc = next(filter( - lambda e : e.name == "winpe_membindiat", - pedll.exported_functions)) - memiatshellcode = \ - pedll.get_content_from_virtual_address( - memiatfunc.address, 0x200) - # memiatshellcode = memiatshellcode[:memiatshellcode.index(0xC3)+1] # retn - + + # generate oepint shellcode if pedll_oph.magic == lief.PE.PE_TYPE.PE32_PLUS: - oepshellcode = gen_oepshellcode64() + oepinit_code = gen_oepinit_code64() pass elif pedll_oph.magic == lief.PE.PE_TYPE.PE32: - oepshellcode = gen_oepshellcode32() + oepinit_code = gen_oepinit_code32() pass else: print("error invalid pe magic!", pedll_oph.magic) return + # if len(oepinit_code) < 0x200: oepinit_code.extend([0x00] * (0x200 - len(oepinit_code))) + + # find necessary functions + membindiat_func = next(filter( + lambda e : e.name == "winpe_membindiat", + pedll.exported_functions)) + membindiat_code = \ + pedll.get_content_from_virtual_address( + membindiat_func.address, 0x200) + # memiatshellcode = memiatshellcode[:memiatshellcode.index(0xC3)+1] # retn + try: + memfindexp_func = next(filter( + lambda e : e.name == "winpe_memfindexp", # x64 stdcall name + pedll.exported_functions)) + except StopIteration: + memfindexp_func = next(filter( + lambda e : e.name == "_winpe_memfindexp@8", # x86 stdcall name + pedll.exported_functions)) + memfindexp_code = \ + pedll.get_content_from_virtual_address( + memfindexp_func.address, 0x200) + # write shellcode to c source file with open(srcpath, "rb") as fp: srctext = fp.read().decode('utf8') - - _codetext = ",".join([hex(x) for x in oepshellcode]) - srctext = re.sub(r"g_oepshellcode(.+?)(\{0x90\})", - r"g_oepshellcode\1{" + _codetext +"}", srctext) - _codetext = ",".join([hex(x) for x in memiatshellcode]) - srctext = re.sub(r"g_memiatshellcode(.+?)(\{0x90\})", - r"g_memiatshellcode\1{" + _codetext +"}", srctext) - + _codetext = ",".join([hex(x) for x in oepinit_code]) + srctext = re.sub(r"g_oepinit_code(.+?)(\{0x90\})", + r"g_oepinit_code\1{" + _codetext +"}", srctext) + _codetext = ",".join([hex(x) for x in membindiat_code]) + srctext = re.sub(r"g_membindiat_code(.+?)(\{0x90\})", + r"g_membindiat_code\1{" + _codetext +"}", srctext) + _codetext = ",".join([hex(x) for x in memfindexp_code]) + srctext = re.sub(r"g_memfindexp_code(.+?)(\{0x90\})", + r"g_memfindexp_code\1{" + _codetext +"}", srctext) with open(targetpath, "wb") as fp: fp.write(srctext.encode('utf8')) def debug(): inject_shellcodestubs("win_injectmemdll.c", "./bin/libwinpe64.dll", - "./bin/_win_injectmemdll.c") + "./bin/_64win_injectmemdll.c") pass def main(): diff --git a/util/include/winpe.h b/util/include/winpe.h index 7330a21..897a47d 100644 --- a/util/include/winpe.h +++ b/util/include/winpe.h @@ -1,11 +1,15 @@ /* - winpe.h, by devseed, v0.2 + winpe.h, by devseed, v0.2.2 for parsing windows pe structure, adjust realoc addrs, or iat + this function for shellcode should only use release version history: v0.1 initial version, with load pe in memory align V0.1.2 adjust declear name, load pe iat v0.2 add append section, findiat function + v0.2.2 add function winpe_memfindexp + v0.2.5 inline basic functions, better for shellcode + v0.3 add winpe_memloadlibrary, winpe_memgetprocaddress, winpe_memfreelibrary */ @@ -32,6 +36,12 @@ #endif #endif +#ifdef _WIN32 +#define STDCALL __stdcall +#else +#define STDCALL __attribute__((stdcall)) +#endif + #ifdef __cplusplus extern "C" { #endif @@ -49,74 +59,191 @@ typedef HMODULE (WINAPI *PFN_LoadLibraryA)( typedef FARPROC (WINAPI *PFN_GetProcAddress)( HMODULE hModule, LPCSTR lpProcName); -// PE functions +typedef PFN_GetProcAddress PFN_GetProcRVA; + +typedef LPVOID (WINAPI *PFN_VirtualAlloc)( + LPVOID lpAddress, SIZE_T dwSize, + DWORD flAllocationType, DWORD flProtect); + +typedef BOOL (WINAPI *PFN_VirtualFree)( + LPVOID lpAddress, SIZE_T dwSize, + DWORD dwFreeType); + +typedef BOOL (WINAPI *PFN_VirtualProtect)( + LPVOID lpAddress, SIZE_T dwSize, + DWORD flNewProtect, PDWORD lpflOldProtect); + +typedef SIZE_T (WINAPI *PFN_VirtualQuery)( + LPCVOID lpAddress, + PMEMORY_BASIC_INFORMATION lpBuffer, + SIZE_T dwLength); + +typedef BOOL (WINAPI *PFN_DllMain)(HINSTANCE hinstDLL, + DWORD fdwReason, LPVOID lpReserved ); + +#define WINPE_LDFLAG_RVAPROC 0x1 + +// PE high order fnctions +/* + load the origin rawpe file in memory buffer by mem align + mempe means the pe in memory alignment + return mempe buffer, memsize +*/ +WINPEDEF WINPE_EXPORT +void* winpe_memload_file(const char *path, + size_t *pmemsize, bool_t same_align); + /* load the overlay data in a pe file return overlay buf, overlay size */ -WINPEDEF WINPE_EXPORT +WINPEDEF WINPE_EXPORT void* winpe_overlayload_file(const char *path, size_t *poverlaysize); /* - for overlay section in a pe file - return the overlay offset + similar to LoadlibrayA, will call dllentry + will load the mempe in a valid imagebase + return hmodule base */ -WINPEDEF WINPE_EXPORT -size_t winpe_overlayoffset(const void *rawpe); +WINPEDEF WINPE_EXPORT +void* STDCALL winpe_memLoadLibrary(void *mempe); /* - load the origin rawpe file in memory buffer by mem align - return mempe buffer, memsize + if imagebase==0, will load on mempe, or in imagebase + will load the mempe in a valid imagebase, + return hmodule base +*/ +WINPEDEF WINPE_EXPORT +inline void* STDCALL winpe_memLoadLibraryEx(void *mempe, + size_t imagebase, DWORD flag, + PFN_LoadLibraryA pfnLoadLibraryA, + PFN_GetProcAddress pfnGetProcAddress); + +/* + similar to FreeLibrary, will call dllentry + return true or false +*/ +WINPEDEF WINPE_EXPORT +inline BOOL STDCALL winpe_memFreeLibrary(void *mempe); + +/* + similar to GetProcAddress + return function va +*/ +WINPEDEF WINPE_EXPORT +inline PROC STDCALL winpe_memGetProcAddress( + void *mempe, const char *funcname); + +// PE query functions +/* + use ped to find kernel32.dll address + return kernel32.dll address +*/ +WINPEDEF WINPE_EXPORT +inline void* winpe_findkernel32(); + +WINPEDEF WINPE_EXPORT +inline PROC winpe_findloadlibrarya(); + +WINPEDEF WINPE_EXPORT +inline PROC winpe_findgetprocaddress(); + +/* + find a valid space address start from imagebase with imagesize + use PFN_VirtualQuery for better use + return va with imagesize +*/ +WINPEDEF WINPE_EXPORT +inline void* winpe_findspace( + size_t imagebase, size_t imagesize, + PFN_VirtualQuery pfnVirtualQuery); + +// PE load, adjust functions +/* + for overlay section in a pe file + return the overlay offset */ WINPEDEF WINPE_EXPORT -void* winpe_memload_file(const char *path, - size_t *pmemsize, bool_t same_align); +inline size_t winpe_overlayoffset(const void *rawpe); /* load the origin rawpe in memory buffer by mem align return memsize */ WINPEDEF WINPE_EXPORT -size_t winpe_memload(const void *rawpe, size_t rawsize, - void *mempe, size_t memsize, bool_t same_align); +inline size_t winpe_memload( + const void *rawpe, size_t rawsize, + void *mempe, size_t memsize, + bool_t same_align); /* realoc the addrs for the mempe addr as image base + origin image base usually at 0x00400000, 0x0000000180000000 + new image base mush be divided by 0x10000, if use loadlibrary return realoc count */ WINPEDEF WINPE_EXPORT -size_t winpe_memreloc(void *mempe, size_t newimagebase); +inline size_t winpe_memreloc( + void *mempe, size_t newimagebase); /* - load the iat for the mempe + load the iat for the mempe, use rvafunc for winpe_memfindexp return iat count */ WINPEDEF WINPE_EXPORT -size_t winpe_membindiat(void *mempe, +inline size_t winpe_membindiat(void *mempe, PFN_LoadLibraryA pfnLoadLibraryA, PFN_GetProcAddress pfnGetProcAddress); /* find the iat addres, for call [iat] - return target iat rva + return target iat va */ -WINPEDEF WINPE_EXPORT -size_t winpe_memfindiat(void *mempe, +WINPEDEF WINPE_EXPORT +inline void* winpe_memfindiat(void *mempe, LPCSTR dllname, LPCSTR funcname); +/* + find the exp addres, the same as GetProcAddress + without forward to other dll + such as NTDLL.RtlInitializeSListHead + return target exp va +*/ +WINPEDEF WINPE_EXPORT +inline void* STDCALL winpe_memfindexp( + void *mempe, LPCSTR funcname); + +/* + forward the exp to the final expva + return the final exp va +*/ +WINPEDEF WINPE_EXPORT +inline void *winpe_memforwardexp( + void *mempe, size_t exprva, + PFN_LoadLibraryA pfnLoadLibraryA, + PFN_GetProcAddress pfnGetProcAddress); + +// PE modify function /* change the oep of the pe if newoeprva!=0 return the old oep rva */ WINPEDEF WINPE_EXPORT -DWORD winpe_setoep(void *mempe, DWORD newoeprva); +inline DWORD winpe_oepval(void *mempe, DWORD newoeprva); + +/* + change the imagebase of the pe if newimagebase!=0 + return the old imagebase va +*/ +WINPEDEF WINPE_EXPORT +inline size_t winpe_imagebaseval(void *mempe, size_t newimagebase); /* close the aslr feature of an pe */ WINPEDEF WINPE_EXPORT -void winpe_noaslr(void *pe); +inline void winpe_noaslr(void *pe); /* Append a section header in a pe, sect rva will be ignored @@ -124,7 +251,7 @@ void winpe_noaslr(void *pe); return image size */ WINPEDEF WINPE_EXPORT -size_t winpe_appendsecth(void *mempe, +inline size_t winpe_appendsecth(void *mempe, PIMAGE_SECTION_HEADER psecth); @@ -135,12 +262,73 @@ size_t winpe_appendsecth(void *mempe, #ifdef WINPE_IMPLEMENTATION #include +#ifndef _DEBUG +#define NDEBUG +#endif +#include #include -// PE functions +inline static int _inl_stricmp(const char *str1, const char *str2) +{ + int i=0; + while(str1[i]!=0 && str2[i]!=0) + { + if (str1[i] == str2[i] + || str1[i] + 0x20 == str2[i] + || str2[i] + 0x20 == str1[i]) + { + i++; + } + else + { + return (int)str1[i] - (int)str2[i]; + } + } + return (int)str1[i] - (int)str2[i]; +} + +inline static void* _inl_memset(void *buf, int ch, size_t n) +{ + char *p = buf; + for(int i=0;iSizeOfHeaders); + _inl_memset(mempe, 0, imagesize); + _inl_memcpy(mempe, rawpe, pOptHeader->SizeOfHeaders); for(WORD i=0;iFirstThunk); pOftThunk = (PIMAGE_THUNK_DATA) (mempe + pImpDescriptor->OriginalFirstThunk); - HMODULE hmod = pfnLoadLibraryA(pDllName); - if(!hmod) return 0; + size_t dllbase = (size_t)pfnLoadLibraryA(pDllName); + if(!dllbase) return 0; for (int j=0; pFtThunk[j].u1.Function && pOftThunk[j].u1.Function; j++) { - PROC addr = NULL; - if(sizeof(size_t) > 4) // x64 - { - if((pOftThunk[j].u1.Ordinal >> 63) != 0x1) // use name - { - pFuncName=(PIMAGE_IMPORT_BY_NAME)(mempe + - pOftThunk[j].u1.AddressOfData); - addr = pfnGetProcAddress(hmod, pFuncName->Name); - } - else // use ordinal - { - addr =pfnGetProcAddress(hmod, - (LPCSTR)(pOftThunk[j].u1.Ordinal & 0x000000000000ffff)); - } - } - else // x86 - { - if((pOftThunk[j].u1.Ordinal >>31) != 0x1) // use name - { - pFuncName=(PIMAGE_IMPORT_BY_NAME)(mempe + - pOftThunk[j].u1.AddressOfData); - addr = pfnGetProcAddress(hmod, pFuncName->Name); - } - else // use ordinal - { - addr =pfnGetProcAddress(hmod, - (LPCSTR)(pOftThunk[j].u1.Ordinal & 0x0000ffff)); - } - } - if(!addr) return 0; - pFtThunk[j].u1.Function = (size_t)addr; + // supposed iat has no ordinal only + pImpByName=(PIMAGE_IMPORT_BY_NAME)(mempe + + pOftThunk[j].u1.AddressOfData); + size_t addr = (size_t)pfnGetProcAddress( + (HMODULE)dllbase, pImpByName->Name); + addr = (size_t)winpe_memforwardexp((void*)dllbase, + addr-dllbase, pfnLoadLibraryA, pfnGetProcAddress); + if(!addr) continue; + pFtThunk[j].u1.Function = addr; + assert(addr == (size_t)GetProcAddress( + (HMODULE)dllbase, pImpByName->Name)); iat_count++; } } return iat_count; } -WINPEDEF WINPE_EXPORT -size_t winpe_memfindiat(void *mempe, +WINPEDEF WINPE_EXPORT +inline void* winpe_memfindiat(void *mempe, LPCSTR dllname, LPCSTR funcname) { PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)mempe; @@ -387,12 +597,12 @@ size_t winpe_memfindiat(void *mempe, PIMAGE_THUNK_DATA pFtThunk = NULL; PIMAGE_THUNK_DATA pOftThunk = NULL; LPCSTR pDllName = NULL; - PIMAGE_IMPORT_BY_NAME pFuncName = NULL; + PIMAGE_IMPORT_BY_NAME pImpByName = NULL; for (; pImpDescriptor->Name; pImpDescriptor++) { pDllName = (LPCSTR)(mempe + pImpDescriptor->Name); - if(dllname && _stricmp(pDllName, dllname)!=0) continue; + if(dllname && _inl_stricmp(pDllName, dllname)!=0) continue; pFtThunk = (PIMAGE_THUNK_DATA) (mempe + pImpDescriptor->FirstThunk); pOftThunk = (PIMAGE_THUNK_DATA) @@ -401,33 +611,120 @@ size_t winpe_memfindiat(void *mempe, for (int j=0; pFtThunk[j].u1.Function && pOftThunk[j].u1.Function; j++) { - if(sizeof(size_t) > 4) // x64 + pImpByName=(PIMAGE_IMPORT_BY_NAME)(mempe + + pOftThunk[j].u1.AddressOfData); + if((size_t)funcname < MAXWORD) // ordinary { - if((pOftThunk[j].u1.Ordinal >>63) != 0x1) // use name - { - pFuncName=(PIMAGE_IMPORT_BY_NAME)(mempe + - pOftThunk[j].u1.AddressOfData); - if(_stricmp(pFuncName->Name, funcname)==0) - return (size_t)&pFtThunk[j] - (size_t)mempe; - } + WORD funcord = LOWORD(funcname); + if(pImpByName->Hint == funcord) + return &pFtThunk[j]; } - else // x86 + else { - if((pOftThunk[j].u1.Ordinal >>31) != 0x1) // use name + if(_inl_stricmp(pImpByName->Name, funcname)==0) + return &pFtThunk[j]; + } + } + } + return 0; +} + +WINPEDEF WINPE_EXPORT +inline void* STDCALL winpe_memfindexp( + void *mempe, LPCSTR funcname) +{ + PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)mempe; + PIMAGE_NT_HEADERS pNtHeader = (PIMAGE_NT_HEADERS) + ((void*)mempe + pDosHeader->e_lfanew); + PIMAGE_FILE_HEADER pFileHeader = &pNtHeader->FileHeader; + PIMAGE_OPTIONAL_HEADER pOptHeader = &pNtHeader->OptionalHeader; + PIMAGE_DATA_DIRECTORY pDataDirectory = pOptHeader->DataDirectory; + PIMAGE_DATA_DIRECTORY pExpEntry = + &pDataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT]; + PIMAGE_EXPORT_DIRECTORY pExpDescriptor = + (PIMAGE_EXPORT_DIRECTORY)(mempe + pExpEntry->VirtualAddress); + + WORD *ordrva = mempe + pExpDescriptor->AddressOfNameOrdinals; + DWORD *namerva = mempe + pExpDescriptor->AddressOfNames; + DWORD *funcrva = mempe + pExpDescriptor->AddressOfFunctions; + if((size_t)funcname <= MAXWORD) // find by ordnial + { + WORD ordbase = LOWORD(pExpDescriptor->Base) - 1; + WORD funcord = LOWORD(funcname); + return (void*)(mempe + funcrva[ordrva[funcord-ordbase]]); + } + else + { + for(int i=0;iNumberOfNames;i++) + { + LPCSTR curname = (LPCSTR)(mempe+namerva[i]); + if(_inl_stricmp(curname, funcname)==0) + { + return (void*)(mempe + funcrva[ordrva[i]]); + } + } + } + return 0; +} + +WINPEDEF WINPE_EXPORT +inline void *winpe_memforwardexp( + void *mempe, size_t exprva, + PFN_LoadLibraryA pfnLoadLibraryA, + PFN_GetProcAddress pfnGetProcAddress) +{ + size_t dllbase = (size_t)mempe; + while (1) + { + PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)dllbase; + PIMAGE_NT_HEADERS pNtHeader = (PIMAGE_NT_HEADERS) + ((void*)dllbase + pDosHeader->e_lfanew); + PIMAGE_OPTIONAL_HEADER pOptHeader = &pNtHeader->OptionalHeader; + PIMAGE_DATA_DIRECTORY pDataDirectory = pOptHeader->DataDirectory; + PIMAGE_DATA_DIRECTORY pExpEntry = + &pDataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT]; + if(exprva>=pExpEntry->VirtualAddress && + exprva<= pExpEntry->VirtualAddress + pExpEntry->Size) + { + char namebuf[MAX_PATH]; + char *dllname = (char *)(dllbase + exprva); + char *funcname = dllname; + int i=0, j=0; + while(dllname[i]!=0) + { + if(dllname[i]=='.') + { + namebuf[j] = dllname[i]; + namebuf[++j] = 'd'; + namebuf[++j] = 'l'; + namebuf[++j] = 'l'; + namebuf[++j] = '\0'; + funcname = namebuf + j + 1; + } + else { - pFuncName=(PIMAGE_IMPORT_BY_NAME)(mempe + - pOftThunk[j].u1.AddressOfData); - if(_stricmp(pFuncName->Name, funcname)==0) - return (size_t)&pFtThunk[j] - (size_t)mempe; + namebuf[j]=dllname[i]; } + i++; + j++; } + namebuf[j] = '\0'; + dllname = namebuf; + dllbase = (size_t)pfnLoadLibraryA(dllname); + exprva = (size_t)pfnGetProcAddress((HMODULE)dllbase, funcname); + exprva -= dllbase; } + else + { + return (void*)(dllbase + exprva); + } } - return 0; + return NULL; } +// PE setting function WINPEDEF WINPE_EXPORT -void winpe_noaslr(void *pe) +inline void winpe_noaslr(void *pe) { PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)pe; PIMAGE_NT_HEADERS pNtHeader = (PIMAGE_NT_HEADERS) @@ -438,7 +735,7 @@ void winpe_noaslr(void *pe) } WINPEDEF WINPE_EXPORT -DWORD winpe_setoep(void *pe, DWORD newoeprva) +inline DWORD winpe_oepval(void *pe, DWORD newoeprva) { PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)pe; PIMAGE_NT_HEADERS pNtHeader = (PIMAGE_NT_HEADERS) @@ -450,8 +747,21 @@ DWORD winpe_setoep(void *pe, DWORD newoeprva) return orgoep; } +WINPEDEF WINPE_EXPORT +inline size_t winpe_imagebaseval(void *pe, size_t newimagebase) +{ + PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)pe; + PIMAGE_NT_HEADERS pNtHeader = (PIMAGE_NT_HEADERS) + ((void*)pe + pDosHeader->e_lfanew); + PIMAGE_FILE_HEADER pFileHeader = &pNtHeader->FileHeader; + PIMAGE_OPTIONAL_HEADER pOptHeader = &pNtHeader->OptionalHeader; + size_t imagebase = pOptHeader->ImageBase; + if(newimagebase) pOptHeader->ImageBase = newimagebase; + return imagebase; +} + WINPEDEF WINPE_EXPORT -size_t winpe_appendsecth(void *pe, +inline size_t winpe_appendsecth(void *pe, PIMAGE_SECTION_HEADER psecth) { PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)pe; @@ -484,7 +794,7 @@ size_t winpe_appendsecth(void *pe, // adjust the section and imagesize pFileHeader->NumberOfSections++; - memcpy(&pSectHeader[sectNum], psecth, sizeof(IMAGE_SECTION_HEADER)); + _inl_memcpy(&pSectHeader[sectNum], psecth, sizeof(IMAGE_SECTION_HEADER)); align = pOptHeader->SectionAlignment; addr = psecth->VirtualAddress + psecth->Misc.VirtualSize; if(addr % align) addr += align - addr%align;