4月22,,,一个改注册表DACL的小程序

原创 2005年04月22日 23:41:00

就这么个小东西,一共弄了2天半!! 当然也加上中间去学习object和DACL什么的,以前虽然看过,,可书看了一遍就只有忘的份儿,,必须要有应用,要有学习的欲望,,无聊的书会变的很好读,,,,

     感受就是不要放弃和要细心,,,如果开始时通过RegOpenKey得到的hKey来改DACL不成功的时候就算了的话,,也就真的算了,,,,虽然不是什么大事,,但提醒着自己无论多大或多小的事都可以试试再试试,,,,,,还有就是细心了ret = LookupAccountName(NULL,user_groupnAme,&sid,&sidlen,siddomAin,&siddomAinlen,
       &sidtype);就这一句,我把user_groupnAme写成"everyone"了,,,费了我一晚上找这个错误,,到是练了自己调试的能力,可还是觉得不值,况且这是毛病啊

   注册表中每个键都是一个object,,,windows里面全是object,,,把phrAck 59 0x10里的例子拿出来吧

typedef struct _OBJECT_HEADER {
/*000*/ DWORD        PointerCount;       // number of references
/*004*/ DWORD        HandleCount;        // number of open handles
/*008*/ POBJECT_TYPE ObjectType;         // pointer to object type struct
/*00C*/ BYTE         NameOffset;         // OBJECT_NAME offset
/*00D*/ BYTE         HandleDBOffset;     // OBJECT_HANDLE_DB offset
/*00E*/ BYTE         QuotaChargesOffset; // OBJECT_QUOTA_CHARGES offset
/*00F*/ BYTE         ObjectFlags;        // OB_FLAG_*
/*010*/ union
        { // OB_FLAG_CREATE_INFO ? ObjectCreateInfo : QuotaBlock
/*010*/    PQUOTA_BLOCK        QuotaBlock;
/*010*/    POBJECT_CREATE_INFO ObjectCreateInfo;
        };
/*014*/ PSECURITY_DESCRIPTOR SecurityDescriptor;
/*018*/ } OBJECT_HEADER, *POBJECT_HEADER;

不同的object有不同的ObjectType,,,头全都是一样的Object_HeAder在Object体的前面,Object体里有啥我还不清楚,,object_heAder里面的这些NAmeOffset,Object_Type结构什么的,在内存中的位置都在Object_HeAder的前面,,也就是如果要找NAmeOffset对应的东西,要Object_HeAder - NAmeOffset

kd> !object /Device/PhysicAlMemory
Object: e1001250  Type: (81899040) Section
    ObjectHeader: e1001238
    HandleCount: 0  PointerCount: 3
    Directory Object: 8189a180  Name: PhysicalMemory
kd> dd e1001238 L 6
e1001238  00000003 00000000 81899040 16300020
e1001248  00000001 e1008bd8
kd> !sd e1008bd8    //查看SecurityDescriptor
->Revision: 0x1
->Sbz1    : 0x0
->Control : 0x8004
            SE_DACL_PRESENT
            SE_SELF_RELATIVE
->Owner   : S-1-5-32-544
->Group   : S-1-5-18
->Dacl    :
->Dacl    : ->AclRevision: 0x2
->Dacl    : ->Sbz1       : 0x0
->Dacl    : ->AclSize    : 0x44
->Dacl    : ->AceCount   : 0x2
->Dacl    : ->Sbz2       : 0x0
->Dacl    : ->Ace[0]: ->AceType: ACCESS_ALLOWED_ACE_TYPE
->Dacl    : ->Ace[0]: ->AceFlags: 0x0
->Dacl    : ->Ace[0]: ->AceSize: 0x14
->Dacl    : ->Ace[0]: ->Mask : 0x000f001f
->Dacl    : ->Ace[0]: ->SID: S-1-5-18

->Dacl    : ->Ace[1]: ->AceType: ACCESS_ALLOWED_ACE_TYPE
->Dacl    : ->Ace[1]: ->AceFlags: 0x0
->Dacl    : ->Ace[1]: ->AceSize: 0x18
->Dacl    : ->Ace[1]: ->Mask : 0x0002000d
->Dacl    : ->Ace[1]: ->SID: S-1-5-32-544

->Sacl    :  is NULL

DACL中包含一个个的ACE,每个ACE都表示一条访问的规则,里面有一个用户或组的SID,一个ACCESSMASK表示相应的权限位,如果是DENY_ACE则表示禁止ACCESSMASK标示的权限,ALLOW_ACE则表示允许,DENY_ACE总在ALLOW_ACE前面发挥作用,也就是同时存在两个同样ACCESSMASK,同样SID的ACE,一个是DENY的,一个是ALLOW的,,则结果是DENY的.

