Creando un proceso crítico !!

Iniciado por TrashAmbishion, 10 Abril 2016, 08:31 AM

0 Miembros y 1 Visitante están viendo este tema.

TrashAmbishion

Holas,

Tuve un codigo hace ya un tiempo que convertia mi programa en un proceso critico del sistema si tratabas de cerrarlo forzozo daba un pantallazo azul.

Dicho codigo lo perdi alguien tendra algo que me resuelva..

Salu2

HCK.

Tienes el programa hecho?, descompilalo con ILSPY o Reflector y sacas el código. Me interesaría bastante, si lo sacas y lo cuelgas lo agradecería mucho.

Si no cuelga el ejecutable (si es que con suerte tienes alguno compilado con ese código y te cuelgo su código yo).

Un saludo

TrashAmbishion

No bro lo perdí el codigo estaba en C# .Net y tuve que convertirlo a VB.NET y trabajaba super bien, cuando iba a cerrar mi programa tenia que quitarle lo del proceso critico porque sino era pantallazo azul..

Salu2

Slava_TZD



The fact is, even if you were to stop bombing us, imprisoning us, torturing us, vilifying us, and usurping our lands, we would continue to hate you because our primary reason for hating you will not cease to exist until you embrace Islam.

TrashAmbishion

Este codigo no estan elaborado como el que me distes (muchas gracias, juro que busque pero no me sabia el nombre de la API), pero funciona....

Código (vbnet) [Seleccionar]

Imports System.Diagnostics
Imports System.Runtime.InteropServices

Public Class Form1

    <DllImport("ntdll.dll", SetLastError:=True)> _
    Public Shared Function NtSetInformationProcess(ByVal hProcess As IntPtr, ByVal processInformationClass As Integer, ByRef processInformation As Integer, ByVal processInformationLength As Integer) As Integer
    End Function

    ' we want this to be a Critical Process
    Dim isCritical As Integer = 1
    ' we want this to be a Critical Process
    Dim NoNCritical As Integer = 0
    ' value for BreakOnTermination (flag)
    Dim BreakOnTermination As Integer = &H1D


    Sub Critico()
        ' setting the BreakOnTermination = 1 for the current process
        NtSetInformationProcess(Process.GetCurrentProcess().Handle, BreakOnTermination, isCritical, 4)

    End Sub

    Sub NoCritical()
        ' setting the BreakOnTermination = 0 for the current process
        NtSetInformationProcess(Process.GetCurrentProcess().Handle, BreakOnTermination, NoNCritical, 4)

    End Sub

    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        Process.EnterDebugMode()
        'acquire Debug Privileges
    End Sub
End Class

HCK.

Muchas gracias por subirlo compañero!!, no sabía que había una API que creará un proceso crítico... Vamos, tampoco me había hecho falta nunca y no lo había buscado, pero ya sabiéndolo perfecto  ;-)

Un saludo

TrashAmbishion

Ahhh es que nunca sabes cuando te hara falta, jajaja, creo que se puede mejorar para evitar que algun inteligente lo vuelva hacer normal desde otra aplicación si encuentro algo lo subo..

Salu2

HCK.

Tengo que investigarlo cuando tenga un rato... Quizás la idea podría pasar en crear un nuevo thread con un bucle while o en un timer, que fuerce constantemente el estado de proceso crítico... Aunque eso sería un apaño algo cutre que haría a la CPU a consumir un cacho de recursos...  :rolleyes:

Esto que digo quizás podría ser algo más eficiente si en la API podríamos encontrar alguna función que permita comprobar el estado del proceso, y si varía, cambiarlo a crítico de nuevo... No se, todo es mirarlo, si doy con algo lo posteo  ;D

Un saludo

TrashAmbishion

Pues si algo elaborare tambien para impedir algo como eso por ahora no me apura, ok !!

Salu2

Eleкtro

#9
Otra forma de llevarlo a cabo sería utilizando el método Win32 RtlSetProcessIsCritical, el cual lo considero más apropiado o "directo" puesto que afecta al proceso actual desde el que se invocó dicho método, pero claro está, si queremos que afecte a un proceso distinto, entonces hay que usar la ya mencionada función Win32 NTSetInformationProcess.

