|
作者: 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号