A forum for reverse engineering, OS internals and malware analysis 

Ask your beginner questions here.
 #25529  by Brock
 Sun Mar 29, 2015 6:15 am
Hi Vrtule,

Not sure about Windows 8 (haven't tested) however on Windows 8.1 protected signer processes belonging to WinTCB, LSA and Antimalware (i.e> MsMpEng.exe aka Windows Defender) will not grant PROCESS_TERMINATE or THREAD_SUSPEND_RESUME access

Best Regards,
Brock
 #25536  by Vrtule
 Mon Mar 30, 2015 10:38 am
Hello Brock,

I actually did not play with protected processes on Windows 8 and newer versions. Does the protected process flag (a bit 11 in the Flags2 field of EPROCESS structure I think) really cause this? Or did the kernel used ObRegisterCallbacks?

Vrtule
 #25537  by Brock
 Mon Mar 30, 2015 11:41 am
Hey Vrtule,

As far as AudioDg is concerned it's a low-integrity protected process so PROCESS_TERMINATE should still be granted from what I understand. It's using the Authenticode level is all. The other levels I mentioned in my previous post will not grant terminate access, though. Alex Ionescu has a great writeup on changes here http://www.alex-ionescu.com/?p=97 That bit inside the ProtectedProcess field is now a new field and no longer a simple on/off bit within EPROCESS struct, it's more complex in Win 8.1+ and I've a feeling when Windows 10 is full-fledged RTM that disabling these processes will not be quite as easy as it was in previous versions of Windows. Too bad opening these processes doesn't allow for MAXIMUM_ALLOWED to try all access combinations, instead I am using PROCESS_QUERY_LIMITED_INFORMATION which works fine for querying the "extended" process basic info, the process name etc. You can open them and read the process image name with QueryFullProcessImageName and get basic process info with NtQueryInformationProcess, the access mask is the key to them, of course. I do this in one of my libs and it works through Windows 10. Check out that link to Alex's article, it's pretty interesting (to me anyhow)
Code: Select all
type
PROCESS_EXTENDED_BASIC_INFORMATION = record
  Size: SIZE_T;
  ProcessBasicInformation: PROCESS_BASIC_INFORMATION;
  Flags: DWORD;
end;

function DECODE_BITFIELD(const dwBitField: DWORD; BitIndex: Byte): Byte;
begin
  result := (dwBitField shr (BitIndex shr 8)) and ((1 shl BitIndex) - 1);
end;

function IsBitSet(const dwBitField: DWORD; BitIndex: Byte): BOOL;
begin
  result := DECODE_BITFIELD(dwBitField, BitIndex) <> 0;
end;

function IsProtectedProcess(const dwProcessId: DWORD): BOOL;
var
  pebi: PROCESS_EXTENDED_BASIC_INFORMATION;
  hProcess: THandle;
const
  IsProtectedProcessBit = 1;
  IsWow64ProcessBit = 2;
  IsProcessDeletingBit = 3;
  IsCrossSessionCreateBit = 4;
  {SPARE 28 bits < Windows 8 else}
  IsFrozenBit = 5;
  IsBackgroundBit = 6;
  IsStronglyNamedBit  = 7;
  {SPARE 25 bits = Windows 8/8.1}
begin
  result := False;
  // Protected processes and PROCESS_QUERY_LIMITED_INFORMATION access_mask
  // are only supported on Windows Vista+
  if Byte(GetVersion()) < 6 then
  Exit;
  hProcess := OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION,
                          False,
                          dwProcessId);
  if (hProcess <> 0) then
  begin
  pebi.Size := sizeof(pebi);
  if (NtQueryInformationProcess(hProcess,
                                ProcessBasicInformation,
                                @pebi,
                                sizeof(pebi),
                                nil) = STATUS_SUCCESS) then
  result := IsBitSet(pebi.Flags, IsProtectedProcessBit);
  CloseHandle(hProcess);
  end;
end;

Best Regards,
Brock