Site hosted by Angelfire.com: Build your free website today!

A Speech for the Imports

Messagebox Construction with no compilers... :)

by Black Shadow


Σε αυτό το tutorial θα σας εξηγήσω πως μπορείτε να προσθέσετε καινούριες λειτουργίες
(Imported Functions) στα προγράμματά σας φτιάχνοντάς τα όλα από την αρχή και να καλέσουμε με 
βάση τα ονόματά τους.


 
Εργαλεία:  Hex Workshop
 
Δυσκολία: Μέτριο - Προχωρημένο
 
Συνοδευτικά αρχεία: ΕΔΩ

    
Πρώτα από όλα να πούμε τις έννοιες που θα χρησιμοποιήσουμε για τον καθορισμό των διευθύνσεων.
Το RVA (Relative Virtual Address,  σχετική διεύθυνση μνήμης) είναι ίσο με το VA (Virtual Address, 
η διεύθυνση που θα βρίσκεται το αρχείο στην μνήμη μας) μείον Image Base(συνήθως 400000) και 
RAW η πραγματική διεύθυνση που θα βρίσκουμε όταν το αρχείο δεν είναι φορτωμένο, ξεκινώντας από 
τη αρχή του αρχείου. Το e_lfanew είναι χαρακτηριστικό “PE” που βρίσκεται σε όλα τα “έγκυρα” αρχεία.
Θα χρησιμοποιήσω το “DD” για να δηλώσω ότι το μέγεθός του είναι dword και το “DW” για το word 
και “DB” για το byte. Τώρα μπορούμε να ξεκινήσουμε!
 
 
 Import Directory
 
 
To Import Directory βρίσκεται στην θέση e_lfanew + 80h αποτελείται από το:
 
Virtual Address DD -> H RVA διεύθυνση που βρίσκεται το Image_Import_Descriptor 
 
Virtual Size DD -> To μέγεθος που καταλαμβάνει στην μνήμη 
 
 
 Import Address Table Directory 
 
To Import Address Table Directory βρίσκεται στην θέση e_lfanew + D8h αποτελείται από τα:
 
Virtual Address DD -> H RVA διεύθυνση που βρίσκεται η αρχή του Image_Thunk_Data
 
Virtual Size DD -> To μέγεθος που καταλαμβάνει στην μνήμη 
 
 
Αυτές οι δύο δομές παίζουν ρόλο για τα Imported Functions του αρχείου. Το Import Directory δείχνει
που βρίσκεται το Image_Import_Descriptor όταν το αρχείο φορτώνεται.Φυσικά μπορούμε να το
βρούμε σε αντιστοιχία και μέσα στο αρχείο όταν το ανοίγουμε με έναν editor. Είναι πολύ σημαντικό 
και υπάρχει σε κάθε αρχείο που έχει Imported Functions. Το Import Address Table Directory μπορεί 
και να μην υπάρχει κιόλας(μηδενισμένο) και δείχνει που βρίσκεται η αρχή του Image_Thunk_Data, 
που τις χρησιμοποιεί το FirstThunk που θα δούμε πιο κάτω.  
 
 
 
 Image_Import_Descriptor

Το Image_Import_Descriptor βρίσκεται εκεί που δείχνει το Import Directory και έχει μέγεθος 
ανάλογα με το τι γράφει το Import Directory που μιλήσαμε προηγουμένως. Εδώ είναι η καρδιά των
Imported Functions. Αποτελείται από τα: 

OriginalFirstThunk DD -> Η RVA διεύθυνση που δείχνει στη δομή του Image_Thunk_Data       
 
TimeDateStamp DD -> Εξαρτάται απο τον Linker και τον Builder που φτιάχτηκε το πρόγραμμα

ForwarderChain DD -> Χρησιμοποιείται για την αμφίδρομη επικοινωνία μεταξύ των DLLs

Name DD -> Η RVA διεύθυνση που δείχνει στο όνομα του DLL 

FirstThunk DD -> Η RVA διεύθυνση που δείχνει στην αντιγραφή της δομής του Image_Thunk_Data

