python逆向入门教程


Posted in Python onJanuary 15, 2018

1、开发环境

我们在Windows 10上开始python逆向之旅,首先开始搭建开发环境,python解释器使用最新的3.6.1,IDE使用PyCharm社区版2017.1.3,下载地址如下所示,下载完成后直接双击安装包安装即可,随后设置PyCharm的Project Interpreter为刚才安装的Python解释器就可以了。

【Python】https://www.python.org/downloads/
【PyCharm】http://www.jetbrains.com/pycharm/download/#section=windows

2、ctypes

首先介绍一下ctypes,它是一个用于Python的外部函数库,提供了与C语言兼容的数据类型,允许调用动态链接库或共享库中的函数,还可以包装这些库。下面是ctypes中的数据类型与C语言、Python中的数据类型的对应关系。

python逆向入门教程

ctypes中的数据类型全部通过class来实现,在Python中加载C库涉及如下几个类。

  1. class ctypes.CDLL 加载共享库,使用标准C函数调用惯例即cdecl,返回类型为int。
  2. class ctypes.OleDLL 加载共享库,只用于Windows平台,使用stdcall函数调用惯例,返回类型为HRESULT。
  3. class ctypes.WinDLL 加载共享库,只用于Windows平台,使用stdcall函数调用惯例,返回类型为int。
  4. class ctypes.PyDLL 类似于CDLL,与前面三个不同的是,在函数调用期间不会释放GIL,Global Interpreter Lock。
  5. class ctypes.LibraryLoader(dlltype) dlltype为CDLL、OleDLL、WinDLL、PyDLL,这个类有一个加载共享库的函数LoadLibrary。

加载C库更简单的方法是使用如下几个预先创建的类实例。

ctypes.cdll
ctypes.oledll
ctypes.windll
ctypes.pydll
ctypes.pythonapi

上面提到了函数调用惯例cdecl和stdcall,cdecl的意思是函数的参数从右往左依次压入栈内,函数的调用者在函数执行完成之后负责函数的平衡,常用于X86架构的C语言里,返回值存储在EAX寄存器中,从汇编代码的角度来看,函数参数从右往左依次压栈,然后调用函数,最后修改栈指针ESP为原来的位置。stdcall,参数传递的顺序也是从右到左,不过栈的平衡处理由函数自己完成,而不是调用者,返回值同样存储在EAX中,也就是说,函数参数压栈、函数调用之后没有像cdecl一样的栈指针ESP移动。

下面的例子在Python中调用C的printf函数,printf属于“C:\Windows\System32\msvcrt.dll”,也就是Linux上的“libc.so”。

from ctypes import *

msvcrt = cdll.msvcrt
message = b"Hello World\n"
msvcrt.printf(b"Message is %s", message)

上面的代码输出“Message is Hello World”。另外,ctypes还允许在Python中定义结构和联合等其它高级功能,详细介绍请参考https://docs.python.org/3.6/library/ctypes.html?highlight=ctypes#。

3、调试原理

使用调试器,能够对程序进行动态跟踪和分析,特别是涉及到exploit、fuzzer和病毒分析的时候,动态分析程序的能力就显得非常重要了。调试程序时,如果可以获得源代码,调试起来就容易一些,也就是透明的白盒测试,如果没有源代码,也就是黑盒测试,想要得到理想的结果,那就必须拥有高超的逆向技术和逆向工具的帮助。黑盒测试包括用户模式与内核模式两种情况,两者有不同的权限。

CPU的寄存器能够对少量的数据进行快速的存取访问,在X86指令集里,一个CPU有八个通用寄存器:EAX、EDX、ECX、ESI、EDI、EBP、ESP和EBX,以及其它的寄存器,下面逐个介绍。
EAX:累加寄存器,除了用于存储函数的返回值外也用于执行计算的操作,许多优化的X86指令集都专门设计了针对EAX寄存器的读写和计算指令。