Hay que tener en cuenta también, que para poder establecer un proceso cómo "crítico", dicho proceso necesita tener establecido el privilegio de proceso "SE_DEBUG_NAME" (y si usasemos la función NtSetInformationProcess, es necesario que el proceso sea abierto con el privilegio "PROCESS_SET_INFORMATION"), por lo que esto aumenta considerablemente el tamaño del código fuente, declarando y utilizando los P/Invokes para asegurarnos (o al menos intentarlo) que todo salga de forma esperada.

Para determinar si un proceso es crítico o no lo es, en versiones superiores a Windows XP podemos llamar a la función Win32 IsProcessCritical, la cual es muy cómoda y abstracta, pero en Windows XP deberemos utilizar la función NtQueryInformationProcess, la cual es insegura llamarla dependiendo de la versión de Windows desde la que se llame (como indica la documentación de dicha función en MSDN), y como Windows XP es un sistema operativo obsoleto, no me he molestado en implementar dicha función.

Aquí está mi solución (probado en Windows 10 y Windows XP), un "todo en uno", tanto para establecer el proceso actual como "Crítico", "Normal", y averiguar si un proceso es crítico o no lo es:

( Todos los P/Invokes del código fuente, excepto el método 'RtlSetProcessIsCritical', los he sacado de mi framework ElektroKit, lo comento por que con mi librería podeis hacer muchas virguerías al poder utilizar todos estos miembros Win32...y una infinidad más en el namespace Elektro.Interop.Win32:
)

Clase para definir el P/Invoking:
Código (vbnet) [Seleccionar]
Namespace Win32

   Friend NotInheritable Class NativeMethods

       <DebuggerNonUserCode>
       Private Sub New()
       End Sub

       <Flags>
       Friend Enum TokenPrivilegesFlags As UInteger
           PrivilegeEnabledBYDefault = &H1UI
           PrivilegeEnabled = &H2UI
           PrivilegeRemoved = &H4UI
           PrivilegeUsedForAccess = &H80000000UI
       End Enum

       <Flags>
       Friend Enum AccessRights As UInteger
           TokenAdjustPrivileges = &H32UI
           TokenQuery = &H8UI
       End Enum

       <StructLayout(LayoutKind.Sequential)>
       Friend Structure TokenPrivileges
           <MarshalAs(UnmanagedType.I4)>
           Public PrivilegeCount As Integer

           <MarshalAs(UnmanagedType.Struct)>
           Public Privileges As LuIdAndAttributes
       End Structure

       <StructLayout(LayoutKind.Sequential)>
       Friend Structure LuIdAndAttributes
           <MarshalAs(UnmanagedType.Struct)>
           Public PLuid As Luid

           <MarshalAs(UnmanagedType.U4)>
           Public Attributes As TokenPrivilegesFlags
       End Structure

       <StructLayout(LayoutKind.Sequential)>
       Friend Structure Luid
           <MarshalAs(UnmanagedType.U4)>
           Public LowPart As UInteger

           <MarshalAs(UnmanagedType.I4)>
           Public HighPart As Integer
       End Structure

       <DllImport("advapi32.dll", SetLastError:=True)>
       Friend Shared Function AdjustTokenPrivileges(
                  <MarshalAs(UnmanagedType.SysInt)> ByVal tokenHandle As IntPtr,
                    <MarshalAs(UnmanagedType.Bool)> ByVal disableAllPrivileges As Boolean,
                  <MarshalAs(UnmanagedType.Struct)> ByRef newState As TokenPrivileges,
                      <MarshalAs(UnmanagedType.U4)> ByVal bufferLength As UInteger,
                  <MarshalAs(UnmanagedType.SysInt)> ByVal previousState As IntPtr,
                  <MarshalAs(UnmanagedType.SysInt)> ByVal returnLength As IntPtr
       ) As <MarshalAs(UnmanagedType.Bool)> Boolean
       End Function

       <DllImport("advapi32.dll", SetLastError:=True)>
       Friend Shared Function OpenProcessToken(
             <MarshalAs(UnmanagedType.SysInt)> ByVal processHandle As IntPtr,
                 <MarshalAs(UnmanagedType.U4)> ByVal desiredAccess As AccessRights,
             <MarshalAs(UnmanagedType.SysInt)> ByRef tokenHandle As IntPtr
       ) As <MarshalAs(UnmanagedType.I4)> Integer
       End Function

       <DllImport("advapi32.dll", SetLastError:=True, CharSet:=CharSet.Unicode, BestFitMapping:=False, ThrowOnUnmappableChar:=True)>
       Friend Shared Function LookupPrivilegeValue(
                 <MarshalAs(UnmanagedType.LPWStr)> ByVal lpSystemName As String,
                 <MarshalAs(UnmanagedType.LPWStr)> ByVal lpName As String,
                 <MarshalAs(UnmanagedType.Struct)> ByRef lpLuid As Luid
       ) As <MarshalAs(UnmanagedType.I4)> Integer
       End Function

       <DllImport("Kernel32.dll", SetLastError:=True)>
       Friend Shared Function IsProcessCritical(
              <MarshalAs(UnmanagedType.SysInt)> ByVal hProcess As IntPtr,
                <MarshalAs(UnmanagedType.Bool)> ByRef refIsCritical As Boolean
       ) As <MarshalAs(UnmanagedType.Bool)> Boolean
       End Function

       <DllImport("ntdll.dll", EntryPoint:="RtlSetProcessIsCritical", SetLastError:=True)>
       Friend Shared Sub SetCurrentProcessIsCritical(
                     <MarshalAs(UnmanagedType.Bool)> ByVal isCritical As Boolean,
                     <MarshalAs(UnmanagedType.Bool)> ByRef refWasCritical As Boolean,
                     <MarshalAs(UnmanagedType.Bool)> ByVal needSystemCriticalBreaks As Boolean)
       End Sub

   End Class

