13 Security Lab

netstat 구현소스 분석 - wnetstat 본문

Computer Science/Projects

netstat 구현소스 분석 - wnetstat

Maj0r Tom 2012. 10. 14. 00:20

GetTcpTable MSDN : http://msdn.microsoft.com/en-us/library/windows/desktop/aa366026(v=vs.85).aspx

wnetstat 소스 실질적 netstat기능을 하는 함수부분 ; tcp 부분

 

void CWnetstatDlg::check()
{
	// TODO: Add your control notification handler code here
	numEntries = 0; //numEntries = 0; 는 class CWnetstatDlg 클래스의 멤버변수. 데이터개수 체크한다.
	bool found = false;
	CString msg = ""; //msg를 담기위한 스트링을 초기화시킨다.

	GetDlgItemText(IDC_EDIT_PORTFILTER, portFilter); //  콤보박스에서 받은 포트 필터링값
	GetDlgItemText(IDC_EDIT_IPFILTER, ipFilter);     //  콤보박스에서 받은 아이피 필터링값

	struct tm *utc_time; //time.h에 정의된 시간 구조체(초분시날달년 등 int변수를 멤버로 가짐 ex)int tm_sec;)
	time_t thetime; //마찬가지로 time 관련
	time(&thetime); //마찬가지 ㅡㅡ
	utc_time = gmtime(&thetime); // 이상 자세한 설명은 생략한다.
	CString tmp = ""; //tmp 스트링 선언 및 초기화
	tmp.Format("%02u-%02u-%04u %02u:%02u:%02u\r\n",(utc_time->tm_year + 1900), (utc_time->tm_mon + 1), utc_time->tm_mday, utc_time->tm_hour, utc_time->tm_min, utc_time->tm_sec);
          //여기따 년-월-일 시:분:초 
	log_str = tmp; //로그 기록할려고 담는듯 
	SetDlgItemText(IDC_EDIT_STATS, log_str); // 시간을 에디트박스에 드디어 찍는다.
	((CEdit *) GetDlgItem(IDC_EDIT_STATS))->LineScroll( ((CEdit *) GetDlgItem(IDC_EDIT_STATS))->GetLineCount(), 0);
         // 카운트해서 자동스크롤링
	char srcIpBuffer[128], dstIpBuffer[128], state[32], fullSrcBuffer[140], fullDstBuffer[140], localPortName[16], remotePortName[16];	unsigned short localPort, remotePort;
	int x, y, curr, breakOut = 0;

	srcIpBuffer[sizeof(srcIpBuffer)-1] = 0;
	dstIpBuffer[sizeof(dstIpBuffer)-1] = 0;

	fullSrcBuffer[sizeof(fullSrcBuffer)-1] = 0;
	fullDstBuffer[sizeof(fullDstBuffer)-1] = 0;

	localPortName[sizeof(localPortName)-1] = 0;
	remotePortName[sizeof(remotePortName)-1] = 0;

	log_str	+= "  Proto   Local Address             Remote Address     State\r\n";
        //각 필드를 나타냄
	if((protocolFilter.CompareNoCase("TCP") == 0) || (protocolFilter.CompareNoCase("NONE") == 0)) // TCP
	{//콤보박스에서 필터를 tcp로 하거나 선택안했을때,
		DWORD tcpTableSize = sizeof(MIB_TCPTABLE) * 128; //tcp table 사이즈 MIB_TCPTABLE는 아래 추가설명
		MIB_TCPTABLE *tcpTable = (MIB_TCPTABLE *)malloc(tcpTableSize); 
		tcpTable->dwNumEntries = 0; // tcp 데이터 개수 0개 초기화 

		GetTcpTable(tcpTable, &tcpTableSize, TRUE); //몽땅받아오긔
		numEntries += tcpTable->dwNumEntries; //tcp 연결 또는 오픈 개수만큼 카운트값 설정

		for (x = 0; x < (int)tcpTable->dwNumEntries; x++) //카운트값만큼 
		{
			breakOut = 0;

			if ((tcpTable->table[x].dwState == MIB_TCP_STATE_LISTEN) && (! 1/*netstat.display.allConnectAndListening*/))
				continue;

			// Hide subnet check.
			for (curr = 0; hideSubnets[curr].subnet; curr++)
			{
				DWORD currSubnet = inet_addr(hideSubnets[curr].subnet), currNetmask = inet_addr(hideSubnets[curr].netmask);

				// If this hosts matches one of the hide subnets.
				if ((breakOut = ((currSubnet & currNetmask) == (tcpTable->table[x].dwRemoteAddr & currNetmask))))
					break;						 
			}

			if (breakOut)
				continue;

			// Hide listen port check.

			localPort = ntohs((unsigned short)(tcpTable->table[x].dwLocalPort & 0xFFFF)); // 로컬포트부분스트링으로 바꿔서 저장한다.
			remotePort = ntohs((unsigned short)(tcpTable->table[x].dwRemotePort & 0xFFFF)); // 리모트포트

			if (tcpTable->table[x].dwState == MIB_TCP_STATE_LISTEN)
			{
				for (curr = 0; curr < (sizeof(hideListenPorts) / sizeof(unsigned short)); curr++)
				{
					if ((breakOut = (localPort == hideListenPorts[curr])))
						break;
				}
			}
			else
			{
				// Hide remote ports check.

				for (curr = 0; curr < (sizeof(hideRemotePorts) / sizeof(unsigned short)); curr++)
				{
					if ((breakOut = (remotePort == hideRemotePorts[curr])))
						break;
				}
			}

			if (breakOut)
				continue;

			resolveAddress(tcpTable->table[x].dwLocalAddr, srcIpBuffer, sizeof(srcIpBuffer)-1, 1);
			resolveAddress(tcpTable->table[x].dwRemoteAddr, dstIpBuffer, sizeof(dstIpBuffer)-1, 0);

			switch (tcpTable->table[x].dwState) // 연결상태
			{
				case MIB_TCP_STATE_CLOSED:
					strcpy(state,"CLOSED"); break;
				case MIB_TCP_STATE_LISTEN:
					strcpy(state,"LISTENING"); break;
				case MIB_TCP_STATE_SYN_SENT:
					strcpy(state,"SYN_SENT"); break;
				case MIB_TCP_STATE_SYN_RCVD:
					strcpy(state,"SYN_RCVD"); break;
				case MIB_TCP_STATE_ESTAB:
					strcpy(state,"ESTABLISHED"); break;
				case MIB_TCP_STATE_FIN_WAIT1:
					strcpy(state,"FIN_WAIT1"); break;
				case MIB_TCP_STATE_FIN_WAIT2:
					strcpy(state,"FIN_WAIT2"); break;
				case MIB_TCP_STATE_CLOSE_WAIT:
					strcpy(state,"CLOSE_WAIT"); break;
				case MIB_TCP_STATE_CLOSING:
					strcpy(state,"CLOSING"); break;
				case MIB_TCP_STATE_LAST_ACK:
					strcpy(state,"LAST_ACK"); break;
				case MIB_TCP_STATE_TIME_WAIT:
					strcpy(state,"TIME_WAIT"); break;
				case MIB_TCP_STATE_DELETE_TCB:
					strcpy(state,"DELETE_TCB"); break;
			}

			memset(fullSrcBuffer, 0, sizeof(fullSrcBuffer));
			memset(fullDstBuffer, 0, sizeof(fullDstBuffer));

			if (tcpTable->table[x].dwState == MIB_TCP_STATE_LISTEN)
				remotePort = 0;

			resolvePort(localPort, localPortName, sizeof(localPortName)-1, "TCP");
			resolvePort(remotePort, remotePortName, sizeof(remotePortName)-1, "TCP");
			

			_snprintf(fullSrcBuffer, sizeof(fullSrcBuffer) - 1, "%s:%s", srcIpBuffer, localPortName);
			_snprintf(fullDstBuffer, sizeof(fullDstBuffer) - 1, "%s:%s", dstIpBuffer, remotePortName);

			for (y = strlen(fullSrcBuffer); y < 23; y++)
				fullSrcBuffer[y] = ' ';

			for (y = strlen(fullDstBuffer); y < 23; y++)
				fullDstBuffer[y] = ' ';

			CString str = ""; // 연결상태 한라인 받을 스트링
			if( (stateFilter.CompareNoCase("NONE") == 0) &&
				(IsDlgButtonChecked(IDC_CHECK_PORTFILTER) == 0) &&
				(IsDlgButtonChecked(IDC_CHECK_IPFILTER) == 0) )
			{
				if (strlen(fullDstBuffer) >= 23)
					str.Format("  TCP    %23s%s  %s\r\n", fullSrcBuffer, fullDstBuffer, state); //연결 한라인 받기
				else
					str.Format("  TCP    %23s%s%s\r\n", fullSrcBuffer, fullDstBuffer, state);
			}
			else
			{
				CString pName = localPortName;
				CString aName = dstIpBuffer;
				if( ((stateFilter.CompareNoCase(state) == 0) || (stateFilter.CompareNoCase("NONE") == 0)) &&
					((IsDlgButtonChecked(IDC_CHECK_PORTFILTER) == 0) || (pName.Find(portFilter) != -1)) &&
					((IsDlgButtonChecked(IDC_CHECK_IPFILTER) == 0) || (aName.Find(ipFilter) != -1)) )
				{
					if (strlen(fullDstBuffer) >= 23)
						str.Format("  TCP    %23s%s  %s\r\n", fullSrcBuffer, fullDstBuffer, state);
					else
						str.Format("  TCP    %23s%s%s\r\n", fullSrcBuffer, fullDstBuffer, state);

					msg += str; // 이부분은 다른 부가기능을 위한것이므로 신경안써도된다 그냥 msg를 신경쓰지말자
					found = true;
				}
			}

			log_str += str; //연결 한라인을 루프마다 log_str에 차곡 차곡 쌓는다.
		}

		free(tcpTable);
	}
if(IsDlgButtonChecked(IDC_CHECK_LOG) != 0)
	{
		log << log_str; //로그 남기기위해  -> ofstream log;
	}

	SetDlgItemText(IDC_EDIT_STATS, log_str); //드디어 출력화면인 에디트컨트롤에 때려박는 부분ㅋㅋ
	((CEdit *) GetDlgItem(IDC_EDIT_STATS))->LineScroll( ((CEdit *) GetDlgItem(IDC_EDIT_STATS))->GetLineCount(), 0); //스크롤링해준다. 신경안써도됨
}
MIB_TCPTABLE 추가설명 & trace

