MSVS

تعلم : قراءة جدول اتصالات TCP الفعالة

16 ردود في هذا الموضوع

كنت أتجول في بعض مواقع البرمجة الأجنبية فوجدت موضوعاً جميلاً عن فحص المنافذ الفعالة بواسطة الدالة GetTcpTable

أحببت أن أترجم لكم الدرس لتعم الفائدة ولكني خلال الترجمة وجدت أن الموضوع يحتاج لشرح أكثر فأحببت صياغة الموضوع من جديد ليكون انفع بإذن الله .

والآن ننتقل للدرس :

دوال الـ IP Helper API كثيرة و تزودنا بفوائد حول الشبكات (الحرفين IP هما اختصار للكلمتين Internet Protocol)

فمثلاً الوظيفة GetTcpTable تعطي معلومات عن جميع إتصالات البروتوكول TCP الفعالة .

فقط باستدعاء واحد للوظيفة السابقة ستحصل على جدول فيه حالة المنفذ و رقم المنافذ الفتوحة لهذا الاتصال و رقم الأيبي للطرفين .

ومع هذا لا تظن أن استخدام الوظيفة GetTcpTable إلى هذا الحد من البساطة :) سنحاول أن نأخذ مثال عملي يوضح لنا كيفية عمل هذه الدالة ثم ننتقل للوثائق ليكون عملنا موثق :) .

للإعلان عن الدالة GetTcpTable نكتب السطر التالي :

Declare Function GetTcpTable Lib "iphlpapi.dll" (ByRef pTcpTable As PMIB_TCPTABLE, _
                                                ByRef pdwSize As Long, _
                                                ByVal bOrder As Long) As Long

و منه يتضح لنا أن الدالة لها 3 بارامترات (وسائط) :

الأول : جدول الاتصالات الفعالة من نوع MIB_TCPTABLE

الثاني : حجم جدول الاتصالات الفعالة من نوع Long

الثالث: فرز الجدول من نوع Long

والآن أول خطوة هي الحصول على حجم البيانات في جدول اتصالاتTCP . نمرر للدالة البارامترات التالية :

الأول : 0

الثاني : رقم طويل من نوع Long

الثالث : 0

كالتلي :

Dim lngSize, lngRetVal As Long

lngRetVal = GetTcpTable(ByVal 0&, lngSize, 0)

والآن بعد تنفيذ الدالة السابقة سنحصل على معلومتين :

الأولى : حجم البيانات في جدول اتصالات TCP و يوضع في المتغير lngSize

الثانية : نتيجة العملية وتوضع في المتغير lngRetVal وهي تدل على نجاح العملية أو سبب فشلها .

هذه الثوابت هي تحليل للقيمة المعادة من الدالة :

Const ERROR_BUFFER_OVERFLOW = 111&
Const ERROR_INVALID_PARAMETER = 87
Const ERROR_NO_DATA = 232&
Const ERROR_NOT_SUPPORTED = 50&
Const ERROR_SUCCESS = 0&

والآن و بعد أن حصلنا على حجم بيانات الجدول TCP

و تأكدنا من نجاح العملية و أن النظام يدعم الـ IP Helper API

نلقي نظرة على وثائق مايكروسوفت عن الدالة GetTcpTable

DWORD GetTcpTable(
 PMIB_TCPTABLE pTcpTable, // buffer for the connection table
 PDWORD pdwSize,          // size of the buffer
 BOOL bOrder              // sort the table?
);

الكود السابق ييشرح لنا بنية الدالة GetTcpTable ونلاحظ أن الوسيط الأول من نوع PMIB_TCPTABLE .

هذه التركيبة (MIB_TCPTABLE) وكما في الوثائق فإن لها البنية التالية :

typedef struct _MIB_TCPTABLE {
 DWORD dwNumEntries;         // number of entries in the table
 MIB_TCPROW table[ANY_SIZE]; // array of TCP connections
} MIB_TCPTABLE, *PMIB_TCPTABLE;

