Перейти к содержимому

Прокси туннелирование C++

Прокси туннелирование C++. Прокси серверы – это компьютеры с установленным специализированным программным обеспечением, служащие для обработки разнообразных запросов со стороны клиента. Основными типами прокси серверов служат: шлюзы, анонимные прокси и файрволы. В данном примере показано как через HTTP прокси получить тестовую html страницу.Подробнее »Прокси туннелирование C++

Программно монтируем диски в директорию

В этой статье рассматривается, как программно монтировать жесткие диски в директории. По умолчанию Windows монтирует несъемные носители автоматически, то есть если вы подключаете новый жесткий диск к компьютеру и после загрузки операционной системы, и установки необходимых драйверов, вы можете увидеть его в проводнике.

В операционных системах UNIX существует возможность монтирования жестких дисков в директории, так называемые точки монтирования. Начиная с Windows NT 4.0 в поставку операционной системы входит утилита mountvol.exe, которая через интерфейс командной строки позволяет создавать, удалять и выводит список точек подключения дисков. Результат работы которой вы видите на рисунке:

Программно монтируем диски в директорию

После не продолжительной работы с данной утилитой, мне захотелось реализовать предоставленные возможности самому, программно. Первым шагом, нужно было, выяснить какие API функции использует mountvol.exe, для этого использовалась программа Dependency Walker входящая в состав поставки среды разработки, ниже на рисунке предоставлено основное окно программы с загруженной в нее утилиты mountvol.exe:
Программно монтируем диски в директорию
Из результата работы Dependency Walker мы видим какие API функции использует mountvol.exe. Для создания программы-примера использовалась среда разработки MS Visual C++ 6.0, тип приложения «Win 32 Console Application».Для начала рассмотрим функций, которые будут использоваться в приложении, и так по порядку:

HANDLE FindFirstVolume(LPTSTR lpszVolumeName,DWORD cchBufferLength);

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

Для дальнейшего поиска используется функция:

BOOL FindNextVolume(HANDLE hFindVolume, LPTSTR lpszVolumeName, DWORD cchBufferLength);

Первым параметром, которой является хендел, полученный при помощи вызова функции FindFirstVolume, в переменную lpszVolumeName возвращаются последующие найденные индефикаторы(GUID) томов.

Для завершения поиска необходимо осуществить вызов функции:

BOOL FindVolumeClose(HANDLE hFindVolume);

Единственным параметром функции, которой является хендел поиска.

Для определения типа тома использовалась функция:

UINT GetDriveType( LPCTSTR lpRootPathName);

Параметром которой является индефикатор тома, возвращаемое значение:

DRIVE_UNKNOWN Не известный тип
DRIVE_NO_ROOT_DIR Не точек подключения
DRIVE_REMOVABLE Съёмный диск
DRIVE_FIXED Фиксированный диск
DRIVE_REMOTE Удалённый или network диск
DRIVE_CDROM CD-ROM диск
DRIVE_RAMDISK RAM диск

Для определения файловой системы и метки тома использовалась функция:

BOOL GetVolumeInformation(
  LPCTSTR lpRootPathName,
  LPTSTR lpVolumeNameBuffer,
  DWORD nVolumeNameSize,
  LPDWORD lpVolumeSerialNumber,
  LPDWORD lpMaximumComponentLength,
  LPDWORD lpFileSystemFlags,
  LPTSTR lpFileSystemNameBuffer,
  DWORD nFileSystemNameSize);

Первый параметр которой является уникальный индефикатор тома, в параметра lpVolumeNameBuffer возвращается метка тома, в параметр lpFileSystemNameBuffer возвращается указатель на буфер содержащий имя файловой системы.

Мною также был найден еще один способ получения уникальных индефикаторов томов, для этого использовалась связка функций GetLogicalDrives и GetVolumeNameForVolumeMountPoint, подробней о их параметрах:

DWORD GetLogicalDrives(void);

Функция возвращает битовую маску, которая содержит все доступные тома в системе.

