(erledigt) start und end offset von Zeichenkette xyz aus Binärdatei ausgeben

Vom einfachen Programm zum fertigen Debian-Paket, Fragen rund um Programmiersprachen, Scripting und Lizenzierung.
Antworten
ren22

(erledigt) start und end offset von Zeichenkette xyz aus Binärdatei ausgeben

Beitrag von ren22 » 07.12.2019 14:00:32

Hallo,

gibt es ein einfache Möglichkeit, im Terminal, sich aus einer Binärdatei ( HDD-Image / ISO-Image ), den Start und End Offset von einer gesuchten Zeichenkette ausgeben zulassen, der auch über mehrere Zeilen geht, also inklusive newlines ?

Vielen Dank
Zuletzt geändert von ren22 am 15.12.2019 17:14:31, insgesamt 1-mal geändert.

Benutzeravatar
Meillo
Moderator
Beiträge: 8813
Registriert: 21.06.2005 14:55:06
Wohnort: Balmora
Kontaktdaten:

Re: start und end offset von Zeichenkette xyz aus Binärdatei ausgeben

Beitrag von Meillo » 07.12.2019 14:11:44

ren22 hat geschrieben: ↑ zum Beitrag ↑
07.12.2019 14:00:32
gibt es ein einfache Möglichkeit, im Terminal, sich aus einer Binärdatei ( HDD-Image / ISO-Image ), den Start und End Offset von einer gesuchten Zeichenkette ausgeben zulassen, der auch über mehrere Zeilen geht, also inklusive newlines ?
Wenn es eine Binaerdatei ist, dann sind Newlines irrelevant. Du solltest ein Programm fuer Binaerdaten verwenden, wenn du diese Aktion ausfuehrst, da Textprogramme von Newlines und Null-Bytes beeinflusst werden.

Was du also suchst ist eine Art Substring() fuer Dateien.

Keine Ahnung, ob's ein Standardprogramm gibt, das das kann. Falls niemand eines kennt, kann man das auch schnell in C programmieren. Programmier-Contest anyone? ;-)


Btw: Den End-Offset brauchst du nicht, da der Start + length(Suchstring) ist.


Nachtrag: Evtl. koennte dir sowas wie:

Code: Alles auswählen

strings -t d image | grep suchstring
helfen. Nur so 'ne Idee ...
Use ed once in a while!

ren22

Re: start und end offset von Zeichenkette xyz aus Binärdatei ausgeben

Beitrag von ren22 » 07.12.2019 14:47:17

Wenn es eine Binaerdatei ist, dann sind Newlines irrelevant.
mit grep habe ich das Problem, wenn Zeichen 'LF' ->HEX:0A enthalten sind, muss ich die "-z" Option verwenden.

...naja momentan mache ich das so, aber das "grep" gibt mir leider nicht von A bis B aus, sondern alle Zeichenketten.

Code: Alles auswählen

grep -barz 'GESUCHTER_STRING_START_MARKER.*GESUCHTER_STRING_END_MARKER' Binärdatei.img
Ausgabe:
527794176:<?xml version="1.0"?>
TEXT TEXT TEXT
TEXT TEXT TEXT
TEXT TEXT TEXT
<END_MARKER>
527826944:<?xml version="1.0"?>
TEXT TEXT TEXT
TEXT TEXT TEXT
TEXT TEXT TEXT
<END_MARKER>
...usw.


Mein Problem ist immo, dass in der Binärdatei der "END Marker" mehrfach enthalten ist und "grep" alle Zeichen bis zum letzten "END Marker" ausgibt. Wenn ich nur nach dem "END Marker" als String suche weiss ich nicht welcher dann der richtige "END Offset" ist, weil ja mehrfach... aber ich bin noch am suchen & probieren.

*mit "strings" hatte ich das schon probiert aber das ist leider langsam im Gegensatz zu "grep"
Btw: Den End-Offset brauchst du nicht, da der Start + length(Suchstring) ist.
Die Zeichenkettenlänge ist vorerst unbekannt, ich erhalte sie von der Zeichenkette die ich per "grep" mittels Start & End Marker bekomme, so meine Idee.

Danke
Zuletzt geändert von ren22 am 07.12.2019 16:25:53, insgesamt 1-mal geändert.

Benutzeravatar
Meillo
Moderator
Beiträge: 8813
Registriert: 21.06.2005 14:55:06
Wohnort: Balmora
Kontaktdaten:

Re: start und end offset von Zeichenkette xyz aus Binärdatei ausgeben

Beitrag von Meillo » 07.12.2019 15:19:01

Ich glaube, ich bin noch dabei, dein Problem ueberhaupt zu verstehen ...

Es geht also *nicht* darum, einen fixen String zu suchen, sondern eine Bytefolge, von der nur der Anfang und das Ende bekannt sind. Die Bytefolge ist vermutlich kein String, sondern eine beliebige Bytesequenz. Gesucht ist die Position (Offset) von Anfang und Ende der Bytesequenz. -- Ist das so korrekt?