وهنا نتوقف عند نقطتين :

النقطة الأولى :

توجد تركيبة أخرى إضافية وهي MIB_TCPROW و بنيتها كالتالي :

typedef struct _MIB_TCPROW {
 DWORD dwState;      // state of the connection
 DWORD dwLocalAddr;  // address on local computer
 DWORD dwLocalPort;  // port number on local computer
 DWORD dwRemoteAddr; // address on remote computer
 DWORD dwRemotePort; // port number on remote computer
} MIB_TCPROW, *PMIB_TCPROW;

و النقطة الثانية :

أن التركيبة MIB_TCPTABLE تحوي على عضوين :

1- dwNumEntries وهو من نوع Long وهذا لا إشكال فيه .

2- table[ANY_SIZE] وهو مصفوفة تركيبة من نوع MIB_TCPROW ، وهنا يقع الإشكال لمبرمجي الفيجوال بيسك .

وهو كيف سيتم الإعلان عن تركيبة (MIB_TCPTABLE) تحتوي على تركيبة (MIB_TCPROW) على شكل مصفوفة "متغيرة" ؟

في هذا الموضع لا تستطيع فيجوال بيسك أن تكون بمرونة C++ ولكن يمكن الإلتفاف على هذه النقطة بأن نحدد طول المصفوفة بـ 500 مثلاً أي 500 صف اتصال وهذا سقف لا اظن أن أي جهاز سيفتح اتصالات بهذا الكم . مع أني وجدت في بعض مواقع البرمجة الأجنبية من يحدد هذا العدد بـ 100 إتصال فقط . و اظنه كاف .

المهم ، نستطيع أن نحاكي تراكيب الـ C++ :) بالإعلان عن التركيبتين التاليتين :

Const MAX_ROW  As Integer = 500


Private Type MIB_TCPROW
   dwState As Long
   dwLocalAddr As Long
   dwLocalPort As Long
   dwRemoteAddr As Long
   dwRemotePort As Long
End Type

Private Type MIB_TCPTABLE
   dwNumEntries As Long                 ' number of entries in the table
   table(MAX_ROW) As MIB_TCPROW         ' array of TCP connections
End Type

لو كان إعلان التركيبة الثانية بهذا الشكل لأصدر لن االمصرف خطأ :

Private Type MIB_TCPTABLE
   dwNumEntries As Long                 ' number of entries in the table
   table() As MIB_TCPROW         ' array of TCP connections
End Type

والسبب هو أننا لم نحدد طول مصفوفة الـ MIB_TCPROW :

عموماً بهذا الإلتفاف نستطيع أن نعلن عن متغير من نوع MIB_TCPTABLE ونمرره كوسيط أول للدالة GetTcpTable التي ستضف فيها بيانات الاتصالات TCP الفعالة . على النحو التالي :

Dim tcpTable As MIB_TCPTABLE
   
lngRetVal = GetTcpTable(tcpTable, lngSize, 0)
)

كما أسلفنا فإن الوسيط الثاني و الذي هو lngSize يعبر عن حجم البيانات في الجدول ، وقد حصلنا عليه من استدعاء سابق لهذه الدالة .

إلى هنا نكتفي و سيكون لنا تكملة في القريب بإذن واحد أحد .

والسلام عليكم ورحمة الله وبركاته

0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه

شرح جميل وعلى فكرة هذه الدروس بعد فهمها جيدا تؤدي الى طريقة سهلة للبدء في بناء برامج ال FireWall بكل بساطة

0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه

Up

0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه

شكرا اخي العزيز و الى الاماااااااااااااااام

0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه

ها قد عدنا و الحمد لله لنكمل ما تبقى بإذن الله .

كنا قد توقفنا عند تعبئة المتغير tcpTable بالبيانات .

