Escanear memoria.

Iniciado por Rekt, 22 Julio 2017, 12:37 PM

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

Rekt

Hola, estoy programando un programa que detecta malware según ciertos patrones que tenga.
La verdad es que soy novato con lo relacionado con memoria y no estoy seguro de cómo hacerlo, estoy interesado en escanear cadenas/strings que son estáticas en la memoria pero no he encontrado ninguna forma eficaz de hacerlo.

He encontrado esto en un foro, pero siempre devuelve 0

Código (csharp) [Seleccionar]
           public static List<MEMORY_BASIC_INFORMATION> MemReg { get; set; }

           public static void MemInfo(IntPtr pHandle)
           {
               IntPtr Addy = new IntPtr();
               while (true)
               {
                   MEMORY_BASIC_INFORMATION MemInfo = new MEMORY_BASIC_INFORMATION();
                   int MemDump = VirtualQueryEx(pHandle, Addy, out MemInfo, Marshal.SizeOf(MemInfo));
                   if (MemDump == 0) break;
                   if ((MemInfo.State & 0x1000) != 0 && (MemInfo.Protect & 0x100) == 0)
                       MemReg.Add(MemInfo);
                   Addy = new IntPtr(MemInfo.BaseAddress.ToInt32() + MemInfo.RegionSize);
               }
           }
           public static IntPtr _Scan(byte[] sIn, byte[] sFor)
           {
               int[] sBytes = new int[256]; int Pool = 0;
               int End = sFor.Length - 1;
               for (int i = 0; i < 256; i++)
                   sBytes[i] = sFor.Length;
               for (int i = 0; i < End; i++)
                   sBytes[sFor[i]] = End - i;
               while (Pool <= sIn.Length - sFor.Length)
               {
                   for (int i = End; sIn[Pool + i] == sFor[i]; i--)
                       if (i == 0) return new IntPtr(Pool);
                   Pool += sBytes[sIn[Pool + End]];
               }
               return IntPtr.Zero;
           }
           public static IntPtr AobScan(string ProcessName, byte[] Pattern)
           {
               Process[] P = Process.GetProcessesByName(ProcessName);
               if (P.Length == 0) return IntPtr.Zero;
               MemReg = new List<MEMORY_BASIC_INFORMATION>();
               MemInfo(P[0].Handle);
               for (int i = 0; i < MemReg.Count; i++)
               {
                   byte[] buff = new byte[MemReg[i].RegionSize];
                   ReadProcessMemory(P[0].Handle, MemReg[i].BaseAddress, buff, MemReg[i].RegionSize, 0);

                   IntPtr Result = _Scan(buff, Pattern);
                   if (Result != IntPtr.Zero)
                       return new IntPtr(MemReg[i].BaseAddress.ToInt32() + Result.ToInt32());
               }
               return IntPtr.Zero;
           }

TickTack

Hola Rekt,

quieres escanear procesos de memoria?

O a que te refieres con memoria? Que memoria?


Gracias y saludos
Citar
"Ninguna mentira puede inventarse lo suficientemente patán: el pueblo hispanohablante la cree. Por una consigna que se les dio, persiguieron a sus compatriotas con mayor encarnizamiento que a sus verdaderos enemigos."

Rekt

#2
Cita de: TickTack en 23 Julio 2017, 20:28 PM
Hola Rekt,

quieres escanear procesos de memoria?

O a que te refieres con memoria? Que memoria?


Gracias y saludos
Perdoan por no responder antes..
A ver, se me ha ocurrido que una forma de detectar malware es escanear todos los procesos abiertos buscando ciertos patrones que siguen, por ejemplo un string.
He encontrado una base de datos que tiene todos estos datos, patrones en memoria, hash de virus, etc y me gustaría hacer un programa que buscase estos strings/patrones en la memoria de todos los programas.
Pero no hace falta que sean exactamente todos, los programas x64 bits pueden ser saltados.
La cosa es que el codigo que he proporcionado siempre me devuelve 0 o se queda atascado  :(
Basicamente lo que quiero hacer es un loop en la memoria de cada proceso y mirar si contiene alguno de los strings que yo tengo en la base de datos, y si así fuese, el proceso seria clasificado como malware.

Eleкtro

Hola.

Cita de: TickTack en 23 Julio 2017, 20:28 PMO a que te refieres con memoria? Que memoria?

Doy a entender que se debe estar refiriendo al espacio de memoria asignado/alojado por "X" proceso.




Cita de: Rekt en 22 Julio 2017, 12:37 PMHe encontrado esto en un foro, pero siempre devuelve 0

Puedes mencionar ese foro. Muestra la firma de las funciones VirtualQueryEx y ReadProcessMemory, una firma equivocada podría ser el causante de todo un problema, y no somos adivinos. Un valor de retorno de Cero en cualquiera de ambas funciones significa ERROR; si es eso lo que te devuelve Cero entonces depura dicho error con el miembro System.Runtime.InteropServices.Marshal.GetLastWin32Error() + la clase System.ComponentModel.Win32Exception.

En general ese código es bastante spaghetti.




Lo que no sé es si quieres leer un segmento/región/página de la memoria, o el espacio de memoria al completo. En el segundo caso a esto lo podriamos llamar un dump o dumpeo de la memoria, y para ello la API de Windows nos proporciona una función de nombre MiniDumpWriteDump:


Dicha función es útil en escenarios de depuración, en casos donde queramos dumpear la memoria junto a otra información de depuración de un proceso (ej. los módulos cargados), a un archivo local. Hay que tener en cuenta que esto no se limita a escribir los datos/bytes "raw" del espacio de memoria, sino un archivo de extensión .dmp (minidump) que podemos leer con ciertas herramientas de depuración. Funciona tanto para dumpear executables .NET, como executables nativos, pero lo cierto es que por experiencia sé que puede dar problemas extraños al intentar dumpear algún proceso (nunca llegué a averiguar muy bien la razón).




...Pero todo esto que he explicado aquí arriba es puramente informativo, es para tomárselo como una alternativa (puesto que su propósito es escribir información de depuración, no solo los bytes raw de la memoria, como ya expliqué). La solución tradicional para leer/escanear la memoria de un proceso externo, bueno, lo cierto es que no soy un experto en temas de ing. inversa, pero yo diría que podría ser de la siguiente forma:

1. Utilizar la clase System.Diagnostics.Process (o en su defecto la función Win32 OpenProcess) para localizar el proceso objetivo y obtener su handle.

2. Utilizar la función Win32 VirtualQueryEx para determinar el tamaño de cada región de la memoria.

3. Utilizar la función Win32 ReadProcessMemory para leer la región de memoria.

Ejemplos por separado y para todo, los tienes en la World Wide Web.

Saludos.