'Python乾貨:黑客們會用到哪些關於Python技術?'

"

Python已經成為漏洞開發領域的行業標準,讀者會發現大多數概念驗證工具都是用Python語言編寫的(除了用Ruby寫的安全漏洞檢測工具)。Python允許開發者編寫腳本處理遠程服務,處理二進制文件,與C語言庫(或者Java的Jython/。Net的IronPython)以快速且簡單的方式進行交互。它“內置電池”原則的巨大標準庫,為開發省去對其它框架或者語言的依賴。

我想跟大家分享一下我個人的Python編程經歷,這些也許會對你未來的工作有所幫助,讓這個世界變得更加安全一些(注:大多數例子基於Python3.0以上版本編寫的,有些可以兼容python所有分支)

"

Python已經成為漏洞開發領域的行業標準,讀者會發現大多數概念驗證工具都是用Python語言編寫的(除了用Ruby寫的安全漏洞檢測工具)。Python允許開發者編寫腳本處理遠程服務,處理二進制文件,與C語言庫(或者Java的Jython/。Net的IronPython)以快速且簡單的方式進行交互。它“內置電池”原則的巨大標準庫,為開發省去對其它框架或者語言的依賴。

我想跟大家分享一下我個人的Python編程經歷,這些也許會對你未來的工作有所幫助,讓這個世界變得更加安全一些(注:大多數例子基於Python3.0以上版本編寫的,有些可以兼容python所有分支)

Python乾貨:黑客們會用到哪些關於Python技術?

1. 環境配置

對於你要編寫的大多數工程或者腳本,建議讀者們最好將所有的依賴放在同一個位置(除了有些在特殊工程中才用到的依賴)。為了滿足上述要求,需要用到一個叫virtualenv的工具(Python3.3已經包括該工具),這個工具有一個簡潔的功能,就是在不打亂全局環境的基礎上,為你的Python工程生成獨立的環境:

# 生成新環境的方法如下:
$ virtualenv <新環境的路徑>
# 或者在Python3.3以上的環境中:
$ python3 -mvenv <新環境的路徑>
# 使用這個環境之前,你要先激活它:
$ source <新環境的路徑>/bin/activate
# 禁止該環境的方式也很簡單:
$ deactivate

2. 安裝依賴包

