`
weimou66
  • 浏览: 1244636 次
文章分类
社区版块
存档分类
最新评论

《软件调试分析技术》学习笔记

 
阅读更多

《软件调试分析技术》学习笔记(一)

今天开始写写一些心得体验。

《软件调试分析技术》是好友Monster的处女作品。作为一直以的好伙伴,他是我看着长大的,(*^__^*) 嘻嘻……之所以有今天这样的成绩,是与他的努力和天赋脱不了关系的。他大方地给了我PDF版的,我也大方的给了我们全班。但我们班有同学说,“这是撒子呦,看不看不懂”。我决心写一些学习笔记,和我班的同学一起来多交流,让更多热爱次行业的人都进入软件调试这个神殿。

好了,闲话不说。

1)逆向工程(reverse engineering)简介

逆向工程是通过对现有的二进制可执行文件进过反汇编、反编译、调试模拟程序运行等手段,分析出程序的执行流程、数据结构等。

逆向工程不是简单的复制和模仿,而是运用相关手段对产品进行分析再设计等创新处理,从而使程序表现出更加优良的性能、缩短新程序的开发周期、提高设计开发效率。

2)学习前提

建议在学习逆向分析技术之前有一定的编程功底。具有一定的代码逻辑能力,最好还做过一些Windows应用程序,了解一些常用的API,PE文件格式、COM原理、Windows的消息处理机制、异常处理机制等。需要和二进程代码打交道,所以一定要掌握好汇编语言(更重要的是反汇编)

由此可以看出来,同学们不是智商不够,而是基础知识比较薄弱

3)常用工具

调试工具OllyDBG、SoftICE、WinDBG、Syser Debugger,分析工具PEID、ExeInfo、FI、FFI…… 等,常见的PE工具有:LoadPE、PETools、Stud_PE、PEditor等,常见的反汇编工具有:IDA pro、W32dASM、C32ASM等。

M运用了很多篇幅简单介绍了各个工具的使用,我认为,这些工具的使用要在平常实战中渐渐熟悉,所以没必要将此章目看的过细。本人也只用过OllyDBG。

4)windows消息处理机制

5)PE文件格式

PE 的意思就是Portable Executable(可移植的执行体)。它是Win32环境自身所带的执行体文件格式。它的一些特性继承自UnixCoff (common object file format)文件格式。PE文件格式给了我们洞悉Windows结构的良机。

DOS MZ header
DOS stub
PE header
Section table
Section 1
Section 2
Section ...
Section n

上图是 PE文件结构的总体层次分布。所有PE文件(甚至32位的DLLs)必须以一个简单的DOS MZ header开始。我们通常对此结构没有太大兴趣。有了它,一旦程序在DOS下执行,DOS就能识别出这是有效的执行体,然后运行紧随MZ header 之后的DOS stubDOS stub实际上是个有效的EXE,在不支持PE文件格式的操作系统中,它将简单显示一个错误提示,类似于字符串"This program requires Windows"或者程序员可根据自己的意图实现完整的 DOS代码。通常我们也不对DOS stub太感兴趣:因为大多数情况下它是由汇编器/编译器自动生成。通常,它简单调用中断21h服务9来显示字符串"This program cannot run in DOS mode"

紧接着 DOS stub的是PE headerPE headerPE相关结构IMAGE_NT_HEADERS的简称,其中包含了许多PE装载器用到的重要域。当我们更加深入研究PE文件格式后,将对这些重要域耳目能详。执行体在支持PE文件结构的操作系统中执行时,PE装载器将从DOS MZ header 中找到PE header 的起始偏移量。因而跳过了DOS stub直接定位到真正的文件头PE headerPE文件的真正内容划分成块,称之为sections(节)。每节是一块拥有共同属性的数据,比如代码/数据、读/写等。我们可以把PE文件想象成一逻辑磁盘,PE header 是磁盘的boot扇区,而sections就是各种文件,每种文件自然就有不同属性如只读、系统、隐藏、文档等等。

上述为摘抄,翻译的不是很好

PE文件最前面紧随DOS MZ文件头的是一个DOS可执行文件(Stub)。这使得PE文件成为一个合法的MS-DOS可执行文件。DOS MZ文件头后面是一个32位的PE文件标志0x50450000(IMAGE_NT_SIGNATURE),即PE00。接下来的是PE的映像文件头,包含的信息有该程序的运行平台,有多少个节,文件链接的时间,文件命名格式,后面还紧跟一个可选映像头,包含PE文件的逻辑分布信息,程序加载信息,开始地址,保留的堆栈数量,数据段大小等。可选头还有一个重要的域,称为“数据目录表”的数组,表的每一项都是指向某一节的指针。可选映像头后面紧跟的是节表和节。节通过节表来实现索引。实际上,节的内容才是真正执行的数据和程序。每一个节都有相关的标志。每一个节会被一个或多个目录表指向,目录表可通过可选头的“数据目录表”的入口找到。就像输出函数表或基址重定位表。也存在没有目录表指向的节。

具体PE还有很多,这里只是一个初步的探究,如果想深入,网上找资料。


《软件调试分析技术》学习笔记(二)

1.寄存器

寄存器M讲的比较透彻。寄存器是中央处理器CPU的组成部分,是有限存贮容量的高速存贮部件,它们可用来暂存指
令、数据和位址,是内存阶层中的最顶端,也是系统获得操作资料的最快速途径。

1.1数据寄存器
数据寄存器主要用来保存操作数和运算结果等信息,从而节省读取操作数所需占用总线和访问
存储器的时间。这些 低16位寄存器分别命名为:AX、BX、CX和DX,它和先前的CPU中的寄存器
相一致。在16位CPU中,AX、BX、CX和DX不能作为基址和变址寄存器来存放存储单元的地址,
但在32位CPU中,其32位寄存器EAX、EBX、ECX和EDX不仅可传送数据、暂存数据保存算术逻辑
运算结果,而且也可作为指针寄存器, 所以,这些32位寄存器更具有通用性。

1.2变址寄存器
寄存器ESI、EDI、SI和DI称为变址寄存器(Index Register),它们主要用于存放存储单元在段内
的偏移量, 用它们可实现多种存储器操作数的寻址方式,为以不同的地址形式访问存储单元提供
方便。它们可作一般的存储器指针使用。在字符串操作指令的执行过程中,对它们有特定的要求,
而且还具有特 殊的功能。

1.3指针寄存器
寄存器EBP、ESP、BP和SP称为指针寄存器(Pointer Register),主要用于存放堆栈内存储单元
的偏移量, 用它们可实现多种存储器操作数的寻址方式,为以不同的地址形式访问存储单元提供
方便。指针寄存器不可分割成8位寄存器。作为通用寄存器,也可存储算术逻辑运算的操作数和运
算结果

它们主要用于访问堆栈内的存储单元,并且规定:
BP为基指针(Base Pointer)寄存器,用它可直接存取堆栈中的数据;
SP为堆栈指针(Stack Pointer)寄存器,用它只可访问栈顶。

1.4段寄存器
段寄存器是根据内存分段的管理模式而设置的。内存单元的物理地址由段寄存器的值和一个偏
移量组合而成 的,这样可用两个较少位数的值组合成一个可访问较大物理空间的内存地址

1.5指令指针寄存器
指令指针EIP、IP(Instruction Pointer)是存放下次将要执行的指令在代码段的偏移量。在具有预
取指令功能的系统中,下次要执行的指令通常已被预取到指令队列中,除非发生转移情况。
1.6标志寄存器
标志寄存器(Flags Register,FR)又称程序状态字(Program Status Word,PSW)。这是一个存
放条件标志、控制标志寄存器,主要用于反映处理器的状态和运算结果的某些特征及控制指令的执
行。

其中有些要有一定的汇编基础,希望大家好好在实践里体验。

2 汇编指令
汇编指令是汇编语言中使用的一些操作符和助记符,还包括一些伪指令(如assume,end)。用
于告诉汇编程序如何进行汇编的指令,它既不控制机器的操作也不被汇编成机器代码,只能为汇编
程序所识别并指导汇编如何进行。汇编指令多到数不过来。这里来介绍些常用到的:
一、数据传输指令
MOV 传送字或字节
PUSH 把字压入堆栈
POP 把字弹出堆栈
PUSHA 把AX,CX,DX,BX,SP,BP,SI,DI依次压入堆栈
POPA 把DI,SI,BP,SP,BX,DX,CX,AX依次弹出堆栈
PUSHAD 把EAX,ECX,EDX,EBX,ESP,EBP,ESI,EDI依次压入堆栈
POPAD 把EDI,ESI,EBP,ESP,EBX,EDX,ECX,EAX依次弹出堆栈
PUSHF 标志入栈
POPF 标志出栈
LEA 装入有效地址
LDS 传送目标指针,把指针内容装入DS
LES 传送目标指针,把指针内容装入ES
LAHF 标志寄存器传送,把标志装入AH
SAHF 标志寄存器传送,把AH内容装入标志寄存器
二、算术运算指令
ADD 加法
ADC 带进位加法
INC 加 1
SUB 减法
SBB 带借位减法
DEC 减 1
NEC 求相反数(以 0 减之)
CMP 比较(两操作数作减法,仅修改标志位,不回送结果)
MUL 无符号乘法
IMUL 整数乘法
DIV 无符号除法
IDIV 整数除法
三、逻辑运算指令
OR 或运算
AND 与运算
XOR 异或运算
NOT 取反
TEST 测试,两操作数作与运算,仅修改标志位,不回送结果
SHL 逻辑左移
SHR 逻辑右移
ROL 循环左移
ROR 循环右移
RCL 通过进位的循环左移
RCR 通过进位的循环右移
四、串指令
MOVSX 先符号扩展,再传送
MOVZX 先零扩展,再传送
MOVS 串传送
CMPS 串比较
五、程序转移指令
JMP 无条件转移指令
CALL 过程调用
RET 过程返回
JG/JNLE 大于转移
JGE/JNL 大于或等于转移
JL/JNGE 小于转移
JLE/JNG 小于或等于转移
JE/JZ 等于转移
JNE/JNZ 不等于时转移
LOOP CX不为零时循环


《软件调试分析技术》学习笔记(三)

M给出一个C程序

  1. #include<stdio.h>
  2. #include<stdlib.h>
  3. inta;
  4. intmain()
  5. {
  6. intb;
  7. int*c;
  8. c=(int*)malloc(sizeof(int));
  9. a=1;
  10. b=2;
  11. *c=3;
  12. free(c);
  13. return0;
  14. }


这段代码定义了一个整型全局变量a,在主函数main()中定义了一个整型局部变量b和一个整形指针变量c,然后调用malloc()函数申请大小为1个整形变量的内存并把申请到的内存地址赋值给指针变量c,再依次给变量a、b和c指向的内存赋值1、2、3,接下来释放刚才申请到的堆内存,释放后退出主函数main()。

用OD加载

  1. .text:00401000pushebp
  2. .text:00401001movebp,esp
  3. .text:00401003subesp,8

这里把栈顶向下压8个字节,为整型变量b和指针变量c开辟空间。它们都是局部变量。

  1. .text:00401006push4;Size
  2. .text:00401008callds:__imp__malloc
  3. .text:0040100Eaddesp,4
  4. .text:00401011mov[ebp+c],eax

一个整型变量占用的空间为4个字节,这里调用函数malloc()申请大小为4个字节的堆空间,然
后把申请到的内存空间地址赋值给变量c。

  1. .text:00401014mov?a@@3HA,1;inta
  2. .text:0040101Emov[ebp+b],2
  3. .text:00401025moveax,[ebp+c]
  4. .text:00401028movdwordptr[eax],3


这里分别给三个变量赋值1、2、3。可以看到变量a所使用的内存空间地址是一个常量,它存在于程序的数据段中;变量b所使用到的内存空间地址是ebp+b,它位于栈区;指针变量c储存的数据是刚才由函数malloc()申请到的堆空间地址。

  1. .text:0040102Emovecx,[ebp+c]
  2. .text:00401031pushecx;Memory
  3. .text:00401032callds:__imp__free
  4. .text:00401038addesp,4
  5. .text:0040103Bxoreax,eax
  6. .text:0040103Dmovesp,ebp
  7. .text:0040103Fpopebp
这里调用函数free()来释放刚才由函数malloc()申请到的堆空间地址。



《软件调试分析技术》学习笔记(四)

  1. 一起看看数组在程序中的使用。C语言代码:
  1. #include<stdio.h>
  2. intmain()
  3. {
  4. inta[2];
  5. a[1]=0;
  6. a[a[1]]=1;
  7. return0;
  8. }


这段代码定义了一个大小为2的整型数组,给数组下标为1的变量赋值0,然后取数组下标为1的变量的值作为新的下标,给该变量赋值1,这里数组下标为1的变量的值为0,就是说给数组下标为0的变量赋值1,最后退出主函数main()。

载入OD看看反汇编代码:

  1. .text:00401000pushebp
  2. .text:00401001movebp,esp
  3. .text:00401003subesp,8


这里为数组a开辟内存空间。一个整型变量所占的内存空间为4字节,数组a的大小为2,因此把栈顶向下压8个字节。

  1. text:00401006mov[ebp+a+1*4],0


只要知道数组就是一个指针,这句代码就很容易理解了。OD是一个好工具,这里它已经分析出a是一个数组了,而ebp+a是数组的基地址。a是一个整型数组,其中的每一个变量占用的大小都是4字节,因此在数组中下标为i的变量的地址就可以表示为数组的基地址加上数组下标为i的变量与数组下标为0的变量的偏移量,即ebp+a+i*4,这一句代码中的地址ebp+a+1*4就是数组下标为1的变量的地址。

  1. text:0040100Dmoveax,[ebp+a+1*4]
  2. .text:00401010mov[ebp+eax*4+a],1

这两句代码,获取数组中下标为1的变量的值,把这个值作为新的数组下标eax,并给数组下标为eax的变量赋值1。

  1. .text:00401018xoreax,eax
  2. .text:0040101Amovesp,ebp
  3. .text:0040101Cpopebp
  4. .text:0040101Dretn

《软件调试分析技术》学习笔记(五)

在了解了变量的使用方式之后,本节来讲讲数在反汇编代码中的简单运算。
计算机在使用数的时候一般会用到二进制,十进制和十六进制。

二进制是计算机技术中广泛采用的一种数制。二进制数据是用0和1两个数码来表示的数。它的基数为2,进位规则是“逢二进一”,借位规则是“借一当二”。现在的CPU使用的基本都是二进程数,用高电平表示1,低电平表示0。为了方便区别,一般在二进程数后追加一个字母B,例如二进制数10则表示为10B。B是二进制的英文binary的首字母。
在人们的日常生活使用的数一般都是十进制数。人类的各种古文明都很有默契地使用十进制数,这与人类有十根手指有密切的关系。十进制数使用十个数码0123456789来表示,逢十进一。为了方便区别,一般在十进程数后追加一个字母D,例如十进制数10则表示为10D。D是十进制的英文decimal的首字母。
在计算机中使用的十进制数一般是BCD码,BCD码用4位二进制数来表示1位十进制数。例如在二进制数10000B表示十进制数的16D,而BCD码10000却表示十进制数10D,它们在内存中的储存形式完全相同,但表示的数却不同。
虽然计算机在处理数据时使用的是二进制数,但是二进制数表示起来是很不方便的,例如一个十进制数1000000D要表示成二进制数则为11110100001001000000B。4位二进制数能表示的最小的数为0000B,能表示的最大的数是1111B,即十进制数15D,这样就可以用4位二进制数来表示16个数字,把这十六个数字分别用一个数码来表示,于是就行成了十六进制数。十六进制数用01234567890ABCDEF这十六个数码来表示0-15D这十六个数,每逢十六进一。为了方便表示,为了方便区别,一般在十六进程数后追加一个字母H,例如十六进制数10则表示为10H。H是十六进制的英文hexadecimal的首字母。一般在程序中用到的十六进制数的表示方法是在数之前加前缀0x,例如十六进制数10则表示为0x10。
通常这三种进制的数之间还需要互相转化。一位十六进程数和四位二进制数是互相对应的,对应关系如下:
十六进制数 二进制数 十六进制数 二进制数
0 0 8 1000
1 1 9 1001
2 10 A 1010
3 11 B 1011
4 100 C 1100
5 101 D 1101
6 110 E 1110
7 111 F 1111
了解了这个转化方式那要转化就很容易了,例如十六进制数0xBC就可以用二进制数10111100B;相反地,二进制数1001010B也可以表示为十六进制数0x4A。二进程数与十进制数之间的转换也是比较容易的。我记得当年学《微型计算机原理》的时候课本上有一句口诀:十进制数转化二进制数,除二取余;二进制数转化十进制数,乘二取整。听起来可能不太好理解,但这是转化方法的精髓。把十进制数转换成二进制数,是一个连续除2的过程,把要转换的十进制数数,除以2,得到一组商和余数;再用计算得到的商来计算,除以2,又得到另一组商和余数。这样一直计算到得到的商为零为止,计算结束后把每一次计算的余数从后往前连起来就得到了这个十进制数对应的二进程数。例如现在有一个十进制11D,转化过程如下:
11 / 2 商:5 余:1
5 / 2 商:2 余:1
2 / 2 商:1 余:0
1 / 2 商:0 余:1
把每一次计算的余数从后往前连起来则为1011,这样就计算出了十进制数11D对应的二进制数1011B。二进制数转化十进制数相对简单一点。二进制数从右往左数第n位表示2的n-1次幂,当第n位为0时忽略,把第n位为1的所有幂加起来就得到了这个十进制数。例如一个二进制数1011B,转化过程如下:
2^3 + 2^1 + 2^0 = 8 + 2 + 1 = 11
那么11D就是二进制数1011B所对应的十进制数。
再来看看另一个问题,机器码的表示方法。机器码的出现主要是为了解决计算机中数的符号和计算问题。这里介绍计算机的原码、反码、补码。
原码是一种计算机中对数字的二进制定点表示方法。原码表示法在数值前面增加了一位符号位(即最高位为符号位),符号位为0表示正数或者0,符号位为1表示负数,其余位表示数值的大小。例如一个int型的十进制数100,用原码表示则为:0000000001100100;同样一个int型的十进制数-100,用原码表示则为:1000000001100100。用原码这样来表示一个数是很直观的,但是它有一个很严重的缺点,就是源码不可以直接进行运算。1 + (-1) = 0,这是很显然的,用源码计算:
0000000000000001 + 1000000000000001 = 1000000000000010
用原码计算的结果为1000000000000010,转换为十进制数则是-2,这显然是错误的。 反码是原码到补码之间的一个过渡产品,它的求法很简单,正数的反码与其原码相同;负数的反码对其绝对值的原码逐位求反例如一个int 型的十进制数100,用原码表示则为:
0000000001100100

同样一个int型的十进制数-100,其绝对值为100,其绝对值的原码为
0000000001100100,逐位求反则得-100的反码为:1111111110011011。
补码是计算机程序在进行运算时统一使用的机器码,他可以将符号位和其它位统一处理。另外,两个用补码表示的数相加时,如果最高位(符号位)有进位,则进位被舍弃。补码的计算方法也很简单,正数的补码和它的原码相等,负数的补码等于它的反码加一。例如一个int型的十进制数-1,其补码计算过程为:首先求出它的绝对值为1,计算它的绝对值1的原码
0000000000000001,

逐位求反则得-1的反码为:1111111111111110,给它加1就变成了:
1111111111111111。

反码可以直接带入运算,例如用反码来计算1 + (-1):
0000000000000001 + 1111111111111111 = 0
然后来看看几种基本的逻辑运算。逻辑常量只有两个,即0和1,用来表示两个对立的逻辑状态。逻辑运算通常用来测试逻辑常量的真假值。大于、大于等于、小于、小于等于、等于、不等于……这些用来比较的逻辑运算就不讲了,上过小学的读者肯定都会的。这里来看看与运算、或运算、异或运算以及非运算。
与运算,把两个操作数的逐位进行比较,若两个操作数的第n位全为1,则运算结果的第n位为
1,否则为0。汇编语言中用and指令来表示与运算,例如:
0010110011010100
1010110010011010
and
-------------------
0010110010010000
或运算,把两个操作数的逐位进行比较,若两个操作数的第n位若有一个为1,则运算结果的第n位为1,否则为0。汇编语言中用or指令来表示或运算,例如:
0010110011010100
1010110010011010
or
-------------------
1010110011011110
异或运算,把两个操作数的逐位进行比较,若两个操作数的第n位有一个为0,而另一个为1,则运算结果的第n位为1,否则为0。汇编语言中用xor指令来表示异或运算,例如:
0010110011010100
1010110010011010
xor
-------------------
1000000001001110
非运算,只有一个操作数,它的计算方法是把该操作数逐位求反。汇编语言中用not指令来表示非运算,例如:
1010110010011010
not
-------------------
0101001101100101
笔者犹记得,当年教的模拟电路老师的几句简单的口令:与运算,有零则零;或运算,有一则

《软件调试分析技术》学习笔记(六)

异或运算,相同则1,不同则0;非运算,零则一,一则零。
明白了机器数和运算的原理以后来看看它们在程序运算中的具体使用方法。C语言代码如下:

  1. #include<stdio.h>
  2. intmain()
  3. {
  4. inta,b,c;
  5. a=1;
  6. b=2;
  7. c=a+b;
  8. c=a-b;
  9. c=a*b;
  10. c=a/b;
  11. c=a%b;
  12. c=a&b;
  13. c=a|b;
  14. c=a^b;
  15. c=~a;
  16. return0;
  17. }


这段代码定义了三个整型变量a、b、c,给变量a赋值1,给变量b赋值2,然后分别进行加、减、乘、除、模、与、或、异或还有非运算。看反汇编代码:

  1. .text:00401000pushebp
  2. .text:00401001movebp,esp
  3. .text:00401003subesp,0Ch



这里抬高栈顶,用来为定义的局部变量开辟储存空间。一个整型变量占4字节,那么0x0C字节则可开辟出三个整型变量的空间,用来储存整型变量a、b、c。

  1. .text:00401006mov[ebp+a],1
  2. .text:0040100Dmov[ebp+b],2


这两句分别对应C语言代码a = 1;和b = 2;。用来给整型变量a、b赋值。

  1. .text:00401014moveax,[ebp+a]
  2. .text:00401017addeax,[ebp+b]
  3. .text:0040101Amov[ebp+c],eax

这里取变量a到eax中,然后把eax和变量b相加,最后把结果放到变量c里。

  1. .text:0040101Dmovecx,[ebp+a]
  2. .text:00401020subecx,[ebp+b]
  3. .text:00401023mov[ebp+c],ecx


这里取变量a到ecx中,然后把ecx和变量b相减,最后把结果放到变量c里。

  1. .text:00401026movedx,[ebp+a]
  2. .text:00401029imuledx,[ebp+b]
  3. .text:0040102Dmov[ebp+c],edx


这里取变量a到edx中,然后把edx和变量b相乘,最后把结果放到变量c里。

  1. .text:00401030moveax,[ebp+a]
  2. .text:00401033cdq
  3. .text:00401034idiv[ebp+b]
  4. .text:00401037mov[ebp+c],eax

这里取变量a到eax中,接着扩展符号位,然后除以变量b,最后把商放到变量c里。

  1. .text:0040103Amoveax,[ebp+a]
  2. .text:0040103Dcdq
  3. .text:0040103Eidiv[ebp+b]
  4. .text:00401041mov[ebp+c],edx


这里取变量a到eax中,接着扩展符号位,然后除以变量b,最后把余数放到变量c里,这里和上面的除法运算的代码是很像的,只有最后储存运算结果的时候不同,除法运算储存的是eax的值,而模运算储存的是edx的值。细心的读者可能注意到了,做除法运算的时候多了一条cdq指令,它是干什么的?还有,idiv指令只有一个操作数它是怎么完成除法运算的。
其实dcq指令的作用是将双字符号扩展至8字节,指的是扩展eax的符号位至edx寄存器中,也就是说,当eax小于80000000时使edx为00000000,当eax大于等于80000000时使edx为FFFFFFFF。
idiv指令是有符号除法,被除数没有的指令中标出来,它是edx:eax。当idiv指令有操作数的时候,除数是操作数;如果没有操作数,那么除数就是ecx。指令的运算结果:eax为商,edx是余数。

  1. .text:00401044moveax,[ebp+a]
  2. .text:00401047andeax,[ebp+b]
  3. .text:0040104Amov[ebp+c],eax


这里取变量a到ecx中,然后把ecx和变量b做与运算,最后把结果放到变量c里。

  1. .text:0040104Dmovecx,[ebp+a]
  2. .text:00401050orecx,[ebp+b]
  3. .text:00401053mov[ebp+c],ecx

这里取变量a到ecx中,然后把ecx和变量b做或运算,最后把结果放到变量c里。

  1. .text:00401056movedx,[ebp+a]
  2. .text:00401059xoredx,[ebp+b]
  3. .text:0040105Cmov[ebp+c],edx

这里取变量a到edx中,然后把edx和变量b做异或运算,最后把结果放到变量c里。

  1. .text:0040105Fmoveax,[ebp+a]
  2. .text:00401062noteax
  3. .text:00401064mov[ebp+c],eax

这里取变量a到eax中,然后把eax和变量b做非运算,最后把结果放到变量c里。

  1. text:00401067xoreax,eax
  2. .text:00401069movesp,ebp
  3. .text:0040106Bpopebp
  4. .text:0040106Cretn


分享到:
评论

相关推荐

    基于机器学习、人工智能和深度学习的恶意代码分析学习笔记+源码.zip

    1、该资源内项目代码经过严格调试,下载即用确保可以运行! 2、该资源适合计算机相关专业(如计科、人工智能、大数据、数学、电子信息等)正在做课程...基于机器学习、人工智能和深度学习的恶意代码分析学习笔记+源码.zip

    (完整版)Python基础学习笔记.docx

    1.5.2理解问题的计算部分 使用计算机解决问题的6个步骤: 分析问题 划分边界 设计算法 编写程序 调试测试 升级维护 第2章 Python程序解析 2.1 Python程序语法元素分析 Python程序包括格式框架、注释、变量、表达式...

    net学习笔记及其他代码应用

    优点: 分工明确,条理清晰,易于调试,而且具有可扩展性。 缺点: 增加成本。 12.在下面的例子里 using System; class A { public A() { PrintFields(); } public virtual void PrintFields(){} } ...

    c#学习笔记.txt

    c#学习笔记(1) 51099在线学习网发布 文章来源:网络收集 发布时间:2006-05-25 字体: [大 中 小] 51099在线学习网 http://www.51099.com 1, 结构(struct) 与 类(class) [attributes] [modifiers] struct ...

    【软件加密_技术内幕】

    [Trial version] 5.7 反静态分析技术 [Trial version] Fooling Disassemblers.htm [Trial version] 5.7.2 花指令 [Trial version] 矛与盾的较量(1)——花指令.htm [Trial version] 5.8 代码与数据结合技术 ...

    (自学笔记)最全嵌入式Linux学习手册.docx

    硬件部件的使用及编程(囊括了常见硬件,比如uart、i2c、lcd等),u-boot、linux内核的分析、配置和移植,根文件系统的构造(包括移植busybox、glibc、制作映象文件等),内核调试技术(比如添加kgdb补丁、栈回溯等...

    study-electron:电子学习笔记

    电子学习笔记 什么是电子? 您可以使用 node.js (io.js) + Chromium 使用 web 技术 (html + css + javascript) 创建桌面应用程序 → 您可以使用浏览器 API 和节点 API 的组合 跨平台(mac、windows、Linux)兼容 ...

    安全客2020季刊第二季:新基建___智慧生活,从智能安全开始.pdf

    StarCTF 2019 v8 off-by-one漏洞学习笔记 Fastjson反序列化漏洞史 CodeQL学习——污点分析 循序渐进分析CVE-2020-1066 CVE-2020-8835 Pwn2Own ebpf提权漏洞分析 pipePotato:一种新型的通用提权漏洞 致谢

    基于SSM的笔记本管理系统

    通过SSM框架搭建的笔记本管理系统,主要是采用... 此资源以开发简化版Spring学习其原理和内核,不仅是代码编写实现也更注重内容上的需求分析和方案设计,所以在学习的过程要结合这些内容一起来实践,并调试对应的代码。

    spring-analysis-note:学习spring 5源码分析笔记

    欢迎来到Spring-Analysis-Note :waving_hand: Spring 5原始学习笔记最近开始学习Spring 5源码,做了一些分析笔记,希望能加深自己对日常一直在用的Spring容器的理解,也希望对你有帮助同时由于个人技术有限,出现...

    机器学习中的分类技术:Softmax分类算法及其在数据分析中的PyTorch应用

    技术经理和决策者寻求了解机器学习应用 AI爱好者和自学者 使用场景及目标: Softmax分类算法广泛应用于各种机器学习和数据分析场景,特别是在需要处理多类别输出的情况,如图像识别、自然语言处理和客户分群等领域。...

    中美 IT 培训 C# Asp.net 全套笔记1

    通过实际项目, 培养学生实战能力,包括系统分析、设计(包括功能需求分析、数据库设计、功能模块设计和详细设计)、开发、调试、测试和部署的能力。 总复习 考试与就业指导 (16课时) 串讲全部内容,并且针对实际...

    ARM学习超级全资料

    很全的ARM学习资料,个人整理的,与其闲置不容免费让大家学习! 《ARM嵌入式常用模块与综合系统设计实例精讲》练习题与答案.rar ...AT91SAM7S64调试笔记.rar 嵌入式系统设计与开发实例详解随书光盘源程序.rar

    51单片机自学笔记(6寸pdf)

     书中的全部内容均是作者亲自实践调试通过的,其中大部分内容采用倒叙的写作手法,即先给出设计内容的全貌,然后结合作者调试时遇到的问题和学生经常问的问题,以对话的形式对设计内容进行分析讲解。书中大胆采用了...

    51单片机自学笔记

    容的全貌,然后结合作者调试时遇到的问题和学生经常问的问题,以对话的形式对设计内容进行分析讲解。 书中大胆采用了许多来源于生活的卡通图片和生活用语,力争生动形象地讲述单片机技术。 本书既可以作为单片机爱好者...

    自己偷着乐吧!USB_HID_PC通信开发资料全集(学习笔记、源码、上位机、教程等)-电路方案

    STM32_USB_HID_分析:STM32 USB HID 固件学习分析 STM32_USB_HID_例子:STM32 USB HID方式收发例子。 STM32_USB_HID_学习心得:基于STM32 的USB程序开发笔记、修改STM32的USB例程为自己所用、初涉USB,初学者USB入门...

    中美 IT 培训 C# Asp.net 笔记2

    通过实际项目, 培养学生实战能力,包括系统分析、设计(包括功能需求分析、数据库设计、功能模块设计和详细设计)、开发、调试、测试和部署的能力。 总复习 考试与就业指导 (16课时) 串讲全部内容,并且针对实际...

    中美 IT 培训 C# Asp.net 笔记3

    通过实际项目, 培养学生实战能力,包括系统分析、设计(包括功能需求分析、数据库设计、功能模块设计和详细设计)、开发、调试、测试和部署的能力。 总复习 考试与就业指导 (16课时) 串讲全部内容,并且针对实际...

    《计算机的组成》教学设计.doc

    初一下学期学生已具备概括、抽象思维逻辑 ,课程内容从两个小情景分析入手,到学习计算机的组成,从了解计算机硬件、软件, 到软件的实现,通过编程,来提高学生学习的兴趣,扩大学生的认知面。 【教学目标】 1. ...

    java核心面试笔记+核心知识源码降解

    通过带着读者从java基础到java编写...阅读建议:此资源以开发简化版Spring学习其原理和内核,不仅是代码编写实现也更注重内容上的需求分析和方案设计,所以在学习的过程要结合这些内容一起来实践,并调试对应的代码。

Global site tag (gtag.js) - Google Analytics