Borrar la cabecera de un ejecutable .NET

Iniciado por Borito30, 26 Mayo 2017, 16:21 PM

0 Miembros y 2 Visitantes están viendo este tema.

Borito30

Hola estoy intentando borrar la cabecera en .NET el método que encontré por internet y que usan es:
Código (csharp) [Seleccionar]
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;


namespace ConsoleApplication9
{
   class Program
   {
       [DllImport("kernel32.dll")]
       public static extern IntPtr OpenProcess(int dwDesiredAccess, bool bInheritHandle, int dwProcessId);
       [DllImport("kernel32.dll", SetLastError = true)]
       static extern bool ReadProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, [Out] byte[] lpBuffer, int dwSize, out IntPtr lpNumberOfBytesRead);
       [DllImport("kernel32.dll", SetLastError = true)]
       //static extern bool WriteProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, byte[] lpBuffer, uint nSize, out UIntPtr lpNumberOfBytesWritten);
       static extern bool WriteProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, byte[] lpBuffer, int dwSize, ref int lpNumberOfBytesWritten);
       [DllImport("kernel32.dll")]
       public static extern IntPtr GetModuleHandle(string lpModuleName);
       private static int ErasePEHeader() // hModule = Handle to the module, procName = Process name (eg. "notepad")
{
   byte[] imagentheaderptr = new byte[4];
   byte[] Stub = new byte[120];
   byte[] Stub2 = new byte[0x108];
   int Out=0, Out2=0;

           IntPtr hModule = GetModuleHandle(null);
           
           string procName = System.Reflection.Assembly.GetExecutingAssembly().GetName().Name;
           procName = procName;
           Console.WriteLine(hModule + "," + procName);

           IntPtr proc = OpenProcess(0x001F0FFF, false, System.Diagnostics.Process.GetProcessesByName(procName)[0].Id);
   IntPtr IMAGE_NT_HEADER = new IntPtr((hModule.ToInt32() + 60)), out2 = IntPtr.Zero;
   ReadProcessMemory(proc, IMAGE_NT_HEADER, imagentheaderptr, 4, out out2);
   if ((WriteProcessMemory(proc, hModule, Stub, 120, ref Out) == true) && (WriteProcessMemory(proc, hModule, Stub2, 0x100, ref Out2) == true)) return Out + Out2;
   else return 0;
}
       static void Main(string[] args)
       {
           int a = ErasePEHeader();
           Console.WriteLine(a);
           Console.ReadKey();
       }
   }
}

Pero siempre me devuelve 0 o falso. ¿Alguien que me pueda explicar porque nunca la borra?
Estoy en contra del foro libre y la Sección de juegos y consolas (distraen al personal)

MCKSys Argentina

Hola!

Verifica lo que devuelven las APIs que llamas.

Por otro lado, no necesitas ni usar OpenProcess, WriteProcessMemory, etc, etc. pues estás en tu propio proceso.

Lo único que te hraía falta sería VirtualProtect para poder escribir y luego otra API tipo ZeroMemory para poner todo a cero.

También deberías depurar el código...  :P

Saludos!
MCKSys Argentina

"Si piensas que algo está bien sólo porque todo el mundo lo cree, no estás pensando."


Eleкtro

#2
Cita de: MCKSys Argentina en 26 Mayo 2017, 18:45 PMVerifica lo que devuelven las APIs que llamas.

Ya lo he hecho yo por él. La función WriteProcessMemory le devuelve el código de error Win32 "998" (dec) que hace referencia al nombre de error "ERROR_NOACCESS" ("Invalid access to memory location"), traducido a código de error HRESULT: "800703E6" (hex), lo que equivale a la excepción administrada System.BadImageFormatException con mensaje de error: "Se realizó un acceso no válido a la ubicación de memoria."

Algo falla al intentar escribir la memoria, eso está claro. :xD

No he depurado las demás llamadas a las otras funciones declaradas de la WinAPI (no es mi trabajo hacerlo).




El código que estás usando es un copy&paste de aquí:


Así que si por casualidad lo que estás intentando hacer es eliminar la cabecera PE con la intención de hacer un anti-dumper, entonces quizas esta otra metodología te pueda resultar de utilidad:


( no he probado el código, la ing. inversa o temas relacionados no son mi fuerte. )

