Невозможно отучить людей изучать самые ненужные предметы.
Введение в CSS
Преимущества стилей
Добавления стилей
Типы носителей
Базовый синтаксис
Значения стилевых свойств
Селекторы тегов
Классы
CSS3
Надо знать обо всем понемножку, но все о немногом.
Идентификаторы
Контекстные селекторы
Соседние селекторы
Дочерние селекторы
Селекторы атрибутов
Универсальный селектор
Псевдоклассы
Псевдоэлементы
Кто умеет, тот делает. Кто не умеет, тот учит. Кто не умеет учить - становится деканом. (Т. Мартин)
Группирование
Наследование
Каскадирование
Валидация
Идентификаторы и классы
Написание эффективного кода
Вёрстка
Изображения
Текст
Цвет
Линии и рамки
Углы
Списки
Ссылки
Дизайны сайтов
Формы
Таблицы
CSS3
HTML5
Блог для вебмастеров
Новости мира Интернет
Сайтостроение
Ремонт и советы
Все новости
Справочник от А до Я
HTML, CSS, JavaScript
Афоризмы о учёбе
Статьи об афоризмах
Все Афоризмы
Помогли мы вам |
В сегодняшней статье мы разберем принцип работы этого инструмента, а также пробежимся по всем пяти режимам, которые позволяют:
Итак, все, как и в любом другом проекте на языке С, начинается с функции main(
, в которую прилетают все нужные параметры. После чего для обеспечения корректного вывода кириллических (и иных) символов дергаем setlocale(
, выводим прекрасный ASCII-баннер и приступаем к валидации входных данных.
int wmain(int argc, wchar_t* argv[]) {
setlocale(LC_ALL, "");
ShowAwesomeBanner();
DWORD dwRC = 0, dwV = 0;
if (argc != 4) {
ShowHelp();
return 0;
}
switch (*argv[1]) {
case '1':
if (ValidateAccInfo(argv[2], argv[3]) == 0) {
dwRC = InitMode1(argv[2], argv[3]);
}
break;
case '2':
if (ValidatePathInfo(argv[2], argv[3]) == 0) {
dwRC = InitMode2(argv[2], argv[3]);
}
break;
case '3':
if (ValidateAccInfo(argv[2], argv[3]) == 0) {
dwRC = InitMode3(argv[2], argv[3]);
}
break;
case '4':
if (ValidatePriv(argv[3])) {
dwRC = InitMode4(argv[2], argv[3]);
}
else {
std::wcout << L"[-] ValidatePriv() Failed" << std::endl;
}
break;
case '5':
std::wcout << L"[!] I'm not able to validate username and PC name. Make sure you enter the correct data." << std::endl;
Sleep(500);
std::wcout << L"[!] Starting" << std::endl;
if (InitMode5(argv[2], argv[3]) != 0) {
std::wcout << L"[-] InitMode 5 Error" << std::endl;
}
break;
default:
std::wcout << L"[-] No such mode" << std::endl;
return 0;
}
return dwRC;
}
Если требуется использовать первый режим работы, то есть добавить привилегии аккаунту, пользователь должен предоставить следующие входные данные:
Программное имя привилегии — это, собственно, само имя привилегии. Есть еще так называемое дружественное имя — это ее описание. Например, программное имя SeDebugPrivilege
, а дружественное — Отладка
.
Итак, обращаемся к Privileger.
Успешное добавление привилегииЯ предусмотрел проверку на валидность имени пользователя, а также имени привилегии, чтобы предотвратить очепятки. Проверка реализуется функцией ValidateAccInfo(
, которая принимает имя пользователя, а также программное имя привилегии.
DWORD ValidateAccInfo(wchar_t* cAccName, wchar_t* cPrivName) {
// validating username
DWORD sid_size = 0;
PSID UserSid;
LPTSTR wSidStr = NULL;
DWORD domain_size = 0;
SID_NAME_USE sid_use;
DWORD wow = LookupAccountName(NULL, cAccName, NULL, &sid_size, NULL, &domain_size, &sid_use);
DWORD dw = GetLastError();
if ((wow == 0) && ( (dw == 122) || (dw == 0))) {
std::wcout << L"[+] User " << cAccName << L" found" << std::endl;
// validating Privilege name
if (!ValidatePriv(cPrivName)) {
std::wcout << L"[-] ValidateAccInfo() failed" << std::endl;
return 1;
}
else {
std::wcout << L"[+] ValidateAccInfo() success" << std::endl;
return 0;
}
}
else {
std::wcout << L"[-] Username may be incorrect. LookupAccountName() Err: " << dw << std::endl;
return 1;
}
return 1;
}
Указание неверного имени привилегииНеверное имя пользователяПроверку имени пользователя я сделал с помощью функции LookupAccountName(). Сама по себе она служит для получения SID (security identifier) пользователя по его имени, но нам ничто не мешает использовать ее просто для проверки имени пользователя, ведь если компьютер не обнаружит пользователя с таким именем, то и вызов функции приведет к ошибке.
Проверку программного имени привилегии я также вынес в отдельную функцию.
LUID luid;
if (!LookupPrivilegeValue(NULL, cPrivName, &luid)) {std::wcout << L"[-] Privilege " << cPrivName << L" may be incorrect" << std::endl;return FALSE;
}
else {std::wcout << L"[+] Privilege " << cPrivName << L" Found n[+] Validation Success" << std::endl;return TRUE;
}}
Здесь алгоритм схож: дергаем LookupPrivilegeValue(), если привилегия есть — все ок, если нет — ошибка.
Убедившись, что предоставленные данные верны, инструмент вызывает InitMode1(
, которому также передает имя пользователя и имя привилегии. Внутри этой функции мы получаем хендл на LSA текущего компьютера (так как работаем с привилегиями локального аккаунта) вызовом функции GetPolicy(
.
std::wcout << L"[+] Initializing mode 1 n [+] Target Account: " << cAccName << "n [+] Privilege: " << cPrivName << std::endl;
LSA_HANDLE hPolicy;
if (GetPolicy(&hPolicy) != 0) {std::wcout << L" [-] GetPolicy() Error: " << std::endl;return 1;
}
AddUserPrivilege(hPolicy, cAccName, cPrivName, TRUE);
return 0;}
DWORD GetPolicy(PLSA_HANDLE LsaHandle){
wchar_t cCompName[MAX_COMPUTERNAME_LENGTH + 1] = { 0 };
DWORD size = sizeof(cCompName);
if (GetComputerNameW(cCompName, &size)) {
std::wcout << L" [+] ComputerName: " << cCompName << std::endl;
}
else {
std::wcout << L" [-] GetComputerNameW Error: " << GetLastError() << std::endl;
}
LSA_OBJECT_ATTRIBUTES lsaOA = { 0 };
LSA_UNICODE_STRING lsastrComputer = { 0 };
lsaOA.Length = sizeof(lsaOA);
lsastrComputer.Length = (USHORT)(lstrlen(cCompName) * sizeof(WCHAR));
lsastrComputer.MaximumLength = lsastrComputer.Length + sizeof(WCHAR);
lsastrComputer.Buffer = (PWSTR)&cCompName;
NTSTATUS ntStatus = LsaOpenPolicy(&lsastrComputer, &lsaOA, POLICY_ALL_ACCESS, LsaHandle);
ULONG lErr = LsaNtStatusToWinError(ntStatus);
if (lErr != ERROR_SUCCESS) {
std::wcout << L" [-] LsaOpenPolicy() Error: " << lErr << std::endl;
return 1;
}
else {
std::wcout << L" [+] LsaOpenPolicy() Success" << std::endl;
return 0;
}
return 1;
}
Получают хендл на политику через функцию LsaOpenPolicy. Единственная особенность работы с LSA состоит в том, что у нее свои коды ошибок, которые просто через GetLastError(
не поймать. Нужно получать значение NTSTATUS
, которое возвращает каждая функция, работающая с LSA, а затем передавать это значение в LsaNtStatusToWinError(
для преобразования в понятный человеческому глазу код ошибки.
По коду ошибки можно понять, что сломалось, — заглядывай в официальную документацию.
Если система выдала нам корректный хендл и мы не получили ERROR_ACCESS_DENIED
, переходим к навешиванию привилегии пользователю, к функции AddUserPrivilege(
.
DWORD AddUserPrivilege(LSA_HANDLE hPolicy, LPWSTR wUsername, LPWSTR wPrivName, BOOL bEnable) {
PSID UserSid;
DWORD sid_size = 0;
LPTSTR wSidStr = NULL;
DWORD domain_size = 0;
SID_NAME_USE sid_use;
if (!LookupAccountName(NULL, wUsername, NULL, &sid_size, NULL, &domain_size, &sid_use)) {
UserSid = (PSID)VirtualAlloc(NULL, sid_size, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
LPTSTR domain = NULL;
domain = (LPTSTR)VirtualAlloc(NULL, domain_size * sizeof(WCHAR), MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
LookupAccountName(NULL, wUsername, UserSid, &sid_size, domain, &domain_size, &sid_use);
VirtualFree(domain, 0, MEM_RELEASE);
ConvertSidToStringSid(UserSid, &wSidStr);
std::wcout << L" [+] User SID: " << wSidStr << std::endl;
LSA_UNICODE_STRING lsastrPrivs[1] = { 0 };
lsastrPrivs[0].Buffer = (PWSTR)wPrivName;
lsastrPrivs[0].Length = lstrlen(lsastrPrivs[0].Buffer) * sizeof(WCHAR);
lsastrPrivs[0].MaximumLength = lsastrPrivs[0].Length + sizeof(WCHAR);
if (bEnable) {
NTSTATUS ntStatus = LsaAddAccountRights(hPolicy, UserSid, lsastrPrivs, 1);
ULONG lErr = LsaNtStatusToWinError(ntStatus);
if (lErr == ERROR_SUCCESS) {
std::wcout << L" [+] Adding " << wPrivName << L" Success" << std::endl;
std::wcout << L" [+] Enumerating Current Privs" << std::endl;
PrintTrusteePrivs(hPolicy, UserSid);
VirtualFree(UserSid, 0, MEM_RELEASE);
return 0;
}
else {
wprintf(L" [-] Error LsaAddAccountRights() %d", lErr);
return 1;
}
} else {
ULONG lErr = LsaRemoveAccountRights(hPolicy, UserSid, FALSE, lsastrPrivs, 1);
if (lErr == ERROR_SUCCESS) {
std::wcout << L" [-] Removing " << wPrivName << L" Success" << std::endl;
std::wcout << L" [+] Enumerating Current Privs" << std::endl;
PrintTrusteePrivs(hPolicy, UserSid);
VirtualFree(UserSid, 0, MEM_RELEASE);
return 0;
}
else {
wprintf(L" [-] Error LsaRemoveAccountRights() %d", lErr);
return 1;
}
}
}
else {
std::wcout << L" [-] LookupAccountName() Error: " << GetLastError() << std::endl;
return 1;
}
return 1;
}
|
|