Was du also brauchst, ist ein Programm, das in der Binaerdatei eine gegebenen Anfangssequenz findet und deren Position ausgibt. Anschliessend muss von dieser Position ausgehend eine (die naechste?) Endsequenz gefunden werden und deren Position ausgegeben werden. -- Ist das so korrekt?

Sind die Anfangs- und Endsequenzen lesbare Strings, oder koennen die auch beliebige Bytes enthalten?


strings(1) kann man nur nutzen, wenn es eine Zeichenkette aus lesbaren Zeichen gewesen waere. grep(1) kann auch keine Newlines und Null-Bytes.
Use ed once in a while!

Benutzeravatar
Meillo
Moderator
Beiträge: 8813
Registriert: 21.06.2005 14:55:06
Wohnort: Balmora
Kontaktdaten:

Re: start und end offset von Zeichenkette xyz aus Binärdatei ausgeben

Beitrag von Meillo » 07.12.2019 16:17:32

Ich hab mal was programmiert:

Code: Alles auswählen

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>

char *start = "START";
char *end = "END";


unsigned long
findnext(FILE *file, char *search) {
	char *cp = search;
	int c;
	off_t offset = 0;

	while ((c = fgetc(file)) != EOF) {
		if (c != *cp) {
			continue;
		}
		offset = ftell(file);
		while (*cp++) {
			if ((c = fgetc(file)) == EOF) {
				exit(1);
			}
			if (*cp && c != *cp) {
				cp = search;
				break;
			}
			if (!*cp) {
				printf("`%s' found at %lu\n", search, offset);
				return offset;
			}
		}
	}
	return 0;
}


int
main(void)
{
	findnext(stdin, start);
	findnext(stdin, end);

	return 0;
}

Oben in die globalen Variablen die Start- und Ende-Strings eintragen (unter der Annahme, dass sie keine Null-Bytes enthaltne, sonst muss man den Code anpassen).

Gelesen wird von Stdin.

Ausgegeben wird dann der Beginn des Start-Strings und der Beginn des Ende-Strings in Bytes ab Dateianfang.


Ich habe nur wenig getestet und es koennen, gut moeglich Off-by-one-Fehler und aehnliches enthalten sein. Aber das ist mal ein Anfang.

Randfalltests und die Uebergabe der Start/Ende-Strings als Kommandozeilenparameter (nur falls es wirklich Strings sind), kann bei Gelegenheit ja jemand von euch beisteuern.


(Ich finde das Problem einfach spannend und hatte Lust ein bisschen C zu schreiben ...)
Use ed once in a while!

ren22

Re: start und end offset von Zeichenkette xyz aus Binärdatei ausgeben

Beitrag von ren22 » 07.12.2019 16:20:55

Ich glaube, ich bin noch dabei, dein Problem ueberhaupt zu verstehen ...

Es geht also *nicht* darum, einen fixen String zu suchen, sondern eine Bytefolge, von der nur der Anfang und das Ende bekannt sind. Die Bytefolge ist vermutlich kein String, sondern eine beliebige Bytesequenz. Gesucht ist die Position (Offset) von Anfang und Ende der Bytesequenz. -- Ist das so korrekt?
... nicht ganz

also ich ver(suche) den START OFFSET der Zeichenkette und den END OFFSET von der Gesamt- Zeichenkette in der Binärdatei zu ermitteln, wenn ich die beiden Werte habe kann ich mir die gesamte Zeichenketten ausgeben lassen, weil der Inhalt kann varieren aber nicht der Start und das Ende der gesamten Zeichenkette.

Also als Bsp.:
gesuchte Zeichenkette:
START_STRING <-- (gesucht wird der OFFSET)
unbekannter inhalt an strings
unbekannter inhalt an strings
unbekannter inhalt an strings
ENDE_STRING <-- (gesucht wird der OFFSET)

Wenn ich die beiden OFFSET Werte habe kann ich mir dann von START OFFSET bis END OFFSET als Hexdump ausgeben lassen, daraus bekomme ich auch die eigentliche Stringlänge und kann auch den Inhalt modifizieren .... und dann ... irgend wann später die modifizierten Zeichenkette in der Binärdatei ersetzen "dd of= seek= count= bs= conv=notrunc" ...
(Ich finde das Problem einfach spannend und hatte Lust ein bisschen C zu schreiben ...)
(O.o) :THX: :hail:
Danke

Benutzeravatar
Meillo
Moderator
Beiträge: 8813
Registriert: 21.06.2005 14:55:06
Wohnort: Balmora
Kontaktdaten:

Re: start und end offset von Zeichenkette xyz aus Binärdatei ausgeben

Beitrag von Meillo » 07.12.2019 16:55:51

ren22 hat geschrieben: ↑ zum Beitrag ↑
07.12.2019 16:20:55
also ich ver(suche) den START OFFSET der Zeichenkette und den END OFFSET von der Gesamt- Zeichenkette in der Binärdatei zu ermitteln, wenn ich die beiden Werte habe kann ich mir die gesamte Zeichenketten ausgeben lassen, weil der Inhalt kann varieren aber nicht der Start und das Ende der gesamten Zeichenkette.

