1 Востаннє редагувалося cheappi386 (21.03.2017 09:52:14)

Тема: Полювання на IoT качок

Наскільки я розумію це все хозяйство у 99% випадків має веб інтерфейс для віддаленного доступу.Тому я накидав такий ось код

#include "stdafx.h"
#define ThreadsNum 100

#pragma warning(disable : 4996)  

void LoadIpData(wchar_t *dataPlace, std::vector <std::string> &data)//завантаження текстової БД адресс
                                                                    //формат - спочатку длина строки, потім сама строка
{
    HANDLE f = CreateFile(dataPlace, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
    if (f != INVALID_HANDLE_VALUE)
    {
        LARGE_INTEGER *sz = new LARGE_INTEGER;
        GetFileSizeEx(f, sz);
        unsigned char *buf = new unsigned char[sz->QuadPart];
        DWORD r = 0;
        ReadFile(f, buf, sz->QuadPart, &r, 0);
        __int64 totalSize = sz->QuadPart;
        unsigned char partSize = 0;
        char ip[16];
        for (;;)
        {
            partSize = buf[0];
            buf += 1;
            totalSize = totalSize - 1;
            memset(ip, 0, 16);
            memcpy(ip, buf, partSize);
            buf += partSize;
            totalSize = totalSize - partSize;
            data.push_back(std::string(ip));
            if (totalSize < 1) { break; }
        }
        buf -= sz->QuadPart;
        delete[]buf;
        delete sz;
    }
    else
    {
        printf("Open IP dresess file Error: %d", GetLastError());
    }
    CloseHandle(f);
}

std::vector <std::string> good80;//позитивні результати сканування
CRITICAL_SECTION cs;

bool Scan(std::string adr)// функція перевіряє чи має адресса відкритий 80 порт
{
    int err = 0;
    SOCKET s;
    unsigned long block = 1;
    struct sockaddr_in sa;
    sa.sin_family = AF_INET;
    sa.sin_addr.s_addr = inet_addr(adr.c_str());
    timeval time_out;
    time_out.tv_sec = 0;
    time_out.tv_usec = 300000;
    fd_set setW, setE;

    s = socket(AF_INET, SOCK_STREAM, 0);
    if (s < 0)
    {
        printf("socket err: %d\n", WSAGetLastError());
        return 0;
    }
    sa.sin_port = htons(80);
    if (ioctlsocket((unsigned int)s, FIONBIO, &block) != 0)
    {
        printf("ioctlsocket err: %d\n", WSAGetLastError());
        return 0;
    }
    connect(s, (struct sockaddr *)&sa, sizeof sa);
    FD_ZERO(&setW);
    FD_SET(s, &setW);
    FD_ZERO(&setE);
    FD_SET(s, &setE);
    select(0, NULL, &setW, &setE, &time_out);
    if (FD_ISSET(s, &setW))
    {
        // Connect выполнен успешно
        return true;
        //printf("%s:%d:conn OK\n", scan_data->adr, i);
    }
    else if (FD_ISSET(s, &setE))
    {
        printf("%s connection fail\n", adr.c_str());
        return false;
        // Соединиться не удалось
    }
    else
    {
        // произошел таймаут (5 секунд)
        printf("%s timeout\n", adr.c_str());
        return false;
    }
    closesocket(s);
    return false;
}

DWORD WINAPI ScanThread(LPVOID lParam)// фцнкція скануючих потоків
{
    std::vector <std::string> data = *((std::vector <std::string> *)lParam);
    for (int i = 0; i < data.size(); i++)
    {
        if (Scan(data[i]) == true)
        {
            EnterCriticalSection(&cs);
            good80.push_back(data[i]);
            LeaveCriticalSection(&cs);
            printf("OK: %s\n", data[i].c_str());
        }
    }
    return 0;
}

int main()
{
    WSADATA wsd = { 0 };
    WSAStartup(MAKEWORD(2, 0), &wsd);

    std::vector <std::string> data;
    LoadIpData(L"G:\\ruM1.bin", data);//завантаження адрес
    printf("Loaded IP adresess: %d\n", data.size());
    
    std::vector <std::string> *tasks = new std::vector <std::string>[ThreadsNum];//формування окремего завдання кожному потоку
    int partSize = data.size() / ThreadsNum;
    std::vector <std::string>::iterator it_cpy=data.begin();
    for (int i = 0; i < (ThreadsNum - 1); i++)
    {
        tasks[i].reserve(partSize);
        tasks[i].insert(tasks[i].begin(), it_cpy, it_cpy + partSize);
        it_cpy += partSize;
    }
    tasks[ThreadsNum - 1].reserve(data.end() - it_cpy);
    tasks[ThreadsNum - 1].insert(tasks[ThreadsNum - 1].begin(), it_cpy, it_cpy + (data.end() - it_cpy) );
    
    InitializeCriticalSection(&cs);

    HANDLE *thrs = new HANDLE[ThreadsNum];
    for (int i = 0; i < ThreadsNum; i++)
    {
        thrs[i] = CreateThread(0, 0, ScanThread, &tasks[i], 0, 0);//стартуємо потоки для сканування
    }

    for (int i = 0; i < ThreadsNum; i++)//чекаємо завршення потоків
    {
        WaitForSingleObject(thrs[i], INFINITE);
    }
    if (good80.size() > 0)//якщо є позитивні результати,записуємо їх до текстового файлу
    {
        printf("found: %d \n", good80.size());
        std::string result;
        for (int i = 0; i < good80.size(); i++)
        {
            result = result + good80[i]+"\r\n";
        }
        HANDLE f = CreateFile(L"G:\\good80.txt", GENERIC_WRITE, FILE_SHARE_WRITE, 0, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
        if (f != INVALID_HANDLE_VALUE)
        {
            DWORD w = 0;
            WriteFile(f, result.c_str(), result.length(), &w, 0);
        }
        else
        {
            printf("Create file error: %d\n", GetLastError());
        }
        CloseHandle(f);
    }
    _getch();
    return 0;
}

Результат такий що приблизно на тисячу IP адрес виявлятся десь від 10 до 30 з відкритим 80 портом.Це доволі не мало. Тому я теперь шукаю ідей як автоматично відпарсити - з паролем/без пароля, камери від роутерів та інш.
PS: звісно було б добре якщо хтось би підказав алгоритм, який би міг відразу знаходити  IPкамери з голими тьолками :[

Подякували: 0xDADA11C7, HetmanNet, Chemist-i3

2 Востаннє редагувалося HetmanNet (21.03.2017 10:17:57)

Re: Полювання на IoT качок

cheappi386 написав:

Наскільки я розумію це все хозяйство у 99% випадків має веб інтерфейс для віддаленного доступу.Тому я накидав такий ось код

#include "stdafx.h"
#define ThreadsNum 100

#pragma warning(disable : 4996)  

void LoadIpData(wchar_t *dataPlace, std::vector <std::string> &data)//завантаження текстової БД адресс
                                                                    //формат - спочатку длина строки, потім сама строка
{
    HANDLE f = CreateFile(dataPlace, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
    if (f != INVALID_HANDLE_VALUE)
    {
        LARGE_INTEGER *sz = new LARGE_INTEGER;
        GetFileSizeEx(f, sz);
        unsigned char *buf = new unsigned char[sz->QuadPart];
        DWORD r = 0;
        ReadFile(f, buf, sz->QuadPart, &r, 0);
        __int64 totalSize = sz->QuadPart;
        unsigned char partSize = 0;
        char ip[16];
        for (;;)
        {
            partSize = buf[0];
            buf += 1;
            totalSize = totalSize - 1;
            memset(ip, 0, 16);
            memcpy(ip, buf, partSize);
            buf += partSize;
            totalSize = totalSize - partSize;
            data.push_back(std::string(ip));
            if (totalSize < 1) { break; }
        }
        buf -= sz->QuadPart;
        delete[]buf;
        delete sz;
    }
    else
    {
        printf("Open IP dresess file Error: %d", GetLastError());
    }
    CloseHandle(f);
}

std::vector <std::string> good80;//позитивні результати сканування
CRITICAL_SECTION cs;

bool Scan(std::string adr)// функція перевіряє чи має адресса відкритий 80 порт
{
    int err = 0;
    SOCKET s;
    unsigned long block = 1;
    struct sockaddr_in sa;
    sa.sin_family = AF_INET;
    sa.sin_addr.s_addr = inet_addr(adr.c_str());
    timeval time_out;
    time_out.tv_sec = 0;
    time_out.tv_usec = 300000;
    fd_set setW, setE;

    s = socket(AF_INET, SOCK_STREAM, 0);
    if (s < 0)
    {
        printf("socket err: %d\n", WSAGetLastError());
        return 0;
    }
    sa.sin_port = htons(80);
    if (ioctlsocket((unsigned int)s, FIONBIO, &block) != 0)
    {
        printf("ioctlsocket err: %d\n", WSAGetLastError());
        return 0;
    }
    connect(s, (struct sockaddr *)&sa, sizeof sa);
    FD_ZERO(&setW);
    FD_SET(s, &setW);
    FD_ZERO(&setE);
    FD_SET(s, &setE);
    select(0, NULL, &setW, &setE, &time_out);
    if (FD_ISSET(s, &setW))
    {
        // Connect выполнен успешно
        return true;
        //printf("%s:%d:conn OK\n", scan_data->adr, i);
    }
    else if (FD_ISSET(s, &setE))
    {
        printf("%s connection fail\n", adr.c_str());
        return false;
        // Соединиться не удалось
    }
    else
    {
        // произошел таймаут (5 секунд)
        printf("%s timeout\n", adr.c_str());
        return false;
    }
    closesocket(s);
    return false;
}

DWORD WINAPI ScanThread(LPVOID lParam)// фцнкція скануючих потоків
{
    std::vector <std::string> data = *((std::vector <std::string> *)lParam);
    for (int i = 0; i < data.size(); i++)
    {
        if (Scan(data[i]) == true)
        {
            EnterCriticalSection(&cs);
            good80.push_back(data[i]);
            LeaveCriticalSection(&cs);
            printf("OK: %s\n", data[i].c_str());
        }
    }
    return 0;
}

int main()
{
    WSADATA wsd = { 0 };
    WSAStartup(MAKEWORD(2, 0), &wsd);

    std::vector <std::string> data;
    LoadIpData(L"G:\\ruM1.bin", data);//завантаження адрес
    printf("Loaded IP adresess: %d\n", data.size());
    
    std::vector <std::string> *tasks = new std::vector <std::string>[ThreadsNum];//формування окремего завдання кожному потоку
    int partSize = data.size() / ThreadsNum;
    std::vector <std::string>::iterator it_cpy=data.begin();
    for (int i = 0; i < (ThreadsNum - 1); i++)
    {
        tasks[i].reserve(partSize);
        tasks[i].insert(tasks[i].begin(), it_cpy, it_cpy + partSize);
        it_cpy += partSize;
    }
    tasks[ThreadsNum - 1].reserve(data.end() - it_cpy);
    tasks[ThreadsNum - 1].insert(tasks[ThreadsNum - 1].begin(), it_cpy, it_cpy + (data.end() - it_cpy) );
    
    InitializeCriticalSection(&cs);

    HANDLE *thrs = new HANDLE[ThreadsNum];
    for (int i = 0; i < ThreadsNum; i++)
    {
        thrs[i] = CreateThread(0, 0, ScanThread, &tasks[i], 0, 0);//стартуємо потоки для сканування
    }

    for (int i = 0; i < ThreadsNum; i++)//чекаємо завршення потоків
    {
        WaitForSingleObject(thrs[i], INFINITE);
    }
    if (good80.size() > 0)//якщо є позитивні результати,записуємо їх до текстового файлу
    {
        printf("found: %d \n", good80.size());
        std::string result;
        for (int i = 0; i < good80.size(); i++)
        {
            result = result + good80[i]+"\r\n";
        }
        HANDLE f = CreateFile(L"G:\\good80.txt", GENERIC_WRITE, FILE_SHARE_WRITE, 0, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
        if (f != INVALID_HANDLE_VALUE)
        {
            DWORD w = 0;
            WriteFile(f, result.c_str(), result.length(), &w, 0);
        }
        else
        {
            printf("Create file error: %d\n", GetLastError());
        }
        CloseHandle(f);
    }
    _getch();
    return 0;
}

Результат такий що приблизно на тисячу IP адрес виявлятся десь від 10 до 30 з відкритим 80 портом.Це доволі не мало. Тому я теперь шукаю ідей як автоматично відпарсити - з паролем/без пароля, камери від роутерів та інш.
PS: звісно було б добре якщо хтось би підказав алгоритм, який би міг відразу знаходити  IPкамери з голими тьолками :[

Варто 8080 та 8081 парсити.. а окрім них є ще ряд портів які теж можна парсити і перевіряти на доступ по дефолтному порту.. бо 80 рідко юзають навіть по дефолту як веб-доступ до камери..

3

Re: Полювання на IoT качок

HetmanNet написав:

Варто 8080 та 8081 парсити.. а окрім них є ще ряд портів які теж можна парсити і перевіряти на доступ по дефолтному порту.. бо 80 рідко юзають навіть по дефолту як веб-доступ до камери..

Якщьо там порт не стандарт, то 100% запоролено.А брут цього це окрема тема.

4

Re: Полювання на IoT качок

cheappi386 написав:
HetmanNet написав:

Варто 8080 та 8081 парсити.. а окрім них є ще ряд портів які теж можна парсити і перевіряти на доступ по дефолтному порту.. бо 80 рідко юзають навіть по дефолту як веб-доступ до камери..

Якщьо там порт не стандарт, то 100% запоролено.А брут цього це окрема тема.

Загалом там ці порти є стандартними.. тобто їх користувач не міняв, просто виробник вирішив зробити це за більшість ледачих користувачів.. але при тому всьому пароль стандартний у них такий самий простий як і у виробників які задали порт 80.. загалом стандартних паролів менше сотні, тому їх можна перебрати без проблем..

5

Re: Полювання на IoT качок

Якщо стандартний GET має відповідь

401 Unauthorized

А браузер видає таке вікно
http://не-дійсний-домен/i9/d3bf176254249c5d9d6056f608fd2bbb/1490386265/6150/1105465/forpost_500.jpghttp://не-дійсний-домен/a3/2017-03-24-20-11/i9-10995457/500x281-r/i.gif
То мабуть потрібно відправляти POST запит для авторизації.
Можливо хтось може підказати структуру такого POST запиту?

6 Востаннє редагувалося HetmanNet (24.03.2017 23:05:56)

Re: Полювання на IoT качок

cheappi386 написав:

Якщо стандартний GET має відповідь

401 Unauthorized

А браузер видає таке вікно
http://не-дійсний-домен/i9/d3bf176254249c5d9d6056f608fd2bbb/1490386265/6150/1105465/forpost_500.jpghttp://не-дійсний-домен/a3/2017-03-24-20-11/i9-10995457/500x281-r/i.gif
То мабуть потрібно відправляти POST запит для авторизації.
Можливо хтось може підказати структуру такого POST запиту?

HTTP/1.1 401 Access Denied
WWW-Authenticate: Basic realm="My Server"
Content-Length: 0

Таке отримав? Тоді ось:

GET /securefiles/ HTTP/1.1
Host: www.httpwatch.com
Authorization: Basic aHR0cHdhdGNoOmY=
https://www.httpwatch.com/httpgallery/authentication/ написав:

The Authorization specifies the authentication mechanism (in this case Basic) followed by the username and password. Although, the string aHR0cHdhdGNoOmY= may look encrypted it is simply a base64 encoded version of <username>:<password>. In this example, the un-encoded string "httpwatch:foo" was used and would be readily available to anyone who could intercept the HTTP request.

Подякували: 0xDADA11C71