Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Delphi: WinAPI и системное программирование > Как поменять права процасса


Автор: _sten_ 22.11.2007, 22:48
Как моей программе поставить права System??
Есть мисль сделать инжект DLL в процес с правами SYSTEM (например lsass.exe) и запустить с под него нужнум программу. Но не получается сделать инжект, пробывал так:
Код

library hook_dll;

uses Windows, UrlMon;

var
   _hook: HHOOK = 0;
   thID: THandle;

function HookProc(nCode, wParam, lParam: integer): integer stdcall;
begin
     Result:=CallNextHookEx(_hook, nCode, wParam, lParam);
end;

procedure SetHK(hk: HHOOK) stdcall;
begin
     _hook:=hk;
end;

procedure WorkWithNet(thrVar: integer) stdcall;
begin
    winexec('calc.exe',sw_show);
     MessageBox(0, 'Все ок',
     'Hook DLL', MB_OK);
     
end;

exports
       HookProc name 'HookProc',
       SetHK name 'SetHK';

begin
     if GetModuleHandle(nil)=GetModuleHandle('iexplore.exe') then
        begin
             CreateThread(nil, 0, @WorkWithNet, pointer(12345), 0, thID);
        end;
end.



и лоадер:
Код

program Injector;

uses
  Windows;

const DLL_INJ = 'DLL Injector (HOOKS)';

type TShp = procedure (hk: HHOOK) stdcall;

procedure InjectDLLviaHOOKS(dll_name: string);
var
   h: THandle;
   p: pointer;
   sh: TShp;
   hk: HHOOK;
begin
     h:=LoadLibrary(PAnsiChar(dll_name));
     if h=0 then
        begin
             MessageBox(0, PAnsiChar('Не могу загрузить DLL '+dll_name+'!'), DLL_INJ, MB_OK+MB_ICONERROR);
             exit;
        end;
     p:=GetProcAddress(h, 'HookProc');
     @sh:=GetProcAddress(h, 'SetHK');
     if ((p=nil) or (@sh=nil)) then
        begin
             MessageBox(0, PAnsiChar('Библиотека '+
                           dll_name+' не содержит необходимых процедур!'),
                           DLL_INJ, MB_OK+MB_ICONERROR);
             FreeLibrary(h);
             exit;
        end;
     hk:=SetWindowsHookEx(WH_CALLWNDPROC, p, h, 0);
     if hk=0 then
        begin
             MessageBox(0, PAnsiChar('Невозможно установить ловушку!'),
                           DLL_INJ, MB_OK+MB_ICONERROR);
             FreeLibrary(h);
             exit;
        end;
     sh(hk);
     MessageBox(0, 'Ловушка установлена! Нажмите OK для снятия.',
                   DLL_INJ, MB_OK);
     UnhookWindowsHookEx(hk);
     FreeLibrary(h);
end;

begin
     InjectDLLviaHOOKS('hook_dll.dll');
end.



с инретнетексполорером все ок, а вот с без оконными приложениями ничего не получается....

Автор: dumb 23.11.2007, 02:12
Цитата(_sten_ @  22.11.2007,  22:48 Найти цитируемый пост)
а вот с без оконными приложениями ничего не получается...
и не получится таким методом. пользуй CreateRemoteThread.

Автор: _sten_ 23.11.2007, 10:59
А поподробнее можно?

Автор: Riply 23.11.2007, 11:07
Цитата(dumb @  23.11.2007,  02:12 Найти цитируемый пост)
пользуй CreateRemoteThread. 


А так разве получиться ?
Что-то "меня терзают смутные сомнения", можно-ли таким способом можно поднять свои права  (с)  smile 

P.S.
 Сама на пробовала.

Автор: bartram 23.11.2007, 13:11
Цитата(Riply @  23.11.2007,  13:07 Найти цитируемый пост)
Что-то "меня терзают смутные сомнения", можно-ли таким способом можно поднять свои права  (с) 

Создаешь удаленный поток и в нем запускаешь....

Автор: dumb 23.11.2007, 14:52
Цитата(Riply @  23.11.2007,  11:07 Найти цитируемый пост)
Что-то "меня терзают смутные сомнения", можно-ли таким способом можно поднять свои права
про поднятие прав речи и не шло.  smile

