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

 

 


Tema destacado: Tutorial básico de Quickjs


  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 ... 24
51  Programación / Programación C/C++ / Re: Programa de Calculadora con sockets en: 1 Septiembre 2022, 02:03 am
Como te están especificando que deben ser enteros de 2 bytes, entonces supongo que te piden que envíes los datos, no como una cadena ASCII (pues en ese caso cada entero podría ocupar hasta 6 bytes, incluyendo el signo positivo/negativo) sino como valores binarios, por lo que no deberías leerlos como cadenas, sino como enteros. Así que, para empezar, A y B deberían ser de tipo int16_t, como ya te dijeron. Y no tiene ningún sentido que sign sea un array de 1024 caracteres; debería ser un simple char.

La forma más simple es enviar (y recibir) una variable a la vez. Esto no es muy eficiente ni correcto, pero te puede sacar del apuro.

En el cliente, una vez que el usuario introdujo los números y el signo, haz algo así:

Código
  1. // Conviertes de orden de bytes local a red
  2. A = htons(A);
  3. B = htons(B);
  4.  
  5. send(sock , &A , sizeof(A) , 0 );
  6. send(sock , &B , sizeof(B) , 0 );
  7. send(sock, &sign , sizeof(sign) , 0);
  8.  
  9. int32_t total;
  10. read( sock , &total, sizeof(total));
  11.  
  12. // Conviertes de orden de bytes de red a local
  13. total = ntohl(total);
  14. std::cout <<  "El total es: " << total << "\n";

En el servidor:

Código
  1. // Pesimos nombres de variables, pero por consistencia con tu codigo, los dejo asi
  2. int16_t A, B;
  3. char sign;
  4. int32_t total;
  5. read( new_socket , &A, sizeof(A) );
  6. A = ntohs(A);
  7. // ...y lo mismo para B y sign...

 Y con un switch/case verificas sign. Por ejemplo:

Código
  1. ...
  2. case '+':
  3. total = A + B;
  4. break;
  5. case '-':
  6. total = A - B;
  7. break;
  8. // etc.

Y finalmente:

Código
  1. total = htonl(total);
  2. send(new_socket , &total, sizeof(total) , 0 );

Esto, como te dije, no es ni mucho menos ideal. Dado que estás enviando cantidades diminutas de bytes, puedes dar por hecho que va a funcionar sin problemas, pero en general, sería más eficiente juntar las variables en un bloque de bytes (ojo, no cadena de texto sino bytes) y enviar/recibir eso. Y lo correcto sería verificar que los datos se envíen/reciban completos. Las funciones read y send no necesariamente envian/reciben el número de bytes que les indiques, por lo que podría ser necesario leer o enviar los restantes con llamadas sucesivas. El problema es que, viendo que buena parte de tu código simplemente la copiaste de algún lugar, y que tienes cosas inexplicables, como lo de la variable sign que te comenté al inicio, creo que la forma más correcta se te podría complicar. De cualquier manera, te doy algunas sugerencias por si lo quisieras intentar.

Dado que vas a enviar 5 bytes fijos, podrías hacer algo así en el cliente:

Código
  1. // Como NO es una cadena, no necesita caracter nulo al final
  2. char buffer[5];
  3. /* Igual podriamos redondear a 8 chars, pues las potencias de 2 siempre son mucho mas agradables :) */

Y copiar ahí los valores de A, B (luego de haberlos convertido con htons) y sign. Para esto podrías usar memcpy, u operaciones a nivel de bits, como &, >> (si ya estás en programación de sockets, supongo que ya conocerás el funcionamiento de memcpy al menos).

Luego envias ese buffer.

Las funciones send y read devuelven el número de bytes leídos/enviados, así que puedes tener una variable que lleve la cuenta de los bytes que faltan de enviar/leer. Aquí va un pseudocódigo con una forma típica de enviar buffers completos:

Código
  1. int restantes = TOTAL_A_ENVIAR;
  2. while (restantes > 0) {
  3. int enviados = send(bytes_restantes_del_buffer);
  4. /* verificar el valor de enviados: si es igual a 0 o -1, algo salio mal. Lidiar con el error */
  5. // En caso contrario
  6. restantes -= enviados;
  7. }

Lo mismo al recibir datos con read. Una vez leído el buffer, se copian sus 2 primeros bytes a A, y los dos siguientes a B (de nuevo, se puede hacer con memcpy), y  luego las conviertes a representación local con ntohs. En el caso de sign, dado que es un char, directamente le podrías asignar el valor de buffer[4].
52  Programación / Programación C/C++ / Re: Puteros dobles y cadena de caracterez reservar memoria dinamica en: 19 Agosto 2022, 16:55 pm
Primero, usar fflush con flujos de entrada, como stdin, nunca ha sido válido. Varios compiladores lo admiten pero no es correcto y, si lo compilaras, por ejemplo, con Visual C++, no limpiaría el buffer ni haría nada. Puedes sustituir esa línea por algo como esto:

