寒江独钓

博客园 首页 新随笔 联系 订阅 管理

python基础部分较为简单,不再记录了。开始ctpytes:

        Ctypes可以调用动态链接库中的函数,可以创建复杂的c数据类型和底层内存处理工具函数。

        动态链接库是主进程在执行时链接的编译二进制文件。Windows下面称为dynamic link libraries (DLL)Linux下面叫做:shared objects (SO).。这些二进制文件,通过导出名展示函数,导出名对应着内存中的实际地址。通常运行时,你需要解析函数地址来调用函数,不过ctypes已经为你做好了这些。

         Ctypes3中不同的加载动态链接库的方法:cdll(),windll(),  oledll(),区别在于库中函数调用的方法和结果返回值。cdll()适用于标准cdecl用。windll()适用于stdcall调用,是Win32 API的默认方式。oledll()windll()类似,但是设定返回Windows  HRESULT错误码,一般用于COM函数返回的错误消息。

    简单实例:我们来实践一下C语言中的printf()Windows对应msvcrt.dllC:\WINDOWS\system32\

from ctypes import*#导入ctypes中的所有模块 

msvcrt =cdll.msvcrt#以cdll的方式加载msvcrt 

#或者写作: msvcrt =cdll.LoadLibrary("msvcrt.dll")

message_string = "hello world!\n"#定义一个字符串

msvcrt.printf("%s",message_string);

再例: 

from ctypes import *  
kernel32 = windll.kernel32   、

#或者写作kernel32 = windll.LoadLibrary("kernel32.dll")

print kernel32  

 cdll(),windll(),  oledll()解释如下:

class CDLL (name, mode=DEFAULT_MODE, handle=None)

Instances of this class represent loaded shared libraries. Functions in these libraries use the standard C calling convention, and are assumed to return int.

class OleDLL(name, mode=DEFAULT_MODE, handle=None)

Windows only: Instances of this class represent loaded shared libraries, functions in these libraries use the stdcall calling convention, and are assumed to return the windows specific HRESULT code. HRESULT values contain information specifying whether the function call failed or succeeded, together with additional error code. If the return value signals a failure, an WindowsError is automatically raised.

class WinDLL(name, mode=DEFAULT_MODE, handle=None)

Windows only: Instances of this class represent loaded shared libraries, functions in these libraries use the stdcall calling convention, and are assumed to return int by default.

 

Fundamental data types

ctypes defines a number of primitive C compatible data types :

ctypes type C type Python type
c_char char 1-character string
c_wchar wchar_t 1-character unicode string
c_byte char int/long
c_ubyte unsigned char int/long
c_short short int/long
c_ushort unsigned short int/long
c_int int int/long
c_uint unsigned int int/long
c_long long int/long
c_ulong unsigned long int/long
c_longlong __int64 or long long int/long
c_ulonglong unsigned __int64 or unsigned long long int/long
c_float float float
c_double double float
c_longdouble long double float
c_char_p char * (NUL terminated) string or None
c_wchar_p wchar_t * (NUL terminated) unicode or None
c_void_p void * int/long or None

 

ctypes类型可以初始化一个值:

>>> from ctypes import *

>>> c_int()

c_long(0)

>>> c_char_p("Hello world!")

c_char_p('Hello world!')

>>> c_ushort(-5)

c_ushort(65531)

>>> 

>>> seitz = c_char_p("loves the python")

>>> print seitz

c_char_p('loves the python')

>>> print seitz.value

loves the python

>>> exit()

 

传引用只需要使用byref()函数,比如:

function_main( byref(parameter) ).

 结构体的定义:

In C

struct beer_recipe

{

int amt_barley;

int amt_water;

};

In Python

class beer_recipe(Structure):

_fields_ = [

("amt_barley", c_int),

("amt_water", c_int),

]

联合中所有成员变量共享内存,可以把同一变量指定为不同类型。

In C

union {

long barley_long;

int barley_int;

char barley_char[8];

}barley_amount;

In Python

class barley_amount(Union):

