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

就这么个小东西,一共弄了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怎么啦?干嘛我一回车就给我空一行呢

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值