首页 > 编程语言 >逆向——汇编中的位运算

逆向——汇编中的位运算

时间:2023-06-02 20:05:03浏览次数:41  
标签:右移 逆向 运算 汇编 SAL 左移 al CF SHL

汇编中的移位指令

1、算术移位指令

 

SAL(算术左移)指令的操作与《SHL指令》一节中的 SHL 指令一样。每次移动时,SAL 都将目的操作数中的每一位移动到下一个最高位上。最低位用 0 填充;最高位移入进位标志位,该标志位原来的值被丢弃:

逆向——汇编中的位运算_操作数

如,二进制数 1100 1111 算术左移一位,得到 1001 1110:

逆向——汇编中的位运算_移位指令_02

SAR(算术右移)指令将目的操作数进行算术右移:

逆向——汇编中的位运算_移位指令_03

  • SAL(Shift Arithmetic Left):算术左移
  • SAR(Shift Arithmetic Right):算术右移
  • 格式:SAL/SAR Reg/Mem, CL/Imm

即算数移位指令后面的第一个操作数是寄存器或者内存;

第二个操作数是寄存器或者立即数

SAL eax,2
SAL ax,1
SAL al,3


举例:
SAR al,1         //al:10000001右移一位最高位补原来符号位,最低位移入CF,即11000000 / CF:1
SAL al,2         //al:10000001左移两位最高位移入CF,最低位补0,即00000100  /  CF:0

2.逻辑移位指令

SHL(左移)指令使目的操作数逻辑左移一位,最低位用 0 填充。最高位移入进位标志位,而进位标志位中原来的数值被丢弃:

逆向——汇编中的位运算_循环右移_04

若将 1100 1111 左移 1 位,该数就变为 1001 1110:

逆向——汇编中的位运算_逆向分析_05

mov dl, 10           ;移动前:00001010
shl dl, 2               ;移动后:00101000

 

 SHR(右移)指令使目的操作数逻辑右移一位,最高位用 0 填充。最低位复制到进位标志位,而进位标志位中原来的数值被丢弃:

逆向——汇编中的位运算_逆向分析_06

  • SHL(Shift Left):逻辑左移
  • SHR(Shift Right):逻辑右移
  • 格式:SHL/SHR Reg/Mem, CL/Imm
SHL eax,2
SHR word ptr es:[ebp],1
SHL al,1

举例:
SHR al,1          //al:10000001右移一位最高位补0,最低位移入CF,即01000000  /  CF:1
SHL al,1          //al:01000001左移一位最高位移入CF,最低位补0,即10000010  /  CF:0
  • shl/sal区别?这样一看,似乎SHL和SAL指令是完全一样的
    区别在于,SHL是逻辑左移SAL是算术左移

SAL算术移位需要考虑最高位的符号位,要保证移到后的最高位,也就是符号位不变。用于带符号数的运算。
最高位符号位移入CF,但本身保持原值,其余位顺序左移,次高位被舍弃。

SHL逻辑移不用考虑直接移就ok。所有位顺序左移,最高位移入CF,最低位补0。用于无符号数的计算

 

3.循环移位指令

 以循环方式来移位即为位元循环(Bitwise Rotation)。一些操作中,从数的一端移出的位立即复制到该数的另一端。还有一种类型则是把进位标志位当作移动位的中间点。

ROL(循环左移)指令把所有位都向左移。最高位复制到进位标志位和最低位。该指令格式与 SHL 指令相同:

逆向——汇编中的位运算_移位指令_07

位循环不会丢弃位。

ROR(循环右移)指令把所有位都向右移,最低位复制到进位标志位和最高位。该指令格式与 SHL 指令相同:

逆向——汇编中的位运算_循环右移_08

 

  • ROL(Rotate Left):循环左移
  • ROR(Rotate Right):循环右移
  • 格式:ROL/ROR r/m, i8/CL
ROL eax,3
ROL cx,1
ROR cl,2

举例
ROL al,1    //al:10000001循环左移一位最高位补到最低位,最高位移入CF,即00000011  /  CF:1
ROR al,1    //al:10000001循环右移一位最低位补到最高位,最低位移入CF,即11000000  /  CF:1

