热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

安全类工具制作第003篇:注册表启动项管理器

一、前言注册表是Windows操作系统中的一个非常重要的数据库,里面记录了我们系统的几乎所有信息。也正因为这个原因,病毒木马也常常利用注册表来做文章。而对于杀毒软件来说,注册表也是要重
一、前言

        注册表是Windows操作系统中的一个非常重要的数据库,里面记录了我们系统的几乎所有信息。也正因为这个原因,病毒木马也常常利用注册表来做文章。而对于杀毒软件来说,注册表也是要重点关注的对象。我在《反病毒攻防研究第002篇:利用注册表实现自启动》中也提到过,恶意程序可以利用注册表实现自启动,比如可以增加系统的启动项或通过映像劫持等的方法。这次我打算编写一个注册表启动项管理器,利用它可以对注册表的启动项进行查看,还可以删除可疑启动项。尽管功能很简单,但却也是反病毒木马的利器。需要说明的是,这篇文章所编写的程序,仅仅针对《利用注册表实现自启动》中提到的两个实现程序自启动的注册表键以及键值来讨论的,也就是说我这里并不会在程序中添加所有的注册表启动项,有兴趣的读者可以自行添加。

 

二、界面的制作

        依旧利用MFC创建一个基于对话框的程序,界面如下:


图1 界面设计

        程序需要使用两个“Static Text”、两个“List Control”以及三个“Button”控件。需要将两个“List Control”控件的属性都进行如下设置:


图2 设置List Control的属性

        最后为界面上面的“List Control”控件添加一个名为“m_RunList”的变量,为下面的“List Control”控件添加一个名为“m_IFEOList”的变量。然后通过编程对两个“List Control”控件进行初始化,主要是对表格的属性进行设置:

void CRegManageRunDlg::InitRunList()
{
//设置“List Control”控件的扩展风格
m_RunList.SetExtendedStyle(
m_RunList.GetExtendedStyle()
| LVS_EX_GRIDLINES //有网络格
| LVS_EX_FULLROWSELECT); //选中某行使整行高亮(只适用于report风格)

//添加列目
m_RunList.InsertColumn(0, _T("序号"));
m_RunList.InsertColumn(1, _T("名 称"));
m_RunList.InsertColumn(2, _T("类 型"));
m_RunList.InsertColumn(3, _T("数 据"));
//设置列的宽度
m_RunList.SetColumnWidth(0, LVSCW_AUTOSIZE_USEHEADER);
m_RunList.SetColumnWidth(1, LVSCW_AUTOSIZE_USEHEADER);
m_RunList.SetColumnWidth(2, LVSCW_AUTOSIZE_USEHEADER);
m_RunList.SetColumnWidth(3, LVSCW_AUTOSIZE_USEHEADER);
}

void CRegManageRunDlg::InitIFEOList()
{
//设置“List Control”控件的扩展风格
m_IFEOList.SetExtendedStyle(
m_IFEOList.GetExtendedStyle()
| LVS_EX_GRIDLINES //有网络格
| LVS_EX_FULLROWSELECT); //选中某行使整行高亮(只适用于report风格)
//添加列目
m_IFEOList.InsertColumn(0, _T("序号"));
m_IFEOList.InsertColumn(1, _T("被劫持程序名称"));
//设置列的宽度
m_IFEOList.SetColumnWidth(0, LVSCW_AUTOSIZE_USEHEADER);
m_IFEOList.SetColumnWidth(1, LVSCW_AUTOSIZE_USEHEADER);
}
        然后进行对话框的初始化,在OnInitDialog()中添加:
InitRunList();
InitIFEOList();
        最后在头文件中的相应位置添加:
void InitRunList();
void InitIFEOList();

        我之所以要使用两个“ListControl”控件,是因为我需要枚举启动项和映像劫持。前者所枚举的是启动项“Run”这个“键”下面的所有“键值”,而后者所枚举的是“映像劫持”这个“键”下面的所有“子键”。对于枚举不同的内容,我觉得还是分开讨论比较好。

 

三、编写代码         首先需要编写两个宏定义,表示我们将要枚举的项:
#define REG_RUN  "Software\\Microsoft\\Windows\\CurrentVersion\\Run\\"
#define REG_IFEO "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Image File Execution Options\\"
        接下来编写显示启动项的代码:

void CRegManageRunDlg::ShowRunList()
{
//清空列表
m_RunList.DeleteAllItems();

DWORD dwType = 0;
DWORD dwBufferSize = MAXBYTE;
DWORD dwKeySize = MAXBYTE;

char szValueName[MAXBYTE] = { 0 };
char szValueKey[MAXBYTE] = { 0 };
char szType[MAXBYTE] = { 0 };

//打开注册表启动项
HKEY hKeyRun = NULL;
LONG lRetRun = RegOpenKey(HKEY_CURRENT_USER, REG_RUN, &hKeyRun);
if ( lRetRun != ERROR_SUCCESS )
{
AfxMessageBox("注册表打开失败!");
return ;
}

int i = 0;
CString strRunTmp;

while ( TRUE )
{
lRetRun = RegEnumValue(hKeyRun, i, szValueName, &dwBufferSize, NULL, &dwType, (unsigned char *)szValueKey, &dwKeySize);
if ( lRetRun == ERROR_NO_MORE_ITEMS )
{
break;
}
strRunTmp.Format("%d", i);
//判断注册表项值的类型
if(dwType == REG_SZ)
{
//一个以0结尾的字符串
strcpy(szType, "REG_SZ");
}
else if(dwType == REG_BINARY)
{
//任何形式的二进制数据
strcpy(szType, "REG_BINARY");
}
else if(dwType == REG_DWORD)
{
//一个32位的数字
strcpy(szType, "REG_DWORD");
}
else if(dwType == REG_EXPAND_SZ)
{
//一个以0结尾的字符串,该字符串包含对环境变量(如%PATH%)的未扩展引用
strcpy(szType, "REG_EXPAND_SZ");
}
else
{
//其它
strcpy(szType, "OTHER");
}
//将获取的注册表内容写入“List Control”控件
m_RunList.InsertItem(i, strRunTmp);
m_RunList.SetItemText(i, 1, szValueName);
m_RunList.SetItemText(i, 2, szType);
m_RunList.SetItemText(i, 3, szValueKey);

i++;

//清空缓冲区
ZeroMemory(szValueName,MAXBYTE);
ZeroMemory(szType,MAXBYTE);
ZeroMemory(szValueKey, MAXBYTE);
}
RegCloseKey(hKeyRun);
}
        然后编写显示映像劫持的代码:
void CRegManageRunDlg::ShowIFEOList()
{
//清空列表
m_IFEOList.DeleteAllItems();

DWORD dwSize = MAXBYTE;
char szKeyName[MAXBYTE] = { 0 };

//打开注册表映像劫持项
HKEY hKeyIFEO = NULL;
LONG lRetIFEO = RegOpenKey(HKEY_LOCAL_MACHINE, REG_IFEO, &hKeyIFEO);
if ( lRetIFEO != ERROR_SUCCESS )
{
AfxMessageBox("映像劫持打开失败!");
return ;
}

int j = 0;
CString strTmp;

while(TRUE)
{
strTmp.Format("%d", j);
lRetIFEO = RegEnumKey(hKeyIFEO, j, szKeyName, dwSize);
if ( lRetIFEO == ERROR_NO_MORE_ITEMS )
{
break;
}

m_IFEOList.InsertItem(j, strTmp);
m_IFEOList.SetItemText(j, 1, szKeyName);

j ++;

ZeroMemory(szKeyName,MAXBYTE);
}
RegCloseKey(hKeyIFEO);
}
        为了使这两个函数正常使用,需要在对话框初始化时,就将注册表内容显示出来。在OnInitDialog()中添加:
ShowRunList();
ShowIFEOList();
        再在头文件中进行函数声明:
void ShowIFEOList();
void ShowRunList();
        至此,两个“List Control”控件的程序编写完毕,接下来是三个按钮控件的编程,首先是“删除启动项”按钮:
