Сканер портов на c

Так сложилось, что я занимался оффлайн технологиями, а потом открыл для себя прекрасный мир программирования для сетей.

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

Мы напишем консольный сканер портов, выводящий список открытых. Сканировать все порты в один поток утомительно, поэтому мы используем заранее заготовленный список интересных портов с их описанием.

wasm

#include "windows.h"

#define port_closed 0
#define host_unresolved -1
#define port_open 1

void PrintConsoleRN(char* data);
BOOL WsaInit();
void PortScan(char* host);
BOOL Utf16_to_Utf8(WCHAR* data_w, char* data_a, int len);

void entry()
{
	//проверим параметры командной строки
	int cmd_num = 0;
	LPWSTR* cmd = CommandLineToArgvW(GetCommandLineW(), &cmd_num);
	if (cmd_num < 2)
	{
		PrintConsoleRN("too few arguments!");
		PrintConsoleRN("format:\t portscan.exe site.com\r\n");
	}
	else{
		//нам дали второй параметр (первый это путь до нашего exe)
		char host[512];
		if (Utf16_to_Utf8(cmd[1], host, sizeof(host)))
		{
			if (WsaInit())
			{
				PortScan(host);
				WSACleanup();
			}
		}
	}
	ExitProcess(0);
}

//проверим состояние порта
DWORD CheckConnection(char* host, WORD port)
{
	DWORD rezult = host_unresolved;

	hostent *hostInfo;
	sockaddr_in Destination_Addr;
	SOCKET m_Socket;

	if (hostInfo = gethostbyname(host))
	{
		Destination_Addr.sin_family = AF_INET;
		Destination_Addr.sin_port = htons(port);
		Destination_Addr.sin_addr = *((struct in_addr *)hostInfo-&gt;h_addr);
		memset(&(Destination_Addr.sin_zero), 0, 8);
		if ((m_Socket = socket(AF_INET, SOCK_STREAM, IPPROTO_IP)) != SOCKET_ERROR)
		{
			if (connect(m_Socket, (sockaddr*)&Destination_Addr, sizeof(sockaddr)) == NULL)
			{
				rezult = port_open;
			}
			else{
				rezult = port_closed;
			}
			closesocket(m_Socket);
		}
	}
	return rezult;
}

//выводим строку в консоль
void PrintConsole(char* data)
{
	static HANDLE std = 0;
	if (!std) std = GetStdHandle(STD_OUTPUT_HANDLE);
	DWORD writen;
	WriteFile(std, data, lstrlenA(data), &writen,0);
}

//вывод с переходом на след. строку
void PrintConsoleRN(char* data)
{
	PrintConsole(data);
	PrintConsole("\r\n");
}

void PrintPortStatus(char* host, WORD port, char* port_desc, BOOL open)
{
	char buf[1024];
	char* mask;

	//проверка не переполнение буфера
	if (port_desc&& host && (lstrlenA(host) + 10) < sizeof(buf))
	{
		if (open) mask = "%s\t%s\t%d\t OPEN";
		else mask = "%s\t%s\t%d\t closed";
		wsprintfA(buf, mask, host, port_desc, port);
		//выведем в консоль
		PrintConsoleRN(buf);
	}
}

/*
список интересных портов и их описание
*/
WORD PORT_LIST[] = { 80, 443, 5222, 21, 22 };
char port_name[sizeof(PORT_LIST) / 2][128] = { "http", "https", "xmpp", "ftp", "ssh" };


void PortScan(char* host)
{
	for (WORD i = 0; i < sizeof(PORT_LIST) / 2; i++)
	{
		WORD port = PORT_LIST[i];
		char* port_desc = port_name[i];

		DWORD s = CheckConnection(host, port);
		if (s == port_open)
		{ 
			PrintPortStatus(host, port, port_desc, true);
		}
		else if (s == port_closed){
			PrintPortStatus(host, port, port_desc, false);
		}
		else if (s == host_unresolved){
			PrintConsoleRN("cant resolve addr");
			break;
		}
	}
}

//для тех кто не знал,
//windows unicode это utf16
BOOL Utf16_to_Utf8(WCHAR* data_w,char* data_a, int len)
{
	//есть такой афоризм, что
	//хороший код должен на большую часть состоять из проверок
	if (data_w && data_a && len)
	{
		int size_w = lstrlenW(data_w);
		if (len &gt;= size_w)
		{
			int out = WideCharToMultiByte(CP_UTF8, 0, data_w, size_w, data_a, len, 0, 0);
			if (out == size_w) return true;
		}
	}
	return false;
}

BOOL WsaInit()
{
	WSADATA wsaData;
	if (WSAStartup(MAKEWORD(1, 1), &wsaData) == 0) return true;
	return false;
}

Вот собственно и весь код, не знаю что тут можно прокомментировать, если вы не работали с сокетами, прочите Руководство по сокетам.
p.s Не забудьте собрать проект как консольный!

2 thoughts on “Сканер портов на c

  1. ну что ж, си это конечно круто и быстро, но порой приходиться что то поправить\добавить в код, и в этом случае удобнее использовать не компилируемые языки программирования, я предпочитаю python(по старой привычке вторую ветку, для третьей изменения должны быть минимальны), так что вот пример многопоточного сканера портов :

    #!/usr/bin/env python
    from threading import Thread
    import subprocess
    from Queue import Queue
    import socket

    def portscanner(ip, start_port, end_port, numthreads):
    num_threads = numthreads
    queue = Queue()

    ran= []
    for p in xrange(start_port, end_port+1):
    ran.append(ip +”:”+str(p))

    def check(ipport):
    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    sock.settimeout(1.5)#timout
    ip=ipport[:ipport.find(“:”)]
    port=ipport[ipport.find(“:”)+1:].replace(“\n”, “”)
    result = sock.connect_ex((ip, int(port)))
    sock.close()
    if result == 0:
    return str(ip)+” “+str(port)+ ” open”
    else:
    return “close”

    def scan(i, q):
    while True:
    ip = q.get()
    wi = check(ip)
    if wi != “close”:
    print wi
    q.task_done()

    for i in range(num_threads):
    worker = Thread(target=scan, args=(i, queue))
    worker.setDaemon(True)
    worker.start()

    for ip in ran:
    queue.put(ip)

    queue.join()

    #Example: portscanner(‘127.0.0.1’, 1, 1000, 150)# ip address , start port, end port, num threads

    Используемые модули есть из коробки после установки python`а.
    P.S.
    сильно не пинать написано было быстро и на коленке для теста)

Добавить комментарий