0x4012DD处开始向后的三条指令是关键

004012DD  lods dword ptr ds:[esi];  从[0x4011ec处开始,每次向后取4个字节(高端存取法),进行异或运算],直到执行到向后偏移4 * 0x3E个字节

  1. 004012DD   >  AD            lods dword ptr ds:[esi]                  ;  从[0x4011ec处开始,每次向后取4个字节(高端存取法),进行异或运算],直到执行到向后偏移4 * 0x3E个字节
  2. 004012DE   . |33D8          xor ebx,eax
  3. 004012E0   . |49            dec ecx

注意在0x4011ec到向后偏移4 * 0x3E处不能有任何断点,不然某些地方数据会变成0xCC, 0xCC对应的汇编指令为int3,是专门用来调试的中断指令。当CPU执行到int3指令时,会触发异常代码为EXCEPTION_BREAKPOINT的异常,这样OD就能够接收到这个异常,然后进行相应的处理,这也是CC断点也叫int3断点的原因。

因此为了获取数据,我们直接从exe文件中读取

  1. const int count = 0x3E;
  2. int size = count * 4;
  3. FILE *f = fopen("Chafe.2.exe","rb");
  4. fseek(f,0x5ec,0);//0x4011ec在文件中的绝对偏移为0x5EC
  5. unsigned long *buffer = new unsigned long[0x3E];
  6. fread(buffer,4,count,f);
  7. fclose(f);

接下来,我们模拟这个异或运算

  1. unsigned long x = 0;
  2. for (int i=0;i<count;i++) {
  3. //对于倒数第2组和第三组的数据,是我们需要逆推的数据,这里先跳过
  4. //由于高位存取法
  5. //所以倒数第二组数据为0xD833ADXX
  6. //所以倒数第三组数据为0xXXXXXX04
  7. if (i == count - 3 || i == count - 2) continue;
  8. x ^= buffer[i];
  9. }

异或运算可以分字节运算,所以,为了求解XX,我们先把已知的字节做运算

  1. //x ^= 0xNNNNNN04
  2. x ^= 0x00000004;
  3. //x ^= 0xD833ADNN
  4. x ^= 0xD833AD00;

然后由于最终结果要等于0xAFFCCFFB,才能注册成功

因此我们再与0xAFFCCFFB做异或运算

  1. x ^= 0xAFFCCFFB;

现在,x的结果为0x5426eb58

对应起来,倒数第二组的末尾字节为0x58,

倒数第三组的前三个字节为0x54eb26

但是,由于4个数据一组,

  1. 004012BB xor dword ptr ds:[0x4012D9],eax ;  [0x4012d9] ^= ans
  2. 004012C1 shr eax,0x10  ;  ans = ans >> 0x10
  3. 004012C4 sub word ptr ds:[0x4012D9],ax  ;  [0x4012d9] -= ans 以上相当于修改了[0x4012d9]处的指令

程序是修改0x4012d9处的数据,4字节数据,即0x4012d9 ,0x4012da,0x4012db,0x4012dc处的数据,而根据逆推,它们分别存储着数据0xEB 0x26 0x54 0x58,由于高位存取法,该处数据实际为0x585426EB

即我们需要把运算结果的最后一字节放到最开头,我们使用位移实现

  1. //做位调换
  2. unsigned long t = x;
  3. x = (t & 0xFF) << 24;
  4. x = x + (t >> 0x8);

现在,我们得出,要想注册成功,0x4012D9的数据必须为0x585426EB

更为关键的是0x585426EB对应的指令正好有一条jmp 0x00401301,因此这样就能跳转到注册成功的地方了,这种动态改变指令的算法很巧妙,值得我们学习

我们来分析,程序是如何计算这里的数据的

  1. 004012A3   .  A1 0B304000   mov eax,dword ptr ds:[0x40300B]          ;  unsigned long ans = 0x58455443
  2. 004012A8   .  BB 6C314000   mov ebx,Chafe_2.0040316C                 ;  for (int i=0; i<16; i++) {
  3. 004012AD   >  0303          add eax,dword ptr ds:[ebx]               ;     ans += *((unsigned long *)p++);
  4. 004012AF   .  43            inc ebx
  5. 004012B0   .  81FB 7C314000 cmp ebx,Chafe_2.0040317C
  6. 004012B6   .^ 75 F5         jnz XChafe_2.004012AD                    ;  }

