反汇编

逆向分析之核心代码的分析

故事扮演 提交于 2020-01-17 03:38:19
   博客 个人感觉分析正常的(没有花指令)反汇编代码最大的挑战就是难以分清反汇编出的代码是用户的代码还是库的代码,还是编译器插入的代码。克服这一关需要丰富的经验。因此,逆向的入门大多数是难倒在这一关上。 1、识别一个函数   程序都是以函数为一个单位。函数内的多条代码使函数完成了特定的功能,在分析当中也是以一个函数作为一个分析单位。在分析时,应当尽可能多的分析出这个函数所完成的具体功能。   反汇编中的函数一般都有如下格式:    1.1 第一种函数格式   push ebp   mov esp,ebp   ....   pop ebp   ret    1.2 第二种函数格式   这种函数没有特定的格式,但可以肯定是在函数的末尾肯定有ret语句。 2、识别函数的返回值,形参,局部变量 函数一般是使用eax寄存器来保存返回值。但是一些编译器可能用其他的方式来传递返回值,因此,在分析程序的前期,需要确定该程序是用什么编译器进行编译的(通过PEId可以产看),才能确定其返回值是用什么方式进行传递的。 函数的形参个数可以通过函数平衡多少字节的栈空间来推理出。因为存在着许多的传参方式,所以这种方法并不是绝对正确的,因此要先观察出一个函数的传参方式是何种方式。 和函数的传参方式息息相关的函数调用方式:   不同的调用方式平衡堆栈的方式是不同的。C方式调用时,是调用者进行堆栈平衡。传参时

IDA Pro7.0使用技巧总结

三世轮回 提交于 2020-01-13 21:46:04
俗话说,工欲善其事,必先利其器,在二进制安全的学习中,使用工具尤为重要,而IDA又是玩二进制的神器,以前在使用IDA的时候,只是用几个比较常用的功能,对于IDA的其他功能没有去研究,于是本着学习的精神,参考着《IDA pro权威指南》(第二版),写下这篇文章,记录自己的学习心得,下面的记录都是在Windows平台下的IDA pro7.0进行的 一些二进制工具 在《IDA pro权威指南》的开篇一两章中,先是介绍了几款常用于二进制研究的工具,我这里简单的记了几个,介绍一波: C++filt: 可以用于显示出c++中复杂的重载后的函数名称 PE tools: 是一组用于分析Windows系统中正在运行的进程和可执行文件的工具 string: 可以用于直接搜索出elf文件中的所有字符串 参数-a 表示搜索整个文件,参数-t 可以显示出每一个字符串的偏移,参数-e 可以用于搜索更多的字符编码的字符串,如Unicode编码 strip: 可用于elf去符号,去符号后仍然保持正常功能但增加了逆向的难度,出题恶人必备 开发了IDA的天才是Ilfak,他的个人博客有很多IDA的教程 https://www.hexblog.com/ IDA目录结构 在IDA的安装根目录下有许多文件夹,各个文件夹存储不同的内容 cfg:包含各种配置文件,基本IDA配置文件ida.cfg,GUI配置文件idagui

c++ 反汇编 虚函数

自作多情 提交于 2020-01-13 20:53:29
  虚函数是面向对象程序设计的关键组成部分。对于具有虚函数的类而言,构造函数和析构函数的识别流程更加简单。而且,在类中定义了虚函数之后,如果没有提供默认的构造函数,编译器必须提供默认的构造函数。   对象的多态性需要通过虚表和虚表指针来完成,虚表指针被定义在对象首地址的前4字节处,因此虚函数必须作为成员函数使用。由于非成员函数没有this指针,因此无法获得虚表指针,进而无法获取虚表,也就无法访问虚函数。 class CVirtual { public: ~CVirtual() { printf("~CVirtual"); } CVirtual() { } CVirtual(int nNumber) { m_nNumber = nNumber; } virtual int GetNumber() { return m_nNumber; } virtual void SetNumber(int nNumber) { m_nNumber = nNumber; } private: int m_nNumber; }; 类中只定义一个int类型的数据成员,类大小却为8。当类中含有虚函数时,对象空间中第一项存放虚表指针。 35: // 获取含有虚函数表的类大小 36: int nSize = sizeof(CVirtual); 0007739D C7 45 EC 08 00 00 00 mov

c++ 反汇编 表达式

家住魔仙堡 提交于 2020-01-07 18:55:39
有符号数溢出: void BreakFor() { for (int i = 1; i > 0; i++) { printf("%d \r\n", i); } } 上面的程序并不是死循环,当有符号数增加到最大整数后,继续加一会进位修改符号位,从而成为负数。 自增、自减 98: int nVarOne = argc; 012665EE 8B 45 08 mov eax,dword ptr [argc] 012665F1 89 45 F8 mov dword ptr [nVarOne],eax 99: int nVarTwo = argc; 012665F4 8B 45 08 mov eax,dword ptr [argc] 012665F7 89 45 EC mov dword ptr [nVarTwo],eax 100: nVarTwo = 5 + (nVarOne++); 012665FA 8B 45 F8 mov eax,dword ptr [nVarOne] 012665FD 83 C0 05 add eax,5 01266600 89 45 EC mov dword ptr [nVarTwo],eax 01266603 8B 4D F8 mov ecx,dword ptr [nVarOne] 01266606 83 C1 01 add ecx,1 //后缀自增