void CRegManageRunDlg::OnBtnRunDel() 
{
// TODO: Add your control notification handler code here
POSITION pos = m_RunList.GetFirstSelectedItemPosition();
int nSelected = -1;

while ( pos )
{
nSelected = m_RunList.GetNextSelectedItem(pos);
}

if ( -1 == nSelected )
{
AfxMessageBox("您尚未选择选择要删除的启动项!");
return ;
}

char szKeyName[MAXBYTE] = { 0 };
m_RunList.GetItemText(nSelected, 1, szKeyName, MAXBYTE);

CString str = "您即将要删除的启动项是:";
str += szKeyName;
AfxMessageBox(str);
str.Empty();

HKEY hKey = NULL;
LONG lRet = RegOpenKey(HKEY_CURRENT_USER, REG_RUN, &hKey);
if ( lRet != ERROR_SUCCESS )
{
AfxMessageBox("启动项打开失败!");
return ;
}

RegDeleteValue(hKey, szKeyName);
RegCloseKey(hKey);

ShowRunList();
}
        然后是“删除映像劫持”按钮:
void CRegManageRunDlg::OnBtnIFEODel() 
{
// TODO: Add your control notification handler code here
POSITION pos = m_IFEOList.GetFirstSelectedItemPosition();
int nSelected = -1;

while ( pos )
{
nSelected = m_IFEOList.GetNextSelectedItem(pos);
}

if ( -1 == nSelected )
{
AfxMessageBox("您尚未选择选择要删除的映像劫持!");
return ;
}

char szKeyName[MAXBYTE] = { 0 };
m_IFEOList.GetItemText(nSelected, 1, szKeyName, MAXBYTE);

CString str = "您即将要删除的映像劫持是:";
str += szKeyName;
AfxMessageBox(str);
str.Empty();

HKEY hKey = NULL;
LONG lRet = RegOpenKey(HKEY_LOCAL_MACHINE, REG_IFEO, &hKey);
if ( lRet != ERROR_SUCCESS )
{
AfxMessageBox("映像劫持打开失败!");
return ;
}

RegDeleteKey(hKey, szKeyName);
RegCloseKey(hKey);

ShowIFEOList();
}
        最后是“退出”按钮:
void CRegManageRunDlg::OnBtnQuit() 
{
// TODO: Add your control notification handler code here
EndDialog(0);
}

        至此,所有代码编写完毕。由于程序原理非常简单,所以这里无需过多论述。

 

四、实际测试         测试时需要使用 《反病毒攻防研究第002篇:利用注册表实现自启动》 中编写的用于模拟计算机病毒的程序,它会在注册表中的两个位置添加自身,以实现自启动。运行该“病毒”程序后,用这里编写的“启动项管理器”进行查看:

图3 查看启动项

        可见我们的程序已经正确识别出了“恶意程序”所添加的启动项,接下来就可以通过点击相应的按钮进行删除,这里不再赘述。

 

五、小结        我们可以在此基础上开发一个完整的注册表启动项管理器,使其可以枚举所有的启动项,再添加其它一些实用的功能,令恶意程序无处藏身。MFC为我们提供了丰富的控件,利用它们可以编写出功能强大且界面精美的程序,这也是我的《安全类软件编写》这一系列坚持使用MFC的原因。