EDX:数据寄存器,本质上是EAX寄存器的延伸,辅助EAX寄存器完成更多复杂的计算操作。
ECX:计数寄存器,用于循环操作,计算是向下而不是向上的,由大减到小。
ESI:Source Index,源操作数指针,存储着输入的数据流的位置,用于读,高效地处理循环操作的数据。
EDI:Destination Index,目的操作数指针,存储了计算结果存储的位置,用于写,高效地处理循环操作的数据。
ESP:Stack Pointer,栈指针,负责函数的调用和栈的操作,函数调用时压栈参数和返回地址,指向栈顶即返回地址。
EBP:Base Pointer,基指针,负责函数的调用和栈的操作,函数调用时压栈参数和返回地址,指向栈底。
EBX:唯一一个没有特殊用途的寄存器,作为额外的数据存储器。
EIP:Instruction Pointer,指令指针,总是指向马上要执行的指令。

熟悉调试器的朋友们都知道断点,断点其实就是一个调试事件,其它事件如经典的段错误(Segment Fault)等。断点包括软件断点、硬件断点和内存断点,用于暂停被执行程序。

软件断点:一个单字节的指令,将控制权转移给调试器的断点处理函数。汇编指令是CPU执行的指令的高级表示方法,如下面的汇编指令MOV EAX, EBX,告诉CPU把存储在EBX寄存器里的东西放到EAX寄存器,然而CPU并不明白这个汇编指令,必须转化为能够让CPU识别的操作码8BC3,假设这一操作发生在地址0x44332211,为了在这个地址设置断点,暂停CPU,需要从2个字节的操作码8BC3中换出一个单字节的操作码,这个单字节的操作码也就是3号中断指令,INT3,一条能让CPU暂停的指令,对应的操作码为0xCC,具体如下面的代码片段所示。当调试器被告知在目标地址设置一个断点时,它首先读取目标地址的第一个字节的操作码然后保存起来,同时把地址存储在内部的中断列表中,接着,调试器把3号中断指令对应的操作码0xCC写到刚才的地址,当CPU执行到替换后的操作码的时候,CPU暂停,并触发一个INT3事件,此时调试器就能捕捉到这个事件,然后调试器通过EIP判断这个中断地址是否是我们设置的断点,如果是,就把对应的操作码写回以恢复程序的正常运行。软件断点包括一次性断点和持续性断点,前者生效一次,后者一直生效,不生效后将其从中断列表移除。需要注意的是,当我们改变了被调试程序的内存数据时,同时改变了运行时软件的CRC即循环冗余代码校验和,CRC是一种校验数据是否被改变的机制,广泛应用于文件、内存、文本、网络数据包等任何想监视数据的地方,它将一定范围内的数据进行hash计算,然后将hash值同此前的hash值进行比较,判断数据是否改变,为了在这种特殊的情况下也能调试程序,就要使用下面介绍的硬件断点了。

地址: 操作码 汇编指令
0x44332211: 8BC3 MOV EAX, EBX
0x44332211: CCC3 MOV EAX, EBX

硬件断点:在小块区域内设置断点,属于CPU级别,使用了DR0到DR7共八个特殊的调试寄存器,这些寄存器专门用于管理硬件断点。DR0到DR3存储硬件断点地址,意味着同一时间内最多只能有4个硬件断点,DR4和DR5保留,DR6是状态寄存器,说明被断点触发的调试事件的类型,DR7是开关寄存器,同时也存储了断点的不同类型,包括指令执行时中断、数据可以写入时中断、有数据读或者写但不执行时中断。硬件断点使用1号中断指令INT1,负责硬件中断和步进事件。硬件断点的特点是同一时间只能设置四个断点,而且断点起作用的区域只有四个字节,如果想要跟踪一大块内存数据,请使用下面介绍的内存断点。

