论坛: 原创软件 标题: 再帮最后一个忙:怎样判断是否超级用户 复制本贴地址    
作者: ricky [ricky]    版主   登录
还有最后一个问题需要解决:取得用户名列表后,用哪个参数或者函数判断用户名的级别

地主 发表时间: 09/01 13:39

回复: flashsky [flashsky]   论坛用户   登录
用组函数取出administrators组的用户
其中的用户就是特权用户

B1层 发表时间: 09/01 19:05

回复: ricky [ricky]   版主   登录
我原来也以为是这样,可是做实验时发现所有用户都是user,不知道问题出在哪儿了

B2层 发表时间: 09/02 08:23

回复: flashsky [flashsky]   论坛用户   登录
取用户组的代码如下:
STDMETHODIMP CNBTool::getgroupuser()
{
    LPWSTR pszServerName = NULL;   
    LPWSTR pszGroupName = NULL;   
    dwLevel =2;
    LPLOCALGROUP_MEMBERS_INFO_2  pBuf;
    LPLOCALGROUP_MEMBERS_INFO_2 pTmpBuf;
    DWORD dwPrefMaxLen = 0xFFFFFFFF;
    DWORD dwEntriesRead = 0;
DWORD dwTotalEntries = 0;
DWORD dwResumeHandle = 0;
    DWORD dwTotalCount = 0;

    pszServerName = (LPWSTR)m_servername;
    pszGroupName = m_groupname.copy();

   do{
nStatus = NetLocalGroupGetMembers(pszServerName,pszGroupName,dwLevel,(LPBYTE*)&pBuf,dwPrefMaxLen,&dwEntriesRead,&dwTotalEntries,&dwResumeHandle);
         if ((nStatus == NERR_Success) || (nStatus == ERROR_MORE_DATA)) {
             if ((pTmpBuf = pBuf) != NULL)
             {
                    for (i = 0; (i < dwEntriesRead); i++)
                    {
if(pTmpBuf != NULL)
                    m_groupuser[dwTotalCount] = pTmpBuf->lgrmi2_domainandname;     
                  m_flags[dwTotalCount] = pTmpBuf->lgrmi2_sidusage;
                pTmpBuf++;
                dwTotalCount++;
            }
         }
      }
      else
         m_status = nStatus;
      if (pBuf != NULL)
      {
         NetApiBufferFree(pBuf);
         pBuf = NULL;
      }
   }while (nStatus == ERROR_MORE_DATA);

   if (pBuf != NULL)
      NetApiBufferFree(pBuf);
   m_allnum = dwTotalCount;
   return S_OK;
}