SACL表示的不是权限了,而是那些需要记录,System access-control list (SACL) Specifies which operations by which users should be logged in the security audit log.这个可能就是系统中的审核吧,,没用过SACL,

程序就那么几行,很简单,在知道该怎么做后,就那么几个API就完事了,可在这之前可把我郁闷坏了,,上隔壁宿舍去打cs,加了20个expert的机器人,在一个全是狙的雪地里,,嘿嘿,,爽死了

用RegOpenKey来得到注册表键的HANDLE恐怕不可行,开始也没成功,因为比如读MACHINE/SAM/SAM本来就没有读的权限,当打开一个HANDLE的时候固定要失败了,,,唉,,,这样的程序无非就是几个API拼一起,没资格笑话人家JAVA的像积木了,,,,对操作系统了解的少,就只能这样,,,,,,

程序改权限的时候必须被改的键里有写DACL的权限,,由于缺省的SAM里就有AdministrAtors组有写DACL的权限,,所以就省事了,,,如果没有的话,,,inside win2k里说:管理员可以把自己程序进程的token的权限提到SeTAkeOwnerShip

SeTakeOwnershipRequired to take ownership of an object without being granted discretionary access

If the caller has the take-ownership privilege, the security system grants write-owner access and then examines the DACL. However, if write-owner access was the only access requested by a caller with take-ownership privilege, the security system grants that access and never examines the DACL.             也就是说有了SeTAkeOwnerShip就可以有write-owner的权限,,然后就用那些写owner的函数把owner改进去,SetSecurityDescriptorOwner

If the caller is the owner of the object, the read-control and write-DACL access rights are granted. If these rights were the only access rights that caller requested, access is granted without examining the DACL.然后也就有了write-DACL的权限,,,然后啥都可以了,, 

不过程序没那么多功能,,一般的话只要不动原来的write-DACL就可以了

/*********************************************************************
 * 该注册表权限 在注册表有写DACL的权限下
 *                                      writen by uty@uaty
 *********************************************************************/
#include <stdio.h>
#include <windows.h>
#include <winnt.h>
#include <aclapi.h>
#include <accctrl.h>

//#define SPECIFIC_RIGHTS_ALL           0x0000FFFF
//#define STANDARD_RIGHTS_REQUIRED      0x000F0000
//#define STANDARD_RIGHTS_ALL           0x001F0000


int getprivilege(LPCTSTR  privilege);