Código
  1. while (getchar() != '\n');

En cuanto al error, es porque estás pasando por valor el puntero a puntero ("puntero doble") a "cargar", por lo que esta función lo que modifica es una copia de array; al volver a main, la variable array original sigue sin inicializarse. En realidad la función cargar debería recibir un puntero a puntero a puntero:

Código
  1. void cargar(char***, int);

y debes pasarle la dirección de array (&array):

Código
  1. cargar(&array, N);

y dentro de la función, en donde accedas a array, cambiarlo por *array:

Código
  1. *array = (char**)malloc(lon * sizeof(char*));
  2. ...
  3. (*array)[i] = (char*)malloc(tam * sizeof(char));

y así con las demás líneas.
53  Programación / Programación General / Re: Duda sobre sincronizar VSCode con Máquina Virtual Ubuntu en: 8 Agosto 2022, 16:37 pm
Bueno, entonces eso no sería sincronizar, sino simplemente compartir archivos, y sí se puede. Si usas VirtualBox, asegúrate de tener instaladas las "Guest Additions", y luego, abre la configuración de la máquina virtual Ubuntu, y en "Carpetas compartidas", selecciona las carpetas a las que quieras que Ubuntu tenga acceso. Ahí mismo puedes configurar la ruta donde las quieras montar, y si quieres que tengan permisos de escritura y se monten automáticamente.
54  Media / Juegos y Consolas / Re: Para qué sirve este stick del mando joystick genius? en: 3 Agosto 2022, 18:42 pm
Dado que pone D y X, debe ser para elegir si quieres que funcione en modo DirectInput o XInput. Salvo cuando vayas a jugar juegos viejos, normalmente deberías dejarlo en X.
55  Programación / Programación General / Re: ¿Como paso de programar cosas para ejecutarlas en consola a hacer algo de utilidad? (programas, juegos, etc) en: 28 Junio 2022, 18:12 pm
Es una pregunta demasiado general, pero si te refieres a programas con interfaz gráfica, lo que debes aprender es a usar una biblioteca o framework para eso. Algunas opciones populares para C++ (y las únicas dignas de mención, en mi opinión) son: Qt, wxWidgets y Dear ImGui, o si no necesitas multiplataforma, directamente la API de Windows.

Pero lo principal es hacer proyectos. Si te pones a estudiar alguna biblioteca en abstracto o "sólo porque sí", vas a acabar igual que ahora: haciendo programitas poco útiles, sólo que más vistosos. Y al final ni siquiera vas a saber usarla bien. Para aprender como se debe, es mucho mejor plantearte hacer algún tipo de programa en específico, y estudiar lo que necesitas para lograrlo. Si tienes alguna idea en mente, coméntala aquí, y ya será más fácil darte sugerencias con una pregunta más concreta.
56  Programación / .NET (C#, VB.NET, ASP) / Re: Obtener Informacion acerca del modulo correspondiente al StartAdress del Thread. en: 17 Junio 2022, 23:28 pm
Descargué el código y parece funcionar correctamente, pero como imaginaba, sólo en una misma arquitectura. Si lo compilas para x86 (o ANY + "Prefer 32-bit") sólo admite id de procesos de 32 bits, y lo mismo para 64.

Eso sí, la excepción de la que hablabas no tiene razón de ser, ya que es normal que SymFromAddr falle a veces. Eso sólo significa que no encontró el símbolo (nombre de función) porque el ejecutable del proceso fue compilado sin información de depuración (no hay archivo .pdb, etc.). Es justamente lo que pasa en la imagen que pusiste en tu mensaje original, donde pone: CodeSmart.exe+0xb426ee. Como no encontró el símbolo (SymFromAddr falló), simplemente pone el offset.

Si quisieras hacer algo similar, ese offset lo calcularías:

Código
  1. threadAddress[0] - module.BaseAddress

donde module es el módulo (.dll o .exe) que contiene la función, y lo obtienes mediante la función de la API SymGetModuleInfo64. Así, simplemente harías que aquí:

Código
  1.      if (!DbgHelpNative.SymFromAddr(hProc, (ulong)threadAddress[0], out displacement, ref symbolInfo))

se devuelva una cadena con el offset. O simplente devuelves "No se encontro simbolo" o lo que quieras.


Edito:

Me entró curiosidad por ver por qué si se compila para x64 no puede aceptar procesos de 32 bits, ya que desde la API en C++ es sencillo hacerlo (pasando los flags adecuados a CreateToolhelp32Snapshot). Resulta que cuando el programa se ejecuta en 64 bits, no carga módulos de 32 bits, y no sé si haya forma de especificar en .NET que lo haga. Probé hacerlo manualmente mediante la API de Windows (como lo hago en C++) y funciona.

Por si te interesa (o alguien más que le llame la atención el tema), lo harías así:

Primero, eliminar esta línea de la función GetThreadStartAddress():

Código
  1.                if (!DbgHelpNative.SymInitialize(hProc, null, true))
  2.                {
  3.                    throw new Win32Exception("SymInitialize failed");
  4.                }

Pues SymInitialize() sólo se debe llamar una vez por proceso, y aquí se está llamando por cada hilo. Y en este caso, lo correcto es llamar a SymCleanup() al final.

Luego, definir esta estructura y dllimports:

Código
  1.       [StructLayout(LayoutKind.Sequential)]
  2.        public struct MODULEENTRY32
  3.        {
  4.            public uint dwSize;
  5.            uint th32ModuleID;
  6.            uint th32ProcessID;
  7.            uint GlblcntUsage;
  8.            uint ProccntUsage;
  9.            public IntPtr modBaseAddr;
  10.            public uint modBaseSize;
  11.            IntPtr hModule;
  12.            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
  13.            public string szModule;
  14.            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)]
  15.            public string szExePath;
  16.        }
  17.  
  18.        [DllImport("kernel32.dll", CharSet = CharSet.Ansi, SetLastError = true)]
  19.        public static extern IntPtr CreateToolhelp32Snapshot(uint flags, uint processid);
  20.        [DllImport("kernel32.dll", CharSet = CharSet.Ansi, SetLastError = true)]
  21.        public static extern bool Module32First(IntPtr hSnapshot, ref MODULEENTRY32 lpme);
  22.        [DllImport("kernel32.dll", CharSet = CharSet.Ansi, SetLastError = true)]
  23.        public static extern bool Module32Next(IntPtr hSnapshot, ref MODULEENTRY32 lpme);

