Axelfc Δημοσ. 28 Δεκεμβρίου 2006 Δημοσ. 28 Δεκεμβρίου 2006 Αυτο που θελω να κανω ειναι ενα προγραμμα το οποιο οταν θα εκτελειται θα βγαζει ενα μηνυμα στην οθονη και συγχρονως θα δημιουργει ενα καινουργιο αρχειο exe. Οταν κλεισω το πρωτο προγραμμα και εκτελεσω το δευτερο θελω αυτο με τη σειρα του να βγαζει ενα αλλο μηνυμα. Το προβλημα ειναι πως με τον παρακατω κωδικα που εχω γραψει και τα δυο προγραμματα τυπωνουν και τα δυο μηνυματα. Ξερει κανεις αν/πως μπορει να γινει αυτο που ψαχνω? Γενικοτερα μπορω με καποιο τροπο να ορισω τις εντολες που θελω να εκτελουνται απο το πρωτο προγραμμα και τις εντολες που θα εκτελουνται απο το δευτερο? Οριστε και ο κωδικας > #include <windows.h> #include <iostream.h> void main() { cout << "1: Initial program...\n"; char currentDir[MAX_PATH]; char pathtofile[MAX_PATH]; HMODULE GetModH = GetModuleHandle(NULL); GetModuleFileName(GetModH,pathtofile,sizeof(pathtofile)); GetCurrentDirectory(MAX_PATH,currentDir); strcat(currentDir,"\\newProgram.exe"); cout << "2: newProgram\n"; CopyFile(pathtofile,currentDir,false); cout << "Press enter to close...\n"; cin.get(); }
Directx Δημοσ. 28 Δεκεμβρίου 2006 Δημοσ. 28 Δεκεμβρίου 2006 Δεν είμαι σίγουρος τι προσπαθείς να κάνεις .. Για παράδειγμα, θέλεις να περάσεις κάποιες παραμέτρους στο αντίγραφο του εαυτού σου ώστε να καταλάβει πως έχει μπει σε δεύτερη φάση εκτέλεσης (το θέτω όπως-όπως καταλαβαίνεις τι εννοώ ) - αν ναι, δες την ShellExecute ή ShellExecuteEx ώστε να τις περάσεις και συνάμα άλλαξε το main σε main(int argc,char *argv[]) για να τις πιάσεις (μιας και το πρόγραμμα σου είναι Console δεν υπάρχει λόγος για άλλες WinAPI κλήσεις επ' αυτού του τελευταίου). Τώρα αν θες κάτι διαφορετικό γίνεται πιο συγκεκριμένος..
sanidas Δημοσ. 28 Δεκεμβρίου 2006 Δημοσ. 28 Δεκεμβρίου 2006 Εάν κατάλαβα καλά αυτό που χρειάζεσαι είναι να δημιουργείς ένα αρχείο .cpp και έπειτα στο run time να μπορείς να το κάνεις compile το αρχείο έτσι ώστε να δημιουργήσεις το .exe. Οπότε αρχικά δημιουργείς το αρχείο .cpp και πετάς μέσα τον κώδικα τον κώδικα του 2ου προγράμματος. Για παράδειγμα. AnsiString Temp=”#include<stdio.h> void main(void){ printf(“oeo”); getch()}”; FILE *fp; fp=fopen(“sanidas.cpp”,w); fprintf(fp,”%s”,Temp); fclose(fp); Έπειτα υπάρχει το σετ εντολών exec (execl,execv κτλ)που μπορείς να καλέσεις εξωτερικά applications. Για να κάνεις compile το sanidas.cpp πρέπει να καλέσεις την εντολή BCC32. Περισσότερες πληροφορίες για το BCC32 θα βρεις στο help της builder στα Command-line tools
dop Δημοσ. 28 Δεκεμβρίου 2006 Δημοσ. 28 Δεκεμβρίου 2006 Ουσιαστικά, θέλεις να αλλάξεις τα static data ενός αντιγράφου του εκτελέσιμού σου. Αυτό προϋποθέτει να δημιουργήσεις έναν binary parser που θα ψάχνει σε εκτελέσιμα για το αντίστοιχο μέρος των static data, θα αλλάζει το string και τα offset σε περίπτωση που έχεις και άλλα αντικείμενα στον static χώρο. Πχ, στον κώδικα αν κάνεις cout << "Hello" << a << "there"; και προσπαθήσεις να αλλάξεις το "Hello" σε κάτι άλλο, πρέπει να αλλάξεις και κάθε reference στο "there" αφού στον static χώρο εμφανίζονται σαν Hello\0there\0 και στις συναρτήσεις δίνονται διευθύνσεις. Κάτι τέτοιο δεν είναι απλό.
Axelfc Δημοσ. 28 Δεκεμβρίου 2006 Μέλος Δημοσ. 28 Δεκεμβρίου 2006 Ας εξηγησω λιγο αναλυτικοτερα αυτο που προσπαθω να κανω. Εχω τον κωδικα του 1ου μου post, ας πουμε με ονομα initialProgram.cpp. Το κανω compile και το τρεχω. Τοτε θα εκτυπωθουν στην οθονη τα δυο cout και συγχρονως θα δημιουργηθει στον τρεχον φακελο ενα καινουργιο αρχειο με ονομα newProgram.exe. Τερματιζω το initialProgram.exe και τρεχω το καινουργιο newProgram.exe. Αυτο με τη σειρα του θα εκτυπωσει τα παραπανω δυο cout. Αυτο που θελω να κανω, (δεν ξερω καν αν γινεται, δεν βρηκα κατι και στο google γι'αυτο ρωταω εδω) ειναι το initialProgram.exe να εκτυπωνει μονο το 1ο cout και να δημιουργει το newProgram.exe ενσωματωνοντας του το 2ο cout ωστε να εκτελεστει οταν τρεξω το καινουργιο προγραμμα. Δεν εχει να κανει δλδ με χρηση αρχειων, fopen, η κληση εξωτερικων προγραμματων, shellExecute. Ισως αυτο που λεει ο dop να εχει καποια σχεση, αν καταλαβα καλα. Ευχαριστω για τις απαντησεις οπως και να εχει.
Directx Δημοσ. 28 Δεκεμβρίου 2006 Δημοσ. 28 Δεκεμβρίου 2006 Θα πρέπει να αλλάξει όχι μόνο τα static data αλλά να ξεφωρτοθείς και το άχρηστο δεύτερο cout σαν κλήση, οπότε ενδεχομένως θα πρέπει να επέμβεις στον κώδικα μηχανής της εφαρμογής -δεν είναι ιδιαίτερα δύσκολο (αν ακολουθήσεις ορισμένες συμβάσεις στην αρχική σχεδίαση) αλλά μπελαλίδικο..
dop Δημοσ. 28 Δεκεμβρίου 2006 Δημοσ. 28 Δεκεμβρίου 2006 Ίσως να μπορέσεις να το κάνεις, αν δημιουργήσεις κάτι σαν: > bool j = true; if (j) // call something else // call something else και να πείσεις τον compiler να μην το κάνει optimize - χρησιμοποιώντας volatile, κάνοντας compile με επιπλέον debugging πληροφορίες κλπ. Έπειτα απλώς θα αλλάξεις την τιμή σε false. Και πάλι όμως μπλέκεις με κώδικα μηχανής. @DirectX: αν βάλει ένα απλό jump, τελείωσε, δεν χρειάζεται να σβήσει κάτι. ΑΛΛΑ, πρέπει να αλλάξει όλες τις σχετικές διευθύνσεις μνήμης μέσα στο πρόγραμμα.
Axelfc Δημοσ. 28 Δεκεμβρίου 2006 Μέλος Δημοσ. 28 Δεκεμβρίου 2006 Βρεθηκε η λυση, περιπου οπως λες dop. Απλως κανω εναν ελεγχο αν το ονομα του προγραμματος που τρεχει ειναι το initial η το new και εκτελω αναλογα τον κωδικα που θελω. Οριστε και ο πηγαιος. > #include <windows.h> #include <iostream.h> int main() { char currentDir[MAX_PATH]; char pathtofile[MAX_PATH]; HMODULE GetModH = GetModuleHandle(NULL); GetModuleFileName(GetModH,pathtofile,sizeof(pathtofile)); if ( strstr( pathtofile, "newProgram.exe" ) != NULL ) { // be the new program cout << "2: newProgram!\n"; cout << "Press enter to close...\n"; cin.get(); } else { // be the old program cout << "1: Initial program...\n"; GetCurrentDirectory(MAX_PATH,currentDir); strcat(currentDir,"\\newProgram.exe"); CopyFile(pathtofile,currentDir,false); cout << "Press enter to close...\n"; cin.get(); } } Ευχαριστω ολους για τις απαντησεις!
Directx Δημοσ. 28 Δεκεμβρίου 2006 Δημοσ. 28 Δεκεμβρίου 2006 @DirectX: αν βάλει ένα απλό jump, τελείωσε, δεν χρειάζεται να σβήσει κάτι. ΑΛΛΑ, πρέπει να αλλάξει όλες τις σχετικές διευθύνσεις μνήμης μέσα στο πρόγραμμα. Πιο συμφέρουσες λοιπόν μερικές nop
Directx Δημοσ. 28 Δεκεμβρίου 2006 Δημοσ. 28 Δεκεμβρίου 2006 Το παρακάτω ενδεικτικό πρόγραμμα, γραμμένο σε Borland C/C++ Builder 6, αντιγράφει τον εαυτό του σε ένα νέο εκτελέσιμο (newProgam.exe) στο τρέχον κατάλογο και ύστερα επεμβαίνει στα δεδομένα της μεταβλητής szLine_A όπου αντικαθιστά τον πρώτο χαρακτήρα αλλαγής γραμμής (\n) με κενό του νέου αντίγραφου. Ύστερα σε δεύτερη φάση αλλάζει τον κώδικα !bSecond_Generation προσπερνώντας όλες τις προηγούμενες ρουτίνες ως το cout ομοίως. Ο λόγος που απλά δεν άλλαξα την default τιμή της bSecond_Generation είναι για να επιδειχθεί η αλλαγή του assembled κώδικα. > //-SELF MODIFY -STATIC & CODE PARTS------------------------------------------ #include <windows.h> #include <iostream> #pragma hdrstop using namespace std; #define DATA_OFFSET 0x14B2 #define CODE_OFFSET 0x788 //--------------------------------------------------------------------------- char szLine_A[100] = "This is line 1\nThis is line 2", szDestination[MAX_PATH]; BYTE byCode [6] = { 0xE9, 0xB5, 0, 0, 0, 0x90 }, byStatic[1] = { ' ' }; bool bSecond_Generation = false; //--------------------------------------------------------------------------- void _SelfModify(char *pszDestination,DWORD dwOffset,BYTE *pszNewData,DWORD dwLen); //--------------------------------------------------------------------------- #pragma argsused int main(int argc, char* argv[]) { try { if(!bSecond_Generation) { // Get current directory if(!GetCurrentDirectory(MAX_PATH,szDestination)) throw (char*)"Cannot find current directory!"; // Build Destination path lstrcat(szDestination,"\\newProgram.exe"); // Copy ourself to newProgram.exe if(!CopyFile(argv[0],szDestination,FALSE)) throw (char*)"Cannot create destination executable!"; // Apply changes to cout static data for second file version (or copy) _SelfModify(szDestination,DATA_OFFSET,byStatic,sizeof(byStatic)); // Change execution flow for newProgram.exe so it won't CopyFile.. _SelfModify(szDestination,CODE_OFFSET,byCode,sizeof(byCode)); } // Print out Lines cout << szLine_A << endl; } catch(char* pszError) { cout << "Exception:" << pszError << endl; } return 0; } //--------------------------------------------------------------------------- void _SelfModify(char *pszDestination,DWORD dwOffset,BYTE *pszNewData,DWORD dwLen) { HANDLE hIO = INVALID_HANDLE_VALUE; DWORD dwWrittenBytes; try { // 1st] Open pszDestination for Read/Write if((hIO=CreateFile(pszDestination,GENERIC_READ|GENERIC_WRITE, 0,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL, NULL))==INVALID_HANDLE_VALUE) throw (char*)"Cannot open destination file for read/write!"; // 2nd] Check Offset validity if(GetFileSize(hIO,NULL)<dwOffset) throw (char*)"Invalid destination file offset!"; // 3rd] Seek Destination offset for manipulation if(SetFilePointer(hIO,dwOffset,NULL,FILE_BEGIN)==0xFFFFFFFF) throw (char*)"Unable to seek destination file offset!"; // 4th] Modify static data if(!WriteFile(hIO,pszNewData,dwLen,&dwWrittenBytes,NULL)) throw (char*)"Cannot write destination file modified data!"; } __finally { // Either case get rid of CreateFile stream CloseHandle(hIO); } } Οι θέσεις μνήμης μεταβλητής και κώδικα, όσο και το μέγεθος των αρχικών op'codes, φυσικά μπορεί να διαφέρουν με βάση τις ρυθμίσεις του C/C++ Builder Compiler/IDE σας (για dis-assembling προτείνω τον IDA freeware edition) -φυσικά αν έχουμε κέφια μπορούμε να γράψουμε ρουτίνες αυτόματου εντοπισμού τους λίγο πολύ σίγουρες. Τέλος ευτύχημα αποτελεί πως η οργάνωση του κώδικα σε 32bit εκτελέσιμα Windows (PE) είναι τέτοια που επιτρέπει εύκολο patching στην πλειονότητα των περιπτώσεων. Υ.Γ. Φυσικά, το λογισμικό μπορεί να περιέχει bugs.. Καλή Πρωτοχρονιά σε όλους!
Προτεινόμενες αναρτήσεις
Αρχειοθετημένο
Αυτό το θέμα έχει αρχειοθετηθεί και είναι κλειστό για περαιτέρω απαντήσεις.