Упражнението обаче също така споменава, че е възможно да се използва само 1 вектор на аргумент за компрометиране на този код. Любопитен съм да видя как може да стане това.
...
Проблемът тук е, че дължината трябва да бъде презаписана, за да се осъществи препълването и адресът за връщане да бъде компрометиран.
Изглежда ми доста просто. Това магическо число 144 има смисъл, ако е sizeof(int) == 8
, което би било, ако изграждате за 64 бита.
Така че, ако приемем оформление на стека, където to_be_exploited
идва преди c
и limit
, можете просто да подадете много дълъг низ с боклуци в байтовете, започващи от отместване 136 (т.е. 128 + sizeof(int)
), и след това внимателно изработени боклуци в байтовете, започващи с отместване 144. Това ще презапише limit
, започвайки с този байт, като по този начин деактивира проверката на дължината. След това внимателно изработените боклуци презаписват адреса за връщане.
Можете да поставите почти всичко в 8-те байта, започвайки от отместване 136, и да ги накарате да направят число, което е достатъчно голямо, за да деактивира проверката за сигурност. Просто се уверете, че няма да получите отрицателно число. Например, низът "HAHAHAHA" би изчислил като цяло число 5206522089439316033. Това число е по-голямо от 144... всъщност е твърде голямо, тъй като искате тази функция да спре копирането, след като вашият низ бъде копиран. Така че просто трябва да разберете колко дълъг всъщност е вашият атакуващ низ и да поставите правилните байтове за тази дължина в тази позиция и атаката ще бъде копирана.
Имайте предвид, че нормалните функции за обработка на низове в C използват NUL байт като терминатор и спират копирането. Тази функция не прави това; то просто се доверява на limit
. Така че можете да поставите всякакви боклуци, които искате, във входния низ, за да използвате тази функция. Въпреки това, ако нормалните C библиотечни функции трябва да копират входните данни, може да се наложи да избягвате NUL байтове.
Разбира се, никой не трябва да въвежда този глупав код в производството.
ЕДИТ: Горното го написах набързо. Сега, когато имам повече време, прочетох отново въпроса ви и мисля, че по-добре разбирам какво искахте да обясните.
Чудите се как една струна може правилно да удря limit
с правилна дължина, без strlen()
да я отрязва накъсо. Това е невъзможно на big-endian компютър, но е напълно възможно на little-endian компютър.
На компютър с малък порядък първият байт е най-малкият байт. Вижте записа в Уикипедия:
http://en.wikipedia.org/wiki/Endianness
Всяко число, което не е абсурдно голямо, трябва да има нула в най-значимите си байтове. На компютър с порядъчен ред това означава, че първите няколко байта ще бъдат нула, ще действат като NUL и ще накарат strlen()
да отреже низа, преди функцията да успее да унищожи limit
. Въпреки това, на компютър с малък ред всички важни байтове, които искате да копирате, ще бъдат пред байтовете NUL.
В ранните дни на интернет беше обичайно компютрите с голям порядък (често закупени от Sun Microsystems) да изпълняват приложения за интернет сървъри. В наши дни най-разпространеният x86 сървърен хардуер е най-разпространен, а x86 е little-endian. На практика всеки, който внедри такъв използваем код като функцията TrickyOverflowSeq()
, ще бъде придобит.
Ако не смятате, че този отговор е достатъчно изчерпателен, моля, публикувайте коментар, обясняващ коя част според вас трябва да покрия по-добре и аз ще актуализирам отговора.
person
steveha
schedule
28.01.2014
to_be_exploited
,c
илиlimit
. Компилаторът е свободен да ги подреди в произволен ред; различни опции за компилатора могат да ги подредят в различен ред. Освен ако не използвате необичайна система,sizeof(int) == 4
, така че 128 + 2 * 4 = 136, оставяйки ви поне 8 байта за презаписване на всяка контролна информация в стека (ако можете да презапишетеc
иlimit
; 16 байта, ако не можете ). Всичко, което трябва да направите, е да извикате програмата с аргумент от поне 144 знака:./yourprog $(perl -e 'print "A" x 144')
. - person Jonathan Leffler   schedule 28.01.2014