然后判断是否是超用户的代码
    ipcattch.groupname = "administrators"
    ipcattch.getgroupuser
    For i = 0 To ipcattch.allnum - 1
        tmpname = ipcattch.groupuser(i)
        j = InStr(tmpname, "\")
        tmpname = Right(tmpname, Len(tmpname) - j)
        For j = 0 To strnum - 1
            If InStr(UCase(tstr(j)), UCase(tmpname) & "||") > 0 Then
                If InStr(tstr(j), "||管理员用户") <= 0 Then
                    tstr(j) = tstr(j) & "||管理员用户"
                End If
                Exit For
            End If
        Next
    Next


B3层 发表时间: 09/02 08:49

回复: ricky [ricky]   版主   登录
我用的是LookupAccountSid,我要远程通过空连接列出用户列表,不是在取得administrator权限的情况下啊,那个函数好像不行啊

B4层 发表时间: 09/02 08:56

回复: ricky [ricky]   版主   登录
不好意思,怪我没讲清楚,哈哈,很谢谢你

B5层 发表时间: 09/02 08:58

回复: flashsky [flashsky]   论坛用户   登录
我上面的代码在NULL连接连上以后就可以,不需要ADMINISTRATOR权限,除非对方做了特殊的安全配置和权限设置。

LookupAccountSid/LookupAccountName也需要先远程进行IPC连接,但是获取的SID字串的解析属于哪个用户组则比较困难,由于SID的信息是特定方式生成的,确保其在所有计算机上都不相同的,对于用户其最后的一个字串是特殊的用户标记,虽然对应于固定adminstrator的用户的SID中一般最后的标记是500,你可以根据获得的用户的sid的最后一位是否等于500来判断administrator,但其他的给予了ADMINISRTATOR组权限的用户解析起来是比较麻烦的,还不如用以上方法来的简单。


[此贴被 闪空(flashsky) 在 9月2日14时41分 编辑过]


[此贴被 闪空(flashsky) 在 9月2日14时45分 编辑过]

B6层 发表时间: 9/2 14:37

回复: flashsky [flashsky]   论坛用户   登录
下面就是我的如上代码通过IPC空连接获取的一台远程主机的用户信息
UID     NAME    注释                                        附属信息
1004  ACTUser 启动 Application Center Test Broker and Controller 服务的帐户 允许注册脚本运行;用户不能修改密码;正常帐户;密码永不过期;
500 Administrator 管理计算机(域)的内置帐户                   允许注册脚本运行;正常帐户;密码永不过期;在线   管理员用户
501 Guest  供来宾访问计算机或访问域的内置帐户  允许注册脚本运行;该帐户被禁止;该帐户无密码要求;用户不能修改密码;正常帐户;密码永不过期;
1005 SQLDebugger This user account is used by the Visual Studio .NET Debugger  允许注册脚本运行;用户不能修改密码;正常帐户;密码永不过期;
1006  tom                                   允许注册脚本运行;正常帐户;密码永不过期; 管理员用户
1009  visitor                               允许注册脚本运行;正常帐户;
1000 VUSR_OLIVER  Account for the Visual Studio Analyzer server components   允许注册脚本运行;该帐户无密码要求;正常帐户;密码永不过期;
1003 VUSR_OLIVER1 Visual Studio Analyzer 7.0 Server 帐户 允许注册脚本运行;该帐户无密码要求;用户不能修改密码;正常帐户;密码永不过期;
1008 VUSR_OLIVER2 Account for the Visual Studio Analyzer server components  允许注册脚本运行;该帐户无密码要求;正常帐户;密码永不过期;

象以上就能判断administrator和tom是在管理员组的用户


[此贴被 闪空(flashsky) 在 9月2日15时59分 编辑过]

B7层 发表时间: 9/2 15:17

回复: ricky [ricky]   版主   登录
谢谢,我试一下,不过有一点可以肯定,我做实验的时候,sid最后一位是500还是1000,和是否超级用户无关,好像和是否初次创建的有关,我这里有一段通过sid取得用户名的代码,你可以看看:
//LookupAccountName接受一个系统名称和一个输入描述,返回一个找到的账号的计算机名和SID
if (!LookupAccountName(argv[1], "guest", pSid, &nSize, lpDomainName, &nSize, peUse))
{
printf ("Lookup failed!%d\n", GetLastError());
goto End;
}

printf ("DomainName:%s\n", lpDomainName);

pSIA = GetSidIdentifierAuthority(pSid);
nSubAuthorityCount = *GetSidSubAuthorityCount(pSid);
for (i = 0; i< nSubAuthorityCount; i++)
dwSubAuthority[i] = (int) *GetSidSubAuthority(pSid, i);

// lookup system account
for (i = 0; i < 100; i++)
{
nSize = 1024;
if (!AllocateAndInitializeSid(pSIA,nSubAuthorityCount,dwSubAuthority[0],dwSubAuthority[1],
dwSubAuthority[2],dwSubAuthority[3],(500 + i),dwSubAuthority[5],dwSubAuthority[6],
dwSubAuthority[7],&pNewSid))
{
printf ("Error SID!%d\n",GetLastError());
goto End;
}
if (!LookupAccountSid(argv[1],pNewSid,lpUserName,&nSize,lpDomainName, &nSize, peUse))
{
printf ("Lookup error!%d\n", GetLastError());
break;
}else
{
printf ("UserName: %s\n", lpUserName);
MyPrintSidInfo(pNewSid, peUse);
}
FreeSid(pNewSid);
}

// look up user account
for (i = 0; i < 100; i++)
{
FreeSid(pNewSid);
nSize = 1024;
if (!AllocateAndInitializeSid(pSIA,nSubAuthorityCount,dwSubAuthority[0],dwSubAuthority[1],
dwSubAuthority[2],dwSubAuthority[3],(1000 + i),dwSubAuthority[5],dwSubAuthority[6],
dwSubAuthority[7],&pNewSid))
{
printf ("Error SID!%d\n",GetLastError());
exit;
}
if (!LookupAccountSid(argv[1],pNewSid,lpUserName,&nSize,lpDomainName, &nSize, peUse))
{
}else{
printf ("UserName: %s\n", lpUserName);
}
}
这段代码也是我从别人那里抄的,可以取出用户名,通过变换sid,但是不知道如何取得该用户名的属性,看来可以和你的方法结合起来用了。
谢谢你给我的帮助,有机会认识一下啊

B8层 发表时间: 09/02 15:23

回复: flashsky [flashsky]   论坛用户   登录
SID在WINDOWS中不仅仅代表用户,windows许多东西都会用sid来代表,如用户组,域等,用户的SID是一个很复杂的组合,其生成和时间是有关的,但是用户的SID最后一位也叫相对SID,这个是按一定规律进行组织的,WINDOWS安装之后会自动生成administrator和guest用户,一般是administrator相对SID是500
guest的相对SID是501,其他再增加的用户则从1000开始,自动增量增加。从我取出的上面机器的例子你可以很清晰的看到。哪怕是以后加入到administrator组的用户,也是1000以后的,那么用户可能会删除掉一个或重命名掉administrator,然后再建立一个administrator用户,你就觉得administrator不是500了。

你给的这段代码,取出sid没什么大的意义,除通过相对SID大致能判断administrator外,不能判断属于administrator组的用户,同时用户也可能删除administrator用户,然后在建立一个administrator用户,这样你更无法判断。

B9层 发表时间: 09/02 15:57

回复: ricky [ricky]   版主   登录
你判断用户级别好像用的delphi的东东啊,c里面好像没有这个结构啊

B10层 发表时间: 09/02 15:59

回复: flashsky [flashsky]   论坛用户   登录
关于SID信息获取和其含义
建议你可以看一本书好象是叫《WINDOWS系统安全》吧,关于SID的组成,作用,相对SID,熟知SID都有非常详细的说明

B11层 发表时间: 09/02 15:59

回复: flashsky [flashsky]   论坛用户   登录
我的核心是c写的一个com
然后用vb去调的
很简单,传一个要获取的组的名称:administrators,获取一个用户列表,依次检查用户是否在这个列表中,注意要去掉domain,和有时候大小写不一定匹配

B12层 发表时间: 09/02 16:01

回复: ricky [ricky]   版主   登录
谢谢

B13层 发表时间: 09/02 16:06

回复: ricky [ricky]   版主   登录
我试过了,你的这个方法在estrictAnonymous=0的时候很好用,在RestrictAnonymous=1的时候无效,我的方法可以在RestrictAnonymous=1的时候列出用户来,但是无法判断用户级别,我想应该还有别的办法可以判断级别的,我要去找一找

B14层 发表时间: 09/02 17:17

回复: flashsky [flashsky]   论坛用户   登录
LookupAccountSid和LookupAccountName是需要知道相对SID或用户名的情况下才能取出用户信息,
你在RestrictAnonymous=1的时候又如何去知道sid或用户名列表呢?
不过相对sid估计好猜测一点。毕竟是有规律的变化

B15层 发表时间: 09/03 08:37

回复: ricky [ricky]   版主   登录
LookupAccountName和LookupAccountSid可以由具有Everyone访问权限的用户来执行,LookupAccountName可以返回sid,不过前提是你至少知道一个Everyone用户,我用guest,不需要password,已经调试过了,你也可以试一下,不过超级用户判断好象就没有办法了。


[此贴被 老实和尚(ricky) 在 9月3日9时41分 编辑过]

B16层 发表时间: 9/3 9:38

回复: flashsky [flashsky]   论坛用户   登录
不是,我只是奇怪你的说法而已
你的说法是:“我的方法可以在RestrictAnonymous=1的时候列出用户来”
而以上我的代码不是获取用户列表的,只是判断组的,这和取用户列表根本无关,我想你要么是说用列举用户的那个NetUserEnumAPI函数不能在RestrictAnonymous=1使用吧。而LookupAccountSid和LookupAccountName又如何在LookupAccountSid和LookupAccountName下列出用户列表呢?因为使用LookupAccountSid和LookupAccountName有个前提,要么已经知道SID,要么已经知道名字,那你又是如何获得用户列表呢?

如果你是说RestrictAnonymous=1我的代码不能用而你的LookupAccountSid和LookupAccountName能获得用户组才有可比性。

另外你也可以尝试一下NetUserGetGroups,NetUserGetLocalGroups的API是否能获取信息。  
  



[此贴被 闪空(flashsky) 在 9月3日13时12分 编辑过]

B17层 发表时间: 9/3 13:49

回复: ricky [ricky]   版主   登录
好的,我试一下

B18层 发表时间: 09/03 15:04

回复: sainthero [sainthero]   论坛用户   登录
我手边恰好也有个例子

function IsAdmin: Boolean;
var
  hAccessToken: THandle;
  ptgGroups: PTokenGroups;
  dwInfoBufferSize: DWORD;
  psidAdministrators: PSID;
  x: Integer;
  bSuccess: BOOL;
begin
  Result := False;
  bSuccess := OpenThreadToken(GetCurrentThread, TOKEN_QUERY, True,    hAccessToken);
  if not bSuccess then
  begin 
   if GetLastError = ERROR_NO_TOKEN then
    bSuccess := OpenProcessToken(GetCurrentProcess, TOKEN_QUERY, hAccessToken);
  end;
  if bSuccess then
  begin
    GetMem(ptgGroups, 1024);
    bSuccess := GetTokenInformation(hAccessToken, TokenGroups,  ptgGroups, 1024, dwInfoBufferSize);
    CloseHandle(hAccessToken);
    if bSuccess then
    begin
      AllocateAndInitializeSid(SECURITY_NT_AUTHORITY, 2,        SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, psidAdministrators);
      {$R-}
      for x := 0 to ptgGroups.GroupCount - 1 do
        if EqualSid(psidAdministrators, ptgGroups.Groups[x].Sid)  then 
       begin
          Result := True;
          Break;
        end;
      {$R+}
      FreeSid(psidAdministrators);
    end;
    FreeMem(ptgGroups); 
 end;
end;
 procedure TForm1.Button1Click(Sender: TObject);
begin
  if isAdmin then
    ShowMessage('Logged in as Administrator');
end;

B19层 发表时间: 09/09 19:57

回复: ricky [ricky]   版主   登录
不好意思,我对delphi不熟,看不太懂,可不可以解释一下

B20层 发表时间: 09/09 21:02

回复: flashsky [flashsky]   论坛用户   登录
他给的例子和你说的是两马事
他这个是判断本机进程的属主的用户SID的,并且好象只能判断自己的,呵呵。

B21层 发表时间: 09/10 09:28

回复: ricky [ricky]   版主   登录
谢谢,我的ipc扫描器核心包括值入运行都调完了,下面就是多进程和界面了,说句老实话,我最讨厌写界面,大概是我的审美有先天缺陷吧,哈哈
再次对你表示感谢,如果没有你的帮助,恐怕我现在还在msdn里翻垃圾呢

B22层 发表时间: 09/10 09:55

论坛: 原创软件

20CN网络安全小组版权所有
Copyright © 2000-2010 20CN Security Group. All Rights Reserved.
论坛程序编写:NetDemon

粤ICP备05087286号