مبهم‌سازی کد

از ویکی‌پدیا، دانشنامهٔ آزاد
(تغییرمسیر از مبهم‌سازی)
پرش به: ناوبری، جستجو

در توسعه نرمافزار مبهم‌سازی کد (به انگلیسی: Obfuscation) به مبهم سازی (و یا مشوش سازی) عامدانه کد منبع و یا کد ماشین به شکلی که درک آن برای انسان سخت باشد، گفته می‌شود. برخی زبان‌های برنامه‌نویسی تمایل بیشتری به مبهم سازی دارند. در رأس آن‌ها، زبان‌هایی از قبیل C، C++ و Perl انتخاب‌های اول برای مبهم سازی هستند. ماکروهای پیش‌پردازش شونده(Macro Preprocessors)، یکی از روش‌های موردعلاقه برای پوشش گذاشتن بر روی ترکیبات و گرامر اصلی کدها و درنتیجه پایین آوردن خوانایی کد منبع هستند. با این کار دستورات و ترکیبات اصلی را طوری تغییر می‌دهند که دیگر برای خواننده قابل‌هضم نباشد. در این میان برنامه‌هایی بانام «مبهم ساز» نیز وجود دارند که پس از گرفتن کد منبع و یا کد شیء آن را بسته به هدفی خاص به شکل خودکار مبهم سازی می‌کنند.

مبهم سازی کدها در اکثر موارد برای جلوگیری از عمل مهندسی معکوس صورت می‌گیرد و برنامه‌نویس با انجام این عمل خطر دسترسی غیرمجاز به کدهای منبع را تا حد قابل‌توجهی کاهش می‌دهد. با انجام این عمل می‌توانند جلوی تحقق پیدا کردن هدف‌هایی چون ترجمه دوباره برنامه و تغییر کنترل آن و یا یافتن آسیب‌پذیری‌ها را گرفت.

مبهم‌سازی تفریحی[ویرایش]

خواندن و نوشتن کدهای مبهم، همچون یک بازی ذهنی برای برنامه نویسان لذت بخش است. از همین روی تعدادی مسایقه برنامه‌نویسی همچون مسابقه بین‌المللی کدنویسی مبهم به زبان سی، مسابقه کدنویسی مبهم به زبان پرل و مسابقه بین‌المللی کدنویسی مبهم به زبان روبی ایجاد شده و به خلاقانه‌ترین کد مبهم‌سازی شده جوایزی اهدا می‌کند.

روش‌ها[ویرایش]

روش‌های گوناگونی برای تولید کدهای مبهم شده وجود دارند، از روش‌های معمولی که بیشتر استفاده می‌شوند می‌توان موارد زیر را نام برد:

  • استفاده کردن و نکردن از فاصله‌های سفید برای تولید یک کد هنرمندانه که مفهومی (در اکثر موارد مفهومی مرتبط با کد، به طور مثال خروجی کد) خاص را می‌رساند.
  • تولید کدهایی که به صورت خودکار خود را تولید می‌کنند.
  • فشرده سازی بیش از اندازه کدها.
  • تولید کدهایی معتبر که در چند زبان به خوبی کار می‌کنند.

مثال[ویرایش]

در معرفی کدهای مبهم شده، می‌توان به برنامه معروف مبهم‌سازی شده پرل (نسبت داده شده به Randal Schwartz) اشاره کرد که جمله «Just another Perl hacker» را به نمایش درمی‌آورد. جمله‌ای که بعدها در امضای اکثر برنامه نویسان پرل به چشم می‌خورد و بعدها آن را JAPH خواندند.

$_='987;s/^(\d+)/$1-1/e;$1?eval:print"Just another Perl hacker,"';eval;

نمونه‌ای دیگر که تنها با استفاده از کلمات کلیدی زبان پرل، JAPH را چاپ می‌کند:

not exp log srand xor s qq qx xor
s x x length uc ord and print chr
ord for qw q join use sub tied qx
xor eval xor print qq q q xor int
eval lc q m cos and print chr ord
for qw y abs ne open tied hex exp
ref y m xor scalar srand print qq
q q xor int eval lc qq y sqrt cos
and print chr ord for qw x printf
each return local x y or print qq
s s and eval q s undef or oct xor
time xor ref print chr int ord lc
foreach qw y hex alarm chdir kill
exec return y s gt sin sort split

