PDA

Просмотр полной версии : утилиты - icmprange, mbrscan


bons
22.12.2008, 22:22
написал недавно пару консольных утилит для Windows на языке C, решил выложить, может будут кому-то полезны.

icmprange

Утилита предназначена для посылки ICMP-запросов диапазону IP-адресов. То есть это примерно то же что и запуск nmap с ключом -sP. Вывод ведется по мере поступления ICMP-ответов поэтому неотсортирован

Пример использования:
icmprange 192.168.0.1-254 1000
где 1000 - таймаут в миллисекундах

Использовать можно например там где нет надобности или возможности применить более мощные инструменты

Исходный код:
#include <windows.h>
#include <winsock.h>
#include <stdio.h>

//Прототипы структур
typedef struct _REQUESTINFO {
void* replyBuf;
int ReplySize;
UINT addr;
} REQUESTINFO,*PREQUESTINFO;

typedef struct _IPRANGE {
BYTE Beg[4];
BYTE End[4];
} IPRANGE,*PIPRANGE;

//Прототипы функций
typedef DWORD (WINAPI *ICMPPARSEREPLIES)(
void* ReplyBuffer,
DWORD ReplySize
);

typedef DWORD (WINAPI * ICMPSENDECHO2)(
HANDLE IcmpHandle,
HANDLE Event,
PVOID ApcRoutine,
PVOID ApcContext,
UINT DestinationAddress,
LPVOID RequestData,
WORD RequestSize,
PVOID RequestOptions,
LPVOID ReplyBuffer,
DWORD ReplySize,
DWORD Timeout
);

typedef HANDLE (WINAPI * ICMPCREATEFILE)(void);

typedef BOOL (WINAPI * ICMPCLOSEHANDLE)(
HANDLE IcmpHandle
);

//Глобальные переменные
UINT nTotalRequests;
ICMPPARSEREPLIES PIcmpParseReplies;
ICMPSENDECHO2 PIcmpSendEcho2;
ICMPCREATEFILE PIcmpCreateFile;
ICMPCLOSEHANDLE PIcmpCloseHandle;

/*~~~~~~~~~~~~~~~~~~~~~~~~~~*/
//Распознать диапазон в виде строки
PIPRANGE ParceRangeString(char* cpStr, UINT* nAddresses)
{
UINT i, j, dwLen, b, e, n;
PCHAR pM;
PCHAR cpValues[4];
PIPRANGE range;
char buf[64];

dwLen = strlen(cpStr);
if(dwLen == 0)return NULL;
range = malloc(sizeof(IPRANGE));

cpValues[0] = cpStr; j=1; n=1;
for(i=0; i<dwLen; i++)
if(cpStr[i] == '.')
{
if(j == 4)
{
free(range);
return NULL;
}
cpValues[j++]=cpStr+i+1;
cpStr[i]=0;
}

if(j<4)
{
free(range);
return NULL;
}

for(j=0;j<4;j++)
{
if((pM = strchr(cpValues[j],'-'))==NULL)
b = e = atol(cpValues[j]);
else
{
*(pM++)=0;
b=atol(cpValues[j]);
e=atol(pM);
}

if((b>255)||(e>255))
{
free(range);
return NULL;
}

if(b>e)
{
free(range);
return NULL;
}
range->Beg[j]=b;
range->End[j]=e;
n = n*(e-b+1);
}
if(nAddresses)*nAddresses = n;
return range;
}
/*~~~~~~~~~~~~~~~~~~~~~~~~~~*/
//Вызывается системой после ICMP-запроса
void WINAPI IcmpCallback (PREQUESTINFO info)
{
UINT net_addr = htonl(info->addr);
UINT resp = PIcmpParseReplies(info->replyBuf, info->ReplySize);

if(resp)printf("%s\n", inet_ntoa(*(struct in_addr*)&net_addr));
free(info->replyBuf);
free(info);
nTotalRequests--;
return;
}

