[PyHack] Bài 3: Network Scanner – Quét thông tin mạng
![](https://rathuuich.com/wp-content/uploads/2024/03/42-4.png)
Thu thập thông tin là một trong những bước quan trọng nhất để pentesting hoặc tấn công victim, mà cụ thể ở đây là network scanner (quét mạng). Bạn không thể truy cập vào một hệ thống nếu bạn không có đủ thông tin về nó. Ví dụ cho dễ hiểu: giả sử bạn đang kết nối với network và một trong những thiết bị kết nối với network này là mục tiêu của bạn. Bạn cần phải biết tất cả các máy được kết nối với network rồi lấy MAC của chúng và sau đó cố gắng thu thập thông tin để có thể truy cập vào mục tiêu của bạn.
Ở bài này, mình sẽ hướng dẫn các bạn cách xây một máy quét mạng (nghe chuối thật sự, từ giờ mình sẽ dùng từ network scanner) bằng python.
Chuẩn bị Lab
Trong lab bao gồm 2 máy ảo:
- Windows XP: Các bạn download file ISO và cài đặt Windows XP trên VMware. Key Windows XP là QW4HD-DQCRG-HM64M-6GJRK-8K83T.
- Kali Linux: Các bạn xem bài hướng dẫn cài đặt Kali Linux trên VMware tại đây.
Lưu ý: Các máy ảo đều sử dụng kiểu kết nối là NAT. Subnet IP trên Nat là 192.168.75.0. Máy Kali sẽ quét Windwos XP để thử nghiệm phần mềm network_scanner.
Scapy là gì?
Scapy là một trình thông dịch Python cho phép bạn tạo, giả mạo hoặc giải mã các gói tin trên network, hoặc bắt các gói và phân tích chúng,… Nó cũng cho phép bạn tiêm (inject) các gói tin vào mạng. Scapy còn hỗ trợ một số lượng lớn các giao thức mạng và nó có thể xử lý và thao tác với các gói tin truyền thông không dây ( wireless communication packets).
Scapy có thể được sử dụng để thay thế công cụ mạng, chẳng hạn như nmap, hping, arpscan, tshark và wireshark.
Nguyên lý hoạt động của Scapy là gửi và nhận các gói tin, nó còn có thể đánh hơi các gói tin khác nữa. Các packets được gửi có thể được tạo dễ dàng bằng cách sử dụng các tùy chọn tích hợp sẵn và phân tích các gói tin đã bắt được. Bắt được các packets giúp ta hiểu được những gì đang diễn ra trên mạng (nhà mình).
ARP là gì?
Hiện nay, có rất nhiều cách để khám phá các máy khác trong cùng 1 mạng. Đơn giản nhất là giả lập những gì một thiết bị bình thường sẽ làm để khám phá một thiết bị khác trên cùng một mạng.
Ví dụ, giả sử mình có thiết lập một lab như mình dưới.
Chúng ta có các thiết bị ABC và D. Tất cả chúng đều được kết nối với router. Chúng ta có thể thấy rằng mỗi thiết bị đều có IP và MAC riêng. Bây giờ, ví dụ thiết bị A cần liên lạc với thiết bị C. Máy A biết IP của máy C. Nhưng như chúng ta đã biết, để các thiết bị giao tiếp trong cùng một mạng, máy A cần biết địa chỉ MAC của máy C vì các máy sử dụng MAC để giao tiếp chứ không phải là địa chỉ IP.
Để 2 máy có thể giao tiếp với nhau, chúng sẽ sử dụng một giao thức gọi là APRP, viết tắt của giao thức phân giải địa chỉ. Và đó là một giao thức rất đơn giản cho phép chúng ta liên kết địa chỉ IP với địa chỉ MAC.
Để biết địa chỉ MAC của máy C, máy A cần sử dụng giao thức ARPU. Về cơ bản, máy A sẽ gửi một packets gồm địa chỉ MAC của chính nó và địa IP của target (máy C) tới tất cả các máy trong mạng.
Bây giờ, tất cả các máy sẽ không phản hồi lại packets này ngoại trừ máy có IP là 10.0.2.6, cũng chính là máy C.
Thiết bị C sẽ phản hồi lại gói packets này, dưới dạng, tôi là máy có IP là 10.0.2.6 và MAC của tôi là 00:11:22:33:44:66. Xong rồi, nó đơn giản vậy đó.
Kiểm tra bao nhiêu thiết bị được kết nối với router
Do subnet IP của NAT là 192.168.75.0 nên mình sẽ dò trong mạng này có bao nhiêu thiết bị kết nối với router, NAT bây giờ đang đóng vai trò là router.
Tại sao chỗ IP mình phải thêm “/24”? Vì “/24” có nghĩa là ta sẽ sử dụng 24 bit cho phần Network ID, và còn lại 8 bit cho Host ID. Nói cho dễ hiểu chương trình sẽ quét từ dãy ip 192.168.75.0 đến 192.168.75.255, cũng chính là subnet IP của NAT, các bạn đọc bài này để hiểu thêm nhé.
Sử dụng ARPU trong Python
Như đã nói ở trên phần ARP là gì? Chúng ta sẽ sử dụng giao thức ARPU để gửi một gói packets gồm địa chỉ IP của target, sau đó target sẽ phản hồi lại gói tin này và sẽ gửi trả lại về MAC của mình cho chúng ta.
Tại sao ARP nó lại hỏi thằng nào có IP là 0.0.0.0 thế nhỉ? Mà sao ARP lại trả lời là 0.0.0.0, chắc là không có máy nào có IP là 0.0.0.0 nên nó hiển thị vậy. Vậy làm sao để cho ARP hỏi IP khác. Trước tiên, ta phải biết tại sao ARP lại hỏi IP 0.0.0.0 thì ta dùng hàm ls().
Hàm này sẽ hiện thị các trường mặc định trong ARP.
Các bạn để ý phần pdst do nó đang là None nên sẽ bằng 0.0.0.0. Vậy làm sao để ta thay đổi nó? Đơn giản lắm, bạn chỉ cần thêm parameters là pdst và gán ip là arguments trong hàm scapy.ARP()
. Và nhớ là bỏ /24 đi nhé, vì bây giờ ta không cần phải tìm kiếm ip trong dãy từ 0 đến 255 nữa.
Chúng ta đã tạo thành công một gói request ARP rồi đó. Để xem thêm thông tin về gói ta dùng hàm show()
.Nếu bạn để ý thì MAC của packets vừa tạo cũng là MAC của máy.
Các bạn lưu ý chỗ này để tránh nhầm lẫn, sở dĩ nó có MAC trùng với Kali là vì target ip (ip mà packets này sẽ gửi đến) của packets này là 192.168.75.128, cũng chính là ip của Kali. Nói cách khác, nó đang tự gửi packets đến Kali rồi lấy MAC của Kali.
Note: hwdst và pdst là MAC và IP máy gửi packets (Kali), còn hwsrc và psrc là MAC và IP máy nhận (phản hồi) packets mà mình gửi.
Vậy làm sao để chúng ta thay đổi ip để lấy MAC của máy khác? Trước tiên ta phải biết dst của broadcast là gì, sau đó đặt target MAC thành broadcast.
Tại sao phải đổi target MAC thành broadcast? Như ở trên đã nói, chúng ta cần phải gửi packets ARP này cho tất cả các máy trong mạng. Và để làm được điều đó, chúng ta cần đổi target MAC thành broadcast để nó gửi packets cho tất cả các thiết bị trong mạng.
Những gì chúng ta cần làm tiếp theo là tạo ra một packets mới là sự kết hợp của 2 gói trước (ARP và Broadcast) mà ta đã tạo. Để làm được điều này, chúng ta chỉ cần thêm dấu “/” vì Scapy hỗ trợ điều đó.
Tại sao chúng ta phải kết hợp 2 thằng đó lại? Packets ARP chỉ là packets gửi đến ip đích cho trước và trả về MAC cho chúng ta thôi, nên nó không thể gửi hết toàn mạng được. Nhưng broadcast lại có thể giải quyết cho ta bài toán này, vì vậy chúng ta mới kết hợp 2 thằng đó lại.
Các bạn dùng hàm show() để xem thông tin các packets đã tạo nhé.
Gửi và nhận Packets
Sau khi đã cấu hình packets rồi, thì đã đến lúc ta gửi nó ra mang nhận lại packets gồm MAC của các máy trong mạng. Để làm được điều đó ta dùng hàm srp()
. Mà hàm này sẽ trả về 2 list là list phản hồi và list không phản hồi.
Vậy là ta đã lấy được IP và MAC của các thiết bị trong mạng rồi đó. Nhưng đó là các packets phản hồi được, còn mấy cái không phản hồi được thì sao nhỉ? Thử xem nhé, bạn chỉ cần thay chỗ hàm print
thành print(unanswers.summary())
là được. Result dài quá nên làm biếng chụp cho anh em coi, nhưng tóm gọn lại thì là những ip không phản hồi từ 192.168.75 đến 192.168.75.255 thôi.
In ra kết quả khó nhìn quá nhỉ, vậy thì mình sẽ hướng dẫn các bạn cách thiết kết giao diện giống hình dưới.
Thiết kế giao diện
Như mình đã nói ở phần trên, phần mềm sẽ trả ra 2 list là answered (phản hồi) và unanswered (không phản hồi), chúng ta chỉ cần danh sách phản hồi nên chỉ sử dụng list answered mà thôi. Bây giờ, ta duyệt qua danh sách và in các giá trị ra xem nó lưu như thế nào.
Tại sao mình lại thêm “[0]” vào hàm scapy.srp.
Bởi vì hàm này trả ra 2 list nên khi bạn gán kết quả của hàm vào một biến thì nó sẽ không hiểu bạn muốn lấy list phản hồi hay không phản hồi nên mình mới phải thêm “[0]”.
Nhiều thông tin thừa quá nhỉ. Giờ mình sẽ giải quyết từng cái một. Đầu tiên là chỗ này, mình muốn ẩn chỗ này đi.
Các bạn chỉ cần thêm parameters verbose=False
vào hàm scapy.srp
.
Tiếp theo chúng ta sẽ lấy những gì cần thiết mà thôi. Các bạn in phần phần tử 1 của elements, nhớ kèm hàm show()
.
Và nó sẽ in ra vài ba cái kết quả như thế này, tuỳ thuộc vào số lượng packets phản hồi.
Bây giờ, bạn tiến hành lấy IP và MAC của máy đã phản hồi gói packets của bạn.
Tiếp theo, các bạn thiết kế khung IP và MAC.
Giờ ta sẽ cải tiến một chút, nếu như trong tương lai bạn cần dùng cái list này thì sao? Chẳng lẽ chạy lại từ đầu, vậy nên chúng ta sẽ bỏ list này vào dict (dictionary) để dễ quản lý, lưu dict trong list. Ta tạo thêm một hàm
print_result()
để in kết quả.
Vậy là xong phần thiết kế rồi. Tiếp theo ta vận dụng kiến thức ở các bài trước để thêm optparse vào phần mềm.
Thêm optparse
Ở 2 bài trước, ta đã được biết cách thêm parse cho phần mềm. Bây giờ là lúc ta vận dụng nó. Mình sẽ không giải thích lại nhé.
Vậy là xong bài 3 rồi. Các bạn nào nếu gặp lỗi gì thì inbox với fanpage RatHuuIch. Hoặc vào group RatHuuIch để học hỏi, giao lưu thêm nhé.