BOOL GetVolumeNameForVolumeMountPoint(
  LPCTSTR lpszVolumeMountPoint,
  LPTSTR lpszVolumeName,
  DWORD cchBufferLength);

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

BOOL DeleteVolumeMountPoint(LPCTSTR lpszVolumeMountPoint);

Параметром которой является точка монтирования.

И самая главная функция по монтированию томов:

BOOL SetVolumeMountPoint(
  LPCTSTR lpszVolumeMountPoint,
  LPCTSTR lpszVolumeName);

Первый параметр которой является точка последующего монтирования, в нашем случае это директория, например “C:\\mnt\\”, второй параметр это уникальный индефикатор тома.

<strong>Предупреждение:</strong>
Точка куда будет монтироваться том, в нашем случае директория должна быть пустой!!!
На содержимое монтируемого тома это условие не распространяется.

А теперь пробуем все вместе, далее приведен исходный текст программы, которая сначала выводит двумя способами уникальные индефикаторы томов, так же файловую систему, тип тома и метку, дальше она производит демонтирование заданного диска и последующее его монтирование в точку C:\\mnt\\ после паузы возвращает первоначальную точку.

#include <iostream.h>
#include <windows.h>
#include <conio.h>
 
HANDLE (WINAPI * FindFirstVolume)(LPTSTR,DWORD);
BOOL   (WINAPI * FindNextVolume)(HANDLE,LPTSTR,DWORD);
BOOL   (WINAPI * FindVolumeClose)(HANDLE);
BOOL   (WINAPI * GetVolumeNameForVolumeMountPoint)(LPCTSTR,LPTSTR,DWORD);
BOOL   (WINAPI * DeleteVolumeMountPoint)(LPCTSTR);
BOOL   (WINAPI * SetVolumeMountPoint)(LPCTSTR,LPCTSTR);
 
void ErrorView();
 
