金山卫士开源软件之旅(十) KSafeMainproject的分析 1
上一次看金山开源到如今已有一两个月了。期间看到QQ群里大家对它非常是热情。
近期有时间想看看金山的主界面projectKSafeMain,自己水平有限,总结的东西浅显。但还是愿意拿来与大家分享。希望对大家有帮助。
转载请标明是引用于 http://blog.csdn.net/chenyujing1234
欢迎大家提出问题讨论。
1、超链接的增加
上图中红色标注的地方就是超链接的地方。
它的实现是在dlgfile_header.xml文件里。
eg:
求助这个button:
<link class="linktext5" pos="-238,6" href="http://www.ijinshan.com/safe/help.html?fr=client" crtext="FFFFFF">求助</link>
标红色的部分表此控制的类型为 linktext5,它是定义在def_style.xml文件里.
通过cursor节点的属性实现放上去有手的开关的功能。
那么是哪里调用了此文件里呢?
在bkwinres.rc2中有
即,我们把此文件定义为509了。
而在dlg_main.xml中对调用了ID为509的XML文件
2、修复漏洞的实现
2、1 界面创建方法
首先绑定dlg_main.xml里的 <tabctrl id="136"
在bkwinres.h中有
#define IDC_TAB_MAIN 136
在beikesafemaindlg.h中有
BK_NOTIFY_MAP(IDC_RICHVIEW_WIN)
//BK_NOTIFY_ID_COMMAND(IDCANCEL, OnBkBtnClose)
BK_NOTIFY_ID_COMMAND(IDC_BTN_SYS_CLOSE, OnBkBtnClose)
BK_NOTIFY_ID_COMMAND(IDC_BTN_SYS_MAX, OnBkBtnMax)
BK_NOTIFY_ID_COMMAND(IDC_BTN_SYS_MIN, OnBkBtnMin)
BK_NOTIFY_TAB_SELCHANGE(IDC_TAB_MAIN, OnBkTabMainSelChange)
BK_NOTIFY_MAP_END()
BOOL CBeikeSafeMainDlg::OnBkTabMainSelChange(int nTabItemIDOld, int nTabItemIDNew)
{ DEBUG_TRACE(L"Tab Change %d, %d\r\n", nTabItemIDOld, nTabItemIDNew); BOOL bRet = FALSE; if (m_bFirstPageChange)
{
if (0 != nTabItemIDNew)
{
PostMessage(MSG_APP_DELAY_EXAM, FALSE);
} m_bFirstPageChange = FALSE;
} bRet = TRUE;
switch (nTabItemIDNew)
{
case 0:
if (m_bPage0NeverShowed)
{
PostMessage(MSG_APP_DELAY_NAVIGATE_IE);
PostMessage(MSG_APP_DELAY_EXAM, TRUE); m_bPage0NeverShowed = FALSE;
} break; case 1:
break; case 2:
break;
case 3: // 修复漏洞
m_viewVulfix.ShowWindow(SW_SHOW);
if(!m_bVulfixInited || m_bVulfixRescanRequired)
{
BOOL toRescan = TRUE;
if(m_bVulfixRescanRequired && theEngine && theEngine->m_isRepairing)
{
toRescan = FALSE;
}
m_bVulfixInited = TRUE;
m_bVulfixRescanRequired = FALSE;
if(toRescan)
m_viewVulfix.m_viewSoftVul.InitEnv();
}
break;
case 4://系统优化
case 5://清理
case 6://网盾
case 8:// 打开软件管理
default:
break;
} return TRUE;
}
能够得知近好改动漏洞后进入的case是:
case 3:
处理的第一条是 m_viewVulfix.ShowWindow(SW_SHOW);
m_viewVulfix是CBeikeSafeMainDlg中的成员:
// 修复漏洞页面里的view
CEmbeddedView m_viewVulfix;
CEmbeddedView也CBeikeSafeMainDlg一样都是继承自CBkDialogViewImpl。
每一个CBkDialogViewImpl的实例中都有三个成员,各自是m_bkHeader、m_bkBody和m_bkFooter,它们分别代表窗体的头部、中间和底部,
它们各自界面元素的载入是在 CBkDialogViewImpl::Load 。
它的类定义非常easy:
class CEmbeddedView
: public CBkDialogViewImpl<CEmbeddedView>
, public CIconAnimate<CEmbeddedView>
{
public:
// 做漏洞扫描动作的类
CBeikeVulfixHandler m_viewSoftVul;
那么m_viewVulfix是在哪里创建的呢?
(1) CBeikeSafeMainDlg::OnInitDialog 的一開始就初始化了这个变量
BOOL CBeikeSafeMainDlg::OnInitDialog(CWindow /*wndFocus*/, LPARAM /*lInitParam*/)
{ SetIcon(::LoadIcon((HMODULE)&__ImageBase, MAKEINTRESOURCE(IDI_BEIKESAFE)));
SetIcon(::LoadIcon((HMODULE)&__ImageBase, MAKEINTRESOURCE(IDI_SMALL)), FALSE); _Module.SetActiveWindow(m_hWnd);
// 创建修复漏洞页面的view
InitVulFix();
它主要是载入界面元素,并创建list控件.
void CBeikeSafeMainDlg::InitVulFix()
{
// 创建 m_viewVulfix 窗体
m_viewVulfix.Create(GetViewHWND(), NULL, WS_CHILD|WS_CLIPCHILDREN, 0, 3000);
// 从 dlg_vul_main.xml 文件里载入控件
ATLVERIFY( m_viewVulfix.Load( IDR_BK_VULDLG_MAIN ) );
// 设置修复漏洞处理逻辑类m_viewSoftVul的父窗体
m_viewVulfix.m_viewSoftVul.SetMainDlg( this );
// 创建列名为:严重程序、补丁名称、补丁描写叙述、发面日期、状态的列表控件
m_viewVulfix.Init(m_hWnd);
}
(2) dlg_vul_main.xml文件分析
主要分为两大部分:
扫描或修复状态、扫描结果.
从XML文件里能够看到 扫描中与repairing是同一块,临时把repairing隐藏起来。
repairing有五个部分:
2、2 button处理函数的实现
扫描结果显示的效果图是:
在 case 3:的处理中显示完界面后主要就是调用扫描漏洞的工作:
if(toRescan)
m_viewVulfix.m_viewSoftVul.InitEnv();
它主要完毕 :
初始化扫描引擎;
载入ksafevul.dll中的API函数, 创建CVulEngine中的IVulEnvironment 接口;
解发開始扫描的消息。
void CBeikeVulfixHandler::InitEnv()
{
if(!theEngine)
{
// 初始化扫描引擎
theEngine = new CVulEngine;
// 载入ksafevul.dll中的API函数, 创建CVulEngine中的IVulEnvironment 接口
theEngine->_InitFunctions(); m_WinInfo.Init();
//m_WinInfo64 = IsWin64();
}
// 解发開始扫描的消息
PostMessage( WMH_SCAN_START, 0, 0);
}
(2、2、1)非常多人反映ksafevul.dll 载入不到。此dll的得到金山是提供源代码的。
大家能够用VS2005打开 beikesafevul.sln
(2、2、1、1)首先编译BeikeUtilsproject。
会出现下面报错:
1>d:\自己的经验总结\自己的经验总结\金山开源\oss\pcmanager\src\publish\common/registrywow.h(18) : error C2146: 语法错误 : 缺少“;”(在标识符“OpenKeyEx”的前面)
1>d:\自己的经验总结\自己的经验总结\金山开源\oss\pcmanager\src\publish\common/registrywow.h(18) : error C4430: 缺少类型说明符 - 假定为 int。注意: C++ 不支持默认 int
1>d:\自己的经验总结\自己的经验总结\金山开源\oss\pcmanager\src\publish\common/registrywow.h(19) : error C4430: 缺少类型说明符 - 假定为 int。注意: C++ 不支持默认 int
解决方法请參考我的还有一篇文章:(里面有相同的出错的处理)
(2、2、1、2) 其他的project都顺利编译通过,仅仅有两个projectksafevul、VulfixLib出现报错:
envutils.h(428) : error C3861: “IsWin64”: 找不到标识符
它是用来推断系统是不是64位用的。
既然源代码没有提供此函数,那么我们自己来实现吧:
考虑到调用到此函数的cpp文件都包括了BeikeUtils.h文件,我决定在BeikeUtils 中加入此函数体
BeikeUtils.h中加入
// 推断是不是64位的系统
// 返回值: TRUE 是64位系统;FALSE 不是64位系统
BOOL IsWin64();
BeikeUtils.cpp里加入
BOOL IsWin64()
{
#define IS_64BIT_OS (sizeof(void *) == 8)
return IS_64BIT_OS;
}
ksafevulproject编译通过后就生成了ksafevul.dll.这样大家就能够调试扫描漏洞与修复漏洞的过程了。
(2、2、2) WMH_SCAN_START消息的回调函数例如以下:
void CBeikeVulfixHandler::OnBkBtnScan()
{
if(m_firstInited)
{
// Clean downloaded files
BOOL bSave = BKSafeConfig::Get_Vulfix_SaveDownFile();
if( !bSave )
theEngine->m_fixLog.CleanFiles(FALSE, NULL);
m_firstInited = FALSE;
SetItemVisible(1015, !theEngine->IsSystemSupported());
}
// 把扫描结果列表清空
ResetListCtrl(m_wndListCtrlVul);
// 调用引擎起一线程開始扫描
if( theEngine->ScanVul( m_RefWin.m_hWnd ) )
{
// 界面处理
m_dwScanBeginTime = GetTickCount();
m_bScanStarted = FALSE; m_nScanState = 0;
m_nTotalItem = 0;
m_nCurrentItem = 0;
_SetDisplayState(SCANSTATE_SCANNING);
_SetScanProgress( 0 );
m_RefWin.SetTimer(0, 200, NULL);
m_wndListCtrlVul.SetEmptyString(BkString::Get(IDS_VULFIX_5027));
m_RefWin.StartIconAnimate( IDC_IMG_VULFIX_SCAN_ANIMATION, IDC_PROGRESS_VULFIX_SCANNING, 300);
SetItemDWordAttribute(IDC_PROGRESS_VULFIX_SCANNING, "showpercent", 0);
}
}
以上基本的工作是调用ScanVul创建一线程完毕扫描
bool CVulEngine::ScanVul(HWND hWnd)
{
if(m_hThreadVulScan)
_SafeTerminateThread( m_hThreadVulScan, FALSE ); m_bVulScanCanceled = FALSE;
m_hThreadVulScan = CreateThread(NULL, 0, ThreadFunc_Scan, (void*)hWnd, 0, NULL);
return m_hThreadVulScan!=NULL;
}
DWORD WINAPI CVulEngine::ThreadFunc_Scan( LPVOID lpParam )
{
HWND hWnd = (HWND)lpParam;
theEngine->_ScanVul(hWnd);
return 0;
}
void CVulEngine::_ScanVul(HWND hWnd)
{
DWORD dwFlags = _GetScanFlags();
CWindowVulfixObserver observer( hWnd);
if(!m_pVulScan)
// 创建扫描组件IVulfix
m_pVulScan = CreateVulFix(); HRESULT hr = E_POINTER;
if(m_pVulScan)
{
// 设计扫描组件的观察者对象
m_pVulScan->SetObserver(&observer);
// 运行扫描(要持续一段时间)
hr = m_pVulScan->Scan(dwFlags);
DEBUG_TRACE(_T("CVulEngine::_ScanVul ScanVul %x(%x) \n"), hr, dwFlags);
m_pVulScan->SetObserver(NULL);
}
// 通知扫描完毕
_RelayMessage(hWnd, WMH_SCAN_DONE, m_bVulScanCanceled, hr);
}
(2、2、3) DLL也载入到了,为什么修复漏洞不是没有扫描的结果呢。
我也被这个问题困扰着,从KSafeMainproject中我们仅仅能知道
hr = m_pVulScan->Scan(dwFlags);
返回了失败.所以没有扫描结果。
但原因是什么呢?我决定对此打破砂锅。
(2、2、3、1)Scan的实如今VulfixLIbproject中(在上面的(2、2、1)中讲到)
说是扫描,事实上是 从数据库文件 office64.dat、office.dat、soft.dat、system64.dat、system.dat中读取漏洞列表
看到这里更坚定了我对对金山的开源的失望是对的。
// 从数据库文件 office64.dat、office.dat、soft.dat、system64.dat、system.dat中读取漏洞列表
HRESULT CImplVulfix::Scan(DWORD dwFlags)
{
TIME_CHECK( _T("CImplVulfix::Scan ") );
m_Canceled = FALSE;
T_ComInit __init__com__;
HRESULT hr ;
do
{
// 把数据库和补丁列表清除
Reset();
GetLangID(); CSysEnv& sysEnv = singleton<CSysEnv>::Instance();
sysEnv.Init();
if( FAILED( hr=sysEnv.IsSupported(FALSE) ) )
break; Init();
m_objIgnore.LoadIgnoreDB(); CString filenameSystem, filenameOffice, filenameSoft;
GetXmlDBFileName(VTYPE_WINDOWS, filenameSystem, IsWin64());
GetXmlDBFileName(VTYPE_OFFICE, filenameOffice, FALSE);
GetXmlDBFileName(VTYPE_SOFTLEAK, filenameSoft, FALSE);
if( !PathFileExists(filenameSystem) && !PathFileExists(filenameOffice) && !PathFileExists(filenameSoft) )
{
hr = KERR_LOAD_FILE;
break;
}
// 创建OS Filter
m_pFilterOS = CreateOSFilter(sysEnv.m_WinVer, dwFlags);
// 初始化OS Filter
InitOSFilter( m_pFilterOS, sysEnv.m_WinVer, dwFlags);
if( m_pFilterOS->WaitComplete() )
{
// 设计数据库对象的观察者
m_dbOS.SetObserver( m_Observer );
m_dbOffice.SetObserver( m_Observer );
m_dbSoft.SetObserver( m_Observer );
m_pFilterOS->SetIIgnore( &m_objIgnore ); CString filename;
try
{
FixLocale(); //BOOL bWin64 = IsWin64();
//PVOID OldValue = NULL;
//if(bWin64)
// Wow64DisableWow64FsRedirection(&OldValue); // 从data目录里的文件加载数据库数据
!m_Canceled && m_dbOffice.Load( filenameOffice, m_pFilterOS, dwFlags );
!m_Canceled && sysEnv.IsLangSupported() && sysEnv.IsOsSupported() && m_dbOS.Load( filenameSystem, m_pFilterOS, dwFlags );
!m_Canceled && m_dbSoft.Load( filenameSoft, NULL, dwFlags); //if(bWin64)
// Wow64RevertWow64FsRedirection(OldValue);
}
catch (...)
{
hr = KERR_LOAD_FILE;
} CSimpleArray<LPTUpdateItem> arrLeaks;
CSimpleArray<TReplacedUpdate*> arrReplaced;
// 从数据库中获得列表
m_dbOS.GetUnfixedLeakList( arrLeaks, m_arrFixedVuls, m_arrInvalid, arrReplaced );
m_dbOffice.GetUnfixedLeakList( arrLeaks, m_arrFixedVuls, m_arrInvalid, arrReplaced ); const CSimpleArray<int> &arrExpired = m_dbOS.GetExpiredIds();
CSimpleArray<int> arrReplacedId;
for(int i=0; i<arrReplaced.GetSize(); ++i)
{
arrReplacedId.Add( arrReplaced[i]->nKBID );
} // select soft ignored vuls
CSimpleArray<LPTVulSoft> arrSoftLeaks;
m_dbSoft.GetUnfixedLeakList( arrSoftLeaks );
for(int i=0; i<arrSoftLeaks.GetSize(); ++i)
{
LPTVulSoft ps = arrSoftLeaks[i];
ps->isIgnored = m_objIgnore.IsIgnored( ps->nID );
if( ps->isIgnored )
{
LPTUpdateItem pu = new TUpdateItem;
pu->m_nType = VTYPE_SOFTLEAK;
pu->nID = ps->nID;
pu->strName = ps->matchedItem.strName;
pu->strDescription = ps->strDescription;
pu->strWebpage = ps->matchedItem.strWebpage;
pu->nWarnLevel = ps->nLevel;
pu->strPubdate = ps->strPubdate; m_arrIgnoredVuls.Add( pu );
m_arrIgnoredVulsFromSoft.Add( pu );
}
else
m_arrSoftLeaks.Add( ps );
} // select installable, ignored , expired
for(int i=0; i<arrLeaks.GetSize(); ++i )
{
LPTUpdateItem &pi = arrLeaks[i];
pi->isExpired = arrExpired.Find( pi->nID )!=-1; if(pi->isExpired)
m_arrInvalid.Add( pi );
else if(pi->isIgnored)
m_arrIgnoredVuls.Add( pi );
else
{
bool bReplaced = arrReplacedId.Find( pi->nID )!=-1;
if(!bReplaced)
m_arrLeaks.Add( pi );
}
} // find correct replace relationship
for(int i=0; i<arrReplaced.GetSize(); ++i)
{
TReplacedUpdate* pu = arrReplaced[i];
BOOL bInstalled = FindArrayIndex( m_arrFixedVuls, pu->nKBID )!=-1;
if( !bInstalled )
{
if( FindArrayIndex(m_arrFixedVuls, pu->nKBID2)!=-1
|| FindArrayIndex(m_arrLeaks, pu->nKBID2)!=-1
|| FindArrayIndex(m_arrIgnoredVuls, pu->nKBID2)!=-1 )
m_arrReplacedUpdates.Add( pu );
}
} // - 保存最后无漏洞时间, 使得下次不再提示有风险
// -- 非高速扫描的结果才有效果
if( RequireUsingInterface() && !(dwFlags & VULSCAN_EXPRESS_SCAN) )
{
BOOL hasMustLeak = FALSE;
const CSimpleArray<LPTUpdateItem> &arrLeaks = GetResults();
for(int i=0; i<arrLeaks.GetSize(); ++i)
{
if(arrLeaks[i]->nWarnLevel>0)
{
hasMustLeak = TRUE;
break;
}
}
CString strVal;
if(!hasMustLeak)
{
T_Date date;
GetLatestPackgeDate(date.nYear, date.nMonth, date.nDay);
strVal.Format(_T("%04d-%02d-%02d"), date.nYear, date.nMonth, date.nDay);
}
WriteVulConfig(_T("VulScan"), _T("LastSafePkgDate"), strVal);
}
} hr = KERR_NONE;
} while (FALSE);
return hr;
}
(2、2、3、2) 仅仅须要把数据库文件拷到KSafeMainproject文件夹下就可以得到扫描结果。
图一中的整个目录data拷到图二中就可以
图一:
图二:
金山卫士开源软件之旅(十) KSafeMainproject的分析 1的更多相关文章
- oschina BI商业智能开源软件
54款 BI商业智能开源软件 MySQL数据仓库解决方案 Infobright OLAP 分析引擎 Apache Kylin 数据处理和分发系统 Apache NiFi OLAP 数据查询引擎 Dru ...
- Windows系统下三十款优秀开源软件
Windows系统下三十款优秀开源软件 1.Firefox 官方网站:http://www.getfirefox.com/ 可替换Internet Explorer 功能特点:如果你还没有使用Fire ...
- Spring Cloud (十四):Spring Cloud 开源软件都有哪些?
学习一门新的技术如果有优秀的开源项目,对初学者的学习将会是事半功倍,通过研究和学习优秀的开源项目,可以快速的了解此技术的相关应用场景和应用示例,参考优秀开源项目会降低将此技术引入到项目中的成本.为此抽 ...
- 2014 年最热门的国人开发开源软件 TOP 100 - 开源中国社区
不知道从什么时候开始,很多一说起国产好像就非常愤慨,其实大可不必.做开源中国六年有余,这六年时间国内的开源蓬勃发展,从一开始的使用到贡献,到推出自己很多的开源软件,而且还有很多软件被国外的认可.中国是 ...
- 2014 年最热门的国人开发开源软件TOP 100
不知道从什么时候开始,很多一说起国产好像就非常愤慨,其实大可不必.做开源中国六年有余,这六年时间国内的开源蓬勃发展,从一开始的使用到贡献,到推出自己很多的开源软件,而且还有很多软件被国外认可.中国是开 ...
- 2014年国人开发的最热门的开源软件TOP 100
不知道从什么时候开始,很多一说起国产好像就非常愤慨,其实大可不必.做开源中国六年有余,这六年时间国内的开源蓬勃发展,从一开始的使用到贡献,到推出自己很多的开源软件,而且还有很多软件被国外的认可.中国是 ...
- [转]开源中国的 IT 公司开源软件整理计划介绍
[转]开源中国的 IT 公司开源软件整理计划介绍 http://www.oschina.net/news/61534/oschina-opensource-collection-plan-for-it ...
- 基于开源软件在Azure平台建立大规模系统的最佳实践
作者 王枫 发布于2014年5月28日 前言 Microsoft Azure 是微软公有云的唯一解决方案.借助这一平台,用户可以以多种方式部署和发布自己的应用. 这是一个开放的平台,除了对于Windo ...
- 最受IT公司欢迎的50款开源软件
文章来自:云头条编译 本文介绍了多款知名的开源应用软件,科技公司可以用它们来管理自己的 IT 基础设施.开发产品. 过去十年间,许多科技公司已开始畅怀拥抱开源.许多公司使用开源工具来运行自己的 IT ...
随机推荐
- RHEL安装时加载第三方raid驱动
IBM x3650 M3服务器做完RAID之后,不能直接的安装Linux系统,会报出没有硬盘的错误 过程如下: 1.到IBM的官方网站下载device drive 下载后的为:ibm_dd_sraid ...
- Python导入模块的三种形式
Python导入模块的3中方式: 1.import module_name 这样在程序里就可以通过module_name.metnod_name()的方式访问模块里的函数了 Example: > ...
- 将Dictionary序列化为json数据 、json数据反序列化为Dictionary
需要引用System.Web.Extensions dll类库 /// <summary> /// 将json数据反序列化为Dictionary /// </summary> ...
- 开源DirectShow分析器和解码器: LAV Filter
LAV Filter 是一款开源的DirectShow视频分离和解码软件,他的分离器LAVSplitter封装了FFMPEG中的libavformat,解码器LAVAudio和LAVVideo则封装了 ...
- Android SoundPool 的使用以及原理分析
好吧,我们今天来聊聊SoundPool这东西. 据说这个东西是冰激凌(Android4.0)里才引入的一个新东西.按照官方的意思大多数情况下是给游戏开发用的,比如一个游戏10关,它能在游戏开始前一次加 ...
- UBUNTU 下如何升级 gcc, g++
正如大家所知道的GCC并不支持"make uninstall". 一种推荐安装方式就是把GCC 安装在你自己指定的一个路径,当你不须要某个GCC版本号的时候你仅仅须要移除相应版本号 ...
- javascript高级知识分析——实例化
代码信息来自于http://ejohn.org/apps/learn/. new做了什么? function Ninja(){ this.name = "Ninja"; } var ...
- web基础-web工作原理,http协议,浏览器缓存
1,web工作原理 2,http协议 3,浏览器缓存 4,cookie和session -------------------------------------------------------- ...
- UIlabel添加背景图片
做UI的时候我们可能想给某个Label添加一个背景图片,但查看的时候会发现好像只有设置背景颜色的方法,不过我们也可以通过这种方式来解决: UIColor *color = [UIColor color ...
- C# - ADO.Net 调用存储过程
------------------------存储过程调用,创建DataSet:----------------------//数据库连接字符串string connStr = @"Dat ...