First CrackMe
2020-01-26 18:57:00 Author: mp.weixin.qq.com(查看原文) 阅读量:151 收藏

本文为看雪论坛优秀文章

看雪论坛作者ID:erfze

0x00 前言

前段时间看完王爽老师的《汇编语言》,受益匪浅。近日开始看《加密与解密》,学习逆向分析技术。

下文是对2.1.3中的CrackMe——TraceMe 动态分析技术调试分析过程及笔者个人思路的总结。

0x01 程序流程分析

运行TraceMe.exe,有两个输入框,分别是获取用户名与序列号:

 
那断点应该下在GetDlgItemTextAGetWindowText,Ctrl+G先搜索GetDlgItemTextA:
 
之后F2在此处下断点。F9开始执行该程序,输入用户名与序列号如下所示:
 
点击"Check",程序停在断点处,查看栈中内容:
 
GetDlgItemText函数原型如下:
UINT GetDlgItemText(
 
HWND hDlg,
 // handle of dialog box
 
int nIDDlgItem,
 // identifier of control
 
LPTSTR lpString,
 // address of buffer for text
 
int nMaxCount
 // maximum size of string
 
)
;
于数据面板中Ctrl+G,定位到0019F6B8处:
 
 
Ctrl+F9,F7返回应用程序领空:
 
 
可以看到绿色方框是应用程序调用GetDlgItemText函数,红色圆框中是笔者输入的用户名。
既然上一个GetDlgItemText函数是获取用户名,那么下一个GetDlgItemText函数应该是获取序列号,跟进call指令验证:
 
注意上图中的红色划线地址,推测其后保存着序列号,Ctrl+G定位到0019F708处后剩余操作同上。推测得以验证:
 
下面三条指令检查用户名是否为空:
 
 
如果未输入用户名,je指令跳转到TraceMe.00401248处执行,输出提示信息:
 
 
接下来的两条指令检查用户名是否少于5个字符,若少于5个字符,同上处理。
下图白色圆框中指令分别将用户名长度、保存用户名地址、保存序列号地址入栈:
 
接下来call调用函数的功能为计算正确序列号。
F8暂且不跟进,继续分析,je指令跳转到TraceMe.0040122E,而由TraceMe.0040122E起始的三条指令是为lstrcpyA()函数——将"序列号错误,再来一次!"复制到TraceMe.004054E4处传递参数:
 
0x02 爆破法
由上述程序流程分析可知,只要004011F5处的je指令不执行,即注册成功。在程序执行到004011F5处时,于寄存器窗口中找到Z标志位,Enter键将其值由1修改为0,je指令不再会执行:
 
 
修改完成后,F9,注册成功:
 
0x03 修改已输入序列号法
执行004011E5处的call指令。暂且不分析如何计算序列号。F8一直执行下去,到0040138A处停止:
 
推测1770是正确序列号,而lstrcmpA则是在比较输入序列号是否与正确序列号相符。那么修改内存中的"12345"为"1770":
 
修改完成后,F9,注册成功:
 
0x04 计算序列号算法分析
重新运行程序,执行004011E5处的call指令。下面是笔者一边分析算法,一边在记事本中的记录:
 
 
根据上图写出了计算序列号的简易C代码:
#include <stdio.h>
#include <string.h>
 
void main(void)
{
    unsigned char Name[6] = "ERFZE";
    unsigned char CA[8] = {
        0x0C,0x0A,0x13,0x09,0x0C,0x0B,0x0A,0x08
    };
    int i = 3;
    int x = 0, y = 0;
    int j = 0, k = 0;
    if (strlen(Name) > i)
    {
        for (; i <= strlen(Name); ++i,++y)
        {
            if (y > 7)
                y = 0;
            j = Name[i];
            k = CA[y];
            x = x + j * k;
 
        }
    }
    printf("%d", x);
}
CA中数据是由下面横线处指令确定:
 
运行结果如下,1770,与正确序列号相符:
 
 
unsigned char Name[6] = "ERFZE;改为unsigned char Name[10] = "ERFZE1999";,结果为4525。验证:
 
成功!
0x05 总结
虽然此次分析过程耗费一下午的时间,但从中收获乐趣,领略到逆向工程之魅力,心情或多或少有些激动,故发文为念。
- End -

看雪ID:erfze

https://bbs.pediy.com/user-817966.htm 

*本文由看雪论坛  erfze  原创,转载请注明来自看雪社区

推荐文章++++

实战栈溢出漏洞

栈溢出原理和利用

堆栈别乱用

栈溢出漏洞--GS和DEP

CVE-2019-0708 bluekeep 漏洞研究分析详细完整版

好书推荐

公众号ID:ikanxue
官方微博:看雪安全
商务合作:[email protected]
“阅读原文”一起来充电吧!

文章来源: http://mp.weixin.qq.com/s?__biz=MjM5NTc2MDYxMw==&amp;mid=2458303076&amp;idx=2&amp;sn=613a600b0b9619ab8047a41624ce6971&amp;chksm=b1818aee86f603f82829a6740c688e68c6c40ec1f537878837b7c27ef0219d3713089f0fe11c#rd
如有侵权请联系:admin#unsafe.sh