« Отговор #2 -: Feb 20, 2008, 09:35 »
Абе цялата работа е защото реших да разбера как стават тия неща с троянизирането на изпълними файлове и с ELF вирусите, които съществували (имало някакво си linux.rst.b).
Та значи работата с ELF хедърите не е голяма философия (противно на това, което очаквах) - хедърите са описани в elf.h и директно могат да си се изчитат от файла и записват съответно.
И взех да си правя експерименти значи. В главния ELF хедър има entry point, който е нещо като пойнтер към адреса, от който започва изпълнението на програмата. Хванах един shellcode от хахорския сайт milw0rm и почнах да го пльоскам из изпълнимите секции и да коригирам ентри пойнт-а да сочи към него - номерът минава. Обаче това не ме радва особено, защото се помазва самата програма и се чупи.
После открих тази прословута NOTE секция, която за жалост е доста къса (20 байта в почти всички случаи - очевидно е някаква дефолтна стойност на линкера). Ако й коригираш в program header-a типа да е LOAD, не NOTE, код оттам може да се изпълнява...разбира се трябва да е по-малък от 20 байта, защото иначе се помазва следващата секция/сегмент.
Взех да си играем с objdump, щото хич не съм някакъв експерт в областта на езиците на ниско ниво и гледам че на x86 архитектура, инструкцията за преход (JMP <address>) в машинен код изглежда: "\xff\x25"<address>
И значи мога да си коригирам ентри пойнт-а да ми сочи към NOTE секцията, вътре да издрънча този jump към някакъв адрес. Написах си една много проста програма дето прави нещо от сорта:
printf("msg1\n");
printf("msg2\n");
printf("msg3\n");
което в общи линии вика 3 write() syscalls, изписващи тези глупости на stdout (fd 1). С objdump -D се виждат 3-те int 80h и зареждането на функционалните регистри и стойностите преди това, както и на кои адреси става. Направих си малко занимавки отново с ентри пойнт-а и моята джъмп инструкция, която набивам и успях да накарам програмата да изписва само msg2\nmsg3 или само msg3.
Дотук доволно, май направих една добра крачка напред. Сега остава да разбера как точно се "инфектира" байнърито като хората с код, който надхвърля 20 байта и при това не се помазва функционалността на оригиналната програма.
Очевидно някоя секция трябва да се разшири, ентри пойнт-а да сочи към началото й и след това да има един джъмп към оригиналния ентри пойнт.
Това разширение обаче не виждам как ще стане лесно, защото са доста големи сметки и seek-ванки из бинарния файл. Не е невъзможно, но е сложно. И ELF бацилите по някакъв начин го правят така че да се самопренасят и да не заемат много памет и място, което все още е някаква загадка за мене как става.
Никой ли не се е интересувал от тези глупости?