int main()
{
        HANDLE hMount;
 
        char szPath[MAX_PATH],
                 szRecvBuff[MAX_PATH+1],
                 szFileSystem[MAX_PATH+1];
 
        HMODULE hmod;
        if((hmod = LoadLibrary("Kernel32.dll")))
        {
                if(!(FindFirstVolume  = (HANDLE(WINAPI *)
                        (LPTSTR,DWORD))GetProcAddress(hmod,"FindFirstVolumeA")))
                {cout<<"Error GetProcAddress...1"<<endl;return -1;}
                if(!(FindNextVolume   = (BOOL(WINAPI *)
                        (HANDLE,LPTSTR,DWORD))GetProcAddress(hmod,"FindNextVolumeA")))
                {cout<<"Error GetProcAddress...2"<<endl;return -1;}
                if(!(FindVolumeClose  = (BOOL(WINAPI *)
                        (HANDLE))GetProcAddress(hmod,"FindVolumeClose")))
                {cout<<"Error GetProcAddress...3"<<endl;return -1;}
                if(!(GetVolumeNameForVolumeMountPoint  = (BOOL(WINAPI *)
                        (LPCTSTR,LPTSTR,DWORD))GetProcAddress(hmod,
                        "GetVolumeNameForVolumeMountPointA")))
                {cout<<"Error GetProcAddress...4"<<endl;return -1;}
                if(!(DeleteVolumeMountPoint  = (BOOL(WINAPI *)
                        (LPCTSTR))GetProcAddress(hmod,"DeleteVolumeMountPointA")))
                {cout<<"Error GetProcAddress...5"<<endl;return -1;}
                if(!(SetVolumeMountPoint  = (BOOL(WINAPI *)
                        (LPCTSTR,LPCTSTR))GetProcAddress(hmod,"SetVolumeMountPointA")))
                {cout<<"Error GetProcAddress...6"<<endl;return -1;}
 
                hMount = FindFirstVolume(szPath,sizeof(szPath));
 
                UINT uin;
 
                if(hMount!=INVALID_HANDLE_VALUE)
                {
                        do
                        {
                                uin = GetDriveType(szPath);
                                if(uin==DRIVE_CDROM)      {cout<<"CDROM: ";}
                                if(uin==DRIVE_UNKNOWN)    {cout<<"UNKNOWN: ";}
                                if(uin==DRIVE_NO_ROOT_DIR){cout<<"NO_ROOT_DIR: ";}
                                if(uin==DRIVE_REMOVABLE)  {cout<<"REMOV: ";}
                                if(uin==DRIVE_FIXED)      {cout<<"FIXED: ";}
                                if(uin==DRIVE_REMOTE)     {cout<<"REMOTE: ";}
                                if(uin==DRIVE_RAMDISK)    {cout<<"RAMDISK: ";}
 
                                GetVolumeInformation(szPath,
                                                                szRecvBuff,
                                                                sizeof(szRecvBuff),
                                                                NULL,NULL,NULL,
                                                                szFileSystem,
                                                                sizeof(szFileSystem));
 
                                cout<<"("<<szRecvBuff
                                      <<"|"<<szFileSystem
                                      <<") "<<szPath<<endl<<endl;  
        
                                ZeroMemory(szRecvBuff,sizeof(szRecvBuff));
                                ZeroMemory(szFileSystem,sizeof(szFileSystem));
 
                        }while(FindNextVolume(hMount,szPath,sizeof(szPath))!=0);
                        
                        FindVolumeClose(hMount);
 
                }else{cout<<"Error FindFirstVolume"<<endl;}
 
                FreeLibrary(hmod);
                
        }else{cout<<"Error LoadLibrary"<<endl;}
                
        ZeroMemory(szRecvBuff,sizeof(szRecvBuff));
        char szDrive[4];DWORD dwID = GetLogicalDrives();
 
        for(int i = 0;i < 26;i++)
        {
           if(((dwID>>i)&0x00000001)==1)
           {
                 szDrive[0] =  char(65+i);
                 szDrive[1] = ':';
                 szDrive[2] = '\\';
                 szDrive[3] = 0;
                 GetVolumeNameForVolumeMountPoint(szDrive,
                                                                        szRecvBuff,
                                                                        sizeof(szRecvBuff));
                 cout <<szDrive<<" "<<szRecvBuff<<endl;
 
           }
        }
 
/************************************/
        if(DeleteVolumeMountPoint("G:\\"))
        {cout<<"DeleteVolumeMountPoint status:OK"<<endl;}
        else
        {cout<<"DeleteVolumeMountPoint status:ERROR"<<endl;ErrorView();}
        if(SetVolumeMountPoint("C:\\mnt\\",
                "\\\\?\\Volume{e7aaf23a-8560-11db-97d5-806d6172696f}\\"))
        {cout<<"SetVolumeMountPoint status:OK"<<endl;}
        else
        {cout<<"SetVolumeMountPoint status:ERROR"<<endl;ErrorView();}
/////////////////
        cout<<"(PAUSE)Press any key..."<<endl;
        while(!getch());
/////////////////
        if(DeleteVolumeMountPoint("C:\\mnt\\"))
        {cout<<"DeleteVolumeMountPoint status:OK"<<endl;}
        else
        {cout<<"DeleteVolumeMountPoint status:ERROR"<<endl;ErrorView();}
        if(SetVolumeMountPoint("G:\\",
                "\\\\?\\Volume{e7aaf23a-8560-11db-97d5-806d6172696f}\\"))
        {cout<<"SetVolumeMountPoint status:OK"<<endl;}
        else
        {cout<<"SetVolumeMountPoint status:ERROR"<<endl;ErrorView();}
/************************************/
 
        cout<<"Press any key to exit..."<<endl;
        while(!getch());
        return 0;
 
}
 
void ErrorView()
{
        LPVOID lpMsgBuf = NULL;
        FormatMessage
        (FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM,
        NULL,GetLastError(),
        MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
        (LPTSTR)&lpMsgBuf, 0, NULL);
        CharToOem((LPTSTR)lpMsgBuf,(LPTSTR)lpMsgBuf);
        cout<<(LPCTSTR)lpMsgBuf<<endl;
        LocalFree(lpMsgBuf);
}

А теперь подробней, по шагам:

