上一次看金山开源到现在已有一两个月了。期间看到QQ群里大家对它很是热情。

最近有时间想看看金山的主界面工程KSafeMain,自己水平有限,总结的东西浅显。但还是愿意拿来与大家分享。希望对大家有帮助。

转载请标明是引用于 http://blog.csdn.net/chenyujing1234

欢迎大家提出问题讨论。

1、超链接的加入

上图中红色标注的地方就是超链接的地方。

它的实现是在dlgfile_header.xml文件中。

eg:

求助这个按钮:

<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 。

它的类定义很简单:

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  按钮处理函数的实现

扫描结果显示的效果图是:

在 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)首先编译BeikeUtils工程。

会出现以下报错:

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

解决方法请参考我的另一篇文章:(里面有同样的出错的处理)

金山卫士开源软件之旅(一) VS 2005环境下编译

(2、2、1、2) 其它的工程都顺利编译通过,只有两个工程ksafevul、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;
}

ksafevul工程编译通过后就生成了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也加载到了,为什么修复漏洞不是没有扫描的结果呢。

我也被这个问题困扰着,从KSafeMain工程中我们只能知道

hr = m_pVulScan->Scan(dwFlags);

返回了失败.所以没有扫描结果。

但原因是什么呢?我决定对此打破砂锅。

(2、2、3、1)Scan的实现在VulfixLIb工程中(在上面的(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) 只需要把数据库文件拷到KSafeMain工程目录下即可得到扫描结果。

图一中的整个文件夹data拷到图二中即可

图一:

图二:

金山卫士开源软件之旅(十) KSafeMain工程的分析 1相关推荐

  1. 金山卫士开源软件之旅(十) KSafeMainproject的分析 1

    上一次看金山开源到如今已有一两个月了.期间看到QQ群里大家对它非常是热情. 近期有时间想看看金山的主界面projectKSafeMain,自己水平有限,总结的东西浅显.但还是愿意拿来与大家分享.希望对 ...

  2. 金山卫士开源软件之旅(一) VS 2005环境下编译

    转载请标明是引用于 http://blog.csdn.net/chenyujing1234 参考文档: http://bbs.code.ijinshan.com/viewthread.php?tid= ...

  3. 金山卫士开源软件之旅(二) 简单教程:如何创建一个基于金山卫士界面库的工程

    完整解决方案代码压缩包: test_full.zip (267.59 KB) 参考: http://bbs.code.ijinshan.com/thread-1391-1-1.html 为了让更多的朋 ...

  4. 《在路上 …》 金山卫士开源 , 人生很多感慨

    最近写日记少了很多, 主要是很多情绪化的东西, 都汇入了某条有去无回的地下河. 好吧, 不说这些, 来说说金山卫士开源. 相比360安全卫士那种作秀式的开源 (代码只对极少极少的人开放, 隐隐藏藏), ...

  5. 《金山卫士开源--让互联网拥抱安全》语音互动实录

    12月22日,金山网络安全技术研发中心过程改进经理,参与了主题<金山卫士开源--让互联网拥抱安全>的公开YY语音,与网友们进行了深度的互动,为广大网友答疑解惑有关金山卫士的详情. 嘉宾简介 ...

  6. 金山卫士开源代码----消息机制浅析 (上

    博客已迁移至:http://kulv.sinaapp.com/,这里不再使用 金山卫士开源代码----消息机制浅析 (上) 代码地址:http://download.csdn.net/source/3 ...

  7. 金山卫士开源系列讲座之一:揭秘卫士如何优化系统

    你的电脑开机速度快不快?你的系统运行速度为何变慢?虽然我们整天用电脑,但很多人对此不明所以,或者知其然而不知其所以然. 作为国内专业的主流安全管理软件,金山卫士拥有简便强劲的系统优化功能,包括开机加速 ...

  8. 金山卫士开源---kclear 卫士垃圾清理

    金山卫士的开源已经进行了好长时间了,现在已经开放第六批源码"kclear 卫士垃圾清理". 下载源码,使用VS2010打开,自动转换解决方法之最新. 首先,源代码是需要atl支持的 ...

  9. 开源软件软件著作权执照详细研究和实例分析

    前言:LGPL大约是开源库商用绕不开的一条,如何使用LGPL,要实现LGPL的开源软件,作为开发者,使用者和商用者我们需要做哪些工作,需要注意哪些问题呢,文章希望通过实例来说明这些问题. 1 开源许可 ...

最新文章

  1. CSS position财产
  2. hive 小技巧总结
  3. matlab mpt工具箱帮助文档_替代 Matlab 的国产软件出现?
  4. .NET 6 Preview 4 已发布,ASP.NET Core 更新内容
  5. .net10个必备工具
  6. python网络编程内容_Python网络编程
  7. stm32 NVIC EXTI
  8. C#LeetCode刷题之#232-用栈实现队列​​​​​​​​​​​​​​(Implement Queue using Stacks)
  9. Ubuntu 配置vsftpd实现FTP服务器
  10. 图卷积网络详细介绍(一)
  11. CFileDialog多选文件的最大数量
  12. 「黑科技」增加栈的空间
  13. redis分布式锁学习总结
  14. java观察者模式举例
  15. python电话簿_python 联系簿
  16. 图片木马制作方法详细教程
  17. 第二工业大学计算机应用大专录取分,2016年上海第二工业大学专科层次依法自主招生各专业分数线...
  18. js判断background颜色明暗色调,以设置白/黑字体颜色
  19. Apache Flink_JZZ158_MBY
  20. 极具挑战性的工作:升级模式库从CQ2002到CQ7

热门文章

  1. 物联网平台TZ-IOT发布透传云内测服务:V1.0
  2. 51单片机指令快速记忆方法总结
  3. 【NLP基础中文处理】jieba分词初级的应用,以及统计《茅山后裔》的主要人物
  4. 反编译工具jad使用方法
  5. 动漫常用网站/APP 彻底帮你解决看动漫的烦恼
  6. sja1c语言,三菱A1SJ71UC24-R2手册A1SJ71UC24-R2硬件用户手册 - 广州凌控
  7. 沪江快速手机打字破解版
  8. Android File System安卓文件系统(安卓存储分区,/data /storage /sdcard)
  9. 393分上岸南昌大学信息工程学院软件工程专硕
  10. 威纶通触摸屏的配方功能具体使用方法介绍(宏指令写入PLC)