C++ 读取组策略中的密码策略

获取组策略中的密码策略只用到了一个api函数 NetUserModalsGet, 具体用法去查MSDN。单靠这一个函数获取的内容还不全面,密码复杂性是否启用不能获取到,还需要再读一下注册表。读取HKEY_LOCAL_MACHINE\SAM\SAM\Domains\Account  键下的“F”键值--一段二进制数据,其中的第80(0开始)个字节为密码长度, 第76个字节为密码复杂性检查是否启用的标记。1代表启用,0代表未启用。 编译时选择uincode。

 

#include "stdafx.h"
#include <stdio.h>
#include <windows.h> 
#include <lm.h>
#include <Aclapi.h>

#pragma comment(lib,"Advapi32")
#pragma  comment(lib, "Netapi32.lib")

typedef  struct 
{
	int  Complex;  //密码复杂性是否已启用
	int  Len;	   //密码最小长度
}PwdComplex;

bool  ModifyRegCompetence(LPSTR Group, LPSTR key);

bool GetPwdComplex(PwdComplex* pCom);

int wmain(int argc, wchar_t *argv[])
{

	DWORD dwLevel = 0;
	USER_MODALS_INFO_0 *pBuf = NULL;
	NET_API_STATUS nStatus;
	LPTSTR pszServerName = NULL;

	if (argc > 2)
	{
		fwprintf(stderr, L"Usage: %s [\\\\ServerName]\n", argv[0]);
		exit(1);
	}

	if (argc == 2)
		pszServerName = argv[1];
	
	nStatus = NetUserModalsGet(pszServerName,
		dwLevel,
		(LPBYTE *)&pBuf);
	
	if (nStatus == NERR_Success)
	{
		if (pBuf != NULL)
		{
			printf("\tMinimum password length:  %d\n", pBuf->usrmod0_min_passwd_len);
			printf("\tMaximum password age (d): %d\n", pBuf->usrmod0_max_passwd_age/86400);
			printf("\tMinimum password age (d): %d\n", pBuf->usrmod0_min_passwd_age/86400);
			printf("\tForced log off time (s):  %d\n", pBuf->usrmod0_force_logoff);
			printf("\tPassword history length:  %d\n", pBuf->usrmod0_password_hist_len);
		}
	}
	
	else
		fprintf(stderr, "A system error has occurred: %d\n", nStatus);
	
	if (pBuf != NULL)
		NetApiBufferFree(pBuf);

	//修改权限对Administrators开放
	bool bModify = ModifyRegCompetence("Administrators", "MACHINE\\SAM\\SAM");

	PwdComplex complex;
	if(GetPwdComplex(&complex))
	{
		printf("\tPassword Complexity :  %s\n", (complex.Complex ?  "密码复杂性已使用":"密码复杂性已禁用"));
		printf("\tPassword len :  %d\n", complex.Len);
	}

	return 0;
}

bool  ModifyRegCompetence(LPSTR Group, LPSTR key)
{
	PACL pOldDacl=NULL;
	PACL pNewDacl=NULL;
	DWORD dRet;
	EXPLICIT_ACCESS_A eia;
	PSECURITY_DESCRIPTOR pSID=NULL;
	dRet = GetNamedSecurityInfoA(key,SE_REGISTRY_KEY,DACL_SECURITY_INFORMATION,NULL,NULL,&pOldDacl,NULL,&pSID);// 获取SAM主键的DACL 
	if(dRet != ERROR_SUCCESS)
		goto END;
	//创建一个ACE,允许Administrators组成员完全控制对象,并允许子对象继承此权限
	ZeroMemory(&eia,sizeof(EXPLICIT_ACCESS_A));
	BuildExplicitAccessWithNameA(&eia,Group, KEY_ALL_ACCESS,SET_ACCESS,SUB_CONTAINERS_AND_OBJECTS_INHERIT);
	// 将新的ACE加入DACL 
	dRet = SetEntriesInAclA(1,&eia,pOldDacl,&pNewDacl);
	if(dRet != ERROR_SUCCESS)
		goto END;
	// 更新SAM主键的DACL 
	dRet = SetNamedSecurityInfoA(key,SE_REGISTRY_KEY,DACL_SECURITY_INFORMATION,NULL,NULL,pNewDacl,NULL);
	if(dRet != ERROR_SUCCESS)
		goto END;
END:	
        //释放DACL和SID
	if(pNewDacl)
		LocalFree(pNewDacl);
	if(pSID)
		LocalFree(pSID);
	return 1;
}

bool GetPwdComplex(PwdComplex* pCom)
{
	HKEY hKey;
	long lResult;
	char buf[MAX_PATH] = {0};
	DWORD len = MAX_PATH;
	lResult = ::RegOpenKeyEx(HKEY_LOCAL_MACHINE, _T("SAM\\SAM\\Domains\\Account"),
		0, KEY_READ, &hKey);
	if(lResult != ERROR_SUCCESS)
		return 0;
	lResult = ::RegQueryValueEx(hKey, _T("F"), NULL, NULL, (LPBYTE)buf, &len);
	if(lResult != ERROR_SUCCESS)
		return 0;
	RegCloseKey(hKey);

	pCom->Complex =(int)buf[76];
	pCom->Len  = (int)buf[80];
	return 1;
}


 

  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值