Суть задачи сменить токен произвольного процесса. На виндовс 7 ZwSetInformationProcess с флагом ProcessAccessToken, возвращает STATUS_NOT_SUPPORTED ( 0xC00000BB ). Проблема оказалось в одном из флагов структуры EPROCESS.Flags2 а именно PrimaryTokenFrozen если он сброшен то все хорошо. Теперь вопрос как сбросить PrimaryTokenFrozen ?
Если сбросить флаг вручную то ZwSetInformationProcess возвращает 0, и привелегии изменяються на нужные. Проблема в том что EPROCESS изменяеться. Есть идеи как это обойти ? Пока что есть идея вручную сделать все то что делает ZwSetInformationProcess с флагом ProcessAccessToken....
В общем сводиться примерно к такому упрощенному коду: Код (Text): NTSTATUS PspAssignPrimaryToken( IN PEPROCESS Process, IN HANDLE Token OPTIONAL, IN PACCESS_TOKEN TokenPointer OPTIONAL ) { if ( Process->Flags2 & PrimaryTokenFrozen ) { Status = STATUS_NOT_SUPPORTED } else { Status = SeExchangePrimaryToken (Process, NewToken, &OldToken); PspLockProcessSecurityExclusive (Process, CurrentThread); PspUnlockProcessSecurityExclusive (Process, CurrentThread); } }; Стек вызовов: Код (Text): nt!NtSetInformationProcess nt!PspAssignPrimaryToken nt!PspAssignPrimaryToken експортируются. Если кому интересно к теме прикрепил более подробное описание. Вчера видемо допустил опечатку, nt!PspSetPrimaryToken не вызывается(покрайней мере в стеке вызовов в windbg ее нет) .
Теперь у меня уперся вопрос в поиск самой функции SeExchangePrimaryToken. Интересно было бы услышать какие либо мысли по данной теме. Проблема в том что SeExchangePrimaryToken вызываеться только через NtSetInformationProcess. Покарайней мере мне удалось увидеть еще в ссылки на эту функцию, смотрел в ida6.1 Что надежней структура EPROCESS или поиск SeExchangePrimaryToken.
Нашол по "сигнатурам" SeExchangePrimaryToken, привелегии удалось сменить. Вот примерный код поиска SeExchangePrimaryToken, осталось проверить на остальных ОС. Код (Text): enum CallType{ CallRelative, CallAbsolute }; // GetInstLenght(myiptr0,&dwLen); дизассемблер длин. DWORD *InstrSearchCall(DWORD *myiptr0,DWORD MaxOffset,CallType *calltype) { DWORD dwLen; while (MaxOffset) { GetInstLenght(myiptr0,&dwLen); if ( (dwLen == 5) & ( 0xE8 == *(BYTE*)myiptr0) ){ *calltype = CallRelative; return myiptr0; }; if (MaxOffset < dwLen) return NULL; MaxOffset -= dwLen; myiptr0 = (PDWORD)( dwLen + (PCHAR)myiptr0 ); }; return NULL; }; PVOID SearchSeExchangePrimaryToken(PVOID PspAssignPrimaryToken) { const DWORD MaxOffset = 0x800; //4096 bytes DWORD CurOffset = 0; PDWORD pMainFunction = (PDWORD)PspAssignPrimaryToken; if (!pMainFunction) return NULL; while(CurOffset < MaxOffset) { CallType call_type; PDWORD new_addr; PDWORD AddrCall; DWORD dwInstrSize; new_addr = InstrSearchCall(pMainFunction,MaxOffset,&call_type); GetInstLenght(new_addr,&dwInstrSize); if (call_type == CallRelative) { if ( *(BYTE*)(dwInstrSize + (PCHAR)new_addr ) == 0x89 ) { DWORD tmp; GetInstLenght((PDWORD)(dwInstrSize + (PCHAR)new_addr),&tmp); if (*(BYTE*)(tmp + dwInstrSize + (PCHAR)new_addr ) == 0xEB) { DWORD dwDelta = *(PDWORD)(1 + (PCHAR)new_addr); AddrCall = (PDWORD)( (DWORD)new_addr + (DWORD)dwDelta + 5 ); return AddrCall; }; }; } else AddrCall = NULL; /* if (AddrCall == NULL ) return NULL; */ CurOffset += dwInstrSize + (DWORD)new_addr - (DWORD)pMainFunction ; pMainFunction =(PDWORD)( dwInstrSize + (DWORD)new_addr ); }; return NULL; }; PVOID SearchPspAssignPrimaryToken() { const DWORD MaxOffset = 0x1000; //4096 bytes DWORD CurOffset = 0; PDWORD pMainFunction = (PDWORD)KernelGetProcAddrEx(GetKernelBase(),CalcHash("NtSetInformationProcess")); if (!pMainFunction) return NULL; while(CurOffset < MaxOffset) { CallType call_type; PDWORD new_addr; PDWORD AddrCall; DWORD dwInstrSize; new_addr = InstrSearchCall(pMainFunction,MaxOffset,&call_type); GetInstLenght(new_addr,&dwInstrSize); if (call_type == CallRelative) { if ( *(BYTE*)(dwInstrSize + (PCHAR)new_addr ) == 0xE9 ) { if (*(BYTE*)(5 + dwInstrSize + (PCHAR)new_addr ) == 0x8b) { DWORD dwDelta = *(PDWORD)(1 + (PCHAR)new_addr); AddrCall = (PDWORD)( (DWORD)new_addr + (DWORD)dwDelta + 5 ); return AddrCall; }; }; } else AddrCall = NULL; if (AddrCall == NULL ) return NULL; CurOffset += dwInstrSize + (DWORD)new_addr - (DWORD)pMainFunction ; pMainFunction =(PDWORD)( dwInstrSize + (DWORD)new_addr ); }; return NULL; }; SearchSeExchangePrimaryToken(SearchPspAssignPrimaryToken()); // возвращает адрес SeExchangePrimaryToken