_fields_ = [

("barley_long", c_long),

("barley_int", c_int),

         ("barley_char", c_char * 8),

         联合体实例:

from ctypes import *

class barley_amount(Union):

_fields_ = [

("barley_long", c_long),

("barley_int", c_int),

("barley_char", c_char * 8),

]

value = raw_input("Enter the amount of barley to put into the beer vat:")

my_barley = barley_amount(int(value))

print "Barley amount as a long: %ld" % my_barley.barley_long

print "Barley amount as an int: %d" % my_barley.barley_int

print "Barley amount as a char: %s" % my_barley.barley_char

        执行结果:

Enter the amount of barley to put into the beer vat: 100

Barley amount as a long: 100

Barley amount as an int: 100

Barley amount as a char: d

 通过以上实例,这个东东so easy!妈妈再也不用担心我的学习

再看一个稍微复杂的例子:

 1 #功能:打开记事本

      from ctypes import *;

 1 class _PROCESS_INFORMATION(Structure):
 2     
 3     _fields_ = [('hProcess', c_void_p),
 4 
 5                 ('hThread', c_void_p),
 6 
 7                 ('dwProcessId', c_ulong),
 8 
 9                 ('dwThreadId', c_ulong)]
10 class _STARTUPINFO(Structure):
11     
12     _fields_ = [('cb',c_ulong),
13 
14                 ('lpReserved', c_char_p),
15 
16                 ('lpDesktop', c_char_p),
17 
18                 ('lpTitle', c_char_p),
19 
20                 ('dwX', c_ulong),
21 
22                 ('dwY', c_ulong),
23 
24                 ('dwXSize', c_ulong),
25 
26                 ('dwYSize', c_ulong),
27 
28                 ('dwXCountChars', c_ulong),
29 
30                 ('dwYCountChars', c_ulong),
31 
32                 ('dwFillAttribute', c_ulong),
33 
34                 ('dwFlags', c_ulong),
35 
36                 ('wShowWindow', c_ushort),
37 
38                 ('cbReserved2', c_ushort),
39 
40                 ('lpReserved2', c_char_p),
41 
42                 ('hStdInput', c_ulong),
43 
44                 ('hStdOutput', c_ulong),
45 
46                 ('hStdError', c_ulong)]
47 NORMAL_PRIORITY_CLASS = 0x00000020
48 
49 kernel32 = windll.LoadLibrary("kernel32.dll")
50 
51 CreateProcess = kernel32.CreateProcessA
52 
53 ProcessInfo = _PROCESS_INFORMATION()
54 
55 StartupInfo = _STARTUPINFO()
56 
57 fileName = 'c:/windows/notepad.exe'
58  CreateProcess(fileName, 0, 0, 0, 0, NORMAL_PRIORITY_CLASS,0, 0, byref(StartupInfo), byref(ProcessInfo)) 

最后来个综合性实例://功能:改变程序流向

1)编写一个win32 程序

   1 #include <windows.h>

 2 int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
 3         LPSTR lpCmdLine, int nCmdShow)
 4 {
 5     int a = 0;
 6     int b = 1;
 7     if ( a != b )
 8     {
 9         MessageBox(NULL, "Bad Python""Python", MB_OK);
10     }
11     else
12     {
13         MessageBox(NULL, "Good Python""Python", MB_OK);
14     }
15 }

# 生成ModifyMe.exe

2)用python来改变程序流向,让以上程序执行else语句。其实就是用WriteProcessMemory将jmp指令前的跳转条件改变
 1 #  -*- coding:utf-8 -*-
 2 #  file: ModifyMemory.py
 3 #
 4 from ctypes import *
 5 # 定义_PROCESS_INFORMATION结构体
 6 class _PROCESS_INFORMATION(Structure):
 7     _fields_ = [('hProcess', c_void_p),
 8                 ('hThread', c_void_p),
 9                 ('dwProcessId', c_ulong),
10                 ('dwThreadId', c_ulong)]
11 # 定义_STARTUPINFO结构体
12 class _STARTUPINFO(Structure):
13     _fields_ = [('cb',c_ulong),
14               ('lpReserved', c_char_p),  
15               ('lpDesktop', c_char_p),  
16               ('lpTitle', c_char_p), 
17               ('dwX', c_ulong),
18               ('dwY', c_ulong), 
19               ('dwXSize', c_ulong),
20               ('dwYSize', c_ulong), 
21               ('dwXCountChars', c_ulong),
22               ('dwYCountChars', c_ulong), 
23               ('dwFillAttribute', c_ulong), 
24               ('dwFlags', c_ulong),
25               ('wShowWindow', c_ushort),  
26               ('cbReserved2', c_ushort), 
27               ('lpReserved2', c_char_p),  
28               ('hStdInput', c_ulong),  
29               ('hStdOutput', c_ulong),
30               ('hStdError', c_ulong)]
31 # 定义NORMAL_PRIORITY_CLASS
32 NORMAL_PRIORITY_CLASS = 0x00000020
33 # 加载kernel32.dll
34 kernel32 = windll.LoadLibrary("kernel32.dll")
35 # 获得CreateProcess函数地址
36 CreateProcess = kernel32.CreateProcessA
37 # 获得ReadProcessMemory函数地址
38 ReadProcessMemory = kernel32.ReadProcessMemory
39 # 获得WriteProcessMemory函数地址
40 WriteProcessMemory = kernel32.WriteProcessMemory
41 TerminateProcess = kernel32.TerminateProcess
42 # 声明结构体
43 ProcessInfo = _PROCESS_INFORMATION()
44 StartupInfo = _STARTUPINFO()
45 # 要进行修改的文件
46 file = 'ModifyMe.exe'  # 这是以上win32所生成的exe文件
47 # 要修改的内存地址,注意此地址需要动态调试得到,调试版本可以直接用vc,否则要用windbg或od...
48 address = 0x0040103c
49 # 缓冲区地址
50 buffer = c_char_p("_"
51 # 读入的字节数
52 bytesRead = c_ulong(0)
53 # 缓冲区大小
54 bufferSize =  len(buffer.value)
55 # 创建进程
56 if CreateProcess(file, 0, 0, 0, 0, NORMAL_PRIORITY_CLASS, 0, 0, byref(StartupInfo), byref(ProcessInfo)):
57     # 读取要修改的内存地址,以判断是否是要修改的文件
58     if ReadProcessMemory(ProcessInfo.hProcess, address, buffer, bufferSize, byref(bytesRead)):
59         if buffer.value == '\x74':
60             # 修改缓冲区内值,将其写入内存
61             buffer.value = '\x75'
62             # 修改内存
63             if WriteProcessMemory(ProcessInfo.hProcess, address, buffer, bufferSize, byref(bytesRead)):
64                 print '成功改写内存!'
65             else:
66                 print '写内存错误!'
67         else:
68             print '打开了错误的文件!'
69             # 如果不是要修改的文件,则终止进程
70             TerminateProcess(ProcessInfo.hProcess,0)
71     else:
72         print '读内存错误!'
73 else:
74     print '不能创建进程!'

that's all!

 

 

 

 

posted on 2012-09-28 10:50  X.W.LIU  阅读(930)  评论(0)    收藏  举报