Linux за българи: Форуми

Програмиране => Общ форум => Темата е започната от: gat3way в Feb 19, 2008, 21:39



Титла: Защо става така?
Публикувано от: gat3way в Feb 19, 2008, 21:39
На практика, entry point-a в ELF хедъра сочи към началото на секцията .text, а не .init. Поне при повечето байнърита, които гледам тука.

Не би ли трябвало да е обратното?

И още нещо, защо код, който се намира в section тип NOTE и без execute флаг (само Allocate), в крайна сметка се изпълнява? Сигурен съм за това, защото си играх с entry point-a на ELF изпълнимия файл. Единственото условие е типа на program header-a да бъде LOAD, не NOTE. Тогава защо въобще ги правят тези флагове за позволения на секциите?

Нищо не разбирам от тия ELF глупости..





Титла: Защо става така?
Публикувано от: neter в Feb 19, 2008, 23:57
Аз всъщност за първи път чувам за абревиатурата ELF и ми отвори материал за четене, поне да разбера що за чудо е това :) Но попаднах на това и рекох да ти го дам, пък току виж успееш да си отговориш на въпросите.

edit: Я, така се наричал форматът за изпълними файлове в Linux! Хмм...





Титла: Защо става така?
Публикувано от: gat3way в 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 бацилите по някакъв начин го правят така че да се самопренасят и да не заемат много памет и място, което все още е някаква загадка за мене как става.

Никой ли не се е интересувал от тези глупости?