注册表自启动基础

  1. 注册表自启动基础
  2. 修改注册表的两种方法
    1. 手动修改注册表
    2. 命令行修改注册表
    3. 查询注册表键值
  3. 隐藏注册表的创建
    1. 原理
    2. 实现

注册表自启动基础

修改注册表实现开机子启动的方法的好处在于,全版本的windows系统都适用。

而修改注册表的方法有两种,gui界面和命令行。

修改注册表的两种方法

手动修改注册表

首先regedit调用注册表。

打开注册表之后,找到如下位置HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Run

以桌面上的1.exe文件为例,在run右侧新建一个字符串值,名字任取,我这里设置为aaa。首先查看1.exe文件的路径:
C:\Users\ASUS\Desktop\1.exe

然后双击aaa并修改它的值为:
"C:\Users\ASUS\Desktop\1.exe" /start

image-20230106160655173

(图片虽然是txt,但是是一样的效果)

image-20230106160722409

命令行修改注册表

通过命令行修改注册表的主要方法为用reg命令来改。
可以在命令行输入以下命令查看帮助:
reg /?

image-20230106161009102

我们需要用到的一个参数是:
reg add
这表示增加或修改。没有的就增加,已有的就覆盖(名称及类型)。该命令的语法及参数的含义可以在命令行中输入:

reg add /?

image-20230106161228642

这里我们需要注意的地方有两个,首先,路径是要被双引号包起来的,其次,双引号后面有一个空格,空格后面才是/`start`参数。
构造语句如下:

reg add HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Run /v bbb /t REG_SZ /d "\"C:\Users\ASUS\Desktop\1.exe\" /start" /f

注意,/d参数后面的双引号内的全部内容是表示要写入bbb键的内容,而由于该参数会识别双引号,因此这里用了转义。同时,空格也是被包含在双引号内的,因此不必再单独处理。
注意修改注册表最好以管理员身份运行命令提示符,以免出现权限不够的情况。

查询注册表键值

reg query
用以上命令即可实现。当然如果不知道语法可以通过以下命令进行查询
reg query /?

举个例子,查询刚刚写入的注册表中的键值

reg query HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Run /v bbb

隐藏注册表的创建

原理

首先讲讲,隐藏注册表的原理吧。

注册表键值名称经过特殊构造: 以”\0”作为开头,后面加上任意字符(不能为数字)

对于Windows系统,”\0”(即0x0000)会被识别为字符串的结束符,所以在对该字符串读取的过程中,遇到开头的”\0”,会被解析成结束符,提前截断,导致读取错误

而使用Native API设定注册表,需要使用结构体OBJECT_ATTRIBUTES作为参数, 指定读取的字符串长度

只要长度设定正常,就能够读取正确的字符串,避免这个bug

所以,我们可以通过Native API来创建这个特殊的注册表名

更为重要的是,像regedit.exe和其他对注册表的操作,通常会调用Win32 API,这就导致该注册表无法被读取,也就实现了所谓的”隐藏”

综上,创建方法为: 通过Native API创建一个以”\0”开头的键值

[Native API_百度百科 (baidu.com)](https://baike.baidu.com/item/Native API/5877113?fr=aladdin)

实现

实现部分我在网上看都是一些工具的使用,感觉不太行,其中有个工具已经找不到了。然后我问了一下新朋友(chatgpt

image-20230106171650419

算是加深了一些印象。

当然可以!首先,您可以使用本机API——RegCreateKeyEx来创建一个注册表键。该函数需要提供根键的句柄、以“\\0”开头的字符串作为键的名称以及相应的保护属性,例如访问权限等属性,以及用于指定所创建键的方式的标志。然后,您可以调用函数RegSetValueEx来设置键值,此函数需要您提供要设置的键的句柄,其值的名称以及具体的值,以在Windows注册表中隐藏键值。

随后又问了下手工创建

image-20230106192024145

完整步骤如下:

1. 首先在你想要创建键值的注册表项下,创建一个新的字符串键值;

2. 使用本机API函数RegSetValueExA()来创建以”\\0”开头的新键值,它的完整代码如下:

// 函数声明
LONG RegSetValueExA(
HKEY hKey,
LPCSTR lpValueName,
DWORD Reserved,
DWORD dwType,
CONST BYTE *lpData,
DWORD cbData
);

// 调用例子
LONG res = RegSetValueExA(hKey, "\\0MyStringKey", 0, REG_SZ, (const BYTE*)"MyStringValue", strlen("MyStringValue"));

(感觉不对呢,仅供参考吧)

随后我还是找了一个工具,工具的实现原理和上面的一样。但是这个工具需要我们下载下来之后自行编译,链接如下

outflanknl/SharpHide: Tool to create hidden registry keys. (github.com)

那么简单介绍一下工具的使用方法

若要创建隐藏的注册表(运行)项,请执行以下操作:
SharpHide.exe action=create keyvalue="C:\Windows\Temp\Bla.exe" 

若要创建带有参数的隐藏注册表(运行)项,请执行以下操作:
SharpHide.exe action=create keyvalue="C:\Windows\Temp\Bla.exe" arguments="arg1 arg2"

删除隐藏的注册表(运行)项:
SharpHide.exe action=delete

开始实践,用命令添加了一个没参数的,

image-20230106231937737

现在来看注册表的里面是没有键值的

image-20230106232344606

现在重新启动一下,看看是不是成功写入启动项了

image-20230106232447518

成功了!

最后值得一提的是,该工具也适用于Cobalt Strike的execute-assembly。

execute-assembly实现原理(非托管C++代码调用C#) 狐狸教程 (freeaihub.com)

后续来进行进一步的研究


转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。后续可能会有评论区,不过也可以在github联系我。