/*~~~~~~~~~~~~~~~~~~~~~~~~~~*/
//Послать ICMP-запрос по заданному адресу
PREQUESTINFO SendPing(PVOID hICMP, UINT addr, UINT timeout)
{
PREQUESTINFO info = malloc(sizeof(REQUESTINFO));
UINT dwRet, iErr, addr2;

info->addr = addr;
info->ReplySize = 40;

addr = htonl(addr);
dwRet = 0;
while(!dwRet)
{
info->replyBuf = malloc(info->ReplySize);
dwRet = PIcmpSendEcho2(hICMP, NULL, IcmpCallback, info, addr, NULL, 0, NULL, info->replyBuf, info->ReplySize, timeout);
if(!dwRet)
{
iErr = GetLastError();
if(iErr == ERROR_INSUFFICIENT_BUFFER)
{
free(info->replyBuf);
info->ReplySize = info->ReplySize*2;
if(info->ReplySize > 65535)
{
free(info);
return NULL;
}
continue;
}
if(iErr == ERROR_IO_PENDING)return info;

free(info);
return NULL;
}
}
return NULL;
}

/*~~~~~~~~~~~~~~~~~~~~~~~~~~*/
//ICMP-сканирование заданного диапазона с заданным таймаутом
void PingRange(PIPRANGE range, UINT timeout)
{
int i0, i1, i2, i3;
UINT addr=0, i=0;
PVOID hICMP = PIcmpCreateFile();

for(i0=range->Beg[0];i0<=range->End[0];i0++)
{
((UCHAR*)&addr)[3]=i0;
for(i1=range->Beg[1];i1<=range->End[1];i1++)
{
((UCHAR*)&addr)[2]=i1;
for(i2=range->Beg[2];i2<=range->End[2];i2++)
{
((UCHAR*)&addr)[1]=i2;
for(i3=range->Beg[3];i3<=range->End[3];i3++)
{
((UCHAR*)&addr)[0]=i3;
if(SendPing(hICMP, addr, timeout))i++;
}
}
}
}
nTotalRequests = i;
while(nTotalRequests>0)
{
SleepEx(INFINITE, TRUE);
}
PIcmpCloseHandle(hICMP);
}
/*~~~~~~~~~~~~~~~~~~~~~~~~~~*/
int main(int argc, char** argv)
{
UINT nAddresses, timeout = 1000;
PIPRANGE iprange;
WSADATA GInitData;
HANDLE hLib;

WSAStartup(0x0202, &GInitData);
if(argc < 2)
{
printf(" Usage: icmpscan ip_range [timeout]\n");
printf(" Example: icmpscan 192.168.0.1-254 5000\n");
return -1;
}
if(argc == 3)
{
timeout = atol(argv[2]);
if(!timeout)timeout = 1000;
}
hLib = LoadLibrary("Iphlpapi.dll");
if(!hLib)
{
printf("Iphlpapi.dll not found\n");
return -1;
}
PIcmpParseReplies = (ICMPPARSEREPLIES)GetProcAddress(hLib, "IcmpParseReplies");
PIcmpSendEcho2 = (ICMPSENDECHO2)GetProcAddress(hLib, "IcmpSendEcho2");
PIcmpCreateFile = (ICMPCREATEFILE)GetProcAddress(hLib, "IcmpCreateFile");
PIcmpCloseHandle = (ICMPCLOSEHANDLE)GetProcAddress(hLib, "IcmpCloseHandle");

if(!PIcmpParseReplies || !PIcmpSendEcho2 || !PIcmpCloseHandle || !PIcmpCreateFile)
{
printf("Needed functions not available\n");
return -1;
}

iprange = ParceRangeString(argv[1], &nAddresses);
printf("Scan %u addresses, timeout %u ms:\n", nAddresses, timeout);
if(!iprange)
{
printf("Invalid parameter\n");
return -1;
}
PingRange(iprange, timeout);
free(iprange);

WSACleanup();
return 0;
}


mbrscan

Утилита сканирует структуры MBR жестких дисков локального компьютера.
Пример вывода утилиты:
# MBR reader starts
HDD Disc Boot Addr Size FS SN mb/gb
------------------------------------------------------------------------
HDD0 C: + 0000003F 03A9A172 (07)NTFS A47B02F6 29 GB
HDD0 D: - 03A9A1F0 0EF7E8D1 (07)NTFS 32CC0564 119 GB

Код можно использовать например для расширения функционала руткита - поиск скрытых разделов, исследование жесткого диска

исходный код:

#include <stdio.h>
#include <windows.h>

char FAT[]="\x01\x04\x06\x0D\x0E";

typedef struct _HARDINFO
{
char nHard; //номер жесткого диска
void* hDrive; //хэндл жесткого диска
UINT dwSectorSize; //размер сектора
UINT bitsPerSector; //количество разрядов для адресации внутри сектора
UINT dwExtendedAddr; //адрес расширенного раздела

} HARDINFO, *PHARDINFO;

