程序打开后有 有一个帮助按钮 有一个不可用的ok键 和一个清除键,点击完帮助按钮 会弹4个弹窗 大概意思就是说:输入正确的用户名和密码 让 ok键 从禁用状态变成可用状态 然后在让清除键和ok键隐藏把下面的logo完整显示出来。
image.png (45.99 KB, 下载次数: 2)
下载附件
2024-11-30 15:56 上传
查壳后是无壳 Delphi编写。
image.png (116.04 KB, 下载次数: 2)
下载附件
2024-11-30 15:59 上传
Delphi编写编写的程序 直接查一下都有哪些事件。
image.png (164.25 KB, 下载次数: 2)
下载附件
2024-11-30 16:02 上传
这个程序就不进行爆破了 我们来直接研究它的算法, 首先 OK按钮点不了 应该是在输入用户名和密码的时候 会进行验证 验证正确了OK按钮才能恢复正常。按照这个思路 先把 用户名和密码输入事件下上断点。
image.png (33.92 KB, 下载次数: 0)
下载附件
2024-11-30 16:06 上传
然后输入用户名和密码。 先看用户名输入事件的代码, 单步跟一下。
image.png (275.2 KB, 下载次数: 0)
下载附件
2024-11-30 16:08 上传
跟到这个位置发现 如果eax+0x47的地址值不为0 就不会跳转,通过我直接改标志位 让这个跳转不成立 进去后发下下面的CALL是恢复OK按钮使用。 也就是说 当 eax+0x47不等于0 就能恢复 OK按钮的使用。
image.png (83.49 KB, 下载次数: 0)
下载附件
2024-11-30 16:10 上传
继续往下跟会发现还有一个跳转 如果跳转不成立 那么0k按钮也会变成可用状态, 这个跳转上面有一个关键CALL决定这个跳转是成立还是不成立,这个CALL在上面 是一些取出用户名 密码 作为参数给这个关键CALL进行传参。 由此就可以看出这个关键CALL可能是算法CALL。
image.png (101.42 KB, 下载次数: 0)
下载附件
2024-11-30 16:15 上传
跟进这个关键CALL 我们发现 这有一个跳转,如果输入的用户名长度小于等于5 那就直接出CALL了 。
image.png (179.51 KB, 下载次数: 0)
下载附件
2024-11-30 16:22 上传
当用户名大于5个的时候 可以顺利走到这个位置 看到了一些计算操作 。
image.png (73.05 KB, 下载次数: 0)
下载附件
2024-11-30 16:26 上传
[Asm] 纯文本查看 复制代码00442A93 | 8B4D FC | mov ecx,dword ptr ss:[ebp-4] | 取用户名给 ECX
00442A96 | 0FB64C01 FF | movzx ecx,byte ptr ds:[ecx+eax-1] | 把用户名第一个字节给ecx 每次循环都递增一个
00442A9B | 8B75 FC | mov esi,dword ptr ss:[ebp-4] | 取出用户名在给ESi
00442A9E | 0FB63406 | movzx esi,byte ptr ds:[esi+eax] | 把用户名第二个字节给ESI 每次循环都递增一个
00442AA2 | 0FAFCE | imul ecx,esi | ecx*esi
00442AA5 | 0FAFC8 | imul ecx,eax | ecx*eax
00442AA8 | 03D9 | add ebx,ecx | 最后算出来的结果 累加到ebx中
00442AAA | 40 | inc eax |
00442AAB | 4A | dec edx |
00442AAC | 75 E5 | jne along3x.1.442A93 |
通过这算法 我们可以看出 就是把用户名的第一个字节乘以第二个字节 再乘以当前循环的次数
正向代码:
[C++] 纯文本查看 复制代码 int ecx = 0;
int esi = 0;
int ebx = str.length();
for (int i = 0; i
看下图 执行了一个 把密码转为16进制 再用之前算出来的值减去密码的16进制 如果等于0x29a;那么相当于OK按钮就可以恢复使用了。 这也就是说 我输入的用户名算出来的值减去0x29A 在转成十进制那就是对应的密码。
image.png (117.02 KB, 下载次数: 0)
下载附件
2024-11-30 16:41 上传
编写一下对应算法 在程序上面输入验证了 算法是正确的 OK键现在可以正常使用了。
image.png (116.98 KB, 下载次数: 0)
下载附件
2024-11-30 16:47 上传
现在我们在来点一下 OK按钮 发现 清空了密码输入内容(由于清空密码输入框改变了内容 导致密码不正确ok按钮又变回不可用状态)
image.png (18.15 KB, 下载次数: 0)
下载附件
2024-11-30 16:49 上传
目前我们知道了 刚才的算法只是能让OK恢复使用 并不能把它隐藏掉。 那我们继续去进入OK的点击事件里面找一下有没有对应的隐藏算法。
进入到OK按钮的点击事件当中 我们发现了有一个关键的比较 cmp byte ptr ds:[eax+47],1 如果等于0x1 那么直接就把OK按钮禁用了 然后一个跳转就出CALL了。 所以这个 eax+0x47是关键 必须要让他不等于0x1才可以。按钮点击事件 现在就不用看了 因为eax+0x47等于0x1那它就直接出CALL了 所以我们在看最后一个清除按钮的事件。
image.png (108.26 KB, 下载次数: 0)
下载附件
2024-11-30 19:00 上传
断下来后我们发现,有跳转 上面的CALL 里面传入了用户名进行运算决定跳转还是不跳转 推测也是一个算法 具体干什么用的还不清楚 跟进去看一下。
image.png (220.12 KB, 下载次数: 0)
下载附件
2024-11-30 17:00 上传
跟进去之后确实看到有一些计算的操作 就不一行一行注释了 大概的操作流程就是 先判断密码长度是否小于等于0x5 如果小于跳出 然后 取用户名的第四个字节和 0x7进行取模运算 得出来的结果在加0x2,计算出来的结果 经过下面的CALL进行阶乘。阶乘出来的结果 保存在esi中备用,然后 走到下面的循环 循环就是 用esi的值以此和用户名的每一个字符相乘的和值保存到ebx当中。 然后ebx的值减去密码的16进制 等于0x7A69 就算成立。
image.png (189.75 KB, 下载次数: 0)
下载附件
2024-11-30 17:04 上传
我们现在来写一下这个算法 输入到程序上面点击清除 结果发现清除按钮已经消失了 并且OK按钮变成了可用状态。
image.png (207.33 KB, 下载次数: 0)
下载附件
2024-11-30 19:01 上传
现在就差一个OK按钮的隐藏就可以了, 这个时候我们继续去看OK按钮事件,发现 eax+0x47已经可以正常跳转了。
继续往下走 我们发现有一个关键跳转, 我更改标志位让他不进行跳转发现 这个跳转里面的CALL就是隐藏ok按钮的CALL ,那这个跳转上面的CALL 就是关键的算法CALL了。
image.png (98.64 KB, 下载次数: 0)
下载附件
2024-11-30 19:03 上传
进入到这个CALL里面 第一个跳转是看密码的长度是否小于5 如果小于 直接跳转出CALL
image.png (209.17 KB, 下载次数: 0)
下载附件
2024-11-30 19:07 上传
继续往下走 又看到了一些计算的操作 不每行都注释了 具体的逻辑就是 传入的密码多长就对应循环几次, 每一次 取最后一个字节 依次递减 取出来的值做一个乘以自己本身(就是做平方) 然后得到的值在乘以密码的长度减去当前循环的次数 得出来的值在和0x19进行取模运算然后在加0x41。得到的值对应ascll的字符。
image.png (67.78 KB, 下载次数: 0)
下载附件
2024-11-30 19:08 上传
继续往下走有一个CALL传递了计算后的参数和用户名。 之前的运算相当于 把密码对应的算出来一个用户名, 通过这个用户名和你输入的用户名做对比 如果一致那么 ok按钮就会隐藏 。
image.png (72.37 KB, 下载次数: 0)
下载附件
2024-11-30 19:14 上传
继续写隐藏ok按钮算法。 算法写出来后 ok按钮也顺利隐藏 至此 整个分析过程就结束了。
image.png (128.95 KB, 下载次数: 0)
下载附件
2024-11-30 19:17 上传
注册机:
[C++] 纯文本查看 复制代码#include
#include
using namespace std;
//可用ok按钮算法
void passWord1(string str)
{
int ecx = 0;
int esi = 0;
int ebx = str.length();
for (int i = 0; i