(更新:注意编译运行文中程序后留意administrator可能会变成active=no,undocument,undocument........哈哈)
要写个修改本地安全策略的工具,本以为修改注册表就行了,没想到还挺复杂,改策略,对应的注册表项会变,倒过来,改对应的注册表项,策略没变,郁闷
[HKEY_LOCAL_MACHINE\SAM\SAM\Domains\Account]        |--------------------------------修改次数
"F"=hex:02,00,01,00,00,00,00,00,e0,7c,9e,21,1a,12,c6,01,43,00,00,00,00,00,00,\        00 ~ 22
  00,00,80,d2,16,47,b9,ff,ff,00,80,2c,ab,6d,fe,ff,ff,00,00,00,00,00,00,00,80,\        23 ~ 47
  00,cc,1d,cf,fb,ff,ff,ff,00,cc,1d,cf,fb,ff,ff,ff,00,00,00,00,00,00,00,00,f1,\        48 ~ 72
  03,00,00,00,00,00,00,02,00,18,00,00,00,00,00,01,00,00,00,03,00,00,00,01,00,\        73 ~ 97
         ^^        ^
       ||        |
       ||        |__ 密码长度最小值
       ||
       ||__    密码必须符合复杂性要求(0为禁止)
       |___ 用可还原的加密来存储密码

第 76 80 位

[HKEY_LOCAL_MACHINE\SAM\SAM\Domains\Account\Users\000001F5]
"F"=hex:02,00,01,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,\
  00,80,c6,50,1f,2b,12,c6,01,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,\
  f5,01,00,00,01,02,00,00,15,02,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,\
               ^
               |____ Guest账号(15禁用,14启用)

第 56 位


比如第76位,
0的时候是"密码必须符合复杂性要求 - 禁用" & "用可还原的加密来存储密码 - 禁用"
14的时候"密码必须符合复杂性要求 - 禁用" & "用可还原的加密来存储密码 - 启用"

有些比如密码长度,锁定什么的用NetUserModalsSet的USER_MODALS_INFO_0和USER_MODALS_INFO_3结构可以搞定。
审核策略用LsaSetInformationPolicy也好搞定,都有现成的代码。

账户策略->密码策略中的"密码必须符合复杂性要求"和"用可还原的加密来存储密码",还有安全选项中的内容,似乎没有公开文档