HANDLE (WINAPI * FindFirstVolume) (LPTSTR,DWORD);
BOOL   (WINAPI * FindNextVolume) (HANDLE,LPTSTR,DWORD);
BOOL   (WINAPI * FindVolumeClose)(HANDLE);
BOOL   (WINAPI * GetVolumeNameForVolumeMountPoint) (LPCTSTR,LPTSTR,DWORD);
BOOL   (WINAPI * DeleteVolumeMountPoint) (LPCTSTR);
BOOL   (WINAPI * SetVolumeMountPoint) (LPCTSTR,LPCTSTR);

Создаются указатели на прототипы функций для последующей загрузки в них адресов функций.

hmod = LoadLibrary("Kernel32.dll"));

Загружаем необходимую библиотеку.

if(!(FindFirstVolume  = (HANDLE(WINAPI *)
(LPTSTR,DWORD))GetProcAddress(hmod,"FindFirstVolumeA")))
{cout<<"Error GetProcAddress...1"<<endl;return -1;}
if(!(FindNextVolume   = (BOOL(WINAPI *)
(HANDLE,LPTSTR,DWORD))GetProcAddress(hmod,"FindNextVolumeA")))
{cout<<"Error GetProcAddress...2"<<endl;return -1;}
if(!(FindVolumeClose  = (BOOL(WINAPI *)
(HANDLE))GetProcAddress(hmod,"FindVolumeClose")))
{cout<<"Error GetProcAddress...3"<<endl;return -1;}
if(!(GetVolumeNameForVolumeMountPoint  = (BOOL(WINAPI *)
(LPCTSTR,LPTSTR,DWORD))GetProcAddress(hmod,
"GetVolumeNameForVolumeMountPointA")))
{cout<<"Error GetProcAddress...4"<<endl;return -1;}
if(!(DeleteVolumeMountPoint  = (BOOL(WINAPI *)
(LPCTSTR))GetProcAddress(hmod,"DeleteVolumeMountPointA")))
{cout<<"Error GetProcAddress...5"<<endl;return -1;}
if(!(SetVolumeMountPoint  = (BOOL(WINAPI *)
(LPCTSTR,LPCTSTR))GetProcAddress(hmod,"SetVolumeMountPointA")))
{cout<<"Error GetProcAddress...6"<<endl;return -1;}

Далее получаем адреса необходимых нам функций.

hMount = FindFirstVolume(szPath,sizeof(szPath));
UINT uin;
if(hMount!=INVALID_HANDLE_VALUE)
{
        do
        {
                uin = GetDriveType(szPath);
                if(uin==DRIVE_CDROM)      {cout<<"CDROM: ";}
                if(uin==DRIVE_UNKNOWN)    {cout<<"UNKNOWN: ";}
                if(uin==DRIVE_NO_ROOT_DIR){cout<<"NO_ROOT_DIR: ";}
                if(uin==DRIVE_REMOVABLE)  {cout<<"REMOV: ";}
                if(uin==DRIVE_FIXED)      {cout<<"FIXED: ";}
                if(uin==DRIVE_REMOTE)     {cout<<"REMOTE: ";}
                if(uin==DRIVE_RAMDISK)    {cout<<"RAMDISK: ";}
                GetVolumeInformation(szPath, szRecvBuff,
                                                 sizeof(szRecvBuff), NULL,NULL,NULL,
                                                 szFileSystem,sizeof(szFileSystem));
                cout<<"("<<szrecvbuff
                       <<"|"<<szFileSystem
                       <<") "<<szPath<<endl<<endl;  
        
                ZeroMemory(szRecvBuff,sizeof(szRecvBuff));
                ZeroMemory(szFileSystem,sizeof(szFileSystem));
 
        }while(FindNextVolume(hMount,szPath,sizeof(szPath))!=0);
}

Производится поиск томов и вывод информации о них.