首先是对用户名进行计算,循环16次,每一次用户名字符串指针向后移到一个字节,并把当前指针指向的地址处的数据向后取出4个字节,转成数字,即向后取4个字符,获取ascii码,由高到低组合成4字节数据

接下来是关键的计算

  1. 004012B8   .  5B            pop ebx                                  ;  获取输入的serial,存入ebx
  2. 004012B9   .  03C3          add eax,ebx                              ;  ans += serial
  3. 004012BB   .  3105 D9124000 xor dword ptr ds:[0x4012D9],eax          ;  [0x4012d9] ^= ans
  4. 004012C1   .  C1E8 10       shr eax,0x10                             ;  ans = ans >> 0x10
  5. 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

  1. unsigned long fl = 0x00584554;
  2. unsigned long key = fl ^ x;
  3. t = (key >> 0x10) + (x & 0xFFFF);
  4. t ^= (fl & 0xFFFF);
  5. key = (key & 0xFFFF0000) + t;

即name的运算结果+serial必须为0x580C3BA3才能注册成功

所以serial = key – (name的运算结果)

综上,我们写出注册机

  1. #include <iostream>
  2. #include <cstdio>
  3. #include <cstring>
  4. using namespace std;
  5. int main() {
  6. const int count = 0x3E;
  7. int size = count * 4;
  8. FILE *f = fopen("Chafe.2.exe","rb");
  9. fseek(f,0x5ec,0);//0x4011ec在文件中的绝对偏移为0x5EC
  10. unsigned long *buffer = new unsigned long[0x3E];
  11. fread(buffer,4,count,f);
  12. fclose(f);
  13. unsigned long x = 0;
  14. for (int i=0;i<count;i++) {
  15. //对于倒数第2组和第三组的数据,是我们需要逆推的数据,这里先跳过
  16. //由于高位存取法
  17. //所以倒数第二组数据为0xD833ADXX
  18. //所以倒数第三组数据为0xXXXXXX04
  19. if (i == count - 3 || i == count - 2) continue;
  20. x ^= buffer[i];
  21. }
  22. //cout << "异或" << x << endl;
  23. x ^= 0xAFFCCFFB;
  24. //x ^= 0xNNNNNN04
  25. x ^= 0x00000004;
  26. //x ^= 0xD833ADNN
  27. x ^= 0xD833AD00;
  28. //做位调换
  29. unsigned long t = x;
  30. x = (t & 0xFF) << 24;
  31. x = x + (t >> 0x8);
  32. //0x585426EB
  33. cout << hex << "0x" << x << endl;
  34. unsigned long fl = 0x00584554;
  35. unsigned long key = fl ^ x;
  36. t = (key >> 0x10) + (x & 0xFFFF);
  37. t ^= (fl & 0xFFFF);
  38. key = (key & 0xFFFF0000) + t;
  39. char name[50];
  40. memset(name,0,50);
  41. cout << "请输入用户名:";
  42. cin >> name;
  43. int len = strlen(name);
  44. char *p = name;
  45. unsigned long ans = 0x58455443;
  46. for (int i=0; i<16; i++) {
  47. ans += *((unsigned long *)p++);
  48. }
  49. cout << dec << key - ans << endl;
  50. return 0;
  51. }