没想到写个这个破工具还要用到未公开API函数,之前在网上查了下有没有相关代码或文档什么的,查了N天google和MSDN,有问的,没有答的,或者就是答非所问,没办法只能自己想办法了
之前使用apimonitor(N多此类工具,都不好用,这个也不咋样),在修改策略的时候获得了如下信息
API    Name    Return    Value    Module    Name    Time    Start    IsEntry    API
Process:    c:\windows\system32\mmc.exe(5052)    ,    Thread:2976
SceGetServerProductType    0    (0x0)    C:\WINDOWS\system32\SCECLI.dll    2008-1-27    23:10:38    True
SceGetServerProductType    0    (0x0)    C:\WINDOWS\system32\SCECLI.dll    2008-1-27    23:10:38    True
SceGetServerProductType    0    (0x0)    C:\WINDOWS\system32\SCECLI.dll    2008-1-27    23:10:38    True
SceGetServerProductType    0    (0x0)    C:\WINDOWS\system32\SCECLI.dll    2008-1-27    23:10:38    True
SceGetServerProductType    0    (0x0)    C:\WINDOWS\system32\SCECLI.dll    2008-1-27    23:10:38    True
SceGetServerProductType    0    (0x0)    C:\WINDOWS\system32\SCECLI.dll    2008-1-27    23:10:38    True
SceOpenProfile        0    (0x0)    C:\WINDOWS\system32\SCECLI.dll    2008-1-27    23:10:38    True
SceGetSecurityProfileInfo    6    (0x6)    C:\WINDOWS\system32\SCECLI.dll    2008-1-27    23:10:38    True
SceFreeMemory        0    (0x0)    C:\WINDOWS\system32\SCECLI.dll    2008-1-27    23:10:38    True
SceGetSecurityProfileInfo    0    (0x0)    C:\WINDOWS\system32\SCECLI.dll    2008-1-27    23:10:38    True
SceFreeMemory        0    (0x0)    C:\WINDOWS\system32\SCECLI.dll    2008-1-27    23:10:38    True
SceGetServerProductType    0    (0x0)    C:\WINDOWS\system32\SCECLI.dll    2008-1-27    23:11:34    True
SceGetServerProductType    0    (0x0)    C:\WINDOWS\system32\SCECLI.dll    2008-1-27    23:11:34    True
SceGetServerProductType    0    (0x0)    C:\WINDOWS\system32\SCECLI.dll    2008-1-27    23:11:34    True
SceRollbackTransaction    12    (0xC)    C:\WINDOWS\system32\SCECLI.dll    2008-1-27    23:11:55    True
SceCloseProfile        0    (0x0)    C:\WINDOWS\system32\SCECLI.dll    2008-1-27    23:11:55    True
SceFreeProfileMemory    0    (0x0)    C:\WINDOWS\system32\SCECLI.dll    2008-1-27    23:11:55    True
SceFreeProfileMemory    0    (0x0)    C:\WINDOWS\system32\SCECLI.dll    2008-1-27    23:11:55    True
SceFreeProfileMemory    0    (0x0)    C:\WINDOWS\system32\SCECLI.dll    2008-1-27    23:11:55    True
SceFreeProfileMemory    1    (0x1)    C:\WINDOWS\system32\SCECLI.dll    2008-1-27    23:11:55    True
Process:    c:\windows\system32\mmc.exe(5052)    ,    Thread:3928
SceOpenProfile        0    (0x0)    C:\WINDOWS\system32\SCECLI.dll    2008-1-27    23:10:49    True
SceGetSecurityProfileInfo    0    (0x0)    C:\WINDOWS\system32\SCECLI.dll    2008-1-27    23:10:49    True
SceCloseProfile        0    (0x0)    C:\WINDOWS\system32\SCECLI.dll    2008-1-27    23:10:49    True
SceFreeMemory        0    (0x0)    C:\WINDOWS\system32\SCECLI.dll    2008-1-27    23:10:49    True
SceFreeMemory        0    (0x0)    C:\WINDOWS\system32\SCECLI.dll    2008-1-27    23:10:49    True
SceFreeMemory        0    (0x0)    C:\WINDOWS\system32\SCECLI.dll    2008-1-27    23:10:56    True
SceUpdateSecurityProfile    0    (0x0)    C:\WINDOWS\system32\SCECLI.dll    2008-1-27    23:10:56    True
Process:    c:\windows\system32\mmc.exe(5052)    ,    Thread:5472
SceFreeMemory        0    (0x0)    C:\WINDOWS\system32\SCECLI.dll    2008-1-27    23:11:43    True
SceUpdateSecurityProfile    0    (0x0)    C:\WINDOWS\system32\SCECLI.dll    2008-1-27    23:11:43    True

Summary Information
API Name: SceOpenProfile
API Define: (Undefine API)
Time Start: 00:11:49.015
Duration: 0.000 ms
Module Name: C:\WINDOWS\system32\SCECLI.dll
Is Entry API: True
Process: C:\WINDOWS\system32\mmc.exe
Thread: 4152
Before Call Parameters
Pointer  Paramter0: 29449864 (0x1C15E88)
Pointer  Paramter1: 1 (0x1)
Pointer  Paramter2: 23981584 (0x16DEE10)
Pointer  Paramter3: (null)
Pointer  Paramter4: 8629392 (0x83AC90)
Pointer  Paramter5: (null)
After Call Parameters
Pointer  Paramter0: 29449864 (0x1C15E88)
Pointer  Paramter1: 1 (0x1)
Pointer  Paramter2: 23981584 (0x16DEE10)
Pointer  Paramter3: (null)
Pointer  Paramter4: 8629392 (0x83AC90)
Pointer  Paramter5: (null)
Return
0 (0x0)