/*~~~~~~~~~~~~~~~~~~~~~~~~~~*/
//Узнать диск по серийному номеру
char GetDiscBySN(UINT SN)
{
UINT VolumeSerialNumber;
UINT ldrives = GetLogicalDrives();
char Drive[4]="X:\\";
int i;

for(i=2;i<25;i++)
if((ldrives & (1<<i)) != 0)
{
Drive[0] = 'A'+i;
switch(GetDriveType(Drive))
{
case DRIVE_CDROM:
break;

default:
GetVolumeInformation(Drive,
NULL,0,
&VolumeSerialNumber,
NULL,0,NULL,0
);
if(VolumeSerialNumber==SN)
return Drive[0];
}
}
return 0;
}
/*~~~~~~~~~~~~~~~~~~~~~~~~~~*/
//Узнать файловую систему диска по коду файловой системы
char* GetFileSystem(unsigned char code)
{
int i;

if((code==0x07)||(code==0x17))
return "NTFS ";
if(code==0x82)
return "ext2 ";
if(code==0x83)
return "ext3 ";
if((code==0x0B)||(code==0x0C))
return "FAT32 ";
for(i=0;i<sizeof(FAT);i++)
if(code==FAT[i])
return "FAT ";
return "? ";
}
/*~~~~~~~~~~~~~~~~~~~~~~~~~~*/
//Вывести текст ошибки
void AnalyzeError(int iErr, char* comment)
{
char locBuf[1024];

FormatMessage(
FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ARGUMENT_ARRAY,
0, iErr, 0, locBuf, sizeof(locBuf), 0
);
CharToOem(locBuf, locBuf);
printf("%s (%u) %s\n", comment, iErr, locBuf);
}
/*~~~~~~~~~~~~~~~~~~~~~~~~~~*/
//сдвинуть указатель
int MovePointer(PHARDINFO inf, UINT secpointer)
{
UINT iErr;
UINT HiPointer = secpointer>>(32-inf->bitsPerSector);
UINT LoPointer = secpointer<<(inf->bitsPerSector);

UINT bRetValue=SetFilePointer(inf->hDrive,LoPointer,&HiPointer,FILE_BEGIN);
if(bRetValue == -1)
{
iErr=GetLastError();
if(iErr!=NO_ERROR)
AnalyzeError(iErr, "# error at SetFilePointer: ");
}
return bRetValue;
}

