转自《python灰帽子》第4章
目标:对printf函数设置断点,获取其第2个运行参数,并更改为一个随机数
脚本一:printf_random.py
from pydbg import *
from pydbg.defines import *
import struct
import random
# This is our user defined callback function
def printf_randomizer(dbg):
# Read in the value of the counter at ESP + 0x8 as a DWORD
parameter_addr = dbg.context.Esp + 0x8
counter = dbg.read_process_memory(parameter_addr,4)
# When using read_process_memory, it returns a packed binary
# string, we must first unpack it before we can use it further
counter = struct.unpack("L",counter)[0]
print "Counter: %d" % int(counter)
# Generate a random number and pack it into binary format
# so that it is written correctly back into the process
random_counter = random.randint(1,100)
random_counter = struct.pack("L",random_counter)[0]
# Now swap in our random number and resume the process
dbg.write_process_memory(parameter_addr,random_counter)
return DBG_CONTINUE
# Instantiate the pydbg class
dbg = pydbg()
# Now enter the PID of the printf_loop.py process
pid = raw_input("Enter the printf_loop.py PID: ")
# Attach the debugger to that process
dbg.attach(int(pid))
# Set the breakpoint with the printf_randomizer function
# defined as a callback
printf_address = dbg.func_resolve("msvcrt","printf")
dbg.bp_set(printf_address,description="printf_address",handler=printf_randomizer)
# Resume the process
dbg.run()
为什么第二参数地址是dbg.context.Esp + 0x8,这是因为现在调用printf的函数栈如下:
脚本二:printf_loop.py
from ctypes import *
import time
import os
print os.getpid()
msvcrt = cdll.msvcrt
counter = 0
while 1:
msvcrt.printf("Loop iteration %d!\n",counter)
time.sleep(2)
counter += 1
测试输出:
在控制台运行脚本二:python print_loop.py(在控制台才看得到printf输出的改变)
接着运行脚本一,输入前面进程的pid,这时prinf的输出就变的随机了,如下
D:\pycode>python printf_loop.py
2604
Loop iteration 0!
Loop iteration 1!
Loop iteration 2!
Loop iteration 3!
Loop iteration 4!
Loop iteration 5!
Loop iteration 6!
Loop iteration 14!
Loop iteration 91!
Loop iteration 83!
Loop iteration 35!
Loop iteration 23!
Loop iteration 73!
Loop iteration 28!
Loop iteration 54!