修正一个单词错误
This commit is contained in:
@@ -10,6 +10,7 @@
|
||||
#include <mscat.h>
|
||||
#pragma comment (lib, "wintrust")
|
||||
#pragma comment (lib, "crypt32.lib")
|
||||
#define PE_BUFF_SIZE 0x1337
|
||||
typedef enum _MEMORY_INFORMATION_CLASS {
|
||||
MemoryBasicInformation,
|
||||
MemoryWorkingSetList,
|
||||
|
||||
@@ -109,8 +109,50 @@ DWORD64 GetProcessMoudleHandle(DWORD pid) {
|
||||
} while (Module32Next(handle, &moduleEntry));
|
||||
return 0;
|
||||
}
|
||||
bool CheckThreadIsInCodeSection(DWORD64 pAddress, HANDLE pHandle, DWORD64 pID) {
|
||||
bool result = false;
|
||||
MODULEENTRY32 moduleEntry;
|
||||
HANDLE handle = ::CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, pID);
|
||||
ZeroMemory(&moduleEntry, sizeof(MODULEENTRY32));
|
||||
moduleEntry.dwSize = sizeof(MODULEENTRY32);
|
||||
char* AllocBuff = (char*)VirtualAlloc(NULL, PE_BUFF_SIZE, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
|
||||
if (AllocBuff) {
|
||||
if (!Module32First(handle, &moduleEntry)) {
|
||||
CloseHandle(handle);
|
||||
return false;
|
||||
}
|
||||
do {
|
||||
DWORD64 ReadNum = 0;
|
||||
if (ReadProcessMemory(pHandle, moduleEntry.modBaseAddr, AllocBuff, PE_BUFF_SIZE, &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;
|
||||
}
|
||||
if (pAddress >= (DWORD64)moduleEntry.modBaseAddr + BaseOfCode && pAddress <= (DWORD64)moduleEntry.modBaseAddr + BaseOfCode + SizeOfCode) {
|
||||
result = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool CheckThreadAddressIsExcute(DWORD64 pAddress,HANDLE pHandle, HANDLE pID, HANDLE Tid, BOOL isRipBackTrack) {
|
||||
} while (Module32Next(handle, &moduleEntry));
|
||||
VirtualFree(AllocBuff, 0, MEM_RELEASE);
|
||||
}
|
||||
CloseHandle(handle);
|
||||
return result;
|
||||
}
|
||||
void CheckThreadAddressIsExcute(DWORD64 pAddress,HANDLE pHandle, HANDLE pID, HANDLE Tid, BOOL isRipBackTrack) {
|
||||
|
||||
DWORD64 ReadNum = 0;
|
||||
MEMORY_BASIC_INFORMATION mbi = { 0 };
|
||||
@@ -127,16 +169,14 @@ bool CheckThreadAddressIsExcute(DWORD64 pAddress,HANDLE pHandle, HANDLE pID, HAN
|
||||
printf("\t => [!!!<21>̶߳<DFB3>ջ<EFBFBD><D5BB><EFBFBD><EFBFBD>!!!] <20><><EFBFBD><EFBFBD>ڴ<EFBFBD><DAB4><EFBFBD><EFBFBD>س<EFBFBD><D8B3><EFBFBD> <20>̵߳<DFB3>ַ %p PID %d TID %d <20>ڴ<EFBFBD><DAB4><EFBFBD><EFBFBD><EFBFBD>ģ<EFBFBD><C4A3><EFBFBD><EFBFBD>ַ: %p\n", pAddress, pID, Tid, mbi.BaseAddress);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
else if (isRipBackTrack && mbi.AllocationProtect & PAGE_READONLY && mbi.AllocationProtect & PAGE_NOACCESS) {
|
||||
printf("\t => [<5B>̶߳<DFB3>ջ<EFBFBD><D5BB><EFBFBD><EFBFBD>] <20><><EFBFBD><EFBFBD>߳<EFBFBD><DFB3><EFBFBD><EFBFBD>ڲ<EFBFBD><DAB2><EFBFBD>ִ<EFBFBD>еĴ<D0B5><C4B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ִ<EFBFBD>й<EFBFBD>[<5B><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ƿ<EFBFBD><C7B7><EFBFBD>Rootkit<69><74><EFBFBD>ڻ<EFBFBD><DABB><EFBFBD><EFBFBD>Ƿ<EFBFBD><C7B7><EFBFBD>Hook] <20><>ַ %p PID %d TID %d \n", pAddress, pID, Tid);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
return;
|
||||
}
|
||||
void ThreadStackWalk() {
|
||||
HANDLE hThreadSnap = INVALID_HANDLE_VALUE;
|
||||
@@ -173,6 +213,11 @@ void ThreadStackWalk() {
|
||||
printf("\t => [<5B>̶߳<DFB3>ջ<EFBFBD><D5BB><EFBFBD><EFBFBD>] <20><><EFBFBD>HWBP Hook PID %d TID %d \n", te32.th32OwnerProcessID, te32.th32ThreadID);
|
||||
}
|
||||
CheckThreadAddressIsExcute(context.Rip, hProcess, (HANDLE)te32.th32OwnerProcessID, (HANDLE)te32.th32ThreadID, TRUE);
|
||||
/*
|
||||
if (CheckThreadIsInCodeSection(context.Rip, hProcess, (DWORD64)te32.th32OwnerProcessID) == false){
|
||||
__debugbreak();
|
||||
}
|
||||
*/
|
||||
StackFarmeEx.AddrPC.Offset = context.Rip;
|
||||
StackFarmeEx.AddrPC.Mode = AddrModeFlat;
|
||||
StackFarmeEx.AddrStack.Offset = context.Rsp;
|
||||
@@ -201,8 +246,13 @@ void ThreadStackWalk() {
|
||||
//hwbp hook
|
||||
printf("\t => [<5B>̶߳<DFB3>ջ<EFBFBD><D5BB><EFBFBD><EFBFBD>] <20><><EFBFBD>HWBP Hook PID %d TID %d \n", te32.th32OwnerProcessID, te32.th32ThreadID);
|
||||
}
|
||||
|
||||
CheckThreadAddressIsExcute(context.Eip, hProcess, (HANDLE)te32.th32OwnerProcessID, (HANDLE)te32.th32ThreadID, TRUE);
|
||||
/*
|
||||
if (CheckThreadIsInCodeSection(context.Eip, hProcess, (DWORD64)te32.th32OwnerProcessID) == false) {
|
||||
__debugbreak();
|
||||
}
|
||||
*/
|
||||
|
||||
StackFarmeEx.AddrPC.Offset = context.Eip;
|
||||
StackFarmeEx.AddrPC.Mode = AddrModeFlat;
|
||||
StackFarmeEx.AddrStack.Offset = context.Esp;
|
||||
@@ -233,13 +283,14 @@ void ThreadStackWalk() {
|
||||
}
|
||||
}
|
||||
void WalkProcessMoudle(DWORD pID,HANDLE pHandle,WCHAR* pMoudleName,BOOL pCheckMoudle) {
|
||||
|
||||
if (pCheckMoudle == false)
|
||||
return;
|
||||
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);
|
||||
char* AllocBuff = (char*)VirtualAlloc(NULL, PE_BUFF_SIZE, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
|
||||
if (AllocBuff) {
|
||||
if (!Module32First(handle, &moduleEntry)) {
|
||||
CloseHandle(handle);
|
||||
@@ -253,25 +304,49 @@ void WalkProcessMoudle(DWORD pID,HANDLE pHandle,WCHAR* pMoudleName,BOOL pCheckMo
|
||||
printf("\t => [ģ<><C4A3>ɨ<EFBFBD><C9A8>] <20><><EFBFBD><EFBFBD><E2B5BD><EFBFBD><EFBFBD>ģ<EFBFBD><C4A3>(Ҳ<><D2B2><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>) ·<><C2B7> %ws <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> %ws pid %d \n", moduleEntry.szExePath, pMoudleName, pID);
|
||||
}
|
||||
}
|
||||
/*
|
||||
DWORD64 ReadNum = 0;
|
||||
if (ReadProcessMemory(pHandle, moduleEntry.modBaseAddr, AllocBuff, 0x200, &ReadNum)) {
|
||||
if (ReadProcessMemory(pHandle, moduleEntry.modBaseAddr, AllocBuff, PE_BUFF_SIZE, &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);
|
||||
PIMAGE_SECTION_HEADER SectionHeader = (PIMAGE_SECTION_HEADER)((PUCHAR)CopyNthead + sizeof(CopyNthead->Signature) + sizeof(CopyNthead->FileHeader) + CopyNthead->FileHeader.SizeOfOptionalHeader);
|
||||
DWORD64 BaseOfCode = 0;
|
||||
DWORD64 SizeOfCode = 0;
|
||||
DWORD64 SizeSignature = 0;
|
||||
DWORD64 SizeFileHeader = 0;
|
||||
DWORD64 SizeFileHeaderSizeOfOptionalHeader = 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;
|
||||
SizeSignature = sizeof(CopyNthead64->Signature);
|
||||
SizeFileHeader = sizeof(CopyNthead64->FileHeader);
|
||||
SizeFileHeaderSizeOfOptionalHeader = CopyNthead64->FileHeader.SizeOfOptionalHeader;
|
||||
}
|
||||
else {
|
||||
PIMAGE_NT_HEADERS32 CopyNthead32 = (PIMAGE_NT_HEADERS32)CopyNthead;
|
||||
BaseOfCode = CopyNthead32->OptionalHeader.BaseOfCode;
|
||||
SizeOfCode = CopyNthead32->OptionalHeader.SizeOfCode;
|
||||
SizeSignature = sizeof(CopyNthead32->Signature);
|
||||
SizeFileHeader = sizeof(CopyNthead32->FileHeader);
|
||||
SizeFileHeaderSizeOfOptionalHeader = CopyNthead32->FileHeader.SizeOfOptionalHeader;
|
||||
}
|
||||
PIMAGE_SECTION_HEADER SectionHeader = (PIMAGE_SECTION_HEADER)((PUCHAR)CopyNthead + SizeSignature + SizeFileHeader + SizeFileHeaderSizeOfOptionalHeader);
|
||||
int FoundNum = 0;
|
||||
for (WORD i = 0; i < CopyNthead->FileHeader.NumberOfSections; i++)
|
||||
{
|
||||
if (SectionHeader[i].Characteristics & IMAGE_SCN_MEM_EXECUTE) {
|
||||
FoundNum++;
|
||||
}
|
||||
if (FoundNum > 1) {
|
||||
if (FoundNum > 3) {
|
||||
printf("\t => [<5B><><EFBFBD>̼<EFBFBD><CCBC><EFBFBD>] <20><><EFBFBD><EFBFBD><E2B5BD><EFBFBD><EFBFBD><EFBFBD>Ŀ<EFBFBD>ִ<EFBFBD><D6B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD>(.rdata<74><61>ɱ or <20>ӿdz<D3BF><C7B3><EFBFBD>) <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> %ws ·<><C2B7> %ws <20><><EFBFBD><EFBFBD>id %d\n", pMoudleName, moduleEntry.szExePath, pID);
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
} while (Module32Next(handle, &moduleEntry));
|
||||
VirtualFree(AllocBuff, 0, MEM_RELEASE);
|
||||
@@ -305,7 +380,6 @@ void ProcessStackWalk() {
|
||||
printf("\t => [<5B><><EFBFBD><EFBFBD>ɨ<EFBFBD><C9A8>] <20><><EFBFBD><EFBFBD><E2B5BD><EFBFBD><EFBFBD>ǩ<EFBFBD><C7A9><EFBFBD><EFBFBD><EFBFBD><EFBFBD> ·<><C2B7> %ws static %d \n", pszFullPath, dDigitalState);
|
||||
}
|
||||
WalkProcessMoudle(pe32.th32ProcessID, hProcess, pe32.szExeFile, dDigitalState == DIGITAL_SIGSTATE_VALID);
|
||||
|
||||
}
|
||||
}
|
||||
CloseHandle(hProcess);
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
# DuckMemoryScan
|
||||
一个简单寻找无文件落地后门的工具,由huoji花了1天编写,编写时间2021-02-24
|
||||
一个简单寻找包括不限于iis劫持,无文件木马,shellcode免杀后门的工具,由huoji花了1天编写,编写时间2021-02-24
|
||||
!!!本程序需要64位编译才能回溯x64的程序堆栈,请勿执行32位编译!!!
|
||||
!!!本工具不能代替杀毒软件!!!
|
||||
|
||||
# 运行截图
|
||||

|
||||

|
||||
|
||||
# 功能列表
|
||||
1. HWBP hook检测 检测线程中所有疑似被hwbp隐形挂钩
|
||||
2. 内存免杀shellcode检测(metasploit,Cobaltstrike完全检测)
|
||||
@@ -12,6 +14,7 @@
|
||||
4. 无文件落地木马检测(检测所有已知内存加载木马)
|
||||
5. 简易rootkit检测(检测证书过期/拦截读取/证书无效的驱动)
|
||||
6. 检测异常模块,检测绝大部分如"iis劫持"的后门(2021年2月26日新增)
|
||||
|
||||
# 免杀木马检测原理:
|
||||
所有所谓的内存免杀后门大部分基于"VirtualAlloc"函数申请内存 之后通过各种莫名其妙的xor甚至是aes加密去混淆shellcode达到"免杀"效果.
|
||||
本工具通过线程堆栈回溯方法(StackWalkEx函数)遍历线程,寻找系统中在VirtualAlloc区域执行代码的区域,从而揪出"免杀木马"
|
||||
@@ -37,4 +40,6 @@
|
||||
目前工具只回溯rip与eip,你可以回溯RSP或者EBP 只需修改StackFarmeEx.AddrPC.Offset即可
|
||||
|
||||
# 追踪这个项目
|
||||
白帽wiki是一个公益性质的知识库为所有人在知识付费时代提供一个简单的免费的存储知识的网站.对标vxjump.net,我会无偿的将我的所学到的知识分享在此wiki中,目前涉及到机器学习领域,虚拟化安全领域,传统安全领域,游戏安全领域,EFI硬件安全领域.希望后人能少一点坑.
|
||||
你可以在此网站中发现一个沉沦很久的讨论群,选择加入,然后一起扯淡聊天.
|
||||
https://key08.com
|
||||
Reference in New Issue
Block a user