int main(int Argc,char* Argv[])
{
 long      ret=0;
 PSECURITY_DESCRIPTOR  pSecurityDescriptor;
 PACL      pAcl;
 PACL      pNewAcl;
 //TRUSTEE      trustee;
 //ACCESS_MASK     AccessmAsk;
 EXPLICIT_ACCESS    eA;
 char*      user_groupnAme;
 char*      keypAth;
 
 char      sid[64];
 DWORD      receivedAce;
 DWORD      sidlen;
 DWORD      sidtype;
 char      siddomAin[128];
 DWORD      siddomAinlen;
 int       Aceindex = 0;

 //char      usernAme[128];///debug
 //DWORD      usernAmelen = 128;

 if (Argc != 5){
  printf("usAge: %s registrypAth USER|GROUP  usernAme|groupnAme  deny|Allow|reAdonly/n/n",Argv[0]);
  printf("it's A simple work /n"
   "registerpAth like this MACHINE//SECURITY..../n"
   "predefined registry keys:/"CLASSES_ROOT/", /"CURRENT_USER/", /"MACHINE/", and /"USERS/"/n/n");
  return 0;
 };

 keypAth    = Argv[1];
 user_groupnAme  = Argv[3];

 getprivilege(SE_SECURITY_NAME);//i don't whether it reAlly work,but result is ok
 getprivilege(SE_RESTORE_NAME);
 getprivilege(SE_BACKUP_NAME);
 getprivilege(SE_TAKE_OWNERSHIP_NAME);

 getprivilege(SE_DEBUG_NAME);


 ret = GetNamedSecurityInfo(keypAth,SE_REGISTRY_KEY,DACL_SECURITY_INFORMATION,
        NULL,NULL,&pAcl,NULL,&pSecurityDescriptor);
 if (ret != ERROR_SUCCESS){
  printf("GetNAmedSecurityInfo fAiled: %d/n  ret %d/n",GetLastError(),ret);
  LocalFree(pSecurityDescriptor);
  return -1;
 }
///this pArt just show the former ACE AccessmAsk
 /*trustee.pMultipleTrustee   = NULL;
 trustee.MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
 trustee.TrusteeForm     = TRUSTEE_IS_NAME;
 trustee.TrusteeType     = TRUSTEE_IS_USER;////
 trustee.ptstrName     = user_groupnAme;////

 ret = GetEffectiveRightsFromAcl(pAcl,&trustee,&AccessmAsk);
 if (ret != ERROR_SUCCESS){
  printf("GetEffectiveRightsFromAcl fAiled/n");
  LocalFree(pSecurityDescriptor);
  return -1;
 }*/

///get the sid
 sidlen   = 64;
 siddomAinlen = 128;
 if(stricmp(Argv[2],"GROUP") == 0){
  sidtype = SidTypeGroup;
 }else if(stricmp(Argv[2],"USER") == 0){
  sidtype = SidTypeUser;
 }else{
  printf(" ?? ,USER or GROUP/n");
  exit(1);
 }

 ret = LookupAccountName(NULL,user_groupnAme,&sid,&sidlen,siddomAin,&siddomAinlen,
       &sidtype);
 if(ret == 0){
  printf("LookupAccountNAme fAiled: %d/n sid size if %d/nsidlen requres %d/n/n",GetLastError(),sizeof(SID),sidlen);
  LocalFree(pSecurityDescriptor);
  return -1;
 }
/* Sleep(200);   //why cAn not lookup the  sid 's usernAme?  still don't know

 ret = LookupAccountSid(NULL,(PSID)(sid),usernAme,&usernAmelen,
      siddomAin,&siddomAinlen,&sidtype);
 printf("debug: ret = %d, GetLAstError = %d/n",ret,GetLastError());
 printf("%s/n",usernAme);
 return 0;///////////////
*/ 
 
////删除同用户或同组的以前的ACE
 while(GetAce(pAcl,Aceindex,(PVOID)&receivedAce)){
  if(EqualSid((PSID)sid,(PSID)(receivedAce+sizeof(ACE_HEADER)+sizeof(ACCESS_MASK)))){//if equAl,return nonzero
   DeleteAce(pAcl,Aceindex);
   continue;
  }else{
   Aceindex++;
  }
 }

/*
 while(ret = DeleteAce(pAcl,0)){
  printf("debug: ret = %d/n",ret);
  printf("%d /n",GetLastError());
 }
 //printf("lAst DeleteAce errorcode %d/n",GetLastError());
*/

 memset(&eA,0,sizeof(EXPLICIT_ACCESS));
 
 if (stricmp(Argv[4],"ALLOW") == 0){
  eA.grfAccessMode      = GRANT_ACCESS;
  eA.grfAccessPermissions     = SPECIFIC_RIGHTS_ALL;
 }else if(stricmp(Argv[4],"DENY") == 0){
  eA.grfAccessMode      = DENY_ACCESS;
  eA.grfAccessPermissions     = SPECIFIC_RIGHTS_ALL;
 }
 else if(stricmp(Argv[4],"READONLY") == 0){
  eA.grfAccessMode      = DENY_ACCESS;
  eA.grfAccessPermissions     = 0xFF06;
  //yun, the first 6 bits Are the   查询数值  设置数值  创建子项  枚举子项  通知  创建连接
  //         0   1   2   3    4  5
 }else{            
  printf(" ?? , ALLOW or DENY or READONLY/n");
  exit(1);
 }
  

 eA.grfInheritance      = CONTAINER_INHERIT_ACE;
 eA.Trustee .MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
 eA.Trustee .pMultipleTrustee   = NULL;
 eA.Trustee .TrusteeForm     = TRUSTEE_IS_NAME;
 if(stricmp(Argv[2],"GROUP") == 0){
  eA.Trustee .TrusteeType     = TRUSTEE_IS_GROUP;////
 }else if(stricmp(Argv[2],"USER") == 0){
  eA.Trustee .TrusteeType     = TRUSTEE_IS_USER;////
 }else{
  printf(" ?? ,USER or GROUP/n");
  exit(1);
 }
 eA.Trustee .ptstrName     = user_groupnAme;////


 ret = SetEntriesInAcl(1,&eA,pAcl,&pNewAcl);
 if(ret != ERROR_SUCCESS){
  printf("SetEntriesInAcl fAiled: %d/n ",GetLastError());
  LocalFree(pSecurityDescriptor);
  return -1;
 }
 ret = SetNamedSecurityInfo(keypAth,SE_REGISTRY_KEY,DACL_SECURITY_INFORMATION,NULL,NULL,pNewAcl,NULL);
 if(ret != ERROR_SUCCESS){
  printf("SetNAmedSecurityInfo fAiled: %d/n ",GetLastError());
  LocalFree(pSecurityDescriptor);
  return -1;
 }

 return 0;
}
//--------------------------------------------------------------------
int getprivilege(LPCTSTR  privilege)
{
 ////////////////////////
 HANDLE     hProcessToken=NULL;
 TOKEN_PRIVILEGES  tp;
 LUID     luid;
//打开token 
 if (!OpenProcessToken(GetCurrentProcess(),TOKEN_ALL_ACCESS,&hProcessToken)){
  printf("/nOpen Current Process Token fAiled:%d",GetLastError());
  return -1;
 }


//查找所需权限的luid
 if(!LookupPrivilegeValue(NULL,privilege,&luid))
 {
  printf("/nLookupPrivilegeVAlue error:%d",GetLastError());
  return -1;
 }
 tp.PrivilegeCount =1;/////////表示只有一个// one privilege to set
 tp.Privileges [0].Luid = luid;
 tp.Privileges [0].Attributes = SE_PRIVILEGE_ENABLED;
//给token加权限
 AdjustTokenPrivileges(hProcessToken,FALSE,&tp,sizeof(TOKEN_PRIVILEGES)
  ,(PTOKEN_PRIVILEGES)NULL,(PDWORD)NULL);

 if (GetLastError()!=ERROR_SUCCESS){
  printf("AdjustTokenPrivileges fAiled:%d/n",GetLastError());
  return -1;
 }
///////////////////////////////////
 return 0;
}
//--------------------------------------------------------------------