ZeroMemory(szRecvBuff,sizeof(szRecvBuff));
char szDrive[4];DWORD dwID = GetLogicalDrives();
for(int i = 0;i < 26;i++)
{
         if(((dwID>>i)&0x00000001)==1)
          {
                 szDrive[0] =  char(65+i);
                 szDrive[1] = ':';
                 szDrive[2] = '\\';
                 szDrive[3] = 0;
                 GetVolumeNameForVolumeMountPoint(szDrive,
                                                      szRecvBuff,
                                                     sizeof(szRecvBuff));
                 cout <<szDrive<<" "<<szRecvBuff<<endl;
 
           }
}

Здесь идет вывод информации вторым способом.

if(DeleteVolumeMountPoint("G:\\"))
{cout<<"DeleteVolumeMountPoint status:OK"<<endl;}
else
{cout<<"DeleteVolumeMountPoint status:ERROR"<<endl;ErrorView();}

Удаление точки монтирования, после выполнения данного участка кода, утилита mountvol покажет вам следующее:
Программно монтируем диски в директорию
Далее устанавливаем новую точку монтирования:

if(SetVolumeMountPoint("C:\\mnt\\",
"\\\\?\\Volume{e7aaf23a-8560-11db-97d5-806d6172696f}\\"))
{cout<<"SetVolumeMountPoint status:OK"<<endl;}
else
{cout<<"SetVolumeMountPoint status:ERROR"<<endl;ErrorView();}

и смотрим результат работы mountvol а также заходим в точку монтирования C:\mnt\ и видим там содержимое жесткого диска:
Программно монтируем диски в директорию
Ну а теперь возвращаем все как было, для этого следующий участок кода:

if(DeleteVolumeMountPoint("C:\\mnt\\"))
{cout<<"DeleteVolumeMountPoint status:OK"<<endl;}
else
{cout<<"DeleteVolumeMountPoint status:ERROR"<<endl;ErrorView();}
if(SetVolumeMountPoint("G:\\",
"\\\\?\\Volume{e7aaf23a-8560-11db-97d5-806d6172696f}\\"))
{cout<<"SetVolumeMountPoint status:OK"<<endl;}
else
{cout<<"SetVolumeMountPoint status:ERROR"<<endl;ErrorView();}

Результат работы программы вы можете видеть на рисунке, в последующем мне хотелось бы создать программу, которая будет для удобства иметь графический интерфейс….
Программно монтируем диски в директорию[/code]

Получение значений счетчиков производительности

В данной статье хочу показать, как можно получить значение счетчиков производительности вашего компьютера, при небольшой модификации кода можно так же получать значения счетчиков других машин.Подробнее »Получение значений счетчиков производительности

Создание драйверов. Часть 5. Фильтр драйвер

Создание драйверов. Часть 5. Фильтр драйвер. В этой части цикла статей, рассматривается создание и тестирование фильтр драйвера – это драйвер, основной функцией которого является обработка проходящих через него IRP пакетов, это возможно благодаря многоуровневой модели драйверов Windows, где несколько драйверов можно выстроить в одну цепочку, соответственно добавляя новые возможности нижележащему драйверу.Подробнее »Создание драйверов. Часть 5. Фильтр драйвер

Создание драйверов. Часть 4. Обмен данными

Создание драйверов. Часть 4. Обмен данными. В данной статье рассмотрены способы обмена данными между приложением и драйвером, при помощи рабочих процедур драйвера с IRP кодом IRP_MJ_READ, IRP_MJ_WRITE и IRP_MJ_DEVICE_CONTROL. Из второй части цикла статей и примеров по созданию и работе с драйверами, мы узнали, как отправлять драйверу IOCTL запросы, в зависимости от которых драйвер будет предпринимать те или иные действия.Подробнее »Создание драйверов. Часть 4. Обмен данными

Создание драйверов. Часть 3. Просмотр состояния драйверов

Создание драйверов. Часть 3. Просмотр состояния драйверов. В данном примере мне хотелось бы показать как с помощью интерфейса SCM(Service Control Manager) можно просмотреть состояние загруженных в системе драйверов. Для этой цели использовалась функция EnumServicesStatus, входящая в состав Advapi32.dll.Подробнее »Создание драйверов. Часть 3. Просмотр состояния драйверов

