Windows 逆向-数据宽度

Oyst3r 于 2023-11-22 发布

前言

这一节主要理解什么呢,要理解的是计算机里面存储数据都是有一个无形的容器的,计算机中存储的数据最终都是二进制存储的,每个容器都有最大容量,比如有的可以装 4 个二进制数,有的可以装 8 个二进制数,但其实归根到底,还是寄存器的宽度导致了存在数据宽度,要是寄存器有 5 位的,7 位的,那么肯定就会有相应的数据宽度,由于数据宽度的存在,数据运算就和个圈一样,下面会给出具体的图

符号问题的话,记住这一点:计算机只会做加减法,至于补码,反码啥的都是人去规定的,这个要结合之后的 JCC 才能彻底理解带符号的运算问题

因为计算机做任何运算,都需要先将数据存到某数据宽度的寄存器中,所以一定要指明数据宽度!!

课堂

总述

以前我们只是记忆过如果计算机中某容器只能存储 4 位二进制数,那么如果存无符号数,那四个位都可以存数,则一共十六种情况,0000 到 1111(24);如果存储有符号数,则最高位要被当做符号位,如果为 0 则为正数,如果为 1 则为负数,所以此时只能后三位用来表示数据值,则有正 000 到 111(23)和负 000 到 111。但是计算机真的认识有没有符号吗???而且我们平时说的反码,原码,补码,计算机不知道,这只是人们总结出来的规律

4 位宽度表示

实际上计算机中没有 4 位容器,我们只是为了引入方便理解,汇编中最小的容器数据宽度是 8 位的,即一个字节

0000 0001 0010 0011 0100 0101 0110 0111 1000 1001 1010 1011 1100 1101 1110 1111

0 1 2 3 4 5 6 7 8 9 A B C D E F

8 位宽度表示

假设现在 4 位不够表示我要存的数了,我换一个大一点的容器,存储数据的范围为 0x00 到 0xFF,即数据宽度为 8 位,那么此时此容器如果用来存无符号数,则可从 0x00 一直存到 0xFF,一共 28=256 种数;如果存有符号数,则还是切一半,00 到 7F 是正数,80 到 FF 为负数,化成二进制可以发现规律,80 到 FF 的最高位都是 1,即最高位为 1 的表示负数。正数同理可得。0xFF 为最大的负数-1,0x80 为最小的负数-128。

16 位宽度表示

32 位宽度表示

目前计算机中最常见的也是这个数据宽度的容器

汇编中对应宽度的单位

name 中文 bit 字节
BYTE 字节 8bit 1 字节
WORD 16bit 2 字节
DWORD 双字 32bit 4 字节

存储的数超过了容器的数据宽度

比如一个容器的数据宽度为 4 位,那么如果我现在存一个数 16,化为二进制为 10000,由于只能存 4 位,那么进位的多出来的位会被丢弃,最终读到的是 0000,即 0

逻辑运算

逻辑运算 汇编符号 C 语言符号  
or    
and &  
异或 xor ^  
not !  

加法计算

就是之后衍生出来的任何运算,包括加法减法乘法啦,都能用上面这几种给运算出来,这个在第一篇文章中也展示过一次,我们再来看一下计算机是如何计算 2+3 的,我们如果用汇编语言写 2+3,两个指令就可以搞定,但是对于计算机收到这个指令,计算机只会对以二进制存储的数据做逻辑运算得出结果,而计算机不会做加法运算,就只能这样

#x,y,R为存储数据的容器

2+3

x:0010
y:0011

    0010
xor 0011
------------
    0001        R:0001

    0010
and 0011
------------
    0010  <<1  得   0100       #<<1表示左移一位

此时计算机会判断0100是否全为0,如果全为0表示运算结束,将R中此时的值作为结果输出,如果不为0则将R中的值赋给x。0100赋给y再做一次同样运算

    0001
xor 0100
-------------
    0101         R:0101

    0001
and 0100
-------------
    0000  <<1  得   0000

判断0000全为0,则运算结束,将R中的值0101作为运算的结果,化成十进制即为5

如何获取某个值的第 N 位是 0 还是 1

比如现在某个寄存器中存了一个值,值化成二进制时,有些特殊的值每一位都有它的特殊含义,所以我们想要知道这个值的第 N 位是 0 还是 1。如果我们把寄存器中的值取出来,一个一个数着看,就会很麻烦,但是如果做下面的运算,就会容易很多:

#现在想要查看某寄存器中的值的第4位是0还是1,我们就可以将寄存器中的值与0x08做与运算,如果得到结果中有一个1,则这个值的第四位就是1,如果结果全是0,则值的第四位就是0

		10001111
and		00001000
----------------------
		00001000

加密解密

如果进行简单的加密,可以使用亦或运算,因为选择一个双方都知道密钥,用此密钥与数据做亦或加密加密过后,别人如果没有密钥则不好解开这个密文,而对于接受方,使用相同的密钥再做一次亦或即可得到原来的明文值

这里海东老师的例子

要加密的数据:20和15			00100000		00010101
		         	 ^	01010100	 ^	01010100
		         	     ------------ ------------
密钥:54				         01110100		01000001

加密后的结果:			      74		       41


					01110100	    01000001
		         	^	01010100	 ^  01010100
		         	     ------------- ------------
				        00100000            00010101

解密后的结果:				  20		       15

作业

1.2-5 等于-3,这个-3 要看存储容器的数据宽度了,如果数据宽度是 8 位,那么刚刚讲过有符号数是这么存储的:FF 是最大的负数-1,那么往前推,FE 表示-2,FD 表示-3,即结果化成十六进制就是 FD,至于最后答案要化成二进制还是八进制,计算机不管,计算机只管将-3 在 8 位宽度的容器中表示为 FD。同理如果是 16 位容器,则结果为 FFFD;32 位容器,则结果为 FFFFFFFD

2.

1000 0111 1010 1101 0110

xor 0101 加密密钥
----------------------------------------------------
1000 0111 1010 1101 0011 加密后的值
xor 0101 解密密钥
-----------------------------------------------------
1000 0111 1010 1101 0110 解密后的值,与原值一致

3.

2-3
假设数据宽度为4bit
-3在计算机中存储方式:先把-3表示出来1011,最高位为符号位,然后除符号位其他位取反最后加1即可(即原码转补码)
所以-3 = 1011 --> 1100 --> 1101 -->  D,即计算机收到-3后会将-3用二进制1101存储(数据宽度为4字节)

x:0010
y:1101

	0010
xor	1101
----------
	1111          R:1111

	0010
and	1101
----------
	0000   <<1   得0000

所以最终结果为1111,注意这只是计算机存储的形式,十六进制为F
根据计算机底层存储原理可以得到F表示最大的负数-1,可得到答案为-1;也可以通过1111除符号位取反1000,然后+1的1001,也可以得到答案是-1