推荐阅读
  • ASP.NET2.0数据教程之十四:使用FormView的模板
    本文介绍了在ASP.NET 2.0中使用FormView控件来实现自定义的显示外观,与GridView和DetailsView不同,FormView使用模板来呈现,可以实现不规则的外观呈现。同时还介绍了TemplateField的用法和FormView与DetailsView的区别。 ... [详细]
  • 如何在php文件中添加图片?
    本文详细解答了如何在php文件中添加图片的问题,包括插入图片的代码、使用PHPword在载入模板中插入图片的方法,以及使用gd库生成不同类型的图像文件的示例。同时还介绍了如何生成一个正方形文件的步骤。希望对大家有所帮助。 ... [详细]
  • 本文由编程笔记小编整理,介绍了PHP中的MySQL函数库及其常用函数,包括mysql_connect、mysql_error、mysql_select_db、mysql_query、mysql_affected_row、mysql_close等。希望对读者有一定的参考价值。 ... [详细]
  • 计算机存储系统的层次结构及其优势
    本文介绍了计算机存储系统的层次结构,包括高速缓存、主存储器和辅助存储器三个层次。通过分层存储数据可以提高程序的执行效率。计算机存储系统的层次结构将各种不同存储容量、存取速度和价格的存储器有机组合成整体,形成可寻址存储空间比主存储器空间大得多的存储整体。由于辅助存储器容量大、价格低,使得整体存储系统的平均价格降低。同时,高速缓存的存取速度可以和CPU的工作速度相匹配,进一步提高程序执行效率。 ... [详细]
  • 本文详细介绍了在ASP.NET中获取插入记录的ID的几种方法,包括使用SCOPE_IDENTITY()和IDENT_CURRENT()函数,以及通过ExecuteReader方法执行SQL语句获取ID的步骤。同时,还提供了使用这些方法的示例代码和注意事项。对于需要获取表中最后一个插入操作所产生的ID或马上使用刚插入的新记录ID的开发者来说,本文提供了一些有用的技巧和建议。 ... [详细]
  • 开发笔记:select from具体执行相关知识介绍及案例分析
    本文由编程笔记小编整理,主要介绍了select from具体执行相关的知识,包括数据插入、查询最小rowID、查询每个重复名字的最小rowID、删除重复数据等操作,并提供了案例分析。希望对读者有一定的参考价值。 ... [详细]
  • MyBatis多表查询与动态SQL使用
    本文介绍了MyBatis多表查询与动态SQL的使用方法,包括一对一查询和一对多查询。同时还介绍了动态SQL的使用,包括if标签、trim标签、where标签、set标签和foreach标签的用法。文章还提供了相关的配置信息和示例代码。 ... [详细]
  • Java学习笔记之使用反射+泛型构建通用DAO
    本文介绍了使用反射和泛型构建通用DAO的方法,通过减少代码冗余度来提高开发效率。通过示例说明了如何使用反射和泛型来实现对不同表的相同操作,从而避免重复编写相似的代码。该方法可以在Java学习中起到较大的帮助作用。 ... [详细]
  • MySQL语句大全:创建、授权、查询、修改等【MySQL】的使用方法详解
    本文详细介绍了MySQL语句的使用方法,包括创建用户、授权、查询、修改等操作。通过连接MySQL数据库,可以使用命令创建用户,并指定该用户在哪个主机上可以登录。同时,还可以设置用户的登录密码。通过本文,您可以全面了解MySQL语句的使用方法。 ... [详细]
  • MySQL中的MVVC多版本并发控制机制的应用及实现
    本文介绍了MySQL中MVCC的应用及实现机制。MVCC是一种提高并发性能的技术,通过对事务内读取的内存进行处理,避免写操作堵塞读操作的并发问题。与其他数据库系统的MVCC实现机制不尽相同,MySQL的MVCC是在undolog中实现的。通过undolog可以找回数据的历史版本,提供给用户读取或在回滚时覆盖数据页上的数据。MySQL的大多数事务型存储引擎都实现了MVCC,但各自的实现机制有所不同。 ... [详细]
  • 合并列值-合并为一列问题需求:createtabletab(Aint,Bint,Cint)inserttabselect1,2,3unionallsel ... [详细]
  • 超级简单加解密工具的方案和功能
    本文介绍了一个超级简单的加解密工具的方案和功能。该工具可以读取文件头,并根据特定长度进行加密,加密后将加密部分写入源文件。同时,该工具也支持解密操作。加密和解密过程是可逆的。本文还提到了一些相关的功能和使用方法,并给出了Python代码示例。 ... [详细]
  • 带添加按钮的GridView,item的删除事件
    先上图片效果;gridView无数据时显示添加按钮,有数据时,第一格显示添加按钮,后面显示数据:布局文件:addr_manage.xml<?xmlve ... [详细]
  • 本文介绍了如何在Jquery中通过元素的样式值获取元素,并将其赋值给一个变量。提供了5种解决方案供参考。 ... [详细]
  • 抽空写了一个ICON图标的转换程序
    抽空写了一个ICON图标的转换程序,支持png\jpe\bmp格式到ico的转换。具体的程序就在下面,如果看的人多,过两天再把思路写一下。 ... [详细]
author-avatar
501917112_0de975_837
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有