当前位置: 首页 > news >正文

逆向入门(43)程序逆向篇-tsrh-crackme

没壳
在这里插入图片描述
不过需要先去个NAG
在这里插入图片描述
想着先进调试器吧,结果一进调试器就退出了,F8追了下
在这里插入图片描述
这里改一下jne,就变成了和直接运行一样的效果,先有NAG然后再正常启动
在这里插入图片描述
查了一个getlasterror,看来是不允许多开了
在这里插入图片描述
接下来找nag,直接f9运行到弹窗的时候,这个时候搜索字符串
在这里插入图片描述
有大量地方调用了403000这个内存地址,并且字符串显示的就是nag,接下来给这个内存地址下硬段,重新加载一下,再运行就断下来了
在这里插入图片描述
一直运行到ret以后跟下去
在这里插入图片描述
就定位到这里了,这里有个je判断跳一个MeseageBoxA,直接改了下eax的值,尝试一下
在这里插入图片描述
最终是正常绕过了,先patch一个
在这里插入图片描述
这样就搞定了去NAG,再接着找
在这里插入图片描述
看一手字符串
在这里插入图片描述
找到了对应位置
在这里插入图片描述
下个断,追一下,发现序列号前四个字节必须为tsrh
在这里插入图片描述
再往后追就看到了这么一段,在这里插入图片描述
这个函数其实做了一堆操作,看着不是很复杂,现在就是不想看了。往IDA里面丢吧
在这里插入图片描述
定位了这样一段,发现在前面还少分析了一个sub_4011f3函数
在这里插入图片描述
做了一个格式化,a1eax,从OD看了下,就是用户名的长度
在这里插入图片描述所以这一串最后得到了一个Stringtsrh-2008-字符串,前四个字符已经分析过了,接下来分析第二个条件
在这里插入图片描述
这一段也有点奇怪,伪代码显示没有参数,但是上一段又传了相加以后值进去,突然又多了个奇怪的v5出来
在这里插入图片描述
不过函数作用还是好理解的,也可以写出这一段的代码出来

    int len = strlen(username);// 1. 初始化序列号sprintf(serial, "tsrh-%d-", len + 2003);int current_length = strlen(serial);// 2. 处理用户名中的每个字符for (int i = 0; i < len; i++) {unsigned char c = username[i];unsigned char v4 = c + 12;int value = (2 * (int)v4 - 17 - current_length) ^ (int)v4;// 将值格式化为大写十六进制并追加char hex[9];sprintf(hex, "%X", value);strcat(serial, hex);current_length += strlen(hex);}int total_length = current_length;

运算结果相同
在这里插入图片描述
再接着往下看
在这里插入图片描述
这里的伪代码有点坑,对应的汇编在这
在这里插入图片描述
其实在第一次赋值以后,后面的内容都被截断了,所以40129C处的edx只有第一次是正常读到了值,后面读到的数值都是0,注意这里的0不是数字0,如果是数字0则会显示为48的,最后注册机显示如下:

#define _CRT_SECURE_NO_WARNINGS#include <stdio.h>
#include <string.h>
#include <ctype.h>void generate_serial(const char* username, char* serial) {int len = strlen(username);// 1. 初始化序列号sprintf(serial, "tsrh-%d-", len + 2003);int current_length = strlen(serial);// 2. 处理用户名中的每个字符for (int i = 0; i < len; i++) {unsigned char c = username[i];unsigned char v4 = c + 12;int value = (2 * (int)v4 - 17 - current_length) ^ (int)v4;// 将值格式化为大写十六进制并追加char hex[9];sprintf(hex, "%X", value);strcat(serial, hex);current_length += strlen(hex);}int esi = 1;bool first = true;int edx = 0;// 3. 调整序列号的特定位置(关键修正)while(true){printf("esi: %d\t", esi);if (!username[esi -1]) break;int eax = username[esi - 1] + 1;if (first) {edx = serial[esi + 0xB];first = false;}else {edx = NULL;}printf("edx:%d\t", edx);eax = eax ^ edx;while (eax < 0x41) eax += 0x8;while (eax > 90) eax -= 0x3;esi += 0x9;serial[esi] = eax;serial[esi + 1] = NULL;printf("%s,%d\n", serial, serial[esi + 1]);esi -= 0x8;if (esi == 0x10) break;}}int main() {char username[256];char serial[256];printf("用户名注册机 (长度>=5)\n");while (1) {printf("\n请输入用户名 (输入quit退出): ");fgets(username, sizeof(username), stdin);// 移除换行符username[strcspn(username, "\n")] = 0;if (strcmp(username, "quit") == 0) {break;}int len = strlen(username);if (len < 5) {printf("错误: 用户名长度必须至少5个字符\n");continue;}// 生成序列号generate_serial(username, serial);printf("生成的序列号: %s\n", serial);}return 0;
}

写是写得粗糙一点啦,其实还可以再优化,不过这样就够了
在这里插入图片描述
搞定,现在做一个题时间花得真久啊,利用好ida加快速度
在这里插入图片描述

http://www.lryc.cn/news/601823.html

相关文章:

  • C++ auto 类型推导
  • Android MQTT 长连接最佳实践技术分享
  • 5.4 ASPICE适配过程中的实施改进
  • 机械学习初识--什么是机械学习--机械学习有什么重要算法
  • Red靶机攻略
  • 字符串是数据结构还是数据类型?
  • Day44 Java数组08 冒泡排序
  • python中的容器与自定义容器
  • Pinocchio 结合 CasADi 进行 IK 逆运动学及 Mujoco 仿真
  • 09_opencv_遍历操作图像像素
  • CIFAR100数据集实测-基于 AlexNet模型的压缩/Bagging/Boosting 探索
  • 人社部物联网安装调试员的实训平台
  • 深度学习(鱼书)day04--手写数字识别项目实战
  • 网络协议:计算机世界的“交通规则“与“社交礼仪“
  • java--WebSocket简单介绍
  • Flutter开发实战之性能优化与调试
  • 深入解析MIPI C-PHY (四)C-PHY物理层对应的上层协议的深度解析
  • Pytest 参数化进阶:掌握 parametrize 的多种用法
  • maven <dependencyManagement>标签的作用
  • AutoLabelImg:高效的数据自动化标注工具和下载
  • IndexedDB全面掌握:从入门到Odoo OWL框架实战
  • mac系统彻底删除mysql并重装
  • [AI8051U入门第十步]W5500-客户端
  • 全方位评测:11款主流指标平台优劣分析
  • FreeRTOS—队列集
  • 【Web APIs】JavaScript 节点操作 ⑩ ( 节点操作综合案例 - 动态生成表格案例 )
  • add新增管理员功能、BaseController类的简介--------示例OJ
  • 链表算法综合——重排链表
  • Webpack 和 Vite 的关键区别
  • 01人工智能中优雅草商业实战项目视频字幕翻译以及声音转译之底层处理逻辑阐述-卓伊凡|莉莉