¿Cómo buscar una secuencia de bytes en modo hexl?

7

¿Es posible buscar una secuencia de bytes hexl-modey posiblemente resaltarla?

Por ejemplo, en el archivo a continuación quiero buscar la secuencia de bytes f9beb4d9. isearchno funciona porque busca la presentación en el búfer y no el archivo original.

00000000: f9be b4d9 1d01 0000 0100 0000 0000 0000  ................
00000010: 0000 0000 0000 0000 0000 0000 0000 0000  ................
00000020: 0000 0000 0000 0000 0000 0000 3ba3 edfd  ............;...
00000030: 7a7b 12b2 7ac7 2c3e 6776 8f61 7fc8 1bc3  z{..z.,>gv.a....
00000040: 888a 5132 3a9f b8aa 4b1e 5e4a 29ab 5f49  ..Q2:...K.^J)._I
00000050: ffff 001d 1dac 2b7c 0101 0000 0001 0000  ......+|........
00000060: 0000 0000 0000 0000 0000 0000 0000 0000  ................
gdkrmr
fuente
Aclare lo que quiere decir con "buscar una secuencia de bytes" con un ejemplo.
Stefan
@Stefan creo "busco una secuencia de bytes" tiene que ser sustituido por "búsqueda de una secuencia de bytes". El OP debe corregir eso. Si la versión corregida es correcta, está bastante claro qué significa "buscar una secuencia de bytes" en un búfer hexl. Hay que tener en cuenta que el búfer hexl en realidad representa la secuencia de bytes del búfer original. El usuario no necesita saber cómo funciona hexl y que hay una pequeña diferencia entre la secuencia de bytes en el búfer hexl y la secuencia de bytes en el original.
Tobias
1
La pregunta principal es cómo piensa especificar la secuencia que está buscando.
Stefan
Espero que la pregunta esté clara ahora.
gdkrmr
@Stefan, puntos de bonificación si puedes buscar tanto la cadena como la representación hexadecimal :-) Solo estoy interesado en la representación hexadecimal de los bytes.
gdkrmr

Respuestas:

2

Si usa nhexl-mode(disponible en su archivo vecino GNU ELPA), puede hacerlo C-s f9beb4d9y buscará la secuencia de 4 bytes con códigos f9 be b4 d9(así como el texto f9beb4d9de 8 bytes, por supuesto, y también los bytes en las direcciones que se incluyen f9beb4d9en su representación hexadecimal).

Stefan
fuente
gracias por esto, funciona, pero el rendimiento en archivos grandes es terrible.
gdkrmr
1
@gdkrmr: Parte de mi motivación para el desarrollo de nhexl-mode fue sortear los problemas de rendimiento en el modo hexl en archivos grandes. Pero, para ser sincero, no estoy completamente sorprendido de que estés experimentando problemas de rendimiento. Informe sobre ellos M-x report-emacs-bugdando tantos detalles como sea posible (una URL a un archivo grande de muestra también podría ser útil, ya que el rendimiento puede verse afectado significativamente por el contenido del archivo).
Stefan
1
Hola Stefan, solo estoy buscando el binario y traduzco las direcciones en posiciones del búfer hexl. Parece que eso no tiene los problemas de rendimiento. Tal vez esa es una alternativa para hexl o nhexl? Ya solucioné un problema en el repositorio de git: github.com/TobiasZawada/hexl-isearch .
Tobias
2

El siguiente código lisp coloca una entrada "Modo de búsqueda Hexl" en el menú "Hexl".

Ese elemento del menú (des) activa el modo menor hexl-isearch-mode. Si activa ese modo, isearchbusca en los datos binarios en lugar del búfer hexl.

La cadena de búsqueda se lee con read. Entonces, todas las secuencias de escape para cadenas de lisp funcionan. Como ejemplo, puede buscar \x0a\x0do \^M\nbuscar extremos de línea dos.