اگرچه کدهای بعدی نامفهوم و غیرقابل درک به نظر می‌رسند، اما این کدها برنامه‌ای کامل و بینقص به زبان C هستند که پس از کامپایل، ۱۲ جمله شعر معروف ۱۲ روز کریسمس را چاپ می‌کنند. این کد تمام رشته‌های مورد نیاز برای تولید هر ۱۲ جمله را در خود به صورت زمر شده دارد و سپس با تکرار آنها جملات مربوط به شعر را می‌سازد:

#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);}

حتی با زبان پایتون نیز می‌توان کدها را مبهم‌سازی کرد، کد زیر نمونه این عمل در زبان پایتون است:

# Primes < 1000
print filter(None,map(lambda y:y*reduce(lambda x,y:x*y!=0,
map(lambda x,y=y:y%x,range(2,int(pow(y,0.5)+1))),1),range(2,1000)))
# First 10 Fibonacci numbers
print map(lambda x,f=lambda x,f:(x<=1) or (f(x-1,f)+f(x-2,f)): f(x,f),
range(10))
# Mandelbrot set
print (lambda Ru,Ro,Iu,Io,IM,Sx,Sy:reduce(lambda x,y:x+y,map(lambda y,
Iu=Iu,Io=Io,Ru=Ru,Ro=Ro,Sy=Sy,L=lambda yc,Iu=Iu,Io=Io,Ru=Ru,Ro=Ro,i=IM,
Sx=Sx,Sy=Sy:reduce(lambda x,y:x+y,map(lambda x,xc=Ru,yc=yc,Ru=Ru,Ro=Ro,
i=i,Sx=Sx,F=lambda xc,yc,x,y,k,f=lambda xc,yc,x,y,k,f:(k<=0)or (x*x+y*y
>=4.0) or 1+f(xc,yc,x*x-y*y+xc,2.0*x*y+yc,k-1,f):f(xc,yc,x,y,k,f):chr(
64+F(Ru+x*(Ro-Ru)/Sx,yc,0,0,i)),range(Sx))):L(Iu+y*(Io-Iu)/Sy),range(Sy
))))(-2.1, 0.7, -1.2, 1.2, 30, 80, 24)
#    \___ ___/  \___ ___/  |   |   |__ lines on screen
#        V          V      |   |______ columns on screen
#        |          |      |__________ maximum of "iterations"
#        |          |_________________ range on y axis
#        |____________________________ range on x axis

در مثالی دیگر می‌توان برنامه زیر که اعداد اول کوچک‌تر از ۱۰۰ را یافته و چاپ می‌کند را با تعییر تابع primes مبهم‌سازی کرد :

void primes(int cap) {
  int i, j, composite;
  for(i = 2; i < cap; i++) {
    composite = 0;
    for(j = 2; j < i; j++)
      composite += !(i % j);
    if(!composite)
      printf("%d\t", i);
  }
}

int main() {
  primes(100);
}

کد بالا پس از اعمال تغییرات مبهم‌سازی چون:

  • جایگزینی حلقه‌های for با یک حلقه while به همراه دستورات تو در توی if-else
  • بازنویسی حلقه while را به صورت بازگشتی
  • تبدیل دستورات if-else را به کاراکترهای تکی مشابه
  • از بین بردن متغیرهای میانی جهت مخفی سازی هدف و نتیجه تابع
  • تغییر نام متغیرها به کاراکترهایی چون _ و __
  • پاک کردن فاصله‌های سفید و پرانتزهای غیر ضروری

به شکل زیر تغییر می‌کند:

_(__,___,____){___/__<=1?_(__,___+1,____):!(___%__)?_(__,___+1,0):___%__==___/
__&&!____?(printf("%d\t",___/__),_(__,___+1,0)):___%__>1&&___%__<___/__?_(__,1+
___,____+!(___/__%(___%__))):___<__*__?_(__,___+1,____):0;}main(){_(100,0,0);}

مزایای مبهم‌سازی کد[ویرایش]

