转载自 用 C++ 修改本地安全策略
(更新:注意编译运行文中程序后留意 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 多此类工具,都不好用,这个也不咋样),在修改策略的时候获得了如下信息
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 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 代码解决了密码复杂度的策略
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 `.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++ 代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 `#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 (sam2, sam, 49 ); HINSTANCE hInst; hInst=LoadLibraryA("scecli.dll" ); typedef BOOL (__stdcall *MYFUNC) (int , int , char *, int ) ; MYFUNC fun=NULL ; fun=(MYFUNC)GetProcAddress(hInst,"SceUpdateSecurityProfile" ); int i = 4 ; fun(NULL ,TRUE,sam2,i); return 0 ; }`
或者
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 `#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) (int , int ,char *, int ) ; MYFUNC fun=NULL ; fun=(MYFUNC)GetProcAddress(hInst,"SceUpdateSecurityProfile" ); printf ("sam=0x%08X\n" ,&sam); printf ("%s" ,sam); fun(NULL ,TRUE,sam,4 ); return 0 ; }`
发现如果 SceUpdateSecurityProfile
函数的第三个参数,后面如果有其它数据,会报错,要是后面大段 \x00 数据的话,就通过,undocument api 只能这样了,估计第三个参数应该是个什么结构。在我的 Windows2003 CN SP1 上测试成功(执行后,会让本地策略 “密码复杂度” 那项变成禁用,还有其它一些策略如审核策略也会更改,应该是第三个参数的每个位对应着不同的策略,安全选项中的似乎不会变),小榕的 Windows2003 EN SP1 上不能成功,估计是这个函数太底层了,应该有更高一层的函数先判断不同的操作系统版本,选择不同的参数,然后在调用 SceUpdateSecurityProfile
函数。 还有安全选项里面的内容,估计是其它函数,有空我也 softice 一下。
最后帖下关于变量定义后在内存什么地方的一段代码,不一定什么时候有用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 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 段,是一个指针,指针指向字符串