Πρώτο commit
Αυτό το commit περιλαμβάνεται σε:
commit
8ec8e9bee2
451 αρχεία άλλαξαν με 46736 προσθήκες και 0 διαγραφές
23
content/articles/32/01_editorial.md
Κανονικό αρχείο
23
content/articles/32/01_editorial.md
Κανονικό αρχείο
|
@ -0,0 +1,23 @@
|
|||
+++
|
||||
title = 'Editorial'
|
||||
date = '2003-06-01T00:00:00Z'
|
||||
description = ''
|
||||
author = 'Ιατρού Μιχάλης iatrou ατ hellug.gr(mailto:iatrou%20%C3%A1%C3%B4%20hellug.gr)'
|
||||
issue = ['Magaz 32']
|
||||
issue_weight = 1
|
||||
+++
|
||||
----------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
*Magaz\... reloaded.*
|
||||
|
||||
----------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
Έχουν περάσει σχεδόν δύο χρόνια από το προηγούμενο τεύχος του Magaz.\
|
||||
Εύχομαι να μην περάσουν άλλα τόσα μέχρι το επόμενο\...\
|
||||
Δυστυχώς, προσωπικά δεν μπορώ να κάνω και πολλά για να υλοποιηθεί η παραπάνω ευχή: είναι στο χέρι των φίλων/αναγνωστών του Magaz να συνεχίσει η λειτουργία του
|
||||
περιοδικού. Χωρίς συντάκτες (έστω και περιστασιακούς) δεν υπάρχουν άρθρα, χωρίς άρθρα δεν υπάρχει Magaz. Τόσο απλά.
|
||||
|
||||
Να αναφέρω, για πολλοστή φορά, ότι δεν είναι ανάγκη να είστε Linux-guru για να γράψετε ένα άρθρο, αρκεί απλά να θέλετε να μοιραστείτε μια εμπειρία σας ή κάτι
|
||||
που σας προβλημάτισε και κίνησε το ενδιαφέρον σας τέλος πάντων.
|
||||
|
||||
Ελπίζω να απολαύσετε το τεύχος \-- και ελπίζω να μην είναι το \"τελευταίο\".
|
105
content/articles/32/02_msvcd.md
Κανονικό αρχείο
105
content/articles/32/02_msvcd.md
Κανονικό αρχείο
|
@ -0,0 +1,105 @@
|
|||
+++
|
||||
title = 'Μετατροπή DivX, DVD σε Video CD στο Linux'
|
||||
date = '2003-04-01T00:00:00Z'
|
||||
description = ''
|
||||
author = 'Nick Apostolakis(mailto:nickapos@agriroot.aua.gr)'
|
||||
issue = ['Magaz 32']
|
||||
issue_weight = 2
|
||||
+++
|
||||
|
||||
----------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
*Ένας σύντομος οδηγός για το πώς μπορείτε να μετατρέψετε video, από DivX και DVD format, σε VCD, χρησιμοποιώντας τον mplayer.*
|
||||
|
||||
----------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
**1. Εισαγωγή**
|
||||
---------------------------------------
|
||||
|
||||
**2. Τα εργαλεία**
|
||||
------------------------------------------
|
||||
|
||||
**3. Λίγα λόγια γενικά για τον MPlayer**
|
||||
----------------------------------------------------------------
|
||||
|
||||
**4. Τα υλικά**
|
||||
---------------------------------------
|
||||
|
||||
**5. Η διαδικασία**
|
||||
-------------------------------------------
|
||||
|
||||
**6. Επίλογος**
|
||||
---------------------------------------
|
||||
|
||||
|
||||
### [1. Εισαγωγή]{#s1}
|
||||
|
||||
Κοιτάζοντας κανείς τον παραπάνω τίτλο μπορεί να αναρωτηθεί για ποίο λόγο κάποιος να θέλει να μετατρέψει ένα video από DivX ή από DVD σε Video CD τη στιγμή που
|
||||
τα 2 πρώτα έχουν σαφώς καλύτερες δυνατότητες από πλευράς ποιότητας αλλά και από πλευράς συμπίεσης (το DivX). Η απάντηση είναι απλή. Το Video CD είναι ένα
|
||||
βιομηχανικό πρότυπο το οποίο έχει υλοποιηθεί σε πληθώρα οικιακών αλλά και φορητών συσκευών ενώ η επεξεργαστική ισχύς που απαιτείται είναι μικρή. Επίσης,
|
||||
χρησιμοποιεί, ως μέσο αποθήκευσης, απλά CD τα οποία είναι διαθέσιμα σε όλους με μικρό κόστος. Οι άλλες λύσεις υστερούν σε αυτούς τους δύο τομείς. Τα μεν DivX
|
||||
είναι κάτι που μεταβάλλεται πολύ γρήγορα και δεν είναι ανοιχτό σε όλο το κόσμο, υπάρχουν δε ελάχιστες standalone συσκευές με δυνατότητα αναπαραγωγής των αρχείων
|
||||
αυτών (και μάλιστα, μόνο συγκεκριμένες εκδόσεις). Το DVD είναι μια πολύ καλή λύση, μόνο που τα εγγράψιμα DVD είναι ακόμα σε βρεφικό στάδιο.
|
||||
|
||||
Το εμφανές μειονέκτημά των Video CD είναι η χαμηλή ποιότητα εικόνας και ήχου που έχουν. Σε αυτό το τομέα υστερούν σαφώς έναντι των DivX αλλά και των DVD. Εδώ
|
||||
όμως θα πρέπει να παρατηρήσω ότι τα VCD έχουν φτιαχτεί για να παίζουν στις χαμηλές αναλύσεις των οικιακών τηλεοράσεων και όχι σε οθόνες υπολογιστών που είναι
|
||||
σαφώς ανώτερες σε ποιότητα. Έτσι, όταν το video παρακολουθείται σε τηλεόραση η διαφορά στην απόδοση σε σχέση με τις άλλες δύο τεχνολογίες είναι μικρή. Τα VCD
|
||||
είναι επίσης \"προβληματικά\" και στον ήχο αφού οι δυνατότητες του φτάνουν μόνο μέχρι τον στερεοφωνικό ενώ δεν υποστηρίζουν AC3. Δυστυχώς για αυτό δεν υπάρχει
|
||||
λύση.
|
||||
|
||||
Παρόλα τα παραπάνω, το VCD παραμένει ένα πολύ καλό ψηφιακό format το οποίο ξεπερνάει σε απόδοση και την ποιότητα της λήψης της τηλεόρασης αλλά και των
|
||||
αναλογικών μέσων (VHS).
|
||||
|
||||
|
||||
### [2. Τα εργαλεία]{#s2}
|
||||
|
||||
Στο Linux υπάρχουν πολλά εργαλεία με τα οποία μπορείτε να κάνετε μετατροπές video μερικά αυτά είναι DVDrip, transcode, MPlayer, DVDx. Τα τρία πρώτα είναι native
|
||||
Linux προγράμματα ενώ το τελευταίο είναι ένα open source πρόγραμμα για Windows το οποίο δουλεύει πολύ καλά και σε Linux μέσω του wine. Στο κείμενα που ακολουθεί
|
||||
θα αναπτύξω την χρήση του MPlayer.
|
||||
|
||||
|
||||
### [3. Λίγα λόγια γενικά για τον MPlayer]{#s3}
|
||||
|
||||
Ο MPlayer αποτελεί τον ελβετικό σουγιά για video στον χώρο του Linux, με λίγα λόγια τα κάνει όλα και συμφέρει. Μπορεί να παίξει σχεδόν όλες τις γνωστές μορφές
|
||||
video, να κάνει encode και capture από κάρτες τηλεόρασης, να μετατρέψει videos από την μια μορφή στην άλλη, να παίξει stream από το δίκτυο, να διορθώσει
|
||||
χαλασμένα αρχεία και διάφορα άλλα. Λίγοι είναι αυτοί που μπορούν να ισχυριστούν ότι γνωρίζουν τις λειτουργίες του MPlayer σε βάθος και εγώ δεν είμαι ένας από
|
||||
αυτούς. Παρακάτω θα περιγράψω μια σχετικά απλή διαδικασία με την οποία μπορούμε να μετατρέψουμε ένα οποιοδήποτε αρχείο video που μπορεί να παίξει ο MPlayer σε
|
||||
mpg αρχικά και τελικά σε Video CD.
|
||||
|
||||
|
||||
### [4. Τα υλικά]{#s4}
|
||||
|
||||
Χρειαζόμαστε, προφανώς, τον ίδιο τον MPlayer (τον κώδικα του). Μέσα στο πακέτο του MPlayer υπάρχει ένα shell script το οποίο ονομάζεται mencvcd και το οποίο
|
||||
χρησιμοποιεί τον MPlayer καθώς και τα mjpegtools για να κάνει την μετατροπή. Το παραγόμενο mpg το μετατρέπουμε σε bin/cue iso images με το πρόγραμμα vcdimager
|
||||
και το γράφουμε με το cdrdao. Τα προγράμματα αυτά μπορούμε να τα αναζητήσουμε στο http://freshmeat.net και να ακολουθήσουμε τις οδηγίες εγκατάστασης τους.
|
||||
|
||||
|
||||
### [5. Η διαδικασία]{#s5}
|
||||
|
||||
Η διαδικασία είναι αρκετά απλή. Έχοντας εγκαταστήσει τα παραπάνω πακέτα, είμαστε έτοιμοι να κάνουμε τις πρώτες δοκιμές. Η λογική πίσω από το mencvcd είναι η
|
||||
εξής: Το καλούμε και του δίνουμε αρχικά τις παραμέτρους για το ίδιο. Μετά ακολουθούν οι παράμετροι που χρειάζεται το MPlayer για να παίξει την ταινία. Προσοχή,
|
||||
δεν δέχεται όλες τις παραμέτρους που δέχεται το MPlayer, αφού για πολλές από αυτές δεν έχει νόημα η χρήση τους. Οι βασικές παράμετροι του mencvcd είναι τρεις.
|
||||
Το -vnorm, το -vfr, και το -w. Το πρώτο καθορίζει ως τι θα μεταχειριστεί το mencvcd το εισαγόμενο video και μπορεί να έχει 3 τιμές p, n, s που αντιστοιχούν σε
|
||||
PAL, NTSC, SECAM. Το δεύτερο και πολύ σημαντικό δηλώνει ποίο θα είναι το frame rate του παραγόμενου mpg και παίρνει ακέραιες τιμές από 0 μέχρι 8. Εάν θέλουμε να
|
||||
καταλήξουμε σε ένα mpg με frame rate 24fps (NTSC) επιλέγουμε την τιμή 2, για 25fps (PAL) επιλέγουμε την τιμή 3. Τέλος, το -w, ασχέτως από το τι μορφής είναι το
|
||||
εισαγόμενο video, κάνει το mencvcd να το μετατρέψει σε 16:9.
|
||||
|
||||
Έτσι, για να μετατρέψουμε το πρώτο τίτλο ενός DVD σε VCD δίνουμε:
|
||||
|
||||
mencvcd output -vnorm n -vfr 2 -dvd 1
|
||||
|
||||
και το mencvcd κάνει όλη την δουλειά μέχρι το σημείο του bin/cue image. Μετά γράφουμε το image σε ένα cd:
|
||||
|
||||
cdrdao write --device 0,0,0 --eject --speed videocd.cue.
|
||||
|
||||
Η αντίστοιχη εντολή για ένα DivX θα ήταν:
|
||||
|
||||
mencvcd output -vnorm n -vfr 2 video.avi
|
||||
|
||||
|
||||
### [6. Επίλογος]{#s6}
|
||||
|
||||
Αυτή είναι η διαδικασία της μετατροπής. Οι πιθανοί συνδυασμοί των παραμέτρων είναι πάρα πολλοί και η αναφορά τους θα απαιτούσε την επεξήγηση του τρόπου που
|
||||
δουλεύει το mencvcd πράγμα που ξεφεύγει από τον σκοπό αυτού του κειμένου. Πάντως, η συμβουλή είναι μια: κάντε πειράματα και για να μην χαλάτε πολλά CD καλό
|
||||
είναι να έχετε 1-2 rewriteable κοντά σας.
|
||||
|
400
content/articles/32/03_grlinux.md
Κανονικό αρχείο
400
content/articles/32/03_grlinux.md
Κανονικό αρχείο
|
@ -0,0 +1,400 @@
|
|||
+++
|
||||
title = 'Ελληνικά στο Linux'
|
||||
date = '2003-04-01T00:00:00Z'
|
||||
description = ''
|
||||
author = 'Κυρίτσης Αθανάσιος (aka DJ Art)'
|
||||
issue = ['Magaz 32']
|
||||
issue_weight = 3
|
||||
+++
|
||||
|
||||
----------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
*Η κατάσταση με τα Ελληνικά στο Linux είναι πλέον σε σχεδόν άριστη μορφή. Όλες οι μοντέρνες διανομές και εφαρμογές υποστηρίζουν Ελληνικά. Το μόνο που θα
|
||||
χρειαστεί να κάνετε, είναι να τα επιλέξετε για χρήση. Η επιλογή αυτή γίνεται με σωστή ρύθμιση 2-3 παραμέτρων του συστήματος και από εκεί και πέρα, τα Ελληνικά
|
||||
είναι θέμα της κάθε εφαρμογής. Με τις παρακάτω οδηγίες μπορείτε να εγκαταστήσετε \"σωστά\" (δηλαδή iso-8859-7) ελληνικά.*
|
||||
|
||||
----------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
Για να εγκαταστήσετε τα ελληνικά, Θα πρέπει να κάνετε τα εξής 3 απλά βήματα:
|
||||
|
||||
1. Να εγκαταστήσετε γραμματοσειρές στο σύστημά σας.
|
||||
2. Να εγκαταστήσετε τα ελληνικά locales και να τα ενεργοποιήσετε.
|
||||
3. Να ενημερώσετε τα αρχεία των Χ για το ελληνικό πληκτρολόγιο και να το ενεργοποιήσετε.
|
||||
|
||||
**1. Εγκατάσταση Γραμματοσειρών**
|
||||
-----------------------------------------------------------
|
||||
|
||||
- [1.1 Graphis](#ss1.1)
|
||||
- [1.2 Εγκατάσταση TrueType γραμματοσειρών](#ss1.2)
|
||||
- [1.3 AntiAliasing](#ss1.3)
|
||||
|
||||
**2. Ενεργοποίηση των locales**
|
||||
---------------------------------------------------------
|
||||
|
||||
- [2.1 Για το RedHat](#ss2.1)
|
||||
- [2.2 Για το Mandrake](#ss2.2)
|
||||
- [2.3 Για το Slackware](#ss2.3)
|
||||
- [2.4 Για Debian](#ss2.4)
|
||||
|
||||
**3. Ρύθμιση των X-Windows**
|
||||
------------------------------------------------------
|
||||
|
||||
- [3.1 Για X 4.3.0 και πάνω](#ss3.1)
|
||||
- [3.2 Για Χ 4.1.0 ώς και X 4.2.1](#ss3.2)
|
||||
- [3.3 Για Χ 4.0.2 και 4.0.3](#ss3.3)
|
||||
- [3.4 Για Χ μικρότερα από 4.0.1](#ss3.4)
|
||||
|
||||
**4. Για την κονσόλα και μόνο**
|
||||
---------------------------------------------------------
|
||||
|
||||
**5. Για GTK+ 2.x / GNOME 2.x εφαρμογές**
|
||||
-------------------------------------------------------------------
|
||||
|
||||
**6. Για το Netscape της σειράς 4.x**
|
||||
---------------------------------------------------------------
|
||||
|
||||
**7. \*BSD Compatibility**
|
||||
----------------------------------------------------
|
||||
|
||||
**8. Credits**
|
||||
----------------------------------------
|
||||
|
||||
|
||||
### [1. Εγκατάσταση Γραμματοσειρών]{#s1}
|
||||
|
||||
Για να έχετε ελληνικά στο σύστημά σας, το πρώτο βήμα είναι να εγκαταστήσετε ελληνικές γραμματοσειρές. Εδώ έχετε 2 επιλογές: να εγκαταστήσετε τις δωρεάν
|
||||
γραμματοσειρές του πακέτου Graphis ή/και επιπλέον TrueType γραμματοσειρές. Εμείς σας προτείνουμε να εγκαταστήσετε και τα δύο. Οι Truetype γραμματοσειρές είναι
|
||||
αισθητικά πιο όμορφες και πιο προτεινόμενες για χρήση σε ένα desktop σύστημα.
|
||||
|
||||
### [1.1 Graphis]{#ss1.1}
|
||||
|
||||
Το Graphis είναι ένα project του Hellug, το οποίο έχει σαν στόχο την ομαδοποίηση των ήδη υπαρχόντων πακέτων γραμματοσειρών, αλλά και την επίλυση αρκετών
|
||||
προβλημάτων τους. Η διεύθυνση του Graphis στο Internet είναι <http://graphis.hellug.gr>. Απο εκεί μπορείτε να κατεβάσετε τις γραμματοσειρές σε .rpm πακέτο ή σε
|
||||
source μορφή (.tar.gz).
|
||||
|
||||
Στη συνέχεια, είναι απαραίτητες οι παρακάτω ενέργειες:
|
||||
|
||||
- Για να γίνει η εγκατάσταση αυτόματα είναι απαραίτητη η ύπαρξη της perl (γλώσσα προγραμματισμού), και να εισέλθετε στο μηχάνημά σας ως \"root\", όχι ως απλός
|
||||
χρήστης. Χρησιμοποιούνται επίσης κάποιες άλλες εντολές, οι οποίες όμως ανήκουν στις standard εντολές, και θα πρέπει να είναι ήδη εγκατεστημένες (π.χ. οι
|
||||
dirname και expr).
|
||||
- Αρχικά πηγαίνετε στον φάκελο που έχετε σώσει τα RPM αρχεία. Στη συνέχεια εκτελέστε αυτήν την εντολή:\
|
||||
rpm -Uvh xfntgr-\*.rpm\
|
||||
Κανονικά θα δείτε τα πακέτα να εγκαθιστώνται το ένα μετά το άλλο.
|
||||
- Αν το σύστημά σας δεν υποστηρίζει rpm πακέτα, τότε θα πρέπει να κάνετε την εγκατάσταση μόνοι σας: Αρχικά πρέπει να αποσυμπιέσετε το αρχείο
|
||||
xfntgr-xx-xx.tar.gz, κάτι που μάλλον ήδη έχετε κάνει. Ως αποτέλεσμα θα πρέπει να έχετε ένα φάκελο με όνομα \"xfntgr-xx\" καθώς και πολλά αρχεία και
|
||||
υποφακέλους μέσα σε αυτόν. Αυτόν τον κατάλογο θα πρέπει να τον μεταφέρετε, μετονομάζοντάς στον σε \"hellas\" στη θέση \"/usr/X11R6/lib/X11/fonts/\". Δηλαδή
|
||||
θα πρέπει να υπάρχει ως \"/usr/X11R6/lib/X11/fonts/hellas/\". Στον φάκελο \"hellas\" θα βρείτε το αρχείο \"graphis\". Εκτελέστε το και οι γραμματοσειρές θα
|
||||
εγκατασταθούν στο σύστημά σας (δηλαδή θα μπούν στο path στο XF86Config).
|
||||
|
||||
### [1.2 Εγκατάσταση TrueType γραμματοσειρών]{#ss1.2}
|
||||
|
||||
Truetype γραμματοσειρές μπορείτε να βρείτε οπουδήποτε. Το καλύτερο μέρος είναι ο φάκελος Fonts των Windows :-) (αρκεί να τα έχετε νόμιμα). Για όσους δεν έχουν
|
||||
πρόσβαση σε μία Windows εγκατάσταση, μπορείτε να κατεβάσετε τα \"core fonts for the web\" στο <http://corefonts.sourceforge.net/>. Επίσης, μπορείτε να βρείτε
|
||||
Truetype γραμματοσειρές σε διάφορα σημεία στο Internet, ενώ υπάρχουν και εμπορικές λύσεις, εμπορικά πακέτα που προσφέρουν ως προϊόν οικογένειες TrueType
|
||||
γραμματοσειρών.
|
||||
|
||||
Για να εγκαταστήσετε και να χρησιμοποιήσετε truetype γραμματοσειρές, χρειάζεστε 2 πράγματα:
|
||||
|
||||
1. font server με υποστήριξη truetype. Αν χρησιμοποιείτε Χ-Windows της σειράς 4.0.x και πάνω, δεν χρειάζεται να ανησυχείτε γιατί τον έχουν ενσωματωμένο. Για Χ
|
||||
κατώτερης έκδοσης, τον truetype font server (xfsft) θα τον βρείτε στο <http://www.dcs.ed.ac.uk/home/jec/programs/xfsft/>.\
|
||||
\
|
||||
2. Την εφαρμογή ttmkfdir. Αν δεν την έχετε στο σύστημά σας, μπορείτε να την βρείτε στο <http://www.joerg-pommnitz.de/TrueType/ttmkfdir.tar.gz>
|
||||
|
||||
Τώρα είστε έτοιμοι να εγκαταστήσετε τις γραμματοσειρές. Πηγαίντε στον κατάλογο /usr/X11R6/lib/X11/fonts και δημιουργείστε έναν καινούριο φάκελο με την ονομασία
|
||||
π.χ. ttf. Μέσα σε αυτόν τον κατάλογο τοποθετήστε όσες truetype γραμματοσειρές επιθυμείτε. Σημειώστε πως τα filenames των γραμματοσειρών δεν θα πρέπει να
|
||||
περιέχουν κενό. Επίσης, αν κάνατε copy τις γραμματοσειρές από το φάκελο fonts των Windows, τότε σιγουρευτείτε πως κάνατε copy μόνο όσα αρχεία έχουν την κατάληξη
|
||||
.ttf, όλες οι άλλες γραμματοσειρές των Windows δεν είναι truetype και δεν θα δουλέψουν. Στη συνέχεια, μπείτε στον κατάλογο ttf και εκτελέστε τις εντολές
|
||||
ttmkfdir -o fonts.dir και ttmkfdir -o fonts.scale. Θα δημιουργηθούν τα αρχεία fonts.dir και fonts.scale, τα οποίο θα περιέχουν όλες τις γραμματοσειρές που
|
||||
εγκαταστήσατε. Τώρα θα πρέπει να προσθέσετε τον φάκελο /usr/X11R6/lib/X11/fonts/ttf στο Fontpath των X-Windows. Αυτό μπορείτε να το κάνετε με 2 τρόπους:
|
||||
|
||||
1. Αν χρησιμοποιείτε τον X font Server (xfs), πηγαίνετε στον κατάλογο /etc/X11/fs και ανοίξτε το αρχείο config με έναν text editor. Προσθέστε στο
|
||||
\"catalogue=\" τον παραπάνω κατάλογο με τις truetype γραμματοσειρές και κάντε restart τον xfs.
|
||||
|
||||
2. Αν δεν χρησιμοποιείτε τον xfs, τότε ανοίξτε το κατάλληλο XF86Config (π.χ. /etc/X11/XF86Config ή /etc/X11/XF86Config-4) και προσθέστε την παρακάτω γραμμή στο
|
||||
Section \"Files\":
|
||||
|
||||
FontPath "/usr/X11R6/lib/X11/fonts/ttf/"
|
||||
|
||||
Κάντε restart τα X-Windows
|
||||
|
||||
Στις καινούριες διανομές, είναι απαραίτητο ακόμα ένα βήμα. Έτσι, λοιπόν, αν έχετε μία από τις εξής διανομές: **RedHat έκδοσης 8.0 και πάνω, Mandrake έκδοσης 9.0
|
||||
και πάνω, SuSE έκδοσης 8.0 και πάνω, Slackware έκδοσης 9.0 και πάνω ή οποιαδήποτε άλλη διανομή που χρησιμοποιεί το πακέτο fontconfig**, τότε αφού έχετε κάνει
|
||||
όλα τα παραπάνω βήματα, εκτελέστε ως root την εντολή **fc-cache -fv**\
|
||||
Το output αυτής της εντολής θα πρέπει να σας πληροφορήσει σχετικά με τον αριθμό των γραμματοσειρών που βρήκε στον κατάλογο με τις ttf γραμματοσειρές σας. Αν δεν
|
||||
\"διάβασε\" τον συγκεκριμένο κατάλογο, τότε θα χρειαστεί να τον προσθέσετε κατάλληλα στο αρχείο: **/etc/fonts/fonts.conf**
|
||||
|
||||
Για το Debian, με την παρακάτω εντολή θα εγκατασταθούν αυτόματα οι core γραμματοσειρές της Microsoft:
|
||||
|
||||
\# apt-get install msttcorefonts
|
||||
|
||||
### [1.3 AntiAliasing]{#ss1.3}
|
||||
|
||||
Όσον αφορά το θέμα AntiAliasing στα fonts, απλά θα αναφέρω πως εδώ μιλάμε πλέον \*ΜΟΝΟ\* για truetype γραμματοσειρές (το ΑΑ δουλεύει μόνο πάνω σε αυτές).
|
||||
Επίσης, θα πρέπει να είστε σίγουροι πως οι βιβλιοθήκες που έχετε, όπως το QT ή το GTK+/Glib και τα X-Windows/libfreetype, το υποστηρίζουν ή ότι τα έχετε κάνει
|
||||
compile με ενεργοποιημένη την υποστήριξη ΑΑ.
|
||||
|
||||
Για τους πιο πολλούς, αν έχετε κάποια από τις τελευταίες διανομές, τότε το πιθανότερο είναι ότι δεν θα χρειαστεί να κάνετε τίποτα (π.χ. απλά επιλέξτε την
|
||||
συγκεκριμένη δυνατότητα από το control center του KDE)
|
||||
|
||||
Σε κάθε άλλη περίπτωση, σας παραπέμπω στο πολύ καλό HowTo για το θέμα αυτό, το οποίο θα βρείτε στο <http://trolls.troll.no/~lars/fonts/qt-fonts-HOWTO.html>.
|
||||
|
||||
|
||||
### [2. Ενεργοποίηση των locales]{#s2}
|
||||
|
||||
Το επόμενο βήμα που θα πρέπει να κάνετε είναι να ενεργοποιήσετε τα ελληνικά locales στο σύστημά σας. Για να το κάνετε αυτό, καλό θα ήταν να συμβουλευτείτε τις
|
||||
οδηγίες που δίνει η διανομή σας. Και, φυσικά, να φροντίσετε (πρίν από οτιδήποτε) τα ελληνικά locales να είναι εγκατεστημένα. Προσέξτε πως αν δεν τα
|
||||
ενεργοποιήσετε, τότε τίποτα από όλα αυτά που αναφέρουμε εδώ δεν πρόκειται να δουλέψει σωστά. (Συνοπτικά, έχω ακούσει ότι για SuSE θα πρέπει να κάνετε το
|
||||
απαραίτητο βήμα μέσω του YAST, ενώ για Redhat/Mandrake, υπάρχει το αρχείο /etc/sysconfig/i18n όπου ορίζονται οι μεταβλητές των locales και η γλώσσα). Αν έχετε
|
||||
αναλυτικές οδηγίες για κάποια διανομή, ευχαρίστως να τις συμπεριλάβω σε αυτό το κείμενο.
|
||||
|
||||
Αν είστε σίγουροι πως έχετε εγκατεστημένα τα locales και ξέρετε πώς να τα ενεργοποιήσετε, τότε πρέπει να ορίσετε το LC\_CTYPE ώς el ή el\_GR ή greek, ανάλογα με
|
||||
τη διανομή που χρησιμοποιείτε. Για να έχετε ελληνικό πληκτρολόγιο η παραπάνω μεταβλητή είναι αρκετή. Αν θέλετε να χρησιμοποιείτε τα εξελληνισμένα προγράμματα
|
||||
και να βλέπετε τα μενού στα παράθυρα στα ελληνικα, τότε πρέπει να ορίσετε την LC\_MESSAGES όπως και την LC\_CTYPE. Ένας manual τρόπος να ορίσετε τις δύο αυτές
|
||||
μεταβλητές είναι να ανοίξετε το αρχείο εκίννησης του shell σας, π.χ. το .bash\_login ή το .bash\_profile ή το .bashrc (ανάλογα με τη διανομή που χρησιμοποιείτε)
|
||||
που υπάρχει στο home directory σας και να γράψετε:
|
||||
|
||||
export LC_CTYPE=el_GR
|
||||
export LC_MESSAGES=el_GR
|
||||
|
||||
### [2.1 Για το RedHat]{#ss2.1}
|
||||
|
||||
Aνοίγουμε το αρχείο /etc/sysconfig/i18n και φροντίζουμε ώστε να υπάρχουν οι εξής γραμμες:
|
||||
|
||||
LANG="el_GR"
|
||||
SUPPORTED="en_US.UTF-8:en_US:en:el_GR.UTF-8:el_GR:el"
|
||||
LC_CTYPE="el_GR"
|
||||
|
||||
Μετά το πείραγμα αυτού του αρχείου, θα πρέπει το RedHat με κάποιο τρόπο να ξαναδιαβάσει αυτό το αρχείο. Ένας γρήγορος τρόπος να το κάνετε αυτό είναι να βγείτε
|
||||
σε init 1 με την εντολή **telinit 1** και ξανά σε init 3 με την εντολή **telinit 3**. Οι πιο αρχάριοι μπορούν να κάνουν ένα reboot (shutdown) του μηχανήματος αν
|
||||
μπερδεύονται με τα inits.
|
||||
|
||||
### [2.2 Για το Mandrake]{#ss2.2}
|
||||
|
||||
Ανοίγουμε το αρχείο /etc/sysconfig/i18n και φροντίζουμε ώστε να μοιάζει κάπως έτσι:
|
||||
|
||||
LANG="el_GR"
|
||||
SUPPORTED="en_US.UTF-8:en_US:en:el_GR.UTF-8:el_GR:el"
|
||||
LC_CTYPE="el_GR"
|
||||
|
||||
Μετά το πείραγμα αυτού του αρχείου, θα πρέπει το Mandrake με κάποιο τρόπο να ξαναδιαβάσει αυτό το αρχείο. Ένας γρήγορος τρόπος να το κάνετε αυτό είναι να βγείτε
|
||||
σε init 1 με την εντολή **telinit 1** και ξανά σε init 3 με την εντολή **telinit 3**. Οι πιο αρχάριοι μπορούν να κάνουν ένα reboot (shutdown) του μηχανήματος αν
|
||||
μπερδεύονται με τα inits.
|
||||
|
||||
### [2.3 Για το Slackware]{#ss2.3}
|
||||
|
||||
Στο Slackware τα πράγματα είναι πολύ εύκολα. Προσθέστε τις παρακάτω γραμμές είτε στο /etc/profile ή στο \~/.bash\_login:
|
||||
|
||||
export LANG=el_GR
|
||||
export LC_CTYPE=el_GR
|
||||
export LC_NUMERIC=POSIX
|
||||
export LC_TIME=POSIX
|
||||
export LC_COLLATE=POSIX
|
||||
export LC_MONETARY=POSIX
|
||||
export LC_MESSAGES=POSIX
|
||||
export LC_PAPER=POSIX
|
||||
export LC_NAME=POSIX
|
||||
export LC_ADDRESS=POSIX
|
||||
export LC_TELEPHONE=POSIX
|
||||
export LC_MEASUREMENT=POSIX
|
||||
export LC_IDENTIFICATION=POSIX
|
||||
|
||||
Όσες επιπλέον μεταβλητές περιβάλλοντος θέλετε να δείχνουν σε el\_GR, αλλάξτε κατάλληλα στις παραπάνω γραμμές το POSIX με el\_GR.
|
||||
|
||||
### [2.4 Για Debian]{#ss2.4}
|
||||
|
||||
Στο Debian, τα locales εγκαθίστανται και ρυθμίζονται με τις εξής εντολές:
|
||||
|
||||
\# apt-get install locales\
|
||||
\# dpkg-reconfigure locales
|
||||
|
||||
Στη συνέχεια επιλέγετε el\_GR.ISO8859-7 ή/και ότι άλλο χρειαζόσαστε.
|
||||
|
||||
|
||||
### [3. Ρύθμιση των X-Windows]{#s3}
|
||||
|
||||
### [3.1 Για X 4.3.0 και πάνω]{#ss3.1}
|
||||
|
||||
Αν έχετε Χ 4.3.0 και πάνω, τότε για να έχετε ελληνικά, αρκεί να πάτε σε κάποιο εργαλείο ρύθμισης των Χ (όπως το xf86config, το xf86cfg, το XF86Setup κλπ) και
|
||||
στην επιλογή για το πληκτρολόγιο να επιλέξετε το ελληνικό. Στη συνέχεια, θα πρέπει να ανοίξετε το κατάλληλο αρχείο XF86Config (ανάλογα με τη διανομή σας, π.χ.
|
||||
το /etc/X11/XF86Config ή το /etc/X11/XF86Config-4) και να πάτε στην ενότητα του πληκτρολογίου ( Section \"Keyboard\" ) και να σιγουρευτείτε πως αυτή η ενότητα
|
||||
θα μοιάζει κάπως έτσι:
|
||||
|
||||
Option "XkbRules" "xfree86"
|
||||
Option "XkbModel" "pc101"
|
||||
Option "XkbLayout" "us,el"
|
||||
Option "XkbOptions" "grp:alt_shift_toggle"
|
||||
|
||||
Η δεύτερη γραμμή μπορεί να είναι διαφορετική, ανάλογα με πόσα πλήκτρα έχει το πληκτρολόγιό σας (προφανώς, αν υπάρχει ήδη γραμμή XkbModel μπορείτε απλά να την
|
||||
κρατήσετε), ενώ η τέταρτη δηλώνει με ποιό συνδυασμό πλήκτρων μπορείτε να αλλάξετε από το αγγλικό στο ελληνικό πληκτρολόγιο, και μπορεί να είναι \"grp:toggle\"
|
||||
(με AltGr), \"grp:shift\_toggle\" (τα δύο Shift μαζί), \"grp:ctrl\_shift\_toggle\", \"grp:ctrl\_alt\_toggle\" και \"grp:caps\_toggle\" (αυτά τα τρία νομίζω
|
||||
είναι προφανή).
|
||||
|
||||
### [3.2 Για Χ 4.1.0 ώς και X 4.2.1]{#ss3.2}
|
||||
|
||||
Αν έχετε Χ 4.1.0 έως και X 4.2.1, τότε για να έχετε ελληνικά, αρκεί να πάτε σε κάποιο εργαλείο ρύθμισης των Χ (όπως το xf86config, το xf86cfg, το XF86Setup κλπ)
|
||||
και στην επιλογή για το πληκτρολόγιο να επιλέξετε το ελληνικό. Στη συνέχεια, θα πρέπει να ανοίξετε το κατάλληλο αρχείο XF86Config (ανάλογα με τη διανομή σας,
|
||||
π.χ. το /etc/X11/XF86Config ή το /etc/X11/XF86Config-4) και να πάτε στην ενότητα του πληκτρολογίου ( Section \"Keyboard\" ) και να σιγουρευτείτε πως αυτή η
|
||||
ενότητα θα μοιάζει κάπως έτσι:
|
||||
|
||||
Option "XkbRules" "xfree86"
|
||||
Option "XkbModel" "pc101"
|
||||
Option "XkbLayout" "el"
|
||||
Option "XkbOptions" "grp:alt_shift_toggle"
|
||||
|
||||
Η δεύτερη γραμμή μπορεί να είναι διαφορετική, ανάλογα με πόσα πλήκτρα έχει το πληκτρολόγιό σας (προφανώς, αν υπάρχει ήδη γραμμή XkbModel μπορείτε απλά να την
|
||||
κρατήσετε), ενώ η τέταρτη δηλώνει με ποιό συνδυασμό πλήκτρων μπορείτε να αλλάξετε από το αγγλικό στο ελληνικό πληκτρολόγιο, και μπορεί να είναι \"grp:toggle\"
|
||||
(με AltGr), \"grp:shift\_toggle\" (τα δύο Shift μαζί), \"grp:ctrl\_shift\_toggle\", \"grp:ctrl\_alt\_toggle\" και \"grp:caps\_toggle\" (αυτά τα τρία νομίζω
|
||||
είναι προφανή).
|
||||
|
||||
### [3.3 Για Χ 4.0.2 και 4.0.3]{#ss3.3}
|
||||
|
||||
Αν έχετε είτε Χ 4.0.2 είτε 4.0.3, τότε για να έχετε ελληνικά, αρκεί να πάτε σε κάποιο εργαλείο ρύθμισης των Χ (όπως το xf86config, το xf86cfg, το XF86Setup κλπ)
|
||||
και στην επιλογή για το πληκτρολόγιο να επιλέξετε το ελληνικό. Στη συνέχεια, θα πρέπει να ανοίξετε το κατάλληλο αρχείο XF86Config (ανάλογα με τη διανομή σας,
|
||||
π.χ. το /etc/X11/XF86Config ή το /etc/X11/XF86Config-4) και να πάτε στην ενότητα του πληκτρολογίου ( Section \"Keyboard\" ) και να σιγουρευτείτε πως αυτή η
|
||||
ενότητα θα μοιάζει κάπως έτσι:
|
||||
|
||||
Option "XkbRules" "xfree86"
|
||||
Option "XkbModel" "pc101"
|
||||
Option "XkbLayout" "gr"
|
||||
Option "XkbOptions" "grp:ctrl_shift_toggle"
|
||||
|
||||
Η δεύτερη γραμμή μπορεί να είναι διαφορετική, ανάλογα με πόσα πλήκτρα έχει το πληκτρολόγιό σας (προφανώς, αν υπάρχει ήδη γραμμή XkbModel μπορείτε απλά να την
|
||||
κρατήσετε), ενώ η τέταρτη δηλώνει με ποιό συνδυασμό πλήκτρων μπορείτε να αλλάξετε από το αγγλικό στο ελληνικό πληκτρολόγιο, και μπορεί να είναι \"grp:toggle\"
|
||||
(με AltGr), \"grp:shift\_toggle\" (τα δύο Shift μαζί), \"grp:ctrl\_shift\_toggle\", \"grp:ctrl\_alt\_toggle\" και \"grp:caps\_toggle\" (αυτά τα τρία νομίζω
|
||||
είναι προφανή).
|
||||
|
||||
### [3.4 Για Χ μικρότερα από 4.0.1]{#ss3.4}
|
||||
|
||||
Το επόμενο απαραίτητο βήμα είναι η ενημέρωση των αρχείων των Χ και η ενεργοποίηση του ελληνικού πληκτρολογίου. Θα πρέπει να κάνετε τις εξής ενέργειες:
|
||||
|
||||
Πρώτα θα πρέπει να έχετε τα αρχεία el και Compose. Μπορείτε να τα βρείτε συμπιεσμένα στο <http://members.hellug.gr/djart/files/el_Compose.tar.bz2>.
|
||||
|
||||
1. Αντιγράφετε το Compose στο /usr/X11R6/lib/X11/locale/iso8859-7/.
|
||||
|
||||
2. Προσθέτετε την παρακάτω γραμμή στο /usr/X11R6/lib/X11/locale/compose.dir:
|
||||
|
||||
iso8859-7/Compose el_GR.ISO8859-7
|
||||
|
||||
3. Αντιγράφετε το el στο /usr/X11R6/lib/X11/xkb/symbols/.
|
||||
|
||||
4. Προσθέτετε την παρακάτω γραμμή στο /usr/X11R6/lib/X11/xkb/symbols.dir:
|
||||
|
||||
-dp----- a------- el(basic)
|
||||
|
||||
5. Στο /etc/X11/XF86Config, στο section \"Keyboard\", σβήνετε όλες τις επιλογές του XKB, και στη θέση τους βάζετε τις εξής:
|
||||
|
||||
XkbRules "xfree86"
|
||||
XkbModel "pc104"
|
||||
XkbLayout "el"
|
||||
XkbOptions "grp:toggle"
|
||||
|
||||
(Η παραπάνω σύνταξη είναι για Χ 3.3.x. Για Χ 4.x η σύνταξη είναι η εξής):
|
||||
|
||||
Option "XkbRules" "xfree86"
|
||||
Option "XkbModel" "pc101"
|
||||
Option "XkbLayout" "el"
|
||||
Option "XkbOptions" "grp:ctrl_shift_toggle"
|
||||
|
||||
H δεύτερη γραμμή μπορεί να είναι διαφορετική, ανάλογα με πόσα πλήκτρα έχει το πληκτρολόγιό σας (προφανώς, αν υπάρχει ήδη γραμμή XkbModel μπορείτε απλά να
|
||||
την κρατήσετε), ενώ η τέταρτη δηλώνει με ποιό συνδυασμό πλήκτρων μπορείτε να αλλάξετε από το αγγλικό στο ελληνικό πληκτρολόγιο, και μπορεί να είναι
|
||||
\"grp:toggle\" (με AltGr), \"grp:shift\_toggle\" (τα δύο Shift μαζί), \"grp:ctrl\_shift\_toggle\", \"grp:ctrl\_alt\_toggle\" και \"grp:caps\_toggle\" (αυτά
|
||||
τα τρία νομίζω είναι προφανή).
|
||||
|
||||
6. Ξαναξεκινάτε τον X server σας. Αυτό ήταν!
|
||||
|
||||
|
||||
### [4. Για την κονσόλα και μόνο]{#s4}
|
||||
|
||||
- Σιγουρευόμαστε πως το αρχείο /etc/inputrc περιέχει τις εξής γραμμές:
|
||||
|
||||
----------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
set meta-flag on
|
||||
set convert-meta off
|
||||
set output-meta on
|
||||
|
||||
----------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
- Εκτελούμε με τη σειρά τις εξής εντολές:
|
||||
|
||||
**\$ echo -ne \"\\033(K\\033)K\" \>/dev/tty**\
|
||||
**\$ setfont iso07.16**\
|
||||
**\$ loadkeys gr**
|
||||
|
||||
Τώρα χρησιμοποιώντας το Alt+Shift μπορούμε να αλλάξουμε σε ελληνικό πληκτρολόγιο και να γράψουμε ελληνικά.
|
||||
|
||||
Αν οι παραπάνω εντολές δεν δουλέψουν στο RedHat 8.0 και πάνω, δοκιμάστε τις εξής εντολές:
|
||||
|
||||
**\$ echo -ne \"\\033(K\\033)K\" \>/dev/tty**\
|
||||
**\$ setfont iso07u-16.psfu.gz -u /lib/kbd/consoletrans/8859-7\_to\_uni.trans**\
|
||||
**\$ loadkeys gr**
|
||||
|
||||
**Για το Debian**, θα χρειαστεί να χρησιμοποιήσετε την εντολή consolechars αντί της setfont, δηλαδή οι εντολές θα είναι κάπως έτσι:
|
||||
|
||||
**\$ echo -ne \"\\033(K\\033)K\" \>/dev/tty**\
|
||||
**\$ consolechars -f /usr/share/consolefonts/iso07.f16.psf.gz**\
|
||||
**\$ loadkeys gr**
|
||||
|
||||
|
||||
### [5. Για GTK+ 2.x / GNOME 2.x εφαρμογές]{#s5}
|
||||
|
||||
Λόγω ενός bug στο gtk+ 2.x, δεν εμφανίζονται οι τόνοι στις εφαρμογές. Για να επιλύσετε το συγκεκριμένο πρόβλημα, θα χρειαστεί να προσθέσετε τις παρακάτω γραμμές
|
||||
στο \~/.bashrc ή \~/.bash\_profile ή \~/.bash\_login (ή όποιο άλλο είναι το αρχείο εκκίνησης του shell σας):
|
||||
|
||||
export GTK_IM_MODULE=xim
|
||||
|
||||
|
||||
### [6. Για το Netscape της σειράς 4.x]{#s6}
|
||||
|
||||
Για να εχουμε ελληνικά στη γραμμή που δίνουμε τις διευθύνσεις και παντού στο email, αντιγράφουμε το αρχείο Netscape.ad απο τον κατάλογο
|
||||
/usr/doc/netscape-communicator-4.xx/ (αν ο netscape είναι εγκατεστημένος από μορφή .rpm ή από τον κατάλογο που τον εγκαταστήσατε, σε περίπτωση μορφής .tar.gz)
|
||||
στο /usr/X11R6/lib/X11/app-defaults/ και το μετονομάζουμε σε Netscape. Το ανοίγουμε με τον joe ή με άλλον επεξεργαστή και στη γραμμή 5567, 5568, 5569 (σημειώστε
|
||||
ότι οι αριθμοί των σειρών αλλάζουν από έκδοση σε έκδοση, θα τους βρείτε όμως γύρω στη γραμμή 5500+) όπου λέει adobe βάζουμε \* δηλ πρέπει να είναι:
|
||||
|
||||
----------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
*XmTextField.fontList: -*-courier-medium-r-*-*-*-120-*-*-*-*-iso8859-*
|
||||
*XmText.fontlist: -*-courier-medium-r-*-*-*-120-*-*-*-*-iso8859-*
|
||||
*XmList*fontlist: -*-courier-medium-r-*-*-*-120-*-*-*-*-iso8859-*
|
||||
|
||||
----------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
Επίσης, στη γραμμή 5600,5601,5602 αντικαθιστούμε το -\*-helvetica με -greek-helvetica και το 100 με 120 δηλαδή πρέπει να είναι:
|
||||
|
||||
----------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
*XmLGrid*fontList:\
|
||||
-greek-helvetica-medium-r-*-*-*-120-*-*-*-*-iso8859-*,\
|
||||
-greek-helvetica-bold-r-*-*-*-120-*-*-*-*-iso8859-*=BOLD,\
|
||||
-greek-helvetica-medium-o-*-*-*-120-*-*-*-*-iso8859-*=ITALIC
|
||||
|
||||
----------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
ΤΕΛΕΙΩΣΑΜΕ
|
||||
|
||||
Ξεκινάμε τον Netscape και απο το view -\> encoding επιλέγουμε το Greek (ISO-8859-7) και πάλι απο το ίδιο μενού το \"Set Default Encoding\" και στο
|
||||
Εdit-\>Preferences-\>Appearance-\>fonts το \"Greek(iso-8859-7)\" και ορίζουμε ποιές γραμματοσειρές θέλουμε. Οι καλύτερες είναι οι Courier (Greek). Tο ίδιο
|
||||
κάνουμε για το \"Western(iso-8859-1)\" έτσι ώστε να μπορούμε να γράψουμε ελληνικά στις φόρμες και στο mail τύπου text/plain.
|
||||
|
||||
|
||||
### [7. \*BSD Compatibility]{#s7}
|
||||
|
||||
Ναι, καλά θα το καταλάβατε. Όλα αυτά για τα Χ ισχύουν σε οποιοδήποτε Unix σύστημα που τρέχει X-Windows (προσοχή, για τα Χ μόνο, όχι και για την κονσόλα). Οι
|
||||
γραμματοσειρές Graphis εγκαθίστανται και σε FreeBSD και σε \*BSD. Παρόλα αυτά, αν σαν ενδιαφέρει το θέμα των ελληνικών στα \*BSD, τότε πρέπει οπωσδήποτε να
|
||||
επισκεφτείτε το web site του [Greek BSD Project](http://www.bsd.gr) και να δείτε τις οδηγίες που προσφέρουν τα παιδιά για τα \*BSD τόσο για την κονσόλα, όσο και
|
||||
για τα Χ, όσο και τις γραμματοσειρές που έχουν φτιάξει.
|
||||
|
||||
|
||||
### [8. Credits]{#s8}
|
||||
|
||||
Τα παιδιά που εργάστηκαν ώστε εσείς να βλέπετε ελληνικά είναι οι:
|
||||
|
||||
- To Graphis team ( <http://graphis.hellug.gr>) και ιδιαιτέρως ο Παναγιώτης Κατσαλούλης.
|
||||
- Βασίλης Βασαΐτης. Το section για τη ρύθμιση των Χ προέρχεται από δικό του e-mail στην i18n mailing list. Ο Παναγιώτης και ο Βασίλης είναι οι δημιουργοί των
|
||||
el και Compose.
|
||||
- Όλα τα παιδιά στην i18n mailing list.
|
||||
- To Σίμο Ξενιτέλλη και όλο το team που μεταφράζει τα προγράμματα που βλέπετε και χρησιμοποιείτε στα ελληνικά.
|
||||
- Τους Αλέξανδρο Παπαδόπουλο και Ιωάννη Παπαϊωάννου για τις Debian specific οδηγίες.
|
||||
- Όλους όσους ξέχασα να αναφέρω, όσους κατά λάθος αδίκησα αναφέροντας λιγότερα από όσα έχουν κάνει και όσους απλά αγνοώ ότι έχουν προσφέρει. Καλά θα κάνουν να
|
||||
μου στείλουν αμέσως ένα e-mail για να αποκαταστήσω την αλήθεια ;-)
|
||||
|
250
content/articles/32/04_traffic.md
Κανονικό αρχείο
250
content/articles/32/04_traffic.md
Κανονικό αρχείο
|
@ -0,0 +1,250 @@
|
|||
+++
|
||||
title = 'Traffic Shaping - Queueing algorithms'
|
||||
date = ''
|
||||
description = ''
|
||||
author = 'Στέφανος Χαρχαλάκης'
|
||||
issue = ['Magaz 32']
|
||||
issue_weight = 4
|
||||
+++
|
||||
----------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
*Μία σύντομη εισαγωγή σε queueing algorithmsς και της εφαρμογής τους σε δίκτυα υπολογιστών.*
|
||||
|
||||
----------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
**1. FIFO**
|
||||
-------------------------------------
|
||||
|
||||
- [1.1 Γενικά](#ss1.1)
|
||||
- [1.2 Λειτουργία](#ss1.2)
|
||||
- [1.3 pfifo\_fast](#ss1.3)
|
||||
- [1.4 Πλεονεκτήματα/Μειονεκτήματα](#ss1.4)
|
||||
|
||||
**2. Stochastic Fairness Queueing (SFQ)**
|
||||
-------------------------------------------------------------------
|
||||
|
||||
- [2.1 Γενικά](#ss2.1)
|
||||
- [2.2 Λειτουργία](#ss2.2)
|
||||
|
||||
**3. Random Early Detection (RED)**
|
||||
-------------------------------------------------------------
|
||||
|
||||
- [3.1 Γενικά](#ss3.1)
|
||||
- [3.2 Λειτουργία](#ss3.2)
|
||||
|
||||
**4. Αναφορές:**
|
||||
------------------------------------------
|
||||
|
||||
|
||||
### [1. FIFO]{#s1}
|
||||
|
||||
### [1.1 Γενικά]{#ss1.1}
|
||||
|
||||
Ο αλγόριθμος FIFO είναι ο ποιο απλός απ\' όσους μπορούν να εφαρμοστούν για την διαχείριση της ουράς σε έναν network interface. Είναι ιδιαίτερα απλός και συνήθως
|
||||
αποτελεί την default αντιμετώπιση.
|
||||
|
||||
### [1.2 Λειτουργία]{#ss1.2}
|
||||
|
||||
Η λειτουργία του βασίζεται στα εξής χαρακτηριστικά:
|
||||
|
||||
- Υπάρχει μία ουρά με σταθερό μέγεθος σε bytes ή πακέτα.
|
||||
- Όσο η ουρά δεν είναι γεμάτη, κάθε πακέτο που έρχεται τοποθετείται στο τέλος της ουράς.
|
||||
- Όταν πρόκειται να σταλεί ένα πακέτο στο δίκτυο, επιλέγεται το πρώτο από την ουρά.
|
||||
- Όταν η ουρά είναι γεμάτη, κάθε πακέτο που έρχεται απορρίπτεται. Ο τρόπος αυτός ονομάζεται tail-drop.
|
||||
|
||||
### [1.3 pfifo\_fast]{#ss1.3}
|
||||
|
||||
Ο pfifo\_fast αποτελεί μια παραλλαγή του FIFO. Ακολουθεί την ίδια λογική, αλλά χωρίζει την ουρά σε τρία bands. Στη συνέχεια, κάθε πακέτο που έρχεται
|
||||
τοποθετείται σε ένα από τα τρία bands, ανάλογα με την τιμή του TOS πεδίου. Το πεδίο αυτό έχει μέγεθος 4 bits, κάθε ένα από τα οποία έχει και άλλη σημασία:
|
||||
|
||||
---------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
\
|
||||

|
||||
|
||||
---------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
Η ταξινόμηση των πακέτων σε κάθε ένα από τα τρία bands γίνεται όπως φαίνεται στον πίνακα.
|
||||
|
||||
---------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
\
|
||||

|
||||
|
||||
---------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
Ποτέ δεν στέλνεται πακέτο από την band 1 όταν υπάρχει κάποιο στη band 0, ούτε από την band 2 όταν υπάρχει κάποιο στη band 1.
|
||||
|
||||
### [1.4 Πλεονεκτήματα/Μειονεκτήματα]{#ss1.4}
|
||||
|
||||
Το μόνο πλεονέκτημα του αλγόριθμου είναι η ταχύτητά και η απλότητά του. Στην πράξη δεν έχει καλά αποτελέσματα όταν υπάρχει συμφόρηση σε κάποια γραμμή, αλλά
|
||||
χρησιμοποιείται με επιτυχία σε γρήγορα interfaces όπου δεν παρατηρείται συμφόρηση.
|
||||
|
||||
|
||||
### [2. Stochastic Fairness Queueing (SFQ)]{#s2}
|
||||
|
||||
### [2.1 Γενικά]{#ss2.1}
|
||||
|
||||
Ο αλγόριθμος SFQ προσπαθεί να λύσει το πρόβλημα που δημιουργεί ο FIFO όταν κάποιο μηχάνημα του δικτύου προκαλεί υπερβολική κίνηση. Απευθύνεται κυρίως σε μικρά
|
||||
τοπικά δίκτυα για τα σημεία όπου υπάρχει συμφόρηση.
|
||||
|
||||
### [2.2 Λειτουργία]{#ss2.2}
|
||||
|
||||
Ο SFQ δημιουργεί πολλά slots του ενός πακέτου, στα οποία ταξινομεί τα πακέτα και στη συνέχεια επιλέγει το επόμενο από αυτά που θα σταλεί στο δίκτυο με κυκλικό
|
||||
(Round-Robin) τρόπο. Πιο συγκεκριμένα:
|
||||
|
||||
- Δημιουργεί 128 διαφορετικά slots του ενός πακέτου.
|
||||
- Κάθε πακέτο το οποίο έρχεται κατευθύνεται ένα από αυτά.
|
||||
- Αν το slot είναι κατειλημμένο τότε το πακέτο απορρίπτεται, αλλιώς τοποθετείται μέσα σε αυτό.
|
||||
|
||||
Στη συνέχεια, όταν πρόκειται να δρομολογήσει ένα πακέτο στο δίκτυο, παίρνει το πρώτο που υπάρχει στην \`\`επόμενη\'\' ουρά.
|
||||
|
||||
#### Hashing
|
||||
|
||||
Η τοποθέτηση του κάθε πακέτου σε κάθε ένα από τα 128 slots γίνεται με την βοήθεια ενός αλγόριθμου hashing. Για τον υπολογισμού του hash key λαμβάνονται υπόψη:
|
||||
|
||||
**Για IPv4 πακέτα:**
|
||||
|
||||
: Η source IP address, η destination IP address και το πρωτόκολλο (TCP,UDP, \...).
|
||||
|
||||
**Για IPv6 πακέτα:**
|
||||
|
||||
: Η source IP address, η destination IP address και η τιμή ενός εσωτερικού pointer.
|
||||
|
||||
**Για τα υπόλοιπα:**
|
||||
|
||||
: Οι τιμές τριών εσωτερικών pointers.
|
||||
|
||||
Επίσης χρησιμοποιείται και ένας τυχαίος αριθμός ο οποίος προέρχεται από το δίκτυο και ο οποίος αλλάζει κάθε 10 δευτερόλεπτα \-- το χρονικό διάστημα ονομάζεται
|
||||
perturb \-- και είναι παραμετροποιήσιμο.
|
||||
|
||||
Ο σκοπός του hashing είναι να αναγνωρίζει flows και να τα διαχωρίζει, δίνοντας ίσες ευκαιρίες στους χρήστες του δικτύου, ακόμα και αν κάποιος δημιουργεί
|
||||
υπερβολική κίνηση. Λόγω του ότι τα hash keys δεν είναι μοναδικά, χρησιμοποιείται ο τυχαίος αριθμός που αναφέρθηκε, ο οποίος ουσιαστικά μεταβάλει τον αλγόριθμο
|
||||
κάθε 10 δευτερόλεπτα.
|
||||
|
||||
#### Αποστολή πακέτων
|
||||
|
||||
Η επιλογή του επόμενου πακέτου προς αποστολή γίνεται με κυκλικό τρόπο (Round-Robin), επιλέγοντας ένα πακέτο από την επόμενη στοίβα κάθε φορά. Με τον τρόπο αυτό,
|
||||
τα flows τα οποία παρουσιάζουν κίνηση μπορούν να δημιουργήσουν 128 φορές μικρότερο πρόβλημα στο δίκτυο.
|
||||
|
||||
#### Παράδειγμα
|
||||
|
||||
Ο τρόπος λειτουργίας του SFQ φαίνεται στο σχήμα. Τη στιγμή όπου η ουρά των 128 πακέτων είναι γεμάτη, ένα πακέτο έχει φύγει για το δίκτυο ελευθερώνοντας χώρο για
|
||||
ένα καινούριο το οποίο θα καταλάβει τη θέση του. Την ίδια στιγμή, ένα άλλο πακέτο θα απορριφθεί γιατί το slot για το οποίο προορίζονταν είναι κατειλημμένο.
|
||||
|
||||
---------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
\
|
||||

|
||||
|
||||
---------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
#### Πλεονεκτήματα/Μειονεκτήματα
|
||||
|
||||
Όπως αναφέρθηκε, ο SFQ προορίζεται για μικρά τοπικά δίκτυα όπου μπορεί να εξασφαλίσει την ομαλή λειτουργία. Έχει το πλεονέκτημα της ταχύτητας και της απλότητας,
|
||||
μιας και δεν απαιτεί ιδιαίτερους υπολογισμούς για τη λειτουργία του.
|
||||
|
||||
Το πρόβλημά του είναι το μικρό μήκος ουράς (μόλις 128 πακέτα), το οποίο οδηγεί σε πολύ μεγάλο αριθμό χαμένων πακέτων. Κάτι τέτοιο είναι αποδεκτό και ίσως και
|
||||
επιθυμητό σε περιπτώσεις όπου ένα flow/slot αντιστοιχεί σε έναν μόνο υπολογιστή του τοπικού δικτύου, αλλά δημιουργεί προβλήματα σε μεγαλύτερα δίκτυα.
|
||||
|
||||
|
||||
### [3. Random Early Detection (RED)]{#s3}
|
||||
|
||||
### [3.1 Γενικά]{#ss3.1}
|
||||
|
||||
Ο αλγόριθμος αυτός είναι μία άλλη αντιμετώπιση της FIFO ουράς. Σκοπός του είναι να μην αφήσει την FIFO ουρά να γεμίσει, απορρίπτοντας επιλεκτικά πακέτα όταν
|
||||
χρειάζεται.
|
||||
|
||||
### [3.2 Λειτουργία]{#ss3.2}
|
||||
|
||||
Η απόρριψη των πακέτων γίνεται στατιστικά, όταν το **μέσο** μέγεθος της ουράς ξεπεράσει κάποιο όριο.
|
||||
|
||||
Ο αλγόριθμος δέχεται τις εξής παραμέτρους:
|
||||
|
||||
**Minimum queue length: (min\_q)**
|
||||
|
||||
: Το μέσο μέγεθος της ουράς το οποίο πρέπει να ξεπεραστεί πριν αρχίσει ο αλγόριθμος να εξετάζει πιθανή απόρριψη πακέτων.
|
||||
|
||||
**Maximum queue length: (max\_q)**
|
||||
|
||||
: Το μέσο μέγεθος της ουράς κάτω από το οποίο προσπαθεί να την κρατάει πάντα ο αλγόριθμος. Ονομάζεται και soft limit.
|
||||
|
||||
**Queue limit: (qlim)**
|
||||
|
||||
: Το απόλυτο μέγιστο μέγεθος της ουράς. Αν το φτάσει τότε ο αλγόριθμος μετατρέπεται σε FIFO. Ονομάζεται και hard limit.
|
||||
|
||||
**Average packet size: (avg\_p)**
|
||||
|
||||
: Το μέσο μέγεθος του κάθε πακέτου. Με βάση αυτό γίνεται ο υπολογισμός όλων των υπόλοιπων.
|
||||
|
||||
**Burst size: (burst)**
|
||||
|
||||
: Το μέγιστο επιτρεπόμενο μέγεθος των bursts , ώστε να μην απορρίπτονται πακέτα όταν δεν υπάρχει πραγματική συμφόρηση.
|
||||
|
||||
Ο αλγόριθμος δεν αναγνωρίζει flows όπως κάποιοι άλλοι και στηρίζεται στην τυχαία επιλογή πακέτων. Η λειτουργία του βασίζεται στο μέσο μέγεθος της ουράς
|
||||
(avg\_q), το οποίο υπολογίζεται με την άφιξη κάθε νέου πακέτου σύμφωνα με τον τύπο:
|
||||
|
||||
---------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
\
|
||||

|
||||
|
||||
---------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
όπου cql είναι το τρέχον μέγεθος της ουράς (current queue length), m είναι ο χρόνος κατά τον οποίο η ουρά δεν είναι άδεια και W είναι μία τιμή που υπολογίζεται
|
||||
ως συνάρτηση των burst, min\_q και avg\_p έτσι ώστε να ισχύει:
|
||||
|
||||
---------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
\
|
||||

|
||||
|
||||
---------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
Το W ονομάζεται και βάρος της ουράς (Queue Weight) και υποδηλώνει το κατά πόσο επηρεάζουν το avg\_q οι νέες τιμές της. Όσο μεγαλύτερο είναι το W, τόσο
|
||||
μεγαλύτερη σημασία έχουν προσωρινές αυξομειώσεις της ουράς \-- δηλώνει το κατά πόσο πρέπει να \`\`θυμάται\'\' ο αλγόριθμος τα παλαιότερα μεγέθη της ουράς.
|
||||
|
||||
Η μεταχείριση του κάθε πακέτου μεταβάλλεται ανάλογα με το avg\_q:
|
||||
|
||||
- **avg\_p \< min\_q**
|
||||
|
||||
Το πακέτο δεν επηρεάζεται.
|
||||
|
||||
- **min\_q \< avg\_q \< max\_q**
|
||||
|
||||
Στο πακέτο αποδίδεται μια πιθανότητα p\_b:
|
||||
|
||||
---------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
\
|
||||

|
||||
|
||||
---------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
όπου max\_p είναι η μέγιστη επιθυμητή τιμή του p\_b. Ταυτόχρονα υπάρχει ένας counter ο οποίος αυξάνεται με κάθε πακέτο όταν το avg\_q βρίσκεται σε αυτά τα
|
||||
όρια. Στη συνέχεια υπολογίζεται η πιθανότητα απόρριψης p\_a:
|
||||
|
||||
---------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
\
|
||||

|
||||
|
||||
---------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
Τέλος χρησιμοποιείται ένας τυχαίος αριθμός R, μεταξύ των 0 και 1, σύμφωνα με τον οποίο απορρίπτεται το πακέτο αν ο R είναι μικρότερος του p\_a.
|
||||
|
||||
- **avg\_q \> max\_q**
|
||||
|
||||
Το πακέτο απορρίπτεται.
|
||||
|
||||
Επειδή η απόρριψη των πακέτων γίνεται με στατιστικό τρόπο, τα flows τα οποία δημιουργούν μεγαλύτερη κίνηση έχουν περισσότερες πιθανότητες να χάσουν πακέτα μιας
|
||||
και στέλνουν δεδομένα ποιο συχνά στο δρομολογητή.
|
||||
|
||||
#### Πλεονεκτήματα/Μειονεκτήματα
|
||||
|
||||
Ο RED αποτελεί μια πολύ καλή λύση για την αντιμετώπιση της συμφόρησης του δικτύου ενώ ταυτόχρονα βοηθάει το TCP/IP να βρει σχετικά σύντομα το σωστό ρυθμό
|
||||
αποστολής δεδομένων.
|
||||
|
||||
Λόγω του ότι δεν αναγνωρίζει flows δεν έχει τη δυνατότητα να παρέχει μεγάλη δικαιοσύνη κάτι το οποίο δεν αποτελεί και σκοπό του.
|
||||
|
||||
|
||||
### [4. Αναφορές:]{#s4}
|
||||
|
||||
- Bert Hubert, Gregory Maxwell, Remco van Mook, Martijn van Oosterhout, Paul B Schroeder, Jasper Spaans, Pedro Larroy. Linux Advanced Routing & Traffic
|
||||
Control HOWTO,
|
||||
- Sally Floyd and Van Jacobson. Random Early Detection Gateways for Congestion Avoidance. University of California, 1993
|
||||
- Linux kernel 2.4.20 sources
|
||||
|
682
content/articles/32/05_rce1.md
Κανονικό αρχείο
682
content/articles/32/05_rce1.md
Κανονικό αρχείο
|
@ -0,0 +1,682 @@
|
|||
+++
|
||||
title = 'Reverse Engineering σε Περιβάλλον Linux, Μέρος 0'
|
||||
date = '2003-04-01T00:00:00Z'
|
||||
description = ''
|
||||
author = 'Φραντζής Αλέξανδρος (aka Alf)'
|
||||
issue = ['Magaz 32']
|
||||
issue_weight = 5
|
||||
+++
|
||||
|
||||
----------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
*Reverse Engineering, από τη σκοπιά του απλού χρήστη :-)*
|
||||
|
||||
----------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
**1. Μέρος 0 - Εισαγωγή στο Reverse Code Engineering**
|
||||
-----------------------------------------------------------------------------
|
||||
|
||||
**2. Γιατί RCE**
|
||||
---------------------------------------
|
||||
|
||||
**3. Tools of the trade.**
|
||||
-------------------------------------------------
|
||||
|
||||
**4. GDB - Ο παρεξηγημένος debugger**
|
||||
------------------------------------------------------------
|
||||
|
||||
- [4.1 GDB - Τα βασικά](#ss4.1)
|
||||
|
||||
**5. Πρόκληση 0**
|
||||
----------------------------------------
|
||||
|
||||
|
||||
### [1. Μέρος 0 - Εισαγωγή στο Reverse Code Engineering]{#s1}
|
||||
|
||||
\"In the beginning the Universe was created. This has made a lot of people very angry and been widely regarded as a bad move.\"- HGG Book 2
|
||||
|
||||
Τη δεκαετία του \'60-\'70 τα προγράμματα άρχισαν να μεγαλώνουν και να γίνονται χαώδη (βλέπε ΙΒΜ OS/360). Ο Dikjstra προσπάθησε να βάλει τάξη αλλά ήταν ήδη αργά
|
||||
:) Πολλοί προγραμματιστές βρέθηκαν στη δύσκολη κατάσταση να λαμβάνουν τόνους παρατημένου κώδικα (σε assembly βέβαια) που έπρεπε να χρησιμοποιήσουν. Τα σχόλια
|
||||
που συνόδευαν τα προγράμματα ήταν συχνά λειψά και στη χειρότερη περίπτωση λανθασμένα(!). Οι επιλογές ήταν δύο· να ξαναγραφεί ο κώδικας από την αρχή ή να
|
||||
χρησιμοποιηθεί (με τα χίλια ζόρια) όπως είναι. Οποιοσδήποτε, όμως, δρόμος απαιτούσε την πλήρη κατανόηση του ήδη υπάρχοντος κώδικα. Ήταν μια δύσκολη δουλειά αλλά
|
||||
κάποιος έπρεπε να την κάνει. Έτσι λοιπόν γεννήθηκε το Reverse Code Engineering.
|
||||
|
||||
Σήμερα τα πράγματα είναι πολύ διαφορετικά από τη μεριά των developers. Οι εφαρμογές αναπτύσσονται σχεδόν αποκλειστικά σε γλώσσες υψηλού επιπέδου (και με
|
||||
εργαλεία ακόμα πιο υψηλού επιπέδου). Οι ίδιοι οι προγραμματιστές, τις περισσότερες φορές, δεν έρχονται σε επαφή με τον object κώδικα που παράγουν οι compilers.
|
||||
Τα έτοιμα modules, που καλούνται να χρησιμοποιήσουν, είναι σε μορφή πηγαίου κώδικα ή σε βιβλιοθήκες με καλά καθορισμένη διεπαφή.
|
||||
|
||||
Μπορεί η διαδικασία παραγωγής να έχει αλλάξει, ο τελικός χρήστης όμως έχει στα χέρια του ότι και παλιότερα: μια ακατανόητη, για την πλειονότητα, σειρά από bytes
|
||||
(εξαιρούνται τα open source) κρυμμένα πίσω από στρώματα αφαιρετικότητας (πχ εικονίδιο). Τώρα πια η τέχνη του RCE εξασκείται κυρίως από περίεργους χρήστες και
|
||||
σπάνια από developers.
|
||||
|
||||
Τώρα έφτασε η μαγική στιγμή για να ορίσουμε το Reverse Code Engineering. Σε ελεύθερη μετάφραση στα ελληνικά ονομάζεται Αντίστροφη Μηχανική Κώδικα και είναι η
|
||||
διαδικασία κατά την οποία εξάγεται η λειτουργικότητα ενός προγράμματος από τον κώδικα του, ο οποίος συνήθως βρίσκεται σε κάποια \"δύσπεπτη\" (συνήθως assembly)
|
||||
μορφή.
|
||||
|
||||
Σε αυτό το σημείο θα ήταν σκόπιμο να αναφερθούμε λίγο στη έννοια cracker. Σε κάποιον εκτός των πραγμάτων ίσως να θυμίζει τα μπισκότα που δίνουμε στους
|
||||
παπαγάλους (Poly wanna cracker?). Συχνά συνδέεται με τον κόσμο των δικτύων και αναφέρεται στον κακόβουλο hacker ο οποίος σπέρνει την καταστροφή στο πέρασμα του
|
||||
:) Στον σύμπαν του RCE το cracking αναφέρεται στη διαδικασία, κατά την οποία προσπαθούμε να ξεπεράσουμε ένα σύστημα ασφαλείας στο επίπεδο του λογισμικού (πχ
|
||||
copy protection). Είναι ουσιαστικά υποκατηγορία του RCE διότι αν και χρησιμοποιεί τις ίδιες τεχνικές έχει πιο περιορισμένο σκοπό και σπάνια απαιτεί την πλήρη
|
||||
κατανόηση του λογισμικού.
|
||||
|
||||
|
||||
### [2. Γιατί RCE]{#s2}
|
||||
|
||||
- 1\. **Γνώση**: Η παρατήρηση της εσωτερικής δομής των προγραμμάτων οδηγεί σε καλύτερη κατανόηση της λειτουργίας τους αλλά και του υπολογιστή γενικότερα.
|
||||
- 2\. **Σιγουριά**: Γνωρίζοντας την εσωτερική λειτουργία ενός προγράμματος είσαι πια σίγουρος πως το λογισμικό κάνει αυτό που λέει, τίποτα λιγότερο και τίποτα
|
||||
περισσότερο.
|
||||
- 3\. **Ευτυχία**: Η διαδικασία του RE είναι ένα πνευματικό παιχνίδι. Αν βγεις νικητής δεν μπορείς παρά να νιώσεις ευτυχισμένος.
|
||||
|
||||
|
||||
### [3. Tools of the trade.]{#s3}
|
||||
|
||||
Βασική προϋπόθεση για την επιτυχία μιας προσπάθειας στο RCE είναι η γνώση των εργαλείων που υπάρχουν, των λεγόμενων tools of the trade. Τα εργαλεία χωρίζονται
|
||||
σε δύο βασικές κατηγορίες ανάλογα με την προσέγγιση που χρησιμοποιούν. Από τη μία υπάρχουν τα εργαλεία που επιτρέπουν την παρακολούθηση της δυναμικής εκτέλεσης
|
||||
του κώδικα και αποτελούν την live προσέγγιση. Τέτοια εργαλεία είναι οι debuggers με πιo χαρακτηριστικά παραδείγματα το πραγματικά πανίσχυρο Numega Softice για
|
||||
Windows και το περιβόητο :) GDB για το linux. Από την άλλη υπάρχουν εργαλεία που παρουσιάζουν τον κώδικα σε στατική μορφή (dead listing). Αυτά είναι
|
||||
disassemblers όπως w32Dasm, IDA (τρέχει σε windows αλλά υποστηρίζει και ELF-linux εκτελέσιμα) και biew, ldasm (linux). Στο linux οι περισσότεροι disassemblers
|
||||
είναι scripts που χρησιμοποιούν την έξοδο του objdump, που περιέχεται στα binutils. Τέλος αξίζει να αναφερθούμε σε μια υβριδική κατηγορία εργαλείων τα οποία εγώ
|
||||
ονομάζω undead. Αυτά παρουσιάζουν την δυναμική εκτέλεση του κώδικα αλλά δεν δίνουν τη δυνατότητα τροποποίησης της εξέλιξης του. Συνήθως οι πληροφορίες που
|
||||
δίνουν είναι πιο υψηλού επιπέδου από assembly. Παράδειγμα τέτοιου εργαλείου είναι το strace που καταγράφει τα system calls που κλήθηκαν από ένα πρόγραμμα.
|
||||
|
||||
|
||||
### [4. GDB - Ο παρεξηγημένος debugger]{#s4}
|
||||
|
||||
O GDB (GNU DeBugger) αποτελεί πνευματικό παιδί του Richard Stallman, ιδρυτή του FSF (Free Software Foundation). Υποστηρίζει πολλές αρχιτεκτονικές (x86, alpha,
|
||||
MIPS\...) και γλώσσες υψηλού επιπέδου (C, C++, Fortran, Modula-2, Pascal, CHILL). Υποστηρίζει (conditional, hardware) breakpoints, remote debugging. Έχει,
|
||||
λοιπόν, όλα εκείνα τα χαρακτηριστικά που τον καθιστούν έναν πολύ ισχυρό debugger. Ποίο είναι το πρόβλημα λοιπόν;
|
||||
|
||||
Όπως δηλώνει και ο τίτλος, ο GDB είναι ο ορισμός του παρεξηγημένου debugger. Κατά καιρούς έχει χαρακτηριστεί με επίθετα όπως \"brain-damaged\", άδικα κατά την
|
||||
ταπεινή μου γνώμη. Το βασικό επιχείρημα των πολέμιων του GDB είναι το user interface. Και όντως, το UI καμία σχέση δεν έχει με το γραφικό περιβάλλον πχ του M\$
|
||||
Visual Studio. Εδώ έχουμε να κάνουμε με command line σε όλο της το μεγαλείο! Όσοι έχουν ασχοληθεί με το Softice στα windows καταλαβαίνουν τι εννοώ. Βέβαια
|
||||
πολλοί έσπευσαν να βελτιώσουν την κατάσταση και έτσι σήμερα υπάρχει μία πληθώρα από front-ends: το built-in Text User Interface (TUI) σε curses,
|
||||
DataDisplayDebugger (DDD) για Χ11/Motif, Kdbg gia KDE κ.α. Στο κείμενο αυτό θα ασχοληθούμε με την απλή μορφή του GDB (άντε και με το TUI :) ). Θα αρχίσουμε με
|
||||
source-code debugging\...
|
||||
|
||||
### [4.1 GDB - Τα βασικά]{#ss4.1}
|
||||
|
||||
Βασική δυνατότητα ενός debugger είναι η παρακολούθηση της εκτέλεσης ενός άλλου προγράμματος και η εν δυνάμει αλλαγή της εξέλιξης του είτε άμεσα, είτε έμμεσα
|
||||
μέσω της αλλαγής των δεδομένων του. Στο κομμάτι αυτό θα χρησιμοποιηθεί ως παράδειγμα ο παρακάτω C κώδικας:
|
||||
|
||||
----------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int num;
|
||||
|
||||
if (argc < 2) {
|
||||
printf("Usage: %s <number>\n",argv[0]);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
num=alf(argv[1]);
|
||||
|
||||
if (num > 10)
|
||||
printf("Ok!\n");
|
||||
else
|
||||
printf("Failed!\n");
|
||||
}
|
||||
|
||||
int alf(char *s)
|
||||
{
|
||||
return atoi(s);
|
||||
}
|
||||
|
||||
----------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
Κάντε compile με : gcc -g -o rce1 rce1.c
|
||||
|
||||
To flag -g λέει στον compiler να περιλάβει στο εκτελέσιμο αρχείο εκτός από το symbol table, πληροφορίες που χρειάζεται ο GDB για source-code debugging. Αν ένα
|
||||
πρόγραμμα δεν έχει τέτοιες πληροφορίες τότε μπορούμε μόνο να δούμε τον assembly κώδικα (και τα σύμβολα).
|
||||
|
||||
Το παραπάνω (παντελώς άχρηστο) πρόγραμμα το μόνο που κάνει είναι να ελέγχει αν η πρώτη παράμετρος στη γραμμή εντολής είναι μεγαλύτερη από 10 και τυπώνει το
|
||||
κατάλληλο μήνυμα.
|
||||
|
||||
#### Φόρτωμα προγράμματος
|
||||
|
||||
Καταρχάς πρέπει να φορτώσουμε το πρόγραμμα στο GDB:
|
||||
|
||||
> bash$ gdb -q rce1
|
||||
> (gdb)
|
||||
>
|
||||
>
|
||||
|
||||
Το switch -q/\--quiet λέει στον gdb να μη δείχνει τα εισαγωγικά μηνύματα. Από εδώ και πέρα θα εννοείται ακόμα και αν δεν γράφεται (πχ alias gdb =\"gdb -q\").
|
||||
|
||||
Το (gdb) prompt δηλώνει πως ο debugger έχει σταματήσει το πρόγραμμα και είναι έτοιμος να δεχτεί εντολές. Παρατηρήστε πως ο GDB δεν έγραψε κάποιο μήνυμα
|
||||
επιβεβαίωσης ότι έγινε σωστά το φόρτωμα του rce1. Εφόσον δεν υπάρχει μήνυμα λάθους η διαδικασία ολοκληρώθηκε επιτυχώς.
|
||||
|
||||
H έξοδος από τον debugger γίνεται με την \"quit\"/\"q\"
|
||||
|
||||
> (gdb) q
|
||||
> bash$
|
||||
>
|
||||
>
|
||||
|
||||
Μια εναλλακτική μέθοδος για να φορτώνουμε αρχεία είναι με την εντολή **file** του GDB. Η **file** φορτώνει το εκτελέσιμο στη μνήμη ΚΑΙ το symbol table στον GDB.
|
||||
Υπάρχει και η exec-file η οποία φορτώνει μόνο τo εκτελέσιμο στη μνήμη.
|
||||
|
||||
> bash$ gdb
|
||||
> (gdb) file rce1
|
||||
> Reading symbols from rce1...done.
|
||||
> (gdb)
|
||||
>
|
||||
>
|
||||
|
||||
Σημείωση: Ο GDB περιλαμβάνει ένα αρκετά πλήρες σύστημα βοήθειας με την εντολή **help**.
|
||||
|
||||
> (gdb) help file
|
||||
> Use FILE as program to be debugged.
|
||||
> It is read for its symbols, for getting the contents of pure memory,
|
||||
> and it is the program executed when you use the `run' command.
|
||||
> If FILE cannot be found as specified, your execution directory path
|
||||
> ($PATH) is searched for a command of that name.
|
||||
> No arg means to have no executable file and no symbols.
|
||||
> (gdb)
|
||||
>
|
||||
>
|
||||
|
||||
Για να δούμε τον κώδικα που έχουμε φορτώσει χρησιμοποιούμε τη εντολή **list**. Η εντολή έχει διάφορες μορφές. Χωρίς παραμέτρους εμφανίζει 10 γραμμές πηγαίου
|
||||
κώδικα γύρω από την τρέχουσα ή τις πρώτες 10 γραμμές αν το πρόγραμμα δεν εκτελείται.
|
||||
|
||||
> (gdb) list
|
||||
> 1 #include <stdio.h>
|
||||
> 2
|
||||
> 3 int main(int argc, char **argv)
|
||||
> 4 {
|
||||
> 5 int num;
|
||||
> 6
|
||||
> 7 if (argc<2) {
|
||||
> 8 printf("Usage: %s <number>\n",argv[0]);
|
||||
> 9 exit(1);
|
||||
> 10 }
|
||||
> (gdb)
|
||||
>
|
||||
>
|
||||
|
||||
Αν η **list** έχει μία παράμετρο τότε εμφανίζει 10 γραμμές κώδικα γύρω από αυτή ενώ μπορούμε να προσδιορίσουμε και ένα διάστημα ***list x,y***
|
||||
|
||||
> (gdb) list 8
|
||||
> 3 int main(int argc, char **argv)
|
||||
> 4 {
|
||||
> 5 int num;
|
||||
> 6
|
||||
> 7 if (argc<2) {
|
||||
> 8 printf("Usage: %s <number>\n",argv[0]);
|
||||
> 9 exit(1);
|
||||
> 10 }
|
||||
> 11
|
||||
> 12 num=alf(argv[1]);
|
||||
> (gdb) list 9,14
|
||||
> 9 exit(1);
|
||||
> 10 }
|
||||
> 11
|
||||
> 12 num=alf(argv[1]);
|
||||
> 13
|
||||
> 14 if (num>10)
|
||||
> (gdb)
|
||||
>
|
||||
>
|
||||
|
||||
#### Εκτέλεση
|
||||
|
||||
Αφού το πρόγραμμα έχει φορτωθεί μπορούμε να το εκτελέσουμε με την εντολή **run** ή **r**. Η **run** δέχεται ως παραμέτρους τα command-line arguments που θέλουμε
|
||||
να περάσουμε στο πρόγραμμα.
|
||||
|
||||
> (gbd) r
|
||||
> Starting program: /home/alf/temp/rce1
|
||||
> Usage: /home/alf/temp/rce1 <number>Program exited with code 01.
|
||||
> (gdb) r 42
|
||||
> Starting program: /home/alf/temp/rce1 42
|
||||
> Ok!
|
||||
> Program exited with code 04.
|
||||
> (gdb) r 3
|
||||
> Starting program: /home/alf/temp/rce1 3
|
||||
> Failed!
|
||||
> Program exited with code 07.
|
||||
> (gdb) r
|
||||
> Starting program: /home/alf/temp/rce1 3
|
||||
> Failed!
|
||||
> Program exited with code 07.
|
||||
>
|
||||
>
|
||||
|
||||
Παρατηρήστε ότι στην απλή **r** τα command-line arguments παραμένουν από την προηγούμενη εκτέλεση. Αυτά είναι αποθηκευμένα στην εσωτερική μεταβλητή του GDB
|
||||
\"args\". Υπάρχει μια πληθώρα από εσωτερικές μεταβλητές που μπορούν να προσπελαστούν με τις **show** και **set** (hint: μη ξεχνάτε το help\...).
|
||||
|
||||
> (gdb) show args
|
||||
> Argument list to give program being debugged when it is started is "3".
|
||||
> (gdb) set args 666 7
|
||||
> (gdb) r
|
||||
> Starting program: /home/alf/temp/rce1 666 7
|
||||
> Ok!
|
||||
> Program exited with code 04.
|
||||
> (gdb)
|
||||
>
|
||||
>
|
||||
|
||||
Βέβαια ως εδώ το μόνο που έχουμε κάνει είναι\... τίποτα! Τα ίδια και με πιο απλό τρόπο θα μπορούσαν να γίνουν από τo command line ενώ εμείς θέλουμε να ελέγχουμε
|
||||
το πρόγραμμα βήμα προς βήμα.
|
||||
|
||||
Για να γίνει αυτό, πρέπει να φροντίσουμε ο έλεγχος να επιστρέψει πίσω στον debugger όταν αρχίσει το πρόγραμμα. Για την ώρα δεχτείτε αυτή την εντολή χωρίς
|
||||
εξηγήσεις (λίγο υπομονή βρε παιδιά!)
|
||||
|
||||
> (gdb) break main
|
||||
> Breakpoint 1 at 0x8048466: file rce1.c, line 7.
|
||||
> (gdb) r
|
||||
> Starting program: /home/alf/projects/rce1
|
||||
>
|
||||
> Breakpoint 1, main (argc=1, argv=0xbffff7e4) at rce1.c:7
|
||||
> 7 if (argc<2) {
|
||||
> (gdb)
|
||||
>
|
||||
>
|
||||
|
||||
Αυτό που κάναμε ήταν να πούμε στον GDB να σταματήσει την εκτέλεση του προγράμματος όταν μπει στη συνάρτηση main. Τώρα είμαστε πριν την εκτέλεση της πρώτης
|
||||
εντολής της main και ο GDB περιμένει οδηγίες. Για να εκτελέσουμε την τρέχουσα εντολή χρησιμοποιούμε την εντολή **next** ή **n**:
|
||||
|
||||
> (gdb) next
|
||||
> 8 printf("Usage: %s <number>\n",argv[0]);
|
||||
> (gdb) n
|
||||
> Usage: /home/alf/projects/rce1 <number>9 exit(1);
|
||||
> (gdb) n
|
||||
>
|
||||
> Program exited with code 01.
|
||||
>
|
||||
>
|
||||
|
||||
Επειδή δεν περάσαμε παραμέτρους στο πρόγραμμα, το argc ήταν μικρότερο του 2 και εκτυπώθηκε ο τρόπος χρήσης του προγράμματος. Ας ξαναδοκιμάσουμε:
|
||||
|
||||
> (gdb) r 123
|
||||
> Starting program: /home/alf/projects/rce1 123
|
||||
>
|
||||
> Breakpoint 1, main (argc=2, argv=0xbffff7e4) at rce1.c:7
|
||||
> 7 if (argc<2) {
|
||||
> (gdb) n
|
||||
> 12 num=alf(argv[1]);
|
||||
> (gdb) n
|
||||
> 14 if (num>10)
|
||||
> (gdb) n
|
||||
> 15 printf("Ok!\n");
|
||||
> (gdb) n
|
||||
> Ok!
|
||||
> 18 }
|
||||
> (gdb) n
|
||||
> 0x4003abb4 in __libc_start_main () from /lib/libc.so.6
|
||||
> (gdb) n
|
||||
> Single stepping until exit from function __libc_start_main,
|
||||
> which has no line number information.
|
||||
>
|
||||
> Program exited with code 04.
|
||||
> (gdb)
|
||||
>
|
||||
>
|
||||
|
||||
Παρατηρήστε ότι μετά τη γραμμή 18 το πρόγραμμα δεν κάνει exit αλλά επιστρέφουμε σε μια συνάρτηση που ανήκει στην libc.so.6. Επειδή δεν έχουμε debugging
|
||||
πληροφορίες για αυτή, η **next** απλώς προχωράει μέχρι να τελειώσει η συνάρτηση. Αυτό που συμβαίνει ακριβώς είναι ότι με την **next** προχωράμε μια γραμμή
|
||||
κώδικα αλλά o GDB δεν έχει πληροφορίες για ποίες εντολές assembly αντιστοιχούν σε κάθε γραμμή, οπότε δεν ξέρει πόσο να προχωρήσει. H \_\_libc\_start\_main()
|
||||
είναι στην πραγματικότητα η πρώτη συνάρτηση που έχει κληθεί από το πρόγραμμα μας και έχει στόχο να αρχικοποιήσει την libc και μετά να καλέσει τη δική μας main
|
||||
(περισσότερα για αυτό στο επόμενο μέρος, όταν θα ασχοληθούμε με την assembly μορφή του κώδικα).
|
||||
|
||||
Αν ενώ είμαστε στον GDB θέλουμε να συνεχίσει κανονικά η εκτέλεση του προγράμματος μπορούμε να χρησιμοποιήσουμε την εντολή **continue** ή **c**. To πρόγραμμα
|
||||
συνεχίζει μέχρι να συναντήσει κάποιο breakpoint ή να τερματιστεί.
|
||||
|
||||
> (gdb) r 123
|
||||
> Starting program: /home/alf/projects/rce1 123
|
||||
> Breakpoint 1, main (argc=2, argv=0xbffff7e4) at rce1.c:7
|
||||
> 7 if (argc<2) {
|
||||
> (gdb) n
|
||||
> 12 num=alf(argv[1]);
|
||||
> (gdb) c
|
||||
> Continuing.
|
||||
> Ok!
|
||||
> Program exited with code 01.
|
||||
> (gdb)
|
||||
>
|
||||
>
|
||||
|
||||
Εκτός από την **next** υπάρχει και η **step** ή **s** η οποία κάνει ότι και η **next** με τη διαφορά ότι αν η τρέχουσα εντολή είναι κλήση συνάρτησης η **step**
|
||||
μπαίνει μέσα στον κώδικα της συνάρτησης.
|
||||
|
||||
> (gdb) r 123
|
||||
> Starting program: /home/alf/projects/rce1 123
|
||||
>
|
||||
> Breakpoint 1, main (argc=2, argv=0xbffff7e4) at rce1.c:7
|
||||
> 7 if (argc<2) {
|
||||
> (gdb) n
|
||||
> 12 num=alf(argv[1]);
|
||||
> (gdb) s
|
||||
> alf (s=0xbffff94f "123") at rce1.c:25
|
||||
> 25 return atoi(s);
|
||||
> (gdb) n
|
||||
> 26 }
|
||||
> (gdb) n
|
||||
> main (argc=2, argv=0xbffff7e4) at rce1.c:14
|
||||
> 14 if (num>10)
|
||||
> (gdb) c
|
||||
> Continuing.
|
||||
> Ok!
|
||||
> Program exited with code 01.
|
||||
> (gdb)
|
||||
>
|
||||
>
|
||||
|
||||
Ας δοκιμάσουμε μερικές ακόμη εντολές:
|
||||
|
||||
> (gdb) r 123 abc
|
||||
> Starting program: /home/alf/projects/rce1 123 abc
|
||||
>
|
||||
> Breakpoint 1, main (argc=2, argv=0xbffff7e4) at rce1.c:7
|
||||
> 7 if (argc<2) {
|
||||
> (gdb) print argc
|
||||
> $1 = 3
|
||||
> (gdb) set argc=6
|
||||
> (gdb) print argc
|
||||
> $2 = 6
|
||||
> (gdb) set argc=argc-2
|
||||
> (gdb) print argc
|
||||
> $3 = 4
|
||||
>
|
||||
>
|
||||
|
||||
Παραπάνω είδαμε δύο σημαντικές εντολές για να εξετάζουμε δεδομένα, την **print** και την **set** (η οποία όπως είδαμε χρησιμοποιείται και για εσωτερικές
|
||||
μεταβλητές). Είναι πολύ βασικό να σημειωθεί πως ό,τι ακολουθεί τις **print** και **set** είναι έκφραση της C, γεγονός που μας δίνει ιδιαίτερη ευελιξία O GDB
|
||||
αναγνωρίζει αυτόματα τον τύπο της έκφρασης και παρουσιάζει τα δεδομένα με τον κατάλληλο τρόπο.
|
||||
|
||||
> (gdb) print &argc
|
||||
> $4 = (int *) 0xbffff790
|
||||
> (gdb) print &argc + 1
|
||||
> $5 = (int *) 0xbffff794
|
||||
> (gdb) print (char *)&argc + 1
|
||||
> $6 = 0xbffff791 ""
|
||||
>
|
||||
>
|
||||
|
||||
Στην πρώτη εντολή λέμε στον GDB να τυπώσει την διεύθυνση της μεταβλητής argc. Το αποτέλεσμα της δεύτερης εντολής ίσως να φαίνεται λίγο παράξενο. Πολλοί θα
|
||||
περίμεναν να είναι 0xbffff791. Επειδή η argc είναι τύπου int που στη συγκεκριμένη περίπτωση είναι 4 bytes το &argc + 1 δείχνει 4 bytes μπροστά. Γενικά, αν p
|
||||
είναι δείκτης σε τύπο Τ, το p + n δείχνει στη θέση μνήμης p+n\*sizeof(T) ( εδώ &argc + 1\*sizeof(int) ). Αν κάνουμε cast το &argc σε (char \*) το αποτέλεσμα
|
||||
είναι το αναμενόμενο, διότι ο char είναι εξ ορισμού 1 byte.
|
||||
|
||||
> (gdb) print argv[1]
|
||||
> $7 = 0xbffff94a "123"
|
||||
> (gdb) print argv[2]
|
||||
> $8 = 0xbffff94d "abc"
|
||||
> (gdb) print argv[0]
|
||||
> $9 = 0xbffff932 "/home/alf/projects/rce1"
|
||||
>
|
||||
>
|
||||
|
||||
Ο GDB αναγνωρίζει πως οι μεταβλητές πρόκειται για strings (char \*) και εμφανίζει το περιεχόμενο τους. Ας παίξουμε λίγο με τα strings :)
|
||||
|
||||
> (gdb) set argv[1]="555"
|
||||
> (gdb) print argv[1]
|
||||
> $10 = 0x8049588 "555"
|
||||
>
|
||||
>
|
||||
|
||||
Παρατηρείστε πως ο GDB έκανε μία σοφή κίνηση: δέσμευσε μόνος του χώρο για το καινούργιο string και άλλαξε τον δείκτη argv\[1\] να δείχνει στον καινούργιο χώρο.
|
||||
O παλιός έμεινε όπως είναι:
|
||||
|
||||
> (gdb) print (char *)0xbffff94a
|
||||
> $11 = 0xbffff94a "123"
|
||||
>
|
||||
>
|
||||
|
||||
#### Breakpoints
|
||||
|
||||
Μετά από όλα αυτά, ήρθε επιτέλους η ώρα να ασχοληθούμε με ένα από τα πιο σημαντικά στοιχεία ενός debugger, τα breakpoints. Όπως δηλώνει και το όνομα τους είναι
|
||||
σημεία στον κώδικα όπου διακόπτεται η εκτέλεση και ο έλεγχος επιστρέφει στον debugger. H βασική εντολή στον GDB για να τεθεί ένα BP είναι η **break** ή **b**.
|
||||
Δέχεται (στη βασική της μορφή) μία παράμετρο: το σημείο όπου θα διακοπεί η εκτέλεση. Η παράμετρος έχει τις εξής μορφές:
|
||||
|
||||
- 1\. Το αρχείο(προαιρετικά) και τη γραμμή του πηγαίου κώδικα \[file:\]line
|
||||
- 2\. Το όνομα μιας συνάρτησης πχ main
|
||||
- 3\. Μια θέση μνήμης πχ \*0x8048560 (προσέξτε το \'\*\')
|
||||
|
||||
Χρήσιμες εντολές για τα BPs είναι η **info break** η οποία είναι εμφανές τι κάνει :), η **delete \[n\]** η οποία σβήνει το BP \#n (η όλα αν δεν προσδιορίσουμε
|
||||
αριθμό), η **disable \[n\]** η οποία απενεργοποιεί προσωρινά το BP \#n (η όλα\...) και η αντίθετη της, η **enable \[n\]**.
|
||||
|
||||
> bash$ gdb rce1
|
||||
> (gdb) break main
|
||||
> Breakpoint 1 at 0x804839c: file rce1.c, line 7.
|
||||
> (gdb) break alf
|
||||
> Breakpoint 2 at 0x804840c: file rce1.c, line 25.
|
||||
> (gdb) info break
|
||||
> Num Type Disp Enb Address What
|
||||
> 1 breakpoint keep y 0x0804839c in main at rce1.c:7
|
||||
> 2 breakpoint keep y 0x0804840c in alf at rce1.c:25
|
||||
> (gdb) disable 1
|
||||
> (gdb) info break
|
||||
> Num Type Disp Enb Address What
|
||||
> 1 breakpoint keep n 0x0804839c in main at rce1.c:7
|
||||
> 2 breakpoint keep y 0x0804840c in alf at rce1.c:25
|
||||
> (gdb) r 1
|
||||
> Starting program: /home/alf/projects/rce1 1
|
||||
>
|
||||
> Breakpoint 2, alf (s=0xbffff951 "1") at rce1.c:25
|
||||
> 25 return atoi(s);
|
||||
> (gdb) n
|
||||
> 26 }
|
||||
> (gdb) n
|
||||
> main (argc=2, argv=0xbffff7e4) at rce1.c:14
|
||||
> 14 if (num>10)
|
||||
> (gdb) c
|
||||
> Continuing.
|
||||
> Failed!
|
||||
>
|
||||
> Program exited with code 01.
|
||||
> (gdb)
|
||||
>
|
||||
>
|
||||
|
||||
Μια εναλλακτική (και πολύ χρήσιμη) μορφή της **break** είναι η **break \... if expr**, με τη οποία η εκτέλεση διακόπτεται μόνο αν η έκφραση *expr* είναι αληθής.
|
||||
|
||||
> bash$ gdb rce1
|
||||
> (gdb) list 10
|
||||
> 5 int num;
|
||||
> 6
|
||||
> 7 if (argc<2) {
|
||||
> 8 printf("Usage: %s <number>\n",argv[0]);
|
||||
> 9 exit(1);
|
||||
> 10 }
|
||||
> 11
|
||||
> 12 num=alf(argv[1]);
|
||||
> 13
|
||||
> 14 if (num>10)
|
||||
> (gdb) break 14 if (num==10)
|
||||
> Breakpoint 1 at 0x80483d7: file rce1.c, line 14.
|
||||
> (gdb) info break
|
||||
> Num Type Disp Enb Address What
|
||||
> 1 breakpoint keep y 0x080483d7 in main at rce1.c:14
|
||||
> stop only if num == 10
|
||||
> (gdb) r 4
|
||||
> Starting program: /home/alf/projects/rce1 4
|
||||
> Failed!
|
||||
>
|
||||
> Program exited with code 01.
|
||||
> (gdb) r 10
|
||||
> Starting program: /home/alf/projects/rce1 10
|
||||
>
|
||||
> Breakpoint 1, main (argc=2, argv=0xbffff7e4) at rce1.c:14
|
||||
> 14 if (num>10)
|
||||
> (gdb) c
|
||||
> Continuing.
|
||||
> Failed!
|
||||
>
|
||||
> Program exited with code 01.
|
||||
> (gdb)
|
||||
>
|
||||
>
|
||||
|
||||
Για να αλλάξουμε τη συνθήκη ενός breakpoint υπάρχει η εντολή **cond n \[expr\]** η οποία αλλάζει τη συνθήκη του BP \#n σε *expr*(ή τίποτα).
|
||||
|
||||
Επίσης είναι δυνατόν να καθορίσουμε μια σειρά από ενέργειες που θα εκτελούνται όταν \"χτυπάει\" ένα BP. Αυτό γίνεται με την
|
||||
|
||||
> commands n
|
||||
> list
|
||||
> end
|
||||
>
|
||||
>
|
||||
|
||||
Ένα δείγμα του τι δυνατότητες μας δίνει το σύστημα:
|
||||
|
||||
> (gdb) break 14 if (numi<=10)
|
||||
> Breakpoint 1 at 0x80483d7: file rce1.c, line 14.
|
||||
> (gdb) commands 1
|
||||
> Type commands for when breakpoint 1 is hit, one per line.
|
||||
> End with a line saying just "end".
|
||||
> >set num=13
|
||||
> >c
|
||||
> >end
|
||||
> (gdb) r 20
|
||||
> Starting program: /home/alf/projects/rce1 20
|
||||
> Ok!
|
||||
>
|
||||
> Program exited with code 01.
|
||||
> (gdb) r 3
|
||||
> Starting program: /home/alf/projects/rce1 3
|
||||
>
|
||||
> Breakpoint 1, main (argc=2, argv=0xbffff7e4) at rce1.c:14
|
||||
> 14 if (num>10)
|
||||
> Ok!
|
||||
>
|
||||
> Program exited with code 01.
|
||||
> (gdb)
|
||||
>
|
||||
>
|
||||
|
||||
Το breakpoint \"χτυπάει\" αλλά συνεχίζει αυτόματα, διότι η τελευταία εντολή στο command list είναι η **continue**. Καταφέραμε με αυτόν τον τρόπο να κάνουμε το
|
||||
πρόγραμμα να τυπώνει πάντα Ok!, ανεξάρτητα από την τιμή της παραμέτρου στη γραμμή εντολής! Βέβαια, αυτό γίνεται μόνο όταν τρέχουμε το πρόγραμμα μέσα από το GDB.
|
||||
Υπομονή μερικά τεύχη για μια καλύτερη λύση\...
|
||||
|
||||
Μια παραλλαγή είναι η **tbreak** (temporary breakpoint) που έχει ακριβώς την ίδια σύνταξη με την **break** αλλά εκτελείται μόνο μια φορά (γίνεται disabled
|
||||
μετά). Πρακτικά είναι ισοδύναμη με την ακολουθία:
|
||||
|
||||
> break xyz
|
||||
> commands 3 --> Αν υποθέσουμε πως το breakpoint είναι το #3
|
||||
> disable 3
|
||||
> end
|
||||
>
|
||||
>
|
||||
|
||||
#### Watchpoints
|
||||
|
||||
Τα watchpoints είναι breakpoints τα οποία δεν ενεργοποιούνται με κριτήριο την εκτέλεση μιας εντολής αλλά την αλλαγή μιας θέσης μνήμης. Για να θέσουμε ένα
|
||||
watchpoint χρησιμοποιούμε την εντολή **watch**!
|
||||
|
||||
> (gdb) watch num
|
||||
> No symbol "num" in current context.
|
||||
> (gdb) break main
|
||||
> Breakpoint 1 at 0x804839c: file rce1.c, line 7.
|
||||
> (gdb) r 11
|
||||
> Starting program: /home/alf/projects/rce1 11
|
||||
>
|
||||
> Breakpoint 1, main (argc=2, argv=0xbffff7e4) at rce1.c:7
|
||||
> 7 if (argc<2) {
|
||||
> (gdb) watch num
|
||||
> Hardware watchpoint 2: num
|
||||
> (gdb) c
|
||||
> Continuing.
|
||||
> Hardware watchpoint 2: num
|
||||
>
|
||||
> Old value = 1075130932
|
||||
> New value = 11
|
||||
> main (argc=2, argv=0xbffff7e4) at rce1.c:14
|
||||
> 14 if (num>10)
|
||||
> (gdb) c
|
||||
> Continuing.
|
||||
> Failed!
|
||||
>
|
||||
> Watchpoint 2 deleted because the program has left the block in
|
||||
> which its expression is valid.
|
||||
> 0x4003abb4 in __libc_start_main () from /lib/libc.so.6
|
||||
> (gdb) c
|
||||
> Continuing.
|
||||
>
|
||||
> Program exited with code 01.
|
||||
> (gdb)
|
||||
>
|
||||
>
|
||||
|
||||
Η πρώτη εντολή (**watch num**) απέτυχε διότι η *num* είναι τοπική μεταβλητή και έχει νόημα μόνο μέσα στη main(). Οπότε πρέπει να είμαστε στη main() για να
|
||||
αναφερθούμε σε αυτή. Τελικά ο GDB μας ενημέρωσε πως η μεταβλητή num άλλαξε τιμή σε 11. Παρατηρήστε πως ο έλεγχος γύρισε σε εμάς αμέσως μετά την εντολή που
|
||||
προκάλεσε την αλλαγή, η οποία προφανώς δεν είναι η if (num \< 10) αλλά η προηγούμενη num=alf(argv\[1\]) που δε φαίνεται πουθενά. Ύστερα ο GDB μας λέει πως το
|
||||
watchpoint διαγράφηκε. Αυτό έγινε διότι η *num* ως τοπική μεταβλητή αποθηκεύεται στο σωρό (stack) και μετά την έξοδο από τη συνάρτηση στην οποία βρισκόταν (τη
|
||||
main()) ο σωρός ελευθερώνεται (δε γίνεται ακριβώς έτσι, όταν εξετάσουμε τον κώδικα σε πιο χαμηλό επίπεδο θα δούμε την διαδικασία επακριβώς)
|
||||
|
||||
Παρόμοια με την **watch** είναι η **rwatch** η οποία ενεργοποιείται όχι σε αλλαγή της μνήμης αλλά σε απλή ανάγνωση.
|
||||
|
||||
> (gdb) break main
|
||||
> Breakpoint 1 at 0x804839c: file rce1.c, line 7.
|
||||
> (gdb) r 12
|
||||
> Starting program: /home/alf/projects/rce1 12
|
||||
>
|
||||
> Breakpoint 1, main (argc=2, argv=0xbffff7e4) at rce1.c:7
|
||||
> 7 if (argc<2) {
|
||||
> (gdb) rwatch num
|
||||
> Hardware read watchpoint 2: num
|
||||
> (gdb) c
|
||||
> Continuing.
|
||||
> Hardware read watchpoint 2: num
|
||||
>
|
||||
> Value = 12
|
||||
> 0x080483db in main (argc=2, argv=0xbffff7e4) at rce1.c:14
|
||||
> 14 if (num>10)
|
||||
> (gdb) c
|
||||
> Continuing.
|
||||
> Ok!
|
||||
>
|
||||
> Watchpoint 2 deleted because the program has left the block in
|
||||
> which its expression is valid.
|
||||
> 0x4003abb4 in __libc_start_main () from /lib/libc.so.6
|
||||
> (gdb) c
|
||||
> Continuing.
|
||||
>
|
||||
> Program exited with code 01.
|
||||
>
|
||||
>
|
||||
|
||||
Ουφφ! Τελειώσαμε\... για την ώρα :)\
|
||||
Αυτό το πρώτο άρθρο δεν είναι και πολύ hardcore RCE αλλά ήταν απαραίτητο ώστε να τεθούν κάποιες βάσεις για αυτά που θα ακολουθήσουν. Στο επόμενο άρθρο θα
|
||||
ασχοληθούμε με τη χρήση του GDB για assembly debugging και θα ρίξουμε μια πιο προσεκτική ματιά στα υπόλοιπα εργαλεία. Επίσης θα μιλήσουμε λίγο περισσότερο για
|
||||
τα breakpoints και πιο συγκεκριμένα για το πως αυτά υλοποιούνται σε χαμηλό επίπεδο.
|
||||
|
||||
|
||||
### [5. Πρόκληση 0]{#s5}
|
||||
|
||||
Σε κάθε άρθρο θα υπάρχει ένα πρόβλημα-πρόκληση για να ασχοληθούν όσοι επιθυμούν. Εδώ τα πράγματα είναι κάπως απλά (αλλά όχι πολύ) αφού το εκτελέσιμο είναι
|
||||
compiled με το -g flag, πρακτικά σας δίνω τον πηγαίο κώδικα δηλαδή. Πάντως είναι μια καλή ευκαιρία να ακονίσετε τα GDB skills και να πάρετε μια πρώτη γεύση από
|
||||
RCE!
|
||||
|
||||
Σκοπός της πρόκλησης είναι να βρείτε ποίος κωδικός αντιστοιχεί στο όνομα/ψευδώνυμο σας. Όποιοι θέλουν ας μου στείλουν τις απαντήσεις τους για να αναγραφούν στο
|
||||
hall of fame στο επόμενο άρθρο! Οι πρώτοι τρεις παίρνουν δώρο μια ετήσια συνδρομή στο magaz :P
|
||||
|
||||
πχ
|
||||
|
||||
> bash$ challenge0 -h
|
||||
> Magaz RCE Challenge 0
|
||||
> Use '-g' to load it into gdb
|
||||
>
|
||||
> bash$ challenge0 -g
|
||||
> (gdb)
|
||||
>
|
||||
> bash$ challenge0
|
||||
> Name: alf82
|
||||
> Password: 089s33k4das
|
||||
> Authentication failed!
|
||||
>
|
||||
> bash$ challenge0
|
||||
> Name: alf82
|
||||
> Password: 09d12iie78722
|
||||
> Authentication successful!
|
||||
>
|
||||
>
|
||||
|
||||
Μπορείτε να κατεβάσετε το εκτελέσιμο από [εδώ](./challenge0.bz2).
|
||||
|
||||
Στείλτε απαντήσεις, σχόλια, διορθώσεις, προσθήκες στο alf82 at freemail.gr. Καλό θα ήταν το subject του email να είναι της μορφής magaz-rce-\... ή κάτι τέτοιο,
|
||||
για να τα ξεχωρίζω εύκολα!
|
||||
|
||||
Καλό RCE!
|
||||
|
Φόρτωση…
Προσθήκη πίνακα
Προσθήκη υπερσυνδέσμου
Παράθεση σε νέο ζήτημα