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

 

 


Tema destacado: Usando Git para manipular el directorio de trabajo, el índice y commits (segunda parte)


+  Foro de elhacker.net
|-+  Programación
| |-+  Programación General
| | |-+  .NET (C#, VB.NET, ASP) (Moderador: kub0x)
| | | |-+  Buscar partes del archivo hex escrito en C#
0 Usuarios y 1 Visitante están viendo este tema.
Páginas: [1] Ir Abajo Respuesta Imprimir
Autor Tema: Buscar partes del archivo hex escrito en C#  (Leído 12,667 veces)
Meta


Desconectado Desconectado

Mensajes: 3.501



Ver Perfil WWW
Buscar partes del archivo hex escrito en C#
« en: 2 Septiembre 2023, 17:01 pm »

Hola:

Estaba pensando en hacer un programa con Windows Form, que lea archivos hex. Se puede abrir con este programa mismo llamado HxD.

Por ejemplo, puedes ver en un archivo de una imagen esto pero solo pongo un trozo que es largo.


Quiero hacer un programa en C#, al menos tener una idea de que al abrir y leer el archivo hex, busque en una dirección en concreta. Por ejemplo, la indicada abajo. En la dirección 7006, en el cual en hex tiene el valor 56 y en ASCII al lado es una letra mayúscula V.


Si pulsas un botón en el formulario, en un textBox muestra dicho valor 56 y el otro textBox la letra V.

Hasta ahí bien.

Hay que hacer una especie de diccionario llenos de if, en el que si detecta el 56, en un tercer textBox muestre un mensaje, Español. Si detecta el 57, que muestre Italia, si es el 58 que muestre Portugal. Si en esos if hay otro valor que no esté incluido, que muestre en el tercer textBox, DESCONOCIDO.

Hablando parece fácil.

¿Es muy complicado de hacer?

Tampoco quiero pegarme media vida averiguar como se hace.

Recuerdo que estamos hablando de un solo Byte, no de varios. Que si se puede, también me vale.

Saludos.


En línea

Elektro Enjuto

Desconectado Desconectado

Mensajes: 121



Ver Perfil WWW
Re: Buscar partes del archivo hex escrito en C#
« Respuesta #1 en: 3 Septiembre 2023, 03:07 am »

¿Es muy complicado de hacer?

Tampoco quiero pegarme media vida averiguar como se hace.

Windows Forms:

Windows Presentation Framework:

Como podrás comprobar, el control de usuario del editor hexadecimal de WPF es mucho más completo y sofisticado que el control de usuario disponible para WinForms. Quizás lo quieras considerar como opción.

El control de usuario "Be.HexEditor" para WinForms también parece tener una funcionalidad implementada para buscar un patrón de texto o bytes:


PD: yo nunca la he llegado a usar, pero no debe ser difícil.



Supongo que con toda esta información será suficiente para resolver tus dudas, pero de todas formas aquí te dejo un algoritmo que he desarrollado en VB.NET para buscar un patrón de bytes en un objeto de tipo Stream (y derivados como FileStream, MemoryStream, etc):

Código
  1. <HideModuleName>
  2. Public Module StreamExtensions
  3.  
  4. ''' ----------------------------------------------------------------------------------------------------
  5. ''' <summary>
  6. ''' Searches for the specified byte pattern within the source <see cref="Global.System.IO.Stream"/>,
  7. ''' and returns the zero-based index of the first occurrence.
  8. ''' </summary>
  9. ''' ----------------------------------------------------------------------------------------------------
  10. ''' <param name="stream">
  11. ''' The source <see cref="Global.System.IO.Stream"/>.
  12. ''' </param>
  13. '''
  14. ''' <param name="startPosition">
  15. ''' The zero-based starting position in the source <see cref="Global.System.IO.Stream"/> to perform the search.
  16. ''' </param>
  17. '''
  18. ''' <param name="count">
  19. ''' The number of bytes in the source <see cref="Global.System.IO.Stream"/> to search.
  20. ''' </param>
  21. ''' ----------------------------------------------------------------------------------------------------
  22. ''' <returns>
  23. ''' The zero-based index of the first occurrence of the specified byte pattern
  24. ''' within the source <see cref="Global.System.IO.Stream"/>,
  25. ''' if found; otherwise, –1.
  26. ''' </returns>
  27. ''' ----------------------------------------------------------------------------------------------------
  28. <Extension>
  29. <EditorBrowsable(EditorBrowsableState.Always)>
  30. <DebuggerStepThrough>
  31. Public Function IndexOf(stream As Global.System.IO.Stream, pattern As Byte(), startPosition As Long, count As Long) As Long
  32.  
  33.  Dim streamLength As Long = stream.Length
  34.  Dim endPosition As Long = startPosition + count
  35.  
  36.  If startPosition > streamLength Then
  37.    Throw New InvalidOperationException("Start Position is greater than the source stream length.",
  38.                      New ArgumentException("", paramName:=NameOf(startPosition)))
  39.  End If
  40.  
  41.  If endPosition > streamLength Then
  42.    Throw New InvalidOperationException("End Position is greater than the source stream length.",
  43.                      New ArgumentException("", paramName:=NameOf(count)))
  44.  End If
  45.  
  46.  If count <= 0 Then
  47.    Throw New ArgumentException("A value greater than zero is required.", paramName:=NameOf(count))
  48.  End If
  49.  
  50.  Dim initialStreamPosition As Long = stream.Position
  51.  stream.Seek(startPosition, SeekOrigin.Begin)
  52.  
  53.  Dim foundPosition As Long
  54.  Dim index As Integer
  55.  Dim readByte As Integer
  56.  
  57.  While (stream.Position <= endPosition)
  58.    readByte = stream.ReadByte()
  59.    If readByte = -1 Then
  60.      Exit While
  61.    End If
  62.  
  63.    If pattern(index) <> readByte Then
  64.      stream.Position -= index
  65.      index = 0
  66.      Continue While
  67.    End If
  68.  
  69.    If index = (pattern.Length - 1) Then
  70.      foundPosition = stream.Position - index
  71.      Exit While
  72.    End If
  73.    index += 1
  74.  End While
  75.  
  76.  stream.Seek(initialStreamPosition, SeekOrigin.Begin)
  77.  Return foundPosition - 1
  78.  
  79. End Function
  80.  
  81. <Extension>
  82. <EditorBrowsable(EditorBrowsableState.Always)>
  83. <DebuggerStepThrough>
  84. Public Function IndexOf(stream As Global.System.IO.Stream, pattern As Byte(), startPosition As Long) As Long
  85.  
  86.  Return StreamExtensions.IndexOf(stream, pattern, startPosition, stream.Length - startPosition)
  87.  
  88. End Function
  89.  
  90. End Module

Puedes convertirlo a C#.

Mi algoritmo está basado en este otro escrito en C#: https://stackoverflow.com/a/76443727/1248295 - simplemente le he aportado más versatilidad de uso para poder limitar la búsqueda a una posición inicial y final, y le añadí control de errores.

Nota: tanto ese algoritmo y el mio como el algoritmo de la respuesta de 'bruno conde' (https://stackoverflow.com/questions/1471975/best-way-to-find-position-in-the-stream-where-given-byte-sequence-starts/1472689#1472689) no son ni por asomo tan rápidos para buscar un patrón de bytes en archivos de gran tamaño (ej. archivos de películas de varios GB) como lo es el algoritmo de búsqueda que utiliza el programa HxD.

EDITO: El código anterior pero bastante mejor optimizado, con tiempos de búsqueda mucho más cortos sobre todo para buscar un patrón de bytes en un archivo de varios GB:

Código
  1. <DebuggerStepThrough>
  2. <Extension>
  3. <EditorBrowsable(EditorBrowsableState.Always)>
  4. Public Function IndexOf(stream As Global.System.IO.Stream, pattern As Byte(), startPosition As Long, count As Long) As Long
  5.  
  6.    Dim streamLen As Long = stream.Length
  7.    Dim pattLen As Integer = pattern.Length
  8.    Dim endPos As Long = startPosition + count
  9.  
  10.    If startPosition > streamLen Then
  11.        Throw New InvalidOperationException("Start Position is greater than the source stream length.",
  12.                                            New ArgumentException("", paramName:=NameOf(startPosition)))
  13.    End If
  14.  
  15.    If endPos > streamLen Then
  16.        Throw New InvalidOperationException("End Position is greater than the source stream length.",
  17.                                            New ArgumentException("", paramName:=NameOf(count)))
  18.    End If
  19.  
  20.    If pattLen > (streamLen - startPosition) Then
  21.        Throw New InvalidOperationException("Pattern Length is greater than the current search capacity length.",
  22.                                            New ArgumentException("", paramName:=NameOf(count)))
  23.    End If
  24.  
  25.    If count <= 0 Then
  26.        Throw New ArgumentException("A value greater than zero is required.", paramName:=NameOf(count))
  27.    End If
  28.  
  29.    Dim matchPos As Long = -1
  30.    Dim pattPos As Integer = 0
  31.  
  32.    Dim buffSize As Integer = CInt(Math.Min(4096, stream.Length))
  33.    Dim buff(buffSize - 1) As Byte
  34.  
  35.    Dim buffStream As New BufferedStream(stream, buffSize)
  36.    buffStream.Seek(startPosition, SeekOrigin.Begin)
  37.  
  38.    Dim streamPos As Long = startPosition
  39.    Dim readArray As Integer = -1
  40.  
  41.    While (readArray <> 0) AndAlso (streamPos <= endPos)
  42.        readArray = buffStream.Read(buff, 0, buffSize)
  43.  
  44.        For buffPos As Integer = 0 To buff.Length - 1
  45.            streamPos += 1
  46.  
  47.            If buff(buffPos) <> pattern(pattPos) Then
  48.                pattPos = 0
  49.            Else
  50.                If pattPos = (pattLen - 1) Then
  51.                    matchPos = (streamPos - pattPos - 1)
  52.                    Exit While
  53.                End If
  54.                pattPos += 1
  55.            End If
  56.  
  57.            If streamPos > endPos Then
  58.                Exit While
  59.            End If
  60.        Next
  61.    End While
  62.  
  63.    Return matchPos
  64.  
  65. End Function



Por cierto, en .NET Core directamente podrías utilizar la función MemoryExtensions.IndexOf:


Saludos.


« Última modificación: 4 Septiembre 2023, 05:02 am por Elektro Enjuto » En línea

@%$& #$ %&#$, ¡hay que decirlo más!.
Meta


Desconectado Desconectado

Mensajes: 3.501



Ver Perfil WWW
Re: Buscar partes del archivo hex escrito en C#
« Respuesta #2 en: 6 Septiembre 2023, 07:13 am »

Ni más información, voy a analizarlo.

Muchas gracias honorable amigo.  ;-) ;-) ;-)
En línea

