东辉主动防御软件是一款通过行为分析来识别和防御病毒木马程序的软件。
项目如图:
BehaviorMon是主程序,BehaviorMon_driver是驱动操作部分。
效果如图:
分析:
DataStruct.h 自定义数据接口:运行模式枚举类型、防御状态类型、被保护注册表信息、被保护文件信息、白名单结构体、保存被hook的nativeAPI函数信息(Ring0使用)、保存被hook的nativeAPI函数信息(Ring3使用)、进程中可疑行为链表结构体、衍生物类型的枚举定义、衍生物项目结构体、线程链表结构体、模块链表结构体、进程项目结构体 、病毒链表结构体、ring0和ring3共享的数据内存池、文件信息……等等
IoctlCmd.h 定义了IO操作接口(ring0和ring3操作接口)
MajorFunctionName.h 定义了IRP函数数组
VistaShadowSSDT.h 定义了Vista下的SSDT函数表
W2K3ShadowSSDT.h 定义了W2K3下的SSDT函数表
W2KShadowSSDT.h 定义了W2K下的SSDT函数表
XPShadowSSDT.h 定义了XP下的SSDT函数表
TypeStruct.h 结构类型:核心结构(函数名和函数地址)、链表(文件连接、线程链表、进程列表……等等)
md5sum.h和md5.h 实现了md5的求算,定义如下:
bool getFileMd5Value(const char *fileName,std::string &md5Ret);
void getStringMD5Value(const char *str,std::string &md5Ret);
WindowsVersion.h 实现了求系统版本,定义如下:
NTSTATUS GetWindowsVersion();
NTSTATUS InitOffsetbyWindowsVersion();
API.h 定义了API相关函数结构,从系统Dll中获取api的地址
File.h 文件操作,定义如下:
//设置是否可以访问
DWORD SetHandleAccess(
HANDLE Handle,
ACCESS_MASK GrantedAccess
);
//设置为保护状态
BOOL AddFileProtectItemToFileProtectList(char *directory,char *file,int score,char * info);
//读取受保护的列表
BOOL ReadFileProtectList();
//写受保护的列表
BOOL WriteFileProtectList();
//删除受保护的状态
BOOL DeleteFileProtectItemFromFileProtectList(char *directory,char *file);
FSD.h 获取ntfs.sys,fastfat.sys文件中驱动派遣例程的原始地址
GDT.h 获得GDT中段描述符(全局)
IDT.h 获取中断表
IoControlFuzz.h io操作文件,定义如下:
/************************************************************************/
/* 添加文件规则
*/
/************************************************************************/
BOOL AddIoControlMITMFuzzItemToList(IOCONTROL_MITM_FUZZ_INFO * fuzzInfo,IOCONTROL_MITM_FUZZ_INFO ** pTargetFuzzInfo)
/************************************************************************/
/* 根据 文件目录 和 文件名称 找到文件规则列表中的目标项目
进行删除操作
*/
/************************************************************************/
BOOL DeleteIoControlMITMFuzzItemFromList(IOCONTROL_MITM_FUZZ_INFO * fuzzInfo)
Memory.h 内存操作
///
//
// 功能实现:申请堆内存
// 输入参数:Length为申请的缓冲区长度
// 输出参数:失败返回NULL,成功则返回申请的内存缓冲区指针
//
///
PVOID
AllocHeapMem(DWORD Length);
///
//
// 功能实现:释放堆内存
// 输入参数:pMem为要释放的缓冲区指针
// 输出参数:无
//
///
void
FreeHeapMem(PVOID pMem);
Module.h
MsgHook.h 消息钩子
Net.h 定义了网络相关的结构:TCP相关结构体、UDP相关结构体、TCP 端口状态.
OS.h 定义如下:
///
//
// 功能实现:判断当前操作系统版本
// 输入参数:无
// 输出参数:输出参数返回函数声明处定义的宏
//
///
WORD GetCurrentOSVersion(void);
///
//
// 功能实现:获取内核文件信息
// 输入参数:KERNELINFO类型的缓冲区指针
// 输出参数:获取成功返回TRUE,否则返回FALSE
//
///
bool
GetKernelFileName(PKERNELINFO pKernelInfo);
PE.h 定义如下:
///
//
// 功能实现:解析PE文件,获取PE结构中各个头的指针
// 输入参数:ibase为映像基地址;
// pfh,poh,psh分别为IMAGE_FILE_HEADER,IMAGE_OPTIONAL_HEADER,
// IMAGE_SECTION_HEADER的指针
// 输出参数:返回TRUE表示获取成功,否则失败
//
///
DWORD GetHeaders(PCHAR ibase,
PIMAGE_FILE_HEADER *pfh,
PIMAGE_OPTIONAL_HEADER *poh,
PIMAGE_SECTION_HEADER *psh);
//
//
// 功能实现:将指定的RVA地址转换成相对文件的偏移
// 输入参数:Base是文件加载的基地址;
// RVA是要获取文件偏移的RVA地址
// 输出参数:返回DWORD类型的相对文件的偏移量
//
///
DWORD RVAToFileOffset(PCHAR Base,DWORD RVAAddress);
///
//
// 功能实现:获取指定文件中的指定节的指针
// 输入参数:ImagePath为要获取指定节指针的映像路径
// FindSetionName为要查找的节名
// ImageBase为返回的映像的默认加载基地址;
// pFile为存放内存映像的缓冲区地址;
// 输出参数:返回指向指定节数据的指针
//
///
PCHAR
GetSettionPoint(PCHAR ImagePath,PCHAR FindSetionName,PDWORD ImageBase,PCHAR* pFile);
//
//
// 功能实现:获取指定PE文件中指定函数的导出地址
// 输入参数:Base为PE文件加载的基地址
// FindFunName为要查找的函数名
// NameLength为函数名长度
// 输出参数:返回指定函数名的函数首地址
//
///
DWORD
FindFunAddress(DWORD Base,PCHAR FindFunName,DWORD NameLength);
Process.h 操作进程,定义如下:
//R3 Jobobj
BOOL KillProcessByJobObj(DWORD processPid);
BOOL KillProcessByR3PVASE(ULONG dwProcessId);
BOOL KillProcessByR3UnMapViewofSection(ULONG dwProcessId);
BOOL KillProcessByR3PostThreadMessage(ULONG dwProcessId);
BOOL KillProcessByR3TerminateThread(ULONG dwProcessId);
BOOL KillProcessByR3CreateRemoteThread(ULONG dwProcessId);
BOOL KillProcessByR3DuplicateHandle(ULONG dwProcessId);
void GetProcessPathByPID(ULONG pid,char *processPath);
BOOL GetProcessPath(DWORD dwProcessId,char * processPath);
int EnumProcessFromRing3_Snapshot(CSortListCtrl * m_processList);
int EnumProcessFromRing3_ZwQuerySystemInformation(CSortListCtrl * m_processList);
int EnumProcessFromRing3_EnumProcess(CSortListCtrl * m_processList);
void UpdateProcessThreadListByRing3(ULONG pid,ULONG nThread,SYSTEM_THREAD_INFORMATION * threadList);
void UpdateProcessModuleListByRing3(ULONG pid);
void CalcAndVerifyAllProcess();
BOOL ReadWhiteList();
BOOL WriteWhiteList();
void InitWhiteListFromProcessList();
BOOL AddFileToWhiteList(int type,char * path);
BOOL AddWhiteItemToWhiteList(char *md5,int type,char * path);
BOOL DeleteWhiteFromWhiteList(char *md5);
BOOL IsInWhiteList(char * md5);
PROCESS_ITEM * GetProcessItemByProcessPid(ULONG processPID);
Reg.h 注册表操作
LONG SetKeyValue(HKEY hKey,LPCTSTR lpSubKey,LPCTSTR lpValueName,DWORD dwType,BYTE * lpData,DWORD cbData);
void DeleteKey(char *keyPath);
void DeleteKeyValue(char *keyPath,char *valueName);
void RegeditJump(char * compressPath);
BOOL AddRegProtectItemToRegProtectList(char *key,char *valuename,int score,char * info);
BOOL ReadRegProtectList();
BOOL WriteRegProtectList();
BOOL DeleteRegProtectItemFromRegProtectList(char *key,char *valuename);
SSDT.h 定义如下:
//
//
// 功能实现:查找KiServiceTable
// 输入参数:hModule为模块加载地址,
// dwKSDT为KeServiceDescriptorTable RVA
// 输出参数:返回KiServiceTable的偏移
//
///
DWORD
FindKiServiceTable(HMODULE hModule,DWORD dwKSDT)
//
//
// 功能实现:解析内核文件,获取SSDT表中的服务函数原始地址
// 输入参数:*NumOfAdd返回原始SSDT表中的服务函数个数
// 输出参数:返回DWORD类型的地址数组指针
// 注释:返回的缓冲区最终要用FreeHeapMem释放
//
///
PDWORD
EnumSSDTNativeFunAdd(PDWORD NumOfAdd)
//
//
// 功能实现:解析内核文件,获取SSDT表中的服务函数原始地址
// 输入参数:*NumOfAdd返回原始SSDT表中的服务函数个数
// 输出参数:返回DWORD类型的地址数组指针
// 注释:返回的缓冲区最终要用FreeHeapMem释放
//
///
PSSDTNAME
EnumServiceFunName(PDWORD NumOfFunName)
///
//
// 功能实现:获取Shadow SSDT服务函数原始地址
// 输入参数:NumOfFun为shadow ssdt的原始地址个数;
// 输出参数:返回存放原始地址数据的缓冲区指针,需要自己调用FreeHeapMem释放释放
//
///
PDWORD GetShadowSSDTNativeAdd(PDWORD NumOfFun)
MicrosoftVerify.h 自定义了微软认证的类
程序重写了很多控件,如下:
//提示信息
class CBalloonTip : public CFrameWnd
//重写编辑框
class CGfxGroupEdit : public CEdit
//重新自定了树控件
class CGfxOutBarCtrl : public CWnd
//重写了弹出菜单
class CGfxPopupMenu : public CMenu
//重写窗口分割器
class CGfxSplitterWnd : public CSplitterWnd
//自定义超链接
class CHyperLink : public CStatic
//重写了列表
class CListCtrlEx : public CListCtrl
//重写了对话框 描述进度
class CProcessBarDialog : public CResizableDialog
//列表头
class CSortHeaderCtrl : public CHeaderCtrl
//重写了列表 实现了顺序排列
class CSortListCtrl : public CListCtrl
//类似电驴的闪屏
class CSplashWnd : public CWnd
//操作托盘图片以及相关功能的实现
class CSystemTray
//提示对话框
class CAlertDialog : public CDialog
//提示结果对话框
class CAlertResultDialog : public CDialog
//详细动作对话框
class CBehaviorDetailDialog : public CDialog
//删除文件对话框
class CDeleteFileDialog : public CResizableDialog
//驱动树图
class CDriveView : public CTreeView
//文件输出文本
class CFileExpDoc : public CDocument
//文件输出框架窗体
class CFileExpFrame : public CFrameWnd
//文件视图 显示文件的信息
class CFileView : public CView
//查找漏洞对话框
class CFindExploitDialog : public CResizableDialog
//操作驱动派遣列表
class CFSDListDialog : public CResizableDialog
//全局描述符列表对话框
class CGDTListDialog : public CResizableDialog
//中断描述符列表对话框
class CIDTListDialog : public CResizableDialog
//搜索黑客攻击对话框
class CIESearchHijackCheckerDialog : public CResizableDialog
//与驱动操作文件的对话框
class CDeviceIoControlFuzzer : public CResizableDialog
//核心句柄列表对话框
class CKernelModuleListDialog : public CResizableDialog
//输出日志对话框
class CMBehaviorLogDialog : public CResizableDialog
//句柄列表对话框
class CModuleListDialog : public CResizableDialog
//消息拦截列表设置对话框
class CMessageHookListDialog : public CResizableDialog
//网络连接列表对话框
class CNetLinkListDialog : public CResizableDialog
//重写了下拉框控件
class CComboInListView : public CComboBox
//设置接口对话框
class CConfigInteractiveDialog : public CDialog
//有消息输出提示对话框
class CComeOutTipDialog : public CDialog
//过滤信息对话框
class CFilterStringDialog : public CDialog
//软件列表显示设置对话框
class CSoftwareListDialog : public CResizableDialog
//ssdt列表操作对话框
class CSSDTListDialog : public CResizableDialog
//常用windows函数及API列表操作对话框
class CSSDTShadowListDialog : public CResizableDialog
//系统服务列表操作对话框
class CSystemServiceListDialog : public CResizableDialog
//线程列表操作对话框
class CThreadListDialog : public CResizableDialog
//病毒输出日志对话框
class CVirusLogDialog : public CResizableDialog
//白名单与黑名单操作管理对话框
class CWhiteListManageDialog : public CResizableDialog
BehaviorMon.h 主程序的启动类,有如下定义:
/* 获得密码的函数
*/
/************************************************************************/
__int64 epass()
/* 给文件加密的函数
*/
/************************************************************************/
BOOL ecfile(LPCTSTR fpath)
/* 给文件解密的函数
*/
/************************************************************************/
BOOL dcfile(LPCTSTR fpath)
/* 根据文件名获取同路径下文件路径
*/
/************************************************************************/
BOOL GetSameDirectoryFilePath(IN char * fileName,OUT char * filePath)
/* 接受多个参数并打印调试信息
*/
/************************************************************************/
void MyOutputDebugString(IN const char * sz, ...)
/* 文件md5计算 直接计算 不使用cache
*/
/************************************************************************/
BOOL CalcFileMd5Str(IN char *path,OUT char * md5)
/* 文件md5计算 使用cache
*/
/************************************************************************/
BOOL GetFileMd5Str(IN char *path,OUT char * md5)
/* 文件验证 使用cache
<md5,isVerified>
*/
/************************************************************************/
BOOL GetFileVerifyResult(IN char *md5,IN char *path)
/* 获取时间字符串 将大整数时间转换为字符串
格式:hh:mm:ss.xxx
*/
/************************************************************************/
void GetTimeStr(IN LARGE_INTEGER liTime,OUT char *timeStrBuf)
/* 获取日期字符串 将大整数日期转换为字符串
格式:YYYY-MM-DD hh:mm:ss
*/
/************************************************************************/
void GetDateTimeStr(LARGE_INTEGER liTime,char *timeStrBuf)
/* 将输入的字符串 line 按照分割字符 delimiter 进行分割
将每个分割项指针存入items数组中
最后返回分割的项目个数
*/
/************************************************************************/
int Split( IN char * line, IN char delimiter, OUT char * items[] )
/* 通过对话框形式 显示错误提示
s 作为提示字符串的前缀
*/
/************************************************************************/
void displayError(IN char * s)
/************************************************************************/
/* 根据注册表键值的类型 返回宏名称的字符串
#define REG_NONE ( 0 ) // No value type
#define REG_SZ ( 1 ) // Unicode nul terminated string
#define REG_EXPAND_SZ ( 2 ) // Unicode nul terminated string
#define REG_BINARY ( 3 ) // Free form binary
#define REG_DWORD ( 4 ) // 32-bit number
#define REG_DWORD_LITTLE_ENDIAN ( 4 ) // 32-bit number (same as REG_DWORD)
#define REG_DWORD_BIG_ENDIAN ( 5 ) // 32-bit number
#define REG_LINK ( 6 ) // Symbolic Link (unicode)
#define REG_MULTI_SZ ( 7 ) // Multiple Unicode strings
#define REG_RESOURCE_LIST ( 8 ) // Resource list in the resource map
#define REG_FULL_RESOURCE_DESCRIPTOR ( 9 ) // Resource list in the hardware description
#define REG_RESOURCE_REQUIREMENTS_LIST ( 10 )
#define REG_QWORD ( 11 ) // 64-bit number
#define REG_QWORD_LITTLE_ENDIAN ( 11 ) // 64-bit number (same as REG_QWORD)
*/
/************************************************************************/
void GetRegValueTypeString(IN ULONG RegValueType,OUT char *RegValueTypeString )
/* 根据衍生物类型 返回宏名称的字符串
*/
/************************************************************************/
void GetRamiTypeString(IN ULONG RamiType,OUT char *RamiTypeString )
/* 根据注册表键值类型 返回该键值可以显示的字符串
*/
/************************************************************************/
void GetRegValueString(IN PVOID value,IN ULONG valueType,IN ULONG valueSize,char *ramiValue)
/* 根据衍生物的状态 获取字符串
*/
/************************************************************************/
void GetRamiStateString(IN RAMIFICATION_STATE state,OUT char *state_c)
/* 根据线程状态 获取字符串
*/
/************************************************************************/
void GetThreadStateString(IN UCHAR state,OUT char *state_c)
/* 检查设备句柄是否存在
*/
/************************************************************************/
BOOL IsValidDeviceHandle(HANDLE device)
/* 从资源中释放一个文件
*/
/************************************************************************/
BOOL ReleaseResourceFile(int resId,char * resType,char *filePath)
/* 线程函数 恶意进程报警处理
靠前台的报警标志缓冲区来判断当前是否有某个进程的评分已经超过了最大阈值
如果超过了阈值,那么就开始识别这个进程可能是什么种类的木马或病毒
然后弹出报警框,询问用户是否加入白名单,还是删除,还是不删除
*/
/************************************************************************/
static void MyThread_alert()
/* 线程函数 计算md5
为后台驱动程序计算进程文件的md5
*/
/************************************************************************/
static void MyThread_md5()
/* 线程函数 ring0通知ring3收容已经死去的进程
把该死去的进程项拷贝到死进程列表中
并开启内存存放该进程的 可疑行为 衍生物 线程 模块
*/
/************************************************************************/
static void MyThread_deadProcess()
/* Ring3初始化 工作线程
*/
/************************************************************************/
void MyThread_InitSystem(LPVOID pParam)
/* Ring3系统退出 工作线程
*/
/************************************************************************/
void MyThread_ExitSystem(LPVOID pParam)
主程序加载驱动部分:
/************************************************************************/
/* 主应用程序初始化函数
*/
/************************************************************************/
BOOL CBehaviorMonApp::InitInstance()
{
BOOL retVal=FALSE;
LPWSTR *szArglist=NULL;
int nArgs=0;
CWinThread* pThreadInitSystem=NULL;
CCommandLineInfo cmdInfo;
//检查是否有相同实例的程序,如果有,则直接提示后退出
hOneInstance=::CreateMutex(NULL,FALSE,UNIQE_NAME);
if(GetLastError() == ERROR_ALREADY_EXISTS)
{
displayError("东辉主动防御程序已运行!");
retVal=FALSE;
goto ret;
}
//获取命令行参数
szArglist = CommandLineToArgvW(GetCommandLineW(), &nArgs);
if( NULL == szArglist )
{
AfxMessageBox("获取命令行参数失败!\n");
return FALSE;
}
if(nArgs>2)
{
AfxMessageBox("参数个数不正确!\n参数说明:\n/d 表示防御模式;\n/t 表示工具模式。\n");
retVal=FALSE;
goto ret;
}
if(nArgs==1 || wcsicmp(szArglist[1],L"/d")==0)//防御模式
{
runMod=RUN_MODE_DEFENSE;
}
else if(wcsicmp(szArglist[1],L"/t")==0)//工具模式
{
runMod=RUN_MODE_TOOL;
}
else
{
AfxMessageBox("参数不正确!\n参数说明:\n/d 表示防御模式;\n/t 表示工具模式。\n");
retVal=FALSE;
goto ret;
}
//MFC
AfxEnableControlContainer();
#ifdef _AFXDLL
Enable3dControls(); // Call this when using MFC in a shared DLL
#else
Enable3dControlsStatic(); // Call this when linking to MFC statically
#endif
SetRegistryKey(_T("Local AppWizard-Generated Applications"));
LoadStdProfileSettings(); // Load standard INI file options (including MRU)
CSingleDocTemplate* pDocTemplate;
pDocTemplate = new CSingleDocTemplate(
IDR_MAINFRAME,
RUNTIME_CLASS(CBehaviorMonDoc),
RUNTIME_CLASS(CMainFrame), // main SDI frame window
RUNTIME_CLASS(CBehaviorMonView));
AddDocTemplate(pDocTemplate);
// Parse command line for standard shell commands, DDE, file open
ParseCommandLine(cmdInfo);
//主窗口最大化(关键)
m_nCmdShow = SW_SHOWMINIMIZED;
// Dispatch commands specified on the command line
// ProcessShellCommand中第一次显示了窗口
if (!ProcessShellCommand(cmdInfo))
{
retVal=FALSE;
goto ret;
}
//
//设置启动时显示欢迎界面 包含滚动条 和 我的照片 哈哈
theApp.pProcessBarDialog=new CProcessBarDialog();
//启动工作线程来初始化系统
pThreadInitSystem=AfxBeginThread((AFX_THREADPROC)MyThread_InitSystem, theApp.pProcessBarDialog);
//开启模式对话框
theApp.pProcessBarDialog->DoModal();
//结束前面的工作线程
TerminateThread(pThreadInitSystem->m_hThread,0);
//获取初始化的结果
retVal=theApp.pProcessBarDialog->m_IsInitSuccess;
//theApp.pProcessBarDialog->DestroyWindow();
//主窗口最大化
theApp.m_pMainWnd->ShowWindow(SW_SHOWMAXIMIZED);
theApp.m_pMainWnd->UpdateWindow();
ret:
//释放命令行参数数据
if(szArglist)
{
GlobalFree(szArglist);
}
//如果初始化结果失败 那么直接进程退出
if(retVal==FALSE)
{
//关闭程序唯一实例句柄
CloseHandle(theApp.hOneInstance);
//隐藏托盘图标
theApp.trayIcon.HideIcon();
//结束进程
ExitProcess(-1);
}
return retVal;
}
//安装设备驱动
//安装了设备驱动后,设备驱动程序中负责创建一个新的虚拟设备
NTSTATUS CBehaviorMonApp::DriverLoad(BOOL isUnloadDriver)
{
DWORD keyValue=1;
int i=0;
char exePath[MAXPATHLEN]={0};
//得到进程文件路径
GetModuleFileName(0,exePath,MAXPATHLEN);
//通过SCM安装驱动程序
SC_HANDLE hService;
SERVICE_STATUS serviceState;
SC_HANDLE hSCManager=OpenSCManager(NULL,NULL,SC_MANAGER_ALL_ACCESS);
if(hSCManager==NULL)
{
displayError("打开服务管理器失败!");
return STATUS_UNSUCCESSFUL;
}
//检查服务是否已经存在
hService=OpenService(hSCManager,"behaviormonservice",SERVICE_ALL_ACCESS);
if(hService)//如果该服务已经启动
{
MyOutputDebugString("防御系统服务已经存在!\n");
/*
//停止这个服务 即卸载该服务的驱动
if(!ControlService(hService,SERVICE_CONTROL_STOP,&serviceState))
{
//displayError("停止已经存在的服务失败!");
}
if(!DeleteService(hService))
{
//displayError("删除已经存在的服务失败!");
//goto ret_unsuccessful;
}
CloseServiceHandle(hService);
*/
//服务自启动
SetKeyValue(HKEY_LOCAL_MACHINE,
"SYSTEM\\CurrentControlSet\\Services\\behaviormonservice",
"Start",
REG_DWORD,
(BYTE *)&keyValue,
sizeof(keyValue));
//前台自启动
SetKeyValue(HKEY_LOCAL_MACHINE,
"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run",
"shineast",
REG_SZ,
(BYTE *)exePath,
strlen(exePath)+1);
//查询服务状态
if(QueryServiceStatus(hService, &serviceState))
{
//如果服务还未处于运行状态
if(serviceState.dwCurrentState != SERVICE_RUNNING)
{
MyOutputDebugString("防御系统服务状态 不是运行状态!\n");
//该服务并没有处于运行状态 另外为了保证驱动路径的准确,因此先卸载再加载
if(!ControlService(hService,SERVICE_CONTROL_STOP,&serviceState))
{
//可能不成功
//displayError("停止已经存在的服务失败!");
MyOutputDebugString("停止 防御系统服务 失败!\n");
}
if(!DeleteService(hService))
{
displayError("删除已经存在的服务失败!");
goto ret_unsuccessful;
}
//关闭该服务的句柄 后面创新创建该服务
CloseServiceHandle(hService);
//重新创建服务
MyOutputDebugString("尝试重新创建 防御系统服务!\n");
goto create_service;
// //启动这个服务
// if(!StartService(hService,0,0))
// {
// displayError("服务已存在,但启动服务失败!");
// goto ret_unsuccessful;
// }
}
else //服务已经在运行
{
MyOutputDebugString("防御系统服务状态 是运行状态!\n");
//如果md5不同,那么需要停止服务 重新创建 并启动服务
if(isUnloadDriver)
{
//停止服务
if(!ControlService(hService,SERVICE_CONTROL_STOP,&serviceState))
{
MyOutputDebugString("停止 防御系统服务 失败!\n");
}
if(!DeleteService(hService))
{
displayError("删除已经存在的服务失败!");
goto ret_unsuccessful;
}
//关闭该服务的句柄 后面创新创建该服务
CloseServiceHandle(hService);
//重新创建服务
MyOutputDebugString("尝试重新创建 防御系统服务!\n");
goto create_service;
}
}
}
else
{
//查询服务状态失败 因此返回不成功
displayError("服务已存在,查询服务状态失败!");
goto ret_unsuccessful;
}
//服务已经存在 并且该服务状态未运行状态 因此无需再次加载驱动
goto ret_successful;
}
create_service:
//开始创建服务
hService=CreateService(hSCManager,"behaviormonservice","behaviormonservice",
SERVICE_START|SERVICE_STOP,SERVICE_KERNEL_DRIVER,SERVICE_DEMAND_START,
SERVICE_ERROR_NORMAL,sysFilePath,0,0,0,0,0);
if(hService==NULL)
{
//指定的服务已标记为删除 则等待
if(GetLastError()==ERROR_SERVICE_MARKED_FOR_DELETE)
{
OutputDebugString("继续等待...");
Sleep(1000);
if(i++<10)
goto create_service;
}
displayError("创建服务失败!");
goto ret_unsuccessful;
}
MyOutputDebugString("创建防御系统服务成功!\n");
//服务自启动
SetKeyValue(HKEY_LOCAL_MACHINE,
"SYSTEM\\CurrentControlSet\\Services\\behaviormonservice",
"Start",
REG_DWORD,
(BYTE *)&keyValue,
sizeof(keyValue));
//前台自启动
SetKeyValue(HKEY_LOCAL_MACHINE,
"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run",
"shineast",
REG_SZ,
(BYTE *)exePath,
strlen(exePath)+1);
//启动服务 即加载驱动
if(!StartService(hService,0,0))
{
displayError("启动服务失败!");
goto ret_unsuccessful;
}
MyOutputDebugString("启动防御系统服务成功!\n");
ret_successful:
CloseServiceHandle(hService);
CloseServiceHandle(hSCManager);
return STATUS_SUCCESS;
ret_unsuccessful:
CloseServiceHandle(hService);
CloseServiceHandle(hSCManager);
return STATUS_UNSUCCESSFUL;
}
//*********************************************************************************
void CBehaviorMonApp::DriverUnload()
{
int i=0;
//命令View中的定时器停止获取行为记录
pView->Capture=FALSE;
Sleep(200);
//是否卸载驱动
if(isUnloadDriver)
{
SC_HANDLE hSCManager;
SERVICE_STATUS serviceState;
SC_HANDLE hService;
//打开服务管理器 获得服务管理器句柄
if((hSCManager=OpenSCManager(NULL,NULL,SC_MANAGER_ALL_ACCESS))==NULL)
{
displayError("打开服务管理器失败!");
return;
}
//打开防御系统服务
if((hService=OpenService(hSCManager,"behaviormonservice",SERVICE_ALL_ACCESS))==NULL)
{
displayError("打开服务失败!");
CloseServiceHandle(hSCManager);
return;
}
//停止服务 即卸载驱动
if(ControlService(hService,SERVICE_CONTROL_STOP,&serviceState))
{
//等待服务状态变成 SERVICE_STOPPED
while(serviceState.dwCurrentState == SERVICE_STOP_PENDING && i++ <80)
{
QueryServiceStatus(hService, &serviceState);
Sleep(50);
}
if(serviceState.dwCurrentState == SERVICE_STOPPED)
{
OutputDebugString("东辉主动防御 驱动卸载成功!");
}
}
else
{
OutputDebugString("东辉主动防御 驱动卸载失败!");
}
//关闭服务句柄
CloseServiceHandle(hService);
CloseServiceHandle(hSCManager);
}
}
/* 开启防御
- hook ssdt and shadow ssdt
- 开启线程
*/
/************************************************************************/
BOOL CBehaviorMonApp::StartProtect()
{
DWORD dw=0;
//检查设备句柄
if(!IsValidDeviceHandle(device))
{
return FALSE;
}
//命令驱动hook ssdt and shadow ssdt
if (!NT_SUCCESS(theApp.Hook()))
{
AfxMessageBox("Hook 内核函数失败!");
return FALSE;
}
//设置缓冲区
ZeroMemory(controlBuff,MAXBUFFERSIZE);
DeviceIoControl(device,IOCTL_BEHAVIORMON_STARTPROTECT,controlBuff,MAXBUFFERSIZE,controlBuff,MAXBUFFERSIZE,&dw,0);
//恶意进程(评分超过阈值)报警处理线程
if(hThread_alert==NULL)
{
hThread_alert=::CreateThread(0,0,(LPTHREAD_START_ROUTINE)MyThread_alert,0,0,&dw);
if(hThread_alert==NULL)
{
AfxMessageBox("创建 接受报警信息 线程失败!");
return FALSE;
}
}
//MD5计算线程
if(hThread_md5==NULL)
{
hThread_md5=::CreateThread(0,0,(LPTHREAD_START_ROUTINE)MyThread_md5,0,0,&dw);
if(hThread_md5==NULL)
{
AfxMessageBox("创建 计算md5 线程失败!");
return FALSE;
}
}
//死亡进程通知线程
if(hThread_deadProcess==NULL)
{
hThread_deadProcess=::CreateThread(0,0,(LPTHREAD_START_ROUTINE)MyThread_deadProcess,0,0,&dw);
if(hThread_deadProcess==NULL)
{
AfxMessageBox("创建 死亡进程通知 线程失败!");
return FALSE;
}
}
return TRUE;
}
//
//关闭保护:不仅要把保护标志置位为FALSE,还要将白名单回写到驱动中,日志依然记录
//
BOOL CBehaviorMonApp::ExitProtect()
{
DWORD dw=0;
//检查设备句柄
if(!IsValidDeviceHandle(device))
{
return FALSE;
}
//控制驱动关闭防御
ZeroMemory(controlBuff,MAXBUFFERSIZE);
DeviceIoControl(device,IOCTL_BEHAVIORMON_EXITPROTECT,controlBuff,MAXBUFFERSIZE,controlBuff,MAXBUFFERSIZE,&dw,0);
//结束线程
if(hThread_alert)
{
if(TerminateThread(hThread_alert,0))
hThread_alert=NULL;
}
if(hThread_md5)
{
if(TerminateThread(hThread_md5,0))
hThread_md5=NULL;
}
if(hThread_deadProcess)
{
if(TerminateThread(hThread_deadProcess,0))
hThread_deadProcess=NULL;
}
return TRUE;
}
/* 根据进程pid 分析该进程的病毒类型 并写入报警提示
返回-1 表示有异常情况
*/
/************************************************************************/
int CBehaviorMonApp::AnalyzeTypeofIt(ULONG pid,char *info,ULONG &type )
{
DWORD dw=0;
int ret=-1;
PROCESS_ITEM *analyzeProcessItem;
MALICIOUS_BEHAVIOR_ITEM * analyze_behavior_list;
MALICIOUS_BEHAVIOR_ITEM * maxscore_behavior_list;
int i=0;
//如果进程链表是空的
if(g_dataMemPool->processItemNum==0)
{
return ret;
}
else
{
//遍历链表,找到对应pid的那个进程
analyzeProcessItem=GetProcessItemByProcessPid(pid);
if(analyzeProcessItem==NULL)
{
OutputDebugString("[AnalyzeTypeofIt] 未找到进程!\n");
return ret;
}
}
//开始对analyzeProcessItem进行分析
if(analyzeProcessItem->nMaliciousBehaviorList==0)
{
OutputDebugString("[AnalyzeTypeofIt] 恶意行为个数为0,不可能是恶意程序?!\n");
return ret;
}
//检查该进程的恶意行为列表是否被映射到ring3
if(analyzeProcessItem->pMaliciousBehaviorList_UVA==NULL
|| analyzeProcessItem->pMaliciousBehaviorList_MDL==NULL)
{
//让驱动先映射一下列表
ZeroMemory(controlBuff,MAXBUFFERSIZE);
if(!DeviceIoControl(device,IOCTL_BEHAVIORMON_MAP_MBEHAVIOR_LIST,controlBuff,MAXBUFFERSIZE,controlBuff,MAXBUFFERSIZE,&dw,0))
{
return ret;
}
}
//找到最大恶意评分的行为
//假设第一个恶意行为的分值最大
maxscore_behavior_list=&analyzeProcessItem->pMaliciousBehaviorList_UVA[0];
for(i=1;i<analyzeProcessItem->nMaliciousBehaviorList;i++)
{
analyze_behavior_list=&analyzeProcessItem->pMaliciousBehaviorList_UVA[i];
if(maxscore_behavior_list->score < analyze_behavior_list->score)
{
maxscore_behavior_list=analyze_behavior_list;
}
}
if(_stricmp(maxscore_behavior_list->fun,"NtWriteVirtualMemory")==0
|| _stricmp(maxscore_behavior_list->fun,"NtCreateThread")==0
|| _stricmp(maxscore_behavior_list->fun,"NtQueueApcThread")==0)
{
sprintf(info,"程序[%s]是[%s]类型的木马或病毒!推荐处理:关闭进程。",analyzeProcessItem->path,"代码注入");
analyzeProcessItem->type=1;
}
else if(_stricmp(maxscore_behavior_list->fun,"NtSetSecurityObject")==0)
{
sprintf(info,"程序[%s]是[%s]类型的木马或病毒!推荐处理:关闭进程。",analyzeProcessItem->path,"修改内核内存");
analyzeProcessItem->type=2;
}
else if(_stricmp(maxscore_behavior_list->fun,"NtUserSetWindowsHookEx")==0)
{
sprintf(info,"程序[%s]是[%s]类型的木马或病毒!推荐处理:关闭进程。",analyzeProcessItem->path,"消息钩子");
analyzeProcessItem->type=3;
}
else if(_stricmp(maxscore_behavior_list->fun,"NtLoadDriver")==0
||_stricmp(maxscore_behavior_list->fun,"NtSetSystemInformation")==0
||_stricmp(maxscore_behavior_list->fun,"NtSystemDebugControl")==0)
{
sprintf(info,"程序[%s]是[%s]类型的木马或病毒!推荐处理:关闭进程。",analyzeProcessItem->path,"加载驱动或进Ring0");
analyzeProcessItem->type=4;
}
else if(_stricmp(maxscore_behavior_list->fun,"NtWriteFile")==0)
{
sprintf(info,"程序[%s]是[%s]类型的木马或病毒!推荐处理:关闭进程。",analyzeProcessItem->path,"感染文件");
analyzeProcessItem->type=5;
}
else if(_stricmp(maxscore_behavior_list->fun,"WSPConnect")==0
|| _stricmp(maxscore_behavior_list->fun,"WSPAccept")==0
|| _stricmp(maxscore_behavior_list->fun,"WSPSend")==0
|| _stricmp(maxscore_behavior_list->fun,"WSPSendTo")==0
|| _stricmp(maxscore_behavior_list->fun,"WSPRecv")==0
|| _stricmp(maxscore_behavior_list->fun,"WSPRecvFrom")==0
)
{
sprintf(info,"程序[%s]是[%s]类型的木马或病毒!推荐处理:关闭进程。",analyzeProcessItem->path,"蠕虫");
analyzeProcessItem->type=6;
}
else if(_stricmp(maxscore_behavior_list->fun,"NtTerminateProcess")==0
||_stricmp(maxscore_behavior_list->fun,"NtTerminateThread")==0
||_stricmp(maxscore_behavior_list->fun,"NtDuplicateObject")==0
||_stricmp(maxscore_behavior_list->fun,"NtTerminateJobObject")==0
||_stricmp(maxscore_behavior_list->fun,"NtUnmapViewOfSection")==0
||_stricmp(maxscore_behavior_list->fun,"NtUserPostThreadMessage")==0
||_stricmp(maxscore_behavior_list->fun,"NtUserPostMessage")==0
||_stricmp(maxscore_behavior_list->fun,"NtUserMessageCall")==0
||_stricmp(maxscore_behavior_list->fun,"NtDebugActiveProcess")==0
)
{
sprintf(info,"程序[%s]是[%s]类型的木马或病毒!推荐处理:关闭进程。",analyzeProcessItem->path,"进程攻击");
analyzeProcessItem->type=7;
}
else if(_stricmp(maxscore_behavior_list->fun,"NtUserSendInput")==0 )
{
sprintf(info,"程序[%s]是[%s]类型的木马或病毒!推荐处理:关闭进程。",analyzeProcessItem->path,"模拟键鼠操作");
analyzeProcessItem->type=8;
}
else
{
if(maxscore_behavior_list->score>=MAX_SCORE)
{
sprintf(info,"程序[%s]是[%s]类型的木马或病毒!推荐处理:关闭进程。",analyzeProcessItem->path,maxscore_behavior_list->behaviorType);
analyzeProcessItem->type=0;
for(int i=0;i<sizeof(virusTyprStr)/sizeof(virusTyprStr[0]);i++)
{
if(stricmp(maxscore_behavior_list->behaviorType,virusTyprStr[i])==0)
analyzeProcessItem->type=i;
}
}
else
{
sprintf(info,"程序[%s]是[%s]类型的木马或病毒!推荐处理:关闭进程。",analyzeProcessItem->path,"未知");
analyzeProcessItem->type=0;
}
}
OutputDebugString(info);
OutputDebugString("\n");
type=analyzeProcessItem->type;
return 0;
}
以上是主程序的类操作,主程序引用了第三方库 ResizableLib快速缩放窗体控件!
下面来看看驱动的有哪些东东!~
LDasm.h 反汇编操作,定义如下:
unsigned long __fastcall SizeOfCode(void *Code, unsigned char **pOpcode);
unsigned long __fastcall SizeOfProc(void *Proc);
char __fastcall IsRelativeCmd(unsigned char *pOpcode);
Data.h 定义如下:
//
//
//功能:释放Hash表中的缓冲区
//输入:无
//输出:g_HashTable
//
//
VOID HashCleanup(VOID);
Device.h NT式操作设备对象
File.h 对应上面的文件操作,有添加、删除保护等等
FSD.h 获取ntfs.sys,fastfat.sys文件中驱动派遣例程的原始地址
Function.h 定义如下:
///
//
// 功能实现:获取内核文件ntos***.exe信息
// 输入参数:KERNELINFO类型的缓冲区指针
// 输出参数:获取成功返回TRUE,否则返回FALSE
//
///
BOOLEAN GetKernelFileName(OUT PKERNELINFO pKernelInfo)
//根据特征值,从KeInsertQueueApc搜索中搜索KiInsertQueueApc
ULONG GetKiInsertQueueApc()
//输出核心函数
VOID
ShowKernelExportFunctions(VOID)
//得到核心函数
BOOLEAN
GetKernelExportFunction(IN CHAR * functionName,OUT PVOID * functionAddress)
//得到函数地址
ULONG GetFunctionAddr( IN PCWSTR FunctionName)
GDT.h 定义如下:
///
//
// 功能实现:获取GDT信息
// 输入参数:pOutbuf为输出缓冲区
// 输出参数:返回0值表示查找失败,否则返回获取的GDT中断个数
//
///
USHORT GetGDTInfo(OUT PGDTGD pOutBuf);
IDT.h 定义如下:
///
//
// 功能实现:获取IDT信息
// 输入参数:pOutbuf为输出缓冲区
// 输出参数:返回0值表示查找失败,否则返回获取的IDT中断个数
//
///
USHORT GetIDTInfo(OUT PIDTGD pOutBuf);
IoControlFuzz.h 驱动操作,定义如下:
/************************************************************************/
/* 检查一个对象是否在IoControlMITMFuzz 列表中
对象标识:pid path deviceName 三元组
*/
/************************************************************************/
BOOL IsInIoControlMITMFuzzList(ULONG pid,char *path,char *deviceName,ULONG ioControlCode,IOCONTROL_MITM_FUZZ_INFO ** pTargetFuzzInfo)
//判断是否在链表中
BOOL IsInIoControlMonList(ULONG pid,char *deviceName)
//添加到链表中
BOOL AddIoControlMonItemToList(ULONG pid,char *deviceName,ULONG ioControlCode,ULONG InputBufferLength,ULONG OutputBufferLength)
//获得操作日志
void GetIoControlMonLog(PVOID outputBuffer,ULONG num)
MBehavior.h 定义如下:
/************************************************************************/
/* 遍历所有活着的进程项
如果某个进程没有映射ring3地址 则进行映射
*/
/************************************************************************/
BOOL MapAllProcessMBehaviorList()
/************************************************************************/
/* 添加一个可疑行为项目到可疑行为列表中
*/
/************************************************************************/
NTSTATUS AddMBehaviorItemToList(PROCESS_ITEM *targetProcessItem,MALICIOUS_BEHAVIOR_ITEM * insertMBehaviorItem)
Memory.h 内存操作,定义如下:
///
//
// 功能实现:创建一个可写的内存块MDL
// 输入参数:MemAddress为要创建的块的首地址;
// MdlLength为MDL块的长度
// pMdlPointer为创建的MDL块的指针
// 输出参数:返回MDL指向的内存给的指针
// 备注:用此函数创建可写的MDL块后,需要用FreeWriteMDL()函数释放
///
PVOID
CreateWriteMDL(IN ULONG MemAddress,
IN ULONG MdlLength,
IN OUT PMDL *pMdlPointer
);
///
//
// 功能实现:释放CreateWriteMDL创建的MDL块
// 输入参数:pMappedPointer为MDL块定义的内存块的指针
// pMdlPointer为创建的MDL块的指针
// 输出参数:返回MDL指向的内存给的指针
//
///
VOID
FreeWriteMDL(IN PMDL pMdlPointer,IN PVOID pMappedPointer);
Module.h 定义如下:
/************************************************************************/
/* 从模块列表中找到一个死去的模块
如果找到 返回该模块在列表中的序号
如果没找到 返回-1
*/
/************************************************************************/
int FindADeadModuleFromModuleList(PROCESS_ITEM *targetProcessItem)
/************************************************************************/
/* 根据模块的tid获取该模块对应的模块列表中的指针
如果存在 返回该模块项的指针
如果不存在 返回NULL
*/
/************************************************************************/
MODULE_ITEM * GetModuleItemByModuleBA(PROCESS_ITEM *targetProcessItem,PVOID baseAddress)
/************************************************************************/
/* 将一个模块项目添加到所属进程列表中
*/
/************************************************************************/
NTSTATUS AddModuleItemToList(PROCESS_ITEM *targetProcessItem,MODULE_ITEM * insertModuleItem)
/************************************************************************/
/* 遍历所有活着的进程项
如果某个进程没有映射ring3地址 则进行映射
*/
/************************************************************************/
BOOL MapAllProcessModuleList()
//通过基地址和进程id清除句柄
void KillModuleByModuleBaseAddressAndProcessId(ULONG ProcessId,PVOID BaseAddress)
Net.h 网络操作,定义如下:
///
//
// 功能实现:根据设备名获取文件句柄或文件对象指针
// 输入参数:FileHandle是要输出的文件句柄指针;
// FileObject是要输出的文件对象指针
// DeviceName是要获取设备的设备名
// 输出参数:返回NTSTATUS类型的值
//
///
NTSTATUS
GetObjectByName(OUT HANDLE *FileHandle,OUT PFILE_OBJECT *FileObject,IN WCHAR *DeviceName)
///
//
// 功能实现:枚举网络连接端口信息
// 输入参数:OutLength为输出缓冲区的大小
// PortType为要枚举的端口类型
// TCPPORT-TCP端口
// UDPPORT-UDP端口
// 输出参数:返回NTSTATUS类型的值
//
///
PVOID
EnumPortInformation(OUT PULONG OutLength,IN USHORT PortType)
notify.h 自定义通知,定义如下:
//图片加载通知
void MyImageLoadNotify(IN PUNICODE_STRING FullImageName,
IN HANDLE ProcessId, // Process where image is mapped
IN PIMAGE_INFO ImageInfo);
//创建进程通知
void MyCreateProcessNotify( IN HANDLE ParentId,//父进程pid
IN HANDLE ProcessId,//子进程pid
IN BOOLEAN Create//TRUE表示要创建;FALSE表示要删除
);
//创建线程通知
void MyCreateThreadNotify( IN HANDLE ProcessId,//进程pid
IN HANDLE ThreadId,//线程tid
IN BOOLEAN Create//TRUE表示要创建;FALSE表示要删除
);
PE.h 操作pe结构,定义如下:
//获得头信息
DWORD GetHeaders(PCHAR ibase,
PIMAGE_FILE_HEADER *pfh,
PIMAGE_OPTIONAL_HEADER *poh,
PIMAGE_SECTION_HEADER *psh)
//偏移到相对地址
ULONG Offset2RVA(ULONG Offset,PIMAGE_SECTION_HEADER pSectionHeader,ULONG Sections)
Protect.h 文件保护操作,定义如下:
/************************************************************************/
/* 将防御系统进程的所有线程设置为不可插APC的状态
*/
/************************************************************************/
void SetProcessThreadUnInsertable()
//开启保护:驱动开始初始化保护,并置位保护标志置位为TRUE
NTSTATUS StartProtect()
//关闭保护:不仅要把保护标志置位为FALSE,还要将白名单回写到驱动中,日志依然记录
NTSTATUS ExitProtect()
//监视线程
void MyProcessWatchThread(IN PVOID pContext)
/************************************************************************/
/* 拦截到可疑行为后
增加恶意评分
检查评分是否查过阈值 报警
返回0 表示放行函数的调用
返回1 表示阻止函数的调用
*/
/************************************************************************/
int DoProtect(IN char *hookedFunName,//调用的函数名
IN char *processFullName_c,//进程路径
IN char *processName_noid,//进程名称
IN ULONG currentProcessPID,//进程pid
IN int *score, //恶意评分
OUT NTSTATUS *ntStatus,//返回值
IN char *objectFullName,//操作对象
IN char *behaviorType,//行为类型
IN char *alertInfo,//警示信息
OUT BOOL *isInWhiteList//返回是否在白名单中
)
//获得线程标识
ULONG GetThreadFlagsOffset()
Rami.h 定义如下:
/************************************************************************/
/* 遍历所有活着的进程项
如果某个进程没有映射ring3地址 则进行映射
*/
/************************************************************************/
BOOL MapAllProcessRamiList()
//加入进程衍生物链表
NTSTATUS AddRamiItemToList(PROCESS_ITEM *targetProcessItem,RAMIFICATION_ITEM * insertRamiItem)
//判断是否在进程衍生物链表
BOOL IsInRamiList(PROCESS_ITEM *ProcessItem,RAMIFICATION_ITEM *RamiItem)
//相关文件是否在衍生物链表
BOOL IsFileInRamiList(char *fileFullName_c,ULONG pid)
//清除衍生物链表
void ClearupRamiList(ULONG pid)
Exit.h 定义了退出函数,定义如下:
//退出防御系统
void ExitMySystem(IN PDRIVER_OBJECT pDriverObject)
//初始化防御系统
/************************************************************************/
/* 初始化防御系统
运行在 DriverEntry 函数中
进程上下文:system
*/
/************************************************************************/
NTSTATUS InitMySystem()
sock.h 操作套接字定义
TdiFilter.h 中断描述符过滤
TdiFilter_ConnState.h 中断描述符连接监听
TdiFilter_DispConn.h 定义如下:
int
tdi_connect(PIRP irp, PIO_STACK_LOCATION irps, struct completion *completion);
int
tdi_disconnect(PIRP irp, PIO_STACK_LOCATION irps, struct completion *completion);
void
update_conn_info(PDEVICE_OBJECT devobj, PFILE_OBJECT connobj);
TdiFilter_DispDg.h 终端描述发送与接收封包,定义如下:
int
tdi_send_datagram(PIRP irp, PIO_STACK_LOCATION irps, struct completion *completion);
int
tdi_receive_datagram(PIRP irp, PIO_STACK_LOCATION irps, struct completion *completion);
TdiFilter_DispEv.h 定义如下:
int
tdi_set_event_handler(PIRP irp, PIO_STACK_LOCATION irps, struct completion *completion);
int
tdi_receive(PIRP irp, PIO_STACK_LOCATION irps, struct completion *completion);
TdiFilter_DispObj.h 定义如下:
int
tdi_create(PIRP irp, PIO_STACK_LOCATION irps, struct completion *completion);
NTSTATUS
tdi_create_addrobj_complete(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID Context);
NTSTATUS
tdi_create_addrobj_complete2(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID Context);
int
tdi_cleanup(PIRP irp, PIO_STACK_LOCATION irps, struct completion *completion);
int
tdi_associate_address(PIRP irp, PIO_STACK_LOCATION irps, struct completion *completion);
int
tdi_disassociate_address(PIRP irp, PIO_STACK_LOCATION irps, struct completion *completion);
TdiFilter_DispSr.h 定义如下:
int
tdi_send(PIRP irp, PIO_STACK_LOCATION irps, struct completion *completion);
TdiFilter_EvConn.h 定义如下:
/*
* TDI_EVENT_CONNECT handler
*/
NTSTATUS
tdi_event_connect(
IN PVOID TdiEventContext,
IN LONG RemoteAddressLength,
IN PVOID RemoteAddress,
IN LONG UserDataLength,
IN PVOID UserData,
IN LONG OptionsLength,
IN PVOID Options,
OUT CONNECTION_CONTEXT *ConnectionContext,
OUT PIRP *AcceptIrp)
NTSTATUS
tdi_evconn_accept_complete(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID Context)
/*
* TDI_EVENT_DISCONNECT handler
*/
NTSTATUS
tdi_event_disconnect(
IN PVOID TdiEventContext,
IN CONNECTION_CONTEXT ConnectionContext,
IN LONG DisconnectDataLength,
IN PVOID DisconnectData,
IN LONG DisconnectInformationLength,
IN PVOID DisconnectInformation,
IN ULONG DisconnectFlags)
TdiFilter_EvDg.h 定义如下:
/*
* TDI_EVENT_RECEIVE_DATAGRAM handler
*/
NTSTATUS tdi_event_receive_datagram(
IN PVOID TdiEventContext,
IN LONG SourceAddressLength,
IN PVOID SourceAddress,
IN LONG OptionsLength,
IN PVOID Options,
IN ULONG ReceiveDatagramFlags,
IN ULONG BytesIndicated,
IN ULONG BytesAvailable,
OUT ULONG *BytesTaken,
IN PVOID Tsdu,
OUT PIRP *IoRequestPacket)
TdiFilter_EvRecv.h 定义如下:
/*
* TDI_EVENT_CHAINED_RECEIVE handler
*/
NTSTATUS
tdi_event_chained_receive(
IN PVOID TdiEventContext,
IN CONNECTION_CONTEXT ConnectionContext,
IN ULONG ReceiveFlags,
IN ULONG ReceiveLength,
IN ULONG StartingOffset,
IN PMDL Tsdu,
IN PVOID TsduDescriptor)
TdiFilter_ObjTbl.h 定义如下:
//初始化hash数据单元内存
NTSTATUS
ot_init(void)
//释放hash数据单元内存
void
ot_free(void)
//添加文件对象
NTSTATUS
ot_add_fileobj(PDEVICE_OBJECT devobj, PFILE_OBJECT fileobj, int fileobj_type, int ipproto,
CONNECTION_CONTEXT conn_ctx) // must be called at PASSIVE_LEVEL!
//删除文件对象
NTSTATUS
ot_del_fileobj(PFILE_OBJECT fileobj, int *fileobj_type)
//查找文件对象
struct ot_entry *
ot_find_fileobj(PFILE_OBJECT fileobj, KIRQL *irql)
//清除
void
ot_cleanup_ote(struct ot_entry *ote)
Thread.h 线程操作,定义如下:
/************************************************************************/
/* 从线程列表中找到一个死去的线程
如果找到 返回该线程在列表中的序号
如果没找到 返回-1
*/
/************************************************************************/
int FindADeadThreadFromThreadList(PROCESS_ITEM *targetProcessItem)
/************************************************************************/
/* 根据线程的tid获取该线程对应的线程列表中的指针
如果存在 返回该线程项的指针
如果不存在 返回NULL
*/
/************************************************************************/
THREAD_ITEM * GetThreadItemByThreadTid(PROCESS_ITEM *targetProcessItem,ULONG threadTID)
/* 将一个线程项目添加到所属进程列表中
如果该线程tid对应的线程已经在列表中,则直接覆盖
*/
/************************************************************************/
NTSTATUS AddThreadItemToList(PROCESS_ITEM *targetProcessItem,THREAD_ITEM * insertThreadItem)
/* 获取每个进程的线程列表
初始化时调用
*/
/************************************************************************/
NTSTATUS GetThreadList()
/* 遍历所有活着的进程项
如果某个进程没有映射ring3地址 则进行映射
*/
/************************************************************************/
BOOL MapAllProcessThreadList()
//杀进程
//
void KillThreadByThreadID(ULONG killedThreadPID)
//杀线程
void KillThreadApcRoutine( IN struct _KAPC *Apc, IN OUT PKNORMAL_ROUTINE *NormalRoutine, IN OUT PVOID *NormalContext, IN OUT PVOID *SystemArgument1, IN OUT PVOID *SystemArgument2 )
Virus.h 病毒操作,定义如下:
//功能:把用户对病毒的处理结果,以及病毒的基本信息,保存到病毒信息链表中
//输入:userSelect 用户选择;targetProcessItem 目标进程的Item
//输出:void
//
//
NTSTATUS AddVirusItemTolist(int userSelect,PROCESS_ITEM * targetProcessItem,ULONG virusType)
//根据md5值来判断是否为病毒
BOOL IsMD5InVirusList(char * virusMD5)
White.h 白名单操作,定义如下:
/* 检查一个md5值对应的文件 是否在白名单列表中
*/
/************************************************************************/
BOOL IsInWhiteList(char * md5)
/* 检查一个pid对应的进程文件 是否在白名单列表中
*/
/************************************************************************/
BOOL IsInWhiteListByPid(ULONG pid)
驱动与用户进程的操作接口如下(我们知道进程与驱动的交流有四种方式,下面是用哪种方式呢?):
NTSTATUS DrvDispatchOfBehavior(IN PDEVICE_OBJECT device,IN PIRP Irp)
{
char *thisFunName="DrvDispatchOfBehavior";
PIO_STACK_LOCATION irpStack;//当前的IRP栈
PVOID inputBuffer;//输入缓冲区
PVOID outputBuffer;//输出缓冲区
ULONG inputBufferLength;//输入缓冲区的大小
ULONG outputBufferLength;//输出缓冲区的大小
ULONG ioControlCode;//DeviceIoControl的控制号
PIO_STATUS_BLOCK IoStatus;//IRP的IO状态
ULONG tmpUserAddress;//用户提供的用户空间地址
NTSTATUS ntStatus=STATUS_SUCCESS;//默认返回值
//获取数据
irpStack = IoGetCurrentIrpStackLocation(Irp);//获得IRP Stack
inputBuffer = Irp->AssociatedIrp.SystemBuffer;
inputBufferLength = irpStack->Parameters.DeviceIoControl.InputBufferLength;
outputBuffer = Irp->AssociatedIrp.SystemBuffer;
outputBufferLength = irpStack->Parameters.DeviceIoControl.OutputBufferLength;
ioControlCode = irpStack->Parameters.DeviceIoControl.IoControlCode;
IoStatus=&Irp->IoStatus;
IoStatus->Status = STATUS_SUCCESS; // Assume success
IoStatus->Information = 0; // Assume nothing returned
//检查调用者是否是防御系统进程 如果不是直接返回
if(g_MyProcessPEPROCESS!=0 && IoGetCurrentProcess()!=g_MyProcessPEPROCESS)
{
IoCompleteRequest(Irp,IO_NO_INCREMENT);
return ntStatus;
}
//根据 ioControlCode 完成不同的任务
switch(ioControlCode)
{
//---------------------------------------------------------------------------------------------------------
case IOCTL_BEHAVIORMON_INIT: //开启防御前的准备
{
//获取内核虚拟地址描述
g_dataMemPool_MDL = IoAllocateMdl(g_dataMemPool, sizeof(DATA_MEM_POOL), FALSE, FALSE, NULL);
//将内核虚拟地址描述转换为物理地址描述
MmBuildMdlForNonPagedPool(g_dataMemPool_MDL);
//将分配的内存映射到用户进程地址空间
try
{
g_dataMemPool_UVA = MmMapLockedPages(g_dataMemPool_MDL, UserMode);
}
except(EXCEPTION_EXECUTE_HANDLER){}
//给ring3返回用户态可以访问的虚拟内存地址
*(PULONG)((ULONG)outputBuffer)=(ULONG)g_dataMemPool_UVA;
IoStatus->Information=sizeof(ULONG);
KdPrint(("[%s] 共享内存 内核态地址=0x%08X\n",thisFunName,g_dataMemPool));
KdPrint(("[%s] 共享内存 用户态地址=0x%08X\n",thisFunName,*(PULONG)((ULONG)outputBuffer)));
//初次枚举进程 存入进程列表中 并初始化关联的 线程列表 和 模块列表
GetProcessList(); //获取数据 并映射ring3地址
GetThreadList(); //获取数据 不映射ring3地址
GetModuleList(); //获取数据 不映射ring3地址
break;
}
case IOCTL_BEHAVIORMON_EXIT: //关闭防御后的处理
{
if(g_dataMemPool_UVA && g_dataMemPool_MDL)
{
KdPrint(("[%s] ring3已注销掉共享内存的用户态地址!\n",thisFunName));
MmUnmapLockedPages(g_dataMemPool_UVA,g_dataMemPool_MDL);
IoFreeMdl(g_dataMemPool_MDL);
g_dataMemPool_MDL=NULL;
g_dataMemPool_UVA=NULL;
}
break;
}
//---------------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------------
case IOCTL_BEHAVIORMON_STARTPROTECT://开启主动防御保护
{
if(!g_IsProtect)
{
//开启主动防御保护
StartProtect();
}
break;
}
case IOCTL_BEHAVIORMON_EXITPROTECT: //关闭主动防御保护
{
if(g_IsProtect)
{
//关闭主动防御保护
ExitProtect();
}
break;
}
//---------------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------------
case IOCTL_BEHAVIORMON_MAP_PROCESS_LIST://更新进程列表
{
//刷新每个进程的线程
GetProcessList();
//刷新线程列表并映射ring3地址
GetThreadList();
MapAllProcessThreadList();
//刷新模块列表并映射ring3地址
GetModuleList();
MapAllProcessModuleList();
break;
}
case IOCTL_BEHAVIORMON_MAP_RAMI_LIST://更新进程的衍生物列表
{
MapAllProcessRamiList();
break;
}
case IOCTL_BEHAVIORMON_MAP_MBEHAVIOR_LIST://更新进程的可疑行为列表
{
MapAllProcessMBehaviorList();
break;
}
//---------------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------------
case IOCTL_BEHAVIORMON_MAP_THREAD_LIST://更新线程列表
{
//刷新每个进程的线程
GetThreadList();
//映射每个进程线程列表的ring3地址 如果已经映射过,就不需要再次映射
MapAllProcessThreadList();
break;
}
case IOCTL_BEHAVIORMON_KILLTHREAD://用户在工具中选择要kill的进程
{
KillThreadByThreadID(*(ULONG *)inputBuffer);
break;
}
//---------------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------------
case IOCTL_BEHAVIORMON_MAP_MODULE_LIST://更新模块列表
{
//刷新每个模块的线程
GetModuleList();
//映射每个进程模块列表的ring3地址 如果已经映射过,就不需要再次映射
MapAllProcessModuleList();
break;
}
case IOCTL_BEHAVIORMON_KILLMODULE://用户在工具中选择要kill的进程
{
KillModuleByModuleBaseAddressAndProcessId(*(ULONG *)inputBuffer,*(PVOID *)((ULONG)inputBuffer+4));
break;
}
//---------------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------------
case IOCTL_BEHAVIORMON_START_LOG: //启动行为日志记录
{
g_IsLogBehavior=TRUE;
break;
}
case IOCTL_BEHAVIORMON_STOP_LOG: //停止行为日志记录
{
g_IsLogBehavior=FALSE;
break;
}
//---------------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------------
case IOCTL_BEHAVIORMON_HOOK://Hook SSDT和SSDT Shadow
{
SSDTHook(inputBuffer);
//SSDT_ShadowHook();
break;
}
case IOCTL_BEHAVIORMON_SAMEWIN32FUNADD://前台告诉驱动的几个Win32函数地址
{
if(*(DWORD *)inputBuffer!=0)
{
g_WinExec=*(DWORD *)inputBuffer;
}
break;
}
//---------------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------------
case IOCTL_BEHAVIORMON_PROC: //指定要单独行为的某个程序路径
{
break;
}
//---------------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------------
case IOCTL_BEHAVIORMON_GETDIRINFO://获取某文件夹下的文件信息
{
PCHAR ioDirName=NULL;
PVOID pDirInfo=NULL;
ULONG dwRetSize=0;
if (!inputBuffer||inputBufferLength<3||(outputBufferLength<sizeof(DIRECTORY_INFO)))
{
KdPrint(("传入的参数错误\n"));
ntStatus=STATUS_INVALID_PARAMETER;
break;
}
ioDirName=(PCHAR)inputBuffer;
KdPrint(("枚举文件夹%s\n",ioDirName));
pDirInfo=GetDirectory(ioDirName,&dwRetSize);
RtlCopyMemory(outputBuffer,pDirInfo,dwRetSize);
SafeExFreePool(pDirInfo);
Irp->IoStatus.Information = dwRetSize;
break;
}
case IOCTL_BEHAVIORMON_GETDIRNUMINFO://获取某文件夹下文件信息的总缓冲长度
{
PCHAR ioDirName=NULL;
PVOID pDirInfo=NULL;
ULONG dwRetSize=0;
ULONG Num=0;
if (!inputBuffer||inputBufferLength<3||(outputBufferLength<sizeof(ULONG)))
{
KdPrint(("传入的参数错误\n"));
ntStatus=STATUS_INVALID_PARAMETER;
break;
}
ioDirName=inputBuffer;
pDirInfo=GetDirectory(ioDirName,&dwRetSize);
Num=dwRetSize/sizeof(DIRECTORY_INFO);
RtlCopyMemory(outputBuffer,&Num,sizeof(ULONG));
SafeExFreePool(pDirInfo);
Irp->IoStatus.Information = sizeof(ULONG);
break;
}
case IOCTL_BEHAVIORMON_KILLFILE://强行删除文件
{
DELETE_INFO Delete_Info;
if(!inputBuffer||inputBufferLength<3||outputBufferLength<sizeof(Delete_Info))
{
KdPrint(("输入的删除文件名错误\n"));
ntStatus=STATUS_INVALID_PARAMETER;
break;
}
KdPrint(("删除文件%s\n",(PCHAR)inputBuffer));
Delete_Info.IsDelete=DeleteFile((PCHAR)inputBuffer);
RtlCopyMemory(outputBuffer,&Delete_Info,sizeof(Delete_Info));
Irp->IoStatus.Information = sizeof(Delete_Info);
break;
}
case IOCTL_BEHAVIORMON_DELETE_FILE://强行删除文件
{
DeleteFile(inputBuffer);
break;
}
case IOCTL_BEHAVIORMON_CHANGEHANDLE://修改句柄
{
HANDLE Handle;
ACCESS_MASK GrantedAccess;
if(!inputBuffer||inputBufferLength<sizeof(HANDLE)+sizeof(ACCESS_MASK))
{
KdPrint(("输入参数错误\n"));
ntStatus=STATUS_INVALID_PARAMETER;
break;
}
Handle = *(HANDLE*)inputBuffer;
GrantedAccess = *(ACCESS_MASK*)((PUCHAR)inputBuffer + sizeof(HANDLE));
if(Handle==NULL)
{
KdPrint(("输入句柄无效\n"));
ntStatus=STATUS_INVALID_PARAMETER;
break;
}
KdPrint(("修改句柄\n"));
if(!SetHandleAccess(Handle, GrantedAccess))
{
KdPrint(("修改句柄属性失败\n"));
ntStatus=STATUS_UNSUCCESSFUL;
}
break;
}
//---------------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------------
case IOCTL_BEHAVIORMON_KILL://在拦截到可疑行为后,用户选择kill进程,杀死进程及其儿子进程
{
if(g_KilledProcessPID!=-1)
{
Sleep(500);//?? DPC
//UpdateProcessList();
KillProcessFamilyByProcessID(g_KilledProcessPID);
g_KilledProcessPID=-1;
}
break;
}
case IOCTL_BEHAVIORMON_KILLPROCESS://用户在工具中选择要kill的进程
{
KillProcessByProcessID(*(ULONG *)inputBuffer);
break;
}
case IOCTL_BEHAVIORMON_KILLPROCESS_PVASE://用户在工具中选择要kill的进程
{
killbyPVASE(*(ULONG *)inputBuffer);
break;
}
//---------------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------------
case IOCTL_BEHAVIORMON_GETSTATS: //获取当前统计数据
{
GetLogStats(outputBuffer,outputBufferLength,IoStatus);
break;
}
case IOCTL_BEHAVIORMON_ZEROSTATS: //清空当前日志缓冲区
{
ZeroLogStats();
break;
}
//---------------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------------
case IOCTL_BEHAVIORMON_GETCURRENTISPOP: //获取当前设置的是否弹出可疑行为对话框
{
if(g_IsPopAlertDialog)
*(DWORD *)outputBuffer=1;
else
*(DWORD *)outputBuffer=0;
IoStatus->Information = 4;
break;
}
case IOCTL_BEHAVIORMON_SETCURRENTISPOP: //设置当前的是否弹出可疑行为对话框
{
if(*(DWORD *)outputBuffer==1)
g_IsPopAlertDialog=TRUE;
else
g_IsPopAlertDialog=FALSE;
break;
}
//---------------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------------
case IOCTL_BEHAVIORMON_GETSSDTINFO: //获取ssdt
{
ULONG DataLen=0;
ULONG NumOfService=GetSSDTServiceNum();
DataLen=NumOfService*sizeof(SSDTINFO);
//如果是请求大小
if(outputBufferLength<DataLen)
{
if(outputBufferLength==sizeof(ULONG))
{
*((PULONG)outputBuffer)=NumOfService;
Irp->IoStatus.Information =sizeof(ULONG);
break;
}
ntStatus = STATUS_BUFFER_TOO_SMALL;
break;
}
//如果是请求数据
NumOfService=EnumSSDTServiceAdd((PSSDTINFO)outputBuffer,&DataLen);
if(!NumOfService)
{
ntStatus = STATUS_UNSUCCESSFUL;
}
Irp->IoStatus.Information = NumOfService*sizeof(SSDTINFO);
break;
}
case IOCTL_BEHAVIORMON_RESTORESSDTITEM://恢复SSDT
{
if(!inputBuffer||inputBufferLength<sizeof(SSDTINFO))
{
KdPrint(("输入缓冲区或输入长度无效!\n"));
ntStatus = STATUS_UNSUCCESSFUL;
break;
}
//KdPrint(("Index=%d\tOriginAdd=0x%08X\n",*(ULONG*)inputBuffer,*(ULONG*)((ULONG)inputBuffer+4)));
if(!RestoreSSDTItem((PSSDTINFO)inputBuffer))
{
KdPrint(("恢复失败!\n"));
ntStatus = STATUS_UNSUCCESSFUL;
}
break;
}
case IOCTL_BEHAVIORMON_GETSHADOWSSDTINFO://获取Shadow SSDT
{
ULONG NumOfService=GetNumOfShadowSSDT();
ULONG DataLen=0;
ULONG SysMajor=0;
PsGetVersion(&SysMajor,NULL,NULL,NULL);
DataLen=NumOfService*sizeof(SSDTINFO);
KdPrint(("获取SHADOW SSDT表信息\n"));
//如果是请求大小
if(outputBufferLength<DataLen)
{
KdPrint(("服务函数个数=%ld\n",NumOfService));
if(outputBufferLength==sizeof(ULONG))
{
*((PULONG)outputBuffer)=NumOfService;
Irp->IoStatus.Information =sizeof(ULONG);
break;
}
ntStatus = STATUS_BUFFER_TOO_SMALL;
break;
}
//如果是请求数据
if(!g_CsrssPEPROCESS)
{
if(SysMajor!=6)
{
NTSTATUS CsrntStatus=STATUS_SUCCESS;
CsrntStatus=PsLookupProcessByProcessId((PVOID)GetCsrPid(),&g_CsrssPEPROCESS);
if (!NT_SUCCESS(CsrntStatus))
{
KdPrint(("获取CSRSS.EXE进程EPROCESS指针失败\n"));
g_CsrssPEPROCESS=NULL;
ntStatus = STATUS_UNSUCCESSFUL;
break;
}
}
}
if(SysMajor!=6)//??
{
KeAttachProcess(g_CsrssPEPROCESS);
}
NumOfService=EnumShadowSSDTFunAdd((PSSDTINFO)outputBuffer,&DataLen);
if(!NumOfService)
{
KdPrint(("服务函数个数=%ld\n",NumOfService));
ntStatus = STATUS_UNSUCCESSFUL;
}
Irp->IoStatus.Information = DataLen;
if(SysMajor!=6)
{
KeDetachProcess();
}
break;
}
case IOCTL_BEHAVIORMON_RESTORESHADOWSSDTITEM://恢复Shadow SSDT
{
if(!inputBuffer||inputBufferLength<sizeof(SSDTINFO))
{
KdPrint(("输入缓冲区或输入长度无效!\n"));
ntStatus = STATUS_UNSUCCESSFUL;
break;
}
if(!RestoreShadowSSDTItem((PSSDTINFO)inputBuffer,g_CsrssPEPROCESS))
{
KdPrint(("恢复失败!\n"));
ntStatus = STATUS_UNSUCCESSFUL;
}
break;
}
//---------------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------------
case IOCTL_BEHAVIORMON_GETIDTINFO://获取IDT信息
{
USHORT IDTLimit=0;
if(!outputBuffer || outputBufferLength<MAX_IDT*sizeof(IDTGD))
{
KdPrint(("缓冲区小于%ld\n",MAX_IDT*sizeof(IDTGD)));
ntStatus=STATUS_BUFFER_OVERFLOW;
break;
}
IDTLimit=GetIDTInfo(outputBuffer);
Irp->IoStatus.Information=IDTLimit*sizeof(IDTGD);
break;
}
//---------------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------------
case IOCTL_BEHAVIORMON_GETGDTINFO://获取GDT信息
{
USHORT GDTLimit=0;
if(!outputBuffer || outputBufferLength<MAX_GDT*sizeof(GDTGD))
{
KdPrint(("缓冲区小于%ld\n",MAX_GDT*sizeof(GDTGD)));
ntStatus=STATUS_BUFFER_OVERFLOW;
break;
}
GDTLimit=GetGDTInfo(outputBuffer);
Irp->IoStatus.Information=GDTLimit*sizeof(GDTGD);
break;
}
//---------------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------------
case IOCTL_BEHAVIORMON_GETFSDROUTINEADD://获取FSD例程函数地址
{
BOOLEAN Typeflag=TRUE;
if(!inputBuffer||inputBufferLength<sizeof(ULONG))
{
KdPrint(("输入缓冲区或输入长度无效!\n"));
ntStatus = STATUS_UNSUCCESSFUL;
break;
}
if(!outputBuffer||outputBufferLength<sizeof(ULONG)*MAX_FSDMJ_ROUTINE)
{
KdPrint(("输出缓冲区或输出长度无效!\n"));
ntStatus = STATUS_UNSUCCESSFUL;
break;
}
if(*((PULONG)inputBuffer)==1)
{
KdPrint(("获取FAT文件系统派遣函数地址\n"));
Typeflag=TRUE;
}
else if(*((PULONG)inputBuffer)==2)
{
KdPrint(("获取NTFS文件系统派遣函数地址\n"));
Typeflag=FALSE;
}
else
{
KdPrint(("输入参数错误!\n"));
ntStatus = STATUS_UNSUCCESSFUL;
break;
}
if(!EnumFileSystemDriverRoutine((PULONG)outputBuffer,Typeflag))
{
KdPrint(("获取FSD Routine地址失败!\n"));
ntStatus = STATUS_UNSUCCESSFUL;
}
else
{
Irp->IoStatus.Information =sizeof(ULONG)*MAX_FSDMJ_ROUTINE;
}
break;
}
case IOCTL_BEHAVIORMON_RESTOREFSDADDITEM://恢复FSD地址
{
BOOLEAN Typeflag=TRUE;
PFSDNOTE fsdnote=NULL;
if(!inputBuffer||inputBufferLength<sizeof(FSDNOTE))
{
KdPrint(("输入缓冲区或输入长度无效!\n"));
ntStatus = STATUS_UNSUCCESSFUL;
break;
}
fsdnote=(PFSDNOTE)inputBuffer;
if(fsdnote->Type==1)
{
KdPrint(("恢复FAT文件系统派遣函数地址\n"));
Typeflag=TRUE;
}
else if(fsdnote->Type==2)
{
KdPrint(("恢复NTFS文件系统派遣函数地址\n"));
Typeflag=FALSE;
}
else
{
KdPrint(("输入参数错误!\n"));
ntStatus = STATUS_UNSUCCESSFUL;
break;
}
if(!RestoreFileSystemDriverRoutine(*fsdnote,Typeflag))
{
KdPrint(("恢复FSD Routine地址失败!\n"));
ntStatus = STATUS_UNSUCCESSFUL;
}
else
{
Irp->IoStatus.Information =0;
}
break;
}
//---------------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------------
case IOCTL_BEHAVIORMON_ENUMTCP://枚举TCP连接
{
PVOID pOut=NULL;
ULONG OutLen=0;
if(outputBufferLength<sizeof(CONNINFO102))
{
KdPrint(("输出缓冲区长度无效\n"));
ntStatus=STATUS_BUFFER_OVERFLOW;
break;
}
pOut=EnumPortInformation(&OutLen,TCPPORT);
if(!pOut)
{
KdPrint(("获取TCP端口信息失败!\n"));
ntStatus=STATUS_UNSUCCESSFUL;
break;
}
if(outputBufferLength<OutLen)
{
KdPrint(("输出缓冲区太小,应为%ld\n",OutLen));
ExFreePool(pOut);
ntStatus=STATUS_BUFFER_OVERFLOW;
break;
}
RtlCopyMemory(outputBuffer,pOut,OutLen);
ExFreePool(pOut);
Irp->IoStatus.Information = OutLen;
break;
}
case IOCTL_BEHAVIORMON_ENUMUDP://枚举UDP连接
{
PVOID pOut=NULL;
ULONG OutLen=0;
if(outputBufferLength<sizeof(UDPCONNINFO))
{
KdPrint(("输出缓冲区长度无效\n"));
ntStatus=STATUS_BUFFER_OVERFLOW;
break;
}
pOut=EnumPortInformation(&OutLen,UDPPORT);
if(!pOut)
{
KdPrint(("获取UDP端口信息失败!\n"));
ntStatus=STATUS_UNSUCCESSFUL;
break;
}
if(outputBufferLength<OutLen)
{
KdPrint(("输出缓冲区太小,应为%ld\n",OutLen));
ExFreePool(pOut);
ntStatus=STATUS_BUFFER_OVERFLOW;
break;
}
RtlCopyMemory(outputBuffer,pOut,OutLen);
ExFreePool(pOut);
Irp->IoStatus.Information = OutLen;
break;
}
//---------------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------------
case IOCTL_BEHAVIORMON_DISPLAY_WHITE_PROCESS_BEHAVIOR://设置显示白名单程序行为
{
g_isDisplayWhiteProcessBehavior=TRUE;
break;
}
case IOCTL_BEHAVIORMON_UNDISPLAY_WHITE_PROCESS_BEHAVIOR://设置不显示白名单程序行为
{
g_isDisplayWhiteProcessBehavior=FALSE;
break;
}
//---------------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------------
case IOCTL_BEHAVIORMON_GET_DRIVERS_LEN://获取驱动对象个数
{
EnumDriverObject((PULONG)outputBuffer,NULL);
Irp->IoStatus.Information = sizeof(ULONG);
break;
}
case IOCTL_BEHAVIORMON_GET_DRIVERS_DATA://获取驱动对象数据
{
ULONG nDrivers=0;
EnumDriverObject(&nDrivers,NULL);
if(outputBufferLength>=nDrivers*sizeof(DriverInfo))
{
EnumDriverObject(NULL,outputBuffer);
Irp->IoStatus.Information = nDrivers*sizeof(DriverInfo);
}
else
{
Irp->IoStatus.Information = 0;
}
break;
}
case IOCTL_BEHAVIORMON_GET_DEVICES_LEN://获取某个驱动对象下的设备对象个数
{
if(inputBufferLength==sizeof(PVOID))
{
EnumDeviceObject((PULONG)outputBuffer,NULL,*(PDRIVER_OBJECT*)inputBuffer);
Irp->IoStatus.Information = sizeof(ULONG);
}
break;
}
case IOCTL_BEHAVIORMON_GET_DEVICES_DATA://获取某个驱动对象下的设备对象数据
{
if(inputBufferLength==sizeof(PVOID))
{
ULONG nDevices=0;
EnumDeviceObject(&nDevices,NULL,*(PDRIVER_OBJECT*)inputBuffer);
if(outputBufferLength>=nDevices*sizeof(DeviceInfo))
{
EnumDeviceObject(NULL,outputBuffer,*(PDRIVER_OBJECT*)inputBuffer);
Irp->IoStatus.Information = nDevices*sizeof(DeviceInfo);
}
else
{
Irp->IoStatus.Information = 0;
}
}
break;
}
//---------------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------------
case IOCTL_BEHAVIORMON_IOCONTROL_MITM_FUZZ_NUM:
{
if(inputBufferLength==sizeof(g_IoControlMITMFuzzInfosNum))
{
g_IoControlMITMFuzzInfosNum=*(PULONG)inputBuffer;
}
break;
}
case IOCTL_BEHAVIORMON_IOCONTROL_MITM_FUZZ_DATA:
{
if(inputBufferLength==MAX_IOCONTOL_MITM_FUZZ_NUM*sizeof(IOCONTROL_MITM_FUZZ_INFO))
{
memcpy(g_IoControlMITMFuzzInfos,inputBuffer,inputBufferLength);
}
break;
}
case IOCTL_BEHAVIORMON_IOCONTROL_MITM_FUZZ_START:
{
g_IsIoControlMITMFuzz=TRUE;
break;
}
case IOCTL_BEHAVIORMON_IOCONTROL_MITM_FUZZ_PAUSE:
{
g_IsIoControlMITMFuzz=FALSE;
break;
}
//---------------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------------
case IOCTL_BEHAVIORMON_IOCONTROL_MON_PROCESS:
{
if(inputBufferLength>=sizeof(ULONG))
{
g_IoControlMonProcessNum=inputBufferLength/sizeof(ULONG);
memcpy(g_IoControlMonProcessPids,inputBuffer,inputBufferLength);
}
break;
}
case IOCTL_BEHAVIORMON_IOCONTROL_MON_START:
{
g_IsIoControlMon=TRUE;
break;
}
case IOCTL_BEHAVIORMON_IOCONTROL_MON_PAUSE:
{
g_IsIoControlMon=FALSE;
break;
}
case IOCTL_BEHAVIORMON_IOCONTROL_MON_GET_LOG_NUM:
{
if(outputBufferLength==sizeof(ULONG))
{
*(PULONG)outputBuffer=g_IoControlMonNum;
Irp->IoStatus.Information = outputBufferLength;
}
break;
}
case IOCTL_BEHAVIORMON_IOCONTROL_MON_GET_LOG_DATA:
{
GetIoControlMonLog(outputBuffer,outputBufferLength/sizeof(IOCONTROL_MON_INFO));
Irp->IoStatus.Information = outputBufferLength;
break;
}
//---------------------------------------------------------------------------------------------------------
}
//返回
IoStatus->Status = ntStatus;
IoCompleteRequest(Irp,IO_NO_INCREMENT);
return ntStatus;
}
学习的目标是成熟!~~~~~