वाह, यह मेरी अपेक्षा से बहुत अधिक दर्दनाक साबित हुआ। दर्द का 100% लिनक्स प्रोग्राम को अधिलेखित और/या डेटा निष्पादित करने से बचा रहा था।
नीचे दिखाए गए दो समाधान। और बहुत सारे गुगलिंग शामिल थे इसलिए कुछ सरल बाइट्स को कुछ सरल बाइट डालें और उन्हें निष्पादित किया गया था, पेज आकार पर mprotect और संरेखित Google खोजों से खींचा गया था, सामान मुझे इस उदाहरण के लिए सीखना था।
स्वयं संशोधित कोड सीधे आगे है, यदि आप प्रोग्राम लेते हैं या कम से कम केवल दो सरल कार्यों को संकलित करते हैं, संकलित करते हैं और फिर उन्हें अलग करते हैं तो आपको उन निर्देशों के लिए ऑपकोड मिलेंगे। या असेंबलर के ब्लॉक संकलित करने के लिए नासम का उपयोग करें, आदि। इससे मैंने ओपेक को तुरंत ईएक्स में लोड करने के लिए निर्धारित किया है।
आदर्श रूप से आप बस कुछ बाम में उन बाइट डालते हैं और उस राम को निष्पादित करते हैं। ऐसा करने के लिए लिनक्स प्राप्त करने के लिए आपको सुरक्षा को बदलना होगा, जिसका अर्थ है कि आपको इसे एक पॉइंटर भेजना होगा जो एमएमएपी पेज पर गठबंधन है। तो आपको अपनी आवश्यकता से अधिक आवंटित करें, पृष्ठ आवंटन पर उस आवंटन के भीतर गठबंधन पता ढूंढें और उस पते से mprotect करें और उस मेमोरी को अपने opcodes डालने के लिए उपयोग करें और फिर निष्पादित करें।
दूसरा उदाहरण प्रोग्राम में संकलित एक मौजूदा फ़ंक्शन लेता है, फिर से सुरक्षा तंत्र की वजह से आप इसे इंगित नहीं कर सकते हैं और बाइट्स को बदल सकते हैं, आपको इसे लिखने से असुरक्षित करना होगा। तो आपको संशोधित करने के लिए कोड को कवर करने के लिए उस पते और पर्याप्त बाइट्स के साथ पूर्व पृष्ठ सीमा कॉल mprotect तक बैक अप लेना होगा। फिर आप उस फ़ंक्शन के लिए बाइट्स/ऑपकोड को किसी भी तरह से बदल सकते हैं (जब तक आप किसी भी फ़ंक्शन में नहीं फैलते जिसे आप उपयोग करना जारी रखना चाहते हैं) और इसे निष्पादित करें। इस मामले में आप देख सकते हैं कि fun()
काम करता है, फिर मैं इसे एक मूल्य वापस करने के लिए बदलता हूं, इसे फिर से कॉल करता हूं और अब इसे संशोधित किया गया है।
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/mman.h>
unsigned char *testfun;
unsigned int fun (unsigned int a)
{
return(a+13);
}
unsigned int fun2 (void)
{
return(13);
}
int main (void)
{
unsigned int ra;
unsigned int pagesize;
unsigned char *ptr;
unsigned int offset;
pagesize=getpagesize();
testfun=malloc(1023+pagesize+1);
if(testfun==NULL) return(1);
//need to align the address on a page boundary
printf("%p\n",testfun);
testfun = (unsigned char *)(((long)testfun + pagesize-1) & ~(pagesize-1));
printf("%p\n",testfun);
if(mprotect(testfun, 1024, PROT_READ|PROT_EXEC|PROT_WRITE))
{
printf("mprotect failed\n");
return(1);
}
//400687: b8 0d 00 00 00 mov $0xd,%eax
//40068d: c3 retq
testfun[ 0]=0xb8;
testfun[ 1]=0x0d;
testfun[ 2]=0x00;
testfun[ 3]=0x00;
testfun[ 4]=0x00;
testfun[ 5]=0xc3;
ra=((unsigned int (*)())testfun)();
printf("0x%02X\n",ra);
testfun[ 0]=0xb8;
testfun[ 1]=0x20;
testfun[ 2]=0x00;
testfun[ 3]=0x00;
testfun[ 4]=0x00;
testfun[ 5]=0xc3;
ra=((unsigned int (*)())testfun)();
printf("0x%02X\n",ra);
printf("%p\n",fun);
offset=(unsigned int)(((long)fun)&(pagesize-1));
ptr=(unsigned char *)((long)fun&(~(pagesize-1)));
printf("%p 0x%X\n",ptr,offset);
if(mprotect(ptr, pagesize, PROT_READ|PROT_EXEC|PROT_WRITE))
{
printf("mprotect failed\n");
return(1);
}
//for(ra=0;ra<20;ra++) printf("0x%02X,",ptr[offset+ra]); printf("\n");
ra=4;
ra=fun(ra);
printf("0x%02X\n",ra);
ptr[offset+0]=0xb8;
ptr[offset+1]=0x22;
ptr[offset+2]=0x00;
ptr[offset+3]=0x00;
ptr[offset+4]=0x00;
ptr[offset+5]=0xc3;
ra=4;
ra=fun(ra);
printf("0x%02X\n",ra);
return(0);
}
http://linux.die.net/man/2/mprotect को यह समझाना चाहिए कि mprotect के लिए तर्क क्या हैं। कॉल करने के लिए फ़ंक्शन आईडी ईएक्स में पारित की जाती है और अगले तर्क ईबीएक्स ईसीएक्स और ईडीएक्स में पास किए जाते हैं। – KitsuneYMG