Also als Bsp.:
gesuchte Zeichenkette:
START_STRING <-- (gesucht wird der OFFSET)
unbekannter inhalt an strings
unbekannter inhalt an strings
unbekannter inhalt an strings
ENDE_STRING <-- (gesucht wird der OFFSET)
Suchst du die Position am Beginn von ``START_STRING'' und die Position am Ende von ``ENDE_STRING''? Also, willst du den gesamten unbekannten Inhalt inklusive oder exklusive der beiden Marker?

Mein Programm liefert derzeit jeweils den Beginn der Marker. Wenn du also zum Ende noch die Laenge des End-Markers hinzuzaehlst, dann hast du den gewuenschten Inhalt inklusive beider Marker.

Kannst du mein Programm mal ausprobieren? Sind deine Daten klein genug, um das mal schnell testen zu koennen?

Oder kannst du eine extrem zusammengekuerzte Test-Datei erzeugen, mit der ich testen koennte? Also am besten etwas, das auf eine Bildschirmseite passt.

Dann kannst du den Hexdump erzeugen und siehst dort dann ja schnell, ob die Marker ganz enthalten sind, oder ob vielleicht ein Off-by-one-Error dabei ist.


Solange niemand ein Programm kennt, das diese Funktionalitaet schon fertig bietet, koennen wir ja an meinem Programm weiterarbeiten. ;-)

Hier eine verbesserte Version (ein Off-by-one-Error beim Start-Offset beseitigt), die bereits den dd-Befehl zum Extrahieren des Abschnitts ausgibt:

Code: Alles auswählen

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
#include <string.h>

char *start = "START";
char *end = "END";


off_t
findnext(FILE *file, char *search) {
	char *cp = search;
	int c;
	off_t offset = 0;

	while ((c = fgetc(file)) != EOF) {
		if (c != *cp) {
			continue;
		}
		offset = ftell(file) - 1;
		while (*cp++) {
			if ((c = fgetc(file)) == EOF) {
				exit(1);
			}
			if (*cp && c != *cp) {
				cp = search;
				break;
			}
			if (!*cp) {
				return offset;
			}
		}
	}
	return 0;
}


int
main(void)
{
	off_t soff=0, eoff=0;

	soff = findnext(stdin, start);
	if (soff == 0) {
		fprintf(stderr, "Error: no start marker (%s) found\n", start);
		return 0;
	}
	printf("start (%s) at %lu\n", start, soff);

	eoff = findnext(stdin, end);
	if (eoff == 0) {
		fprintf(stderr, "Error: no end marker (%s) found\n", end);
		return 0;
	}
	printf("end (%s) at %lu\n", end, eoff + strlen(end));

	printf("extract section with:  dd bs=1 skip=%lu count=%lu\n",
			soff, (eoff+strlen(end))-soff);

	return 0;
}

Use ed once in a while!

ren22

Re: start und end offset von Zeichenkette xyz aus Binärdatei ausgeben

Beitrag von ren22 » 15.12.2019 17:12:42

Danke für deine Mühe aber ich kein leider kein C Programmieren und ich gerne unabhängig bleiben möchte, bleiben mir nur die üblichen Linux Verdächtigen auf der Kommandozeile.

Meine Lösung ist zwar nicht perfekt aber sie funktioniert soweit erstmal.

zuerste suche ich mittels grep nach drei Strings/Zeichenketten (den ersten string,den darauf folgenden string und den letzen string)
und pipe das an awk weiter, wobei awk wiederum prüft ob erstes pattern1=string1,dann prüfen ob pattern2=string2 direkt folgt nach dem ersten pattern1 und dann solange alle strings einlesen bis awk den dritten string mittels pattern3=string3 match'd ... die gesamte Ausgabe landet dabei direkt in einer Variable ...
*code Auszug vom bashscript"
$1="foo\|bar\|ende"
$FILE_OPT="DieHDDImageDatei.img"

Code: Alles auswählen

SEARCHRESULT="$(grep -baro -e "$1" "$FILE_OPT" | awk '/'"$FIRSTLINE"'/{a=0;l1=$0;c=NR} (/'"$SECONDLINE"'/&&NR==(c+1)){a=1;next;} (/'"$LASTLINE"'/&&a==1){a=0;print l1;print} (a==1){print}')"
... dann kann ich die Werte aus der Variable gut weiterverarbeiten mit einer readline schleife:

Code: Alles auswählen

i=0
while read line ; do
if [ $i -eq 0 ]; then
SEARCHRESULT_OFFSET_START="${line%:*}"
SEARCHRESULT_STRING_START="${line#*:}"
...
                 i=$(($i+1))
                 continue
             elif [ $i -eq 1 ]; then
                 SEARCHRESULT_OFFSET_END="${line%:*}"
                 SEARCHRESULT_STRING_END="${line#*:}"
                 ...
und erhalte den START und END OFFSET ....

vielen Dank an alle :THX:

Antworten