内存断点:用于大块区域,不是真正的断点,而是改变了内存中某个块或者页的权限。一个内存页是操作系统处理的最小的内存单位,一个内存页被申请成功后,就拥有了一个权限集,如可执行页、可读页、可写页,这些决定了内存该如何被访问,任何对保护页的访问都会引发异常,之后页面恢复访问前的状态。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Python 相关文章推荐
python数字图像处理实现直方图与均衡化
May 04 Python
Python用csv写入文件_消除空余行的方法
Jul 06 Python
python批量修改图片后缀的方法(png到jpg)
Oct 25 Python
Django实现一对多表模型的跨表查询方法
Dec 18 Python
python如何实现异步调用函数执行
Jul 08 Python
Python是什么 Python的用处
May 26 Python
解决python运行启动报错问题
Jun 01 Python
Python unittest discover批量执行代码实例
Sep 08 Python
python excel和yaml文件的读取封装
Jan 12 Python
Python如何利用正则表达式爬取网页信息及图片
Apr 17 Python
pycharm代码删除恢复的方法
Jun 26 Python
Python Pytorch查询图像的特征从集合或数据库中查找图像
Apr 09 Python
Python3一行代码实现图片文字识别的示例
Jan 15 #Python
Python编程二分法实现冒泡算法+快速排序代码示例
Jan 15 #Python
selenium python浏览器多窗口处理代码示例
Jan 15 #Python
100行python代码实现跳一跳辅助程序
Jan 15 #Python
tornado 多进程模式解析
Jan 15 #Python
200 行python 代码实现 2048 游戏
Jan 12 #Python
一篇文章快速了解Python的GIL
Jan 12 #Python
You might like
电脑硬件及电脑配置知识大全
2020/03/17 数码科技
在JavaScript中调用php程序
2009/03/09 PHP
PHP多例模式介绍
2013/06/24 PHP
php面向对象中的魔术方法中文说明
2014/03/04 PHP
Yii支持多域名cors原理的实现
2018/12/05 PHP
在 Laravel 6 中缓存数据库查询结果的方法
2019/12/11 PHP
javascript 密码强度验证规则、打分、验证(给出前端代码,后端代码可根据强度规则翻译)
2010/05/18 Javascript
javascript日期转换 时间戳转日期格式
2011/11/05 Javascript
Javascript变量的作用域和作用域链详解
2015/04/02 Javascript
JavaScript实现的简单烟花特效代码
2015/10/20 Javascript
jQueryUI中的datepicker使用方法详解
2016/05/25 Javascript
javascript函数中的3个高级技巧
2016/09/22 Javascript
使用grunt合并压缩js和css文件的方法
2017/03/02 Javascript
深入浅析ES6 Class 中的 super 关键字
2017/10/20 Javascript
angular写一个列表的选择全选交互组件的示例
2018/01/22 Javascript
使用 vue-i18n 切换中英文效果
2018/05/23 Javascript
JS使用对象的defineProperty进行变量监控操作示例
2019/02/02 Javascript
JavaScript数值类型知识汇总
2019/11/17 Javascript
python使用xauth方式登录饭否网然后发消息
2014/04/11 Python
Python编程中对文件和存储器的读写示例
2016/01/25 Python
聊聊Python中的pypy
2018/01/12 Python
Python文件如何引入?详解引入Python文件步骤
2018/12/10 Python
Python判断是否json是否包含一个key的方法
2018/12/31 Python
python笔记_将循环内容在一行输出的方法
2019/08/08 Python
PyQt5实现登录页面
2020/05/30 Python
python实现人工蜂群算法
2020/09/18 Python
CSS3弹性伸缩布局之box布局
2016/07/12 HTML / CSS
浅谈CSS3 box-sizing 属性 有趣的盒模型
2019/04/02 HTML / CSS
使用html5 canvas 画时钟代码实例分享
2015/11/11 HTML / CSS
美国著名手表网站:Timepiece
2017/11/15 全球购物
互联网创业计划书的书写步骤
2014/01/28 职场文书
班主任师德师风自我剖析材料
2014/10/02 职场文书
企业财务人员岗位职责
2015/04/14 职场文书
个人欠条范本
2015/07/03 职场文书
2019年销售部季度工作计划3篇
2019/10/09 职场文书
Python 如何安装Selenium
2021/05/06 Python