يمكنك الآن التجول داخل أعضاء المتغير tcpTable و اكتشاف البيانات التي حصلنا عليها وهذه الصورة توضح بنية المتغير :

TcpTableMembers.JPG

ولكي نعرض بيانات اتصالات Tcp الفعالة ضع في مشروعك أداة نص و لنفرض اسمها Text2 ثم ضع الكود التالي (طبعاً إضافة للشفرة اللازمة في الأعلى)تحت حدث النقر على زر أمر :

    Text2.Text = ""
   Text2.Text = "State " & vbTab & "LocalAddr " & vbTab & "LocalPort " & vbTab & "

RemoteAddr " & vbTab & "Remote Port "
   For i = 0 To tcpTable.dwNumEntries - 1
       
       Text2.Text = Text2.Text & _
                    vbNewLine & _
                    tcpTable.table(i).dwState & vbTab & vbTab & _
                    tcpTable.table(i).dwLocalAddr & vbTab & _
                    tcpTable.table(i).dwLocalPort & vbTab & vbTab & _
                    tcpTable.table(i).dwRemoteAddr & vbTab & vbTab & _
                    tcpTable.table(i).dwRemotePort
   
   Next i

ستظهر لك بيانات جدول شبيه بالتالي :

State  LocalAddr  LocalPort  RemoteAddr  Remote Port 
5 1273828948 42503  1405884107 20480
2  0 1540  0  42096
2  0 34835  0  19448
2  0 27397  0  62976
2  0 48385  0  32776
2  0 34560  0  52256
2  0 53255  0  42936
2  0 772  0  43776
2  0 37639  0  46248
2 1273828948 35584  0  45576
2  0 260  0  38552
2  0 56189  0  27712

ولكن ألا تلاحظ معي أن البيانات أعلاه مازالت غامضة ؟

هل يمكن أن يكون رقم الأيبي لجهازي هو 1273828948 ؟

وهل يمكن أن يكون رقم منفذ الاتصال في جهازي هو 42503 ؟

وهل الرقم 1405884107 هو رقم أيبي سيرفر الفريق العربي للبرمجة(كنت اتصفح الموقع لحظتها) ؟ 203.22.204.83

وهل المنفذ الفعال في سيرفر الموقع الذي اتصفحه هو 20480 ؟ 80

بيانات غامضة أليس كذلك !!!

حسناً ، ما رأيك لو قلت لك أن الرقم 1273828948 يعني الأيبي 84.22.237.75

و الرقم 42503 يعني المنفذ رقم 1958

و الرقم 1405884107 يعني الأيبي 203.22.204.83 (أيبي الفريق العربي للبرمجة)

و الرقم 20480 يعني المنفذ رقم 80

نعم هذه هي البيانات بعد إزالة الأقنعة :)

لا تقلق فالأمر أبسط مما تتوقع

نعود قليلاً لتركيبة MIB_TCPTABLE انظر للصورة :

MIB_TcpTable%20Struct.JPG

هذه الصورة توضح لنا التركيبة على مستوى الأعضاء ( لاحظ أن كل عضو حجمه 4 بايت = Long)

وعلى افتراض أن أول 4 بايت في المتغير = 9 0 0 0

و أن أول صف (أي الـ20 بايت من بعد الـ 4 بايت الأولى ) في جدول الـTCP هو كالتالي :

State	LocalAddr  LocalPort  RemoteAddr  Remote Port 
----------------------------------------------------------------------
2 1273828948 42503  1405884107 20480

لكان توزيع القيم على البياتات على النحو التالي :

TcpTableAnalyzer.JPG

من الصورة في الأعلى ستعرف كيف توصلنا لرقم الأيبي ، و زيادة في الشرح نقول :

حجم الرقم 1273828948 في الذاكرة يأخذ حيز بمقدار 4 بايت أي Dword .

فإذا حللنا قيمة كل بايت سنصل لرقم الأيبي . و لتحليل الرقم نتبع الآتي :