4.带进位的循环移位指令

 

  • RCL(Rotate through Carry Left):带进位循环左移
  • RCR(Rotate through Carry Right):带进位循环右移
  • 格式:RCL/RCR r/m, i8/CL
RCL eax,1
RCR cx,2
RCR al,1

举例:
RCL al,1  //al:10000001,CF:0循环左移一位最高位移入CF,CF原来的数补到最低位,即al:00000010 / CF:1
RCR al,1  //al:10000001,CF:0循环右移一位最低位移入CF,CF原来的数补到最高位,即al:01000000 / CF:1

C语言中的移位运算

与运算 &

printf("%d",2&3); //2

或运算 |

printf("%d",2|3); //3

非运算 ~

printf("%d",~2); //-3,因为%d打印的是有符号的整数

异或运算 ^

printf("%d",2^3); //1

移位运算 << >>

左移运算,有符号和无符号是无区别的

int a = 8;
printf("%d",a<<1);  //16
unsigned int b = 8;
printf("%d",b<<1);  //16

查看反汇编:生成的汇编指令都是shl,逻辑左移

逆向——汇编中的位运算_逆向分析_09

右移运算,有符号对应SAR即算数右移,无符号对应SHR即逻辑右移

int a = 0xF0000000;
printf("%d",a>>1);  //-134217728
unsigned int b = 0xF0000000;
printf("%d",b>>1);  //2013265920

查看反汇编:有符号右移生成的指令为SAR,无符号右移生成的指令为SHR

逆向——汇编中的位运算_逆向分析_10

作业【有错,pass吧】

 

#include "stdafx.h"


    void Function_1_1()     
    {
            unsigned char x=0xf5,y=0xff;
            int i;
            scanf("%d",&i);
        /*  if((x=x&(y<<i))==0)
                (printf("第%d位是0",i+1));
            else
                (printf("第%d位是1",i+1));
*/
    printf("第%d位是%x",i,x=x&(y>>(8-i))); 
        //  printf("%x",x);
            
    }       



int main()
{           

        Function_1_1();             

    return 0;

}

 

16:       unsigned char x=0xf5,y=0xff;
0040D830   mov         byte ptr [ebp-0Ch],0F5h
0040D834   mov         byte ptr [ebp-10h],0FFh
17:       int i;
18:       scanf("%d",&i);
0040D838   lea         ecx,[ebp-14h]
0040D83B   push        ecx
0040D83C   push        offset string "112" (00422134)
0040D841   call        scanf (0040faa0)
0040D846   add         esp,8
19:   /*  if((x=x&(y<<i))==0)
20:           (printf("第%d位是0",i+1));
21:       else
22:           (printf("第%d位是1",i+1));
23:   */
24:       printf("第%d位是%x",i,x=x&(y>>(8-i)));
0040D849   mov         edx,dword ptr [ebp-0Ch]
0040D84C   and         edx,0FFh
0040D852   mov         eax,dword ptr [ebp-10h]
0040D855   and         eax,0FFh
0040D85A   mov         ecx,8
0040D85F   sub         ecx,dword ptr [ebp-14h]
0040D862   sar         eax,cl;//********************关键**************
0040D864   and         edx,eax
0040D866   mov         byte ptr [ebp-0Ch],dl
0040D869   mov         ecx,dword ptr [ebp-0Ch]
0040D86C   and         ecx,0FFh
0040D872   push        ecx
0040D873   mov         edx,dword ptr [ebp-14h]
0040D876   push        edx
0040D877   push        offset string "%d\n" (0042201c)
0040D87C   call        printf (00401120)
0040D881   add         esp,0Ch

 

逆向——汇编中的位运算_逆向分析_11

 

 

看来这个小伙做错了!!!

 

  • 用十六进制文本编辑器分别打开一个.exe、.dll、.sys、.txt、.doc、.jpg、.pdf等将前两个字节写在下面

.exe:内存中显式为4D 5A,我们读作0x5A4D.dll:同样是4D 5A.sys:4D 5A开头,但也有25 75.txt:0A 66,读作0x660A.doc:D0 CF,读作0xCFD0.jpg:FF D8.pdf:25 50,读作0x5025

  • 将一个在十六进制编辑器中打开的.exe文件,拖拽到最后,观察文件中的大小和硬盘上的大小

