如何超越Windows2000赋予的ADMINISTRATOR权限!虽然Admin权利大,但不是最大
NT的安全组件里有一个叫Local Security Authority Protected Subsystem.当我们以ADMINISTRATOR登陆时,系统根据缺省的授权,赋予ADMINISTRATOR16个授权.下面乃是详细的清单.
SeChangeNotifyPrivilege
SeSecurityPrivilege
SeBackupPrivilege
SeRestorePrivilege
SeSystemtimePrivilege
SeShutdownPrivilege
SeRemoteShutdownPrivilege
SeTakeOwnershipPrivilege
SeDebugPrivilege
SeSystemEnvironmentPrivilege
SeSystemProfilePrivilege
SeProfileSingleProcessPrivilege
SeIncreaseBasePriorityPrivilege
SeLoadDriverPrivilege
SeCreatePagefilePrivilege
SeIncreaseQuotaPrivilege
其中 SeChangeNotifyPrivilege是缺省打开的.其他则需要调整TOKEN来打开.拥有了这么多的权限后,ADMIN真可谓强大,没有任何其他用户拥有这么多的权限了.但是,仍然有几个更有威力的权限没有赋予ADMIN.那就是SeTcbPrivilege和SeCreateTokenPrivilege. SeTcbPrivilege表示当前用户的操作代表了系统的操作,SeCreateTokenPrivilege更可赤裸裸地为任意令牌创建权限.乃是无上的特权.如果任何人拥有了这两个权限,在NT世界的权利就太夸张了.所以,NT根本就不给任何用户以这两个权限.
出于对权利的渴望,通常病毒,HACKER都会想法获取最高权限.现在,由于NT的保护,直接地获取这2个权限是不行了.那么就需要饶个弯子了.
由于没有直接的API可以增加TOKEN的特权,我们只好通过LSA POLICY库调整用户权限.因为用户权限在LSA POLICY库里被提取出来.当LSA POLICY库里增加了一个特权,用户可以在下一个进程里打开该特权.HEHE... ADMIN组对LSA POLICY库有写权.:DDD ADMIN没有超级特权,LSA对用户的特权从POLICY库里提取... 真是个可爱的连环套啊. :)
下面是我写的程序,打开ADMINISTRATOR的SeTcbPrivilege特权.尽管我在程序里面设置了ADMIN检查,但是通过少量的改写就可以时普通用户获取一些超级权限.:)里面的小技巧大家自己通常可以动出脑筋的.当然并不是通过删除ADMINISTRATOR检验就可以完成的. :)
当然,这里有编译好的版本供下载.
/*++
sec.cpp
#define UNICODE
#include <windows.h>
#include <iostream.h>
#include <stdio.h>
#include <ntsecapi.h>
//
//Global vars
//
LSA_HANDLE PolicyHandle;
PSID Sid=0;
DWORD cbSid=0;
LPTSTR ReferencedDomainName=0;
DWORD cbReferencedDomainName=0;
SID_NAME_USE peUse;
PUNICODE_STRING UserRights=0; //UnicodeString Pointer to PRIVILEGE
ULONG Count=0; //
WCHAR textSid[200];
HANDLE token=0;
PTOKEN_PRIVILEGES TokenInformation=0;
BOOL owned=0;
//
//quit
//
void quit(int err){
if (Sid) delete Sid;
if (ReferencedDomainName) delete ReferencedDomainName;
if (UserRights) delete UserRights;
if (TokenInformation) delete TokenInformation;
if (token) CloseHandle(token);
if (PolicyHandle) LsaClose(PolicyHandle);
wprintf(L"\n\nWritten by Lu Lin. 2000.1.30\nLicence: Freeware.\n");
if (err){
exit(0xc0000000);
}
else {
exit(0);
}
}
void printprivilege(LUID_AND_ATTRIBUTES* luid){
WCHAR dispname[100];
ULONG cb=100;
if (!LookupPrivilegeName(
0,
&(luid->Luid),
dispname,
&cb)){
wprintf(L"I can't translate SOME LUID to privilege!\n");
exit(1);
}
wprintf(L"\tPrivilege: %s\n",dispname);
if (!_wcsicmp(dispname,L"SeTcbPrivilege")) owned=1;
switch (luid->Attributes){
case SE_PRIVILEGE_ENABLED_BY_DEFAULT:
wprintf(L"\t\tThis privilege is enabled by default\n");
break;
case SE_PRIVILEGE_ENABLED:
wprintf(L"\t\tThis privilege is enabled.\n");
break;
case SE_PRIVILEGE_USED_FOR_ACCESS:
wprintf(L"\t\tThis privilege is used for access.\n");
break;
case 3:
wprintf(L"\t\tThis privilege is always on for you.\n");
break;
case 0:
wprintf(L"\t\tThis privilege you owned has not been enabled yet.\n");
}
}
void init(){
WCHAR username[30];
ULONG cb;
OSVERSIONINFO osv;
//if nt?
ZeroMemory(&osv,sizeof(osv));
osv.dwOSVersionInfoSize=sizeof(osv);
GetVersionEx(&osv);
if (!osv.dwPlatformId&VER_PLATFORM_WIN32_NT){
wprintf(L"This program only runs on NT");
quit(1);
}
//
//Check if this thread is executed inside administrator's context.
//
cb=30;
GetUserName(username,&cb);
if (_wcsicmp(username,L"administrator")){
wprintf(L"Logon as administrator first!\n");
quit(1);
}
wprintf(L"WINDOWS NT %i.%i Build %i %s\n\n",
osv.dwMajorVersion,
osv.dwMinorVersion,
osv.dwBuildNumber,
osv.szCSDVersion);
}
BOOL GetTextualSid(
PSID pSid, // binary Sid
LPTSTR TextualSid, // buffer for Textual representation of Sid
DWORD dwBufferLen // required/provided TextualSid buffersize
)
{
PSID_IDENTIFIER_AUTHORITY psia;
DWORD dwSubAuthorities;
DWORD dwSidRev=SID_REVISION;
DWORD dwCounter;
DWORD dwSidSize;
// Validate the binary SID.
if(!IsValidSid(pSid)) return FALSE;
// Get the identifier authority value from the SID.
psia = GetSidIdentifierAuthority(pSid);
// Get the number of subauthorities in the SID.
dwSubAuthorities = *GetSidSubAuthorityCount(pSid);
// Compute the buffer length.
// S-SID_REVISION- + IdentifierAuthority- + subauthorities- + NULL
dwSidSize=(15 + 12 + (12 * dwSubAuthorities) + 1) * sizeof(TCHAR);
// Check input buffer length.
// If too small, indicate the proper size and set last error.
if (dwBufferLen < dwSidSize)
{
SetLastError(ERROR_INSUFFICIENT_BUFFER);
return FALSE;
}
// Add 'S' prefix and revision number to the string.
dwSidSize=wsprintf(TextualSid, TEXT("S-%lu-"), dwSidRev );
// Add SID identifier authority to the string.
if ( (psia->Value[0] != 0) || (psia->Value[1] != 0) )
{
dwSidSize+=wsprintf(TextualSid + lstrlen(TextualSid),
TEXT("0x%02hx%02hx%02hx%02hx%02hx%02hx"),
(USHORT)psia->Value[0],
(USHORT)psia->Value[1],
(USHORT)psia->Value[2],
(USHORT)psia->Value[3],
(USHORT)psia->Value[4],
(USHORT)psia->Value[5]);
}
else
{
dwSidSize+=wsprintf(TextualSid + lstrlen(TextualSid),
TEXT("%lu"),
(ULONG)(psia->Value[5] ) +
(ULONG)(psia->Value[4] << 8) +
(ULONG)(psia->Value[3] << 16) +
(ULONG)(psia->Value[2] << 24) );
}
// Add SID subauthorities to the string.
//
for (dwCounter=0 ; dwCounter < dwSubAuthorities ; dwCounter++)
{
dwSidSize+=wsprintf(TextualSid + dwSidSize, TEXT("-%lu"),
*GetSidSubAuthority(pSid, dwCounter) );
}
return TRUE;
}
void main(){
LSA_OBJECT_ATTRIBUTES ObjectAttributes;
ZeroMemory(&ObjectAttributes,sizeof(ObjectAttributes));
init();
//
//First open LSA policy database
//the call returns a NTSTATUS. NTSTATUS 0 means everything is OK.
//
if (LsaOpenPolicy(
0,
&ObjectAttributes,
GENERIC_EXECUTE|GENERIC_READ|GENERIC_WRITE,
&PolicyHandle
)){
wprintf(L"Open Policy error!\n");
}
else {
Sid=new char[500];
ReferencedDomainName=new WCHAR[100];
cbSid=500;
cbReferencedDomainName=100;
//
//Show Administrator SID
//
if (!LookupAccountName(
0,
L"Administrator",
Sid,
&cbSid,
ReferencedDomainName,
&cbReferencedDomainName,
&peUse
)){
wprintf(L"Damn, I can't find out the account looking for!\n");
quit(1);
}
if (!GetTextualSid(Sid,textSid,200)){
wprintf(L"Damn, Get textual SID error! Maybe a bug in this program.\n");
quit(1);
}
wprintf(L"The SID of administrator is: %s \n",textSid);
wprintf(L"\tOn the server: %s\n",ReferencedDomainName);
//
//Check current privilege
//
if (!OpenProcessToken(
GetCurrentProcess(),
TOKEN_QUERY,
&token)){
wprintf(L"Can't open process token! What's happened?\n");
quit(1);
}
TokenInformation=(PTOKEN_PRIVILEGES)(new char[2000]);
if (!GetTokenInformation(
token,
TokenPrivileges,
(void*)TokenInformation,
2000,
&cbSid //Note, Returned lenght of token information.
)){
wprintf(L"Can't get token information\n");
quit(1);
}
else{
LUID_AND_ATTRIBUTES *luid;
luid=(LUID_AND_ATTRIBUTES *)&TokenInformation->Privileges;
wprintf(L"\nTotal privilege count: %i\n\n",TokenInformation->PrivilegeCount);
for (Count=0;Count<TokenInformation->PrivilegeCount;
Count++,luid++){
printprivilege(luid);
}
}
//
//Add SeTchPrivilege to Administrator if not owned yet!
//
if (!owned){
UserRights=new LSA_UNICODE_STRING;
UserRights->Buffer=L"SeTcbPrivilege";
UserRights->MaximumLength=28;
UserRights->Length=28;
if (LsaAddAccountRights(
PolicyHandle,
Sid,
UserRights,
1
)){
wprintf(L"Damn! Add right failed! :(\n");
quit(1);
}
else wprintf(L"\nAdd SeTcbPrivilege successfully!\n");
quit(0);
}
else {
wprintf(L"\nYou own SeTcbPrivilege. I don't add it for you.\n");
}
}
}