Error DuplicateTokenEx и Windows XP

Тема в разделе "WASM.WIN32", создана пользователем M0rg0t, 18 мар 2020.

  1. M0rg0t

    M0rg0t Well-Known Member

    Публикаций:
    0
    Регистрация:
    18 окт 2010
    Сообщения:
    1.576
    Столкнулся со странной ошибкой, причем сугубо на ХР. Есть код, примерно такой, копирует токен с Winlogon.exe или smss.exe

    Код (C):
    1.  
    2. int main()
    3. {
    4. DWORD dAccess,dwProcessId = GetSysPid();
    5. HANDLE hProcess,TokenHandle,phNewToken;
    6. BOOL bRet;
    7. SECURITY_ATTRIBUTES TokenAttributes =
    8. {
    9.   .lpSecurityDescriptor = NULL,
    10.   .bInheritHandle = FALSE,
    11. .nLength = sizeof(SECURITY_ATTRIBUTES)
    12. };
    13. EnableWindowsPrivilege(L"SeDebugPrivilege");
    14. hProcess = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, dwProcessId);
    15. bRet = OpenProcessToken(hProcess, MAXIMUM_ALLOWED, &TokenHandle);
    16. bRet = DuplicateTokenEx(TokenHandle,MAXIMUM_ALLOWED,&TokenAttributes,SecurityImpersonation,TokenPrimary,&phNewToken);
    17. if (bRet == FALSE)
    18. { wprintf(L"Error , can't duplicate token %d\n",GetLastError()); return FALSE; }
    19. else
    20. { wprintf(L"token duplicated..\n"); }
    21. return 0;
    22. }
    23.  
    Код прекрасно работает на последней десятке, но возвращает access_denied на WinXP ! Причем на функции DuplicateTokenEx .
    На всех остальных ОС (виста и выше ) все работает. Почему такое может быть, что было в ХР ? Indy_
     
  2. Rel

    Rel Well-Known Member

    Публикаций:
    2
    Регистрация:
    11 дек 2008
    Сообщения:
    5.323
    А что за MAXIMUM_ALLOWED? Может TOKEN_ALL_ACCESS имелось ввиду, не?
     
  3. M0rg0t

    M0rg0t Well-Known Member

    Публикаций:
    0
    Регистрация:
    18 окт 2010
    Сообщения:
    1.576
    На виста+ работает так. Считается, что плохая практика передавать _ALL_ACCESS , + в более новых ОС никто таких прав банально не даст.
     
  4. Indy_

    Indy_ Well-Known Member

    Публикаций:
    4
    Регистрация:
    29 апр 2011
    Сообщения:
    4.775
    Нужен сервис и статусный код, мне лень проверять.
     
  5. M0rg0t

    M0rg0t Well-Known Member

    Публикаций:
    0
    Регистрация:
    18 окт 2010
    Сообщения:
    1.576
    Indy_, ок. Как в ХР запустить процесс с правами системы? Имея админский аккаунт, но не через службу. В ОС выше ХР решается вот кодом выше - открываем Winlogon/smss , копируем оттуда токен, создаем новый процесс. В ХР такой фокус не проходит, дает ошибку ACCESS_DENIED на том или ином этапе.
     
  6. Indy_

    Indy_ Well-Known Member

    Публикаций:
    4
    Регистрация:
    29 апр 2011
    Сообщения:
    4.775
    M0rg0t,

    Отладчиком пройди и посмотри статусный код. Этот winerr это группа из пол сотни статусов поэтому это не ошибка а вообще ничего. За пол часа это можно было сделать сотню раз.
     
  7. M0rg0t

    M0rg0t Well-Known Member

    Публикаций:
    0
    Регистрация:
    18 окт 2010
    Сообщения:
    1.576
    Indy_, что дает нтстатус? Посмотрел, NtDuplicatToken вернул тот же C0000022
     
  8. Indy_

    Indy_ Well-Known Member

    Публикаций:
    4
    Регистрация:
    29 апр 2011
    Сообщения:
    4.775
    M0rg0t,

    Всё даст, так как на XP есть сурки и всё можно посмотреть не отлаживая ядро:

    Код (Text):
    1.     //  Check the handle's access to the existing token and get
    2.     //  a pointer to that token.  Pick up the default desired
    3.     //  access mask from the handle while we're at it.
    4.     //
    5.  
    6.     Status = ObReferenceObjectByHandle(
    7.                  ExistingTokenHandle,    // Handle
    8.                  TOKEN_DUPLICATE,        // DesiredAccess
    9.                  SeTokenObjectType,     // ObjectType
    10.                  PreviousMode,           // AccessMode
    11.                  (PVOID *)&Token,        // Object
    12.                  &HandleInformation      // GrantedAccess
    13.                  );
    Дальше смотри по цепочке. Реф можно проверить остановкой потока. PROCESS_QUERY_INFORMATION -> TOKEN_DUPLICATE ?
     
  9. M0rg0t

    M0rg0t Well-Known Member

    Публикаций:
    0
    Регистрация:
    18 окт 2010
    Сообщения:
    1.576
    Indy_, но на ОС выше работает без DUPLICATE, более того - на десятке даже PROCESS_QUERY_INFORMATION не проходит. Впрочем, не суть.
    Может , на ХР и ниже вообще нельзя создать процесс от имени системы? Попробовать Process Hacker, тоже какую-то ошибку показал.
     
  10. Rel

    Rel Well-Known Member

    Публикаций:
    2
    Регистрация:
    11 дек 2008
    Сообщения:
    5.323
    Максимум эллауд устанавливает всего один бит, который, можно предположить не обрабатывается на xp, но обрабатывается на виста+. В документации мсдн к дупликейт хендл и оупен процесс токен такого флага в принципе нет.
    --- Сообщение объединено, 18 мар 2020 ---
    Так а что твой максимум эллауд это меньше прав, чем олл эксес или что? Передавай конкретный набор прав, который тебе нужен тогда.
     
  11. M0rg0t

    M0rg0t Well-Known Member

    Публикаций:
    0
    Регистрация:
    18 окт 2010
    Сообщения:
    1.576
    Rel, в любом случае, оно не работает. Пишу OpenProcess(PROCESS_ALL_ACCESS... ) - тут гуд.
    А OpenProcessToken(hProcess, TOKEN_ALL_ACCESS.. - возвращает все тот же ACCESS_DENIED.

    Процесс системный. т.е. винлогон. Мб нельзя такое там сделать, вот сторонние тулзы тоже не запускают от системы.
     
  12. Andrey333

    Andrey333 Member

    Публикаций:
    0
    Регистрация:
    30 янв 2020
    Сообщения:
    35
    M0rg0t, вам OpenProcessToken возвращает хэндл без TOKEN_DUPLICATE и вы этого не замечаете, т.к. используете MAXIMUM_ALLOWED, вместо того чтобы задавать конкретные права. Дело в том, что в DACL токена в ACE для администраторов нет данного разрешения, однако владельцем являются администраторы. А раз мы и есть владелец, то мы можем открыть токен с правом WRITE_DAC и отредактировать DACL как нам нужно.
     
  13. Rel

    Rel Well-Known Member

    Публикаций:
    2
    Регистрация:
    11 дек 2008
    Сообщения:
    5.323
    Так задай конкретные необходимые тебе права, какая проблема у тебя?
     
  14. M0rg0t

    M0rg0t Well-Known Member

    Публикаций:
    0
    Регистрация:
    18 окт 2010
    Сообщения:
    1.576
    Andrey333, так с какими правами нужно открыть системный процесс? Какие флаги передать ? Сначала WRITE_DAC , а потом что ? Не пойму до конца мысль.

    Rel, ну какие права-то? Проблема такая, что нельзя просто так взять и написать OpenProcessToken с TOKEN_ADJUST_DEFAULT | TOKEN_ADJUST_SESSIONID | TOKEN_QUERY | TOKEN_DUPLICATE | TOKEN_ASSIGN_PRIMARY;

    Для системного процесса в ХР / 2к не хватает привилегий, какие не указывай - все равно, один фиг не откроется. Для обычного процесса все будет гуд. А вот lsass/ winlogon так не открыть. Если же указывать тут другие флаги, тогда падает DuplicateToken.
     
  15. hiddy

    hiddy Member

    Публикаций:
    0
    Регистрация:
    10 мар 2019
    Сообщения:
    82
    На 10 можно сделать следующим образом, может и на хрюше сработает:
    1. Получить SeDebugPrivilege привилегии
    2. Получить хэндл системного процесса
    3. Передать полученный хэндл в NtCreateProcess/NtCreateUserProccess
     
  16. M0rg0t

    M0rg0t Well-Known Member

    Публикаций:
    0
    Регистрация:
    18 окт 2010
    Сообщения:
    1.576
    с какими правами открывать?
     
  17. hiddy

    hiddy Member

    Публикаций:
    0
    Регистрация:
    10 мар 2019
    Сообщения:
    82
    PROCESS_CREATE_PROCESS должно хватить.
     
  18. Rel

    Rel Well-Known Member

    Публикаций:
    2
    Регистрация:
    11 дек 2008
    Сообщения:
    5.323
    Эмм, ну токен_дупликейт и какие там еще права нужны на запуск процесса? Если я правильно понимаю, что ты пытаешься сделать.
    --- Сообщение объединено, 20 мар 2020 ---
    В мсдн написано, что нужно TOKEN_QUERY, TOKEN_DUPLICATE и TOKEN_ASSIGN_PRIMARY.
     
  19. Andrey333

    Andrey333 Member

    Публикаций:
    0
    Регистрация:
    30 янв 2020
    Сообщения:
    35
    Мне проще кодом ответить.
    Код (C++):
    1.  
    2. #include <sddl.h>
    3. #include <stdio.h>
    4.  
    5. const wchar_t ACCESS_FOR_ADMINS_SECURITY_DESCRIPTOR[] =
    6.  
    7.     SDDL_OWNER SDDL_DELIMINATOR SDDL_BUILTIN_ADMINISTRATORS
    8.  
    9.     SDDL_GROUP SDDL_DELIMINATOR SDDL_BUILTIN_ADMINISTRATORS
    10.  
    11.     SDDL_DACL SDDL_DELIMINATOR SDDL_PROTECTED
    12.  
    13.         SDDL_ACE_BEGIN
    14.  
    15.             SDDL_ACCESS_ALLOWED SDDL_SEPERATOR
    16.             SDDL_CONTAINER_INHERIT SDDL_OBJECT_INHERIT SDDL_SEPERATOR
    17.             SDDL_GENERIC_ALL SDDL_SEPERATOR
    18.             SDDL_SEPERATOR
    19.             SDDL_SEPERATOR
    20.             SDDL_BUILTIN_ADMINISTRATORS
    21.  
    22.         SDDL_ACE_END;
    23.  
    24. int main()
    25. {
    26.     HANDLE hProcess = NULL;
    27.     HANDLE hToken = NULL;
    28.     HANDLE hNewToken = NULL;
    29.     PSECURITY_DESCRIPTOR pSD = NULL;
    30.  
    31.     EnablePrivilege(L"SeDebugPrivilege");  
    32.  
    33.     hProcess = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, 368 /* smss.exe PID */);
    34.     if (NULL == hProcess) {
    35.         printf("OpenProcess failed, error code: 0x%0.8lX", GetLastError());
    36.         goto Cleanup;
    37.     }
    38.    
    39.     if (!OpenProcessToken(hProcess, WRITE_DAC, &hToken)) {
    40.         printf("OpenProcessToken failed, error code: 0x%0.8lX", GetLastError());
    41.         goto Cleanup;
    42.     }
    43.    
    44.     if (!ConvertStringSecurityDescriptorToSecurityDescriptor(
    45.         ACCESS_FOR_ADMINS_SECURITY_DESCRIPTOR, SDDL_REVISION_1, &pSD, NULL))
    46.     {
    47.         printf("ConvertStringSecurityDescriptorToSecurityDescriptor failed, "
    48.             "error code: 0x%0.8lX", GetLastError());
    49.         goto Cleanup;
    50.     }
    51.  
    52.     if (!SetKernelObjectSecurity(hToken, DACL_SECURITY_INFORMATION, pSD)) {
    53.         printf("SetKernelObjectSecurity failed, error code: 0x%0.8lX", GetLastError());
    54.         goto Cleanup;
    55.     }
    56.  
    57.     CloseHandle(hToken);
    58.     hToken = NULL;
    59.  
    60.     if (!OpenProcessToken(hProcess, TOKEN_DUPLICATE, &hToken)) {
    61.         printf("OpenProcessToken failed, error code: 0x%0.8lX", GetLastError());
    62.         goto Cleanup;
    63.     }
    64.    
    65.     if (!DuplicateTokenEx(hToken, TOKEN_QUERY | TOKEN_DUPLICATE |
    66.         TOKEN_ASSIGN_PRIMARY, NULL, SecurityImpersonation, TokenPrimary,
    67.         &hNewToken))
    68.     {
    69.         printf("DuplicateTokenEx failed, error code: 0x%0.8lX", GetLastError());
    70.         goto Cleanup;
    71.     }
    72.  
    73.     printf("TOKEN DUPLICATED!");
    74.  
    75. Cleanup:
    76.  
    77.     if (NULL != pSD) LocalFree((HLOCAL)pSD);  
    78.     if (NULL != hNewToken) CloseHandle(hToken);  
    79.     if (NULL != hToken) CloseHandle(hNewToken);
    80.     if (NULL != hProcess) CloseHandle(hProcess);
    81.  
    82.     return 0;
    83. }
    А чем плох запуск через службу?
     
    M0rg0t нравится это.
  20. M0rg0t

    M0rg0t Well-Known Member

    Публикаций:
    0
    Регистрация:
    18 окт 2010
    Сообщения:
    1.576
    Andrey333, да, это то что надо. Спасибо!

    В нем ничего плохого нет, да и в целом, мне поддержка ХР давно уже не нужна. Кто ее юзает? Ну вот кроме Клерка и того товарища, что ходит по форумам с глюками АМД. Практической ценности мало. Просто, однажды тестил код запуска от системы, который корректно работает на виста-10, но не сработал на ХР. Вот стало интересно.
    А через службу , конечно же, я знал как запустить, но задался целью разобраться с токенами - почему в ОС выше оно работает, а тут нет. Как то так.

    Спасибо еще раз за помощь!