Создание драйверов. Часть 2

Создание драйверов. Часть 2. Начинаем наращивать наш драйвер, будем использовать скелет, который мы создали в прошлой статье. В данном примере мне хотелось бы объяснить, как осуществляется «общение» с драйвером.Подробнее »Создание драйверов. Часть 2

Создание драйверов. Часть 1

Создание драйверов. Часть 1. В данной статье мне хотелось бы показать, как создавать драйвера, если Вам необходима теоретическая информация то советую прочесть книгу Дэвида Соломона и Марка Руссиновича «Внутреннее устройство Microsoft Windows 2000». Для начала мы сделаем простой драйвер для Windows 2000, который послужит нам каркасом для дальнейших экспериментов. Для работы понадобится «Windows 2000 Driver Development Kit», именно с помощью данного пакета создаются драйвера, в его состав входят компилятор, линкер, заголовочные файлы, lib-файлы, документация, полезные инструменты и конечно множество примеров.Подробнее »Создание драйверов. Часть 1

Неавторизованная отправка почты

Неавторизованная отправка почты. В данном примере хочу Вам показать, как использовать неавторизованную отправку почты, то есть владелец электронного почтового ящика получает письмо от себя. Хочу сразу предупредить, что такой способ используют спамеры и это чревато проблемами с законодательством.Подробнее »Неавторизованная отправка почты

Raw сокеты WinSocket C++

Raw сокеты WinSocket C++. В данной статье – примере мне хотелось бы показать работу с простыми(raw) сокетами. Данные сокеты позволяют получить доступ к базовому протоколу передачи данных, это дает нам большие возможности создания таких сетевых утилит как Ping, Traceroute, а также для организации IP Spoofing, DDoS, ICMP-flood, и многого еще =) Рассматривать будем только протокол IP, так как большинство других протоколов вообще не поддерживают простые сокеты, разве только ATM.Подробнее »Raw сокеты WinSocket C++

Как узнать, сколько памяти занимает процесс

Как узнать, сколько памяти занимает процесс?

#include <iostream>
#include <windows.h>
#include <psapi.h>//Psapi.lib
using namespace std;
 
int main()
{
 
        DWORD pid;
        PROCESS_MEMORY_COUNTERS pmc;
 
        cout<<"Enter process PID: ";cin>>pid;
 
        HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS,FALSE,pid);
        if(NULL != hProcess)
        {
                if(GetProcessMemoryInfo(hProcess,&pmc,sizeof(pmc)))
                {
                        cout<<pmc.cb<<endl;
                        cout<<pmc.PageFaultCount/1024<<endl;
                        cout<<pmc.PeakWorkingSetSize/1024<<endl;
                        cout<<pmc.WorkingSetSize/1024<<endl;
                        cout<<pmc.QuotaPeakPagedPoolUsage/1024<<endl;
                        cout<<pmc.QuotaPagedPoolUsage/1024<<endl;
                        cout<<pmc.QuotaPeakNonPagedPoolUsage/1024<<endl;
                        cout<<pmc.QuotaNonPagedPoolUsage/1024<<endl;
                        cout<<pmc.PagefileUsage/1024<<endl;  
                        cout<<pmc.PeakPagefileUsage/1024<<endl;
                }
        }
        CloseHandle( hProcess );
        return 0;
}

Просматриваем заголовок исполняемого файла

Просматриваем заголовок исполняемого файла. В Интернете можно найти достаточное количество информации о формате исполняемых файлов. В данном примере мне хотелось бы показать Вам как можно получить данные из заголовка.Подробнее »Просматриваем заголовок исполняемого файла

Программно создаем динамическую иконку

Программно создаем динамическую иконку. Для создания динамической иконки (и не только) понадобится API функция:

HICON CreateIcon(HINSTANCE hInstance, int nWidth, int nHeight, BYTE cPlanes, BYTE cBitsPixel, CONST BYTE *lpbANDbits, CONST BYTE *lpbXORbits);
Подробнее »Программно создаем динамическую иконку