一、工具和调试环境
二、分析用户名/注册码的算法
2.1运行程序
作者意图是让我们将OK和Cancella两个按钮隐藏。其中OK按钮是不可点击的。需要填写Nome和Codice。
2.2查壳
用Die查壳,没有加壳,是Delphi程序,貌似是Delphi 4,记住版本后面会用到
006-01.png (30.73 KB, 下载次数: 0)
下载附件
2023-2-4 00:05 上传
2.3详细分析
通过005的分析,我们了解到了Delphi的改变控件有效状态的api为:SetVisible,更具体点为:TControl.SetVisible。那么下面就借助IDR,找到该API的地址
006-02.png (30.09 KB, 下载次数: 0)
下载附件
2023-2-4 00:05 上传
如上图,选择ClassViewer视图,然后在该视图空白处右键Search,然后如下图,在弹出的查找框中寻找SetVisible
006-03.png (15.4 KB, 下载次数: 0)
下载附件
2023-2-4 00:05 上传
找到如下地址
006-04.png (1.76 KB, 下载次数: 0)
下载附件
2023-2-4 00:05 上传
双击,会跳转到CodeViewer视图,显示该函数代码,可以看到TControl.SetVisible
006-05.png (15.04 KB, 下载次数: 0)
下载附件
2023-2-4 00:05 上传
双击进去,就可以得到TControl.SetVisible的地址了,如下图为:0x004231B0
006-06.png (20.01 KB, 下载次数: 0)
下载附件
2023-2-4 00:05 上传
但是如果x64dbg在该地址下断点,并不能找到关键地方。只有使用正确的方法使Cancella隐藏才是我们想要的触发,问题的关键是我们就是在寻找正确的方法。
那么怎么办呢?接下来就要请出我们的新伙伴IDA了。
使用IDA打开程序,然后打开签名视图,如下图或者直接使用快捷键Shift + F5
006-07.png (97.48 KB, 下载次数: 0)
下载附件
2023-2-4 00:05 上传
在签名视图空白处右键选择添加一个新的签名,或者使用快捷键Ins,然后选择Delphi 4(之前Die查到的版本)
006-08.png (26.94 KB, 下载次数: 0)
下载附件
2023-2-4 00:05 上传
在汇编视图中查找之前的函数(TControl.SetVisible)地址:0x004231B0
006-09.png (106.46 KB, 下载次数: 0)
下载附件
2023-2-4 00:05 上传
由于OK按钮目前是不可点击的,那么我们先看Cancella按钮的点击事件,双击过去。然后和IDR对照看,如有不懂,可以先看上一篇005
006-10.png (65.83 KB, 下载次数: 0)
下载附件
2023-2-4 00:05 上传
可以看出关键的地方在于0x442EE7处的call algorithm1(名字是我改的,算法1)函数调用,当该函数返回非0时(其实返回值不是0就是1),Cancella按钮会被隐藏且ok按钮变为可点击。如果返回为0时,Codice编辑框内容重新设置为0。
接下来就进入算法1函数中,看如何使其返回1。关键算法如下
006-11.png (79.58 KB, 下载次数: 0)
下载附件
2023-2-4 00:05 上传
Nome必须大于五位,且Codice和Nome满足以下关系就返回1,否则返回0。
Codice与Nome的关系:Nome的第5个字符的ASCII码值模7,再加上2。其结果的阶乘与Nome的每一个字符的ASCII码值相乘,所有乘积累加。新的结果减去0x7A69,就是Codice的内容。算法代码如下
char* GetSerial6_1(char* szNome)
{
static char szCodice[60] = {};
int nNomeLen = strlen(szNome);
if (nNomeLen
现在成功的隐藏了Cancella按钮,且ok按钮可点击了。接下来就是隐藏ok按钮了。还记得前面查找的OK按钮的点击处理函数中也调用了控件隐藏的函数。那么就看看ok按钮的点击处理函数
006-12.png (80.91 KB, 下载次数: 0)
下载附件
2023-2-4 00:05 上传
可以看出关键的地方在于0x442DC1处的call algorithm2(名字是我改的,算法2)函数调用,当该函数返回非0时(其实返回值不是0就是1),OK按钮会被隐藏。如果返回为0时,不做处理。和前面Cancella按钮点击处理函数差不多。不过该处理函数,会首先检测Cancella按钮是否被隐藏,如果没隐藏就会将Codice编辑框内容设置为0,然后返回。只有Cancella被隐藏了。才会执行前面关键代码。
接下来就进入算法2函数中,看如何使其返回1。关键算法如下
006-13.png (95.7 KB, 下载次数: 0)
下载附件
2023-2-4 00:05 上传
Codice必须大于五位,且Codice和Nome满足以下关系就返回1,否则返回0。
Codice与Nome的关系:Codice的数字转换为字符串,然后将该字符串的每个字符的ascii码值进行平方计算,计算结果再乘以该字符的字符串中的位数(从1开始)得到新的结果,再用新的结果模0x19,最后再加上0x41。得到的新的字符串和Nome字符串相同就返回1,否则返回0。
算法代码如下:
char* GetSerial6_2(char* szCodice)
{
static char szNome[60] = {};
int nCodiceLen = strlen(szCodice);
if (nCodiceLen