diff --git a/DuckMemoryScan.sln b/DuckMemoryScan.sln new file mode 100644 index 0000000..d8cd4f8 --- /dev/null +++ b/DuckMemoryScan.sln @@ -0,0 +1,31 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.31005.135 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DuckMemoryScan", "DuckMemoryScan\DuckMemoryScan.vcxproj", "{932D1518-C5AD-4563-B947-C135307FD8FF}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {932D1518-C5AD-4563-B947-C135307FD8FF}.Debug|x64.ActiveCfg = Debug|x64 + {932D1518-C5AD-4563-B947-C135307FD8FF}.Debug|x64.Build.0 = Debug|x64 + {932D1518-C5AD-4563-B947-C135307FD8FF}.Debug|x86.ActiveCfg = Debug|Win32 + {932D1518-C5AD-4563-B947-C135307FD8FF}.Debug|x86.Build.0 = Debug|Win32 + {932D1518-C5AD-4563-B947-C135307FD8FF}.Release|x64.ActiveCfg = Release|x64 + {932D1518-C5AD-4563-B947-C135307FD8FF}.Release|x64.Build.0 = Release|x64 + {932D1518-C5AD-4563-B947-C135307FD8FF}.Release|x86.ActiveCfg = Release|Win32 + {932D1518-C5AD-4563-B947-C135307FD8FF}.Release|x86.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {0EAE959F-09DA-422E-972C-2714DF960CD1} + EndGlobalSection +EndGlobal diff --git a/DuckMemoryScan/CdigitalSig.cpp b/DuckMemoryScan/CdigitalSig.cpp new file mode 100644 index 0000000..f2bc5a6 --- /dev/null +++ b/DuckMemoryScan/CdigitalSig.cpp @@ -0,0 +1,321 @@ +#include "CdigitalSig.h" +CdigitalSig::CdigitalSig(LPCWSTR lpFileName) +{ + CheckFileTrust(lpFileName); +} +std::string CdigitalSig::GetDigitalSigString() +{ + return this->DigitalSigString; +} + +std::string CdigitalSig::GetMd5DigitalSigString() +{ + return this->Md5DigitalSigString; +} + +DWORD CdigitalSig::GetDigitalState() +{ + return this->dDigitalState; +} + + + +LONG CdigitalSig::GetSoftSign(PCWSTR v_pszFilePath, char* v_pszSign, int v_iBufSize) +{ + //жϲǷȷ + if (v_pszFilePath == NULL) return -1; + + HCERTSTORE hStore = NULL; + HCRYPTMSG hMsg = NULL; + PCCERT_CONTEXT pCertContext = NULL; + BOOL bResult; + DWORD dwEncoding, dwContentType, dwFormatType; + PCMSG_SIGNER_INFO pSignerInfo = NULL; + PCMSG_SIGNER_INFO pCounterSignerInfo = NULL; + DWORD dwSignerInfo; + CERT_INFO CertInfo; + SYSTEMTIME st; + LONG lRet; + DWORD dwDataSize = 0; + + char chTemp[MAX_PATH] = { 0 }; + + do + { + + //ǩļлȡ洢 + bResult = CryptQueryObject( + CERT_QUERY_OBJECT_FILE, //ָʾҪѯĶ + v_pszFilePath, + CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED_EMBED, + CERT_QUERY_FORMAT_FLAG_BINARY, + 0, + &dwEncoding, + &dwContentType, + &dwFormatType, + &hStore, + &hMsg, + NULL + ); + + if (!bResult) + { + lRet = -1; + break; + } + //ȡǩϢĻС + bResult = CryptMsgGetParam( + hMsg, + CMSG_SIGNER_INFO_PARAM, + 0, + NULL, + &dwSignerInfo + ); + if (!bResult) + { + lRet = -1; + break; + } + + //仺 + pSignerInfo = (PCMSG_SIGNER_INFO)LocalAlloc(LPTR, dwSignerInfo); + if (pSignerInfo == NULL) + { + lRet = -1; + break; + } + + + //ȡǩϢ + bResult = CryptMsgGetParam( + hMsg, + CMSG_SIGNER_INFO_PARAM, + 0, + pSignerInfo, + &dwSignerInfo + ); + if (!bResult) + { + lRet = -1; + break; + } + + CertInfo.Issuer = pSignerInfo->Issuer; + CertInfo.SerialNumber = pSignerInfo->SerialNumber; + + pCertContext = CertFindCertificateInStore( + hStore, + CRYPT_ASN_ENCODING, + 0, + CERT_FIND_SUBJECT_CERT, + (PVOID)&CertInfo, + NULL + ); + if (pCertContext == NULL) + { + lRet = -1; + break; + } + + + //ȡּ + //ûиô˵ֻҪȡҪij + if (v_pszSign == NULL) + { + dwDataSize = CertGetNameString( + pCertContext, + CERT_NAME_SIMPLE_DISPLAY_TYPE, + 0, + NULL, + NULL, + 0 + ); + if (dwDataSize != 0) + { + lRet = dwDataSize; + } + else + { + lRet = -1; + } + + break; + } + + if (!(CertGetNameStringA( + pCertContext, + CERT_NAME_SIMPLE_DISPLAY_TYPE, + 0, + NULL, + v_pszSign, + v_iBufSize + ) + ) + ) + { + + lRet = -1; + break; + } + lRet = 0; + + } while (FALSE); + + if (pSignerInfo != NULL) + { + LocalFree((HLOCAL)pSignerInfo); + } + if (hStore != NULL) + CertCloseStore(hStore, 0); + if (hMsg != NULL) + CryptMsgClose(hMsg); + if (pCertContext != NULL) + CertFreeCertificateContext(pCertContext); + return lRet; +} + + +void CdigitalSig::CheckFileTrust(LPCWSTR lpFileName) //md5md5ascii +{ + + WINTRUST_DATA wd = { 0 }; + WINTRUST_FILE_INFO wfi = { 0 }; + WINTRUST_CATALOG_INFO wci = { 0 }; + CATALOG_INFO ci = { 0 }; + + HCATADMIN hCatAdmin = NULL; + if (!CryptCATAdminAcquireContext(&hCatAdmin, NULL, 0)) + { + return; + } + + HANDLE hFile = CreateFileW(lpFileName, GENERIC_READ, FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, + NULL, OPEN_EXISTING, 0, NULL); + if (INVALID_HANDLE_VALUE == hFile) + { + CryptCATAdminReleaseContext(hCatAdmin, 0); + return; + } + + DWORD dwCnt = 100; + BYTE byHash[100]; + CryptCATAdminCalcHashFromFileHandle(hFile, &dwCnt, byHash, 0); + CloseHandle(hFile); + + LPWSTR pszMemberTag = new WCHAR[dwCnt * 2 + 1]; + for (DWORD dw = 0; dw < dwCnt; ++dw) + { + wsprintfW(&pszMemberTag[dw * 2], L"%02X", byHash[dw]); + } + + HCATINFO hCatInfo = CryptCATAdminEnumCatalogFromHash(hCatAdmin, byHash, dwCnt, 0, NULL); + + GUID action = WINTRUST_ACTION_GENERIC_VERIFY_V2; + HRESULT lStatus = WinVerifyTrust(NULL, &action, &wd); + DWORD dwLastError = GetLastError(); + switch (lStatus) + { + case ERROR_SUCCESS: + /* + Signed file: + - Hash that represents the subject is trusted. + - Trusted publisher without any verification errors. + - UI was disabled in dwUIChoice. No publisher or + time stamp chain errors. + - UI was enabled in dwUIChoice and the user clicked + "Yes" when asked to install and run the signed + subject. + */ + /*wprintf_s(L"The file \"%s\" is signed and the signature " + L"was verified.\n", + pwszSourceFile);*/ + this->dDigitalState = DIGITAL_SIGSTATE_VALID; + break; + + case TRUST_E_NOSIGNATURE: + // The file was not signed or had a signature + // that was not valid. + + // Get the reason for no signature. + + if (TRUST_E_NOSIGNATURE == dwLastError || + TRUST_E_SUBJECT_FORM_UNKNOWN == dwLastError || + TRUST_E_PROVIDER_UNKNOWN == dwLastError) + { + // The file was not signed. + /*wprintf_s(L"The file \"%s\" is not signed.\n", + pwszSourceFile);*/ + this->dDigitalState = DIGITAL_SIGSTATE_OTHER; + } + else + { + // The signature was not valid or there was an error + // opening the file. + /*wprintf_s(L"An unknown error occurred trying to " + L"verify the signature of the \"%s\" file.\n", + pwszSourceFile);*/ + this->dDigitalState = DIGITAL_SIGSTATE_OTHER; + } + + break; + + case TRUST_E_EXPLICIT_DISTRUST: + // The hash that represents the subject or the publisher + // is not allowed by the admin or user. + /*wprintf_s(L"The signature is present, but specifically " + L"disallowed.\n");*/ + this->dDigitalState = DIGITAL_SIGSTATE_OTHER; + break; + + case TRUST_E_SUBJECT_NOT_TRUSTED: + // The user clicked "No" when asked to install and run. + /*wprintf_s(L"The signature is present, but not " + L"trusted.\n");*/ + this->dDigitalState = DIGITAL_SIGSTATE_OTHER; + break; + + case CRYPT_E_SECURITY_SETTINGS: + /* + The hash that represents the subject or the publisher + was not explicitly trusted by the admin and the + admin policy has disabled user trust. No signature, + publisher or time stamp errors. + */ + /*wprintf_s(L"CRYPT_E_SECURITY_SETTINGS - The hash " + L"representing the subject or the publisher wasn't " + L"explicitly trusted by the admin and admin policy " + L"has disabled user trust. No signature, publisher " + L"or timestamp errors.\n");*/ + this->dDigitalState = DIGITAL_SIGSTATE_OTHER; + break; + + default: + // The UI was disabled in dwUIChoice or the admin policy + // has disabled user trust. lStatus contains the + // publisher or time stamp chain error. + if (dwLastError == 0x800b0101) // + { + this->dDigitalState = DIGITAL_SIGSTATE_EXPIRE; + } + else if (dwLastError == 0x800b010c) { // + this->dDigitalState = DIGITAL_SIGSTATE_REVOKED; + } + else if (dwLastError == 0x80096010) { //֤ + this->dDigitalState = DIGITAL_SIGSTATE_VALID; + } + else { + this->dDigitalState = DIGITAL_SIGSTATE_OTHER; + //wprintf_s(L"Error is: 0x%x.\n",lStatus); + } + + break; + } + if (NULL != hCatInfo) + { + CryptCATAdminReleaseCatalogContext(hCatAdmin, hCatInfo, 0); + } + CryptCATAdminReleaseContext(hCatAdmin, 0); + + delete[] pszMemberTag; + return; +} \ No newline at end of file diff --git a/DuckMemoryScan/CdigitalSig.h b/DuckMemoryScan/CdigitalSig.h new file mode 100644 index 0000000..8d09c8f --- /dev/null +++ b/DuckMemoryScan/CdigitalSig.h @@ -0,0 +1,41 @@ +#pragma once +#include +#include +#include +#include +#include +#include +#include +#include +#include +#pragma comment (lib, "wintrust") +#pragma comment (lib, "crypt32.lib") + +static GUID WINTRUST_ACTION_GENERIC_VERIFY_V2 = {0xaac56b, 0xcd44, 0x11d0, 0x8c, 0xc2, 0x0, 0xc0, 0x4f, 0xc2, 0x95, 0xee}; +enum SignState +{ + DIGITAL_SIGSTATE_CANNOTGET = 0, + DIGITAL_SIGSTATE_VALID = 1, + DIGITAL_SIGSTATE_EXPIRE = 2, //µ½ÆÚ + DIGITAL_SIGSTATE_REVOKED = 3, //È¡Ïû + DIGITAL_SIGSTATE_OTHER = 4 +}; + +class CdigitalSig +{ +private: + std::string DigitalSigString; + std::string Md5DigitalSigString; + DWORD dDigitalState = DIGITAL_SIGSTATE_CANNOTGET; + +public: + std::string GetDigitalSigString(); + std::string GetMd5DigitalSigString(); + DWORD GetDigitalState(); + CdigitalSig(LPCWSTR lpFileName); + + +private: + LONG GetSoftSign(PCWSTR v_pszFilePath, char* v_pszSign, int v_iBufSize); + void CheckFileTrust(LPCWSTR lpFileName); +}; \ No newline at end of file diff --git a/DuckMemoryScan/DuckMemoryScan.vcxproj b/DuckMemoryScan/DuckMemoryScan.vcxproj new file mode 100644 index 0000000..728742a --- /dev/null +++ b/DuckMemoryScan/DuckMemoryScan.vcxproj @@ -0,0 +1,153 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + 16.0 + Win32Proj + {932d1518-c5ad-4563-b947-c135307fd8ff} + DuckMemoryScan + 10.0 + + + + Application + true + v142 + Unicode + + + Application + false + v142 + true + Unicode + + + Application + true + v142 + Unicode + + + Application + false + v142 + true + Unicode + + + + + + + + + + + + + + + + + + + + + true + + + false + + + true + + + false + + + + Level3 + true + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + + + + + Level3 + true + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + true + true + + + + + Level3 + true + _DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + + + + + Level3 + true + false + true + NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + Disabled + + + Console + true + true + true + RequireAdministrator + + + + + + + + + + + + + \ No newline at end of file diff --git a/DuckMemoryScan/DuckMemoryScan.vcxproj.filters b/DuckMemoryScan/DuckMemoryScan.vcxproj.filters new file mode 100644 index 0000000..a488aab --- /dev/null +++ b/DuckMemoryScan/DuckMemoryScan.vcxproj.filters @@ -0,0 +1,30 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + 资源文件 + + + 资源文件 + + + + + 资源文件 + + + \ No newline at end of file diff --git a/DuckMemoryScan/main.cpp b/DuckMemoryScan/main.cpp new file mode 100644 index 0000000..6e7a0aa --- /dev/null +++ b/DuckMemoryScan/main.cpp @@ -0,0 +1,380 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#pragma comment(lib,"dbghelp.lib") +#include "tlhelp32.h" +#include "CdigitalSig.h" +BOOL Is64BitPorcess(HANDLE hProcess) +{ + BOOL bIsWow64 = false; + IsWow64Process(hProcess, &bIsWow64); + return bIsWow64 == false; +} +BOOL EnableDebugPrivilege(BOOL bEnable) +{ + //Enabling the debug privilege allows the application to see + //information about service application + BOOL fOK = FALSE; //Assume function fails + HANDLE hToken; + //Try to open this process's acess token + if (OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hToken)) + { + //Attempt to modify the "Debug" privilege + TOKEN_PRIVILEGES tp; + tp.PrivilegeCount = 1; + LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &tp.Privileges[0].Luid); + tp.Privileges[0].Attributes = bEnable ? SE_PRIVILEGE_ENABLED : 0; + AdjustTokenPrivileges(hToken, FALSE, &tp, sizeof(tp), NULL, NULL); + fOK = (GetLastError() == ERROR_SUCCESS); + CloseHandle(hToken); + } + return fOK; +} + +void WCharToChar(const WCHAR* tchar, char* _char) +{ + int iLength; + iLength = WideCharToMultiByte(CP_ACP, 0, tchar, -1, NULL, 0, NULL, NULL); + WideCharToMultiByte(CP_ACP, 0, tchar, -1, _char, iLength, NULL, NULL); +} +void CharToWchar(const char* _char, WCHAR* tchar) +{ + int iLength; + iLength = MultiByteToWideChar(CP_ACP, 0, _char, strlen(_char) + 1, NULL, 0); + MultiByteToWideChar(CP_ACP, 0, _char, strlen(_char) + 1, tchar, iLength); +} +BOOL DosPathToNtPath(WCHAR* pszDosPath, LPTSTR pszNtPath) +{ + TCHAR szDriveStr[500]; + TCHAR szDrive[3]; + TCHAR szDevName[100]; + INT cchDevName; + INT i; + + // + if (!pszDosPath || !pszNtPath) + return FALSE; + + //ȡشַ + if (GetLogicalDriveStrings(sizeof(szDriveStr), szDriveStr)) + { + for (i = 0; szDriveStr[i]; i += 4) + { + if (!lstrcmpi(&(szDriveStr[i]), L"A:\\") || !lstrcmpi(&(szDriveStr[i]), L"B:\\")) + continue; + + szDrive[0] = szDriveStr[i]; + szDrive[1] = szDriveStr[i + 1]; + szDrive[2] = '\0'; + if (!QueryDosDevice(szDrive, szDevName, 100))//ѯ Dos 豸 + return FALSE; + + cchDevName = lstrlen(szDevName); + if (_wcsnicmp(pszDosPath, szDevName, cchDevName) == 0)// + { + lstrcpy(pszNtPath, szDrive);// + lstrcat(pszNtPath, pszDosPath + cchDevName);//· + + return TRUE; + } + } + } + + lstrcpy(pszNtPath, pszDosPath); + + return FALSE; +} +DWORD64 GetProcessMoudleHandle(DWORD pid) { + MODULEENTRY32 moduleEntry; + HANDLE handle = NULL; + handle = ::CreateToolhelp32Snapshot(0x00000008, pid); + ZeroMemory(&moduleEntry, sizeof(MODULEENTRY32)); + moduleEntry.dwSize = sizeof(MODULEENTRY32); + if (!Module32First(handle, &moduleEntry)) { + CloseHandle(handle); + return NULL; + } + do { + CloseHandle(handle); + return (DWORD64)moduleEntry.hModule; + } while (Module32Next(handle, &moduleEntry)); + return 0; +} +bool CheckThreadAddressIsExcute(DWORD64 pAddress,HANDLE pHandle, HANDLE pID, HANDLE Tid) { + + DWORD64 ReadNum = 0; + MEMORY_BASIC_INFORMATION mbi = { 0 }; + + if (VirtualQueryEx(pHandle, (LPCVOID)pAddress, &mbi, sizeof(mbi))) + { + if (mbi.AllocationBase) { + if (mbi.Type != MEM_IMAGE) { + if (mbi.AllocationProtect & PAGE_EXECUTE || + mbi.AllocationProtect & PAGE_EXECUTE_READ || + mbi.AllocationProtect & PAGE_EXECUTE_READWRITE || + mbi.AllocationProtect & PAGE_EXECUTE_WRITECOPY) + { + printf("\t => [̶߳ջ] ⵽δ֪ڴ[VirtualAllocɱ?] ַ %p PID %d TID %d \n", pAddress, pID, Tid); + char PEStack[0x2]; + if (ReadProcessMemory(pHandle, mbi.BaseAddress, PEStack, sizeof(PEStack), &ReadNum)) { + if (PEStack[0] == 'M' && PEStack[1] == 'Z') { + printf("\t => [!!!̶߳ջ!!!] ⵽ڴس ̵ַ߳ %p PID %d TID %d ڴģַ: %p\n", pAddress, pID, Tid, mbi.BaseAddress); + } + } + return true; + } + } + } + } + return false; +} +void ThreadStackWalk() { + HANDLE hThreadSnap = INVALID_HANDLE_VALUE; + THREADENTRY32 te32; + DWORD ExitCode = 0; + hThreadSnap = CreateToolhelp32Snapshot(0x00000004, GetCurrentProcessId()); + if (hThreadSnap) + { + te32.dwSize = sizeof(THREADENTRY32); + if (!Thread32First(hThreadSnap, &te32)) + { + CloseHandle(hThreadSnap); + return; + } + do + { + if (te32.th32OwnerProcessID != GetCurrentProcessId() && te32.th32ThreadID != GetCurrentThreadId()) + { + HANDLE hThread = OpenThread(THREAD_ALL_ACCESS, 0, te32.th32ThreadID); + if (hThread && hThread != (HANDLE)-1) + { + HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, false, te32.th32OwnerProcessID); + if (hProcess) { + STACKFRAME_EX StackFarmeEx; + memset(&StackFarmeEx, 0, sizeof(STACKFRAME_EX)); + if (Is64BitPorcess(hProcess)) { + CONTEXT context = { 0 }; + context.ContextFlags = CONTEXT_ALL; + if (GetThreadContext(hThread, &context)) + { + if (context.Dr0 != 0 || context.Dr1 != 0 || context.Dr2 != 0 || context.Dr3 != 0) + { + //hwbp hook + printf("\t => [̶߳ջ] ⵽HWBP Hook PID %d TID %d \n", te32.th32OwnerProcessID, te32.th32ThreadID); + } + CheckThreadAddressIsExcute(context.Rip, hProcess, (HANDLE)te32.th32OwnerProcessID, (HANDLE)te32.th32ThreadID); + StackFarmeEx.AddrPC.Offset = context.Rip; + StackFarmeEx.AddrPC.Mode = AddrModeFlat; + StackFarmeEx.AddrStack.Offset = context.Rsp; + StackFarmeEx.AddrStack.Mode = AddrModeFlat; + StackFarmeEx.AddrFrame.Offset = context.Rsp; + StackFarmeEx.AddrFrame.Mode = AddrModeFlat; + DWORD machineType = IMAGE_FILE_MACHINE_AMD64; + while (true) + { + if (!StackWalkEx(machineType, hProcess, hThread, &StackFarmeEx, &context, NULL, NULL, NULL, NULL, NULL)) + break; + if (StackFarmeEx.AddrFrame.Offset == 0) + break; + CheckThreadAddressIsExcute(StackFarmeEx.AddrPC.Offset, hProcess, (HANDLE)te32.th32OwnerProcessID, (HANDLE)te32.th32ThreadID); + } + } + } else { + WOW64_CONTEXT context = { 0 }; + context.ContextFlags = CONTEXT_ALL; + if (Wow64GetThreadContext(hThread, &context)) + { + if (context.Dr0 != 0 || context.Dr1 != 0 || context.Dr2 != 0 || context.Dr3 != 0) + { + //hwbp hook + printf("\t => [̶߳ջ] ⵽HWBP Hook PID %d TID %d \n", te32.th32OwnerProcessID, te32.th32ThreadID); + } + + CheckThreadAddressIsExcute(context.Eip, hProcess, (HANDLE)te32.th32OwnerProcessID, (HANDLE)te32.th32ThreadID); + StackFarmeEx.AddrPC.Offset = context.Eip; + StackFarmeEx.AddrPC.Mode = AddrModeFlat; + StackFarmeEx.AddrStack.Offset = context.Esp; + StackFarmeEx.AddrStack.Mode = AddrModeFlat; + StackFarmeEx.AddrFrame.Offset = context.Ebp; + StackFarmeEx.AddrFrame.Mode = AddrModeFlat; + DWORD machineType = IMAGE_FILE_MACHINE_I386;//IMAGE_FILE_MACHINE_I386; IMAGE_FILE_MACHINE_AMD64; + while (true) + { + if (!StackWalkEx(machineType, hProcess, hThread, &StackFarmeEx, NULL, NULL, NULL, NULL, NULL, NULL)) + break; + if (StackFarmeEx.AddrFrame.Offset == 0) + break; + CheckThreadAddressIsExcute(StackFarmeEx.AddrPC.Offset, hProcess, (HANDLE)te32.th32OwnerProcessID, (HANDLE)te32.th32ThreadID); + } + } + } + CloseHandle(hProcess); + } + CloseHandle(hThread); + } + } + + } while (Thread32Next(hThreadSnap, &te32)); + CloseHandle(hThreadSnap); + } +} +void WalkProcessMoudle(DWORD pID,HANDLE pHandle,WCHAR* pMoudleName) { + + MODULEENTRY32 moduleEntry; + HANDLE handle = NULL; + handle = ::CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, pID); + ZeroMemory(&moduleEntry, sizeof(MODULEENTRY32)); + moduleEntry.dwSize = sizeof(MODULEENTRY32); + char* AllocBuff = (char*)VirtualAlloc(NULL, 0x200, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); + if (AllocBuff) { + if (!Module32First(handle, &moduleEntry)) { + CloseHandle(handle); + return; + } + do { + DWORD64 ReadNum = 0; + if (ReadProcessMemory(pHandle, moduleEntry.modBaseAddr, AllocBuff, 0x200, &ReadNum)) { + if (AllocBuff[0] == 'M' && AllocBuff[1] == 'Z') { + PIMAGE_DOS_HEADER CopyDosHead = (PIMAGE_DOS_HEADER)AllocBuff; + PIMAGE_NT_HEADERS CopyNthead = (PIMAGE_NT_HEADERS)((LPBYTE)AllocBuff + CopyDosHead->e_lfanew); + /* + DWORD64 BaseOfCode = 0; + DWORD64 SizeOfCode = 0; + if (CopyNthead->FileHeader.Machine == IMAGE_FILE_MACHINE_AMD64) { + PIMAGE_NT_HEADERS64 CopyNthead64 = (PIMAGE_NT_HEADERS64)CopyNthead; + BaseOfCode = CopyNthead64->OptionalHeader.BaseOfCode; + SizeOfCode = CopyNthead64->OptionalHeader.SizeOfCode; + } + else { + PIMAGE_NT_HEADERS32 CopyNthead32 = (PIMAGE_NT_HEADERS32)CopyNthead; + BaseOfCode = CopyNthead32->OptionalHeader.BaseOfCode; + SizeOfCode = CopyNthead32->OptionalHeader.SizeOfCode; + } + */ + PIMAGE_SECTION_HEADER SectionHeader = (PIMAGE_SECTION_HEADER)((PUCHAR)CopyNthead + sizeof(CopyNthead->Signature) + sizeof(CopyNthead->FileHeader) + CopyNthead->FileHeader.SizeOfOptionalHeader); + int FoundNum = 0; + for (WORD i = 0; i < CopyNthead->FileHeader.NumberOfSections; i++) + { + if (SectionHeader[i].Characteristics & IMAGE_SCN_MEM_EXECUTE) { + FoundNum++; + } + if (FoundNum > 1) { + printf("\t => [̼] ⵽Ŀִ(.rdataɱ or ӿdz) %ws id %d ģ %ws %s \n", pMoudleName, moduleEntry.szExePath, pID, SectionHeader[i].Name); + break; + } + } + } + } + + } while (Module32Next(handle, &moduleEntry)); + VirtualFree(AllocBuff, 0, MEM_RELEASE); + } + CloseHandle(handle); +} +void ProcessStackWalk() { + PROCESSENTRY32 pe32; + pe32.dwSize = sizeof(pe32); + HANDLE hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); + if (hProcessSnap == INVALID_HANDLE_VALUE) + { + printf("CreateToolhelp32Snapshot error.\n"); + return; + } + BOOL bProcess = Process32First(hProcessSnap, &pe32); + while (bProcess) + { + //ӡͽID + HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, false, pe32.th32ProcessID); + if (hProcess) { + WalkProcessMoudle(pe32.th32ProcessID, hProcess, pe32.szExeFile); + WCHAR szImagePath[MAX_PATH]; + WCHAR pszFullPath[MAX_PATH]; + if (GetProcessImageFileName(hProcess, szImagePath, MAX_PATH)) + { + if (DosPathToNtPath(szImagePath, pszFullPath)) + { + CdigitalSig DigitalSig(pszFullPath); + DWORD dDigitalState = DigitalSig.GetDigitalState(); + if (dDigitalState == DIGITAL_SIGSTATE_REVOKED || dDigitalState == DIGITAL_SIGSTATE_EXPIRE) { + printf("\t => [ɨ] ⵽ǩ · %ws static %d \n", pszFullPath, dDigitalState); + } + } + } + CloseHandle(hProcess); + } + bProcess = Process32Next(hProcessSnap, &pe32); + } + CloseHandle(hProcessSnap); + return; + +} +void ScanSystemDrivers() { + DWORD cbNeeded = 0; // drivers[] صֽ + LPVOID drivers[MAX_PATH] = { 0 }; // ַб + int cDrivers = 0; // + Wow64EnableWow64FsRedirection(0); + if (EnumDeviceDrivers(drivers, sizeof(drivers), &cbNeeded) && cbNeeded < sizeof(drivers)) // EnumDeviceDrivers ÿļļصַ + { + char szDriver[MAX_PATH] = { 0 }; // ļ + char szPath[MAX_PATH] = { 0 }; // ļȫ· + char szNtPath[MAX_PATH] = { 0 }; + char szSystemPath[MAX_PATH] = { 0 }; // system32 ļ· + cDrivers = cbNeeded / sizeof(LPVOID); // + + for (int i = 0; i < cDrivers; i++) + { + if (drivers[i]) { + if (GetDeviceDriverBaseNameA(drivers[i], szDriver, sizeof(szDriver) / sizeof(LPVOID))) + { + if (GetDeviceDriverFileNameA(drivers[i], szPath, sizeof(szPath))) { + bool isSystemDriver = true; + //ֻжϷϵͳ + if (szPath[1] == '?') + { + isSystemDriver = false; + int len = strlen(szPath); + szPath[len + 1] = '\0'; + for (int j = 0; j < len; j++) + { + szPath[j] = szPath[j + 4]; + } + WCHAR UnicodeFilePath[MAX_PATH << 1] = { 0 }; + CharToWchar(szPath, UnicodeFilePath); + CdigitalSig DigitalSig(UnicodeFilePath); + DWORD dDigitalState = DigitalSig.GetDigitalState(); + if (dDigitalState != DIGITAL_SIGSTATE_VALID) { + printf("\t => [ɨ] ⵽δ֪ · %ws \n", UnicodeFilePath); + } + } + } + } + } + } + } + Wow64EnableWow64FsRedirection(1); +} +int main() +{ + printf("DuckMemoryScan By huoji 2021-02-23 \n"); + if (EnableDebugPrivilege(true) == false) { + printf("Ȩʧ,ԹԱ \n"); + system("pause"); + return 0; + } + printf("̶߳ջݼ ... \n"); + ThreadStackWalk(); + printf("... \n"); + ScanSystemDrivers(); + printf("̼... \n"); + ProcessStackWalk(); + printf(" ... \n"); + system("pause"); + return 0; +} \ No newline at end of file diff --git a/enc_temp_folder/e27b8a5668995a66c9342927ce26b149/main.cpp b/enc_temp_folder/e27b8a5668995a66c9342927ce26b149/main.cpp new file mode 100644 index 0000000..900d1d1 --- /dev/null +++ b/enc_temp_folder/e27b8a5668995a66c9342927ce26b149/main.cpp @@ -0,0 +1,380 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#pragma comment(lib,"dbghelp.lib") +#include "tlhelp32.h" +#include "CdigitalSig.h" +BOOL Is64BitPorcess(HANDLE hProcess) +{ + BOOL bIsWow64 = false; + IsWow64Process(hProcess, &bIsWow64); + return bIsWow64 == false; +} +BOOL EnableDebugPrivilege(BOOL bEnable) +{ + //Enabling the debug privilege allows the application to see + //information about service application + BOOL fOK = FALSE; //Assume function fails + HANDLE hToken; + //Try to open this process's acess token + if (OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hToken)) + { + //Attempt to modify the "Debug" privilege + TOKEN_PRIVILEGES tp; + tp.PrivilegeCount = 1; + LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &tp.Privileges[0].Luid); + tp.Privileges[0].Attributes = bEnable ? SE_PRIVILEGE_ENABLED : 0; + AdjustTokenPrivileges(hToken, FALSE, &tp, sizeof(tp), NULL, NULL); + fOK = (GetLastError() == ERROR_SUCCESS); + CloseHandle(hToken); + } + return fOK; +} + +void WCharToChar(const WCHAR* tchar, char* _char) +{ + int iLength; + iLength = WideCharToMultiByte(CP_ACP, 0, tchar, -1, NULL, 0, NULL, NULL); + WideCharToMultiByte(CP_ACP, 0, tchar, -1, _char, iLength, NULL, NULL); +} +void CharToWchar(const char* _char, WCHAR* tchar) +{ + int iLength; + iLength = MultiByteToWideChar(CP_ACP, 0, _char, strlen(_char) + 1, NULL, 0); + MultiByteToWideChar(CP_ACP, 0, _char, strlen(_char) + 1, tchar, iLength); +} +BOOL DosPathToNtPath(WCHAR* pszDosPath, LPTSTR pszNtPath) +{ + TCHAR szDriveStr[500]; + TCHAR szDrive[3]; + TCHAR szDevName[100]; + INT cchDevName; + INT i; + + // + if (!pszDosPath || !pszNtPath) + return FALSE; + + //ȡشַ + if (GetLogicalDriveStrings(sizeof(szDriveStr), szDriveStr)) + { + for (i = 0; szDriveStr[i]; i += 4) + { + if (!lstrcmpi(&(szDriveStr[i]), L"A:\\") || !lstrcmpi(&(szDriveStr[i]), L"B:\\")) + continue; + + szDrive[0] = szDriveStr[i]; + szDrive[1] = szDriveStr[i + 1]; + szDrive[2] = '\0'; + if (!QueryDosDevice(szDrive, szDevName, 100))//ѯ Dos 豸 + return FALSE; + + cchDevName = lstrlen(szDevName); + if (_wcsnicmp(pszDosPath, szDevName, cchDevName) == 0)// + { + lstrcpy(pszNtPath, szDrive);// + lstrcat(pszNtPath, pszDosPath + cchDevName);//· + + return TRUE; + } + } + } + + lstrcpy(pszNtPath, pszDosPath); + + return FALSE; +} +DWORD64 GetProcessMoudleHandle(DWORD pid) { + MODULEENTRY32 moduleEntry; + HANDLE handle = NULL; + handle = ::CreateToolhelp32Snapshot(0x00000008, pid); + ZeroMemory(&moduleEntry, sizeof(MODULEENTRY32)); + moduleEntry.dwSize = sizeof(MODULEENTRY32); + if (!Module32First(handle, &moduleEntry)) { + CloseHandle(handle); + return NULL; + } + do { + CloseHandle(handle); + return (DWORD64)moduleEntry.hModule; + } while (Module32Next(handle, &moduleEntry)); + return 0; +} +bool CheckThreadAddressIsExcute(DWORD64 pAddress,HANDLE pHandle, HANDLE pID, HANDLE Tid) { + + DWORD64 ReadNum = 0; + MEMORY_BASIC_INFORMATION mbi = { 0 }; + + if (VirtualQueryEx(pHandle, (LPCVOID)pAddress, &mbi, sizeof(mbi))) + { + if (mbi.AllocationBase) { + if (mbi.Type != MEM_IMAGE) { + if (mbi.AllocationProtect & PAGE_EXECUTE || + mbi.AllocationProtect & PAGE_EXECUTE_READ || + mbi.AllocationProtect & PAGE_EXECUTE_READWRITE || + mbi.AllocationProtect & PAGE_EXECUTE_WRITECOPY) + { + printf("\t => [̶߳ջ] ⵽δ֪ڴ[VirtualAllocɱ?] ַ %p PID %d TID %d \n", pAddress, pID, Tid); + char PEStack[0x2]; + if (ReadProcessMemory(pHandle, mbi.BaseAddress, PEStack, sizeof(PEStack), &ReadNum)) { + if (PEStack[0] == 'M' && PEStack[1] == 'Z') { + printf("\t => [!!!̶߳ջ!!!] ⵽ڴس ̵ַ߳ %p PID %d TID %d ڴģַ: %p\n", pAddress, pID, Tid, mbi.BaseAddress); + } + } + return true; + } + } + } + } + return false; +} +void ThreadStackWalk() { + HANDLE hThreadSnap = INVALID_HANDLE_VALUE; + THREADENTRY32 te32; + DWORD ExitCode = 0; + hThreadSnap = CreateToolhelp32Snapshot(0x00000004, GetCurrentProcessId()); + if (hThreadSnap) + { + te32.dwSize = sizeof(THREADENTRY32); + if (!Thread32First(hThreadSnap, &te32)) + { + CloseHandle(hThreadSnap); + return; + } + do + { + if (te32.th32OwnerProcessID != GetCurrentProcessId() && te32.th32ThreadID != GetCurrentThreadId()) + { + HANDLE hThread = OpenThread(THREAD_ALL_ACCESS, 0, te32.th32ThreadID); + if (hThread && hThread != (HANDLE)-1) + { + HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, false, te32.th32OwnerProcessID); + if (hProcess) { + STACKFRAME_EX StackFarmeEx; + memset(&StackFarmeEx, 0, sizeof(STACKFRAME_EX)); + if (Is64BitPorcess(hProcess)) { + CONTEXT context = { 0 }; + context.ContextFlags = CONTEXT_ALL; + if (GetThreadContext(hThread, &context)) + { + if (context.Dr0 != 0 || context.Dr1 != 0 || context.Dr2 != 0 || context.Dr3 != 0) + { + //hwbp hook + printf("\t => [̶߳ջ] ⵽HWBP Hook PID %d TID %d \n", te32.th32OwnerProcessID, te32.th32ThreadID); + } + CheckThreadAddressIsExcute(context.Rip, hProcess, (HANDLE)te32.th32OwnerProcessID, (HANDLE)te32.th32ThreadID); + StackFarmeEx.AddrPC.Offset = context.Rip; + StackFarmeEx.AddrPC.Mode = AddrModeFlat; + StackFarmeEx.AddrStack.Offset = context.Rsp; + StackFarmeEx.AddrStack.Mode = AddrModeFlat; + StackFarmeEx.AddrFrame.Offset = context.Rsp; + StackFarmeEx.AddrFrame.Mode = AddrModeFlat; + DWORD machineType = IMAGE_FILE_MACHINE_AMD64; + while (true) + { + if (!StackWalkEx(machineType, hProcess, hThread, &StackFarmeEx, &context, NULL, NULL, NULL, NULL, NULL)) + break; + if (StackFarmeEx.AddrFrame.Offset == 0) + break; + CheckThreadAddressIsExcute(StackFarmeEx.AddrPC.Offset, hProcess, (HANDLE)te32.th32OwnerProcessID, (HANDLE)te32.th32ThreadID); + } + } + } else { + WOW64_CONTEXT context = { 0 }; + context.ContextFlags = CONTEXT_ALL; + if (Wow64GetThreadContext(hThread, &context)) + { + if (context.Dr0 != 0 || context.Dr1 != 0 || context.Dr2 != 0 || context.Dr3 != 0) + { + //hwbp hook + printf("\t => [̶߳ջ] ⵽HWBP Hook PID %d TID %d \n", te32.th32OwnerProcessID, te32.th32ThreadID); + } + + CheckThreadAddressIsExcute(context.Eip, hProcess, (HANDLE)te32.th32OwnerProcessID, (HANDLE)te32.th32ThreadID); + StackFarmeEx.AddrPC.Offset = context.Eip; + StackFarmeEx.AddrPC.Mode = AddrModeFlat; + StackFarmeEx.AddrStack.Offset = context.Esp; + StackFarmeEx.AddrStack.Mode = AddrModeFlat; + StackFarmeEx.AddrFrame.Offset = context.Ebp; + StackFarmeEx.AddrFrame.Mode = AddrModeFlat; + DWORD machineType = IMAGE_FILE_MACHINE_I386;//IMAGE_FILE_MACHINE_I386; IMAGE_FILE_MACHINE_AMD64; + while (true) + { + if (!StackWalkEx(machineType, hProcess, hThread, &StackFarmeEx, NULL, NULL, NULL, NULL, NULL, NULL)) + break; + if (StackFarmeEx.AddrFrame.Offset == 0) + break; + CheckThreadAddressIsExcute(StackFarmeEx.AddrPC.Offset, hProcess, (HANDLE)te32.th32OwnerProcessID, (HANDLE)te32.th32ThreadID); + } + } + } + CloseHandle(hProcess); + } + CloseHandle(hThread); + } + } + + } while (Thread32Next(hThreadSnap, &te32)); + CloseHandle(hThreadSnap); + } +} +void WalkProcessMoudle(DWORD pID,HANDLE pHandle,WCHAR* pMoudleName) { + + MODULEENTRY32 moduleEntry; + HANDLE handle = NULL; + handle = ::CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, pID); + ZeroMemory(&moduleEntry, sizeof(MODULEENTRY32)); + moduleEntry.dwSize = sizeof(MODULEENTRY32); + char* AllocBuff = (char*)VirtualAlloc(NULL, 0x200, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); + if (AllocBuff) { + if (!Module32First(handle, &moduleEntry)) { + CloseHandle(handle); + return; + } + do { + DWORD64 ReadNum = 0; + if (ReadProcessMemory(pHandle, moduleEntry.modBaseAddr, AllocBuff, 0x200, &ReadNum)) { + if (AllocBuff[0] == 'M' && AllocBuff[1] == 'Z') { + PIMAGE_DOS_HEADER CopyDosHead = (PIMAGE_DOS_HEADER)AllocBuff; + PIMAGE_NT_HEADERS CopyNthead = (PIMAGE_NT_HEADERS)((LPBYTE)AllocBuff + CopyDosHead->e_lfanew); + /* + DWORD64 BaseOfCode = 0; + DWORD64 SizeOfCode = 0; + if (CopyNthead->FileHeader.Machine == IMAGE_FILE_MACHINE_AMD64) { + PIMAGE_NT_HEADERS64 CopyNthead64 = (PIMAGE_NT_HEADERS64)CopyNthead; + BaseOfCode = CopyNthead64->OptionalHeader.BaseOfCode; + SizeOfCode = CopyNthead64->OptionalHeader.SizeOfCode; + } + else { + PIMAGE_NT_HEADERS32 CopyNthead32 = (PIMAGE_NT_HEADERS32)CopyNthead; + BaseOfCode = CopyNthead32->OptionalHeader.BaseOfCode; + SizeOfCode = CopyNthead32->OptionalHeader.SizeOfCode; + } + */ + PIMAGE_SECTION_HEADER SectionHeader = (PIMAGE_SECTION_HEADER)((PUCHAR)CopyNthead + sizeof(CopyNthead->Signature) + sizeof(CopyNthead->FileHeader) + CopyNthead->FileHeader.SizeOfOptionalHeader); + int FoundNum = 0; + for (WORD i = 0; i < CopyNthead->FileHeader.NumberOfSections; i++) + { + if (SectionHeader[i].Characteristics & IMAGE_SCN_MEM_EXECUTE) { + FoundNum++; + } + if (FoundNum > 1) { + printf("\t => [̼] ⵽Ŀִ(.rdataɱ or ӿdz) %ws ģ %ws %s \n", pMoudleName, moduleEntry.szExePath, SectionHeader[i].Name); + break; + } + } + } + } + + } while (Module32Next(handle, &moduleEntry)); + VirtualFree(AllocBuff, 0, MEM_RELEASE); + } + CloseHandle(handle); +} +void ProcessStackWalk() { + PROCESSENTRY32 pe32; + pe32.dwSize = sizeof(pe32); + HANDLE hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); + if (hProcessSnap == INVALID_HANDLE_VALUE) + { + printf("CreateToolhelp32Snapshot error.\n"); + return; + } + BOOL bProcess = Process32First(hProcessSnap, &pe32); + while (bProcess) + { + //ӡͽID + HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, false, pe32.th32ProcessID); + if (hProcess) { + WalkProcessMoudle(pe32.th32ProcessID, hProcess, pe32.szExeFile); + WCHAR szImagePath[MAX_PATH]; + WCHAR pszFullPath[MAX_PATH]; + if (GetProcessImageFileName(hProcess, szImagePath, MAX_PATH)) + { + if (DosPathToNtPath(szImagePath, pszFullPath)) + { + CdigitalSig DigitalSig(pszFullPath); + DWORD dDigitalState = DigitalSig.GetDigitalState(); + if (dDigitalState == DIGITAL_SIGSTATE_REVOKED || dDigitalState == DIGITAL_SIGSTATE_EXPIRE) { + printf("\t => [ɨ] ⵽ǩ · %ws static %d \n", pszFullPath, dDigitalState); + } + } + } + CloseHandle(hProcess); + } + bProcess = Process32Next(hProcessSnap, &pe32); + } + CloseHandle(hProcessSnap); + return; + +} +void ScanSystemDrivers() { + DWORD cbNeeded = 0; // drivers[] صֽ + LPVOID drivers[MAX_PATH] = { 0 }; // ַб + int cDrivers = 0; // + Wow64EnableWow64FsRedirection(0); + if (EnumDeviceDrivers(drivers, sizeof(drivers), &cbNeeded) && cbNeeded < sizeof(drivers)) // EnumDeviceDrivers ÿļļصַ + { + char szDriver[MAX_PATH] = { 0 }; // ļ + char szPath[MAX_PATH] = { 0 }; // ļȫ· + char szNtPath[MAX_PATH] = { 0 }; + char szSystemPath[MAX_PATH] = { 0 }; // system32 ļ· + cDrivers = cbNeeded / sizeof(LPVOID); // + + for (int i = 0; i < cDrivers; i++) + { + if (drivers[i]) { + if (GetDeviceDriverBaseNameA(drivers[i], szDriver, sizeof(szDriver) / sizeof(LPVOID))) + { + if (GetDeviceDriverFileNameA(drivers[i], szPath, sizeof(szPath))) { + bool isSystemDriver = true; + //ֻжϷϵͳ + if (szPath[1] == '?') + { + isSystemDriver = false; + int len = strlen(szPath); + szPath[len + 1] = '\0'; + for (int j = 0; j < len; j++) + { + szPath[j] = szPath[j + 4]; + } + WCHAR UnicodeFilePath[MAX_PATH << 1] = { 0 }; + CharToWchar(szPath, UnicodeFilePath); + CdigitalSig DigitalSig(UnicodeFilePath); + DWORD dDigitalState = DigitalSig.GetDigitalState(); + if (dDigitalState != DIGITAL_SIGSTATE_VALID) { + printf("\t => [ɨ] ⵽δ֪ · %ws \n", UnicodeFilePath); + } + } + } + } + } + } + } + Wow64EnableWow64FsRedirection(1); +} +int main() +{ + printf("DuckMemoryScan By huoji 2021-02-23 \n"); + if (EnableDebugPrivilege(true) == false) { + printf("Ȩʧ,ԹԱ \n"); + system("pause"); + return 0; + } + printf("̶߳ջݼ ... \n"); + ThreadStackWalk(); + printf("... \n"); + ScanSystemDrivers(); + printf("̼... \n"); + ProcessStackWalk(); + printf(" ... \n"); + system("pause"); + return 0; +} \ No newline at end of file