目录
第一步:权限检查是否是管理员
第二步:编辑注册表
第三步:编辑注册表项的意义
第四步:源码
项目来源: GitHub - S12cybersecurity/WinDefenderKiller: Windows Defender Killer | C++ Code Disabling Permanently Windows Defender using Registry Keys
彻底关掉windows defender程序下载:https://download.csdn.net/download/clygo9/88104570
原理:在管理员权限下,通过编辑注册表,彻底关闭windows defender。(源码在末尾)
下面我们详细讲解,到底是如何关掉它的。
①介绍权限检查api:
在这个函数中,我们创建了一个代表管理员用户组的 SID,而不是提取出本进程运行的 SID,这是因为我们的目的是检查当前运行的进程是否有管理员权限,而不是检查这个进程的 SID 是否是管理员的 SID。
在 Windows 中,权限是通过访问令牌(access tokens)来分配的,每个进程在启动时都会从其父进程那里获得一个访问令牌。访问令牌包含了进程运行的用户和组的 SID,以及其他的一些安全信息。
当我们检查一个进程是否有管理员权限时,我们要做的是检查该进程的访问令牌中是否包含管理员组的 SID。这就是为什么我们需要创建一个代表管理员组的 SID,然后使用 `CheckTokenMembership` 函数来检查访问令牌中是否包含这个 SID。
如果我们直接提取出进程的 SID 并检查它是否是管理员的 SID,这只能告诉我们这个进程是由哪个用户启动的,但不能告诉我们这个进程是否有管理员权限。因为在 Windows 中,一个用户可能是管理员用户,但是他启动的进程却可能没有管理员权限,这就是所谓的 User Account Control (UAC) 技术。
所以,为了检查一个进程是否有管理员权限,我们需要创建一个管理员组的 SID,然后检查进程的访问令牌中是否包含这个 SID。
这里主要涉及了 Windows 系统中用于 SID(Security Identifier)(权限检查)相关操作的函数。下面逐个解释这些函数的作用:
1. AllocateAndInitializeSid 函数:
AllocateAndInitializeSid`函数用于创建一个 SID,该 SID 由指定的标识授权、指定的子授权和指定的 RID(Relative Identifier)数组组成。函数原型如下:
BOOL AllocateAndInitializeSid(
PSID_IDENTIFIER_AUTHORITY pIdentifierAuthority,
BYTE nSubAuthorityCount,
DWORD nSubAuthority0,
DWORD nSubAuthority1,
DWORD nSubAuthority2,
DWORD nSubAuthority3,
DWORD nSubAuthority4,
DWORD nSubAuthority5,
DWORD nSubAuthority6,
DWORD nSubAuthority7,
PSID *pSid
);- pIdentifierAuthority: 指定 SID 的标识授权,即 SID 的头部部分,通常为SECURITY_NT_AUTHORITY表示本地的安全授权。
- nSubAuthorityCount: 指定该 SID 包含的 RID 数量,通常为 2。
- nSubAuthority0 ~ nSubAuthority7: 指定 SID 的 RID 部分。
- pSid: 用于存储创建的 SID。在这个函数中,`AllocateAndInitializeSid` 创建了一个包含两个 RID 的 SID,表示管理员组的 SID,然后将其存储在 `AdministratorsGroup` 变量中。
2. CheckTokenMembership`函数:
CheckTokenMembership`函数用于检查一个令牌是否属于一个指定的 SID。如果令牌属于指定的 SID,函数返回 `TRUE`,否则返回 `FALSE`。函数原型如下:
BOOL CheckTokenMembership(
HANDLE TokenHandle,
PSID SidToCheck,
PBOOL IsMember
);- TokenHandle: 令牌的句柄,如果为 `NULL`,表示检查当前进程的令牌。
- SidToCheck: 要检查的 SID。
- IsMember: 用于存储检查结果,如果令牌属于指定的 SID,则为 `TRUE`,否则为 `FALSE`。在这个函数中,CheckTokenMembership`用于检查当前进程的令牌是否属于管理员组的 SID,并将结果存储在 `isAdmin` 变量中。
3. `FreeSid` 函数:
`FreeSid` 函数用于释放通过 `AllocateAndInitializeSid` 创建的 SID。函数原型如下:
BOOL FreeSid(
PSID pSid
);- pSid: 要释放的 SID。
在函数的最后,根据 `isAdmin` 的值,判断当前用户是否为管理员组的成员,并返回对应的结果。如果是管理员组成员,函数返回 `true`,否则返回 `false`。同时,需要注意在使用完 SID 后,通过调用 `FreeSid` 函数释放对应的内存空间,以防止内存泄漏。
总的来说,这段代码通过创建管理员组的 SID,并检查当前进程的令牌是否属于该 SID,来判断当前用户是否为管理员。
附:SID讲解:
SID(Security Identifier)是Windows操作系统中用于唯一标识安全主体(Security Principal)的一种标识符。安全主体可以是用户账户、组、计算机等,每个安全主体都会被赋予一个唯一的SID。SID在Windows系统中广泛用于标识用户和组的身份,以及控制资源的访问权限。
SID由一个变长的二进制数据组成,通常由以下几个部分构成:
1. SID标识授权(SID Identifier Authority):这是一个6字节(48位)的值,它标识了SID的管理者。Windows系统定义了一些标准的授权,其中最常见的是:
- SECURITY_NULL_SID_AUTHORITY: 表示一个空SID,不表示任何安全主体。
- SECURITY_WORLD_SID_AUTHORITY: 表示"Everyone"组的SID,即所有用户。
- SECURITY_LOCAL_SID_AUTHORITY: 表示本地机器上的用户和组的SID。
- SECURITY_NT_AUTHORITY: 表示Windows NT 系列操作系统的SID。2. 亚权限数量(Subauthority Count):这个字节表示SID中的亚权限(Subauthority)数量。
3. 亚权限(Subauthority):亚权限是一个32位的值,用于标识SID的特定安全主体。每个SID可以有多个亚权限,它们以顺序方式排列,形成了一个完整的SID。
例如,一个标准用户账户的SID可能如下所示:
S-1-5-21-3623811015-3361044348-30300820-1013
其中:
- S: 表示这是一个SID。
- 1: 表示授权标识为`SECURITY_NT_AUTHORITY`。
- 5-21-3623811015-3361044348-30300820-1013: 表示亚权限部分,标识了该用户账户的唯一身份信息。SID在Windows系统中的作用非常重要,它们用于在安全描述符(Security Descriptor)中标识安全主体的身份,确定其权限和访问控制列表(ACL)等信息。当用户或者进程请求访问某个资源时,系统会根据SID和访问控制列表来判断其是否有权限进行操作。
总结一下,SID是Windows系统中用于唯一标识安全主体的一种标识符,它包含了授权标识、亚权限数量和亚权限等信息。SID在访问控制中起着至关重要的作用,用于确定安全主体的权限和资源的访问控制。
更多sid介绍:
https://www.cnblogs.com/suv789/p/17507591.html
GitHub - S12cybersecurity/WinDefenderKiller: Windows Defender Killer | C++ Code Disabling Permanently Windows Defender using Registry Keys
在Windows编程中,注册表操作是非常常见的,一些基本的注册表操作函数如下:
//
1.RegOpenKeyEx函数是用来打开注册表中的一个已经存在的键。
函数原型如下:
LONG RegOpenKeyExA(
HKEY hKey,
LPCSTR lpSubKey,
DWORD ulOptions,
REGSAM samDesired,
PHKEY phkResult
);
参数说明:- `hKey`: 预定义的注册表主键句柄。
这些预定义的注册表主键句柄是在Windows中访问注册表信息时用来定位信息存储位置的。它们表示的是注册表的主要部分,每个部分包含了一类特定的信息。具体来说:
- `HKEY_CLASSES_ROOT`:包含了所有的文件类型和它们的关联程序,以及OLE信息。当你在Windows资源管理器中双击一个文件时,就会通过这部分的信息找到对应的程序来打开文件。
- `HKEY_CURRENT_USER`:包含了当前登录用户的所有首选项和用户环境信息。这个部分的信息会在用户登录时加载,而且每个用户都有自己的一份。
- `HKEY_LOCAL_MACHINE`:包含了系统的硬件、软件、和安装设置的信息。这部分的信息在系统启动时加载,对所有用户都相同。
- `HKEY_USERS`:包含了所有用户的个人首选项信息。这部分信息包括了`HKEY_CURRENT_USER`的内容,以及其他用户的信息。
- `HKEY_CURRENT_CONFIG`:包含了硬件配置信息。这部分信息在每次系统启动时根据硬件配置动态生成。
通过这些主键句柄,你可以在注册表中定位到你需要操作的信息的具体位置。例如,如果你需要修改某个文件类型的关联程序,你就可以通过`HKEY_CLASSES_ROOT`找到相应的信息进行修改。
- `lpSubKey`: 指向一个null-terminated的字符串,该字符串包含了从给定的hKey到打开的键之间的路径。
- `ulOptions`: 保留,必须为零。
- `samDesired`: 它是一个访问掩码,它用来定义对注册表键的访问类型。
你可以组合使用以下值(定义在 Winnt.h 文件中)来定义所需的权限:
- `KEY_READ`:请求查询值的权限、枚举、创建和删除子键的权限,以及请求通知权限。这等价于 `KEY_QUERY_VALUE | KEY_ENUMERATE_SUB_KEYS | KEY_NOTIFY` 的组合,和标准访问权限 `SYNCHRONIZE`。
- `KEY_WRITE`:请求创建、删除和设置子键值的权限。这等价于 `KEY_SET_VALUE | KEY_CREATE_SUB_KEY` 的组合。
- `KEY_EXECUTE`:请求执行对应于 "读取" 的访问权限。在注册表函数中,这相当于 `KEY_READ`。
- `KEY_ALL_ACCESS`:请求所有可能的访问权限。这等价于 `KEY_QUERY_VALUE | KEY_SET_VALUE | KEY_CREATE_SUB_KEY | KEY_ENUMERATE_SUB_KEYS | KEY_NOTIFY | KEY_CREATE_LINK` 的组合,并且包含标准访问权限 `SYNCHRONIZE`。
- `KEY_QUERY_VALUE`:请求查询键值的权限。
- `KEY_SET_VALUE`:请求创建、删除或设置键值的权限。
- `KEY_CREATE_SUB_KEY`:请求创建子键的权限。
- `KEY_ENUMERATE_SUB_KEYS`:请求枚举子键的权限。
- `KEY_NOTIFY`:请求更改通知的权限。
- `KEY_CREATE_LINK`:请求创建符号链接的权限。
记住,当你使用 `RegOpenKeyEx` 函数时,必须指定你想要的访问权限。如果你的访问权限过高,可能会导致操作失败;如果你的访问权限过低,你可能无法完成你想做的事情。
- `phkResult`: 是一个指针,它指向一个变量,该变量接收打开的键的句柄。
返回值:如果函数成功,返回ERROR_SUCCESS。如果函数失败,返回一个系统错误码。
这个函数在Windows编程中经常被用到,它使得程序可以在注册表中的一个特定的键下读取和写入值。
2. RegCreateKeyEx:创建注册表键。如果指定的键已存在于注册表中,则函数打开现有的键。原型:LONG RegCreateKeyEx(HKEY hKey, LPCTSTR lpSubKey, DWORD Reserved, LPTSTR lpClass, DWORD dwOptions, REGSAM samDesired, const LPSECURITY_ATTRIBUTES lpSecurityAttributes, PHKEY phkResult, LPDWORD lpdwDisposition);
参数说明:- `hKey`: 预定义的注册表主键句柄,例如HKEY_CLASSES_ROOT、HKEY_CURRENT_USER、HKEY_LOCAL_MACHINE、HKEY_USERS或HKEY_CURRENT_CONFIG。
- `lpSubKey`: 指向一个null-terminated的字符串,该字符串包含了从给定的hKey到打开的键之间的路径。
- `Reserved`: 保留,必须为零。
- `lpClass`: 指向一个null-terminated的字符串,它包含了用户定义的类类型。这个参数一般为NULL。
- `dwOptions`: 设置子键的选项。这个值可以是0,表示默认设置;也可以是REG_OPTION_NON_VOLATILE,表示子键是非易失的,信息会保存到硬盘。
- `samDesired`: 它是一个访问掩码,指定了对键的安全访问。例如:KEY_READ、KEY_WRITE、KEY_EXECUTE、KEY_ALL_ACCESS等。
- `lpSecurityAttributes`: 指向一个SECURITY_ATTRIBUTES结构,它决定了新创建的键是否可以被子进程继承,以及它的安全描述符。如果这个参数为NULL,那么键不能被继承,而且使用默认的安全描述符。
- `phkResult`: 是一个指针,它指向一个变量,该变量接收打开的键的句柄。
- `lpdwDisposition`: 指向一个变量,这个变量接收一个标志,这个标志说明了函数是创建了一个新的键,还是打开了一个已经存在的键。这个标志可以是:REG_CREATED_NEW_KEY或REG_OPENED_EXISTING_KEY。
返回值:如果函数成功,返回ERROR_SUCCESS。如果函数失败,返回一个系统错误码。
这个函数在需要在注册表中创建新的子键,或者需要打开已经存在的子键进行操作时使用。
/
/
3. RegSetValueEx:设置指定名称的注册表项的数据。如果项不存在于注册表中,函数将创建它。
原型:LONG RegSetValueEx(HKEY hKey, LPCTSTR lpValueName, DWORD Reserved, DWORD dwType, const BYTE* lpData, DWORD cbData);
参数说明:- `hKey`: 已打开的注册表键的句柄,或者是预定义的注册表句柄,例如HKEY_CLASSES_ROOT、HKEY_CURRENT_USER、HKEY_LOCAL_MACHINE、HKEY_USERS或HKEY_CURRENT_CONFIG。
- `lpValueName`: 指向一个null-terminated的字符串,该字符串表示要设置的值的名称。如果值不存在,则该函数将创建它。
- `Reserved`: 保留,必须为零。
- `dwType`: 要设置的值的类型。
REG_BINARY
: 二进制数据。任何形式的二进制数据都可以存储在此类型的值中。
REG_DWORD
: 32位数字。这种类型的值通常用于存储布尔值(True/False)、开/关设置或数值设置。
REG_DWORD_LITTLE_ENDIAN
: 以小端(little-endian)字节顺序存储的32位数值。在x86架构(Windows的主要硬件平台)中,这种类型与REG_DWORD
相同。
REG_DWORD_BIG_ENDIAN
: 以大端(big-endian)字节顺序存储的32位数值。这个类型在Windows中很少使用。
REG_EXPAND_SZ
: 可扩展的字符串数据。这种类型的字符串包含变量引用,如"%USERNAME%",它在读取时会被环境变量的值替换。
REG_LINK
: 符号链接。这个类型很少在Windows的注册表中使用。
REG_MULTI_SZ
: 多字符串。这种类型的值包含一个或多个以null字符分隔的字符串,最后以两个null字符结尾。
REG_NONE
: 没有定义的值类型。这种类型的值中的数据没有特定的类型。
REG_QWORD
: 64位数字。这种类型的值可以存储大于4,294,967,295的数值。
REG_QWORD_LITTLE_ENDIAN
: 以小端(little-endian)字节顺序存储的64位数值。在x86架构(Windows的主要硬件平台)中,这种类型与REG_QWORD
相同。
REG_SZ
: 字符串。这种类型的值包含一个以null字符结束的字符串。这些数据类型让注册表可以存储各种类型的用户设置和系统信息,使得注册表可以支持各种不同的配置需求。
- lpData: 指向一个缓冲区,该缓冲区包含要为指定注册表项设置的数据。
- cbData: 指定`lpData`参数中的数据的大小,以字节为单位。
返回值:如果函数成功,返回ERROR_SUCCESS。如果函数失败,返回一个非零的错误代码。
/
/
4. RegCloseKey:关闭注册表键并释放所有的内存资源。
原型:`LONG RegCloseKey(HKEY hKey);`
/
/
5. RegDeleteKeyEx:删除注册表中的一个子键及其所有子项。
原型:LONG RegDeleteKeyEx(HKEY hKey, LPCTSTR lpSubKey, REGSAM samDesired, DWORD Reserved);
/
/
6. `RegQueryValueEx`:获取指定注册表项的数据。
原型:`LONG RegQueryValueEx(HKEY hKey, LPCTSTR lpValueName, LPDWORD lpReserved, LPDWORD lpType, LPBYTE lpData, LPDWORD lpcbData);`
参数说明:
hKey
: 已打开的注册表键的句柄,或者是预定义的注册表句柄,例如HKEY_CLASSES_ROOT、HKEY_CURRENT_USER、HKEY_LOCAL_MACHINE、HKEY_USERS或HKEY_CURRENT_CONFIG。
lpValueName
: 指向一个以null结尾的字符串,该字符串包含要查询的值的名称。
lpReserved
: 保留,必须为NULL。
lpType
: 指向一个变量,该函数将数据类型放入该变量。可能的类型值包括:REG_BINARY、REG_DWORD、REG_DWORD_LITTLE_ENDIAN、REG_DWORD_BIG_ENDIAN、REG_EXPAND_SZ、REG_LINK、REG_MULTI_SZ、REG_NONE、REG_QWORD、REG_QWORD_LITTLE_ENDIAN、REG_SZ。如果lpType
为NULL,那么类型信息不会被返回。
lpData
: 指向一个缓冲区,该缓冲区接收值的数据。该缓冲区必须具有足够的空间来存放数据。
lpcbData
: 指向一个变量,该函数将实际数据的大小(以字节为单位)放入该变量。如果lpData
为NULL,该函数返回数据的大小,而不返回数据。返回值:如果函数成功,返回ERROR_SUCCESS。如果函数失败,返回一个非零的错误代码。
总的来说,
RegQueryValueEx
函数用于查询注册表键的值。如果你需要读取和解析注册表值,这个函数是很有用的。/
代码中的每个注册表项都控制着Windows Defender的一个特定功能。下面是对它们的解释:
DisableAntiSpyware
: 如果将此值设置为1,它将禁用Windows Defender的反间谍软件组件。
Real-Time Protection
: 这是一个新创建的注册表键,用于存储实时保护设置。
DisableRealtimeMonitoring
: 如果将此值设置为1,它将禁用Windows Defender的实时监控。
DisableBehaviorMonitoring
: 如果将此值设置为1,它将禁用Windows Defender的行为监控。
DisableScanOnRealtimeEnable
: 如果将此值设置为1,它将禁用在实时保护启用时进行的扫描。
DisableOnAccessProtection
: 如果将此值设置为1,它将禁用访问保护。
DisableIOAVProtection
: 如果将此值设置为1,它将禁用Windows Defender的输入输出访问验证保护。这段代码的目的是修改这些注册表项以关闭Windows Defender的特定功能。这可能是因为用户希望使用其他的安全软件,或者Windows Defender与某些应用程序有冲突,需要临时禁用。但这也可能被恶意软件用于关闭系统的保护。
#include
#include
#include
using namespace std;
// 段代码通过操作Windows的注册表来禁用Windows Defender的相关功能。
// 请注意,修改注册表可能会对系统造成影响,请谨慎操作。同时,确保在以管理员权限运行此程序时执行,否则可能无法成功修改注册表。
// 定义了一个名为isUserAdmin的函数,用于检查当前用户是否是管理员(拥有管理员权限)。如果是管理员,返回true,否则返回false。
bool isUserAdmin() {
BOOL isAdmin = FALSE;
SID_IDENTIFIER_AUTHORITY NtAuthority = SECURITY_NT_AUTHORITY; //定义了一个SID_IDENTIFIER_AUTHORITY结构体变量NtAuthority,表示SID的标识授权。
PSID AdministratorsGroup; // 定义了一个PSID类型的变量AdministratorsGroup,表示管理员组的SID。
// AllocateAndInitializeSid函数用于创建一个SID,该SID由指定的标识授权、指定的子授权和指定的RID数组组成。
// 其中,NtAuthority 是一个 SID_IDENTIFIER_AUTHORITY 结构体,表示 SID 的标识授权。2 是子授权的数量。SECURITY_BUILTIN_DOMAIN_RID 和 DOMAIN_ALIAS_RID_ADMINS 是两个子授权的值,它们共同定义了一个代表管理员用户组的 SID。最后一个参数 &AdministratorsGroup 是一个指向 PSID 类型变量的指针,这个函数会为其分配内存并初始化为代表管理员用户组的 SID。
if (!AllocateAndInitializeSid(&NtAuthority, 2, SECURITY_BUILTIN_DOMAIN_RID,DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0,&AdministratorsGroup)) {
return false;
}
// CheckTokenMembership函数用于检查一个令牌是否属于一个指定的SID。如果令牌属于指定的SID,返回true,否则返回false。
if (!CheckTokenMembership(NULL, AdministratorsGroup, &isAdmin)) {
FreeSid(AdministratorsGroup); // FreeSid函数用于释放一个SID。
return false;
}
FreeSid(AdministratorsGroup); // FreeSid函数用于释放一个SID。
return isAdmin != FALSE;
}
// disable defender via registry
int main(int argc, char* argv[]) {
HKEY key; // 定义了一个HKEY类型的变量key,表示注册表项的句柄。
HKEY new_key;
DWORD disable = 1;
if (!isUserAdmin()) {
cout << "please run this program as administrator." << endl;
return -1;
}
// RegOpenKeyEx函数用于打开一个注册表项,如果成功,返回ERROR_SUCCESS,否则返回错误代码。
LONG res = RegOpenKeyEx(HKEY_LOCAL_MACHINE, "SOFTWARE\\Policies\\Microsoft\\Windows Defender", 0, KEY_ALL_ACCESS, &key);
if (res == ERROR_SUCCESS) {
RegSetValueEx(key, "DisableAntiSpyware", 0, REG_DWORD, (const BYTE*)&disable, sizeof(disable)); // RegSetValueEx函数用于设置一个注册表项的值。
RegCreateKeyEx(key, "Real-Time Protection", 0, 0, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, 0, &new_key, 0); // RegCreateKeyEx函数用于创建一个注册表项。
RegSetValueEx(new_key, "DisableRealtimeMonitoring", 0, REG_DWORD, (const BYTE*)&disable, sizeof(disable));
RegSetValueEx(new_key, "DisableBehaviorMonitoring", 0, REG_DWORD, (const BYTE*)&disable, sizeof(disable));
RegSetValueEx(new_key, "DisableScanOnRealtimeEnable", 0, REG_DWORD, (const BYTE*)&disable, sizeof(disable));
RegSetValueEx(new_key, "DisableOnAccessProtection", 0, REG_DWORD, (const BYTE*)&disable, sizeof(disable));
RegSetValueEx(new_key, "DisableIOAVProtection", 0, REG_DWORD, (const BYTE*)&disable, sizeof(disable));
RegCloseKey(key); // RegCloseKey函数用于关闭一个注册表项。
RegCloseKey(new_key);
}
cout << "Windows Defender has been disabled." << endl;
cout << "Please restart your computer to take effect." << endl;
getchar();
return 0;
}