Λοιπόν για κάθε ένα DLL που χρησιμοποιούμε έχουμε και μία δομή του Image_Import_Descriptor. Το 
OriginalFirstThunk και το FirstThunk δείχνουν στην ομάδα των Image_Thunk_Data των αντίστοιχων
Imported Function του αντίστοιχου DLL που δείχνει το Name. Το OriginalFirstThunk μπορεί και 
να μην υπάρχει(μηδενισμένο) και το πρόγραμμα να "τρέχει" κανονικά. Υπάρχουν δύο αντιγραφές των
Image_Thunk_Data, η μία ομάδα (που δείχνει το OriginalFirstThunk)δείχνει στα ονόματα των
Imported Functions όταν το πρόγραμμα είναι φορτωμένο στη μνήμη και η άλλη (που δείχνει το
FirstThunk) αντικαθιστώνται με τις πραγματικές διευθύνσεις των Imported Functions. Η δομή αυτή 
τελειώνει με πέντε μηδενικά dwords.
   

Image_Import_By_Name 



Το Image_Import_By_Name αποτελείται από τα :

Hint DW -> Όταν το Imported Function καλείται με βάση το ordinal του 
                   
Name DB -> Είναι το όνομα του Imported Function   

Για κάθε ένα Imported Function χρησιμοποιούμε και μία δομή. Εκεί θα δείχνει η αντίστοιχη 
δομή του Image_Thunk_Data. Κάθε όνομα τελειώνει με ένα μηδενικό DB.

Image_Thunk_Data


Το Image_Thunk_Data αποτελείται από το :

Virtual Address DD -> RVA διεύθυνση 



Εάν τα Imported Functions καλούνται με το όνομα τότε η διεύθυνση αυτή δείχνει που βρίσκεται το 
Image_Import_By_Name. Αλλιώς έχει το αντίστοιχο ordinal του Imported Function με την 
Image_Ordinal_Flag (η οποία είναι το Most Significan Bit) σηκωμένη.Μεταξύ των Image_Thunk_Data 
που αντιστοιχούν σε Imported Functions ξεχωριστών DLL τα χωρίζουμε με ένα μηδενικό dword και 
τελειώνει με αυτό.


Για να δούμε σχηματικά πως μπορούμε να καλέσουμε ένα Imported Function :