Summary Information
API Name: SceGetSecurityProfileInfo
API Define: (Undefine API)
Time Start: 00:11:49.015
Duration: 0.001 ms
Module Name: C:\WINDOWS\system32\SCECLI.dll
Is Entry API: True
Process: C:\WINDOWS\system32\mmc.exe
Thread: 4152
Before Call Parameters
Pointer  Paramter0: 688576 (0xA81C0)
Pointer  Paramter1: 302 (0x12E)
Pointer  Paramter2: 65535 (0xFFFF)
Pointer  Paramter3: 8629480 (0x83ACE8)
Pointer  Paramter4: 23981572 (0x16DEE04)
Pointer  Paramter5: 2088955995 (0x7C82F05B)
After Call Parameters
Pointer  Paramter0: 688576 (0xA81C0)
Pointer  Paramter1: 302 (0x12E)
Pointer  Paramter2: 65535 (0xFFFF)
Pointer  Paramter3: 8629480 (0x83ACE8)
Pointer  Paramter4: 23981572 (0x16DEE04)
Pointer  Paramter5: 2088955995 (0x7C82F05B)
Return
0 (0x0)
GetLastError
Value:3758096642
Description:

Summary Information
API Name: SceCloseProfile
API Define: (Undefine API)
Time Start: 00:11:49.109
Duration: 0.000 ms
Module Name: C:\WINDOWS\system32\SCECLI.dll
Is Entry API: True
Process: C:\WINDOWS\system32\mmc.exe
Thread: 4152
Before Call Parameters
Pointer  Paramter0: 23981584 (0x16DEE10)
Pointer  Paramter1: 2088955995 (0x7C82F05B)
Pointer  Paramter2: 8629392 (0x83AC90)
Pointer  Paramter3: 8570560 (0x82C6C0)
Pointer  Paramter4: 8629296 (0x83AC30)
Pointer  Paramter5: 302124616 (0x12020E48)
After Call Parameters
Pointer  Paramter0: 23981584 (0x16DEE10)
Pointer  Paramter1: 2088955995 (0x7C82F05B)
Pointer  Paramter2: 8629392 (0x83AC90)
Pointer  Paramter3: 8570560 (0x82C6C0)
Pointer  Paramter4: 8629296 (0x83AC30)
Pointer  Paramter5: 302124616 (0x12020E48)
Return
0 (0x0)

Summary Information
API Name: SceAddToNameStatusList
API Define: (Undefine API)
Time Start: 00:11:49.109
Duration: 0.000 ms
Module Name: C:\WINDOWS\system32\SCECLI.dll
Is Entry API: True
Process: C:\WINDOWS\system32\mmc.exe
Thread: 4152
Before Call Parameters
Pointer  Paramter0: 23981476 (0x16DEDA4)
Pointer  Paramter1: 787520 (0xC0440)
Pointer  Paramter2: 76 (0x4C)
Pointer  Paramter3: 1 (0x1)
Pointer  Paramter4: (null)
Pointer  Paramter5: 8629392 (0x83AC90)
After Call Parameters
Pointer  Paramter0: 23981476 (0x16DEDA4)
Pointer  Paramter1: 787520 (0xC0440)
Pointer  Paramter2: 76 (0x4C)
Pointer  Paramter3: 1 (0x1)
Pointer  Paramter4: (null)
Pointer  Paramter5: 8629392 (0x83AC90)
Return
0 (0x0)

Summary Information
API Name: SceFreeMemory
API Define: (Undefine API)
Time Start: 00:11:49.109
Duration: 0.000 ms
Module Name: C:\WINDOWS\system32\SCECLI.dll
Is Entry API: True
Process: C:\WINDOWS\system32\mmc.exe
Thread: 4152
Before Call Parameters
Pointer  Paramter0: 1514080 (0x171A60)
Pointer  Paramter1: 311 (0x137)
Pointer  Paramter2: (null)
Pointer  Paramter3: 8629392 (0x83AC90)
Pointer  Paramter4: (null)
Pointer  Paramter5: 4 (0x4)
After Call Parameters
Pointer  Paramter0: 1514080 (0x171A60)
Pointer  Paramter1: 311 (0x137)
Pointer  Paramter2: (null)
Pointer  Paramter3: 8629392 (0x83AC90)
Pointer  Paramter4: (null)
Pointer  Paramter5: 4 (0x4)
Return
0 (0x0)


