获取组策略中的密码策略只用到了一个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;
}