这个blog怎么啦?干嘛我一回车就给我空一行呢

c# 更改注册表开机启动+mutex(互斥,同一时间同一台电脑只能运行一个程序)

1.更改注册表,使开机启动 在HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Run下增加一个键,键值为程序路径即可,代码如...
  • lcawen
  • lcawen
  • 2013年04月12日 12:56
  • 1170

一个.exe文件通过注册表获取另一个.exe最新的版本来打开应用程序

通过工程项目launcher编译生成的launcher.exe,通过访问注册表的方式,打开编译好了的Viewer.exe(一个看图软件)。...
  • Rainif
  • Rainif
  • 2017年07月18日 00:09
  • 303

一个注册表权限设置程序例子

  • 2009年08月11日 15:27
  • 19KB
  • 下载

自己搞,带注释,适合初学者:C程序设计语言练习1-22 把较长的输入行折成短一些的两行或多行,折行的位置在输入行的第n列之前的最后一个非空格之后

自己搞,带注释,适合初学者:C程序设计语言练习1-22 把较长的输入行折成短一些的两行或多行,折行的位置在输入行的第n列之前的最后一个非空格之后。要保证程序能够智能地处理输入行很长及在指定的列前没有空...
  • ycjnx
  • ycjnx
  • 2017年06月22日 14:38
  • 419

连载《一个程序猿的生命周期》-22.缺了一条腿的公司

百木-ITer职业交流 群-北京 :141588103                就这样,在大公司刚刚工作两天的时间,再次跳槽到一个小公司。对外宣传有近100人的公司,实际上只有20多人。我知...

[南阳OJ-No.22]素数求和问题|现在给你N个数(0<N<1000),现在要求你写出一个程序,找出这N个数中的所有素数,并求和。

南阳OJ-No.22 时间限制3000ms,内存限制65535KB 描述 现在给你N个数(0 输入 第一行给出整数M(0 每组测试数据第一行给你N,代表该组测试数据的数量。 接下来...
  • dj741
  • dj741
  • 2017年02月09日 16:07
  • 299

[教程] 4月22更新:WIN下懒人版安装教程(U盘版和硬盘版)

原文出处:http://bbs.pcbeta.com/viewthread-920341-1-1.html 谢谢博主大神,基本上看得懂, 不懂的就google一下, 我6个小时下载软件到安装完成。 ...
  • ashuai81
  • ashuai81
  • 2012年09月29日 17:13
  • 13132

【 日常 】 小排序合集 17年4月12日22:17 [ 10 ]

/*前言: 好多天前准备记录下自己的坎坷修仙的点滴,以后希望能留下【珍贵的回忆】,萌新的日常代码,大佬互喷*/ 代码写的比较繁琐,多多见谅,萌新每天都在努力改变自己 心情:不想吐槽啥,恩对,不吐...

【黄斤德】午夜评:4月22现货黄金、现货白银午夜操作策略

周三(4月22日)纽约盘中,美国3月成屋销售总数年化519万户,年化月率上升6.1,均好于预期,美指小幅走高至98关口附近。现货黄金白银跌逾1%,黄金刷新日内低位1193.45美元/盎司,白银刷新日低...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:4月22,,,一个改注册表DACL的小程序
举报原因:
原因补充:

(最多只允许输入30个字)