Summary Information
API Name: SceUpdateSecurityProfile
API Define: (Undefine API)
Time Start: 00:11:52.203
Duration: 0.000 ms
Module Name: C:\WINDOWS\system32\SCECLI.dll
Is Entry API: True
Process: C:\WINDOWS\system32\mmc.exe
Thread: 4152
Before Call Parameters
Pointer  Paramter0: (null)
Pointer  Paramter1: 1 (0x1)
Pointer  Paramter2: 28866104 (0x1B87638)
Pointer  Paramter3: 4 (0x4)
Pointer  Paramter4: (null)
Pointer  Paramter5: 8629056 (0x83AB40)
After Call Parameters
Pointer  Paramter0: (null)
Pointer  Paramter1: 1 (0x1)
Pointer  Paramter2: 28866104 (0x1B87638)
Pointer  Paramter3: 4 (0x4)
Pointer  Paramter4: (null)
Pointer  Paramter5: 8629056 (0x83AB40)
Return
0 (0x0)

郁闷的是before call和after call参数都没变,不知道是软件问题还是未注册的原因
请教了czy,帮忙逆向了一下,高手就是高手,没多久就给我一段asm代码解决了密码复杂度的策略
.386
.model stdcall,flat
option casemap:none
include 
\masm32\include\windows.inc
include \masm32\include\user32.inc
include \masm32\include\kernel32.inc
include \masm32\include\masm32.inc
include \masm32\include\shlwapi.inc
include \masm32\include\shell32.inc

includelib \masm32\lib\user32.lib
includelib \masm32\lib\kernel32.lib
includelib \masm32\lib\masm32.lib
includelib \masm32\lib\shlwapi.lib
includelib \masm32\lib\shell32.lib

.const

.data
nini    db 'a',0
seclib  db 'scecli.dll',0
myapi   db 'SceUpdateSecurityProfile',0
mydata  db 2eh,01h,00h,00h,0feh,0ffh,0ffh,0ffh,0feh,0ffh,0ffh,0ffh,0feh,0ffh,0ffh,0ffh,00h,00h,00h,00h,0feh,0ffh,0ffh,0ffh,0feh,0ffh,0ffh,0ffh,0feh,0ffh,0ffh,0ffh,0feh,0ffh,0ffh,0ffh,0feh,0ffh,0ffh,0ffh,0feh,0ffh,0ffh,0ffh,00h,00h,00h,00h
;偏移10H如为0就是禁用,为1就是启用
.data?

.code

start:
    
    invoke    
MessageBox,0,offset nini,offset nini,1  
    
invoke  LoadLibraryA,offset seclib
    
invoke  GetProcAddress,eax,offset myapi
    
mov     esi,eax
    
push    4
    
mov     eax,offset mydata
    
push    eax
    
xor     edi,edi
    
inc     edi
    
push    edi    
    
xor     ebx,ebx
    
push    ebx
    
call    esi

    
invoke    ExitProcess,0

end start


编译执行没问题,OK,改成C++的版本,老是提示内存不能写(内嵌汇编也不行),还请教了小榕,貌似变量定义的问题
使用OD动态跟踪,发现asm版本的生成exe后执行mydata变量是在.data可读写数据段里面,而C++的版本是在.rdata只读数据段里面,使用OD的时候修改数据测试可以成功,然后再修改C++代码
#include <stdio.h>
#include <windows.h>
char *sam2;
int main()
{
    
sam2 new char[99];
    
char *sam 
    
"\x2e\x01\x00\x00\x0fe\x0ff\x0ff\x0ff"
        "\x0fe\x0ff\x0ff\x0ff\x0fe\x0ff\x0ff\x0ff"
        "\x00\x00\x00\x00\x0fe\x0ff\x0ff\x0ff"
        "\x0fe\x0ff\x0ff\x0ff\x0fe\x0ff\x0ff\x0ff"
        "\x0fe\x0ff\x0ff\x0ff\x0fe\x0ff\x0ff\x0ff"
        "\xfe\x0ff\x0ff\x0ff\x00\x00\x00\x00"
;
    
memcpy(sam2sam49);
    
HINSTANCE hInst;
    
hInst=LoadLibraryA("scecli.dll");
    
typedef BOOL (__stdcall *MYFUNC)(intintchar*, int);
    
MYFUNC fun=NULL;
    
fun=(MYFUNC)GetProcAddress(hInst,"SceUpdateSecurityProfile");
    
int 4;
    
fun(NULL,TRUE,sam2,i);

/*    __asm
    {
        mov esi,fun
        push 4
        mov eax,sam2
        push eax
        xor edi,edi
        inc edi
        push edi
        xor ebx,ebx
        push ebx
        call esi
    }
*/
    
return 0;
}