1273828948 / 256 = 4975894 و الباقي 84

4975894 / 256 = 19437 و الباقي 22

19437 / 256 = 75 و الباقي 237

75 / 256 = 0 و الباقي 75

فإذا ضممنا الأرقام السابقة سنحصل على

84.22.237.75

هذه العملية السابقة نستطيع تغليفها في الوظيفة التالية :

Private Function GetIpFromLong(lngIPAddress As Long) As String
   '
   Dim arrIpParts(3) As Byte
   CopyMemory arrIpParts(0), lngIPAddress, 4
   '
   GetIpFromLong = CStr(arrIpParts(0)) & "." & CStr(arrIpParts(1)) & "." & CStr(

arrIpParts(2)) & "." & CStr(arrIpParts(3))
   '
End Function

هذه الوظيفة تأخذ رقم طويل و تعيد رقم أيبي . الحقيقة لا أريد أن أشرحها كي لا يطول الموضوع .

حسناً ،،، بقي رقم المنفذ .

فكما قلنا أن الرقم 42503 يعني المنفذ رقم 1958 ، كيف يحدث هذا ؟

لو رجعنا للصورة الأخيرة لوجدنا أن الرقم 42503 حجمه 2 بايت .

البايت الأول قيمته 166

البايت الثاني قيمته 7

نضرب البايت الأول * 256

166 * 256 = 42496

البايت الثاني سيكون كالخارج من القسمة فإذا جمعناه مع الرقم السابق نحصل على الرقم 42503

من هنا أتانا هذا الرقم ، أما طريقة تحويله لرقم منفذ فكالتالي :

42503 / 256 = 166 والباقي 7

7 * 256 = 1792

------------------------------

نجمع النتيجتين = 1958

------------------------------

هذه العملية مغلفة بالوظيفة التالية :

Private Function GetTcpPortNumber(DWord As Long) As Long
   GetTcpPortNumber = DWord / 256 + (DWord Mod 256) * 256
End Function

والآن هذه الشفرة تقوم بعرض جدول اتصالات TCP النشيطة ، و إلى اللقاء في درس قادم :

'=========================================================================

Const MAX_ROW  As Integer = 500


Private Type MIB_TCPROW
   dwState As Long
   dwLocalAddr As Long
   dwLocalPort As Long
   dwRemoteAddr As Long
   dwRemotePort As Long
End Type

Private Type MIB_TCPTABLE
   dwNumEntries As Long                 ' number of entries in the table
   table(MAX_ROW) As MIB_TCPROW         ' array of TCP connections
End Type



'
Private Const ERROR_BUFFER_OVERFLOW = 111&
Private Const ERROR_INVALID_PARAMETER = 87
Private Const ERROR_NO_DATA = 232&
Private Const ERROR_NOT_SUPPORTED = 50&
Private Const ERROR_SUCCESS = 0&
'
Private Const MIB_TCP_STATE_CLOSED = 1
Private Const MIB_TCP_STATE_LISTEN = 2
Private Const MIB_TCP_STATE_SYN_SENT = 3
Private Const MIB_TCP_STATE_SYN_RCVD = 4
Private Const MIB_TCP_STATE_ESTAB = 5
Private Const MIB_TCP_STATE_FIN_WAIT1 = 6
Private Const MIB_TCP_STATE_FIN_WAIT2 = 7
Private Const MIB_TCP_STATE_CLOSE_WAIT = 8
Private Const MIB_TCP_STATE_CLOSING = 9
Private Const MIB_TCP_STATE_LAST_ACK = 10
Private Const MIB_TCP_STATE_TIME_WAIT = 11
Private Const MIB_TCP_STATE_DELETE_TCB = 12
'