可以发现用十六进制编辑器打开一个.exe文件,它的最大地址0x0829CDF0,换算成10进制,就刚好等于这个文件的大小136957440字节

逆向——汇编中的位运算_移位指令_12

 

分类: 逆向-PE

汇编中的移位指令

1、算术移位指令

 

SAL(算术左移)指令的操作与《SHL指令》一节中的 SHL 指令一样。每次移动时,SAL 都将目的操作数中的每一位移动到下一个最高位上。最低位用 0 填充;最高位移入进位标志位,该标志位原来的值被丢弃:

逆向——汇编中的位运算_操作数

如,二进制数 1100 1111 算术左移一位,得到 1001 1110:

逆向——汇编中的位运算_移位指令_02

SAR(算术右移)指令将目的操作数进行算术右移:

逆向——汇编中的位运算_移位指令_03

  • SAL(Shift Arithmetic Left):算术左移
  • SAR(Shift Arithmetic Right):算术右移
  • 格式:SAL/SAR Reg/Mem, CL/Imm

即算数移位指令后面的第一个操作数是寄存器或者内存;

第二个操作数是寄存器或者立即数

SAL eax,2
SAL ax,1
SAL al,3


举例:
SAR al,1         //al:10000001右移一位最高位补原来符号位,最低位移入CF,即11000000 / CF:1
SAL al,2         //al:10000001左移两位最高位移入CF,最低位补0,即00000100  /  CF:0

2.逻辑移位指令

SHL(左移)指令使目的操作数逻辑左移一位,最低位用 0 填充。最高位移入进位标志位,而进位标志位中原来的数值被丢弃:

逆向——汇编中的位运算_循环右移_04

若将 1100 1111 左移 1 位,该数就变为 1001 1110:

逆向——汇编中的位运算_逆向分析_05

mov dl, 10           ;移动前:00001010
shl dl, 2               ;移动后:00101000

 

 SHR(右移)指令使目的操作数逻辑右移一位,最高位用 0 填充。最低位复制到进位标志位,而进位标志位中原来的数值被丢弃:

逆向——汇编中的位运算_逆向分析_06

  • SHL(Shift Left):逻辑左移
  • SHR(Shift Right):逻辑右移
  • 格式:SHL/SHR Reg/Mem, CL/Imm
SHL eax,2
SHR word ptr es:[ebp],1
SHL al,1

举例:
SHR al,1          //al:10000001右移一位最高位补0,最低位移入CF,即01000000  /  CF:1
SHL al,1          //al:01000001左移一位最高位移入CF,最低位补0,即10000010  /  CF:0
  • shl/sal区别?这样一看,似乎SHL和SAL指令是完全一样的
    区别在于,SHL是逻辑左移SAL是算术左移

SAL算术移位需要考虑最高位的符号位,要保证移到后的最高位,也就是符号位不变。用于带符号数的运算。
最高位符号位移入CF,但本身保持原值,其余位顺序左移,次高位被舍弃。

SHL逻辑移不用考虑直接移就ok。所有位顺序左移,最高位移入CF,最低位补0。用于无符号数的计算

 

3.循环移位指令

 以循环方式来移位即为位元循环(Bitwise Rotation)。一些操作中,从数的一端移出的位立即复制到该数的另一端。还有一种类型则是把进位标志位当作移动位的中间点。

ROL(循环左移)指令把所有位都向左移。最高位复制到进位标志位和最低位。该指令格式与 SHL 指令相同:

逆向——汇编中的位运算_移位指令_07

位循环不会丢弃位。

ROR(循环右移)指令把所有位都向右移,最低位复制到进位标志位和最高位。该指令格式与 SHL 指令相同:

逆向——汇编中的位运算_循环右移_08

 

  • ROL(Rotate Left):循环左移
  • ROR(Rotate Right):循环右移
  • 格式:ROL/ROR r/m, i8/CL
ROL eax,3
ROL cx,1
ROR cl,2

举例
ROL al,1    //al:10000001循环左移一位最高位补到最低位,最高位移入CF,即00000011  /  CF:1
ROR al,1    //al:10000001循环右移一位最低位补到最高位,最低位移入CF,即11000000  /  CF:1

