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怎么啦?干嘛我一回车就给我空一行呢

DACL & SACL

在前一个文章MutexEx 中,Mutex的创建,使用也要对其权限进行设置..同样的,如果我们想在不同的帐号使用这个Mutex,我们可能也不得不使用另一种方式的身份模拟. 在Win32中,我们可以通...
  • u014421422
  • u014421422
  • 2016年03月16日 15:20
  • 982

一个设置默认输入法的小程序

用C++写了个设置默认输入法的小程序,E文不好,捣鼓几天才终于弄明白了一些了 首先是删除输入法 使用 UnloadKeyboardLayout 卸载Imm32框架的输入法,只作用于当前,重新启...
  • zhoujiaxq
  • zhoujiaxq
  • 2014年03月12日 09:36
  • 2345

开发一个方便修改文件名的小程序

近期看到刚毕业的师弟师妹们上传了毕业照,有的人把每张照片都修改了与照片内容相关的文件名,可见很怀念大学里的人。我想手动一张一张的修改照片太麻烦了,就用工作使用的Delphi写一个小程序,支持一边翻阅图...
  • Jing5022
  • Jing5022
  • 2015年06月02日 20:58
  • 734

DACL(自由访问控制列表)详解

DACL(自由访问控制列表)详解
  • kaylc
  • kaylc
  • 2011年02月09日 15:52
  • 7390

2月16日,一个改文件名的小程序

导读:   /*改名字,把程序在当前目录下运行,将把当前目录下的所有文件改名为*.sys,按数字顺序,,并   *生成文件renAme.cmd运行后,恢复原来的名字,数字从0开始,由于目录 . .....
  • yingfox
  • yingfox
  • 2007年11月13日 22:36
  • 388

4月22日

      好久没写了,来北大青鸟也有一个多月了,每天都能学到新知识,这样的生活让人来不及觉得无聊,挺好的。      不过,自己还是不够努力了,这样总会在心里有些愧疚,觉得对不起家人。但刚开始嘛,就...
  • kaixin578
  • kaixin578
  • 2007年04月22日 22:04
  • 328

微信小程序修改数组的值

var authority = ‘buttonGroup.authority’ that.setData({ [authority]: parseInt(level) ...
  • lrq112233
  • lrq112233
  • 2017年08月24日 19:54
  • 678

通过简单C编程实现注册表修改

把事情做到最简单,做到最多人能接受,才是最好的,鉴于最多的人学的是C,所以全部用C写一下对注册表的枚举,更改,删除的操作。     以HKEY_LOCAL_MACHINE\Software\Miscr...
  • shantikai
  • shantikai
  • 2015年01月23日 21:00
  • 455

微信小程序开发:显示本地天气

前言微信小程序是一种不需要下载安装即可使用的应用,它实现了应用“触手可及”的梦想,用户扫一扫或者搜一下即可打开应用。也体现了“用完即走”的理念,用户不用关心是否安装太多应用的问题。微信“小程序”可以为...
  • Chation_99
  • Chation_99
  • 2017年02月03日 13:57
  • 216

小程序学习--1

小程序学习–1简介 微信小程序就是一个类似 RN 的轮子,可以快速开发,有一定的适用场景,但是也有其局限性, 适合于 低频 但重要的需求 微信小程序提供了什么? 底层API 和 组件 微...
  • mjzhang1993
  • mjzhang1993
  • 2017年01月13日 11:01
  • 917
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:4月22,,,一个改注册表DACL的小程序
举报原因:
原因补充:

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