Private Declare Function GetTcpTable Lib "iphlpapi.dll" _
               (ByRef pTcpTable As Any, _
                ByRef pdwSize As Long, _
                ByVal bOrder As Long) As Long
               
               
Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" _
               (ByRef pDest As Any, _
                ByRef pSource As Any, _
                ByVal Length As Long)

'
Private Sub Command1_Click()
   '
   Dim arrBuffer() As Byte
   Dim lngSize As Long
   Dim lngRetVal As Long
   Dim lngRows As Long
   Dim i As Long
   Dim TcpTableRow As MIB_TCPROW
   Dim lvItem As ListItem
   '
   ListView1.ListItems.Clear
   '
   lngSize = 0
   '

   lngRetVal = GetTcpTable(ByVal 0&, lngSize, 0)
   '
   
   If lngRetVal = ERROR_NOT_SUPPORTED Then
       
       'This API works only on Win 98//2000 and NT4 with SP4
       MsgBox "IP Helper is not supported by this system."
       Exit Sub
       '
   End If
   
   

  lngRetVal = GetTcpTable(ByVal 0&, lngSize, 0)
   
   
   Dim tcpTable As MIB_TCPTABLE
   
   lngRetVal = GetTcpTable(tcpTable, lngSize, 0)

   If lngRetVal = ERROR_SUCCESS Then
   
       '
       For i = 0 To tcpTable.dwNumEntries - 1
               
               'Add the data to the ListView control
               With tcpTable.table(i)
                   Set lvItem = ListView1.ListItems.Add(, , GetIpFromLong(.dwLocalAddr))
                   lvItem.SubItems(1) = GetTcpPortNumber(.dwLocalPort)
                   lvItem.SubItems(2) = GetIpFromLong(.dwRemoteAddr)
                   lvItem.SubItems(3) = GetTcpPortNumber(.dwRemotePort)
                   lvItem.SubItems(4) = GetState(.dwState)
               End With
       Next i
       '
   End If
   '

End Sub

Private Sub Command2_Click()
   Unload Me
End Sub

Private Function GetIpFromLong(lngIPAddress As Long) As String
   '
   Dim arrIpParts(3) As Byte
   CopyMemory arrIpParts(0), lngIPAddress, 4
   '
   GetIpFromLong = CStr(arrIpParts(0)) & "." & CStr(arrIpParts(1)) & "." & CStr(

arrIpParts(2)) & "." & CStr(arrIpParts(3))
   '
End Function

Private Function GetState(lngState As Long) As String
   '
   Select Case lngState
       Case MIB_TCP_STATE_CLOSED:     GetState = "CLOSED"
       Case MIB_TCP_STATE_LISTEN:     GetState = "LISTEN"
       Case MIB_TCP_STATE_SYN_SENT:   GetState = "SYN_SENT"
       Case MIB_TCP_STATE_SYN_RCVD:   GetState = "SYN_RCVD"
       Case MIB_TCP_STATE_ESTAB:      GetState = "ESTAB"
       Case MIB_TCP_STATE_FIN_WAIT1:  GetState = "FIN_WAIT1"
       Case MIB_TCP_STATE_FIN_WAIT2:  GetState = "FIN_WAIT2"
       Case MIB_TCP_STATE_CLOSE_WAIT: GetState = "CLOSE_WAIT"
       Case MIB_TCP_STATE_CLOSING:    GetState = "CLOSING"
       Case MIB_TCP_STATE_LAST_ACK:   GetState = "LAST_ACK"
       Case MIB_TCP_STATE_TIME_WAIT:  GetState = "TIME_WAIT"
       Case MIB_TCP_STATE_DELETE_TCB: GetState = "DELETE_TCB"
   End Select
   '
End Function


Private Function GetTcpPortNumber(DWord As Long) As Long
   GetTcpPortNumber = DWord / 256 + (DWord Mod 256) * 256
End Function

لا تنس أن تضيف أداة ListView للنموذج :)

والسلام عليكم ورحمة الله وبركاته

0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه

السلام عليكم

