Comment démonter la fonction principale d'une dépouillé application?
Disons que j'ai compilé le formulaire ci-dessous et dépouillé de ses symboles.
#include <stdio.h>
int main()
{
printf("Hello\n");
}
Procédure de construction:
gcc -o hello hello.c
strip --strip-unneeded hello
Si l'application n'était pas dépouillé, démontage, la fonction principale serait facile. Cependant, je n'ai aucune idée de la façon de démonter le principal fonction d'une dépouillé application.
(gdb) disas main
No symbol table is loaded. Use the "file" command.
(gdb) info line main
Function "main" not defined.
Comment pourrais-je le faire? Est-il même possible?
Notes: cela doit être fait avec GDB seulement. Oubliez objdump. Supposons que je n'ai pas accès au code.
Une étape-par-étape de l'exemple serait grandement apprécié.
- Imaginez que je n'ai pas les sources de l'application et aussi que je n'ai pas accès à d'autres outils en plus de GDB.
- L'utilisation de l'IDA 😉 ... désolé, pas pu résister. Je sais que vous le souhaitez pour GDB seulement.
- Quiconque vers le bas voté à ma question, veuillez expliquer pourquoi.
- Je ne vois pas downvote ...? Hein?
- J'ai marqué quelques dizaines de réponses ce week-end, et je soupçonne que quelqu'un n'aime pas avoir leur réponse supprimé. Je suis descendu voix sur presque toutes mes questions et les récentes réponses en moins de 3 minutes. C'est pourquoi j'ai demandé la raison pour laquelle le vote vers le bas. Apparemment, la personne a décidé d'annuler leur vote.
- ah, ok. Mais ne pas l'heuristique de sélection lorsque vous obtenez des sérieusement downvoted et recalcule votre rep? Pensais, j'ai lu quelque chose quelque part.
- Ce n'était pas une énorme baisse de-vote-attaque, à seulement 7 ou 8 en 3 minutes.
Vous devez vous connecter pour publier un commentaire.
Ok, ici une grande édition de ma réponse précédente. Je crois que j'ai trouvé un moyen maintenant.
Vous (encore 🙂 ont ce problème spécifique:
Maintenant, si vous compilez le code (j'ai ajouté un
return 0
à la fin), vous obtiendrez avecgcc -S
:Maintenant, vous pouvez voir que votre binaire vous donne quelques infos:
Rayures:
Le plus important ici est
.text
. C'est un nom commun pour une assemblée début de code, et de l'explication des principaux ci-dessous, à partir de sa taille, vous pouvez voir qu'il comprend principal. Si vous le démontage, vous verrez un appel à l' __libc_start_main. Le plus important, vous êtes le démontage d'un bon point d'entrée qui est vrai code (vous n'êtes pas trompeur de DONNÉES de changement de CODE).L'appel à __libc_start_principaux obtient comme premier argument un pointeur à main(). Donc, le dernier argument de la pile immédiatement avant l'appel de votre main() adresse.
Ici, il est 0x400524 (comme nous le savons déjà). Maintenant, vous définissez un point d'arrêt d'un essayez ceci:
Maintenant, vous pouvez démontage à l'aide de:
C'est surtout la solution.
BTW, c'est un autre code, pour voir si elle fonctionne. C'est pourquoi l'assemblée ci-dessus est un peu différent. Le code ci-dessus est à partir de ce fichier c:
Mais!
si cela ne fonctionne pas, alors vous avez encore quelques conseils:
Vous devriez être à la recherche pour définir des points d'arrêt au début de toutes les fonctions à partir de maintenant. Ils sont juste avant un
ret
ouleave
. Le premier point d'entrée est.text
lui-même. C'est le début de l'assemblée, mais pas le principal.Le problème est que pas toujours un point d'arrêt permettra à votre programme de course. Comme celui-ci dans le très
.text
:De sorte que vous devez continuer d'essayer jusqu'à ce que vous trouver votre chemin, définition de points d'arrêt à:
De l'autre réponse, on devrait garder cette info:
Dans le non-rayé version du fichier, nous voyons:
Maintenant, nous savons que la main est à
0x0000000000400524,0x0000000000400539
. Si nous utilisons le même décalage de regarder les rayures binaire, nous obtenons les mêmes résultats:Donc, sauf si vous pouvez obtenir un peu d'astuce, où le principal chantier (comme l'utilisation d'un autre code avec des symboles), d'une autre manière, si vous pouvez avoir quelques infos sur les premières instructions de montage, de sorte que vous pouvez démonter en détails les lieux et regarder si elle correspond. Si vous n'avez pas accès à tout le code, vous pouvez toujours lire le ELFE de la définition à comprendre comment beaucoup de sections doit apparaître dans le code et essayer un calcul d'adresse. Encore, vous avez besoin d'info sur les articles dans le code!
Que le travail est dur, mon ami! Bonne chance!
Beco
info files
peut vous aider un peu. Si je trouve une mise à jour dans les prochains jours, je commente ici. Bonne chance.catch syscall write
ou tout simplementcatch syscall
, et puis vous essayez d'exécuter. Il ne travaille pas toujours, en raison de l'absence de contexte si le point d'arrêt est trop tôt.gdb gdb
,info files
,disas 0x44f400,0x44f429
,disas 0x44f4f0,0x44f500
et cela a fonctionné. 😉(gdb) disas 0x0000000000400524,0x0000000000400600
où est la fin demain
?0x0000000000400440 - 0x0000000000400618 is .text
. Mais gardez à l'esprit que la fin demain
peut-être ailleurs, en raison de la dissimulation de l'. Vous devriez vraiment suivre l'assemblée et continuer jusqu'à ce que cela a du sens. Le point important est le point d'entrée. À partir de là, le PC (program counter) va continuer, à la suite de nombres que des instructions (au lieu du segment de données où les nombres sont des données).Comment faire
info files
pour obtenir la liste de section (avec l'adresse), et va à partir de là?Exemple:
Le démonter
.init
:Puis aller de l'avant et de démonter le reste.
Si j'étais vous, et j'ai eu la même version de GCC que votre exécutable a été construit avec, j'aimerais étudier la séquence des fonctions appelées sur un mannequin non dépouillé exécutable. La séquence d'appels est probablement similaire dans la plupart des cas habituels, ce qui pourra vous aider à moudre à travers la séquence de démarrage jusqu'à votre
main
par comparaison. Optimisations vont probablement venir de la manière que.Si votre binaire est dépouillé et optimisé,
main
peut ne pas exister comme une "entité" dans le binaire; les chances sont que vous ne pouvez pas obtenir beaucoup mieux que ce type de procédure.main()
. IDA, par exemple, utilise des signatures pour automatiser cela en grande partie à l'aide d'une approche similaire à celle du manuel de celui proposé par Tapis.Il y a un nouvel outil gratuit appelé unstrip de la paradyn projet (divulgation complète: je travaille sur ce projet) qui va réécrire votre programme binaire, en ajoutant les informations de symbole à elle, et de récupérer tous (ou presque tous) les fonctions en dépouillé des binaires Elf pour vous, avec une grande précision. Il ne sera pas identifier la fonction principale comme "principal", mais il va le trouver, et vous pouvez appliquer l'heuristique vous l'avez déjà mentionné ci-dessus pour déterminer la fonction principale.
http://www.paradyn.org/html/tools/unstrip.html
Je suis désolé, ce n'est pas un gdb seule solution.
IIRC,
x/i <location>
est votre ami. Bien sûr, vous devez trouver l'endroit où vous souhaitez démonter vous-même.