或者

#include <stdio.h>
#include <windows.h>
char sam[]=
    
"\x2e\x01\x00\x00\x0fe\x0ff\x0ff\x0ff"
    "\x0fe\x0ff\x0ff\x0ff\x0fe\x0ff\x0ff\x0ff"
    "\x10\x00\x00\x00\x0fe\x0ff\x0ff\x0ff"
    "\x0fe\x0ff\x0ff\x0ff\x0fe\x0ff\x0ff\x0ff"
    "\x0fe\x0ff\x0ff\x0ff\x0fe\x0ff\x0ff\x0ff"
    "\xfe\x0ff\x0ff\x0ff\x00\x00\x00\x00"
    "\x00\x00\x00\x00\x00\x00\x00\x00"
    "\x00\x00\x00\x00\x00\x00\x00\x00"
    "\x00\x00\x00\x00\x00\x00\x00\x00"
    "\x00\x00\x00\x00\x00\x00\x00\x00"
    "\x00\x00\x00\x00\x00\x00\x00\x00"
    "\x00\x00\x00\x00\x00\x00\x00\x00"
    "\x00\x00\x00\x00\x00\x00\x00\x00"
    "\x00\x00\x00\x00\x00\x00\x00\x00"
;

int main()
{
    
HINSTANCE hInst;
    
hInst=LoadLibraryA("scecli.dll");
    
typedef BOOL (__stdcall *MYFUNC)(intint,char*, int);
    
MYFUNC fun=NULL;
    
fun=(MYFUNC)GetProcAddress(hInst,"SceUpdateSecurityProfile");
    
printf("sam=0x%08X\n",&sam);
    
printf("%s",sam);
    
fun(NULL,TRUE,sam,4);
/*    __asm
    {
        mov esi,fun
        push 4
        mov eax,sam2
        push eax
        xor edi,edi
        inc edi
        push edi
        xor ebx,ebx
        push ebx
        call esi
    }
*/
    
return 0;
}


发现如果SceUpdateSecurityProfile函数的第三个参数,后面如果有其它数据,会报错,要是后面大段\x00数据的话,就通过,undocument api只能这样了,估计第三个参数应该是个什么结构。在我的Windows2003 CN SP1上测试成功(执行后,会让本地策略“密码复杂度”那项变成禁用,还有其它一些策略如审核策略也会更改,应该是第三个参数的每个位对应着不同的策略,安全选项中的似乎不会变),小榕的Windows2003 EN SP1上不能成功,估计是这个函数太底层了,应该有更高一层的函数先判断不同的操作系统版本,选择不同的参数,然后在调用SceUpdateSecurityProfile函数。
还有安全选项里面的内容,估计是其它函数,有空我也softice一下。

最后帖下关于变量定义后在内存什么地方的一段代码,不一定什么时候有用

//main.cpp
int a = 0; 全局初始化区
char *p1; 全局未初始化区
main()
{
int b; 栈
char s[] = "abc"; 栈
char *p2; 栈
char *p3 = "123456"; 123456\0在常量区,p3在栈上。
static int c =0; 全局(静态)初始化区
p1 = (char *)malloc(10);
p2 = (char *)malloc(20);
分配得来得10和20字节的区域就在堆区。
strcpy(p1, "123456"); 123456\0放在常量区,编译器可能会将它与p3所指向的"123456"优化成一个地方。
}

全局
char *str="\x20\x20\x20\x20\x20\x20\x20\x20";
str存在.data段,是一个指针,内容为一个地址(地址在.rdata区段),这个地址指向的内容为字符串

全局
char str[]="\x20\x20\x20\x20\x20\x20\x20\x20";
str存在.data段,是一个指针,指针指向字符串