End Namespace


Clase para definir los métodos o abstracción de los algoritmos:
Código (vbnet) [Seleccionar]
Imports Win32
Imports Win32.NativeMethods

Namespace Tools

   Public NotInheritable Class ProcessUtil

       <DebuggerNonUserCode>
       Private Sub New()
       End Sub

       ''' ----------------------------------------------------------------------------------------------------
       ''' <summary>
       ''' Specifies a critical state of a process.
       ''' </summary>
       ''' ----------------------------------------------------------------------------------------------------
       Public Enum ProcessCriticalState As Integer

           ''' <summary>
           ''' Process isn't critical.
           ''' </summary>
           NonCritical = 0

           ''' <summary>
           ''' Process is critical.
           ''' </summary>
           Critical = 1

       End Enum

       ''' ----------------------------------------------------------------------------------------------------
       ''' <summary>
       ''' Determines whether the specified process is considered <c>critical</c>.
       ''' </summary>
       ''' ----------------------------------------------------------------------------------------------------
       ''' <param name="handle">
       ''' A handle (<see cref="IntPtr"/>) to the process to query.
       ''' </param>
       ''' ----------------------------------------------------------------------------------------------------
       ''' <returns>
       ''' A <see cref="ProcessCriticalState"/> enumeration value indicating the critical state.
       ''' </returns>
       ''' ----------------------------------------------------------------------------------------------------
       <DebuggerStepThrough>
       Public Shared Function GetProcessCriticalState(ByVal handle As IntPtr) As ProcessCriticalState

           If (handle = IntPtr.Zero) Then
               Throw New ArgumentNullException(paramName:="handle")

           Else
               Dim result As Boolean
               Dim win32Err As Integer

               NativeMethods.IsProcessCritical(handle, result)
               win32Err = Marshal.GetLastWin32Error()

               If (win32Err <> 0) Then
                   Throw New Win32Exception(win32Err)

               Else
                   Select Case result
                       Case True
                           Return ProcessCriticalState.Critical

                       Case Else
                           Return ProcessCriticalState.NonCritical

                   End Select

               End If

           End If

       End Function

       ''' ----------------------------------------------------------------------------------------------------
       ''' <summary>
       ''' Determines whether the caller process is considered <c>critical</c>.
       ''' </summary>
       ''' ----------------------------------------------------------------------------------------------------
       ''' <returns>
       ''' A <see cref="ProcessCriticalState"/> enumeration value indicating the critical state.
       ''' </returns>
       ''' ----------------------------------------------------------------------------------------------------
       <DebuggerStepThrough>
       Public Shared Function GetCurrentProcessCriticalState() As ProcessCriticalState

           Return ProcessUtil.GetProcessCriticalState(Process.GetCurrentProcess().Handle)

       End Function

       ''' ----------------------------------------------------------------------------------------------------
       ''' <summary>
       ''' Sets the critical state for the caller process.
       ''' </summary>
       ''' ----------------------------------------------------------------------------------------------------
       ''' <param name="state">
       ''' The new critical state.
       ''' </param>
       ''' ----------------------------------------------------------------------------------------------------
       ''' <exception cref="InvalidEnumArgumentException">
       ''' state
       ''' </exception>
       ''' ----------------------------------------------------------------------------------------------------
       <DebuggerStepThrough>
       Public Shared Sub SetCurrentProcessCriticalState(ByVal state As ProcessCriticalState)

           Dim isCritical As Boolean
           Dim wasCritical As Boolean
           Dim needSystemCriticalBreaks As Boolean = False

           Select Case state

               Case ProcessCriticalState.Critical
                   isCritical = True

               Case ProcessCriticalState.NonCritical
                   isCritical = False

               Case Else
                   Throw New InvalidEnumArgumentException(argumentName:="state", invalidValue:=state,
                                                      enumClass:=GetType(ProcessCriticalState))
                   Exit Sub

           End Select

           ' Set "SE_DEBUG_NAME" process privilege,
           ' required to debug and adjust the memory of a process owned by another account.
           ProcessUtil.SetCurrentProcessPrivilege("SE_DEBUG_NAME")

           ' Set the critical state.
           NativeMethods.SetCurrentProcessIsCritical(isCritical, wasCritical, needSystemCriticalBreaks)

