晃晃悠悠

isrobert

  VC知识库BLOG :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 登录 ::
  12 随笔 :: 0 文章 :: 34 评论 :: 0 Trackbacks
<2008年11月>
2627282930311
2345678
9101112131415
16171819202122
23242526272829
30123456

留言簿(0)

随笔分类

随笔档案

文章档案

相册

收藏夹

相关链接

搜索

最新评论

阅读排行榜

评论排行榜

对注册表操作算是比较全了,感觉不错,收藏!

原文:http://www.helpmsg.com/blog/article.asp?id=48

开始前先了解一些基础知识,对后面的工作会方便不少,其码不会出现散晕的现像,对注册表的历史也就不再说了有兴趣可以   
  1. 查查新华字典呵呵.注册表的组织方式跟文件目录比较相似,主要分为 跟键,子键,键值项 三部分跟文件目录对应的话就是   
  2. 跟目录,子目录,和文件.分别介绍一下,跟键为分5个分别为HKEY_CLASSES_ROOT,HKEY_CURRENT_USER,HKEY_LOCAL_MACHINE   
  3. HKEY_USERS,HKEY_CURRENT_CONFIG把它们理解成磁盘的五个分区可以了,子键可以有多个子键和键值项,就像一个目录中可   
  4. 以有多个子目录和多个文件一样,而键值项可以理解为文件它由三部分组成,分别为 名称,类型,数据. 类型又分为多种主要   
  5. 包括如下:   
  6.   
  7. REG_BINARY        二进制数据   
  8.   
  9. REG_DWORD        32位双字节数据   
  10.   
  11. REG_SZ            以0结尾的字符串   
  12.   
  13. REG_DWORD_BIG_ENDIAN    高位排在底位的双字   
  14.   
  15. REG_EXPAND_SZ        扩展字符串,可以加入变量如%PATH%   
  16.   
  17. REG_LINK        UNICODE 符号链接   
  18.   
  19. REG_RESOURCE_LIST    设备驱动程序资源列表   
  20.   
  21. REG_MULTI_SZ        多字符串   
  22.   
  23. 注册表数据项的数据类型有8种但最常用的主要是前3种而以,有了这些基础下面我们讨论如何编程实现对注册表的操作   
  24.   
  25.   
  26.   
  27.   
  28. 打开/关闭注册表句柄   
  29.   
  30.   
  31.   
  32. 在对注册表操作前应该先打开指定的键,然后通过键的句柄进行操作,打开键句柄可以用API RegOpenKeyEx来实现其原形如下   
  33.   
  34. RegOpenKeyEx(   
  35.         hKey,        //父键句柄   
  36.         lpSubKey,    //子键句柄   
  37.         dwOptions,    //系统保留,指定为0   
  38.         samDesired,    //打开权限   
  39.         phkResult,    //返回打开句柄   
  40.         )   
  41.   
  42. 其中打开权限有多种 想方便的话可以指定为KEY_ALL_ACCESS 这样什么权限都有了,当函数执行成功时返回ERROR_SUCCESS   
  43.   
  44. 其实例代码如下:   
  45.   
  46.     HKEY key;   
  47.     LPCTSTR data="SOFTWARE\Microsoft\Windows\CurrentVersion\Run";   
  48.     if(RegOpenKeyEx(HKEY_LOCAL_MACHINE,data,0,KEY_ALL_ACCESS,&key)==ERROR_SUCCESS)   
  49.     {   
  50.         /**//*需要执行的操作*/  
  51.     }   
  52.     ::RegCloseKey(key);   
  53. 要注意的是在使用后应该调用RegCloseKey();函数为关闭句柄.   
  54.   
  55.   
  56.   
  57. 木马编程DIY之注册表管理   文/图 冷风   
  58. 获取子键/键值信息   
  59.   
  60.   
  61. 在现实的编程操作中我们常常需要获取 子键/键值的信息比如:子键/键值的数量,长度,以及数据的最大长度等等这些信息可以   
  62. 通过RegQueryInfoKey函数来获取   
  63.   
  64. 它的原型如下:   
  65.   
  66. RegQueryInfoKey(   
  67.         hkey,            //要获取信息的句柄   
  68.         lpClass,        //接受创建健时的Class字符串   
  69.         lpcbClass,        //lpClass的长度   
  70.         lpReserved,        //系统保留,指定为0   
  71.         lpcSubKeys,        //子键数量   
  72.         lpcbMaxSubKeyLen,    //子键中最长名称的长度   
  73.         lpcbMaxClassLen,    //子键中最长Class字符串长度   
  74.   
  75.         lpcVlaues,        //键值数量   
  76.         lpcbMaxValueNameLen,    //键值项中最长名称的长度   
  77.         lpcbMaxValueLen,    //键值项数据最大长度   
  78.         lpcbSecurityDescriptor,    //安全描述符长度   
  79.         lpftLastWriteTime,    //FILETIME结构,最后修改时间   
  80.         )   
  81. 哈哈是不是挺吓人的?其实看实际情况接受自己需要的就好了,不需要的可以放个NULL就OK了,还有一点需要注意就是它所返回   
  82. 的长度都不包括结尾的0字符,所以在使用时应该用长度+1   
  83.   
  84. 其实例代码如下   
  85.   
  86. DWORD dwIndex=0,NameSize,NameCnt,NameMaxLen,Type;   
  87. DWORD KeySize,KeyCnt,KeyMaxLen,DateSize,MaxDateLen;   
  88.   
  89. if(RegQueryInfoKey(key,NULL,NULL,NULL,&KeyCnt,&KeyMaxLen,NULL,&NameCnt,&NameMaxLen,&MaxDateLen,NULL,NULL)!=ERROR_SUCCESS)   
  90. {   
  91.     printf("RegQueryInfoKey错误");   
  92.     return;   
  93. }   
  94.   
  95. 用的时候套用格式就成了,不然会很麻烦的..有了这些信息我们就可以枚举子键和键值的信息了   
  96.   
  97.   
  98.   
  99. 枚举子键信息   
  100.   
  101.   
  102. 枚举子键可以用API函数 RegEnumKeyEx来实现 调用RegEnumKeyEx时将返回子键的名称,长度和一些相关数据,如果想得到一个   
  103. 键下的全部子键的话应该循环调用,直到返回ERROR_NO_MORE_ITEMS为至,就说明以枚举完了所有数据其函数原型如下   
  104.   
  105. RegEnumKeyEx(   
  106.         hkey,        //被枚举的键句柄   
  107.         dwIndex,    //子键索引编号   
  108.         lpName,        //子键名称   
  109.         lpcbName,    //子键名称长度   
  110.         lpReserved,    //系统保留,指定为0   
  111.         lpClass,    //子键类名   
  112.         lpcbClass,    //子键类名长度   
  113.         lpftLastWriteTime//最后写入时间   
  114.         )   
  115. 因为在之前我们以通过RegQueryInfoKey函数获取了键的有关数据,所以在这里不再跟据ERROR_NO_MORE_ITEMS来实现了   
  116.   
  117. 其实现代码如下:   
  118.   
  119. for(dwIndex=0;dwIndex<KeyCnt;dwIndex++)        //枚举子键   
  120. {   
  121.     KeySize=KeyMaxLen+1;            //因为RegQueryInfoKey得到的长度不包括0结束字符,所以应加1   
  122.     szKeyName=(char*)malloc(KeySize);   
  123.     /**//*参数定义请参照获取子键/键值信息部分*/  
  124.     RegEnumKeyEx(hKey,dwIndex,szKeyName,&KeySize,NULL,NULL,NULL,NULL);//枚举子键   
  125.     printf(szKeyName);   
  126. }   
  127.   
  128. 最后需要注意的是在每次调用RegEnumKeyEx前必须重新将KeySize的值设为KeyMaxLen缓冲区的大小,因为每次函数返回时   
  129. KeySize的值会变成返回的键值的名称长度,随着循环次数这个值会变小,而可能出现无法枚举所有键值项的情况.   
  130.   
  131.   
  132.   
  133. 枚举键值信息   
  134.   
  135. 枚举键值信息的方法与枚举子键信息极为相似,可以用RegEnumValue函数实现,其函数原型如下:   
  136.   
  137. RegEnumValue(   
  138.         hkey,        //被枚举的键句柄   
  139.         dwIndex,    //子键索引编号   
  140.         lpValueName,    //键值名称   
  141.         lpcbValueName,    //键值名称长度   
  142.         lpReserved,    //系统保留,指定为0   
  143.         lpType,        //键值数据类型   
  144.         lpDate,        //键值数据   
  145.         lpcbDate    //键值数据长度   
  146.         )   
  147. 其实现代码如下:   
  148.   
  149. for(dwIndex=0;dwIndex<NameCnt;dwIndex++)    //枚举键值   
  150. {   
  151.     DateSize=MaxDateLen+1;   
  152.     NameSize=NameMaxLen+1;   
  153.     szValueName=(char *)malloc(NameSize);   
  154.     szValueDate=(LPBYTE)malloc(DateSize);   
  155.     /**//*参数定义请参照获取子键/键值信息部分*/  
  156.     RegEnumValue(hKey,dwIndex,szValueName,&NameSize,NULL,&Type,szValueDate,&DateSize);//读取键值   
  157.   
  158.     if(Type==REG_SZ)   
  159.     {   
  160.         /**//*判断键值项类型并做其它操作*/  
  161.     }   
  162.     if(Type==REG_DWORD)   
  163.     {   
  164.   
  165.     }   
  166.   
  167. }   
  168.   
  169. 与枚举子键相似,在每次循环中应该重新设置    数据长度DateSize=MaxDateLen+1键值名称长度NameSize=NameMaxLen+1   
  170.   
  171.   
  172. 创建/删除子键   
  173.   
  174. 创建子键跟打开子键差不多,要以用RegCreateKeyEx函数来实现,其原型如下   
  175.   
  176.       
  177. RegCreateKeyEx(   
  178.         hkey,            //父键句柄   
  179.         lpSubKey,        //子键句柄   
  180.         Reserved,        //系统保留,指定为0              
  181.         lpClass,        //定义子键类名,通常设为NULL   
  182.         dwOptions,        //创建子键时的选项   
  183.         samDesired,        //创建后操作权限   
  184.         lpSecurityAttributes,    //指向SECURITY_ATTRIBUTES结构,指定键句柄的继承性   
  185.         phkResult,        //返回创建句柄   
  186.         lpdwDisposition        //通常设为NULL   
  187.         )   
  188.   
  189. 个人感觉这个API 罗哩罗嗦不好使大多参数在大多数时候都放NULL,还不如16位下的API函数RegCreateKey用着方便   
  190.   
  191. 其实例代码如下:   
  192.   
  193. HKEY KEY;   
  194.   
  195. if (ERROR_SUCCESS!=RegCreateKey(HKEY_LOCAL_MACHINE,"SOFTWARE\Microsoft\Windows\MyKey",&KEY))   
  196. {   
  197.     MessageBox("创建失败!");   
  198. }else  
  199. {   
  200.     MessageBox("创建成功!");   
  201. }   
  202.   
  203. 嘿嘿 是不是简单多了?   
  204.   
  205. 不关什么事破坏总比创建要容易,删除一个键可以用RegDeleteKey()实现,它有两个参数原型如下   
  206.   
  207. RegDeleteKey(   
  208.         hkey,        //主键句柄   
  209.         lpSubKey,    //子键名称字符串   
  210.   
  211.         )   
  212. 如果想删除上面创建的MyKey子键可以用下面的代码实现:   
  213.   
  214. if(ERROR_SUCCESS==RegDeleteKey(HKEY_LOCAL_MACHINE,"SOFTWARE\Microsoft\Windows\MyKey"))   
  215. {   
  216.     AfxMessageBox("删除成功!");   
  217. }else  
  218. {   
  219.     AfxMessageBox("删除失败!");   
  220. }   
  221.           
  222. 需要注意的是 在创建子键时可以创建多级子键,比如   
  223.   
  224. RegCreateKey(HKEY_LOCAL_MACHINE,"SOFTWARE\Microsoft\Windows\MyKey1\MyKey2",&KEY)   
  225.   
  226. 如果MyKey1不存在的话那么它将先创建MyKey1再创建MyKey2,这一点与文件系统中创建目录是不同的   
  227.   
  228. 但是删除的时候却不能删除多级子键比如我想删除MyKey1那么我必须先删除MyKey2才可以,不过一个子键下面的多个键值   
  229. 可以一次删除.   
  230.   
  231. 木马编程DIY之注册表管理   文/图 冷风   
  232.   
  233. 创建/删除键值项   
  234.   
  235.   
  236. 创建键值可以用RegSetValueEx函数来实现,它的原型如下:   
  237.   
  238. RegSetValueEx(   
  239.         hkey,        //键句柄,键值项将保存在此键下   
  240.         lpValueName,    //键值项名称   
  241.         Reserved,    //系统保留,指定为0   
  242.         dwType,        //键值项类型   
  243.         lpDate,        //键值项数据   
  244.         cbDate        //键值项长度   
  245.         )   
  246. 使用这个函数的时个有一点需要注意,其中参数lpDate和cbDate的值要跟据dwType的值来设定,按常用设置我们分三种情况   
  247.   
  248. 1当dwType为REG_SZ时,这时跟通常一样,lpDate为要设置的数据, cbDate为数据的长度   
  249.   
  250. 2当dwType为REG_DWORD 时,cbDate应该设为4,为什么?因为不设为4就不对   
  251.   
  252. 3当dwType为REG_BINARY 时,cbDate也应该设为4,没有为什么了吧呵呵   
  253.   
  254. 如果调用时,键值项名称以经存在了会怎么样呢?答案是:覆盖 用新的键值项数据覆盖原来的,如果没有就新建一个   
  255.   
  256. 我们来看一下实现功能的实例代码:   
  257.   
  258. void CreateValue::OnCreate()   
  259. {   
  260.     HKEY    key;   
  261.     UpdateData(true);   
  262.     if(m_type=="REG_SZ")   
  263.     {   
  264.         if(RegOpenKeyEx(MKEY,SubKey,0,KEY_ALL_ACCESS,&key)==ERROR_SUCCESS)      
  265.         {   
  266.             if(::RegSetValueEx(key,m_name,0,REG_SZ,(const unsigned char *)m_date,MAX_PATH)==ERROR_SUCCESS)   
  267.             {   
  268.                 MessageBox("创建成功!");   
  269.             }   
  270.         }   
  271.     }   
  272.   
  273.     if(m_type=="REG_DWORD")   
  274.     {   
  275.         if(RegOpenKeyEx(MKEY,SubKey,0,KEY_ALL_ACCESS,&key)==ERROR_SUCCESS)      
  276.         {   
  277.             if(::RegSetValueEx(key,m_name,0,REG_DWORD,(const unsigned char *)m_date,4)==ERROR_SUCCESS)//注意数据长度应该设为4   
  278.             {   
  279.                 MessageBox("创建成功!");   
  280.             }   
  281.         }   
  282.     }   
  283.   
  284.     /**//*其它类型的设置*/  
  285. }   
  286.   
  287. 删除键值可以用RegDeleteValue来实现它的函数原型如下   
  288.   
  289. RegDeleteValue(   
  290.         hkey,        //父键句柄   
  291.         lpValueName    //要删除的键值项名称   
  292.         )   
  293. 其实例代码如下:   
  294.   
  295. HKEY key;   
  296. char value[MAX_PATH]="LengFeng"            //键值   
  297. LPCTSTR data="SOFTWARE\Microsoft\Windows\CurrentVersion\Run";//路径   
  298.   
  299. RegOpenKeyEx(HKEY_LOCAL_MACHINE,data,0,KEY_WRITE,&key);        //打开   
  300.   
  301. if(ERROR_SUCCESS==::RegDeleteValue(key,value))            //删除   
  302. {   
  303.     MessageBox("删除成功!");   
  304. }   
  305.   
  306.   
  307. 备份/恢复注册表   
  308.   
  309.   
  310. 备份和恢复注册表相对来说用的不是太多,我在程序中也没有加入这项功能,但为了这这篇文章完整一些,就用一个运行在CONSOLE   
  311. 下的小程序来讨论一下它们的实现   
  312.   
  313. 备份注册表可以用RegSaveKey函来实现 它的原形如下   
  314.   
  315. RegSaveKey(   
  316.         hkey,            //要备份的键句柄   
  317.         lpFile,        //保存信息的文件名称   
  318.         lpSecurityAttributes    //文件安全属性   
  319.         )   
  320.   
  321. hkey为要备份的键句柄,可以是系统预定义的,也可以是用RegOpenKey()打开或是RegCreateKeyEx()创建的   
  322. lpFile为保存信息的文件名称,注意这个文件必须是不存在的,而且也不能有扩展名(否则RegRestoreKey()函无法读取)   
  323. lpSecurityAttributes,它在NT系统中用来设置新文件的安全属性,通常设置为NULL   
  324.   
  325. 在使用这个函数时需要有SE_BACKUP_NAME权限,而这个权限是不可以在RegOpenKey()或是RegCreateKeyEx()指定的   
  326. 要做到这一点我们需要提升自己的权限,其具体实现如下代码如示:  
  327. #include <windows.h>               
  328. #include <stdio.h>  
  329. #include <stdlib.h>   
  330. void main()   
  331. {   
  332.     char strKey[]="Software\Microsoft\Internet Explorer";   
  333.     LPTSTR szSaveFileName;   
  334.     HKEY key;   
  335.     // 申请备份权限   
  336.     HANDLE hToken;   
  337.     TOKEN_PRIVILEGES tkp;   
  338.     if(!OpenProcessToken(GetCurrentProcess(),TOKEN_ADJUST_PRIVILEGES|TOKEN_QUERY,&hToken))   
  339.         return;   
  340.     LookupPrivilegeValue(NULL,SE_BACKUP_NAME,&tkp.Privileges[0].Luid);//申请SE_BACKUP_NAME权限   
  341.     tkp.PrivilegeCount=1;   
  342.     tkp.Privileges[0].Attributes=SE_PRIVILEGE_ENABLED;              
  343.     AdjustTokenPrivileges(hToken,FALSE,&tkp,0,(PTOKEN_PRIVILEGES)NULL,0);   
  344.     //开始备份工作   
  345.     szSaveFileName=LPTSTR("D:\KeyDate");        //注意文件不可存在否则无法成功   
  346.     RegOpenKeyEx(   
  347.                             HKEY_CURRENT_USER,   
  348.                             (LPCTSTR)strKey,   
  349.                             0,   
  350.                             KEY_ALL_ACCESS,   
  351.                             &key);   
  352.     RegSaveKey(key,szSaveFileName, NULL);   
  353.     RegCloseKey(key);   
  354. }   
  355.   
  356. 上面用到了提升权限的代码,以前杂志上面有很多可以参考一下来看,这样备份就完成了.而恢复可以用函数RegRestoreKey来实现   
  357. 它的原形如下   
  358. RegRestoreKey(   
  359.         hkey,            //要恢复的键句柄   
  360.         lpFile,        //保存信息的文件名称   
  361.         dwFlage        //标志是否易失   
  362.         )   
  363. 此函数的前两个参数可以与RegSaveKey相同,而参数dwFlage为TRUE的话是暂时恢复注册表,如果为FALSE则是永久修改注册表值.同样需要   
  364. 注意的是使用这个函数需要有SE_RESTORE_NAME权限 
posted on 2007-11-20 12:33 isrobert 阅读(1320) 评论(3)  编辑 收藏

评论

# re: 木马编程DIY之注册表管理 2007-11-21 16:02 gaoqing000
写得好

# re: 木马编程DIY之注册表管理 2007-11-21 19:40 sjdev
命令行下,reg add,reg query也许更方便。

# re: 木马编程DIY之注册表管理 2007-11-21 20:56 挑战杯
挑战病毒呀。

标题  
姓名  
主页
验证码 *
内容   
  登录  使用高级评论  Top
[使用Ctrl+Enter键可以直接提交]