160个crackme 024详细题解(动态指令)相关推荐

  1. [反汇编练习] 160个CrackMe之024

    [反汇编练习] 160个CrackMe之024. 本系列文章的目的是从一个没有任何经验的新手的角度(其实就是我自己),一步步尝试将160个CrackMe全部破解,如果可以,通过任何方式写出一个类似于注 ...

  2. 逆向破解之160个CrackMe —— 023-024

    CrackMe -- 023 160 CrackMe 是比较适合新手学习逆向破解的CrackMe的一个集合一共160个待逆向破解的程序 CrackMe:它们都是一些公开给别人尝试破解的小程序,制作 c ...

  3. 视频+图文+注册+机源码 | 160个CrackMe深度解析合集 | 逆向破解入门

    全部合集的获取请关注微信公众号:逆向驿站 回复:160 即可获得其余合集 以下是示例文章 160个CrackMe深度解析合集-001 提倡"刨根问底",拒绝"浅尝辄止&q ...

  4. Crackme006 - 全新160个CrackMe学习系列(图文|视频|注册机源码)

    知乎:逆向驿站 原文链接 CrackMe006 | 难度适中适合练手 |160个CrackMe深度解析(图文+视频+注册机源码) crackme006,依然是delphi的,而且没壳子,条线比较清晰, ...

  5. [反汇编练习] 160个CrackMe之023

    [反汇编练习] 160个CrackMe之023. 本系列文章的目的是从一个没有任何经验的新手的角度(其实就是我自己),一步步尝试将160个CrackMe全部破解,如果可以,通过任何方式写出一个类似于注 ...

  6. 【寒假每日一题】剪绳子(个人练习)详细题解+推导证明(第六天)

    文章目录 前言 题目 详细题解 写法1 O(nlogn)O(nlogn)O(nlogn) 推导证明 举一反三 总结 前言 今天终于出核酸检测的结果,还好大家都没事,不然怕是要封城了!!! 今天还是寒假 ...

  7. 【寒假每日一题】分巧克力(个人练习)详细题解+推导证明(第八天)附带转载程序员壁纸

    文章目录 前言 题目 详细题解 写法1 O(nlogn)O(nlogn)O(nlogn) 推导证明 举一反三 总结 前言 话说今天开始准备搞一个秋招的GitHub,算是复习一遍了. 今天还是寒假每日一 ...

  8. Unique Snowflakes 详细题解

    Unique Snowflakes Emily the entrepreneur has a cool business idea: packaging and selling snowflakes. ...

  9. [反汇编练习] 160个CrackMe之021

    [反汇编练习] 160个CrackMe之021. 本系列文章的目的是从一个没有任何经验的新手的角度(其实就是我自己),一步步尝试将160个CrackMe全部破解,如果可以,通过任何方式写出一个类似于注 ...

最新文章

  1. 还没用上 JDK 11吧,JDK 12 早期访问构建版使用
  2. ThinkPHP读取数据库数据到模板文件
  3. 发生系统错误 5 拒绝访问
  4. windows driver 分配内存
  5. linux跳出循环的三种方式,shell study-13day--跳出循环(break、continue)
  6. 全网最全!2021最新常用肿瘤生信数据库收藏级汇总!
  7. shell编程系列26--大型脚本工具开发实战
  8. MyBatis常用配置解析-mapper标签
  9. python ftplib_python:使用ftplib编写FTP客户端
  10. 虫食算(洛谷-P1092)
  11. 读书笔记——计算机网络CN
  12. 26.Linux/Unix 系统编程手册(上) -- 监控子进程
  13. 笔记本主板如何测试软件,笔记本硬件检测,小编教你笔记本怎么检测硬件
  14. c 语言 农历,C++算法系列之中国农历的算法
  15. SaaS服务应用集成和生态该何去何从
  16. 小红书一个月快速涨十万粉的秘籍
  17. Ubuntu打开WPS ofifice卡顿、无法进行编辑操作解决办法
  18. 为什么我电脑在线看黄色很慢_为什么我的电脑这么慢?
  19. Matlab篇----常用的回归分析Matlab命令(regress篇)
  20. acm刷题一些总结,至每一个努力拼搏的acmer

热门文章

  1. css 设置背景图片模糊效果
  2. Jump Game Jump Game II
  3. vue 数组中的元素 渲染到一行
  4. 君越更换初装变速箱油教程
  5. ESXi Arm Edition version 1.11更新,及安装Win11 Arm版
  6. 微信小程序 文字下标_微信小程序开发中,怎么给导航栏图标下面加上文本?...
  7. mysql可重复读概念_Mysql可重复读原理
  8. 初识vue-baidu-map
  9. 大佬们抖音带货流水都过亿 普通人有什么抖音变现的好方式
  10. addon游戏_SnowMobile Addon