call [RVA(address)]
.
.
.
.
address:jmp[VA(FirstThunk's Image_Thunk_Data)]


Τώρα θα δούμε και πρακτικά πως μπορούμε να φτιάξουμε απο την αρχή τα δικά μας Imported Functions.
Για αυτό το λόγο έφτιαξα ένα προγραμματάκι χωρίς καθόλου Imports. Το μόνο που θέλουμε να κάνουμε
είναι να καλούμε ένα MessageBox και μετά να κλείνει. Το μόνο που έχω γράψει είναι το μήνυμα και
τις παραμέτρους του MessageBoxA. 

Πρώτα από όλα γράφουμε μέσα στο rdata section στην παρακάτω διεύθυνση τα ονόματα των Imported 
Functions που θέλουμε να χρησιμοποιήσουμε, μπροστά τους με ένα word(Hint) μηδενικό. Αυτή είναι η
δομή του Image_Import_By_Name.


00000CA0 0000 4D65 7373 6167 6542 6F78 4100 0045 ..MessageBoxA..E
00000CB0 7869 7450 726F 6365 7373 0000 0000 0000 xitProcess......


Τώρα σε μία άλλη διεύθυνση βάζουμε τους δείκτες που δείχνουν στα ονόματα των Imported Functions
μαζί με τα μηδενικά, επειδή τα καλούμε με τα ονόματά τους. Αυτή είναι η δομή του Image_Thunk_Data.
Μεταξύ τους έχουν ένα dword με μηδενικά επειδή ανήκουν σε ξεχωριστά DLL. Αυτή τη δομή θα τη 
χρησιμοποιήσει το FirstThunk και για αυτό θα φτιάξουμε άλλη μία για το OriginalFirstThunk. 
Οι διευθύνσεις είναι τα RVA γραμμένα με τη μορφή του Little Indian Addressing.


π.χ.  Little Indian A022 0000 -> RVA 0000 22A0 -> RAW 0000 0CA0 

 
00000BA0 A022 0000 0000 0000 AD22 0000 0000 0000 ."..............


Ορίστε...


00000B40 A022 0000 0000 0000 AD22 0000 0000 0000 ."......."......
Τώρα γράφουμε τα ονόματα των DLLs για τα αντίστοιχα Imported Functions που χρησιμοποιούμε. Εδώ θα δείχνουν τα Names των αντίστοιχων Image_Import_Descriptor. 00000CE0 4B65 726E 656C 3332 2E64 6C6C 0000 0000 Kernel32.dll....
00000CF0 5573 6572 3332 2E64 6C6C 0000 0000 0000 User32.dll......
Τώρα θα φτιάξουμε την δομή Image_Import_Descriptor. Το πρώτο dword είναι το RVA και δείχνει στη δομή του Image_Thunk_Data(MessageBoxA) του OriginalFirstThunk. Το επόμενα δύο dwords είναι το TimeDateStamp και το ForwarderChain. Είναι μηδενικά γιατί δεν μας ενδιαφέρουν. Το επόμενο dword είναι το Name του DLL (User32.dll) και το επόμενο dword είναι το RVA και δείχνει στη δομή του Image_Thunk_Data(MessageBoxA) του FirstThunk. Τα αντίστοιχα είναι για το επόμενο Imported Function (ExitProcess). Δημιουργήσαμε δύο δομές γιατί έχουμε δύο διαφορετικά DLLs. Η δομή αυτή τελειώνει με πέντε μηδενικά dwords. 00000C30 4021 0000 0000 0000 0000 0000 F022 0000 @!..........."..
00000C40 A021 0000 4821 0000 0000 0000 0000 0000 .!..H!..........
00000C50 E022 0000 A821 0000 0000 0000 0000 0000 ."...!..........
00000C60 0000 0000 0000 0000 0000 0000 ............
Αφού τελειώσουμε με αυτά πάμε να φτιάξουμε τις διευθύσεις του Import Directory και του Import Address Table. Το e_lfanew(PE) βρίσκεται στη θέση RAW offset 0Α8h οπότε έχουμε : Import Directory βρίσκεται στην θέση e_lfanew + 80h = 128h Δείχνει στην αρχή του Image_Import_Descriptor και έχει μέγεθος 30h Import Address Table Directory βρίσκεται στην θέση e_lfanew + D8h = 180h Δείχνει στην αρχή του Image_Thunk_Data του FirstThunk και έχει μέγεθος 10h 00000120 0000 0000 0000 0000 3022 0000 3000 0000 ........0"..0...
00000130 0000 0000 0000 0000 0000 0000 0000 0000 ................
00000140 0000 0000 0000 0000 0000 0000 0000 0000 ................
00000150 0000 0000 0000 0000 0000 0000 0000 0000 ................
00000160 0000 0000 0000 0000 0000 0000 0000 0000 ................
00000170 0000 0000 0000 0000 0000 0000 0000 0000 ................
00000180 A021 0000 1000 0000 0000 0000 0000 0000 .!..............

 Αυτό ήταν!!! Τώρα έχουμε να κάνουμε με τον προγραμματισμό...
 
Είχα γράψει κάποιες εντολές που έχουν σχέση με το MessageBoxA και το μόνο που μας λείπει είναι
τα calls. Οπότε γράφουμε τις παρακάτω εντολές :





Αυτό ήταν!!!




Black Shadow
 
 

ΠΡΟΣΟΧΗ
 
Φυσικά δεν χρειάζεται καν να σας θυμίσω πως το βοήθημα αυτό είναι αυστηρά 
για εκπαιδευτικούς σκοπούς και για την οποιαδήποτε λάθος χρήση τους ο 
δημιουργός του δεν φέρει καμία ευθύνη. Αν θέλετε έτοιμα cracks υπάρχουν
πολλά άλλα μέρη στο internet, εδώ παρέχουμε μόνο γνώση.

 

BACK HOME