En ese código parece aplicarse lo que te mencionó el compañero MckSYS:
Cita de: MCKSys Argentina en 26 Mayo 2017, 18:45 PMLo único que te hraía falta sería VirtualProtect para poder escribir y luego otra API tipo ZeroMemory para poner todo a cero.

PD: Puedes traducirlo a C# con cualquier conversor de código online.

Saludos!








Borito30

#3
Algo así pero me devuelve excepcion:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;


namespace ConsoleApplication9
{
    class Program
    {
        public enum MemoryProtectionConsts : uint
        {
            EXECUTE = 0x10,
            EXECUTE_READ = 0x20,
            EXECUTE_READWRITE = 0x40,
            NOACCESS = 0x01,
            READONLY = 0x02,
            READWRITE = 0x04
        }

        [DllImport("kernel32.dll")]
        public static extern IntPtr GetModuleHandle(string lpModuleName);
        [DllImport("kernel32.dll", SetLastError = true)]
        private static extern bool VirtualProtect(IntPtr lpAddress, int dwSize, MemoryProtectionConsts flNewProtect,
            int lpflOldProtect);
        [DllImport("kernel32.dll", CharSet = CharSet.Auto, EntryPoint = "RtlSecureZeroMemory")]
        private static extern void SecureZeroMemory(IntPtr ptr, IntPtr cnt);
        private static int ErasePEHeader() // hModule = Handle to the module, procName = Process name (eg. "notepad")
        {
            int OldProtect = 0;
            IntPtr pBaseAddr = GetModuleHandle(null);
            VirtualProtect(pBaseAddr, 4096, // Assume x86 page size
             MemoryProtectionConsts.READWRITE, OldProtect);
            SecureZeroMemory(pBaseAddr, (IntPtr)4096);
            return 0;
        }
        static void Main(string[] args)
        {
            ErasePEHeader();
            Console.WriteLine("");
            Console.ReadKey();
        }
    }
}


CitarPor otro lado, no necesitas ni usar OpenProcess, WriteProcessMemory, etc, etc. pues estás en tu propio proceso.
Tienes razón me pase cinco pueblos.
Citarhttp://www.mpgh.net/forum/showthread.php?t=743307
Tendré que repasarme enserio la teoria..

El error que me devuelve es:


Y ya de paso dejar de copy/pastear y aprender a programar  :xD

Estoy en contra del foro libre y la Sección de juegos y consolas (distraen al personal)

Eleкtro

#4
Cita de: Ragaza en 27 Mayo 2017, 04:51 AMEl error que me devuelve es:

El mensaje de error te está diciendo que no encuentra ningún export con el nombre "RtlSecureZeroMemory", y eso proobablemente sea por que, como se indica en la MSDN, el alias "SecureZeroMemory" que apunta a la función "RtlSecureZeroMemory" no está expuesta en ninguna dll.

En su lugar puedes probar a utilizar la función RtlZeroMemory:
Código (csharp) [Seleccionar]
[DllImport("Kernel32.dll", EntryPoint = "RtlZeroMemory", SetLastError = false)]
private void ZeroMemory(IntPtr destination, IntPtr length)
{}

El efecto es exactamente el mismo, según la documentación oficial, la única diferencia es que RtlSecureZeroMemory garantiza el borrado/zerofill.

Saludos.








Borito30

Basicamente es lo mismo:
[DllImport("kernel32.dll")]
private static extern IntPtr ZeroMemory(IntPtr addr, IntPtr size);

[DllImport("kernel32.dll")]
private static extern IntPtr VirtualProtect(IntPtr lpAddress, IntPtr dwSize, IntPtr flNewProtect, ref IntPtr lpflOldProtect);

[DllImport("kernel32.dll")]
public static extern IntPtr GetModuleHandle(string lpModuleName);

public static void EraseHeader()
{
IntPtr address = GetModuleHandle(null);
IntPtr dwOld = default(IntPtr);
VirtualProtect(address, (IntPtr)4096, (IntPtr)0x40, ref dwOld);
ZeroMemory(address, (IntPtr)4096);
}


Pero si cargas un formulario a tu aplicación te mostrara System.outofmemory exception.
Estoy en contra del foro libre y la Sección de juegos y consolas (distraen al personal)