Elektro Enjuto

Desconectado Desconectado

Mensajes: 121



Ver Perfil WWW
Re: Buscar partes del archivo hex escrito en C#
« Respuesta #3 en: 6 Septiembre 2023, 23:34 pm »

No me aparece el botón para modificar mi post, creo que en el foro ahora hay un límite de tiempo o algo. En fin, era para corregir un pequeño despiste en el último código, por que la clase BufferedStream implementa la interface IDisposable, así que conviene llamar al método BufferedStream.Dispose para liberar los recursos.

También cabría mencionar que cuando se trata de procesar secuencialmente un FileStream para buscar un patrón de bytes, envolverlo en un objeto BufferedStream como hago en ese código aporta una mejoría de velocidad tremenda, pero por otro lado, cuando se trata de un MemoryStream es totalmente innecesario envolverlo en un objeto BufferedStream y hacerlo influye negativamente ralentizando la búsqueda del patrón de bytes, aunque la diferencia es muy diminuta (aproximadamente 2-3 segundos en mis pruebas) al buscar patrones de bytes que están posicionados casi al final en archivos de unos 2 GB, así que la diferencia es prácticamente imperceptible con búfers de mucho menos tamaño, pero bueno, ahí queda el dato por si se quieren llevar a cabo microoptimizaciones.