مبهم‌سازی خودکار کد مزایای قابل شمارشی دارد که بهره‌گیری از آن در پلاتفرم‌های گوناگون را محبوب کرده است. در برخی زبان‌های برنامه‌نویسی سطح بالا (همچون جاوا،[۱] اندروید[۲] و دات نت) مترجم‌های وارون رایگان به سادگی می‌توانند کدماشین و یا یک کتابخانه را مهندسی معکوس کرده و به کد منبع بازگردانند؛ بنابراین بزرگترین مزیت مبهم‌سازی خودکار کدها، محافظت از حقوق معنوی نهفته در نرمافزار است، به طوری که با پیچیده و سخت سازی عمل مهندسی معکوس، آن را از لحاظ اقتصادی پرهزینه می‌سازد. از دیگر مزیت‌های مبهم‌سازی کدها می‌توان به کمک در محافظت از مکانیزم پروانه نرمافزار در برابر دسترسی غیرمجاز و فشرده سازی کد ماشین اشاره کرد.

معایب مبهم‌سازی کد[ویرایش]

درحالی که مبهم‌سازی کدها، خواندن، بازنویسی و یا مهندسی معکوس کدها را مشکل و غیر اقتصادی می‌کند، لزوماً آن را غیرممکن نمی‌سازد.[۳][۴] علاوه بر این مبهم سازی کدها ممکن است جهت مخفی سازی یک عمل خرابکارانه صورت بگیرد، از این رو برخی نرمافزارهای ضدبدافزار همچون AVG در صورت مشاهده یک کد مبهم‌سازی شده به صورت دستی، به کاربر هشدار می‌دهد. با این حال ممکن است برخی توسعه دهندگان از مبهم‌سازی برای افزایش امنیت دسترسی غیرمجاز به کدها و یا کاهش اندازه باینری نهایی بهره بگیرند، از این رو کاربران معمولی نباید انتظار داشته باشند که نرمافزارهای ضدبدافزار در صورت مشاهده یک تکه کد مبهم‌سازی شده بی‌ضرر، هشدار تولید کنند.

نرمافزاهای مبهم‌سازی[ویرایش]

در حال حاضر ابزارهای گوناگونی جهت مبهم‌سازی خودکار کدها موجود است. این نرمافزارها ابزارهای تحقیقاتی ایجاد شده توسط دانشگاهیان، ابزارهای سرگرمی، محصولات تجاری ایجاد شده توسط تولیدگران حرفه‌ای و نرمافزارهای منبع باز را شامل می‌شود. در مقابل ابزارهایی خودکار جهت معکوس سازی عمل مبهم‌سازی نیز موجود است.

بیشتر ابزارهای مبهم‌سازی با تغییر ساختار و شمایل کد منبع[۵][۶]و یا کدمیانی (همچون بایت‌کدهای استفاده شده در جاوا[۷] و دات‎نت[۸]) کار خود را پیش می‌برند، با این‌ حال ابزارهایی جهت مبهم سازی مستقیم کد ماشین نیز موجود است.

مبهم‌سازی و پروانه کپی‌لفت[ویرایش]

در گذشته منظاره‌ای دربارهٔ دربارهٔ قانونی و یا غیرقانونی بودن نشر کد منبع به صورت مبهم سازی شده تحت پروانه کپی‌لفت در جریان بود، چرا که در این رویکرد نویسنده‌ی کد، رضایت کمتری از انتشار کدهای خود دارد. این مسئله در پروانه عمومی همگانی گنو برطرف شد، در این پروانه کد منبع به یک نسخه برگزیده از کد منبع اطلاق می‌شود[۹] و کد مبهم‌سازی شده یک کد منبع واقعی محسوب نمی‌شود.[۱۰]

منابع[ویرایش]

  • ماژول JAPH در cpan.org
  • مشارکت‌کنندگان ویکی‌پدیا، «Obfuscation (software)»، ویکی‌پدیای انگلیسی، دانشنامهٔ آزاد.
  • مشارکت‌کنندگان ویکی‌پدیا، «Just another Perl hacker»، ویکی‌پدیای انگلیسی، دانشنامهٔ آزاد.
  • مشارکت‌کنندگان ویکی‌پدیا، «International Obfuscated C Code Contest»، ویکی‌پدیای انگلیسی، دانشنامهٔ آزاد.