很多時候大家會發現,藉助大型python社區中的python庫編寫的個人工具,可以幫助我們很快得到結果。你可以通過個人軟件管理包或者可用的python軟件包管理器安裝這些庫,其中最權威的就是pip工具了。有了pip,你可以全局安裝這些依賴包(#pip install),或者逐用戶安裝(

"

Python已經成為漏洞開發領域的行業標準,讀者會發現大多數概念驗證工具都是用Python語言編寫的(除了用Ruby寫的安全漏洞檢測工具)。Python允許開發者編寫腳本處理遠程服務,處理二進制文件,與C語言庫(或者Java的Jython/。Net的IronPython)以快速且簡單的方式進行交互。它“內置電池”原則的巨大標準庫,為開發省去對其它框架或者語言的依賴。

我想跟大家分享一下我個人的Python編程經歷,這些也許會對你未來的工作有所幫助,讓這個世界變得更加安全一些(注:大多數例子基於Python3.0以上版本編寫的,有些可以兼容python所有分支)

Python乾貨:黑客們會用到哪些關於Python技術?

1. 環境配置

對於你要編寫的大多數工程或者腳本,建議讀者們最好將所有的依賴放在同一個位置(除了有些在特殊工程中才用到的依賴)。為了滿足上述要求,需要用到一個叫virtualenv的工具(Python3.3已經包括該工具),這個工具有一個簡潔的功能,就是在不打亂全局環境的基礎上,為你的Python工程生成獨立的環境:

# 生成新環境的方法如下:
$ virtualenv <新環境的路徑>
# 或者在Python3.3以上的環境中:
$ python3 -mvenv <新環境的路徑>
# 使用這個環境之前,你要先激活它:
$ source <新環境的路徑>/bin/activate
# 禁止該環境的方式也很簡單:
$ deactivate

2. 安裝依賴包

很多時候大家會發現,藉助大型python社區中的python庫編寫的個人工具,可以幫助我們很快得到結果。你可以通過個人軟件管理包或者可用的python軟件包管理器安裝這些庫,其中最權威的就是pip工具了。有了pip,你可以全局安裝這些依賴包(#pip install),或者逐用戶安裝(

Python乾貨:黑客們會用到哪些關於Python技術?

pip install)。讀者可以手動地使用個人發行版包管理器,或者基於Python3.4提供的庫,安裝pip包。

有一個基本的python包叫iPython,通常在我不是100%肯定該如何解決當前任務,想嘗試做些實驗時,我會安裝這個依賴包。IPython是常用的python命令行,它是基於Python編寫的,有以下幾個特點:

  • 動態對象內省
  • 通過Tab完成本地命名空間
  • 持續的歷史記錄
  • 會話日誌
  • 路徑補全
  • JIT調試器
  • 自動縮進

和平常一樣,通過pip安裝也很簡單:$ pip install ipython

如果你想創建教程或者其它文本文件,ipython中的筆記本特性(現在由jupyter提供)允許用戶通過個人瀏覽器和IPython命令行交互,包括markdown、 mathjax、matplotlib等工具支持。

(通過安裝jupyter(pip install jupyter)可以使用它們,開啟筆記本服務通過(jupyter notebook))。

如果你在操作時需要與包括JSON/XML的HTTP服務交互,我建議特別好用的requests依賴庫。該python庫可以處理與網頁交互面對的各類操作,如編碼、解碼、參數、標記、重定向等。例如,請求和解析一個JSON資源的代碼如下:

r = requests.get('https://api.github.com/user', auth=('user', 'pass'))
r.json()
{u'private_gists': 419, u'total_private_repos': 77, ...}

大多數HTML解析和交互工作都可以交給BeautifulSoup庫,該python庫可以在任何現在瀏覽器上處理HTML輸入,包括修復受損代碼。

3. 與網絡交互

我們大多數目標都有可能在網絡上獲取,安裝好的標準庫中已經包含了通用的、有用的python庫,這裡我對其進行簡短的介紹。socket模塊是基於BSD socket API的瘦包裝器,它在所有的通用操作系統都可用。

所以如果你已經有C語言socket編程經驗,你可以將你的代碼輕易地翻譯成python代碼。有很多特別方便的函數,如create_connection函數可以創建TCP socket,建立本機和給定主機或者端口的連接。另一個包裝器是sendall方法,有些數據只有當所有給定數據都被髮出,或者有錯誤發生才能在線路中傳輸,而sendall方法可以嘗試重傳這些數據。

from __future__ import unicode_literals
import socket
s = socket.create_connection(('www.ernw.de', 80))
s.sendall(b'GET / HTTP/1.1
Host: www.ernw.de
')
print(s.recv(1024))

增加TSL加密鏈路也非常簡單:

from __future__ import unicode_literals
import socket
import ssl
s = socket.create_connection(('www.ernw.de', 443))
s = ssl.wrap_socket(s)
s.sendall(b'GET / HTTP/1.1
Host: www.ernw.de
')
print(s.recv(1024))

上述功能也可以在已經使用的連接中實現:

from __future__ import unicode_literals
import socket
import ssl
s = socket.create_connection(('smtp.example.com', 25))
s.sendall(b'HELO smtp.example.com
STARTTLS
')
print(s.recv(1024))
s = ssl.wrap_socket(s)
s.sendall(b'MAIL FROM:<[email protected]>
')
print(s.recv(1024))

如何你不需要這些低級服務交互,還有些模塊可以提供高層服務交互:

smtplib

ftplib

poplib

imaplib

httplib (Python 3以上版本的http客戶端)

nntplib

telnetlib (應用於服務開發和之後的需要交互命令行會話)

xmlrpclib (Python 3以上版本的xmlrpc客戶端)

4. 二進制操作或編碼

當開發與服務或者文件交互的腳本時,你經常會發現需要將數據轉換為不同格式或者編碼。在Python2.x版本中,通常使用encode或者decode方法將字符串在不同格式之間轉換。

"Hello World".encode("hex")
"AAA=".decode("base64")

很可惜,這種捷徑在Python3.x版本中被取消了,encode和decode方法當前只可以實現字符編碼,如utf-8, cp1250, iso8859, big5等。

作為替代,你現在只能使用bytes類型的兩種方法實現十六進制編碼:

bytes.fromhex('414141')
b'AAA'.hex() # 從Py3.5 開始

對於Base64編碼,你需要使用另外的模塊(在Python2.x版本中也有):

import base64
base64.b64encode(b'Hello World')
import codecs
codecs.encode(b'Hello World', 'base64')
import binascii
binascii.b2a_base64(b'Hello World')

URLs編碼或者解析可以用urllib.parse模塊實現(Python2.x版本中是urllib)

from urllib.parse import quote_plus, unquote_plus
quote_plus('Hello World+1=1337') # Hello+World%2B1%3D1337
unquote_plus('Hello+World') # Hello World

Python普通數據類型(如int,float,str)與二進制之間的一般轉換,可以在stuct模塊中實現:

import struct
struct.pack('<I', 1337) # convert the integer 1337 into its little endian, 32 bit representation
struct.unpack('<I', b'')[0] # returns tuple of results -> get only the first result
struct.unpack('<I4s', b'Test') # returns (16, b'Test')

Python3.2也可以使用int類型直接獲取其二進制表示:

a = 1337
a.to_bytes(4, 'little') # 32 bit little endian
a.to_bytes(2, 'big') # 16 bit big endian
int.from_bytes(b'', 'little') # 16

ctypes 模塊還有一個特別棒的特徵,如果你將cpython作為解譯器(通常大家都是這樣),就可以使用ctypes.Structure結構化描述C語言,獲取它們的二進制表示,就好像從C應用程序中轉儲的一樣。

from ctypes import *
import io
class TestStructure(Structure):
_fields_ = (('foo', c_int), ('bar', c_char))
t = Test()
t.foo = 1337
t.bar = b'A'
b = io.BytesIO()
b.write(t)
b.seek(0)
print(b.getvalue()) # 9A
t2 = Test()
b = io.BytesIO(b'B')
b.readinto(t2)
print(t2.foo) # 16
print(t2.bar) # B

ctypes 模塊通常是Python程序集和C語言庫之間的橋樑,不需要編寫任何Python包裝器。有了ctypes模塊,你可以使用任何C語言庫和其輸出函數:

from ctypes import *
libc = ctypes.CDLL('libc.so.6')
libc.printf(b'Hello World
')

上文中提到Structure 類型主要用於C語言庫的交互,在函數調用過程中傳遞或者獲取結構。

5. 漏洞開發工具

很多CTF團體提供他們自己的的CTF解決方案框架,我發現來自Gallopsled 的pwntools框架特別有用,尤其是開發遠程elf二進制時,它包含很多方便的函數,例如位移計算(通過cyclic模式)、格式化字符串開發(普通數據饋送以及產生的格式化字符串)、跳轉組合(基於ropgadget解析elf二進制以及提供生成簡單跳轉組合調用的包裝器)和不同傳輸通道的全部API(稱作管道)。這些可以讓讀者們開發gdb編譯後端,同時簡單地改變一行代碼就可以傳輸到目標服務。

from pwn import *
r = gdb.debug('./level3')
# r = remote(IP, PORT) # 為了做一個遠程交互式的接口,先註釋
r.recvuntil(': ')
r.sendline(EXPLOIT)
r.interactive() # 開啟一個交互式會話
"

相關推薦

推薦中...