程序设计中的读写注册表的编程介绍
川师信息安全研究中心作者:安美洪
提到注册表,各位黑友没有哪个不或多或少都有所了解,因为在好多的黑客软件中,可能需要涉及到这方面的编程,如系统启动自动加载程序运行,收集肉机的相关信息,修改相关的设置,提高服务器的抗拒绝服务攻击能力等,所以说,对注册表的编程操作是我们各位黑友进行工具开发的重要内容,我们没有理由不深入了解它。WINDOWS系列操作系统的注册数据库(Registry)是系统中非常重要的组成部分,在Win32 API中有一组注册表操作函数来处理这些问题,其一般的读写过程如下:
1、使用RegOpenKeyEx或RegCreateKeyEx函数打开或创建一个键;
2、如果上一步成功,使用RegQueryValueEx读取子键的值,使用RegSetValueEx设置子键值,使用RegEnumKey获得所有子键,使用RegDeleteKey删除一个键;
3、完成操作后使用RegCloseKey关闭键。
而Windows API 中可用于注册表的函数一共有二十多个,根据其功能不同可以分为如下几类:
键管理类
RegCloseKey()
RegCreateKey()
RegCreateKeyEx()
RegDeleteKey()
RegDeleteKeyEx()
RegOpenKey()
RegOpenKeyEx()
值管理类
RegDeleteValue()
RegQueryValue()
RegQueryValueEx()
RegSetValue()
RegSetValueEx()
查询计数类
RegQueryInfoKey()
RegEnumKey()
RegEnumKeyEx()
RegEnumValue()
备份/恢复类
RegLoadKey()
RegReplaceKey()
RegRestoreKey()
RegSaveKey()
实用类
RegConnectRegistry()
RegNotifyChangeKeyValue()
RegUnloadKey()
安全类
(仅适用于NT)
RegGetKeySecurity()
RegSetKeySecurity()
以上注册表函数的细节请参阅注册表函数细节,地址是:(包括相关的也在相邻地方,这里仅是RegCloseKey()这个函数)http://msdn.microsoft.com/library/default.asp?url=/library/en-us/sysinfo/base/regclosekey.asp下边我们就来详细介绍相关的内容。
一、基本操作介绍
我们对注册表的操作一般的步骤是,打开、读写、关闭,那就先来看看相关最重要的几个函数介绍吧,其它更多的函数还得靠大家去MSDN查阅。
首先来看看,打开与关闭函数,在读写注册表前,必须先将目标的子键打开,也就是取得一个操作的句柄,而打开这个函数最常用的就是RegCreateKeyEx,如果没有这个键存在,那么就会自动的创建这个子键项。
LONG RegCreateKeyEx(
HKEY hKey, //父键的句柄
LPCTSTR lpSubKey, //子键名称
DWORD Reserved, //一般为0
LPTSTR lpClass, //一般为0
DWORD dwOptions, //创建子键时的选项
REGSAM samDesired, //打开方式
LPSECURITY_ATTRIBUTES lpSecurityAttributes,//指定继承性
PHKEY phkResult, //用于返回子键的句柄
LPDWORD lpdwDisposition //打开还是创建子键的信息
);
如果函数调用成功,会返回ERROR_SUCCESS也就是说成功会返回0,失败返回非0值。
SamDesired参数有多个取值,最后这个lpdwDisposition参数用于返回信息,有两个取值:
REG_CREATED_NEW_KEY指定的键不存在,那么创建。
REG_OPENED_EXISTING_KEY指定的键存在,那么打开。另外还有相近的函数如下:
LONG RegOpenKeyEx(
HKEY hKey, // 要打开主键的句柄
LPCTSTR lpSubKey, //要打开子键
DWORD ulOptions, //保留
REGSAM samDesired, //安全存取参数
PHKEY phkResult //打开键句柄的地址
);
与打开函数相比,关闭就比较容易了,它的函数原型如下:
LONG RegCloseKey( HKEY hKey);所以只需传入一个要关闭的句柄就行了。
然后,我们来看看读写的相关函数,读取的函数原型如下:
LONG RegQueryValueEx(
HKEY hKey, //子键句柄
LPCTSTR lpValueName, //键值名称
LPDWORD lpReserved, //为0
LPDWORD lpType, //返回键值的数据类型
LPBYTE lpData, //返回键值的数据
LPDWORD lpcbData //缓冲区的大小
);
函数调用成功后,返回ERROR_SUCCESS.
写的函数主要是RegCreateKeyEx外,还有RegSetValueEx,它的原型如下:
LONG RegSetValueEx(
HKEY hKey,//键值所在子键的句柄
LPCTSTR lpValueName, //要设置的键值名称
DWORD Reserved, //为0
DWORD dwType, //设置键值的数据类型
const BYTE* lpData, //设置键值的数据缓冲区
DWORD cbData //设置键值的数据缓冲区大小
);
最后再介绍一下删除键值的函数,它就是:
LONG RegDeleteValue(
HKEY hKey,//子键的句柄
LPCTSTR lpValueName //删除键值的名称
);
这两个函数的返回情况一样,如果函数调用成功,会返回ERROR_SUCCESS也就是说成功会返回0,失败返回非0值。
现在,我们在编程操作中常用到的几个函数介绍完了,大家也有所了解了,但我们在实际编程中,当然要参考的函数还很多,下而我们就举例的说明,一个是读的,一个是写的。
二、注册表的读操作
在这里我们用编程操作实现读注册表里的配置信息,从而查询出CPU的相关信息,CPU的重要性当然不用说,我们入侵了一台肉机后,可能很想知道CPU的相关信息,在注册表的这个路径下:HKEY_LOCAL_MACHINE\Hardware\Description\System\CentralProcessor\0
下边我们看看编程的实现:
void CPUINFO(void)
{
long lRet;
HKEY hKey;
TCHAR tchData[64];
DWORD dwSize;
lRet = RegOpenKeyEx(
HKEY_LOCAL_MACHINE,
"Hardware\\Description\\System\\CentralProcessor\\0",
0,
KEY_QUERY_VALUE,
&hKey
);//打开注册表
if(lRet == ERROR_SUCCESS)//读操作成功
{
dwSize = sizeof(tchData);
lRet = RegQueryValueEx(
hKey,
"ProcessorNameString",
NULL,
NULL,
(LPBYTE)tchData,
&dwSize
);//如果打开成功,则读
if(lRet == ERROR_SUCCESS)
{
printf("\n CPU INFO:");
printf("%s\n",tchData);
}
//以下是读取失败
else
{
printf("\nCPU INFO:");
printf("UNKNOWN\n");
}
}
//以下是打开失败
else
{
printf("\n CPU INFO:");
printf("UNKNOWN\n");
}
RegCloseKey(hKey);//记住,一定要关闭
}
三、注册表的写操作
在各种后门程序中,要实现的一个重要功能就是让后门程序能在开机的时候实现自动启动,当然,实现这样自己启动的方法有很多种,我这里主要是介绍的是修改注册表中的相关设置来实现。另外就是不同的系统可能有点不一样,需要修改改一下相关的内容。下边是实现的程序:
void SELFRUN(void)
{
// 根键、子键名称、和到子键的句柄
HKEY hRoot = HKEY_LOCAL_MACHINE;
char *szSubKey = "Software\\Microsoft\\Windows\\CurrentVersion\\Run";
HKEY hKey;// 打开指定子键
DWORD dwDisposition = REG_OPENED_EXISTING_KEY;
// 如果不存在不创建
LONG lRet = RegCreateKeyEx(
hRoot,
szSubKey,
0,
NULL,
REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS,
NULL,
&hKey,
&dwDisposition
);
if(lRet != ERROR_SUCCESS)
return ;
// 得到当前执行文件的文件名(包含路径)
char szModule[MAX_PATH] ;
GetModuleFileName (NULL, szModule, MAX_PATH);
// 创建一个新的键值,设置键值数据为文件名
lRet = RegSetValueEx(
hKey,
"SelfRunDemo",
0,
REG_SZ,
(BYTE*)szModule,
strlen(szModule));
if(lRet == ERROR_SUCCESS)
{
printf(" self run success\n");
}
// 关闭子键句柄
RegCloseKey(hKey);
}
四、函数的主体
#include <stdio.h>
#include <windows.h>
void SELFRUN(void)
void CPUINFO(void)
int main(int argc, char* argv[])
{
CPUINFO();
// SELFRUN();
//要用时自己改一下这,这里我仅是为了调试方便,放在一起了
}
最后说说,其实我们在实际的编程中,可能远远比这复杂,但基本知识还是这些,只要你多参考下相关的函数说明,我想你也会对注册表的操作得心应手的,别人都说,不会自己写程序的黑客,不叫黑客,现在你动手吧,不要让别人再笑话你了,写几个简单的程序其实也不是想象中的那么困难哟,祝各位黑友玩得高兴!如有什么问题联系anmeihong@sina.com与我的QQ18184412,欢迎共同讨论(并附上相关的代码)