【吾爱】逆向实战crackme160学习记录(一)
前言
最近想拿吾爱上的crackme程序练练手,发现论坛上已经有pk8900总结好的160个crackme,非常方便,而且有很多厉害的前辈已经写好经验贴和方法了,我这里只是做一下自己练习的记录,欢迎讨论学习,感谢吾爱论坛的各位大神。
程序本身无病毒,杀毒报错可无视,如果实在担心也可也用虚拟机练习。
Acid burn
惯例查一下peid,之后打开
打开发现作者的留言
界面是仨按钮,一个账户密码验证,一个序列号验证。
先看账户密码验证吧。
x32dbg打开,输入1111111,1111111点击按钮
弹出按钮时候先不点击确认,回去让xdbg暂停一下,然后逐步走到用户代码段,
发现一堆111111111,这里已经是弹出出来的位置了,所以判断部分肯定在上面,往上翻翻ret在哪里,顺带还发现了登陆成功的信息:
这里的jne就是判断代码了,失败了会直接跳过下面登录成功的部分,所以直接nop掉判断就行
上面加个断点,下面判断部分nop掉,重新跑一次
就成功了。
接着看后面那个序列号验证
输入后发现弹出信息是Try again!
刚刚是调试找到判断的位置,这里换个方式,直接搜索字符串找一下位置
上面看一眼,看到了jne判断,上面下个断点,设置个nop,重新跑一下
这里就直接验证成功了,现在可以回头看一下注册机的逻辑。
这里输入111是账户,22222是密码,断点设置在刚刚找的判断代码的上面,发现这里eax里面是CW-4018-CRACKED
,ebx是我们输入的,然后基于这俩寄存器call了一个4039fc的函数,猜测就是判断密码是不是等于这个了,可以直接重新跑一下看一下,也可以去函数里面仔细看一下。
但是这个CW-4018-CRACKED在最开始查找字符串的时候并没有发现这个字符,大概率是程序运行过程中算出来的(或者换个账户重新试几次也能发现),所以可以找一下这个密码生产的算法。
重新输入aaaa作为账户,2是密码,发现密钥是CW-7954-CRACKED,搜一下cw出现的位置,发现一个可疑的位置,
这里cw
、-
、cracked
仨字符单独出现了,猜测是形成密码的函数
分析逻辑后发现:
获取输入字符并计算数值:
从内存地址 [ebx+1DC] 获取字符串,调用函数 41AA58 将其存储到局部变量 [ebp-10]。
提取该字符串的首字符 ASCII 值(如字符 '2' 对应 0x32)。
将该 ASCII 值与全局变量 [431750] 的值相乘,结果存回 [431750]。
再将 [431750] 的值翻倍(通过 add 自身),最终得到一个计算后的数值。
构造固定字符串部分:
将字符串常量 "CW" 和 "CRACKED" 分别复制到局部变量 [ebp-4] 和 [ebp-8]。
生成中间数字字符串:
调用函数 406718 将全局变量 [431750] 的数值转换为字符串(如 "7954"),存入 [ebp-18]。
拼接完整序列号:
通过多次 push 操作将 "CW"、"-"、转换后的数字 "7954"、"-" 和 "CRACKED" 拼接成最终字符串(如 "CW-7954-CRACKED"),存储到 [ebp-C]。
验证用户输入:
从 [ebx+1E0] 获取用户输入的字符串,调用函数 41AA58 存入 [ebp-10]。
调用函数 4039FC 比较生成的字符串 [ebp-C] 和用户输入是否一致,以此验证合法性。
这里ai分析的, 再翻译过来就是取第一个字母的ASNI的数字,如111111中第一个字符1对应数字0x31,然后用它乘以0x29,结果再自增一倍(即x2),将得到的数字转为10进制的字符串,在前加上”CW-”,后加上”-CRACKED”,就组成了用户名对应的注册码。
后面那个单独序列号验证的时候,可以简单的发现序列号“Hello Dude!”,直接明文出来了,没有什么加密的部分,所以不多写了。
Afkayas.1
点开发现是个登录界面
xdbg打开,搜索字符串,找到提示框的位置
往上翻一下找到跳转的代码,下个断点。
跟前面一样的思路,nop掉判断就成功了。
光绕过验证是没啥意义的,所以接着找一下加密的逻辑,但是这里生产密码的逻辑感觉不是很好找,根据天清地宁大神的文章,找到了加密的代码部分。
004023ED . FF90 A0000000 call dword ptr ds:[eax+0xA0] ; 这里获得了账户
004023F3 . 3BC7 cmp eax,edi
004023F5 . 7D 12 jge XAfkayas_.00402409
004023F7 . 68 A0000000 push 0xA0 ; 如果返回值小于0就走这里
004023FC . 68 5C1B4000 push Afkayas_.00401B5C
00402401 . 53 push ebx
00402402 . 50 push eax
00402403 . FF15 04414000 call dword ptr ds:[<&MSVBVM50.__vbaHresultChec>; msvbvm50.__vbaHresultCheckObj
00402409 > 8B95 50FFFFFF mov edx,dword ptr ss:[ebp-0xB0]
0040240F . 8B45 E4 mov eax,dword ptr ss:[ebp-0x1C] ; vbaLenBstr 获取 账户的长度,eax返回长度
00402412 . 50 push eax ; /String
00402413 . 8B1A mov ebx,dword ptr ds:[edx] ; |
00402415 . FF15 E4404000 call dword ptr ds:[<&MSVBVM50.__vbaLenBstr>] ; \__vbaLenBstr
0040241B . 8BF8 mov edi,eax ; 账户长度存储在EDI中
0040241D . 8B4D E8 mov ecx,dword ptr ss:[ebp-0x18]
00402420 . 69FF FB7C0100 imul edi,edi,0x17CFB ; 将账户长度 * 0x17CFB
00402426 . 51 push ecx ; /String
00402427 . 0F80 91020000 jo Afkayas_.004026BE ; |计算出来的结果>=0x80000000 就异常
0040242D . FF15 F8404000 call dword ptr ds:[<&MSVBVM50.#516>] ; \rtcAnsiValueBstr
00402433 . 0FBFD0 movsx edx,ax ; 返回账户的第一个字符代码
00402436 . 03FA add edi,edx ; 返回的字符代码与账户长度 * 0x17CFB相加
00402438 . 0F80 80020000 jo Afkayas_.004026BE ; 结果大于0x80000000就异常
0040243E . 57 push edi ; 这个函数是将I4转换成STR
0040243F . FF15 E0404000 call dword ptr ds:[<&MSVBVM50.__vbaStrI4>] ; msvbvm50.__vbaStrI4
00402445 . 8BD0 mov edx,eax ; 返回值为390240字符串
这段代码实现了一个用户名到序列号的转换算法,核心逻辑为:
序列号 = (用户名长度 × 97531) + 用户名首字符的ASCII值
最终将计算结果转换为字符串输出
自己写了一下注释如下:
004023ED call dword ptr ds:[eax+0xA0] ; 调用COM对象方法获取账户属性
004023F3 cmp eax,edi ; 比较返回值
004023F5 jge XAfkayas_.00402409 ; 返回值≥0则跳过错误处理
004023F7 push 0xA0 ; 错误处理路径开始
...
00402403 call dword ptr ds:[__vbaHresultCheckObj] ; VB错误检查[6,8](@ref)0040240F mov eax,dword ptr ss:[ebp-0x1C] ; 账户字符串指针
00402412 push eax ; 压入字符串参数
00402415 call dword ptr ds:[__vbaLenBstr] ; 调用VB长度函数[9](@ref)
0040241B mov edi,eax ; 长度结果存入EDI00402420 imul edi,edi,0x17CFB ; edi = edi * 0x17CFB (97531)
00402426 jo Afkayas_.004026BE ; 溢出检查
0040242D call dword ptr ds:[rtcAnsiValueBstr] ; 取首字符ASCII值
00402433 movsx edx,ax ; 符号扩展ASCII值到32位
00402436 add edi,edx ; edi = (长度*97531) + ASCII值
00402438 jo Afkayas_.004026BE ; 再次检查溢出0040243E push edi ; 压入计算结果
0040243F call dword ptr ds:[__vbaStrI4] ; 整数转字符串[6,8](@ref)
00402445 mov edx,eax ; 字符串句柄存入edx
AfKayAs.2
打开程序
跟前几个一样,xdbg打开,找到开始函数(vb弹窗函数是rtcMsgBox,可以找到这个),下断点,nop,
很简单的流程,但是接着要找到它的算法和逻辑。
往上翻,找到了push ebp;move ebp,esp;
像是程序入口,下断点开始逐步跑
后面的代码有点长,这里就不全部贴出来了。
跑到下面显示发现eax中出现了输入的账户,走到0x408225的时候突然eax变成了一个新的序列(根据输入的name算出来的),它上面有个函数被call了。
先下个断点,接着跑,发现eax在后面又发生了多次变化,最后又走到前面原本Nop的判断代码位置,这个再下个断点,俩断点之间的部分就是计算密码的部分。
中间计算逻辑注释一下:
004081F2 push eax ; 输入字符串地址 (如"3333")
004081F5 call __vbaLenBstr ; 计算字符串长度 (len=4)
004081FD mov ecx, [ebp-0x18] ; 获取字符串内容
00408200 imul edi, eax, 0x15B38 ; edi = 4 * 88888 = 355552
0040820D call rtcAnsiValueBstr ; 取首字符ASCII值 ('3'=51)
00408216 add edi, eax ; edi = 355552 + 51 = 355603
··············
0040821F call __vbaStrI4 ; 整数转字符串 -> "355603"
0040822A call __vbaStrMove ; 保存到[ebp-0x20]
···············
004083FB fmul qword [0x401010] ; 355605.0 * 3.0 = 1066815.0
00408404 fsub qword [0x401018] ; 1066815.0 - 2.0 = 1066813.0
···············
004084E5 fsub qword [0x401020] ; 1066813.0 - (-15.0) = 1066828.0
················
004085D2 call __vbaR8Str ; 用户输入序列号转浮点 S
004085E2 call __vbaR8Str ; 计算值转浮点 C=1066828.0
004085F1 fdivr ; 计算 C / S
0040861A fcomp qword [0x401028] ; 与密钥常量比较
···············
00408622 test ah, 0x40 ; 检查浮点比较结果是否相等
00408625 je 40862E ; 不相等则跳转
00408627 mov esi, 1 ; 验证成功标记
0040862E xor esi, esi ; 验证失败标记
·············
00408677 je 4086DB ; 关键跳转:若esi=0则跳失败处理
0040867F push "You Get It" ; 验证成功提示
逻辑大体是:
# 输入 "3333" 的运算过程:
T1 = len("3333") * 88888 + ord('3') = 355603
T2 = T1 + (10.0 / 5.0) = 355605.0
T3 = T2 * 3.0 = 1066815.0
T4 = T3 - 2.0 = 1066813.0
T5 = T4 - (-15.0) = 1066828.0
ajj.1
打开后发现没有按钮
peid查过没壳,拖进xdbg打开
搜索字符串之后发现有明文信息,找到了弹出的信息。
回到程序上,发现鼠标挪动到下面灰色方框的时候,会出现提示,说注册成功后会出现一张照片。
xdbg上往上翻翻,发现jne跳转(会先看到一个向上跳转的,然后再往上找),发现这个跳转阻止了程序进入注册成功的代码部分,所以nop掉
然后就可以发现照片出来了。
简要总结
一次性做了四个(其实是五个),第五个ajj.2有点复杂,没搞出来逻辑,等之后整理一下接着写,前面这几个都是比较老的cm了,逻辑和破解手法都比较简单,权当是复健一下动调和汇编了。之后再接着更新吧,再次感谢吾爱破解的大神们。
相关文章:

【吾爱】逆向实战crackme160学习记录(一)
前言 最近想拿吾爱上的crackme程序练练手,发现论坛上已经有pk8900总结好的160个crackme,非常方便,而且有很多厉害的前辈已经写好经验贴和方法了,我这里只是做一下自己练习的记录,欢迎讨论学习,感谢吾爱论坛…...

vue2 + webpack 老项目升级 node v22 + vite + vue2 实战全记录
前言 随着这些年前端技术的飞速发展,几年前的一些老项目在最新的环境下很可能会出现烂掉的情况。如果项目不需要升级,只需要把编译后的文件放在那里跑而不用管的话还好。但是,某一天产品跑过来给你讲要升级某一个功能,你不得不去…...
opengauss 数据库安装主备 非om方式
一. 准备两台服务器 192.168.141.130 --主 192.168.141.131 --备 1.关闭防火墙 systemctl stop firewalld systemctl disable firewalld 2.关闭 selinux 服务 setenforce 0 vim /etc/selinux/config #设置 SELINUXdisabled 3.关闭透明大页 echo never > /sys/kern…...

STM32的HAL编码流程总结(上部)
目录 一、GPIO二、中断系统三、USART串口通信四、I2C通信五、定时器 一、GPIO 1.选择调试类型 在SYS中Debug选择Serial Wire模式 2.选择时钟源 在RCC中将HSE和LSH都选择为内部晶振 3.时钟树配置 4.GPIO配置 在芯片图上选择开启的引脚和其功能 配置引脚的各自属性 5.工…...

深度学习|pytorch基本运算
【1】引言 pytorch是深度学习常用的包,顾名思义,就是python适用的torch包,在python里面使用时直接import torch就可以调用。 需要注意的是,pytorch包与电脑配置、python版本有很大关系,一定要仔细阅读安装要求、找到…...
(自用)Java学习-5.15(模糊搜索,收藏,购物车)
1. 模糊搜索商品功能 前端实现: 通过解析URL参数(如search联想)获取搜索关键字,发送AJAX GET请求到后端接口/product/searchGoodsMessage。 动态渲染搜索结果:若结果非空,循环遍历返回的商品数据ÿ…...

替代 WPS 的新思路?快速将 Word 转为图片 PDF
在这个数字化办公日益普及的时代,越来越多的人开始关注文档处理工具的功能与体验。当我们习惯了某些便捷操作时,却发现一些常用功能正逐渐变为付费项目——比如 WPS 中的一项实用功能也开始收费了。 这款工具最特别的地方在于,可以直接把 W…...

【K8S】K8S基础概念
一、 K8S组件 1.1 控制平面组件 kube-apiserver:公开 Kubernetes HTTP API 的核心组件服务器。 etcd:具备一致性和高可用性的键值存储,用于所有 API 服务器的数据存储。 kube-scheduler:查找尚未绑定到节点的 Pod,并将…...
FEMFAT许可分析的数据可视化方法
随着企业对FEMFAT软件使用的增加,如何有效地管理和分析许可数据成为了关键。数据可视化作为一种强大的工具,能够帮助企业直观地理解FEMFAT许可的使用情况,从而做出更明智的决策。本文将介绍FEMFAT许可分析的数据可视化方法,并探讨…...
打印机无法远程打印?可以本地打印,本地网络打印机设置给异地使用
很多小伙伴常有打印、远程打印的需求,特别是对于电商人、跨境电商、教师、产品经理、实验人员等群体来说掌握这项技能可谓是能够在很多场景下带来便捷,大幅提升做事效率!打印机是家庭和企业经常用到的设备,很多情况下会遇到本地可…...

包含Javascript的HTML静态页面调取本机摄像头
在实际业务开发中,需要在带有摄像头的工作机上拍摄施工现场工作过程的图片,然后上传到服务器备存。 这便需要编写可以运行在浏览器上的代码,并在代码中实现Javascript调取摄像头、截取帧保存为图片的功能。 为了使用户更快掌握JS调取摄像头…...

PCB设计实践(三十一)PCB设计中机械孔的合理设计与应用指南
一、机械孔的基本概念与分类 机械孔是PCB设计中用于实现机械固定、结构支撑、散热及电气连接的关键结构元件,其分类基于功能特性、制造工艺和应用场景的差异,主要分为以下几类: 1. 金属化机械孔 通过电镀工艺在孔内壁形成导电层,…...
deepseek问答记录:请讲解一下torch.full_like()
torch.full_like() 是 PyTorch 中的一个张量创建函数,用于创建一个与输入张量形状相同但所有元素值都填充为指定标量值的新张量。下面详细讲解其用法和特性: 1. 函数签名 torch.full_like(input, fill_value, *, dtypeNone, layoutNone, deviceNone, r…...

【Linux篇章】Linux 进程信号2:解锁系统高效运作的 “隐藏指令”,开启性能飞跃新征程(精讲捕捉信号及OS运行机制)
本篇文章将以一个小白视角,通俗易懂带你了解信号在产生,保存之后如何进行捕捉;以及在信号这个话题中;OS扮演的角色及背后是如何进行操作的;如何理解用户态内核态;还有一些可以引出的其他知识点;…...

多功能秒达开源工具箱源码|完全开源的中文工具箱
源码介绍 完全开源的中文工具箱永远的自由软件轻量级运行全平台支持(包括ARMv8)类似GPT的智能支持高效UI高度集成提供Docker映像和便携式版本支持桌面版开源插件库 下载地址 百度网盘下载 提取码:p9ck ▌本文由 6v6-博客网 整理分享 ▶ 更多…...
如何在腾讯云 OpenCloudOS 上安装 Docker 和 Docker Compose
从你提供的 /etc/os-release 文件内容来看,你的服务器运行的是 OpenCloudOS 9.2。这是一个基于 CentOS 和 RHEL 的开源操作系统,因此它属于 CentOS/RHEL 系列。 关键信息总结 操作系统名称:OpenCloudOS版本:9.2ID:op…...
清理skywalking历史索引
import requests from datetime import datetime, timedelta import os import re# 配置参数 ES_HOST os.getenv("ES_HOST", "http://192.168.0.250:9200") # ES地址 ES_USER os.getenv("ES_USER", "") # 用户…...

用nz-tabel写一个合并表格
用nz-tabel写一个合并表格 <nz-table #basicTable [nzData]"tableSearchStatus.dataList" nzBordered><thead><tr><th>班级</th><th>姓名</th><th>年龄</th><th>电话</th></tr></thead&…...
matlab计算转子系统的固有频率、振型、不平衡响应
可以计算转子系统的固有频率、振型、不平衡响应 MatrixRiccati/code/Dichotomy_1 (2).m , 2210 MatrixRiccati/code/Dichotomy_1.m , 2210 MatrixRiccati/code/RiccatiSY_1.m , 2756 MatrixRiccati/code/Trans1x (2).m , 451 MatrixRiccati/code/Trans1x.m , 451 MatrixRiccat…...

leetcode hot100刷题日记——29.合并两个有序链表
解答: 方法一:递归 递归的边界条件是啥呢? 递归别想那么多具体步骤,考虑大步骤,小的递归自己会去做的 class Solution { public:ListNode* mergeTwoLists(ListNode* list1, ListNode* list2) {//递归比较大小//先考虑…...
【机器人】具身导航 VLN 最新论文汇总 | Vision-and-Language Navigation
本文汇总了具身导航的论文,供大家参考学习,涵盖2025、2024、2023等 覆盖的会议和期刊:CVPR、IROS、ICRA、RSS、arXiv等等 论文和方法会持续更新的~ 一、🏠 中文标题版 2025 😆 [2025] WMNav:…...
Windows 安装 WSL2 并运行 Ubuntu 22.04 指南
Windows 安装 WSL2 并运行 Ubuntu 22.04 指南 本文为 Windows 10 和 Windows 11 用户提供从零开始搭建 WSL2 环境的详细指南,涵盖安装 Ubuntu 22.04、自定义存储位置、性能优化以及常见问题排查。无论你是开发者、运维工程师还是 Linux 爱好者,本文将助你…...
AI情感陪伴在医疗领域的核心应用潜力
一、精准情绪监测与干预 多模态情感识别系统 通过整合语音语调分析(降调与语速异常检测抑郁倾向)、微表情捕捉(面部肌肉运动追踪焦虑状态)、生理指标监测(心率变异幅度反映应激水平)等技术,构建…...

【计算机网络】第1章:概述—分组延时、丢失和吞吐量
目录 一、分组延时、丢失 1. 节点处理延时: 2. 排队延时: 3. 传输延时: 4. 传播延时: 5. 节点延时 6. 排队延时 7. 分组丢失 二、吞吐量 三、总结 (一)分组延时 1. 处理延时(Processing Delay) …...
Python Day38
Task: 1.Dataset类的__getitem__和__len__方法(本质是python的特殊方法) 2.Dataloader类 3.minist手写数据集的了解 1. Dataset 类的 __getitem__ 和 __len__ 方法 在 PyTorch (或类似深度学习框架) 中,Dataset 是一个抽象基类&a…...

DeepSeek R1 模型小版本升级,DeepSeek-R1-0528都更新了哪些新特性?
DeepSeek-R1‑0528 技术剖析:思维链再进化,推理性能飙升 目录 版本概览深度思考能力再升级基准测试成绩功能与体验更新API 变动与示例模型开源与下载结语 版本概览 DeepSeek 团队今日发布 DeepSeek‑R1‑0528 —— 基于 DeepSeek V3 Base(2…...
线路板厂家遇到的PCB元件放置的常见问题有哪些?
印刷电路板现在无处不在。尽管大多数人认为这是理所当然的,但工程师和设计师们充分意识到这些电路开发和生产背后的巨大努力。传统的PCB生产涉及复杂的机械和高昂的前期成本,因此必须将制造外包给专业工厂。 说到交货时间,你可能需要几周的时…...
【C/C++】无限长有序数组中查找特定元素
在无限长有序数组中查找特定元素,由于数组长度未知,需先定位搜索范围,再进行二分查找。以下是C实现: #include <iostream> #include <vector> #include <climits> using namespace std;// 假设数组访问函数&am…...

SQL正则表达式总结
这里写目录标题 一、元字符二、正则表达函数1、 regexp_like(x,pattern[,match_option])2、 regexp_instr(x,pattern[,start[,occurrence[,return_option[, match_option]]]]) 3、 REGEXP_SUBSTR(x,pattern[,start[,occurrence[, match_option]]]) 4、 REGEXP_REPLACE(x,patter…...

力扣经典算法篇-13-接雨水(较难,动态规划,加法转减法优化,双指针法)
1、题干 给定 n 个非负整数表示每个宽度为 1 的柱子的高度图,计算按此排列的柱子,下雨之后能接多少雨水。 示例 1: 输入:height [0,1,0,2,1,0,1,3,2,1,2,1] 输出:6 解释:上面是由数组 [0,1,0,2,1,0,1,3…...