/*~~~~~~~~~~~~~~~~~~~~~~~~~~*/
//Читать один сектор с жесткого диска
void* RawRead(PHARDINFO inf)
{
UINT iErr, SectorSize, nRead, i, n;
void* buf;

SectorSize = inf->dwSectorSize;

if(!SectorSize)SectorSize = 0x200;

buf = malloc(SectorSize);
while(!ReadFile(inf->hDrive, buf, SectorSize, &nRead, NULL))
{
iErr=GetLastError();
free(buf);
if((iErr == ERROR_INVALID_PARAMETER)&&(SectorSize<0x8000))
{
SectorSize = SectorSize*2;
buf = malloc(SectorSize);
continue;
}
AnalyzeError(iErr, "# error at ReadFile: ");
return NULL;
};
if(inf->dwSectorSize != SectorSize)
{
i = SectorSize; n = 0;
while(i = i/2)n++;
inf->bitsPerSector = n;
inf->dwSectorSize = SectorSize;
}

return buf;
}
/*~~~~~~~~~~~~~~~~~~~~~~~~~~*/
/*Изъять серийный номер для FAT или NTFS
abs_addr - адрес начала логического диска в секторах
Serial - адрес 8-байтного буфера для серийного номера
id - идентификатор файловой системы
*/
BOOL GetDiscSerial(PHARDINFO inf, UINT abs_addr, UCHAR* Serial, UCHAR id)
{
char* buf;
int i;

if(MovePointer(inf, abs_addr) == -1)return FALSE;
if((buf = RawRead(inf)) == NULL)return FALSE;

switch(id)
{
case 0x07: //NTFS
memcpy(Serial,buf+72,8);
break;

case 0x0E:
case 0x0C:
case 0x0B: //FAT32
memcpy(Serial,buf+67,4);
break;

default:
for(i=0; i<sizeof(FAT); i++)
if(id == FAT[i])
{
memcpy(Serial, buf+39, 4);
free(buf);
return TRUE;
}
return FALSE;
}
free(buf);
return TRUE;
}
/*~~~~~~~~~~~~~~~~~~~~~~~~~~*/
PHARDINFO Init(char n)
{
char HardDiskName[] = "\\\\.\\PHYSICALDRIVE0";
void* hDrive;
UINT iErr, dwSectorSize;
PHARDINFO inf;

HardDiskName[sizeof(HardDiskName)-2] = n+'0';

hDrive = CreateFile(
HardDiskName,
GENERIC_READ,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL, OPEN_EXISTING, 0, NULL
);

if(hDrive == INVALID_HANDLE_VALUE)
{
iErr = GetLastError();
if(iErr == ERROR_FILE_NOT_FOUND)return NULL;
AnalyzeError(iErr, "# Error at CreateFile: ");
return NULL;
}

inf = malloc(sizeof(HARDINFO));
inf->hDrive = hDrive;
inf->nHard = n;
inf->dwSectorSize = 0;

return inf;
}
/*~~~~~~~~~~~~~~~~~~~~~~~~~~*/
void DeInit(PHARDINFO inf)
{
CloseHandle(inf->hDrive);
free(inf);
}
/*~~~~~~~~~~~~~~~~~~~~~~~~~~*/
//Вывести список разделов из Partition Table в MBR
UINT ListMBR(PHARDINFO inf, UCHAR* pMBR, UINT dwMBRAddr)
{
UCHAR* pPart;
UCHAR id, active;
UINT ext = 0, secBegin, secLength, mbLength=0, gbLength=0;
UINT SectorSize, abs_addr, SN4;
UCHAR SN[8];
char* cpFS;
int i;

SectorSize = inf->dwSectorSize;
pPart = pMBR+0x01BE;

for(i=0; i<4; i++)
{
id = pPart[4];
if(!id)
{
pPart += 0x10;
continue;
}
secBegin = *(UINT*)&pPart[8];
secLength = *(UINT*)&pPart[12];
active = pPart[0];
if(active)active = '+';
else active = '-';
pPart += 0x10;
mbLength = secLength/(2*1024)*SectorSize/512;
gbLength = mbLength/1024;
abs_addr = dwMBRAddr + secBegin;

cpFS = GetFileSystem(id);

if((id == 0x0F)||(id == 0x05))
{
ext=secBegin;
continue;
}
memset(SN, 0,sizeof(SN));
GetDiscSerial(inf, abs_addr, SN, id);
memcpy(&SN4, SN, 4);

printf("HDD%c %c: %c %08X %08X (%02X)%s %08X %u %s\n",
'0'+inf->nHard,
SN4?GetDiscBySN(SN4):'?',
active,
abs_addr, secLength, id, cpFS,
SN4,
gbLength?gbLength:mbLength,
gbLength?"GB":"MB"
);
GetDiscBySN(SN4);
}
return ext;
}
/*~~~~~~~~~~~~~~~~~~~~~~~~~~*/
//Печатать заголовок
void PrintHead()
{
printf("# MBR reader starts\n");
printf("HDD Disc Boot Addr Size FS SN mb/gb\n");
printf("------------------------------------------------------------------------\n");
}
/*~~~~~~~~~~~~~~~~~~~~~~~~~~*/
//Проверить сигнатуру
BOOL CheckMBR(UCHAR* pMBR)
{
BOOL bRetValue=*(USHORT*)(pMBR+0x01FE)==0xAA55;
if(!bRetValue)printf("# invalid MBR\n");
return bRetValue;
}
/*~~~~~~~~~~~~~~~~~~~~~~~~~~*/
//Пройтись по цепочке MBR
BOOL WalkOnMBR(PHARDINFO inf)
{
UINT ext, dwNextMBRAddr;
void* pMBR;

if((pMBR = RawRead(inf)) == NULL)return FALSE;
if(!CheckMBR(pMBR))
{
free(pMBR);
return FALSE;
}
if(ext = ListMBR(inf,pMBR,0))
{
inf->dwExtendedAddr = ext;
ext=0;
while(1)
{
free(pMBR);
dwNextMBRAddr = ext + inf->dwExtendedAddr;
if(MovePointer(inf, dwNextMBRAddr) == -1)return FALSE;
if((pMBR = RawRead(inf)) == NULL)return FALSE;
if(!CheckMBR(pMBR))
{
free(pMBR);
return FALSE;
}
if(!(ext = ListMBR(inf, pMBR, dwNextMBRAddr)))break;
}
}
free(pMBR);
return TRUE;
}
/*~~~~~~~~~~~~~~~~~~~~~~~~~~*/
//Точка входа
int main(int argc, char** argv)
{
PHARDINFO inf;
UCHAR nHDD = 0;

PrintHead();
while(inf = Init(nHDD))
{
WalkOnMBR(inf);
DeInit(inf);
nHDD++;
}
}