4.带进位的循环移位指令

 

  • RCL(Rotate through Carry Left):带进位循环左移
  • RCR(Rotate through Carry Right):带进位循环右移
  • 格式:RCL/RCR r/m, i8/CL
RCL eax,1
RCR cx,2
RCR al,1

举例:
RCL al,1  //al:10000001,CF:0循环左移一位最高位移入CF,CF原来的数补到最低位,即al:00000010 / CF:1
RCR al,1  //al:10000001,CF:0循环右移一位最低位移入CF,CF原来的数补到最高位,即al:01000000 / CF:1

C语言中的移位运算

与运算 &

printf("%d",2&3); //2

或运算 |

printf("%d",2|3); //3

非运算 ~

printf("%d",~2); //-3,因为%d打印的是有符号的整数

异或运算 ^

printf("%d",2^3); //1

移位运算 << >>

左移运算,有符号和无符号是无区别的

int a = 8;
printf("%d",a<<1);  //16
unsigned int b = 8;
printf("%d",b<<1);  //16

查看反汇编:生成的汇编指令都是shl,逻辑左移

逆向——汇编中的位运算_逆向分析_09

右移运算,有符号对应SAR即算数右移,无符号对应SHR即逻辑右移

int a = 0xF0000000;
printf("%d",a>>1);  //-134217728
unsigned int b = 0xF0000000;
printf("%d",b>>1);  //2013265920

查看反汇编:有符号右移生成的指令为SAR,无符号右移生成的指令为SHR

逆向——汇编中的位运算_逆向分析_10

作业【有错,pass吧】

 

#include "stdafx.h"


    void Function_1_1()     
    {
            unsigned char x=0xf5,y=0xff;
            int i;
            scanf("%d",&i);
        /*  if((x=x&(y<<i))==0)
                (printf("第%d位是0",i+1));
            else
                (printf("第%d位是1",i+1));
*/
    printf("第%d位是%x",i,x=x&(y>>(8-i))); 
        //  printf("%x",x);
            
    }       



int main()
{           

        Function_1_1();             

    return 0;

}

 

16:       unsigned char x=0xf5,y=0xff;
0040D830   mov         byte ptr [ebp-0Ch],0F5h
0040D834   mov         byte ptr [ebp-10h],0FFh
17:       int i;
18:       scanf("%d",&i);
0040D838   lea         ecx,[ebp-14h]
0040D83B   push        ecx
0040D83C   push        offset string "112" (00422134)
0040D841   call        scanf (0040faa0)
0040D846   add         esp,8
19:   /*  if((x=x&(y<<i))==0)
20:           (printf("第%d位是0",i+1));
21:       else
22:           (printf("第%d位是1",i+1));
23:   */
24:       printf("第%d位是%x",i,x=x&(y>>(8-i)));
0040D849   mov         edx,dword ptr [ebp-0Ch]
0040D84C   and         edx,0FFh
0040D852   mov         eax,dword ptr [ebp-10h]
0040D855   and         eax,0FFh
0040D85A   mov         ecx,8
0040D85F   sub         ecx,dword ptr [ebp-14h]
0040D862   sar         eax,cl;//********************关键**************
0040D864   and         edx,eax
0040D866   mov         byte ptr [ebp-0Ch],dl
0040D869   mov         ecx,dword ptr [ebp-0Ch]
0040D86C   and         ecx,0FFh
0040D872   push        ecx
0040D873   mov         edx,dword ptr [ebp-14h]
0040D876   push        edx
0040D877   push        offset string "%d\n" (0042201c)
0040D87C   call        printf (00401120)
0040D881   add         esp,0Ch

 

逆向——汇编中的位运算_逆向分析_11

 

 

看来这个小伙做错了!!!

 

  • 用十六进制文本编辑器分别打开一个.exe、.dll、.sys、.txt、.doc、.jpg、.pdf等将前两个字节写在下面

.exe:内存中显式为4D 5A,我们读作0x5A4D.dll:同样是4D 5A.sys:4D 5A开头,但也有25 75.txt:0A 66,读作0x660A.doc:D0 CF,读作0xCFD0.jpg:FF D8.pdf:25 50,读作0x5025

  • 将一个在十六进制编辑器中打开的.exe文件,拖拽到最后,观察文件中的大小和硬盘上的大小

