Quand puis-je modifier des chaînes dans un binaire exécutable?

11

J'ai un binaire exécutable; appelons ça a.out. Je peux voir que le binaire contient des chaînes

$ strings a.out
...
/usr/share/foo
....

Je dois changer la chaîne /usr/share/fooen /usr/share/bar. Puis-je simplement remplacer la chaîne par sed?:

sed -i 's@/usr/share/foo@/usr/share/bar@' a.out

Cela ressemble à une chose sûre à faire. Cela fonctionnera-t-il également lorsque les cordes ne sont pas de la même longueur?

Martin Vegter
la source

Réponses:

17

Je ne sais pas si votre version de sedsera nettoyée en binaire ou si elle s'étouffera avec ce qu'elle pense être de très longues lignes en entrée, mais à moins de ces problèmes, l'édition de la chaîne en place devrait fonctionner. Pour voir si c'est le cas, comparez les anciennes et les nouvelles versions avec cmp -l. Il devrait vous indiquer si les trois seules différences entre les deux fichiers sont ou non ces 3 octets.

L'édition de chaînes dans un exécutable compilé fonctionnera en effet si les chaînes sont de la même longueur, mais cela fonctionnera presque toujours aussi si vous raccourcissez la chaîne, en raison de la façon dont les chaînes fonctionnent en C. Dans les chaînes C, tout après le NULterminateur ne compte pas, donc si vous écrivez un nouveau NULterminateur avant la position de l'ancien, vous raccourcirez efficacement la chaîne.

En général, il n'y a aucun moyen d'allonger une chaîne en utilisant ce hack.

Celada
la source
Qu'en est-il de raccourcir la chaîne avec quelque chose comme sed -i 's@longstring@foo@' a.out? Cela rendra le binaire entier plus petit de 7 octets, cela ne corrompra-t-il pas le binaire?
Martin Vegter
Oui, cela corrompra le binaire. C'est pourquoi vous devez traduire la chaîne en une longueur exactement identique, mais définir un NULterminateur à une position antérieure comme je l'ai expliqué (bien que peut-être trop brièvement). Le problème est que vous ne pouvez pas avoir un NULoctet sur la ligne de commande, vous devez donc mettre votre sedprogramme dans un fichier et vous y référer avec -f. D'un autre côté, la chose la plus sûre à faire serait d'utiliser un outil conçu pour fonctionner avec des données binaires au lieu de sedcelui conçu pour fonctionner avec des données texte.
Celada
2
Bonne réponse. sed peut faire beaucoup de choses, mais, en général, c'est pour cela que les éditeurs binaires ont été inventés. Ils peuvent être difficiles à utiliser lors de la navigation dans un grand fichier binaire, mais ils vous permettront de changer les choses octet par octet. J'utilise hexeditlorsque je dois examiner ou modifier un fichier binaire. Vous pouvez utiliser strings -t x file | lesspour localiser les décalages des chaînes (imprimables) que vous souhaitez modifier avant de sauter dans l'éditeur.
Joe
Disons que j'ai une chaîne dans mon programme C: "Mon nom était Mr Robot" et que je veux remplacer "était" par "est", alors le remplissage \0devra être fait avec soin, car si le remplacement fait ceci: "Mon nom est \ 0 Mr Robot ", puis lors de l'exécution des opérations avec la chaîne, le caractère" \ 0 "créera des problèmes car la longueur diminuera involontairement.
Nehal J Wani
@NehalJWani non, dans ce cas, vous devez déplacer le reste de la chaîne d'un octet vers l'avant afin que votre nouvelle terminaison supplémentaire se termine NUL, à côté de l'existant NUL.
Celada