Автор: Riply 23.11.2007, 15:27
Цитата(dumb @  23.11.2007,  14:52 Найти цитируемый пост)
про поднятие прав речи и не шло.


Значит я не правильно поняла.
Я подумала, что имеется ввиду: создаем нить в теле жертвы, облалающей более высокими правами, чем наши,
а эта нить создает новый процесс уже с правами жертвы smile 

Уже собралась было писать тестовый пример, чтобы убедиться, что такой фокус не пройдет.
Как я поимаю время можно не тратить ?

Автор: _sten_ 23.11.2007, 15:43
Цитата

Значит я не правильно поняла.
Я подумала, что имеется ввиду: создаем нить в теле жертвы, облалающей более высокими правами, чем наши,
а эта нить создает новый процесс уже с правами жертвы  

Уже собралась было писать тестовый пример, чтобы убедиться, что такой фокус не пройдет.
Как я поимаю время можно не тратить ?

Да все именно так, только я не могу понять почему не получится? 

Автор: dumb 23.11.2007, 17:02
Цитата(Riply @  23.11.2007,  15:27 Найти цитируемый пост)
Как я поимаю время можно не тратить ? 
не трать. это было бы вопиющим privilege escalation.

Автор: Riply 23.11.2007, 17:42
Цитата(dumb @  23.11.2007,  17:02 Найти цитируемый пост)
не трать. это было бы вопиющим privilege escalation. 


Я тоже так считаю.
Про "смутные сомнения" написала исходя из того, что (чем черт не шутит), 
а вдруг такой финт пройдет именно для перехода:  Администратор --> Ситема ?
Админские права они не совсем такие как другие. 
Некузяво выразилась, но надеюсь понятно, что я хотела сказать  smile 

Автор: _sten_ 23.11.2007, 21:25
Дык сопственно что именно не получится? Внедрится в SYSTEM-процес или права не унаследуются?

Автор: bems 23.11.2007, 22:20
пропишись в HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon\Notify

Автор: Riply 23.11.2007, 23:25
Не удержалась и набросала "на коленке" тестовый пример.
Моему удивлению нет границ:
попробовала сыграть такую шутку с ibserver.exe (от Borland).
Проскочило...  "Ничего не понимаю". (с)  smile 
Работала из под админа. ibserver, и слова мне не сказав, запустил процесс из под системы.

Надо привести код в божеский вид и попробовать то же самое в разных, 
связках, например,  Power User --> Admin (уверена, что не пройдет smile)
и с разными процессами типа WinLgon.

Н это так, "для очистки совести". 
Видимо, я была права, что "Админские права - особые права" smile

Автор: _sten_ 23.11.2007, 23:59
Riply,  а монжо на примерчик посмотреть?

Автор: Riply 24.11.2007, 01:21
Цитата(_sten_ @  23.11.2007,  23:59 Найти цитируемый пост)
Riply,  а монжо на примерчик посмотреть? 