#If DEBUG Then
           Debug.WriteLine(String.Format("Current process was critical?: {0}", wasCritical))
#End If

       End Sub

       ''' ----------------------------------------------------------------------------------------------------
       ''' <summary>
       ''' Sets a process privilege for the caller process.
       ''' </summary>
       ''' ----------------------------------------------------------------------------------------------------
       ''' <remarks>
       ''' <see href="https://msdn.microsoft.com/en-us/library/windows/desktop/bb530716%28v=vs.85%29.aspx"/>
       ''' </remarks>
       ''' ----------------------------------------------------------------------------------------------------
       Private Shared Sub SetCurrentProcessPrivilege(ByVal privilegeName As String)

           Dim hToken As IntPtr
           Dim tkp As New TokenPrivileges

           NativeMethods.OpenProcessToken(Process.GetCurrentProcess().Handle,
                                          AccessRights.TokenAdjustPrivileges Or
                                          AccessRights.TokenQuery,
                                          hToken)

           With tkp
               .PrivilegeCount = 1
               .Privileges.Attributes = TokenPrivilegesFlags.PrivilegeEnabled
           End With

           NativeMethods.LookupPrivilegeValue(Nothing, privilegeName, tkp.Privileges.PLuid)
           NativeMethods.AdjustTokenPrivileges(hToken, False, tkp, 0UI, IntPtr.Zero, IntPtr.Zero)

       End Sub

   End Class

End Namespace


Clase (cualquiera) donde utilizar los miembros definidos:
Código (vbnet) [Seleccionar]
Imports Tools
Imports Tools.ProcessUtil

Public NotInheritable Class Form1 : Inherits Form

   ' Establecer el estado del proceso actual a: crítico.
   Private Sub Button1_Click() Handles Button1.Click
       ProcessUtil.SetCurrentProcessCriticalState(ProcessCriticalState.Critical)
   End Sub

   ' Establecer el estado del proceso actual a: no-crítico.
   Private Sub Button2_Click() Handles Button2.Click
       ProcessUtil.SetCurrentProcessCriticalState(ProcessCriticalState.NonCritical)
   End Sub

   ' Determinar el estado del proceso actual.
   Private Sub Button3_Click() Handles Button3.Click
       Dim state As ProcessCriticalState = ProcessUtil.GetCurrentProcessCriticalState()
       MessageBox.Show(String.Format("Is process critical?: {0}", CBool(state)))
   End Sub

End Class