استاذي / محمد بدوي

يشرفي مرورك ، وبجهودك و بقية الإخوة يمكن عمل أكبر من مشروع FireWall

الأخ / HnHn

الأخ / eng_ashraf

شكراً لكما و أرجو أن يكون الشرح واضحاً .

والسلام عليكم

GetTcpTable.rar

0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه

اخي العزيز شكرا على مجهودتاك وارجوا ان تكمل المشوار فمنذ زمن طويل اقترح الاستاذ خضر ترزي ان يشرح مواضيع ال TCP IP والدخول فيها ولكنه تخوف من الدخول في هذه الامور لكي لا يتم استغلالها في غير محلها

ولكننا اخطئنا فعلينا تعلمها جميعا للدخول الى مستواى اكبر من نوعية البرمجة فلا نبقى في مستوى قواعد البيانات

0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه
ولكننا اخطئنا فعلينا تعلمها جميعا للدخول الى مستواى اكبر من نوعية البرمجة فلا نبقى في مستوى قواعد البيانات

صدقت يا أخي محمد ،

يجب أن ننتقل نقلة نوعية لنرتقي عن مستوى قواعد البيانات .

0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه

شكرا لك يا اخى على هذا الموضوع الشيقندعو الله ان يوفقك الى كل ماهو هو خير

0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه

اخي العزيز السلام عليكم ورحمة الله وبركاته

هل يمكن ان احصل على IP ADDRESS للجهاز فقط بحيث عند الضغط على الكوماند يظهر لي الايبي ادرس في التكست بوكس الخاصه به

ولك الشكر

ابو روان

0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه

طبعا لا اعرف ولا استطيع القول او الفعل لاعطي لك حقك مشكور اخي علي مجهودك وبارك الله فيك ......

والله الموفق

0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه

مشكور أخى و لزيادة الأفادة

http://www.allapi.net/apilist/3DBD57E6A4F4...A4BB2FE178.html

اخي العزيز السلام عليكم ورحمة الله وبركاته

هل يمكن ان احصل على IP ADDRESS للجهاز فقط بحيث عند الضغط على الكوماند يظهر لي الايبي ادرس في التكست بوكس الخاصه به

ولك الشكر

ابو روان

تفضل أخى

http://www.allapi.net/apilist/87CE0B960AB6...4C037C7234.html

0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه

جازاك الله خيرا يا اخي فعلا موضوع مهم جدا من زمان كنت انتظر هيك مواضيع .............................

وإن شاء الله حلم ك مبرمج عربي يتحقق و نخرج برامج تنافس على مستوى العالم............................

جاري فهم الموضوع لانه بده مخ مخه شوي

0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه

اولا شكرا لموضوعك وفعلا انا انفسى نعمل حاجة غير قواعد بيانات

2 - انا بطلب من اى حد يضيف موضوع فى اكواد يشرح كل دالو فى الكود وكل امر من اوامر الدالة وكل متغير زى ما انتا عملت كدة

3- انا طال منك بقى حاجة بما انكم فى المنتدى بتبحثو فى موضوع الحائط النارى انا عايز اعرف ازاى اقفل منفذ ف الجهاز

ويا سلام لو فى حاجة بتعرفك شكل الحزم اللى بيجى لبرنامج ومعنها من خلال اتصالة بالنت بس دى صعبة اتوقع الرد فى موضوع ازاى اتحكم فى منافذ الجهاز ولكم جزيل الشكر

ملحوظة: التوقيعات بتاعت الاعضاء دى رخمة بتقل التصفح وفى المنتديات الاجنبية بيمنعوها

0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه

جزاك الله كل خير يا خي وزادك علما نافع لك ولغيرك

0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه
زوار
This topic is now closed to further replies.

  • يستعرض القسم حالياً   0 members

    لا يوجد أعضاء مسجلين يشاهدون هذه الصفحة .