مبهمسازی کد
در توسعه نرمافزار مبهمسازی کد (به انگلیسی: 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);}
از جمله بدافزارهای مبهمسازیشده میتوان از تروجان Emotet نام برد.
مزایای مبهمسازی کد
مبهمسازی خودکار کد مزایای قابل شمارشی دارد که بهرهگیری از آن در پلاتفرمهای گوناگون را محبوب کردهاست. در برخی زبانهای برنامهنویسی سطح بالا (همچون جاوا، اندروید و دات نت) مترجمهای وارون رایگان به سادگی میتوانند کدماشین یا یک کتابخانه را مهندسی معکوس کرده و به کد منبع بازگردانند؛ بنابراین بزرگترین مزیت مبهمسازی خودکار کدها، محافظت از حقوق معنوی نهفته در نرمافزار است، بهطوریکه با پیچیده و سخت سازی عمل مهندسی معکوس، آن را از لحاظ اقتصادی پرهزینه میسازد. از دیگر مزیتهای مبهمسازی کدها میتوان به کمک در محافظت از مکانیزم پروانه نرمافزار در برابر دسترسی غیرمجاز و فشرده سازی کد ماشین اشاره کرد.
معایب مبهمسازی کد
درحالی که مبهمسازی کدها، خواندن، بازنویسی یا مهندسی معکوس کدها را مشکل و غیر اقتصادی میکند، لزوماً آن را غیرممکن نمیسازد. علاوه بر این مبهم سازی کدها ممکن است جهت مخفی سازی یک عمل خرابکارانه صورت بگیرد، از این رو برخی نرمافزارهای ضدبدافزار همچون AVG در صورت مشاهده یک کد مبهمسازی شده به صورت دستی، به کاربر هشدار میدهد. با این حال ممکن است برخی توسعه دهندگان از مبهمسازی برای افزایش امنیت دسترسی غیرمجاز به کدها یا کاهش اندازه باینری نهایی بهره بگیرند، از این رو کاربران معمولی نباید انتظار داشته باشند که نرمافزارهای ضدبدافزار در صورت مشاهده یک تکه کد مبهمسازی شده بیضرر، هشدار تولید کنند.
نرمافزاهای مبهمسازی
در حال حاضر ابزارهای گوناگونی جهت مبهمسازی خودکار کدها موجود است. این نرمافزارها ابزارهای تحقیقاتی ایجاد شده توسط دانشگاهیان، ابزارهای سرگرمی، محصولات تجاری ایجاد شده توسط تولیدگران حرفهای و نرمافزارهای منبع باز را شامل میشود. در مقابل ابزارهایی خودکار جهت معکوس سازی عمل مبهمسازی نیز موجود است.
بیشتر ابزارهای مبهمسازی با تغییر ساختار و شمایل کد منبع و یا کدمیانی (همچون بایتکدهای استفاده شده در جاوا و داتنت) کار خود را پیش میبرند، با این حال ابزارهایی جهت مبهم سازی مستقیم کد ماشین نیز موجود است.
مبهمسازی و پروانه کپیلفت
در گذشته مناظره ای دربارهٔ دربارهٔ قانونی یا غیرقانونی بودن نشر کد منبع به صورت مبهم سازی شده تحت پروانه کپیلفت در جریان بود، چرا که در این رویکرد نویسندهٔ کد، رضایت کمتری از انتشار کدهای خود دارد. این مسئله در پروانه عمومی همگانی گنو برطرف شد، در این پروانه کد منبع به یک نسخه برگزیده از کد منبع اطلاق میشود و کد مبهمسازی شده یک کد منبع واقعی محسوب نمیشود.
منابع
- ↑ «همه چیز درباره پرانتشارترین بدافزار». رامونا پردازش نگار. ۲۰۲۲-۰۳-۲۳. دریافتشده در ۲۰۲۲-۰۳-۲۴.
- ↑ ""Decompiling Java" by Godfrey Nolan" (به انگلیسی). Apress.
- ↑ «"Decompiling Android" by Godfrey Nolan». Apress.
- ↑ ""Can We Obfuscate Programs?" by Boaz Barak" (به انگلیسی). Math.ias.edu. Archived from the original on 10 August 2014. Retrieved 2013-11-25.
- ↑ "On the (Im)possibility of Obfuscating Programs". CRYPTO 2001: Advances in Cryptology — CRYPTO 2001 (به انگلیسی). Springer. 02 August 2001. doi:10.1007/3-540-44647-8_1.
- ↑ "Open Directory - Computers: Programming: Languages: JavaScript: Tools: Obfuscators" (به انگلیسی). Dmoz.org. 2013-08-03. Archived from the original on 6 April 2017.
- ↑ "Open Directory - Computers: Programming: Languages: PHP: Development Tools: Obfuscation and Encryption" (به انگلیسی). Dmoz.org. 2013-09-19. Archived from the original on 6 April 2017.
- ↑ "Open Directory - Computers: Programming: Languages: Java: Development Tools: Obfuscators" (به انگلیسی). Dmoz.org. 2013-04-09. Archived from the original on 6 April 2017.
- ↑ "Open Directory - Computers: Programming: Component Frameworks: .NET: Tools: Obfuscators" (به انگلیسی). Dmoz.org. 2007-01-02. Archived from the original on 7 April 2017.
- ↑ «Reasoning behind the "preferred form" language in the GPL [LWN.net]». دریافتشده در ۲۰۱۷-۰۴-۰۶.
- ↑ "What is free software?" (به انگلیسی). gnu.net.
- ماژول JAPH در cpan.org