Да я ж написала, что собирала его "на коленке".
Ну и закономерный результат небрежности в написании кода: работать то он работает, только
при попытке обратиться к Handle`у мною же созданной нити получаю Access is denied.
А это означает, что где-то у меня напортачено, просто сразу не проявляется :(

Автор: Riply 24.11.2007, 13:04
Вот что дала проверка:   smile 
 Этим способом можно из под Админа получить права SYSTEM.
Как жертва использовался Winlogon
 Повысить права в других случаях - не получается (во всяком случае у меня  smile )
Вот примерный код:
(там используется пара простеньких функций. 
Я думаю, написать их самостоятельно, заинтересованным лицам не составит труда).

Код

type
 PFunctTable = ^TFunctTable;
 TFunctTable = packed record
  hKernel32: HMODULE;
  _GetLastError: function: DWORD; stdcall;
  _CloseHandle: function(hObject: THandle): BOOL; stdcall;
  _CreateProcessW: function(lpApplicationName: PWideChar; lpCommandLine: PWideChar; 
                                              lpProcessAttributes, lpThreadAttributes: PSecurityAttributes;
                                              bInheritHandles: BOOL; dwCreationFlags: DWORD; lpEnvironment: Pointer; lpCurrentDirectory: PWideChar;
                                              const lpStartupInfo: TStartupInfoW; var lpProcessInformation: TProcessInformation): BOOL; stdcall;
  function InitSelf: DWord;
 end;

type
 PInjectInfo = ^TInjectInfo;
 TInjectInfo = packed record
  ProcessNameW: array[0..Pred(MAX_PATH)] of WideChar;
  FuntionsTable: TFunctTable;
  LastErr: DWord;
  function pInjectTreadCode: Pointer;
  function InitSelf(const pwLibName: PWideChar; const cbParam: DWord): DWord;
 end;

function TFunctTable.InitSelf: DWord;
begin
 Result := ERROR_CALL_NOT_IMPLEMENTED;
 FillChar(Self, SizeOf(TFunctTable), 0);
 hKernel32 := GetModuleHandle(kernel32);
 if hKernel32 <> 0 then
  try
   @_GetLastError := GetProcAddress(hKernel32, 'GetLastError');
   if not Assigned(@_GetLastError) then Exit;
   @_CloseHandle := GetProcAddress(hKernel32, 'CloseHandle');
   if not Assigned(@_CloseHandle) then Exit;
   @_CreateProcessW := GetProcAddress(hKernel32, 'CreateProcessW');
   if not Assigned(@_CreateProcessW) then Exit;
   Result := ERROR_SUCCESS;
  finally
   if Result <> ERROR_SUCCESS then
    begin
     Result := GetLastError;
     FillChar(Self, SizeOf(TFunctTable), 0);
    end;
  end
 else Result := GetLastError;
end;

function TInjectInfo.InitSelf(const pwLibName: PWideChar; const cbParam: DWord): DWord;
begin
 FillChar(Self, SizeOf(TInjectInfo), 0);
 Result := FuntionsTable.InitSelf;
 if Result = ERROR_SUCCESS then
  if pwLibName <> nil then lstrcpyw(ProcessNameW, pwLibName);
end;

function TInjectInfo.pInjectTreadCode: Pointer;
begin
 Result := Pointer(DWord(@Self) + SizeOf(TInjectInfo));
end;

function InjectInfo_AllocMem(var pInjInfo: PInjectInfo; const pRemoteThread: Pointer; const cbCodeSize: DWord): DWord;
begin
 Result := cbCodeSize + SizeOf(TInjectInfo);
 ReallocMem(pInjInfo, Result);
 Move(pRemoteThread^, pInjInfo.pInjectTreadCode^, cbCodeSize);
end;

procedure InjectInfo_Dispose(var pInjInfo: PInjectInfo);
begin
 ReallocMem(pInjInfo, 0);
end;

function RPC_Proc(pInjInfo: PInjectInfo): DWord; stdcall;
var
 SiW: _STARTUPINFOW;
 Proc_Info: _PROCESS_INFORMATION;
begin
 Result := ERROR_SUCCESS;
 with SiW do
  begin
   cb := SizeOf(STARTUPINFOW);
   dwFlags := startf_UseShowWindow;
   wShowWindow := SW_SHOWNORMAL;
   lpReserved := nil;
   lpDesktop := nil;
   lpTitle := nil;
   dwX := 0;
   dwY := 0;
   dwXSize := 0;
   dwYSize := 0;
   dwXCountChars := 0;
   dwYCountChars := 0;
   dwFillAttribute := 0;
   cbReserved2 := 0;
   lpReserved2 := nil;
   hStdInput := 0;
   hStdOutput := 0;
   hStdError := 0;
  end;
 with pInjInfo^, FuntionsTable do
  if  _CreateProcessW(nil, @ProcessNameW,
                      nil, nil, False,
                      CREATE_DEFAULT_ERROR_MODE,
                      nil, nil, SiW, Proc_Info) then
   begin
    _CloseHandle(Proc_Info.hThread);
    _CloseHandle(Proc_Info.hProcess);
    LastErr := ERROR_SUCCESS;
   end
 else LastErr := _GetLastError;
end;

function RPC_CodeSize: DWord;
begin
 Result := DWord(@RPC_CodeSize) - DWord(@RPC_Proc);
end;

function Proc_CreateRemote(const hVictim: THandle; const pwProcessName: PWideChar; var RemoteError: DWord): DWord;
var
 pInjInfo: PInjectInfo;
 WaitArr: Int64;
 ThreadID, WaitResult, cbWritten, TmpSize: DWord;
 pRemoteData: Pointer;
 hThread: THandle;
begin
 pInjInfo := nil;
 pRemoteData := nil;
 WaitResult := WAIT_OBJECT_0;
 TmpSize := InjectInfo_AllocMem(pInjInfo, @RPC_Proc, RPC_CodeSize);
 try
  Result := pInjInfo.InitSelf(pwProcessName, ERROR_SUCCESS);
  if Result = ERROR_SUCCESS then
   if Proc_AllocAndWriteMemory(hVictim, MEM_COMMIT or MEM_RESERVE, PAGE_READWRITE, pInjInfo, TmpSize, pRemoteData) then
    try
     hThread := CreateRemoteThread(hVictim, nil, 0, PInjectInfo(pRemoteData).pInjectTreadCode, pRemoteData, 0, ThreadID);
     if hThread <> 0 then
      try
       WaitArr := Make_Int64(hVictim, hThread);
       WaitResult := WaitForMultipleObjects(2, @WaitArr, False, INFINITE);
       case WaitResult of
        WAIT_OBJECT_0:
         begin
          if ReadProcessMemory(hVictim, pRemoteData, pInjInfo, SizeOf(TInjectInfo), cbWritten) then
           begin
            RemoteError := pInjInfo.LastErr;
            Result := ERROR_SUCCESS;
           end
          else Result := GetLastError;
         end;
        WAIT_OBJECT_0 + 1: Result := ERROR_WAIT_NO_CHILDREN;
        WAIT_FAILED: Result := GetLastError;
        else Result := ERROR_WAIT_NO_CHILDREN;
       end;
      finally
       CloseHandle(hThread);
      end
     else Result := GetLastError;
    finally
     if (WaitResult <> WAIT_OBJECT_0 + 1) and (WaitResult <> WAIT_TIMEOUT)
      then VirtualFreeEx(hVictim, pRemoteData, 0, MEM_RELEASE);
    end
   else Result := GetLastError;
 finally
  InjectInfo_Dispose(pInjInfo);
 end;
end;


P.S.
 При работе не забываем дать себе Debud-привилегии, 
 и внимательно относимся к параметрам при открытии целевого процесса

P.S.S
 Можно было бы обойтись без ожидания и чтения (PROCESS_VM_READ и SYNCHRONIZE), 
 но они дают нам возможность получить код ошибки и убрать за собой мусор  smile 

Автор: _sten_ 24.11.2007, 21:27
Я наверное покажусь ужасно наглым, но все же можно исходник;)

Автор: Riply 24.11.2007, 22:17
Цитата(_sten_ @  24.11.2007,  21:27 Найти цитируемый пост)
Я наверное покажусь ужасно наглым, но все же можно исходник;) 


А в чем проблеммы ?
Если я не ошибаюсь, там не хватает двух ф-ий. 
Я умышленно их не привела. Своего рода страховка.
Тому кто понимает, что делает их написать не сложно.
А если не понимаешь, то надо идти в Help. (Эта методика и у Рихтера хорошо описана)

Дело в том, что скорее всего тестирование будет на "жизненно важных" процессах.
Иначе смысла в этом никакого нет. 
 Ошибка, очень вероятно, приведет к падению системы. Или к чему по-хуже. 
 Например, если ты попробуешь освободить память в целевом процессе раньше, чем отработает нить.
Я не хочу оказаться виновной в подобных казусах. smile 
Sorry.

P.S.
 Будут конкретные вопросы - постараюсь ответить.

Автор: _sten_ 26.11.2007, 11:00
http://wasm.ru/article.php?article=apihook_3 нашол замечатильную сатейку про переход в 0-е кольцо безопасности, в нем полний доступ к памяти, и примеры как сделать такое безобразие как помениять PID и имя процеса. Так вот может можно подобним образом поменять права или поменять родителя, а значит и права... 
Возможно ли такое? И если можно то как? 

Автор: dumb 27.11.2007, 03:05
Цитата(_sten_ @  26.11.2007,  11:00 Найти цитируемый пост)
нашол замечатильную сатейку про переход в 0-е кольцо безопасности, в нем полний доступ к памяти
все легитимные способы входа в ring0 требуют наличия административных прав. нелегитимные же способы проникновения в 0-ое кольцо или получения адм.прав основаны на уязвимостях, причем приватных. ибо если они попадают "на публику", их довольно резво исправляют.
так что можешь остыть.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)