Directx Δημοσ. 4 Ιανουαρίου 2012 Δημοσ. 4 Ιανουαρίου 2012 Δίχως περιστροφές, ότι κλειδώνει ξεκλειδώνει, το θέμα είναι πόσο δύσκολα, πόση εμπειρία, κέφι διάθεση και αποφασιστικότητα έχει εκείνος που θα θελήσει να κάνει reverse engineering αλλά και πόσες γνώσεις έχει εκείνος που κλειδώνει την εφαρμογή. Ως επί το πλείστο οι περισσότεροι καταλήγουν στην αγορά ή στην χρήση κάποιου ελεύθερου ή εμπορικού συστήματος ασφαλείας. Αν πρόκειται για Native κώδικα, αυτά τα συστήματα αλλοιώνουν την δομή του εκτελέσιμου καταστρέφοντας διάφορα κρίσιμα για την ανάλυση και επίθεση τμήματα του (πχ. Imports) ενώ παράλληλα συμπιέζουν και κρυπτογραφούν ή και διαγράφουν ύστερα από την πρώτη εκτέλεση διάφορα κομμάτια του λογισμικού ώστε να καταστήσουν διάφορες τεχνικές επαναφοράς του δύσκολες ως "αδύνατες". Ταυτόχρονα αφιερώνουν ένα πολύ μεγάλο μέρος των τεχνικών τους σε διάφορα τρικ με σκοπό να μπλοκάρουν, να μπερδέψουν ή τέλος πάντων να κουράσουν τον Debugger σου (self-modifing code, ώστε και ο disassembler να μην βοηθά ιδιαίτερα κλπ). Αν πρόκειται για Managed κώδικα, συνήθως τα συστήματα αυτά αναδιατάσσουν τον κώδικα ώστε να τον καταστήσουν όσο το δυνατόν πιο δυσνόητο (μετονομάζουν classes σε τυχαία ονόματα, κάνουν ελεεινό optimize στον κώδικα για να μην βγαίνει άκρη -καμία φορά το ίδιο το εκτελέσιμο παύει να δουλεύει σωστά από την τόση κακοποίηση! κλπ) ή μη συμβατό με διάφορους Managed disassembler. Και οι δυο τεχνικές μπορούν υπό συνθήκες να παραβιαστούν, αφού για κάθε μέτρο υπάρχει και ένα αντίμετρο και υπάρχουν σύγχρονα εργαλεία που αυτοματοποιούν τέτοιες διαδικασίες (συνήθως) - τώρα αν απλά πα να γράψει μόνος του κάποια ρουτίνα προστασίας δίχως εμπειρία (αλλά και με εμπειρία) .. .. δεν έχει και πολλές πιθανότητες. Αν θέλει πραγματική προστασία και το πρόγραμμα του φίλου σου αξίζει την επένδυση (διότι πρόκειται για επένδυση) θα πρέπει να δει HASP λύσεις και αυτές αφού εντρυφήσει στο πως λειτουργούν διότι αν πάει να τις χρησιμοποιήσει σε αυτόματο mode προστασίας θα έχει ενδεχομένως πρόβλημα. Τέλος πολύ σημαντικό είναι και το πόσο δημοφιλές ή ιδιόρρυθμο είναι το πρόγραμμα του ώστε να τραβήξει τα ανάλογα βλέμματα λόγο ζήτησης ώστε να χρειασθεί να αναλωθεί πολύ σε ζητήματα ασφαλείας (δίχως αυτό να σημαίνει ότι δεν πρέπει να βάλει κάποιο License System).
taazz Δημοσ. 4 Ιανουαρίου 2012 Δημοσ. 4 Ιανουαρίου 2012 Αλλο πραμα κατεβασα ενα σπασμενο φοτοσοπ στο σπιτι και αλλο πραμα κατεβασα ενα σπασμενο φοτοσοπ στην εταιρια. Εχει πολυ μεγαλη διαφορα, στο κατω κατω ποια εταιρια εχει σπασμενα προγραμματα στην Ελλαδα; Καμια! Σε όλες τις εταιρίες που δούλεψα υπήρχαν, αλλού μικρές αλλού μεγάλες, παρανομίες. Πχ. Εταιρία ανάπτυξης λογισμικού. Αγοράζει 1 ακριβή αδεια χρήσης εργαλείου ανάπτυξης, 1 φθηνή και έχει 8 προγραμματιστές να χρησιμοποιούν την ακριβή με βλέψεις για την αγορά 7 φθηνών ακόμα μέχρι το τέλος του έτους το οποίο και έκανε. Μονο τα μπουρδελα που θελουν να λεγονται και εταιριες. Και από πότε η νομιμότητα, οργάνωση και ηθική είναι μέρος του ορισμού της εταιρίας? Αν θες να το συζητήσουμε πάμε σε pm. Δεν βλέπω λόγο να χαλάμε το θέμα. Τελευταία ανάρτηση για το θέμα ζητώ συγνώμη για την παρεκτροπή.
Directx Δημοσ. 4 Ιανουαρίου 2012 Δημοσ. 4 Ιανουαρίου 2012 Για παράδειγμα, μια σχετικά απλή μέθοδος διαγραφής ενός τμήματος ενός προγράμματος από το ίδιο την ώρα που εκτελείται με άμεση μετατροπή του κώδικα του θα μπορούσε να γίνει κατά αυτό τον τρόπο: > // How to erase a defined PE block during runtime (self-modifying code), by XDir! // Written with C++ Builder.. #include <windows.h> #include <stdio.h> void _erase_me(void); int main(void) { /* Get PE base address */ DWORD baseAddr = GetModuleHandle(NULL), clnFromAddr = 0, clnToAddr = 0; /* Self access.. */ HANDLE hProc = OpenProcess(PROCESS_VM_READ|PROCESS_VM_WRITE|PROCESS_VM_OPERATION, FALSE, GetCurrentProcessId()); if(!hProc) fprintf(stderr, "OpenProcess error!\n"); else { BYTE byteBuffer, *ptrNilBuf = NULL; /* Function to erase */ _erase_me(); /* Search 0x91, 0x92, 0x93, 0x94 in PE memory */ for(;ReadProcessMemory(hProc, (void*)baseAddr, &byteBuffer, 1, NULL); baseAddr++) if(byteBuffer == 0x91) { BYTE byteMemSig[4]; DWORD dwByteRead; if(ReadProcessMemory(hProc, (void*)baseAddr, &byteMemSig, 4, &dwByteRead) && dwByteRead == 4 && byteMemSig[0] == 0x91 && byteMemSig[1] == 0x92 && byteMemSig[2] == 0x93 && byteMemSig[3] == 0x94) if(!clnFromAddr) clnFromAddr = baseAddr; else clnToAddr = baseAddr + 4; } /* Function address */ printf("From: %x\nTo :%x\n", clnFromAddr, clnToAddr); /* Clean memory.. */ for(byteBuffer = 0x90 ; clnFromAddr < clnToAddr; clnFromAddr++) if(!WriteProcessMemory(hProc, (void*)clnFromAddr, &byteBuffer, 1, NULL)) fprintf(stderr, "WriteProcessMemory error!\n"); CloseHandle(hProc); } return 0; } /* Function to erase after first run */ void _erase_me(void) { int I; goto execute; /* Goto saves the day ;-) */ /* Code to erase starts from here */ __emit__(0x91, 0x92, 0x93, 0x94); execute: for(I = 0; I < 10; I++) printf("Erase me!\n"); goto exit; /* Up to here.. */ __emit__(0x91, 0x92, 0x93, 0x94); exit: } Το τρικ είναι ότι μαρκάρουμε τα σημεία του PE Image που επιθυμούμε να διαγράψουμε (στην περίπτωση μας πρόκειται για οτιδήποτε υπάρχει μεταξύ των 0x91 - 94 -τα παράγω απευθείας στον κώδικα μέσο της εντολής του compiler __emit__ και τα ξεπερνώ μέσο "goto") και ύστερα με την βοήθεια των ReadProcessMemory & WriteProcessMemory που προσφέρει το Windows API προβαίνουμε στην διαγραφή τους (πχ. με 0x90 δηλαδή NOP) σκανάροντας από την αρχή (base-address) του φορτωμένου PE image μας (βλ. GetModuleHandle). Το αποτέλεσμα σε πρώτη φάση είναι η εκτέλεση της ρουτίνας _erase_me(); όπως φαίνεται στο listing του OllyDbg: Ενώ στην δεύτερη φάση τα περιεχόμενα της ρουτίνας έχουν πλέον αφαιρεθεί με τα NOP μου: Φυσικά τέτοιου είδους κώδικας μπορεί να μην λειτουργεί μεταξύ μεταφραστών ακόμα και της ίδιας εταιρίας διότι παίζουν πολλά πολλά πράματα, αλλά είναι ενδεικτικός για να πάρετε μια ιδέα σχετικά με ορισμένες μεθόδους προστασίας πάντα συνδυασμένες μεταξύ τους (διότι σκόρπια δεν βοηθούν).
defacer Δημοσ. 5 Ιανουαρίου 2012 Δημοσ. 5 Ιανουαρίου 2012 Για παράδειγμα, μια σχετικά απλή μέθοδος διαγραφής ενός τμήματος ενός προγράμματος από το ίδιο την ώρα που εκτελείται με άμεση μετατροπή του κώδικα του θα μπορούσε να γίνει κατά αυτό τον τρόπο: Μέχρι που κάνεις memory dump και βλέπεις ότι το text της process δεν είναι ίδιο με το image στο δίσκο, οπότε μετά απλά βάζεις ένα watchpoint στις συγκεκριμένες περιοχές μνήμης, βρίσκεις τον κώδικα που πάει να κάνει τον έξυπνο και του κάνεις τη μούρη NOP για το ειρωνικό της υπόθεσης. Όπως πολύ καλά λες, δεν έχει νόημα να συζητάμε για σκόρπιες τεχνικές.
Directx Δημοσ. 5 Ιανουαρίου 2012 Δημοσ. 5 Ιανουαρίου 2012 [..] Όπως πολύ καλά λες, δεν έχει νόημα να συζητάμε για σκόρπιες τεχνικές. [..]Φυσικά τέτοιου είδους κώδικας μπορεί να μην λειτουργεί μεταξύ μεταφραστών ακόμα και της ίδιας εταιρίας διότι παίζουν πολλά πολλά πράματα, αλλά είναι ενδεικτικός για να πάρετε μια ιδέα σχετικά με ορισμένες μεθόδους προστασίας πάντα συνδυασμένες μεταξύ τους (διότι σκόρπια δεν βοηθούν). Σκόρπιες ή μη κάτι μένει και ίσως για κάποιους αποτελέσει έναυσμα για περαιτέρω ψάξιμο, αυτός ήταν ο αντικειμενικός στόχος της ανάρτησης. Συγκεκριμένα, το "σκόρπια" πάει στο ότι από μόνη της δεν μπορεί να βοηθήσει αποτελεσματικά - αλλά φτάνει για να δει κάποιος που έχει διάθεση "το πως" λειτουργεί (απομυθοποίηση μιας τεχνικής) και αν θέλει το/την προχωρά περισσότερο μόνος του μετά κλπ πάντα με γνώμονα ότι "ότι κλειδώνει - ξεκλειδώνει".
Προτεινόμενες αναρτήσεις
Δημιουργήστε ένα λογαριασμό ή συνδεθείτε για να σχολιάσετε
Πρέπει να είστε μέλος για να αφήσετε σχόλιο
Δημιουργία λογαριασμού
Εγγραφείτε με νέο λογαριασμό στην κοινότητα μας. Είναι πανεύκολο!
Δημιουργία νέου λογαριασμούΣύνδεση
Έχετε ήδη λογαριασμό; Συνδεθείτε εδώ.
Συνδεθείτε τώρα