如何超越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");
}
}
}
作者Blog:http://blog.csdn.net/小星星/