Saludos
« Última modificación: 6 Septiembre 2023, 23:43 pm por Elektro Enjuto » En línea

@%$& #$ %&#$, ¡hay que decirlo más!.
Serapis
Colaborador
***
Desconectado Desconectado

Mensajes: 3.391


Ver Perfil
Re: Buscar partes del archivo hex escrito en C#
« Respuesta #4 en: 28 Septiembre 2023, 13:48 pm »

Si solo buscas un byte, la búsqueda puede ser secuencial (dentro de un for) y si buscas varios valores de bytes seguidos, tampoco es más complicado.


Código:
Idioma
Por cada byte en el array X
    Si bytes <=56) y (byte <=58)
        seleccionar caso byte
            caso 56: Idioma = "Español"
            caso 57: Idioma =
            caso 58: Idioma = "Italiano"
        fin casos
        salir de la funcion
    fin si
siguiente
Idioma = "Desconocido"

Si conoces un índice específico en el array donde se localiza, entonces el bucle for es innecesario.
Si por el contrario debe buscarse en múltiples partes, otra función debe llamar a 'ésta', y entre sí deben retener el índice donde se localiza (por referencia), el bucle ya no vale un 'for each', ya deberá ser uno desde el índice hasta el final.
Y siempre que se devuelva otro valor distinto de 'desconocido' implica que no se terminó de buscar en el array, luego la siguiente llamada continuará un índice más alto que donde se encontró. Cuando se devuelva 'desconocido', podrá leerse el siguiente tramo (caso de un fichero muy grande y no querer saturar la memoria con una lectura completa del fichero).

