python编程书籍1020python编程书籍_从零单排之玩转Python安全编程(II)
轉(zhuǎn)自:http://www.secpulse.com/archives/35893.html
都說Python大法好,作為一名合格的安全從業(yè)人員,不會(huì)幾門腳本語言都不好意思說自己是從事安全行業(yè)的。
而Python是最容易入門且使用最順手的腳本語言,為了不引起程序員世界大戰(zhàn),我們不說Python是世界上最好的語言,沒有之一。
這是《從零單排之玩轉(zhuǎn)Python安全編程》的第二篇。第一篇參見安全脈搏
本教程繼續(xù)展示一些基本的Python腳本概念。我們把我們的代碼轉(zhuǎn)換成一個(gè)腳本、函數(shù)、類和系統(tǒng)模塊。
Python的腳本結(jié)構(gòu):
下面是可用于啟動(dòng)Python腳本(script)。
開始 我們通過“#!/usr/bin/env python”來告訴操作系統(tǒng)(OS)使用哪個(gè)編譯器(interpreter) 。
然后,我們聲明一個(gè)主功能 "def main()" 和最后2行代碼來讓 main()先運(yùn)行。您可以在腳本中定義的其他功能,使代碼更容易理解和修改:
#!/usr/bin/python
import ,
def myFunction():
def main():
myFunction()
if __name__=="__main__":
main()
功能Functions:
利用函數(shù)的一種常用的方法是有一段代碼執(zhí)行一些動(dòng)作和返回輸出。下面是一些基本的代碼演示這個(gè)概念:
# Declare function/setup logic
def MyFunction:
...do work...
return output
#Call the function from main:
def main():
output = MyFunction(input)
類(classes):
Python類(classes)一開始可能會(huì)顯得混亂,因?yàn)樗且粋€(gè)不同的方式來設(shè)計(jì)你的代碼。
如果你把握了定義的概念,那么你可以把類(class)當(dāng)成的數(shù)據(jù)(data)和定義(definition)的邏輯分組(logical grouping)。
這樣類將具有某些屬性(attribute)和與之相關(guān)聯(lián)的方法(method)。當(dāng)你定義以后可以創(chuàng)建該類將繼承的屬性和與之關(guān)聯(lián)的方法的對(duì)象類,這被稱為面向?qū)ο缶幊?object-oriented programming)。
如果這個(gè)概念對(duì)于你來說很混亂,我建議你不要太在意類(classes)。你其實(shí)并不需要利用類(classes),但它可以使你的代碼少冗余。
下面我們將使用“類”關(guān)鍵詞來定義一類新的“域”(Domain) 。
有各種方法在類代碼可供選擇( various methods within the class code are available)當(dāng)你需要一個(gè)Domain類型的對(duì)象(object of type Domain)。
>>> import os
>>> class Domain:
... def __init__(self, domain, port, protocol):
# Stores the variabled passed inside two variables
... self.domain=domain
... self.port=port
... self.protocol=protocol
# Defines a method to build a URL
... def URL(self):
... if self.protocol == 'https':
... URL = 'https://'+self.domain+':'+self.port+'/'
... if self.protocol == 'http':
... URL = 'http://'+self.domain+':'+self.port+'/'
... return URL
# Sets up a method to lookup resolve domain to IP using host command via os.system
... def lookup(self):
... os.system("host "+self.domain)
...
>>>
>>> domain=Domain('google.com', '443', 'https')
>>>
>>> dir(domain)
['URL', '__doc__', '__init__', '__module__', 'ip', 'lookup', 'port', 'protocol']
>>> domain.URL()
'https://8.8.8.8:443/'
>>> domain.ip
'8.8.8.8'
>>> domain.port
'443'
>>> domain.protocol
'https'
>>> domain.lookup()
google.com has address 74.125.228.233
google.com has address 74.125.228.227
google.com has address 74.125.228.232
如上圖 你可以看到在實(shí)例化域名類的一個(gè)實(shí)例后,你能運(yùn)行類中的方法。
同樣,這個(gè)概念可以在第一會(huì)造成混淆,尤其是當(dāng)你剛剛掌握Python和編程的時(shí)候。
你可以嘗試在一個(gè)你已經(jīng)寫好的Python腳本里實(shí)現(xiàn)一個(gè)新的類,我發(fā)現(xiàn)這可能是開始把握概念的有效途徑。
處理命令行參數(shù)“sys”:
這個(gè)介紹里的最后一個(gè)模塊觸及的是sys模塊。這使您可以在讀取 CLI 給定的參數(shù)(argument),并將其拉進(jìn)變量(variable)在腳本中。
語法是非常簡單的, sys.agrv[0]就是腳本名稱,并在命令行(command line)中給定每個(gè)參數(shù)(argument)后,每個(gè)參數(shù)會(huì)被分配一個(gè)號(hào)碼。
下面是一個(gè)簡單的例子:
import sys
script = sys.argv[0]
ip = sys.argv[1]
port = sys.argv[2]
print "[+] The script name is: "+script
print "[+] The IP is: "+ip+" and the port is: "+port
當(dāng)這種快速腳本調(diào)用在命令行中,加上幾個(gè)參數(shù)就產(chǎn)生以下的輸出:
~$ python sys.py 8.8.8.8 53
[+] The script name is: sys.py
[+] The IP is: 8.8.8.8 and the port is: 53
繼續(xù)探索更多的Python模塊和內(nèi)置的功能,因?yàn)樗麄儠?huì)允許你解決問題容易得多,你開始編寫更復(fù)雜的代碼。
-----------------------------------------------------------------------------------------
接下來的教程將介紹建立網(wǎng)絡(luò)連接與Python通過構(gòu)建一個(gè)基本的端口掃描器的概念。
在本教程中,我們將演示如何通過建立一個(gè)基本的端口掃描(port scanner)程序,使與Python的網(wǎng)絡(luò)連接。
我們將做的是建立網(wǎng)絡(luò)套接字連接一遍又一遍的使用IP/端口組合。為了做到這一點(diǎn),我們將引入一個(gè)新的概念,循環(huán)(for loop):
>>>
>>> for port in range(1000,1024):
... print "[+] The port is: "+str(port)
...
[+] The port is: 1000
[+] The port is: 1001
[+] The port is: 1002
[+] The port is: 1003
[+] The port is: 1004
[+] The port is: 1005
[+] The port is: 1006
[+] The port is: 1007
[+] The port is: 1008
[+] The port is: 1009
[+] The port is: 1010
[+] The port is: 1011
[+] The port is: 1012
[+] The port is: 1013
[+] The port is: 1014
[+] The port is: 1015
[+] The port is: 1016
[+] The port is: 1017
[+] The port is: 1018
[+] The port is: 1019
[+] The port is: 1020
[+] The port is: 1021
[+] The port is: 1022
[+] The port is: 1023
請(qǐng)注意,for loop以上的代碼片段有縮進(jìn)。通常人們縮進(jìn)2個(gè)空格或制表符,不過只要你在整個(gè)腳本一致這些都無所謂。
為了做一個(gè)簡單的端口掃描程序(port scanner),我們將更換打印語句(print statement)為一個(gè)代碼片段(code snippet)來建立套接字連接(socket connection)。
下面的代碼演示了如何使用內(nèi)置的socket 模塊(built-in socket module)進(jìn)行套接字連接(socket connection):
>>>
>>> import socket
>>>
>>> s = socket.socket()
>>> s.connect(('127.0.0.1', 22))
>>> s.send('Primal Security \n')
17
>>> banner = s.recv(1024)
>>> print banner
OpenSSH
上面我們導(dǎo)入了socket 模塊(socket module)以及調(diào)用了connect()功能(function)來連接到給定的IP地址和端口號(hào)。
這將建立一個(gè)TCP連接( SYN / SYN - ACK / ACK ),我們實(shí)際上是使用send()功能(function)來將數(shù)據(jù)發(fā)送到指定的服務(wù),并使用recv()來打印響應(yīng)(response)。
現(xiàn)在,如果端口未打開socket 將拋出一個(gè)異常(exception):
>>>
>>> s.connect(('127.0.0.1', 23))
Traceback (most recent call last):
File "", line 1, in ?
File "", line 1, in connect
socket.error: (111, 'Connection refused')
這可以以多種方式來解決。現(xiàn)在,我們將用一種非常簡單的方法,使用“嘗試(try)/除外(except)”循環(huán)(loop),并通過異常(exception)。
>>>
>>> try:
... s.connect(('127.0.0.1', 23))
... except: pass
...
>>>
請(qǐng)注意沒有“error!” 這是一個(gè)很好的方式來讓你的代碼看起來像是它們?cè)诠ぷ鱋(∩_∩)O~。現(xiàn)在,讓我們使用這些概念,并做出一個(gè)快速的環(huán)路(for loop)端口(port)掃描器(scanner):
>>>
>>> for port in range(20,25):
... try:
... print "[+] Attempting to connect to 127.0.0.1:"+str(port)
... s.connect(('127.0.0.1', port))
... s.send('Primal Security \n')
... banner = s.recv(1024)
... if banner:
... print "[+] Port "+str(port)+" open: "+banner
... s.close()
... except: pass
...
17
[+] Attempting to connect to 127.0.0.1:20
[+] Attempting to connect to 127.0.0.1:21
[+] Attempting to connect to 127.0.0.1:22
[+] Port 22 open: OpenSSH
[+] Attempting to connect to 127.0.0.1:23
[+] Attempting to connect to 127.0.0.1:24
[+] Attempting to connect to 127.0.0.1:25
上面我們展示的“試(try)/除外(except)”循環(huán)(loop)的基本用法來傳遞(pass) 端口(port)關(guān)閉時(shí)被socket (socket)拋出的異常(exception)。我們還展示了如何利用一個(gè)基本的條件語句 "if" 來只嘗試打印開放的端口,如果該端口回應(yīng)我們的探頭(probe)。另一種方法來創(chuàng)建一個(gè)端口掃描器是 定義一個(gè)列表來包括你想用數(shù)組(array)來掃描的端口,然后循環(huán)(loop)通過這個(gè)數(shù)組(array):
>>>
>>> ports = [22, 445, 80, 443, 3389]
>>> for port in ports:
... print port
...
22
445
80
443
3389
>>>
如果我們想一次性處理多個(gè)主機(jī)(hosts),我們將利用一個(gè)嵌套循環(huán)(nested for loop)。這將涉及外層(outter layer)環(huán)路(for loop)來通過主機(jī)循環(huán)然后內(nèi)循環(huán)(inner for loop)通過該端口(port)循環(huán)。下面是一個(gè)基本的例子來講述如何利用嵌套for循環(huán)來建立一個(gè)稍微復(fù)雜一些的掃描器:
>>>
>>> hosts = ['127.0.0.1', '192.168.1.5', '10.0.0.1']
>>>
>>> ports = [22, 445, 80, 443, 3389]
>>>
>>> for host in hosts:
... for port in ports:
... try:
... print "[+] Connecting to "+host+":"+str(port)
... s.connect((host, port))
... s.send('Primal Security \n')
... banner = s.recv(1024)
... if banner:
... print "[+] Port "+str(port)+" open: "+banner
... s.close()
... except:pass
...
[+] Connecting to 127.0.0.1:22
[+] Port 22 open: OpenSSH
[+] Connecting to 127.0.0.1:445
[+] Connecting to 127.0.0.1:80
[+] Connecting to 127.0.0.1:443
[+] Connecting to 127.0.0.1:3389
[+] Connecting to 192.168.1.5:22
[+] Connecting to 192.168.1.5:445
[+] Connecting to 192.168.1.5:80
[+] Connecting to 192.168.1.5:443
[+] Connecting to 192.168.1.5:3389
[+] Connecting to 10.0.0.1:22
[+] Connecting to 10.0.0.1:445
[+] Connecting to 10.0.0.1:80
[+] Connecting to 10.0.0.1:443
[+] Connecting to 10.0.0.1:3389
正如你可以通過輸出看到,它循環(huán)陣列的主機(jī)(hosts array),并嘗試端口陣列(port array)中的每個(gè)端口然后再移動(dòng)到下一個(gè)主機(jī)。對(duì)于最終的端口掃描器,你可能會(huì)想要要修改打印報(bào)表來只打印開放的那些端口。
在一天結(jié)束時(shí),你會(huì)發(fā)現(xiàn)Nmap仍然是端口掃描一個(gè)更好的選擇,但在以后的博客帖子內(nèi) 我們將建立在這些概念來完成一些更實(shí)際的使用案例。花一些時(shí)間來探索socket 模塊(socket module) "dir(socket)" 內(nèi) 提供的各種功能。
總結(jié)
以上是生活随笔為你收集整理的python编程书籍1020python编程书籍_从零单排之玩转Python安全编程(II)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: linux的accept函数源码,acc
- 下一篇: python的序列类型及其特点_Flue