написал недавно пару консольных утилит для Windows на языке C, решил выложить, может будут кому-то полезны. icmprange Утилита предназначена для посылки ICMP-запросов диапазону IP-адресов. То есть это примерно то же что и запуск nmap с ключом -sP. Вывод ведется по мере поступления ICMP-ответов поэтому неотсортирован Пример использования: Code: icmprange 192.168.0.1-254 1000 где 1000 - таймаут в миллисекундах Использовать можно например там где нет надобности или возможности применить более мощные инструменты Исходный код: Code: #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 жестких дисков локального компьютера. Пример вывода утилиты: Code: # 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 Код можно использовать например для расширения функционала руткита - поиск скрытых разделов, исследование жесткого диска исходный код: Code: #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: вещь полезная прикреплю файлы к посту)
ТС, повторюсь, очень даже не плохо))), вообщем если согласен, то офрми красивенько и запости в министатьи)) --- p.s. Delimiter приведддд)))
полагаю, что статья, даже мини, должна чему-то учить, в статье должен быть какой-то материал для развития. А здесь просто исходники. Запостил ссылку сюда в теме "Полезные программы[С/С++, C#, Delphi, .NET, Asm]" .
В принципе полезно, в особенности mbr. Ping - можно и более проще реализовать ) p.s. IcmpCloseHandle - под NT видными лучше не использовать. Ошибку в программе часто выдает.
в какой-то статье видел подобную информацию, но... тестировал на WinXP SP2 и SP3 ошибки не было, все в порядке. В MSDN тоже ничего не сказано.. Если действительно проблема актуальна то код изменю.. Там проверка на 5 самых распространенных ФС. Можно было бы и больше распознавать но я не нашел точный полный список кодов файловых систем
На зчет закрытия дескриптора - то возможно си проверяет данные исключения автоматом. А вот проги на делфье порой вылетают и на XP SP2 и на W2K3
2 bons можешь обяснить дураку... пишу подобную программу (я про mbr) ну получил я разобрал таблицу разделов посмотрел смещение сектора secBegin расширеного раздела.... делаю так (ибо у тебя не понял как, пытаюсь разобратся) LARGE_INTEGER offset; offset.QuadPart=secBegin; SetFilePointer(hFile,offset.LowPart,&offset.HighPart,FILE_BEGIN); ну если передавать смешение активного раздела правильно показывает... а пытаюсь подать смещение расширеного фигню показывает... чето там мне говорили типа надо + смещение mbr... в общем как выполняется переход по расширеным разделам этим? (
сначала надо разобрать главную mbr, смещение расширенного раздела запомнить.(допустим это будет extended_addr). По этому смещению(относительно начала диска) будет расположена следующая mbr (вторичная). Таблица разделов в ней содержит 2 элемента - смещение логического диска (относительно extended_addr) и смещение следующей mbr (тоже относительно extended_addr). В следующей mbr точно также два элемента и все смещения там указаны относительно extended_addr. Так устроена цепочка mbr, в конце цепочки смещение следующего mbr будет 0. Во всех таблицах смещения указаны в секторах, а ты с ними обращаешься так как будто это байты. Для всех жестких дисков размер сектора 512 байт, для некоторых флешек он другой