逆向学习笔记2
逆向学习笔记2
一 动态调试
1.exe与elf的区别
可执行文件指的是可以由操作系统进行加载执行的文件
可执行文件的文件格式常见有:exe 和 dll(Windows 系列)、elf(Linux 系列)
EXE(Executable)是Windows操作系统中的可执行文件格式,它是一种二进制格式,包含了程序的机器代码和相关的资源。EXE文件可以直接在Windows上运行,它通常以.exe作为文件扩展名。EXE文件可以包含多个可执行程序和库文件,它们可以通过链接器和加载器来进行连接和加载。
ELF(Executable and Linkable Format)是一种通用的可执行文件格式,主要用于UNIX和类UNIX操作系统,如Linux。ELF文件也是一种二进制格式,包含了程序的机器代码、数据和相关的元数据。ELF文件可以通过链接器和加载器来进行连接和加载,它支持动态链接和共享库的使用。
总的来说,EXE和ELF是不同操作系统中的可执行文件格式,它们在文件结构和使用方式上有一些区别。
文件结构上的区别:
- EXE文件通常包含一个程序的完整可执行代码,以及相关的资源和数据。它可以有多个节(section)来存储不同类型的数据。
- ELF文件也包含程序的可执行代码,但它使用节(section)和段(segment)的概念来组织数据。节用于存储不同类型的数据,而段用于定义内存映射的相关信息。
使用方式上的区别:
- EXE文件主要用于Windows操作系统,可以直接在Windows上运行。它可以通过Windows的API和资源管理器来访问和执行。
- ELF文件主要用于UNIX和类UNIX操作系统,如Linux。它可以通过命令行或者调用系统调用来执行。ELF文件还支持动态链接和共享库的使用,可以在运行时加载和链接所需的库。
此外,EXE和ELF还有一些其他细微的差异,比如文件头部的结构和字段的定义,以及特定操作系统的特定功能和限制。
2.IDA中F7和F8区别
F8 | Step Over 表示跳到下一步 |
---|---|
F7 | Step Into 表示进入到代码 |
一句话:1、想要点进方法里面就按F7
2、想要跳转到下一行就按F8
3.调试sub.elf
首先将IDA的linux_server64放在虚拟机中,再在虚拟机命令行里用管理员(sudo linux_server64)打开,再在命令行运行要调试的sub.elf,在回主机打开IDA,在debugger里找到Attach,再找到remote linux debugger,输入虚拟机的ip(用ifconfig -a命令查找),确认完毕后,即可对sub.elf进行调试(包括F2下断点,F7和F8的步入和步过)
注:如果要调试安卓的文件等,要先运行android_x64_server等文件(注意版本问题),其他步骤类似同上。
二. 位运算
1.位运算概述
从现代计算机中所有的数据二进制的形式存储在设备中。即 0、1 两种状态,计算机对二进制数据进行的运算(+、-、*、/)都是叫位运算,即将符号位共同参与运算的运算。
2.位运算概览:
符号 | 描述 | 运算规则 |
---|---|---|
& | 与 | 两个位都为1时,结果才为1 |
| | 或 | 两个位都为0时,结果才为0 |
^ | 异或 | 两个位相同为0,相异为1 |
~ | 取反 | 0变1,1变0 |
<< | 左移 | 各二进位全部左移若干位,高位丢弃,低位补0 |
>> | 右移 | 各二进位全部右移若干位,对无符号数,高位补0,有符号数,各编译器处理方法不一样,有的补符号位(算术右移),有的补0(逻辑右移) |
注意:
逻辑运算符:位与(&),位或(|),位异或(^),位非(~)。
移位运算符:左移(<<),右移(>>),无符号右移(>>>)。
3.按位与运算符(&):
定义:参加运算的两个数据,按二进制位进行”与”运算。
运算规则:
1 | 0&0=0 0&1=0 1&0=0 1&1=1 |
总结:两位同时为1,结果才为1,否则结果为0。
例如:3&5 即 0000 0011& 0000 0101 = 0000 0001,因此 3&5 的值得1。
注意:负数按补码形式参加按位与运算。
4.与运算的用途:
1)清零
如果想将一个单元清零,即使其全部二进制位为0,只要与一个各位都为零的数值相与,结果为零。
2)取一个数的指定位
比如取数 X=1010 1110 的低4位,只需要另找一个数Y,令Y的低4位为1,其余位为0,即Y=0000 1111,然后将X与Y进行按位与运算(X&Y=0000 1110)即可得到X的指定位。
3)判断奇偶
只要根据最未位是0还是1来决定,为0就是偶数,为1就是奇数。因此可以用if ((a & 1) == 0)代替if (a % 2 == 0)来判断a是不是偶数。
5.按位或运算符(|):
定义:参加运算的两个对象,按二进制位进行”或”运算。
1 | 0|0=0 0|1=1 1|0=1 1|1=1 |
总结:参加运算的两个对象只要有一个为1,其值为1。
例如:3|5即 0000 0011| 0000 0101 = 0000 0111,因此,3|5的值得7。
注意:负数按补码形式参加按位或运算。
6.或运算的用途:
常用来对一个数据的某些位设置为1
比如将数 X=1010 1110 的低4位设置为1,只需要另找一个数Y,令Y的低4位为1,其余位为0,即Y=0000 1111,然后将X与Y进行按位或运算(X|Y=1010 1111)即可得到。
7.异或运算符(^):
定义:参加运算的两个数据,按二进制位进行”异或”运算。
运算规则:
1 | 0^0=0 0^1=1 1^0=1 1^1=0 |
总结:参加运算的两个对象,如果两个相应位相同为0,相异为1。
8.异或运算的用途:
1)翻转指定位
比如将数 X=1010 1110 的低4位进行翻转,只需要另找一个数Y,令Y的低4位为1,其余位为0,即Y=0000 1111,然后将X与Y进行异或运算(X^Y=1010 0001)即可得到。
2)与0相异或值不变
例如:1010 1110 ^ 0000 0000 = 1010 1110
3)使一个数的最低位为零
使a的最低位为0,可以表示为:a & 1。1的值为 1111 1111 1111 1110,再按”与”运算,最低位一定为0。因为” ~”运算符的优先级比算术运算符、关系运算符、逻辑运算符和其他运算符都高。
9.异或的几条性质:
- 1、交换律
- 2、结合律 (a^b)^c == a^(b^c)
- 3、对于任何数x,都有 x^x=0,x^0=x
- 4、自反性: a^b^b=a^0=a;
10.取反运算符 (~):
定义:参加运算的一个数据,按二进制进行”取反”运算。
运算规则:
1 | ~1=0 |
总结:对一个二进制数按位取反,即将0变1,1变0。
11.左移运算符(<<):
定义:将一个运算对象的各二进制位全部左移若干位(左边的二进制位丢弃,右边补0)。
设 a=1010 1110,a = a<< 2 将a的二进制位左移2位、右补0,即得a=1011 1000。
若左移时舍弃的高位不包含1,则每左移一位,相当于该数乘以2。
12.右移运算符(>>):
定义:将一个数的各二进制位全部右移若干位,正数左补0,负数左补1,右边丢弃。
例如:a=a>>2 将a的二进制位右移2位,在符号位左补0 或者 左补1得看被移数是正还是负。
操作数每右移一位,相当于该数除以2。
手搓base64代码
1 | import base64 #导入base64模块 |
task题目wp
1.base题目
首先查看有没有upx壳,发现没有后,直接IDA分析,F5看伪代码,然后看到两个字符串”443067337B495F4C3076655F53616B7572616A696D614D61697D“和“0123456789ABCDEF”前者经过分析下面的伪代码,可以看出这就是我们要比较的目标,后者分析发现形式非常像16进制,在分析伪代码发现,代码进行的移位加密非常像Base64,结合想法后可以得出结论:这是一个Base16加密,于是直接用网上在线的base16解码解第一个字符串就得出flag了。
1 | D0g3{I_L0ve_SakurajimaMai} |
总结:题目本身是非常简单的,难点在于认出这是base16加密,这类题目通常会给出一个标准的密码表,如base16的“0123456789ABCDEF”,这是提示,也是解题的关键,所以对base系列的伪代码移位要足够熟练才能快速认出。
2.xor题目
首先查看有没有壳,发现无壳后IDA分析,发现输入的s[]与s1[]进行了异或操作,又点击sub_916找s1[],发现s1[]与s2[]比较,直接点击s2[]看字符串用lazy_ida将s2[]取出得到:
1 | s2[] =[0x56, 0x4E, 0x57, 0x58, 0x51, 0x51, 0x09, 0x46, 0x17, 0x46, 0x54, 0x5A, 0x59, 0x59, 0x1F, 0x48, 0x32, 0x5B, 0x6B, 0x7C, 0x75, 0x6E, 0x7E, 0x6E, 0x2F, 0x77, 0x4F, 0x7A, 0x71, 0x43, 0x2B, 0x26, 0x89, 0xFE,0x00] |
此时直接写一个s2与s1异或的脚本会出现如下结果:
1 | '/$ 2(}!d''":/m-T<A*$INç |
发现不是所求的flag,于是重新看伪代码,对s1进行ctrl+x进行交叉引用,发现有一个sub_84A函数引用了s1,点进去:
1 | for ( i = 0; i <= 33; ++i ) |
发现s1又进行了一次异或,所以更改脚本:
1 | T1 = 'qasxcytgsasxcvrefghnrfghnjedfgbhn' |
解出flag
1 | flag{c0n5truct0r5_functi0n_in_41f} |
总结:本题伪代码非常简单,但是可能会遗漏s1又进行了一次异或这个关键条件,所以,要常常交叉引用一下看这个s1是否在别处进行了引用,不能只看明面上的伪代码,要仔细找到题目中每一个关键条件,只有这样才能解出真正的flag。
第三周总结
第三周整体难度不高,主要是知识上的积累,题目方面变得更加有难度,同时更考验细心程度,这可能就是逆向的解题关键,仔细分析伪代码,认真找题目要点,结合条件编写脚本,这就是我这一周最大的收获了吧。(弱弱问一句,第三周压缩包里是只有base和xor是题目吗,其他都是给我们看一下这些函数内部构成吗?)