可以发现用十六进制编辑器打开一个.exe文件,它的最大地址0x0829CDF0,换算成10进制,就刚好等于这个文件的大小136957440字节

逆向——汇编中的位运算_移位指令_12

标签:右移,逆向,运算,汇编,SAL,左移,al,CF,SHL
From: https://blog.51cto.com/u_11908275/6404734

相关文章

  • upc 8378: Floating-Point Numbers(模拟浮点数运算)
    8378:Floating-PointNumbers时间限制:1Sec  内存限制:128MB提交:10  解决:4[提交][状态][讨论版][命题人:admin]题目描述Inthisproblem,weconsiderfloating-pointnumberformats,datarepresentationformatstoapproximaterealnumbersoncomputers.S......
  • 2023安卓逆向 -- JNI学习(从开发到反编译)
    一、新建nativeC++项目,填写好项目信息,一路下一步即可二、创建好项目,直接点击运行,出现下面界面,说明我们的环境都没有问题三、Java层调用java层函数1、新建一个JavaClass,命名为JavaFun2、编写java函数packagecom.example.jnitest;publicclassJavaFun{publicstaticStr......
  • java精确除法运算-BigDecimal
    一、BigDecimal介绍Java中提供了大数字(超过16位有效位)的操作类,即java.math.BinInteger类和java.math.BigDecimal类,用于高精度计算.其中BigInteger类是针对大整数的处理类,而BigDecimal类则是针对大小数的处理类.BigDecimal类的实现用到了BigInteger类,不......
  • C语言——运算符和表达式
    所谓表达式就是指由运算符、运算量和标点符号组成的有效序列,其目的是说明一个计算过程。表达式可以独立成语句:表达式;运算符按功能分为:算术运算、赋值运算、关系运算、逻辑运算、位运算以及其他运算符1.算术运算符:+-*/%++–(1)/:整数相除,向下取整。inta=3/2;floatb=3/2;fl......
  • 定点乘法运算
    原码的一位乘法:首先部分积为0,部分积用双符号位表示,乘数用单符号位表示,两者都是绝对值x=-0.1101 y=-0.1011[x*y]]原?|x|=0.1101 |y|=0.1011  00.0000   +00.1101    0.1011=00.1101    =00.01101    +00.1101     0.101=01.......
  • JS逆向实战16——猿人学第20题 新年挑战-wasm进阶
    声明本文章中所有内容仅供学习交流,抓包内容、敏感网址、数据接口均已做脱敏处理,严禁用于商业用途和非法用途,否则由此产生的一切后果均与作者无关,若有侵权,请联系我立即删除!网站https://match.yuanrenxue.cn/match/20网站分析首先进去网站,我们查看下接口发现有两个值是改变......
  • 关系运算符加法
    题目描述请编写一个函数,将两个数字相加。不得使用+或其他算数运算符。给定两个intA和B。请返回A+B的值测试样例:1,2返回:3classUnusualAdd{public:intaddAB(intA,intB){//writecodeherewhile(B!=0){inttemp=A......
  • day16 Python下的三元运算符
    Python下的三元运算符【一】引言三元表达式(三目运算符)能够简洁我们的代码三元表达式其实是将if...else...判断语句的简化表达,代替很多ifelse和if-else一样,只有一个表达式会被执行。因此,三元表达式中的if和else可以包含大量的计算,但只有True的分支会被执行在Java、C......
  • C++ 中的运算符优先级
     运算符的优先级确定表达式中项的组合。这会影响到一个表达式如何计算。某些运算符比其他运算符有更高的优先级,例如,乘除运算符具有比加减运算符更高的优先级。例如x=7+3*2,在这里,x被赋值为13,而不是20,因为运算符*具有比+更高的优先级,所以首先计算乘法3*2,然后再加......
  • 位运算符
     位运算符作用于位,并逐位执行操作。&、|和^的真值表如下所示:pqp&qp|qp^q00000010111111010011假设如果A=60,且B=13,现在以二进制格式表示,它们如下所示:A=00111100B=00001101-----------------A&B=00001100A|B=0......