note20200604
note20200604
Ivoripuionnotes from chapter 4
x86-64函数调用约定
VS编译出的64程序只有寄存器快速调用约定:前4个参数使用寄存器传递,超过的参数放在栈中,入栈顺序从右至左,由函数平衡堆栈。
- 参数1:RCX;
- 参数2:RDX;
- 参数3:R8;
参数4:R9;
任何大于8字节或者不是1字节、2字节、4字节、8字节的参数必须由引用来传递(地址传递)。所有浮点参数的传递都是使用XMM寄存器完成的,它们在XMM0、XMM1、XMM2和XMM3中传递。
参数1:XMM0;
- 参数2:XMM1;
- 参数3:XMM2;
- 参数4:XMM3;
如果参数既有浮点类型,又有整数类型,例如”void fun(float, int, float,int)”, 那么参数传递顺序为笫1个参数(XMM0)、笫2个参数(RDX)、 笫3个参数(XMM2)、笫4个参数(R9)。
如果参数是结构体且大于8字节,在传递参数时,会先把结构内容复制到栈空间中,再把结构体地址当成函数的参数来传递(引用传递)。
类的函数中,由于rcx寄存器保存了this指针,所以函数的参数调用从rdx开始使用。
虚函数相关
判断一个函数为构造函数或者析构函数:
函数的栈初始化完毕后,使用”lea reg, off_l40007970”和”mov[reg], reg”特征初始化虚表,且返回值为this指针,就可以怀疑这个函数是一个构造函数或者析构函数,这里的off_l40007970就是虚表指针。
多重继承时,一个类中会有多个虚表。
于纯虚函数没有实现代码,编译器默认填充了_purecall函数的地址。_purecall函数的功能就是显示一个错误信息并退出程序。这是识别抽象类的一个依据。
在逆向分析中,如果发现一个类的虚表里面有_purecall虚表项,就可以怀疑这个类是抽象类。
notes from chapter 5
一些验证产品序列号的方法
将用户名等信息作为自变量,通过函数F变换之后得到注册码
使用的变换:
1 | 序列号=F(用户名) |
通过该方法计算出来的序列号是以明文形式在内存中出现的,所以很容易就能在内存中找到它,从而获得注册码。
通过注册码验证用户名的正确性
使用的变换:
1 | 序列号=F(用户名) |
这里要求F是一个可逆变换。而软件在检查注册码的时候,是利用F的逆变换G对用户输入的注册码进行变换的。如果变换的结果和用户名相同,则说明是正确的注册码,即:
1 | 用户名=G(序列号) |
破解这种注册码检查方法时,除了可以采用修改比较指令的办法(爆破),还有如下考虑:
- 通过G(x)得出F(x),从而得到注册机;
- 给定一个用户名,通过穷举法找到一个G(x);
- 给定一个序列号,通过穷举法找到一个G(x);
通过对等函数检查注册码
使用的变换:
1 | F1(用户名)=F2(序列号) |
同时将用户名和注册码作为自变量(即采用二元函数)
1 | 特定值=F(用户名,序列号) |
总结
注册码的复杂性问题归根到底是一个数学问题。
如何攻击序列号保护机制
数据约束性原则
在序列保护号程序中,正确的序列号会在某一时刻出现在内存中。
“12121212”为输入的序列号,2470为正确的序列号。
hmemecpy函数
即万能断点。
利用提示信息
智能搜索->查找ascii。
注册机制作
keymake
一般断点设置:
- 进入注册码生成函数(call xxxxxxxx)断点一次;
- 进行比较时断点一次,断在push正确注册码时(push xxxx call strcmp);
点内存方式,寄存器设置为上面push的寄存器。
F1(用户名)=F2(密码)型注册机时
需要分析出F1逆函数G,用用户名=G(F2(密码))的方式制作注册机。
破解nag
找到DialogBoxParam
函数,将对话框处理函数指针指向的函数中的第一行指令改为jmp
到配合前面打开窗口的关闭窗口函数EndDialog
的下一行指令。
菜单功能限制
找到EnableMenultem()
或者EnableWindow
函数进行修改。
KeyFile
破解思路
破解过程
创建的文件名”KwazyWeb.bit”:
程序根据”KwazyWeb.bit”的内容跑迷宫,碰到”X”就算成功:
1 | signed int __usercall problem_401033@<eax>(char a1@<al>) |
迷宫:
1 | **************** |
答案:
1 | 222122232211010011100333030011111211011211122332330332223221110011112233 |
16进制:
1 | A9 AB A5 10 54 3F 30 55 65 16 56 BE F3 EA E9 50 55 AF |
最终答案:
1 | 04 6d 69 78 69 1e 1c 12 a7 e3 88 87 e2 d2 a1 e1 9 44 5d 5e e7 e2 18 |
1 | raw=[0xA9,0xAB,0xA5,0x10,0x54,0x3F,0x30,0x55,0x65,0x16,0x56,0xBE,0xF3,0xEA,0xE9,0x50,0x55,0xAF] |
check:
只运行运行一个实例
实现方法
查找窗口法
使用的api:findWindowA
。
互斥对象法
使用的api:CreateMutexA
。
使用共享内存块法
题目修改点:
1 | CODE:0040101A 74 01 jz short loc_40101D |
改为:
1 | CODE:0040101A EB 01 jmp short loc_40101D |