Finalmente, el código, que puse dentro de get_process_thread_Click() sólo por simplicidad:

Código
  1.        private void get_process_thread_Click(object sender, EventArgs e)
  2.        {
  3.            Process proc = Process.GetProcessById(int.Parse(proc_txt.Text));
  4.  
  5.  
  6.            // Los flags: TH32CS_SNAPMODULE | TH32CS_SNAPMODULE32
  7.            IntPtr hSnap = DbgHelpNative.CreateToolhelp32Snapshot(0x00000008 | 0x00000010, (uint)proc.Id);
  8.  
  9.            // INVALID_HANDLE_VALUE
  10.            if ((long)hSnap == -1)
  11.            {
  12.                // Error
  13.            }
  14.  
  15.            if (!DbgHelpNative.SymInitialize(proc.Handle, null, true))
  16.            {
  17.                throw new Win32Exception("SymInitialize failed");
  18.            }
  19.  
  20.            DbgHelpNative.MODULEENTRY32 me = new DbgHelpNative.MODULEENTRY32();
  21.  
  22.            me.dwSize = (uint)Marshal.SizeOf(me);
  23.  
  24.            if (DbgHelpNative.Module32First(hSnap, ref me))
  25.            {
  26.                do
  27.                {
  28.                    if (0 == DbgHelpNative.SymLoadModule64(proc.Handle, IntPtr.Zero, me.szExePath, me.szModule, (ulong)me.modBaseAddr, (uint)me.modBaseSize))
  29.                    {
  30.                        /* Esta segunda verificacion es necesaria, ya que cuando SymLoadModule64
  31.                          * devuelve 0, si TAMBIEN GetLastError es 0, simplemente significa
  32.                          * que el modulo ya habia sido cargado*/
  33.  
  34.                        // En caso contrario, hay error
  35.                        if (Marshal.GetLastWin32Error() != 0)
  36.                        {
  37.                            // Error: no se cargo el modulo
  38.                        }
  39.  
  40.                    }
  41.                } while (DbgHelpNative.Module32Next(hSnap, ref me));
  42.            }
  43.  
  44.  
  45.            ProcessThreadCollection procThread = proc.Threads;
  46.            threadinfo_list.Items.Clear();
  47.            int idx = 0;
  48.            foreach (ProcessThread i in procThread)
  49.            {
  50.                threadinfo_list.Items.Add(i.Id.ToString());
  51.                threadinfo_list.Items[idx].SubItems.Add(DbgHelp.GetThreadStartAddress(proc.Handle, (uint)i.Id));
  52.                threadinfo_list.Items[idx].SubItems.Add(i.PriorityLevel.ToString());
  53.                idx++;
  54.            }
  55.  
  56.            DbgHelpNative.SymCleanup(proc.Handle);
  57.            DbgHelpNative.CloseHandle(hSnap);
  58.        }

Con esto, al compilar para x64 (o ANY con "Prefer 32-bit" deshabilitado) ya aceptaría procesos de ambas arquitecturas.
57  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.
58  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.
59  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.
60  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.
Páginas: 1 2 3 4 5 [6] 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 ... 24
WAP2 - Aviso Legal - Powered by SMF 1.1.21 | SMF © 2006-2008, Simple Machines