سؤال

هل من الممكن كتابة C وظيفة أن يفعل ما يلي ؟

  1. تخصيص مجموعة من الذاكرة في كومة الذاكرة المؤقتة
  2. يكتب رمز الجهاز في ذلك
  3. ينفذ تلك الآلات تعليمات

بالطبع أود أن استعادة الدولة من كومة إلى ما كان عليه قبل تنفيذ تلك التعليمات الجهاز يدويا ، ولكن أريد أن أعرف إذا كان هذا ممكنا في المقام الأول.

هل كانت مفيدة؟

المحلول

انها بالتأكيد ممكن.لأسباب مختلفة ، لقد قضينا الكثير من الجهد من 30-40 عاما الماضية تحاول أن تجعل من الصعب قدر الإمكان ، ولكن من الممكن.في معظم نظم الآن هناك الأجهزة والبرامج والآليات التي تحاول حماية البيانات الفضاء من إعدامهم.

أساسيات, رغم أن, هي واضحة إلى حد ما:يمكنك بناء قطعة من التعليمات البرمجية ، وتجميعه ، إما باليد or4 عبر مترجم.ثم تحتاج جزء من التعليمات البرمجية الفضاء, لذلك يمكنك إدراج رمز في البرنامج

unsigned int prgm[] = { 0x0F, 0xAB, 0x9A ... };  // Random numbers, just as an example

منذ كنت تريد استخدام كومة تحتاج إلى malloc الفضاء

void * myspace ;
if((myspace= malloc(sizeof(prgm))) != NULL) {
     memcpy(myspace, pgrm, sizeof(pgrm));
} else { // allocation error
}

الآن, ما تحتاجه هو وسيلة للحصول على برنامج مكافحة أن نشير إلى أن جزءا من البيانات التي هي أيضا جزء من التعليمات البرمجية.هنا حيث كنت بحاجة إلى القليل من مكر.وضع عداد البرنامج ليس صفقة كبيرة;هذا مجرد القفز التعليمات الأساسية الخاصة بك آلة.ولكن كيف نفعل ذلك ؟

واحدة من أسهل الطرق هو هادف العبث مع المكدس.كومة مرة أخرى من الناحية النظرية ، يبدو شيئا من هذا القبيل (التفاصيل تعتمد على كل من نظام التشغيل الخاص بك و مترجم أزواج ، و على الأجهزة الخاصة بك):

    | subroutine return addr |
    | parameters ...         |
    | automatic variables    |

الأساسية الخدعة هنا هو أن خلسة الحصول على عنوان التعليمة البرمجية الخاصة بك إلى عودة العنوان ؛ عندما روتين يعود ذلك أساسا يقفز إلى أن عودة addrfess.إذا كان يمكنك وهمية بها, PC سيتم تعيين إلى حيث تريد.

لذا ما تحتاجه هو الروتين ، دعنا نسميها "goThere()"

void goThere(void * addr){
    int a ;     // observe above; this is the first space 
                // on the stack following the parameters
    int * pa;   // so we use it's address

    pa = (&a - (sizeof(int)+(2*sizeof(void*))) ;  // so use the address
                // but back up by the size of an int, the pointer on the
                // stack, and the return address
    // Now 'pa' points to the routine's return add on the stack.
    *pa = addr; // sneak the address of the new code into return addr
    return ;    // and return, tricking it into "returning"
                // to the address of your special code block
}

سوف يعمل ؟ ربما اعتمادا على الجهاز ونظام التشغيل.معظم نظام التشغيل الحديثة من شأنها حماية كومة (عبر خرائط الذاكرة أو ما شابه) من جهاز الكمبيوتر تتحرك فيه.هذا هو الشيء المفيد لأغراض أمنية لأننا كنا فقط وكذلك لا تمكنك من اتخاذ هذا النوع من السيطرة الكاملة.

نصائح أخرى

هذه هي مشابهة جدا هذا السؤال :)

قراءة كود الاتصال المخزنة في كومة من vc++.على posix, mprotect يبدو أن المناسبة (انظر إلى man mprotect):

char *mem = malloc(sizeof(code));
mprotect(mem, sizeof(code), PROT_READ|PROT_WRITE|PROT_EXEC);
memcpy(mem, code, sizeof(code));
// now arrange some code to jump to mem. But read the notes here on casting 
// from void* to a function pointer:
// http://www.opengroup.org/onlinepubs/009695399/functions/dlsym.html

ومع ذلك يقول:

سواء PROT_EXEC لديه أي تأثير مختلفة من PROT_READ هو العمارة و النواة التي تعتمد على الإصدار.على بعض الأجهزة (على سبيل المثال ، i386), PROT_WRITE يعني PROT_READ.

حتى أفضل, أولا التحقق ما إذا كان على نظام التشغيل الخاص بك, يعمل.

RE:يدويا إعادة المكدس

إذا كنت تتبع يدعو الاتفاقيات التي يستخدمها النظام الأساسي الخاص بك / برنامج التحويل البرمجي داخل الجهاز كود توليد, ثم يجب أن لا يكون لديك أي دليل المكدس استعادة.المترجم سوف نفعل ذلك لك عندما تفعل

*pfunc(وسائط)

يجب إضافة أي مناسبة قبل أو بعد استدعاء المكدس التلاعب الخطوات اللازمة.

فقط تأكد من أن لك اتبع الحق الاتفاقيات داخل التعليمات البرمجية التي تم إنشاؤها ذلك.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top