http://slil.ru/26470215
De-v: вещь полезная прикреплю файлы к посту)

criz
22.12.2008, 22:46
Полезные вещи :) спасибо за сорцы)

Delimiter
22.12.2008, 23:33
маладец! 8)) ...

только лучше в министатьи!

De-visible
22.12.2008, 23:42
ТС, повторюсь, очень даже не плохо))), вообщем если согласен, то офрми красивенько и запости в министатьи))
---
p.s. Delimiter приведддд)))

Delimiter
22.12.2008, 23:43
да да ... оформи тока!!! 8))
________________________________
De-visible привед!!!

bons
23.12.2008, 01:23
полагаю, что статья, даже мини, должна чему-то учить, в статье должен быть какой-то материал для развития. А здесь просто исходники.
Запостил ссылку сюда в теме "Полезные программы[С/С++, C#, Delphi, .NET, Asm]" .

slesh
23.12.2008, 16:45
В принципе полезно, в особенности mbr. Ping - можно и более проще реализовать )

p.s. IcmpCloseHandle - под NT видными лучше не использовать. Ошибку в программе часто выдает.

ss88
23.12.2008, 17:13
2bons ты бы сигнатур файловых систем для наглядности добавил бы, а то только 4 штуки ;)

bons
23.12.2008, 17:46
IcmpCloseHandle - под NT видными лучше не использовать. Ошибку в программе часто выдает.

в какой-то статье видел подобную информацию, но...
тестировал на WinXP SP2 и SP3 ошибки не было, все в порядке. В MSDN тоже ничего не сказано.. Если действительно проблема актуальна то код изменю..

2bons ты бы сигнатур файловых систем для наглядности добавил бы, а то только 4 штуки

Там проверка на 5 самых распространенных ФС. Можно было бы и больше распознавать но я не нашел точный полный список кодов файловых систем

slesh
24.12.2008, 00:56
На зчет закрытия дескриптора - то возможно си проверяет данные исключения автоматом. А вот проги на делфье порой вылетают и на XP SP2 и на W2K3

Gar|k
05.06.2009, 02:23
2 bons можешь обяснить дураку... пишу подобную программу (я про mbr)
ну получил я разобрал таблицу разделов посмотрел смещение сектора secBegin расширеного раздела.... делаю так (ибо у тебя не понял как, пытаюсь разобратся)

LARGE_INTEGER offset;
offset.QuadPart=secBegin;
SetFilePointer(hFile,offset.LowPart,&offset.HighPart,FILE_BEGIN);

ну если передавать смешение активного раздела правильно показывает... а пытаюсь подать смещение расширеного фигню показывает... чето там мне говорили типа надо + смещение mbr... в общем как выполняется переход по расширеным разделам этим? (

bons
05.06.2009, 15:20
сначала надо разобрать главную mbr, смещение расширенного раздела запомнить.(допустим это будет extended_addr). По этому смещению(относительно начала диска) будет расположена следующая mbr (вторичная). Таблица разделов в ней содержит 2 элемента - смещение логического диска (относительно extended_addr) и смещение следующей mbr (тоже относительно extended_addr). В следующей mbr точно также два элемента и все смещения там указаны относительно extended_addr. Так устроена цепочка mbr, в конце цепочки смещение следующего mbr будет 0.

Во всех таблицах смещения указаны в секторах, а ты с ними обращаешься так как будто это байты. Для всех жестких дисков размер сектора 512 байт, для некоторых флешек он другой

DESASDA
07.11.2009, 23:51
Может кто-нить перезалить исходники! Спасибо!

fker
08.11.2009, 00:14
https://forum.antichat.ru/attachment.php?attachmentid=1121
внимательней смотри, в первом посте все есть.