El código no es perfecto.

  1. Supongamos que busca una cadena ELF\x01que solo ocurre al comienzo de un archivo. Además, suponga que hay una cadena ELf\x00más adelante en el binario. Luego, cuando llegues a ELF\x0escribir, Emacs encontrará la coincidencia posterior y si continúas escribiendo, ELF\x01Emacs piensa que no hay ocurrencias de esa cadena porque ya llegó a la ELF\x0que aparece más tarde en el archivo ELF\x01. Vale la pena hacer una búsqueda superpuesta en tal caso. (Ese problema ya está solucionado en la versión git del paquete ).

  2. Solo la secuencia de bytes se resalta correctamente en el búfer hexl, no la representación de cadena en el lado derecho.

  3. Si la cadena de búsqueda abarca dos líneas en el búfer hexl, la representación de la cadena al final de la línea y la dirección al comienzo de la línea también se resaltan. Eso no se debe a que pertenecen a la coincidencia, sino a que están en el camino al resaltar la secuencia de bytes.

(require 'hexl)

(defvar-local hexl-isearch-raw-buffer nil
  "Buffer with the dehexlified content of the hexl buffer for hexl-isearch-mode.
This variable is set in the original hexl-mode buffer.")

(defvar-local hexl-isearch-original-buffer nil
  "This variable is set in the buffer with the dehexlified content.
It points to the corresponding hexl buffer.")

(defun hexl-address (position)
  "Return address of hexl buffer POSITION."
  (save-excursion
    (goto-char position)
    (hexl-current-address)))

(defun hexl-isearch-startup ()
  "Prepare hexl buffer for `hexl-isearch'."
  (let ((original-buf (current-buffer)))
    (setq-local hexl-isearch-raw-buffer (generate-new-buffer " hexl"))
    (setq-local isearch-search-fun-function (lambda () #'hexl-isearch-fun))
    (with-current-buffer hexl-isearch-raw-buffer
      (set-buffer-multibyte nil)
      (setq-local hexl-isearch-original-buffer original-buf)
      (insert-buffer-substring original-buf 1 (buffer-size original-buf))
      (dehexlify-buffer))))

(defun hexl-isearch-end ()
  "Cleanup after `hexl-isearch'."
  (let ((isearch-raw-buffer hexl-isearch-raw-buffer))
    (setq-local hexl-isearch-raw-buffer nil)
    (when (buffer-live-p isearch-raw-buffer)
      (kill-buffer isearch-raw-buffer))))

(defun hexl-isearch-fun (string &optional bound noerror count)
  "Search for byte sequence of STRING in hexl buffer.
The arguments BOUND and NOERROR work like in `search-forward'."
  (when bound (setq bound (1+ (hexl-address bound))))
  (setq string (read (concat "\"" string "\"")))
  (let ((point (1+ (hexl-current-address)))
    match-data)
    (with-current-buffer hexl-isearch-raw-buffer
      (goto-char point)
      (setq point (funcall (if isearch-forward #'re-search-forward #'re-search-backward)
               (if isearch-regexp
                   string
                 (regexp-quote string))
               bound noerror count))
      (setq match-data (match-data t nil t)))
    (when point
      (prog1
      (hexl-goto-address (1- point))
    (set-match-data
     (mapcar (lambda (el)
           (if (integerp el)
               (hexl-address-to-marker (1- el))
             el))
         match-data))))))

(define-minor-mode hexl-isearch-mode
  "Search for binary string with isearch in hexl buffer."
  :lighter " hi"
  (if hexl-isearch-mode
      (progn
    (setq-local isearch-search-fun-function #'hexl-isearch-fun)
    (add-hook 'isearch-mode-hook #'hexl-isearch-startup t t)
    (add-hook 'isearch-mode-end-hook #'hexl-isearch-end t t))
    (setq-local isearch-search-fun-function #'isearch-search-fun-default)
    (remove-hook 'isearch-mode-hook #'hexl-isearch-startup t)
    (remove-hook 'isearch-mode-end-hook #'hexl-isearch-end t)))

(easy-menu-add-item hexl-mode-map '(menu-bar Hexl)
            ["Hexl Isearch Mode" (if hexl-isearch-mode (hexl-isearch-mode -1) (hexl-isearch-mode)) :style toggle :selected hexl-isearch-mode] "Go to address")
Tobias
fuente
¡Tu también funciona y es mucho más eficiente en archivos grandes!
gdkrmr