elhacker.net cabecera Bienvenido(a), Visitante. Por favor Ingresar o Registrarse
¿Perdiste tu email de activación?.


Tema destacado: Entrar al Canal Oficial Telegram de elhacker.net


  Mostrar Mensajes
Páginas: 1 2 3 4 5 6 [7] 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 ... 25
61  Programación / .NET (C#, VB.NET, ASP) / Re: Obtener Informacion acerca del modulo correspondiente al StartAdress del Thread. en: 16 Junio 2022, 21:21 pm
No lo he probado pero ¿lo estás compilando para x86, x64, o Any CPU? Y si es este último, ¿tienes activado "Prefer 32-bit"? Te lo digo porque las funciones de depuración son muy quisquillosas en cuanto a la arquitectura.  Te recomendaría primero que nada meterle al programa PIDs de procesos tanto de 32 como de 64 bits a ver si falla con ambos o no. Y luego recompilarlo a otra arquitectura y probar de nuevo. Y es que si compilas para 32 o con prioridad a 32, probablemente no podrías usarlo con procesos de 64 y quizás tampoco al revés (digo probablemente porque no he revisado ese código).

Hablando de eso, y por si acaso, me faltó decir que el ejemplo que puse funcionaría en 32 bits. Para 64, habría que hacer unos pocos cambios, como sustituir los campos Eip, Ebp y Esp de context por sus variantes para x64 (Rip, Rbp, Rsp), pasar IMAGE_FILE_MACHINE_AMD64 a StackWalk64() y cambiar el tipo de la variable startAddress y su tamaño a 64 bits en vez de DWORD (de hecho, sería mejor usar un tipo que cambie con la arquitectura, como un puntero, size_t, etc.).

De cualquier forma, veré si luego tengo tiempo de revisar el código que encontraste y buscar el error.
62  Programación / .NET (C#, VB.NET, ASP) / Re: Obtener Informacion acerca del modulo correspondiente al StartAdress del Thread. en: 15 Junio 2022, 19:15 pm
Le di una revisada rápida a la documentación de la API Debug Help y no es muy difícil, siempre que lo que quieras sea algo básico. Eso sí, hacerlo desde .NET será engorroso porque las funciones de esta API toman varias estructuras que tendrías que definir en tu programa. De cualquier forma, te explico más o menos como lo podrías hacer, con una mezcla de pseudocódigo y C. En este ejemplo se mostraría la información para el proceso actual:

Primero deberías inicializar el manejador de símbolos y luego cargar las tablas de cada módulo cargado por el proceso. Esto carga los nombres de funciones de las dll y demás:

Código
  1. HANDLE hProcess = GetCurrentProcess();
  2. SymInitialize(hProcess, NULL, TRUE);
  3.  
  4. /* En C llamariamos a CreateToolhelp32Snapshot() y Module32First()/Module32Next() para obtener los modulos cargados.
  5. En .NET creo que los obtienes directamente en Process.Modules */
  6. For cada Modulo en proceso.Modules
  7. SymLoadModule64(hProcess, NULL, Modulo.FileName, Modulo.ModuleName, Modulo.BaseAddress, Modulo.ModuleMemorySize);
  8. Next Modulo

A SymInitialize le podrías pasar como segundo parámetro una cadena con rutas separadas por punto y coma, como se explica en: https://docs.microsoft.com/en-us/windows/win32/debug/symbol-paths . Esto te serviría, por ejemplo, para usar el servidor de símbolos de Microsoft, pero es opcional.

Después, iteras a través de los hilos del proceso:

Código
  1. /* En C, Thread32First()/Thread32Next(). En .NET, en la coleccion Threads */
  2. IMAGEHLP_SYMBOL64 *pSym = NULL;
  3. For cada thread en proceso.ProcessThreads
  4.  

Y dentro del for, por cada hilo, obtienes un contexto:

Código
  1. HANDLE hThread = OpenThread(THREAD_ALL_ACCESS, false, thread.id);
  2. CONTEXT context;
  3. context.ContextFlags = CONTEXT_FULL;
  4.  
  5. // Comparar el id, NO el handle
  6. if (thread.id == System.Threading.Thread.CurrentThread.ManagedThreadId)
  7.              RtlCaptureContext(&context);
  8. else {
  9.              SuspendThread(hThread);
  10.              GetThreadContext(hThread, &context);
  11.              ResumeThread(hThread);
  12. }

Llamamos a NtQueryInformationThread() para obtener la dirección de inicio:

Código
  1.       size_t startAddress;
  2.  
  3.       NtQueryInformationThread(hThread, ThreadQuerySetWin32StartAddress, &startAddress, sizeof(startAddress), NULL);



Obtenemos el nombre del módulo (dll/exe) que contiene la función. Dos opciones:



Opción 1.

Llamas a StackWalk64():

Código
  1.       STACKFRAME64 sf64;
  2.       sf64.AddrPC.Offset = context.Eip;
  3.       sf64.AddrPC.Mode = AddrModeFlat;
  4.       sf64.AddrFrame.Offset = context.Ebp;
  5.       sf64.AddrFrame.Mode = AddrModeFlat;
  6.       sf64.AddrStack.Offset = context.Esp;
  7.       sf64.AddrStack.Mode = AddrModeFlat;
  8.  
  9.       StackWalk64(IMAGE_FILE_MACHINE_I386, hProcess, hThread, &sf64, &context, NULL, SymFunctionTableAccess64, SymGetModuleBase64, NULL);

Luego a SymGetModuleInfo64():

Código
  1.       IMAGEHLP_MODULE64 module;
  2.       memset(&module, 0, sizeof(module));
  3.       module.SizeOfStruct = sizeof(module);
  4.       SymGetModuleInfo64(hProcess, sf64.AddrPC.Offset, &module);
  5.  




Opción 2 (recomendada).

Obtenemos directamente el nombre del módulo pasandole startAddress:

Código
  1.       IMAGEHLP_MODULE64 module;
  2.       memset(&module, 0, sizeof(module));
  3.       module.SizeOfStruct = sizeof(module);
  4.       SymGetModuleInfo64(hProcess, startAddress, &module);
  5.  




Luego obtenemos el nombre de la función:

Código
  1.       if (!pSym) (IMAGEHLP_SYMBOL64*)malloc(sizeof(IMAGEHLP_SYMBOL64) + MAX_SYM_NAME * sizeof(TCHAR));
  2.  
  3.       memset(pSym, 0, sizeof(IMAGEHLP_SYMBOL64) + MAX_SYM_NAME);
  4.       pSym->SizeOfStruct = sizeof(IMAGEHLP_SYMBOL64);
  5.       pSym->MaxNameLength = MAX_SYM_NAME;
  6.  
  7.       SymGetSymFromAddr64(hProcess, startAddress, NULL, pSym);

Con esto, ya podrias mostrar la información que quieres:

Código
  1. Console.WriteLine(module.ModuleName & "!" & pSym.Name & "+" (startAddress - pSym.Address).ToString("x"))
  2. CloseHandle(hThread);
  3. Next thread
  4. free(pSym);
  5.  

Lo anterior mostraría algo tipo:

Código:
miEjecutable!mainCRTStartup+0
ntdll!TpCallbackIndependent+140

Por supuesto, esto sólo es un ejemplo para darte una idea. No es nada robusto, no verifico errores, etc., y no es nada limpio, pero lo hice así para que fuera lo más simple posible, además de que sólo le di una leída muy deprisa a la documentación y apenas le dediqué unos minutos al ejemplo. Si lo conviertes correctamente a VB, debería funcionar en general, pero probablemente haya casos límite donde podría fallar. Obviamente, para implementarlo bien, deberías revisar con calma la documentación de las funciones usadas, pero creo que este ejemplo puede servir como punto de partida.

Editado para hacer unas cuantas correcciones.
63  Programación / .NET (C#, VB.NET, ASP) / Re: Obtener Informacion acerca del modulo correspondiente al StartAdress del Thread. en: 14 Junio 2022, 17:22 pm
Sí, en lo que yo me enfoqué es sólo en la dirección, porque pensé que te referías a eso. Pero ¿seguro que es lo mismo que ya obtenías? Que yo recuerde, pT.StartAddress no te da exactamente lo que quieres. O sea, según yo, el resultado que obtienes es distinto al que te da NtQueryInformationThread, y sólo este último es el que se corresponde con lo que te muestran herramientas como Process Explorer o PocessHacker. Prueba a mostrar los hilos de Process.GetCurrentProcess() de una forma y la otra y verás (o no, si es que me falla la memoria).

Para conseguir los nombres creo que sí necesitarías dbghelp.dll, como dicen en el segundo link que pusiste. Si más tarde tengo tiempo, reviso bien la información y posteo lo que encuentre.
64  Programación / .NET (C#, VB.NET, ASP) / Re: Obtener Informacion acerca del modulo correspondiente al StartAdress del Thread. en: 9 Junio 2022, 02:59 am
Más o menos, aunque la función devuelve un simple entero, y alguno de los parámetros no es del todo exacto. En C# sería algo así:

Código
  1. [DllImport("ntdll.dll", CharSet = CharSet.Unicode, SetLastError = true)]
  2. static extern int NtQueryInformationThread(IntPtr ThreadHandle, ThreadInfoClass ThreadInformationClass, IntPtr ThreadInformation, int ThreadInformationLength, IntPtr ReturnLength);

Para conseguir el StartAddress no importa si el enum está incompleto, ya que el único valor que necesitas es 9 (ThreadQuerySetWin32StartAddress).

Por lo demás, y aunque no lo he probado, no veo por qué no habría de funcionar.
65  Programación / .NET (C#, VB.NET, ASP) / Re: Obtener Informacion acerca del modulo correspondiente al StartAdress del Thread. en: 8 Junio 2022, 23:59 pm
La forma en que lo hacen en el segundo link (NtQueryInformationThread) es sencilla en C++, pero no tengo mucha experiencia llamando a funciones de la API desde .NET, y nunca he programado en Vb.Net. De cualquier forma, van algunos consejos que te podrían servir al menos darte una idea general.

En C# sería algo más o menos así:

Obtener handle a cada hilo mediante la función de la API OpenThread (kernel32.dll):

Código
  1. IntPtr hThread = OpenThread(0x0040, false, idHilo);

Luego llamas a NtQueryInformationThread (ntdll.dll):

Código
  1. IntPtr startAddress = Marshal.AllocHGlobal(IntPtr.Size);
  2. NtQueryInformationThread(hThread, 9, startAddress, IntPtr.Size, IntPtr.Zero);

Cierras el handle con la función de API CloseHandle (kernel32.dll):

Código
  1. CloseHandle(hThread);

Obviamente habría que hacer manejo de errores y demás, pero para empezar podrías probar a ver si te sirve de esta manera.
66  Programación / Programación C/C++ / Re: C++ Challenge en: 8 Mayo 2022, 22:04 pm
Una solución rápida que se me ocurre es esto:

La función que recibe los comandos del usuario los pondría en algún tipo de cola, de forma sincronizada (usando una región crítica, por ejemplo). Cuando el usuario llama a la función Analizar(), ésta va tomando cada comando de la cola (obviamente, de forma sincronizada) y ejecutándolo. Dado que no quieres que un comando bloquee la ejecución de otro, esta función podría lanzar un hilo que ejecute cada uno de ellos. Para que esto no sea muy ineficiente, te recomendaría usar un "pool", que podrías crear tú, o usar el de Windows (la familia de funciones *Threadpool* de la API de Windows).

El comando CuentaRegresiva lo podrías manejar dentro de un bucle y haciendo llamadas a Sleep(1000) luego de cada mensaje "Faltan X cantidad de segundos", porque como se ejecuta en su propio hilo, no bloquearía el programa; o algo más elegante sería usar funciones de colas de temporizadores (Timer Queues) que la API de Windows proporciona. Éstos se ejecutan de forma periódica; en tu caso harías que esto ocurriera una vez por segundo. Podrías pasarle a la función callback de cada timer un puntero a una variable con el valor inicial recibido en el comando CuentaRegresiva (10 si fueran 10 segundos, etc.) y ésta, en cada ejecución lo decrementaría. Una vez que ese valor llega a 0, detienes (destruyes) el timer.

Dado lo anterior, Inicializar() podría inicializar las regiones críticas, y Apagar() esperaría a que los hilos terminen su ejecución (mediante la función WaitFor* correspondiente al tipo de hilo que decidas usar).

No me detengo en cada punto de los que pusiste porque me parece que algunos son muy simples.  Creo que lo único que podría tener cierta complicación es el tema de procesar comandos sin que uno bloquee los demás, y quizás la implementación de la cuenta regresiva; de ahí que me centrara en estos temas.
67  Programación / Programación C/C++ / Re: Escribir en archivos con file descriptors introduce caracteres extraños en: 23 Abril 2022, 17:22 pm
Es cierto que x86/x64 son little endian, pero eso no es lo que causa tu problema. Los editores de texto y el comando cat esperan un archivo de texto, pero en la línea

Código
  1.  if(write(fd, &userid, sizeof(int)) == -1 )

estás escribiendo un valor entero en el archivo. Obviamente si se intenta leer como ASCII o UTF-8, se van a mostrar símbolos raros. Necesitas convertir userid a texto, por ejemplo, mediante sprintf o snprintf, y luego guardar esa cadena resultante.

Tienes otro error importante. Los elementos de argv son punteros, no arrays. Así, esto:

Código
  1.  databuffer = (char *) ec_malloc(sizeof(argv[1]));

está mal, pues sizeof devolverá el tamaño de un puntero (4 u 8), por lo que si el mensaje no cabe en esa cantidad de bytes, estarás sobrescribiendo bytes indebidos. Lo que necesitas pasar a ec_malloc es: "strlen(argv[1]) + 1".
68  Programación / Programación General / Re: Borrar dll y que no se pueda recuperar en: 17 Abril 2022, 17:07 pm
Es que no digo que sobrescribir en nuevas posiciones sea lo normal sino que es posible. No conozco todas las circunstancias en que eso pueda ocurrir ni sé si está documentado. Sí sé que, por ejemplo, si el archivo se encuentra en un directorio donde la compresión de Windows esté activada, o si se usa la cifrado de disco, sí puede suceder (y creo que es lo normal) que los datos se escriban en otras posiciones, pero la mayoría de los usuarios no usan esas características. No sé en qué otros casos pueda ocurrir, pero como te decía en el segundo mensaje al mencionar WriteFile, no me parece motivo de preocupación, pues creo que en la mayoría (si no es que en todos) de los casos típicos, sí se sobrescribirán correctamente.

Con los SSD y memoria flash en general, es diferente. Normalmente usan técnicas para que las escrituras estén bien distribuidas a lo largo de la unidad. Aunque dudo que las memorias USB económicas que la mayoría usamos las implementen (y si lo hacen, que lo hagan bien), los SSD, o al menos la mayoría, seguro que sí lo hacen. Cada fabricante usará sus técnicas, algunas más o menos agresivas, pero un ejemplo: https://en.wikipedia.org/wiki/Wear_leveling

Citar
The first type of wear leveling is called dynamic wear leveling (...) Each time the OS writes replacement data, the map is updated so the original physical block is marked as invalid data, and a new block is linked to that map entry. Each time a block of data is re-written to the flash memory, it is written to a new location.

Como sea, yo no me preocuparía mucho, a menos que estuviera haciendo algo ilegal. Con sobrescribir los datos de las maneras ya mencionadas, creo que es muy poco probable que una persona normal los pueda recuperar.
69  Programación / Programación General / Re: Borrar dll y que no se pueda recuperar en: 17 Abril 2022, 03:48 am
Por si algún "listillo" recupera la dll, si la recupera, antes hay que modificar la dll, guardar la dll modificada que es inservible, solo hay datos corrupto por llamarlo de alguna manera, se guarda la dll y luego se borra.

Al recuperar dicha dll por el "listillo", recuperará si, la dll pero modificada. Ahí está el truco. La dll original no se puede recuperar porque ha sido modificada. Si fuera solo borrada sin modificar si puede hacerlo.



Sí, eso está claro desde el principio. A lo que me refiero es a que, dependiendo de cómo se haga, sobrescribir un archivo no necesariamente implica que se sobrescriban los sectores originales. Digamos que tienes un archivo C:\archivo.dll. Por más que lo sobrescribas, el SO, e incluso la controladora del disco/unidad (especialmente en SSD) son libres de escribir los datos nuevos en una ubicación completamente distinta, y simplemente hacer que C:\archivo.dll "apunte" a estos nuevos sectores, dejando intactos los anteriores, y por lo tanto, susceptibles de ser recuperados. Por eso la propia Microsoft en su documentación dice que la única manera más o menos confiable de hacer que un archivo sea (prácticamente) irrecuperable es usando herramientas especializadas.

En tu caso no estamos hablando de proteger información ante un análisis forense profesional ni nada por el estilo, así que, como te mencioné, probablemente con que sobrescribas la .dll mediante WriteFile u otra función similar sea suficiente. Pero es importante ser conscientes de que la posibilidad de recuperación existe, y de que, sin usar software especial, el hecho de que los datos sean o no realmente sobrescritos, es algo que no puedes controlar, al menos hasta donde sé.
70  Programación / Programación General / Re: Borrar dll y que no se pueda recuperar en: 16 Abril 2022, 19:14 pm
Todo eso que dices se puede hacer sin mayor problema, pero es difícil hacer que un archivo sea 100% irrecuperable por muchas razones. Si sólo necesitas evitar que un "listillo" los recupere, hay varias alternativas.

Si quieres sobrescribir el ejecutable desde un .bat, lo mejor sería invocando herramientas externas como SDelete. Esto lo podrías hacer como te dije en el mensaje anterior, reemplazando el "del" con "sdelete" o algún programa equivalente, y así podrías incluso prescindir de la .dll. Te sugiero una herramienta especializada porque borra de forma relativamente segura, haciendo difícil la recuperación, y porque los comandos estándar con los que podrías intentar sobrescribir el archivo (echo, copy, xcopy, etc.) en realidad crean uno nuevo y borran el anterior.

Si no quieres usar programas adicionales, puedes usar la opción de una .dll. Obviamente deberás usar carga explícita (LoadLibrary, etc.) para poder cerrarla. Luego la puedes sobrescribir, por ejemplo, con WriteFile. Aunque seguramente no hay garantías de que los bytes originales se sobrescriban, creo que (normalmente) sí sucede así. Eso sí, en este caso, al final no podrías sobrescribir el .exe sino sólo borrarlo.
Páginas: 1 2 3 4 5 6 [7] 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 ... 25
WAP2 - Aviso Legal - Powered by SMF 1.1.21 | SMF © 2006-2008, Simple Machines