160个crackme 024详细题解(动态指令)
0x4012DD处开始向后的三条指令是关键
004012DD lods dword ptr ds:[esi]; 从[0x4011ec处开始,每次向后取4个字节(高端存取法),进行异或运算],直到执行到向后偏移4 * 0x3E个字节
- 004012DD > AD lods dword ptr ds:[esi] ; 从[0x4011ec处开始,每次向后取4个字节(高端存取法),进行异或运算],直到执行到向后偏移4 * 0x3E个字节
- 004012DE . |33D8 xor ebx,eax
- 004012E0 . |49 dec ecx
注意在0x4011ec到向后偏移4 * 0x3E处不能有任何断点,不然某些地方数据会变成0xCC, 0xCC对应的汇编指令为int3,是专门用来调试的中断指令。当CPU执行到int3指令时,会触发异常代码为EXCEPTION_BREAKPOINT的异常,这样OD就能够接收到这个异常,然后进行相应的处理,这也是CC断点也叫int3断点的原因。
因此为了获取数据,我们直接从exe文件中读取
- const int count = 0x3E;
- int size = count * 4;
- FILE *f = fopen("Chafe.2.exe","rb");
- fseek(f,0x5ec,0);//0x4011ec在文件中的绝对偏移为0x5EC
- unsigned long *buffer = new unsigned long[0x3E];
- fread(buffer,4,count,f);
- fclose(f);
接下来,我们模拟这个异或运算
- unsigned long x = 0;
- for (int i=0;i<count;i++) {
- //对于倒数第2组和第三组的数据,是我们需要逆推的数据,这里先跳过
- //由于高位存取法
- //所以倒数第二组数据为0xD833ADXX
- //所以倒数第三组数据为0xXXXXXX04
- if (i == count - 3 || i == count - 2) continue;
- x ^= buffer[i];
- }
异或运算可以分字节运算,所以,为了求解XX,我们先把已知的字节做运算
- //x ^= 0xNNNNNN04
- x ^= 0x00000004;
- //x ^= 0xD833ADNN
- x ^= 0xD833AD00;
然后由于最终结果要等于0xAFFCCFFB,才能注册成功
因此我们再与0xAFFCCFFB做异或运算
- x ^= 0xAFFCCFFB;
现在,x的结果为0x5426eb58
对应起来,倒数第二组的末尾字节为0x58,
倒数第三组的前三个字节为0x54eb26
但是,由于4个数据一组,
- 004012BB xor dword ptr ds:[0x4012D9],eax ; [0x4012d9] ^= ans
- 004012C1 shr eax,0x10 ; ans = ans >> 0x10
- 004012C4 sub word ptr ds:[0x4012D9],ax ; [0x4012d9] -= ans 以上相当于修改了[0x4012d9]处的指令
程序是修改0x4012d9处的数据,4字节数据,即0x4012d9 ,0x4012da,0x4012db,0x4012dc处的数据,而根据逆推,它们分别存储着数据0xEB 0x26 0x54 0x58,由于高位存取法,该处数据实际为0x585426EB
即我们需要把运算结果的最后一字节放到最开头,我们使用位移实现
- //做位调换
- unsigned long t = x;
- x = (t & 0xFF) << 24;
- x = x + (t >> 0x8);
现在,我们得出,要想注册成功,0x4012D9的数据必须为0x585426EB
更为关键的是0x585426EB对应的指令正好有一条jmp 0x00401301,因此这样就能跳转到注册成功的地方了,这种动态改变指令的算法很巧妙,值得我们学习
我们来分析,程序是如何计算这里的数据的
- 004012A3 . A1 0B304000 mov eax,dword ptr ds:[0x40300B] ; unsigned long ans = 0x58455443
- 004012A8 . BB 6C314000 mov ebx,Chafe_2.0040316C ; for (int i=0; i<16; i++) {
- 004012AD > 0303 add eax,dword ptr ds:[ebx] ; ans += *((unsigned long *)p++);
- 004012AF . 43 inc ebx
- 004012B0 . 81FB 7C314000 cmp ebx,Chafe_2.0040317C
- 004012B6 .^ 75 F5 jnz XChafe_2.004012AD ; }
首先是对用户名进行计算,循环16次,每一次用户名字符串指针向后移到一个字节,并把当前指针指向的地址处的数据向后取出4个字节,转成数字,即向后取4个字符,获取ascii码,由高到低组合成4字节数据
接下来是关键的计算
- 004012B8 . 5B pop ebx ; 获取输入的serial,存入ebx
- 004012B9 . 03C3 add eax,ebx ; ans += serial
- 004012BB . 3105 D9124000 xor dword ptr ds:[0x4012D9],eax ; [0x4012d9] ^= ans
- 004012C1 . C1E8 10 shr eax,0x10 ; ans = ans >> 0x10
- 004012C4 . 66:2905 D9124>sub word ptr ds:[0x4012D9],ax ; [0x4012d9] -= ans 以上相当于修改了[0x4012d9]处的指令
这里就是修改0x4012D9处的数据了
首先写出运算过程
ans += serial;
unsigned long x = 0x584554; //0x4012D9的初始内容
x ^= ans;
ans = ans >> 0x10;
x -= ans & 0xFF;
x == 0x585426EB
由于异或运算可以分字节单独运算,于是我们写出方程
0x0058 ^ ans_h = 0x5854
ans_l ^ 0x4554 – ans_h = 0x26EB
解得ans_h = 0x580C
ans_l = 3BA3
所以 ans = 0x580C3BA3
- unsigned long fl = 0x00584554;
- unsigned long key = fl ^ x;
- t = (key >> 0x10) + (x & 0xFFFF);
- t ^= (fl & 0xFFFF);
- key = (key & 0xFFFF0000) + t;
即name的运算结果+serial必须为0x580C3BA3才能注册成功
所以serial = key – (name的运算结果)
综上,我们写出注册机
- #include <iostream>
- #include <cstdio>
- #include <cstring>
- using namespace std;
- int main() {
- const int count = 0x3E;
- int size = count * 4;
- FILE *f = fopen("Chafe.2.exe","rb");
- fseek(f,0x5ec,0);//0x4011ec在文件中的绝对偏移为0x5EC
- unsigned long *buffer = new unsigned long[0x3E];
- fread(buffer,4,count,f);
- fclose(f);
- unsigned long x = 0;
- for (int i=0;i<count;i++) {
- //对于倒数第2组和第三组的数据,是我们需要逆推的数据,这里先跳过
- //由于高位存取法
- //所以倒数第二组数据为0xD833ADXX
- //所以倒数第三组数据为0xXXXXXX04
- if (i == count - 3 || i == count - 2) continue;
- x ^= buffer[i];
- }
- //cout << "异或" << x << endl;
- x ^= 0xAFFCCFFB;
- //x ^= 0xNNNNNN04
- x ^= 0x00000004;
- //x ^= 0xD833ADNN
- x ^= 0xD833AD00;
- //做位调换
- unsigned long t = x;
- x = (t & 0xFF) << 24;
- x = x + (t >> 0x8);
- //0x585426EB
- cout << hex << "0x" << x << endl;
- unsigned long fl = 0x00584554;
- unsigned long key = fl ^ x;
- t = (key >> 0x10) + (x & 0xFFFF);
- t ^= (fl & 0xFFFF);
- key = (key & 0xFFFF0000) + t;
- char name[50];
- memset(name,0,50);
- cout << "请输入用户名:";
- cin >> name;
- int len = strlen(name);
- char *p = name;
- unsigned long ans = 0x58455443;
- for (int i=0; i<16; i++) {
- ans += *((unsigned long *)p++);
- }
- cout << dec << key - ans << endl;
- return 0;
- }
160个crackme 024详细题解(动态指令)相关推荐
- [反汇编练习] 160个CrackMe之024
[反汇编练习] 160个CrackMe之024. 本系列文章的目的是从一个没有任何经验的新手的角度(其实就是我自己),一步步尝试将160个CrackMe全部破解,如果可以,通过任何方式写出一个类似于注 ...
- 逆向破解之160个CrackMe —— 023-024
CrackMe -- 023 160 CrackMe 是比较适合新手学习逆向破解的CrackMe的一个集合一共160个待逆向破解的程序 CrackMe:它们都是一些公开给别人尝试破解的小程序,制作 c ...
- 视频+图文+注册+机源码 | 160个CrackMe深度解析合集 | 逆向破解入门
全部合集的获取请关注微信公众号:逆向驿站 回复:160 即可获得其余合集 以下是示例文章 160个CrackMe深度解析合集-001 提倡"刨根问底",拒绝"浅尝辄止&q ...
- Crackme006 - 全新160个CrackMe学习系列(图文|视频|注册机源码)
知乎:逆向驿站 原文链接 CrackMe006 | 难度适中适合练手 |160个CrackMe深度解析(图文+视频+注册机源码) crackme006,依然是delphi的,而且没壳子,条线比较清晰, ...
- [反汇编练习] 160个CrackMe之023
[反汇编练习] 160个CrackMe之023. 本系列文章的目的是从一个没有任何经验的新手的角度(其实就是我自己),一步步尝试将160个CrackMe全部破解,如果可以,通过任何方式写出一个类似于注 ...
- 【寒假每日一题】剪绳子(个人练习)详细题解+推导证明(第六天)
文章目录 前言 题目 详细题解 写法1 O(nlogn)O(nlogn)O(nlogn) 推导证明 举一反三 总结 前言 今天终于出核酸检测的结果,还好大家都没事,不然怕是要封城了!!! 今天还是寒假 ...
- 【寒假每日一题】分巧克力(个人练习)详细题解+推导证明(第八天)附带转载程序员壁纸
文章目录 前言 题目 详细题解 写法1 O(nlogn)O(nlogn)O(nlogn) 推导证明 举一反三 总结 前言 话说今天开始准备搞一个秋招的GitHub,算是复习一遍了. 今天还是寒假每日一 ...
- Unique Snowflakes 详细题解
Unique Snowflakes Emily the entrepreneur has a cool business idea: packaging and selling snowflakes. ...
- [反汇编练习] 160个CrackMe之021
[反汇编练习] 160个CrackMe之021. 本系列文章的目的是从一个没有任何经验的新手的角度(其实就是我自己),一步步尝试将160个CrackMe全部破解,如果可以,通过任何方式写出一个类似于注 ...
最新文章
- 还没用上 JDK 11吧,JDK 12 早期访问构建版使用
- ThinkPHP读取数据库数据到模板文件
- 发生系统错误 5 拒绝访问
- windows driver 分配内存
- linux跳出循环的三种方式,shell study-13day--跳出循环(break、continue)
- 全网最全!2021最新常用肿瘤生信数据库收藏级汇总!
- shell编程系列26--大型脚本工具开发实战
- MyBatis常用配置解析-mapper标签
- python ftplib_python:使用ftplib编写FTP客户端
- 虫食算(洛谷-P1092)
- 读书笔记——计算机网络CN
- 26.Linux/Unix 系统编程手册(上) -- 监控子进程
- 笔记本主板如何测试软件,笔记本硬件检测,小编教你笔记本怎么检测硬件
- c 语言 农历,C++算法系列之中国农历的算法
- SaaS服务应用集成和生态该何去何从
- 小红书一个月快速涨十万粉的秘籍
- Ubuntu打开WPS ofifice卡顿、无法进行编辑操作解决办法
- 为什么我电脑在线看黄色很慢_为什么我的电脑这么慢?
- Matlab篇----常用的回归分析Matlab命令(regress篇)
- acm刷题一些总结,至每一个努力拼搏的acmer