分析由Python编写的大型项目(Volatility和Cuckoo)
之前使用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)的更多相关文章
- Python不能用于大型项目?关于Python的10大误解
 语言多元化是PayPal编程文化中一个重要的组成部分.在C++和Java长期流行的同时,更多的团队选择了Jva和Scala.同时,Braintree的收购也引入了一个久经世故的Ruby社区.Pyt ...
- Python不能用于大型项目?人们对Python的十大误解
Python 类型系统的特点是拥有强大.灵活的类型操作. 维基百科上对此作出的阐述. 而存在一个不争而有趣的事实是, Python 是比Java更加强类型的. Java 对于原生类型和对象区分了类型系 ...
- b2c项目基础架构分析(一)b2c 大型站点方案简述 已补充名词解释
我最近一直在找适合将来用于公司大型bs,b2b b2c的基础架构. 实际情况是要建立一个bs架构b2b.b2c的网站,当然还包括wap站点.手机app站点. 一.现有公司技术人员现状: 1.熟悉asp ...
- 在大型项目上,Python 是个烂语言吗
Robert Love, Google Software Engineer and Manager on Web Search. Upvoted by Kah Seng Tay, I was the ...
- python编写网络抓包分析脚本
python编写网络抓包分析脚本 写网络抓包分析脚本,一个称手的sniffer工具是必不可少的,我习惯用Ethereal,简单,易用,基于winpcap的一个开源的软件 Ethereal自带许多协议的 ...
- SLAM+语音机器人DIY系列:(二)ROS入门——8.理解roslaunch在大型项目中的作用
摘要 ROS机器人操作系统在机器人应用领域很流行,依托代码开源和模块间协作等特性,给机器人开发者带来了很大的方便.我们的机器人“miiboo”中的大部分程序也采用ROS进行开发,所以本文就重点对ROS ...
- 【Python】【持续项目】Python-安全项目搜集
1.前言 Python发展以来,除了web安全方向,二进制方向也早已经积累有很多用Python写的项目.作为搜集者当然不能错过! 2.项目分类 安全编程 多功能Python键盘记录工具:Radium ...
- 1、大型项目的接口自动化实践记录--robotframework环境搭建
因为人力.团队技术问题,选用robotframework来做自动化,首先说下环境搭建 齐涛道长的入门教程非常棒:http://blog.csdn.net/tulituqi/article/detail ...
- fw: 专访许鹏:谈C程序员修养及大型项目源码阅读与学习
C家最近也有一篇关于如何阅读大型c项目源代码的文章,学习..融合.. -------------------- ref:http://www.csdn.net/article/2014-06-05 ...
随机推荐
- RabbitMQ(七)心跳控制 -- heartbeat
https://blog.csdn.net/jiao_fuyou/article/details/23186407
- mysql中tinyint(1)与tinyint(2)的区别
tinyint 型的字段如果设置为UNSIGNED类型,只能存储从0到255的整数,不能用来储存负数.tinyint 型的字段如果不设置UNSIGNED类型,存储-128到127的整数. 1个tiny ...
- Android组件内核之Activity调用栈分析(一)
阿里P7Android高级架构进阶视频免费学习请点击:https://space.bilibili.com/474380680 导语 我们陈述一下Activity,Activity是整个应用用户交互的 ...
- zabbix cpu监控介绍
一.CPU utilization 使用Zabbix查看CPU利用率,会有下面几个值: CPU idle time:空闲的cpu时间比[简称id]CPU user time:用户态使用的cpu时间比[ ...
- Python- 接口类-抽象类
接口类 继承有两种用途: 一:继承基类的方法,并且做出自己的改变或者扩展(代码重用) 二:声明某个子类兼容于某基类,定义一个接口类Interface,接口类中定义了一些接口名(就是函数名)且并未实现接 ...
- 2018APIO 进京赶考
先见识了一下CTSC的操作...涨了见识... 打铁匠x1 见识了个全英文的ppt,各种讲课其实真的讲的很好,只是逻辑性太强反而让完全不会的同学有些尴尬... linux真的令人窒息...GUIDE用 ...
- android 批量加载数据
public class MainActivity extends Activity { private ListView listView; private List<String> d ...
- 理解EntityFramework两个核心类型的职责 DbSet和D'bContext
DbSet与DbContext是多对一的关系DbSet是实体对象的集合,提供了实现CRUD的相应方法DbContext封装与数据库和数据模型相关的功能,依据数据实体状态创建SQL命令,将数据更改保存到 ...
- 在MyEclipse中更换或修改svn的用户名和密码
1.通过删除SVN客户端的账号配置文件 (1)找到我们使用的客户端配置文件,Windows XP中的位置是在系统盘的Documents and Settings\Administrator\A ...
- 2018-2-13-win10-uwp-魔力鬼畜
title author date CreateTime categories win10 uwp 魔力鬼畜 lindexi 2018-2-13 17:23:3 +0800 2018-2-13 17: ...