之前使用python都是用来做一些简单的脚本,本质上和bat批处理文件没有区别。

但是Python是可以用来编写大型的项目的,比如:

Volatility:https://code.google.com/p/volatility/

Cuckoo:http://cuckoosandbox.org/index.html

1. ctypes库

http://docs.python.org/2/library/ctypes.html

Python被称为一种“胶水语言(http://en.wikipedia.org/wiki/Glue_language#Glue_languages)”,是因为它可以很方便地与其他语言,比如C语言进行协作。

另外,Windows操作系统的API基本上都是由DLL库提供的,Python如果需要使用Windows API,就需要能够与DLL进行协作。

ctypes就是解决这两种需要的库。

ctypes is a foreign function library for Python. It provides C compatible data types, and allows calling functions in DLLs or shared libraries. It can be used to wrap these libraries in pure Python.

>>> import ctypes

>>> print ctypes.windll.kernel32

<WinDLL 'kernel32', handle 77090000 at 29eb208>

>>> 

我们到Process Hacker中查看IDLE进程的module列表:

kernel32.dll, 0x77090000, 1.12 MB, Windows NT BASE API Client DLL

“print ctypes.windll.kernel32”是如何打印出来的?

class CDLL(object):

    def __repr__(self):

            return "<%s '%s', handle %x at %x>" % \

                   (self.__class__.__name__, self._name,

                    (self._handle & (_sys.maxint*2 + 1)),

                    id(self) & (_sys.maxint*2 + 1))

    

id(self)代表的是object的地址,而self._handle是ctypes.windll.kernel32的成员变量,代表的是这个模块的基地址,具体是由下面的代码初始化的

class CDLL(object):

    def __init__(self, name, mode=DEFAULT_MODE, handle=None,

                     use_errno=False,

                     use_last_error=False):

    ......

    

            if handle is None:

                self._handle = _dlopen(self._name, mode)

            else:

                self._handle = handle

当程序访问windll的kernel32成员变量时,如果该变量还没有被定义,那么会调用__getattr__元函数来定义这个变量:

class LibraryLoader(object):

    def __init__(self, dlltype):

        self._dlltype = dlltype

 

    def __getattr__(self, name):

        if name[0] == '_':

            raise AttributeError(name)

        dll = self._dlltype(name)

        setattr(self, name, dll)

        return dll

 

    def __getitem__(self, name):

        return getattr(self, name)

 

    def LoadLibrary(self, name):

        return self._dlltype(name)

而windll正好是一个LibraryLoader的object,它的构造函数的参数为WinDLL类对象,WinDLL继承自CDLL

if _os.name in ("nt", "ce"):

    windll = LibraryLoader(WinDLL)

    oledll = LibraryLoader(OleDLL)

重新理顺一下,windll实际上是一个WinDLL(该类继承自CDLL)类的对象,kernel32是该对象动态生成(通过元函数__getattr__)的一个成员变量,在kernel32成员变量初始化的过程中,会调用_dlopen打开相应的module,并且将module的基地址(即handle)赋值给kernel32._handle成员变量。

这个过程,可以看出Python是一种很灵活,而且很“面向对象”的语言。而个人的经验是,对于这样的一种语言,高层次的设计就显得尤为重要,而设计模式的地位也就是凸显出来了。

2. Python的数据模型

参考:http://docs.python.org/2/reference/datamodel.html

Every object has an identity, a type and a value. An object’s identity never changes once it has been created; you may think of it as the object’s address in memory. The ‘is‘ operator compares the identity of two objects; the id() function returns an integer representing its identity (currently implemented as its address). An object’s type is also unchangeable. [1] An object’s type determines the operations that the object supports (e.g., “does it have a length?”) and also defines the possible values for objects of that type. The type() function returns an object’s type (which is an object itself). The value of some objects can change. Objects whose value can change are said to be mutable; objects whose value is unchangeable once they are created are called immutable. (The value of an immutable container object that contains a reference to a mutable object can change when the latter’s value is changed; however the container is still considered immutable, because the collection of objects it contains cannot be changed. So, immutability is not strictly the same as having an unchangeable value, it is more subtle.) An object’s mutability is determined by its type; for instance, numbers, strings and tuples are immutable, while dictionaries and lists are mutable.

这段话很重要,简单翻译如下:

每个Python的对象都有一个身份,一个类型以及一个

1. 身份:【身份可以用来区分两个对象是否相同】

一个Python对象一旦被创建了,它的身份就不会再发生改变;它的身份可以用对象在内存中的存储地址来表示。is操作符可以用来对比两个对象的身份是否相同;而id函数会返回代表一个对象的身份的内存地址,以一个整数的形式作为返回值。

2. 类型:【代表着所有同类对象的抽象特征】

一个Python对象的类型也是不可以改变的,类型决定了这个对象支持哪些操作,以及这个对象可能拥有什么样类型的数据。type函数可以返回一个对象的类型,返回值也是一个对象,用来代表类型的抽象信息。

3. 值:【就是这个对象承载的有效信息负荷】

一个Python对象的值是可以变化的,当然也可以保持不变。我们使用mutable/immutable来区分一个Python对象的值是不是保持不变。

一个Python对象的值是否可变(它的mutability),是由这个对象的类型决定的。

比如:numbers, strings, tuples都是值不可变的类型(immutable),而dictionaries, list都是值可变的类型(mutable)。

3. Python的特殊成员函数

Python定义了一些特殊的成员函数,用户自定义的类型可以覆盖这些特殊函数的默认实现。

3.1 __new__与__init__

参考:http://stackoverflow.com/questions/674304/pythons-use-of-new-and-init

http://bbs.csdn.net/topics/340028226

__new__() is intended mainly to allow subclasses of immutable types (like int, str, or tuple) to customize instance creation. It is also commonly overridden in custom metaclasses in order to customize class creation.

__new__的调用时机比__init__早,__new__主要是用来个性化地定制那些值不可以改变的内置类型的子类型的实例化过程。这是为什么呢?

前面我们说到,有些内置类型是immutable的,就是说它们一旦被赋值,就无法再改变,那么它们是在哪里被赋值呢,是在__new__中,还是在__init__中呢?

import os,sys

 

class square_of(float):

    def __new__(cls, val):

        print "invoked __new__(%s, %f)" % ( cls.__name__,val)

        return float.__new__(cls, val*val)

 

    def __init__(self, val):

        print "invoked __init__(%s, %f)" % ( self.__class__.__name__,self)

        float.__init__(self, val*val)

 

a = square_of(2.2)

print a

>>> ================================ RESTART ================================

>>> 

invoked __new__(square_of, 2.200000)

invoked __init__(square_of, 4.840000)

4.84

>>> 

很明显,是在float.__new__中赋值的,等到了__init__时,木已成舟,一切都晚了。

至于为什么提供__new__呢,如果我们想要自己定义一种新的Immutable的数据类型,要怎么办呢?

http://en.wikipedia.org/wiki/Immutable_object#Python给出的方案如下:

class Immutable(object):

     """An immutable class with a single attribute 'value'."""

     def __setattr__(self, *args):

         raise TypeError("can't modify immutable instance")

     __delattr__ = __setattr__

     def __init__(self, value):

         # we can no longer use self.value = value to store the instance data

         # so we must explicitly call the superclass

         super(Immutable, self).__setattr__('value', value)

但是,这并不是一个严格的Immutable的实现,因为数据是存放在父类object类中的,而object本身并不是Immutable的,所以这个实现就是一个伪实现,

class Immutable(object):

    """An immutable class with a single attribute 'value'."""

    def __setattr__(self, *args):

        raise TypeError("can't modify immutable instance")

    __delattr__ = __setattr__

    def __init__(self, value):

        # we can no longer use self.value = value to store the instance data

        # so we must explicitly call the superclass

        super(Immutable, self).__setattr__('value', value)

 

b = Immutable(2.2)

super(Immutable, b).__setattr__('value', 4.4)

print b.value

>>> ================================ RESTART ================================

>>> 

4.4

>>> 

因为接口并没有被封死。

那么应该如何实现自定义的Immutable类型呢,答案是用内置的Immutable类型来派生新的Immutable类型。


__new__可以创建一个与cls不相同的类型的对象,然后返回,虽然它是被要求返回cls类型的对象的。

如果__new__创建的是与cls相同类型的对象,那么会调用__init__函数;否则,不会调用__init__函数。

3.2 __del__

与__init__是相对的,二者就类似于构造和析构函数。

3.3 __repr__和__str__

可以理解为__repr__是为了Python内部对象交换使用的,比如Serialization;而__str__主要是为了print打印的,以方便阅读为前提。

3.4 __getattr__, __setattr__和__delattr__

主要是对于attribute的访问接口

object.attribute

3.5 __getitem__, __setitem__和__delitem__

主要是访问字典的接口

self[key]

分析由Python编写的大型项目(Volatility和Cuckoo)的更多相关文章

  1. Python不能用于大型项目?关于Python的10大误解

     语言多元化是PayPal编程文化中一个重要的组成部分.在C++和Java长期流行的同时,更多的团队选择了Jva和Scala.同时,Braintree的收购也引入了一个久经世故的Ruby社区.Pyt ...

  2. Python不能用于大型项目?人们对Python的十大误解

    Python 类型系统的特点是拥有强大.灵活的类型操作. 维基百科上对此作出的阐述. 而存在一个不争而有趣的事实是, Python 是比Java更加强类型的. Java 对于原生类型和对象区分了类型系 ...

  3. b2c项目基础架构分析(一)b2c 大型站点方案简述 已补充名词解释

    我最近一直在找适合将来用于公司大型bs,b2b b2c的基础架构. 实际情况是要建立一个bs架构b2b.b2c的网站,当然还包括wap站点.手机app站点. 一.现有公司技术人员现状: 1.熟悉asp ...

  4. 在大型项目上,Python 是个烂语言吗

    Robert Love, Google Software Engineer and Manager on Web Search. Upvoted by Kah Seng Tay, I was the ...

  5. python编写网络抓包分析脚本

    python编写网络抓包分析脚本 写网络抓包分析脚本,一个称手的sniffer工具是必不可少的,我习惯用Ethereal,简单,易用,基于winpcap的一个开源的软件 Ethereal自带许多协议的 ...

  6. SLAM+语音机器人DIY系列:(二)ROS入门——8.理解roslaunch在大型项目中的作用

    摘要 ROS机器人操作系统在机器人应用领域很流行,依托代码开源和模块间协作等特性,给机器人开发者带来了很大的方便.我们的机器人“miiboo”中的大部分程序也采用ROS进行开发,所以本文就重点对ROS ...

  7. 【Python】【持续项目】Python-安全项目搜集

    1.前言 Python发展以来,除了web安全方向,二进制方向也早已经积累有很多用Python写的项目.作为搜集者当然不能错过! 2.项目分类 安全编程 多功能Python键盘记录工具:Radium ...

  8. 1、大型项目的接口自动化实践记录--robotframework环境搭建

    因为人力.团队技术问题,选用robotframework来做自动化,首先说下环境搭建 齐涛道长的入门教程非常棒:http://blog.csdn.net/tulituqi/article/detail ...

  9. fw: 专访许鹏:谈C程序员修养及大型项目源码阅读与学习

      C家最近也有一篇关于如何阅读大型c项目源代码的文章,学习..融合.. -------------------- ref:http://www.csdn.net/article/2014-06-05 ...

随机推荐

  1. testNG官方文档翻译-5 测试方法,测试类和测试组

    5.1 - 测试方法 测试方法是被 @Test注解的方法.这些方法的返回值会被忽略,除非在testng.xml中将allow-return-values设置为true. <suite allow ...

  2. nginx+tomcat负载均衡实验

    导言: 本次实验,tomcat就直接使用录原生的主页,只是简单修改主页识别主机,nginx也是直接在欢迎页上面修改的,直接实现负载均衡. 主机1:192.168.100.156 nginx+tomca ...

  3. Python面试题之“猴子补丁”(monkey patching)指的是什么?这种做法好吗?

    “猴子补丁”就是指,在函数或对象已经定义之后,再去改变它们的行为. 举个例子: import datetime datetime.datetime.now = lambda: datetime.dat ...

  4. 线性方程组迭代算法——Gauss-Seidel迭代算法的python实现

    原理: 请看本人博客:线性方程组的迭代求解算法——原理 代码: import numpy as np max=100#迭代次数上限 Delta=0.01 m=2#阶数:矩阵为2阶 n=3#维数:3X3 ...

  5. C语言各种进制输出

    #include<stdio.h> int main() { ; float f = 12.0; printf("十进制输出:%d\n", number); print ...

  6. 微信小程序のwxss

    一.wxss简介 wxss是微信小程序的样式文件,同h5框架的css类似,它具有以下特性: 二.外联样式导入 我们可以通过@import引入外部文件的样式 小程序样式是从上到下,从左到右执行的,如果样 ...

  7. sum - 计算文件的校验和,以及文件占用的块数

    总览 (SYNOPSIS) ../src/sum [OPTION]... [FILE]... 描述 (DESCRIPTION) 显示 每个 文件 FILE 的 校验和, 以及 他们 占用的 块数. - ...

  8. linux 命令 - man, help, info(查看命令帮助手册)

    man, help, info - 查看命令帮助手册   help xxx  # 显示内置命令帮助信息: xxx --help  # 显示外置命令帮助信息: man xxx  # 没有内建与外部命令的 ...

  9. python os模块用法

    import os   #os主要做路径管理import glob  #glob主要做搜索查询匹配import sys inputpath = r"C:\Users\Administrato ...

  10. ZOJ-3524 拓扑排序+完全背包(好题)

    题意:在一个DAG上,主角初始有W钱起点在s点,每个点有一个代价wi和价值vi,主角从起点走到某一点不能回头走,一路上可以买东西(一个点的东西可以买无限次),且体力消耗为身上负重*路径长度.主角可以在 ...