مقالنا اليوم يتكلم حول طرق سيئه “للغايه” لكتابه الكود بحيث لن يفهم هذا الكود الا القليل ، وهناك بعض الأسباب لعمل مثل هذه البرامج منها مثلا التسليه Fun ، التحدي ، حمايه كود البرنامج ، الفوز بمسابقه ما (هناك مسابقه عالميه تقام كل سنه حول هذا النوع من البرامج International Obfuscated C Code Contest ) .
أغلب هذه البرامج تكون مكتوبه بسي ، أو بيرل ، ونادرا ما نجد سي++ ، وذلك لأن سي تحتوي بعضا من الأمور قد تم تلافيها في سي++ ، منها مثلا استدعاء الداله main من داخل البرنامج .
أحب أن أذكر أن الطرق الموجوده هنا ، لا ينصح باستخدامها أبدا ، فهي طرق سيئه جدا ، وكما ذكرت فقط الغرض منها هو التشويش …
ولنأخذ مثال “فاتح للشهيه” قبل أن نبدأ بالطرق ، قم بقرائه المثال ، وفي حال فهمت المثال كاملا وعرفت المخرجات ، فسوف أجزم أنك أحد هؤلاء المجانين .
#include <stdio.h> main(t,_,a)char *a;{return!0<t?t<3?main(-79,-13,a+main(-87,1-_, main(-86,0,a+1)+a)):1,t<_?main(t+1,_,a):3,main(-94,-27+t,a)&&t==2?_<13? main(2,_+1,"%s %d %d\n"):9:16:t<0?t<-72?main(_,t, "@n'+,#'/*{}w+/w#cdnr/+,{}r/*de}+,/*{*+,/w{%+,/w#q#n+,/#{l,+,/n{n+,/+#n+,/#\ ;#q#n+,/+k#;*+,/'r :'d*'3,}{w+K w'K:'+}e#';dq#'l \ q#'+d'K#!/+k#;q#'r}eKK#}w'r}eKK{nl]'/#;#q#n'){)#}w'){){nl]'/+#n';d}rw' i;# \ ){nl]!/n{n#'; r{#w'r nc{nl]'/#{l,+'K {rw' iK{;[{nl]'/w#q#n'wk nw' \ iwk{KK{nl]!/w{%'l##w#' i; :{nl]'/*{q#'ld;r'}{nlwb!/*de}'c \ ;;{nl'-{}rw]'/+,}##'*}#nc,',#nw]'/+kd'+e}+;#'rdq#w! nr'/ ') }+}{rl#'{n' ')# \ }'+}##(!!/") :t<-50?_==*a?putchar(31[a]):main(-65,_,a+1):main((*a=='/')+t,_,a+1) :0<t?main(2,2,"%s"):*a=='/'||main(0,main(-61,*a, "!ek;dc i@bK'(q)-[w]*%n+r3#l,{}:\nuwloca-O;m .vpbks,fxntdCeghiry"),a+1);}
حاول أن تتخيل ما هي المخرجات قبل أن تقوم بتشغيله ، تخيل فقط !!
كيف تكتب برنامج مشوش ؟
هنا علينا أن نرجع الى بدايه تعلمنا للغه ونتذكر ما هي أصعب الأشياء التي واجهتنا في التعلم ، أذكر أنني جلست كم يوم حتى فهمت ما هو المؤشر Pointer ، مممم أيضا الأستدعاء الذاتي مربك أيضا ، أيضا المصفوفات وخاصه عندما نستخدم Pointer Arithmetic ، معامل الفاصله Comma مربك ايضا لان تنفيذه غريب بعض الشيء ، جميع المواضيع السابقه التي كنت تعتبرها صعبه ، هنا ستكون هي سلاحك الأول
أيضا المتغيرات ذات الشكل المتشابه مثلا الحرف O و الحرف o ( الأول كبير والثاني صغير ) و الرقم 0 ، أيضا الحرف i والحرف l والحرف L الرقم 1 ، هذه المتغيرات تسبب لي التشاؤم من البرنامج ، خاصه عندما كنت أقرأ برنامج أحد الطلاب ، وهذه أحد سطور أحد الطلاب :
char clear,ch,c,bag[100],bag1[10][10],bag2[100]; int n=0,m,x,w=0,aa=0,z,l=0,nn[50],mm[50],qw,az,i,j; // other code for(int fg=1;fg<=az;fg+=2) { if (nn[fg-1]==nn[fg]){ bag2[fg-1]=bag1[nn[fg-1]][(mm[fg-1]+1)%5]; bag2[fg]=bag1[nn[fg-1]][(mm[fg]+1)%5]; } else if(mm[fg-1]==mm[fg]){ bag2[fg-1]=bag1[(nn[fg-1]+1)%5][mm[fg-1]]; bag2[fg]=bag1[(nn[fg]+1)%5][mm[fg]]; } else {bag2[fg-1]=bag1[nn[fg-1]][mm[fg]]; bag2[fg]=bag1[nn[fg]][mm[fg-1]]; }}
يبدوا لي أن هذا الطالب يكتب برنامج Obfuscated بالفطره ، وأعتقد أنه سيفوز بمثل هذه المسابقات بكل سهوله 🙂 .
نبدأ الأن بقطع من الكود ، ونحاول أن نغيرها من كود عادي الى مشوش ، وبعدها نأخذ مثال Hello World ومن ثم نحوله الى Hello Devil .
التلاعب بأسماء المتغيرات :
نأخذ مثال لبرنامج يطبع الحروف من A الى Z ، ونقوم ببعض التغيرات عليه في اسامي المتغيرات :
#include <stdio.h> int main () { for (int i='A' ; i<='Z' ; i++) printf("%c",i); return 0; }
الان قمنا بوضع جمله الطباعه في داله ، ومررنا لها الحرف الأول والأخير ، ومن ثم طبعنا الحروف :
#include <stdio.h> void _(int O , int _O) { for ( ; O<=_O ; O++) printf("%c",O); } int main () { // you can change A with 65 in decimal OR with 0x41 in hex // olse you can change Z to 90 in decimal or 0x5A in hex _(0x41,90); return 0; }
لاحظ استخدام الحروف المشابه O و _O ، أيضا ارسال الحرف A بقيمته في النظام Hex ، ويمكن أستخدام أي نظام أخر .
(طبعا عليك بازاله التعليق من البرنامج ، وهو أصلا موضوع لك أنت ، حيث البرنامج المفترض يشوش القارئ وليس يشرح للقارئ).
التلاعب بالمؤشرات والمصفوفات :
مراجعه سريعه للأمر ، تجدها في هذه السطور :
printf("\n\n%d\n",arr[1]); // print 20 printf("%d\n",*(arr+1)); // print 20 printf("%d\n",*(1+arr)); // print 20 printf("Address = %x\n",&arr[1]); // print Address for element 1 printf("Address = %x\n",arr+1); // print Address for element 1
الأن كيف يمكن أن نتلاعب هنا ، كلنا نعرف أذا أردنا أن نرسل مصفوفه لداله نقوم بارسال عنوانها ، حسنا ، ممكن أن نضع هذا العنوان في متغير int أولا ، ونقوم بارسال هذا العدد (العنوان) ، الان من داخل المصفوفه نقوم بتحويل هذا العدد int الى مؤشر عن طرق الCast .
أنظر الى المثال القادم ، وهو لطباعه الأعداد من 1 الى 10 ، والذي يليه هو بعد التلاعب فيه قليلا :
#include <stdio.h> void functionOne ( int* array , int size ) { for (int i=0 ; i<size; i++) printf("%d ",array[i]); // or *array++ or *(array+i) } int main() { int array[] = {1,2,3,4,5,6,7,8,9,10}; functionOne(array,10); return 0; }
الان النسخه المعدله ، ولاحظ أننا في الداله main قمنا بأخذ عنوان المصفوفه ، وارساله الى الداله functionOne ، وهناك قمنا بعمل cast لهذا الرقم وحولناه الى مؤشر ، بعدها باستخدام pointer arithmetic قمنا بالوصول الى عناصر المصفوفه .
#include <stdio.h> void functionOne ( int address , int size ) { int i=0; for (; i<size; i++) printf("%d ", *((int*)address+i)); } int main() { int array[] = {1,2,3,4,5,6,7,8,9,10}; int address = (int)array ; // (int) &array[0] functionOne(address,10); return 0; }
المعامل الشرطي الثلاثي Conditional Operator ومعامل الفاصله Comma Operator :
معامل الفاصله يعمل من اليسار الى اليمين ، ومن ثم يسند قيمه المتغير الموجود في الجهه اليمني الى المتغير اذا كان هناك. نأخذ مثال :
int a=0; int b=3; a = (b+=3, b-1);
الان عند تنفيذ السطر الثالث ، نقوم بزياده b بمقدار 3 وتصبح 6 ، بعدها نطرح من b واحد وتصبح 5 ، وأخيرا نسند b الى a (اي تصبح قيمه a هي 5 ).
المعامل الشرطي هو بديل لجمله If :
if (<test_condition>) { <variable_name> = <value_if_true>; } else { <variable_name> = <value_if_false>; }
وباستخدام Conditional Operator :
<variable_name> = (<test_condition>) ? (<value_if_true>) : (<value_if_false>);
في حال كان test_condition صحيح سوف ينفذ value_if_true والا value_if_false .
هذا المعامل له دور كبير جدا في هذه النوعيه من البرامج ، حيث يتم استبدال أي جمله شرطيه بهذا المعامل .
وفي حاله كانت هناك nested if ، يمكن استخدام المعامل الشرطي مع معامل الفاصله لكي يؤدي الغرض :
<variable_name> = (<test_condition>) ? (<expression_a1>, ..., <value_if_true>) : (<expression_b1>, ..., <value_if_false>);
مثال :
int a=1; int b=2; int c=3; if (a<0) { b+=3; a=b-1; } else { c+=b; a=c+2; }
الان نحوله الى conditional operator و comma operator :
int a=1; int b, c; a=(b=2, c=3, a<0) ? (b+=3, b-1) : (c+=b, c+2);
وهنا أولا سوف يسند 2 الى b ، بعدها 3 الى c ، بعدها يقارن هل a أصغر من 0 ، في حال كان ذلك ، يزيد على b ثلاثه ، ومن ثم يطرح واحد ، ويرجع القيمه ويسندها الى a . اما اذا كان a أكبر من 0 ، سوف يزيد على c مقدار b وهي 2 ، بعدها يزيد على c 2 ويسند الناتج الى a .
الأستدعاء الذاتي :
الجميع يعلم هذا الموضوع ، وهي داله تنادي نفسها في حال تحقق شرط ما ، وهنا أغلب الأحيان نرسل قيمه وهي التي تدل على نهائيه الأستدعاء ، أو نقوم بعمل متغير static لكن لا يجب أ ن تستخدم هذه الطريقه في حاله استدعيت الداله أكثر من مره .
نأخذ مثال لطباعه الأعداد من 1 – 10 ، وبعدها نحوله الى النداء الذاتي :
#include "stdio.h" int main() { int array[]={0,1,2,3,4,5,6,7,8,9}; int i; for (i=0; i<10; ++i) { printf("%d ",array[i]); } return 0; }
وها هو البرنامج بعد التعديل :
#include "stdio.h" void recursiveFunction(int array, int i, int stop) { printf("%d ",*((int*)array+i)); i++; if (i < stop) { recursiveFunction(array, i, stop); } } int main() { int array[]={0,1,2,3,4,5,6,7,8,9}; recursiveFunction((int)array, 0, 10); return 0; }
الأن نأخذ مثال شامل لـ Hello World ، المثال هو :
#include "stdio.h" int main() { printf("Hello World!"); return 0; }
وبعدها سندخل هذا المثال غرفه العمليات ، للقيام بعمليه تجميل ، ليخرج بالشكل :
#include "stdio.h" _(__,_0,O_,___){(O_<_0)?printf("%c",(O_==2) ||(O_==3)||(O_==9)?___++,O_++,108:*((int*)__ +O_++-___)),_(__,_0, O_, ___):0;}main(){int array []={72,'e',111,040,0127,0x6F,'r',0x64,041 };_(array , 12 , 0 , 0 ) ; }
جميل أليس كذلك !
نبدا الأن .
الخطوه الأولى :
نعمل داله للطباعه ، نرسل اليها المصفوفه ، القيم التي في المصفوفه كتبناها بالنظام العشري .
void myFunction(int array[], int arraySize) { int i; for (i=0; i<arraySize; ++i) { printf("%c", array[i]); } } int main() { int array[]={72,101,108,108,111,32,87,111,114,108,100,33}; myFunction(array,12); return 0; }
الخطوه الثانيه :
استخدمنا فكره ارسال متغير يحمل العنوان (التي شرحناها في الأعلى) وبعدها نقوم بعمل cast للمتغير ونحوله الى مؤشر :
#include "stdio.h" void myFunction(int integer, int arraySize) { int i; for (i=0; i<arraySize; ++i) { printf("%c", *((int*)integer+i)); } } int main() { int array[]={72,101,108,108,111,32,87,111,114,108,100,33}, integer=(int)array; myFunction(integer,12); return 0; }
الخطوه الثالثه :
غيرنا الداله وقمنا بعمل استدعاء ذاتي ، وغيرنا if الى Conditional Operator :
void myFunction(int integer, int arraySize, int i) { (i<arraySize) ? printf("%c", *((int*)integer + i++ )), myFunction(integer, arraySize, i) : 0; } int main() { int array[]={72,101,108,108,111,32,87,111,114,108,100,33}; myFunction((int)array,12, 0); return 0; }
الخطوه الرابعه :
نتخلص من بعض الحروف المكرره في المصفوفه (وهو الحرف L) يتكرر ثلاث مرات 108 ، في الموقع 2 و 3 و 9 :
#include "stdio.h" void myFunction(int integer, int arraySize, int i, int k) { (i<arraySize) ? (i==2)||(i==3)||(i==9) ? k++, i++, printf("%c",108) : printf("%c", *((int*)integer + i++ - k)), myFunction(integer,arraySize, i, k) : 0; } int main() { int array[]= { 72, 101, 111, 32, 87, 111, 114, 100, 33 }; myFunction((int)array, 12, 0, 0); return 0; }
الخطوه الخامسه :
نغير من ترتيب معامل الشرط في الداله :
void myFunction(int integer, int arraySize, int i, int k) { (i<arraySize) ? printf("%c",(i==2)||(i==3)||(i==9) ? k++, i++, 108 : *((int*)integer + i++ - k)), myFunction(integer,arraySize, i, k) : 0; } int main() { int array[]= { 72, 101, 111, 32, 87, 111, 114, 100, 33 }; myFunction((int)array, 12, 0, 0); return 0; }
الخطوه السادسه :
نغير من أسماء المتغيرات في الداله ، ودائما تغير اسماء المتغيرات يأتي في أخر مرحله حتى لا تضيع أنت وتشوش على نفسك اثناء كتابة البرنامج ، أيضا تغيير القيم في المصفوفه وجعلها بعده أنظمه Hex و octal وdecimal :
#include "stdio.h" void myFunction(int __, int _0, int O_, int ___) { (O_<_0) ? printf("%c",(O_==2)||(O_==3)||(O_==9) ? ___++, O_++, 108 : *((int*)__ + O_++ - ___)), myFunction(__,_0, O_, ___) : 0; } int main() { int array[]= { 72, 'e', 111, 040, 0127, 0x6F, 'r', 0x64, 041 }; myFunction((int)array, 12, 0, 0); return 0; }
الخطوه السابعه :
تغير اسم الداله ، حذف القيمه الراجعه ، وسوف يعتبرها المترجم هي int ، أيضا حذف نوع المتغير المرسل في الداله وأيضا سيتعبرها int :
_(__, _0, O_, ___) { (O_<_0) ? printf("%c",(O_==2)||(O_==3)||(O_==9) ? ___++, O_++, 108 : *((int*)__ + O_++ - ___)), _(__,_0, O_, ___) : 0; } main() { int array[]= { 72, 'e', 111, 040, 0127, 0x6F, 'r', 0x64, 041 }; _(array, 12, 0, 0); }
الخطوه الأخير :
نقوم بحذف المسافات بين الجمل ، وضغطها :
#include "stdio.h" _(__,_0,O_,___){(O_<_0)?printf("%c",(O_==2) ||(O_==3)||(O_==9)?___++,O_++,108:*((int*)__ +O_++-___)),_(__,_0, O_, ___):0;}main(){int array []={72,'e',111,040,0127,0x6F,'r',0x64,041 };_(array , 12 , 0 , 0 ) ; }
واوووو …… من كان يصدق أن هذا البرنامج Hello World !
نقطه أخيره
البرنامج السابق هو أسهل برنامج مشوش ، نعم !! هناك بعض البرامج معقده جدا وخاصه عندما يتم استخدام جمل الهاش # أو Preprocessor Directive
هناك بعض البرامج ، يمكن أن تقوم بكشفها بسرعه مثل :
_(__,___,____){___/__<=1?_(__,___+1,____):!(___%__)?_(__,___+1,0):___%__==___/ __&&!____?(printf("%d\t",___/__),_(__,___+1,0)):___%__>1&&___%__<___/__?_(__,1+ ___,____+!(___/__%(___%__))):___<__*__?_(__,___+1,____):0;}main(){_(100,0,0);}
وهو يطبع الأعداد الأوليه من 1 الى 100 ، وهنا أولا أستعن بخاصيه Find & Replace الموجوده في الDE أو في أي محرر نصوص ، وغير كل : _ بمثلا Function ، وبعدها سوف تصبح النتيجه :
Function(__,___,____){___/__<=1?Function(__,___+1,____):!(___%__)?Function(__,___+1,0):___%__==___/ __&&!____?(printf("%d\t",___/__),Function(__,___+1,0)):___%__>1&&___%__<___/__?Function(__,1+ ___,____+!(___/__%(___%__))):___<__*__?Function(__,___+1,____):0;}main(){Function(100,0,0);}
الان غير كل : __ بمثلا varOne وقم بعمل replace All :
Function(varOne,___,____){___/varOne<=1?Function(varOne,___+1,____):!(___%varOne)?Function(varOne,___+1,0):___%varOne==___/ varOne&&!____?(printf("%d\t",___/varOne),Function(varOne,___+1,0)):___%varOne>1&&___%varOne<___/varOne?Function(varOne,1+ ___,____+!(___/varOne%(___%varOne))):___<varOne*varOne?Function(varOne,___+1,____):0;}main(){Function(100,0,0);}
واستمر هكذا الى أن تنتهي من جميع أسماء المتغيرات العجيبه ، وبعدها قم بتنظيم البرنامج ، وهنا ستجد نفسك أمام الكود مباشره !
أخيرا ، لما لا يطرح كل منا كوده الـ Obfuscated ونشاهد من هو صاحب الكود الأكثر تشويشا ؟
راااااااائع !!
أصابني المقال بالدوار @_@ هه….لكن فكرة جميلة وإبداعية
جميل
وين القبلة
commande en ligne kamagra sans abonnement livraison le lendemain
kamagra comprar
how to buy enclomiphene cheap wholesale
enclomiphene chicago where to buy
buy androxal usa buy online
how to order androxal generic online cheapest
discount flexeril cyclobenzaprine generic extended release
flexeril cyclobenzaprine online with next day shipping
dutasteride online no perscription fedex
discount dutasteride without prescriptions canada
how to buy fildena generic next day delivery
cheapest buy fildena generic no prescription
how to buy gabapentin generic side effect
cheap gabapentin cost tablet
how many orgasms can u get on 1 itraconazole pill
get itraconazole price on prescription
how to buy staxyn usa suppliers
buy cheap staxyn generic uae
online order avodart cheap now
cheapest buy avodart purchase toronto
buy rifaximin new zealand buy online
does generic rifaximin really work
online order xifaxan cheap drugs
discount xifaxan canada price
kamagra bez předpisu
fedex kamagra přes noc