Si el número de bytes a localizar es mayor de 1 y este valor pueda ser variable, entonces la eficiencia la encontrarás usando el algoritmo de Knuth, Morris y Pratt (KMP), o el de Boyer y Moore (BM)... (el de Karp Rabin puede ser más farragoso para cosas simples). Típicamente se utilizan para cadenas de texto, pero una cadena de texto no dejan de ser bytes consecutivos en el fichero.
Eso sí, operando con números si ocupan más de 2 bytes ten en cuenta su 'endianidad'... pues altera el orden de ellos (caso que no ocupa cuando se trata de un texto).

Hace años edité el artículo, era un galimatías probablemente producto de una traducción (de entonces) defectuosa del inglés, sin explicaciones ni detalles específicos:
https://es.wikipedia.org/wiki/Algoritmo_Knuth-Morris-Pratt

« Última modificación: 28 Septiembre 2023, 13:52 pm por Serapis » En línea

Meta


Desconectado Desconectado

Mensajes: 3.501



Ver Perfil WWW
Re: Buscar partes del archivo hex escrito en C#
« Respuesta #5 en: 26 Octubre 2023, 17:56 pm »

Muchas gracias camaradas, me toca practicar ya que estoy de vacaciones.
En línea

Páginas: [1] Ir Arriba Respuesta Imprimir 

Ir a:  

Mensajes similares
Asunto Iniciado por Respuestas Vistas Último mensaje
Leer partes de un archivo.
Programación Visual Basic
Scratz 6 2,912 Último mensaje 26 Noviembre 2006, 19:40 pm
por Scratz
Borrar datos de un archivo escrito en php
PHP
Cerdo 0 1,978 Último mensaje 28 Julio 2008, 05:48 am
por Cerdo
Como descargo un archivo de internet ( EN PARTES ). Alguien sabe? « 1 2 »
.NET (C#, VB.NET, ASP)
70N1 17 10,162 Último mensaje 29 Marzo 2010, 11:47 am
por 70N1
(Solucionado) Crear un archivo desde el menú contextual con contenido escrito?
Windows
Eleкtro 7 6,722 Último mensaje 24 Diciembre 2012, 16:53 pm
por Eleкtro
Convertir manualmente partes de un archivo html a csv
Desarrollo Web
Esgrimidor 2 2,430 Último mensaje 13 Septiembre 2017, 16:57 pm
por Esgrimidor
WAP2 - Aviso Legal - Powered by SMF 1.1.21 | SMF © 2006-2008, Simple Machines