"tcpmib.h"
typedef struct _MIB_TCPTABLE {
    DWORD dwNumEntries;
    MIB_TCPROW table[ANY_SIZE];
} MIB_TCPTABLE, *PMIB_TCPTABLE;

typedef MIB_TCPROW_LH MIB_TCPROW; //정의 부분

typedef struct _MIB_TCPROW_LH {
    union {
        DWORD dwState;       // Old field used DWORD type.
        MIB_TCP_STATE State; // New field uses enum type.
    };
    DWORD dwLocalAddr;
    DWORD dwLocalPort;
    DWORD dwRemoteAddr;
    DWORD dwRemotePort;
} MIB_TCPROW_LH, *PMIB_TCPROW_LH;
typedef enum {
    MIB_TCP_STATE_CLOSED     =  1,
    MIB_TCP_STATE_LISTEN     =  2,
    MIB_TCP_STATE_SYN_SENT   =  3,
    MIB_TCP_STATE_SYN_RCVD   =  4,
    MIB_TCP_STATE_ESTAB      =  5,
    MIB_TCP_STATE_FIN_WAIT1  =  6,
    MIB_TCP_STATE_FIN_WAIT2  =  7,
    MIB_TCP_STATE_CLOSE_WAIT =  8,
    MIB_TCP_STATE_CLOSING    =  9,
    MIB_TCP_STATE_LAST_ACK   = 10,
    MIB_TCP_STATE_TIME_WAIT  = 11,
    MIB_TCP_STATE_DELETE_TCB = 12,
} MIB_TCP_STATE;
Comments