售卖大航海时代Online外挂资料

半腔热情 提交于 2019-12-29 23:56:10
有了这些资料,你可以做到后台的任何形式的强大机器人外挂程序,如近港买卖,采集(丢弃后台)等。是你制作大航海时代Online外挂的必须资料,这里有你所需要的call地址和参数信息,和绝大部分内存地址结构数据分析资料。这些我是花费3个月的时间反汇编分析得来。 有诚意 购买 者可以给我发邮件索取价格(¥5000+以上),另外也可寻求 合作 。谢谢! 一系列的游戏call: 一系列的内存地址数据: 来源: https://www.cnblogs.com/wj/archive/2008/03/18/DOL_WG_INFO.html

从两句汇编认识运行时地址与链接地址

♀尐吖头ヾ 提交于 2019-12-29 01:49:02
首先看两行汇编代码: 1: adr r0, _start 2: ldr r1, =_start /*--> */ /*--> */   同样是加载一个标号的地址值,adr和ldr有什么区别呢?注意这里的ldr不是命令ldr,而是伪指令ldr,若想区分它们请参看我的一篇博文《 adr adrl ldr mov总结整理 》。 要区分它们,就需要引入4个概念: 1、运行时地址起始位置:它芯片公司指定的一开始运行代码的位置。这个位置和芯片本身有关,不可改动。对于2440来说一般就是片内SRAM的首地址0x0;对于210来说就是片内SRAM中的地址0xD0020010。 2、链接地址起始位置:它是由程序员指定的,或者说是有链接脚本设定。是可以变动的。但是这个位置在程序链接之后,就会确定下来。 3、运行时地址:就在从运行时地址起始位置(包括起始位置)往后排都是运行时地址。 4、链接地址:就是从链接地址起始位置(包括起始位置)往后排都是链接地址。      说明了以上4点内容之后,我需要铺垫一些前提内容,adr r0, _start ; ldr r1, =_start 这两句代码是从朱老师的一个实验程序里直接截取出来,这实验的目的是演示重定位。之后这段代码我会贴到文章的最后。因为开发板是210的板子所以运行时地址是从0xd0020010开始的,链接地址设置为0xd0024000开始的。

GDB常用命令

本秂侑毒 提交于 2019-12-25 06:41:03
启动和停止:   gdb <gropram>  //使用gdb调试program可执行文件,注意在编译时gcc要加入-g参数。   gdb <program> core //用 gdb 同时调试一个运行程序和 core 文件,core 是程序异常终止后 core dump 后产生的文件。   gdb <program> <PID>  //如果你的程序是一个服务程序,那么你可以指定这个服务程序运行时的进程 ID。gdb 会自动attach 上去,并调试他。program 应该在 PATH 环境变量中搜索得到。   run或r  //运行程序(在此给出命令行参数)   kill  //停止程序 显示代码:   list==l   list<linenum>  //显示程序第linenum行周围的程序   list<functiont>  //显示函数名为function的函数的源程序   list  //显示当前行后面的源程序   list-  //显示当前行前面的源程序 断点:   break == b   break <function>   //在函数function入口处设置断点   break <linenum>  //在指定行号停住   break *addreee  //在地址address处停止   break <linespc> thread <threadno>  

while(1)和for(;;)的区别

你离开我真会死。 提交于 2019-12-24 03:06:52
在主程序中经常会用到大循环while(1)和for(;; ),但是大部分情况下用的都是for(;; ),这是因为从反汇编的角度来看,while(1)的代码更长,执行的时间要长一点点,如下图所示。 可以看出,for的反汇编代码短于while,因此执行的时间更短一些。 转自: https://blog.csdn.net/xussy/article/details/91959178 来源: CSDN 作者: bandaoyu 链接: https://blog.csdn.net/bandaoyu/article/details/103665037

【逆向知识】动态调试技巧-C++代码逆向

为君一笑 提交于 2019-12-20 09:08:08
1、C++类代码的特点 寄存器ECX传参时一般用作this指针(对象地址)或是计数器。 有ecx传参的call,是成员函数,构造函数,析构函数 能访问成员变量的函数都会有ecx传参 静态函数、全局函数无ecx(this指针) 返回值 寄存器eax一般用作返回值 识别构造函数的OD反汇编代码 特点: (1) 代码特点:没有返回值、用于初始化 (2)反汇编特点:有返回值,而且是this指针 根据反汇编可以看出成员变量的顺序,因为在内存数据中的排布顺序是由代码中成员变量定义顺序决定的。 识别构造函数的办法: (1)构造函数调用时,会使用ECX用于this指针 (2)构造函数在反汇编层有返回值,是eax存放this指针 (3)构造函数用于初始化,一般内存如果是未初始化的比如CCCCCCC,经过构造函数会完成初始化。 (4)如果一个函数有对前4字节初始化为一个指针地址,那么可能是在初始化虚函数表指针。 如果一个类有虚函数,那么对象的内存数据里会有虚函数指针的定义。构造函数会初始化虚函数表指针,而类中定义多少个虚函数也只有一个虚函数表指针。 识别成员函数的OD反汇编代码 特点: (1)ECX传递this指针,调用成员函数 (2)成员函数中会访问exc所指向的内存空间 成员函数与虚函数本身没有什么区别,所以反汇编出来的代码都差不多。 识别成员函数: (1)如果找到了构造函数