(2023.8.28)Hi铁布衫-CM Ver 0.001 - Cracked-writeup
Hi铁布衫-CM Ver 0.001 WriteUp
本文作者:XDbgPYG(小吧唧)
发布时间:2023年8月28日
内容概要:Hi铁布衫-CM Ver 0.001 WriteUp
收集信息
有一段时间没写过代码了,源码早就忘光了,今天碰巧有时间,好好测试一下我的网络验证的强度。
PE 信息如下:
vc 8.0 above 是个很新的程序~

内存布局如下:
嗯,很帅。

字符串如下:
有一堆的 PYG 水印。(除了水印已无太多信息)

readMe:
- readMe 有提到程序是由
hi-Easyx编写的。 - readMe 有提到程序由
登录窗口=>功能窗口组成。 - readMe 有提到这是一个
网络验证 CrackME。
所以我们可以尝试通过 CreateWindow系列函数 和 hi-Easyx相关字符串 进行定位 hi-Easyx 创建窗口的 Call 或 Sig(特征码)。
所以我们可以尝试通过 send、recv 等网络函数进行回溯=>分析验证的加密算法、解密算法等对于网络验证来说很重要的东西。
调试
创建窗口函数的分析-失败
可以看到有个 Error creating window: 字符串,转到目标地址,进行控制流分析。

可以看出程序是通过 CreateWindowExW 创建的窗口,而在其地址上方有个 可能的关键信息:wchar_t *HiEasyX::g_lpszClassName

我习惯先对字符串进行搜索引用(函数的调用可能会有很多),经过引用搜索,发现俩个字符串都位于该函数中。
void __cdecl HiEasyX::InitWindow(...)
对这个函数进行引用分析,发现只有 1 个引用。
0x0007FF7169B8D4A lea rcx, ds:[0x0x0007FF7169B7C80]
继续回溯,看样子想通过 className 进行定位 创建窗口 函数的想法是泡汤了。
0x0007FF7169B8FA2 call HWND__* __cdecl HiEasyX::initgraph_win32(...)
累了,不跟踪了。
通过 send recv 定位 1 个关键点范围
如果程序的客户端验证没有使用到线程池技术(不考虑有保护的情况)的话,那么有趣的事情就会这样发生。
有线程池情况的 处理包流程图:没学原理,到时候给验证添加线程池后再来补好了。
无线程池(有循环)获取一段数据的情况:

无线程池(无循环)获取一段数据的情况:

现在搜索一下 send 的引用,发现许多调用,看样子程序是把 发包函数 给 inline 了。

现在搜索一下 recv 的引用,看样子程序是把 收包函数 给 inline 了。

不知道 收包函数、发包函数 是否有多种加密解密情况,如果有的话,就不逆向算法了。

有趣的地方来了,我似乎没有对缓冲区进行清理导致直接获得了一个信息 web|notice 。很明显,程序这是在获取公告。
既然如此,就碰碰运气,对所有 recv 函数的引用地址下断点,重启下程序,进行简单的测试。

获取公告
0x0007FF7169C1A2B | FF15 5FFB0600 | call qword ptr ds:[<&recv>] |
循环获取公告(看控制流有多次调用、应该是循环获取公告)
0x0007FF7169C1D13 | FF15 77F80600 | call qword ptr ds:[<&recv>] |
登录
login|pygChina|UserPassWord|superPassWord
0x0007FF7169C4C9F | FF15 EBC80600 | call qword ptr ds:[<&recv>] |
定位到 获取登录返回值 的地址了,对 recv 的 buffer 下硬件访问断点。
看样子程序是调用了 rc4 加密。
0x0007FF7169B9BF0 CryptoLibEx::RC4::Encode(unsigned char *, unsigned char *, int)
0x0007FF7169B9CCA | 48:8B05 575D0C00 | mov rax,qword ptr ds:[<class CryptoLibEx::RC4 rc4>] | 0x0007FF716A7FA28:&"1234567890..."
0x0007FF7169B9D8D | 41:3203 | xor al,byte ptr ds:[r11] |
看样子程序是调用了 rc4 解密。
0x0007FF7169B9DE0 public: class CryptoLib::stringx __cdecl CryptoLibEx::RC4::Decode(unsigned char *, int)
既然现在找到了验证的包加密、解密算法。那山寨一个出来就不是难题了。
对 CryptoLibEx::RC4::Decode 搜索引用下断点,并进行跟踪调试。
登录返回值 L"bad..."。
0x0007FF7169C4CB3 | E8 2851FFFF | call <hi铁布衫-cm ver 0.001.public: class CryptoLib::stringx __cdecl |
将 L"bad..." 转换为 "bad...",即 unicode2Asccii()。
0x0007FF7169C4CC4 | E8 A7B10x000 | call <hi铁布衫-cm ver 0.001.public: class std::basic_string<char, struc |
对字符串下硬件访问断点。可以看到如下关键信息。
0x0007FF7169C4DF7 | 4C:8B8424 00070000 | mov r8,qword ptr ss:[rsp + 0x700] |
0x0007FF7169C4DFF | 4C:3BC0 | cmp r8,rax |
0x0007FF7169C4E02 | 0F85 051D0000 | jne hi铁布衫-cm ver 0.001.7FF7169C6B0D |
0x0007FF7169C4E08 | 48:8D9424 8C030000 | lea rdx,qword ptr ss:[rsp + 0x38C] |
0x0007FF7169C4E10 | E8 6BFE0300 | call <hi铁布衫-cm ver 0.001.memcmp> |
0x0007FF7169C4E15 | 85C0 | test eax,eax |
0x0007FF7169C4E17 | 0F85 F01C0000 | jne hi铁布衫-cm ver 0.001.7FF7169C6B0D |
0x0007FF7169C4E1D | C605 32AA0B00 01 | mov byte ptr ds:[<bool Logined>],0x1 | TestClient.cpp:486
0x0007FF7169C4E2F | 48:8D0D 62710B00 | lea rcx,qword ptr ds:[<class HiEasyX::Window methodWindow>] | rcx:"bad..."
ps: 值得注意的是,我看到了创建窗口的符号,这说明第一个思路是对的,可能是因为操作失误了,导致没有追根到底。
看样子我们找到关键的控制流跳转了(jcc)。简单的修改下标志位和跳转,测试下:程序爆破成功(MayBeSuccess?)。
ps:在看完源代码后,发现这个窗口标题是服务器已经发现在破解情况下触发的;同时这个窗口是暗装窗口。

搜索下创建窗口的引用,有趣的来了,有三个窗口。这说明有 1 个是假的功能窗口。

现在,我不想继续跟下去了,要是分析了半天暗装算法,就得不偿失了。
通过 Server 端,拿出来一个 测试账号 玩玩。
uN: pygxDbg
pW: oKVxXlGKtomCUCML
正版卡记录控制流与数据
0x0007FF7169C4E17 jump
successResult: "bad2..."
0x0007FF7169C6B74 noJump
0x0007FF7169C6B7A | C605 D58C0B00 01 | mov byte ptr ds:[<bool Logined>],0x1 | TestClient.cpp:532
有趣的是,程序依旧被检测到调试了。(我也不知道为啥,也许是登录超时了)

嗯,下次要快点,重来一次,记录好数据。(控制流已经不用管了)
0x0007FF7169C6E36 | 48:8BC8 | mov rcx,rax | rax:&L"PVZ Plug Ver 4.7\n"
0x0007FF7169C7090 | 48:8BC8 | mov rcx,rax | rax:L"46"
0x0007FF7169C72AE | 48:8BC8 | mov rcx,rax | rax:L"47"
0x0007FF7169C74C7 | 48:8BC8 | mov rcx,rax | rax:L"48"
0x0007FF7169C76AF | 48:8BC8 | mov rcx,rax | rax:L"50"
0x0007FF7169C7907 | 48:8BC8 | mov rcx,rax | rax:&L"MayBeSuccess?\n"
对比下窗口,看样子有 4 个数据是与本地算法有关的。(另外俩个分别是标题、标签的字符串,我记得是没有 数据复用 的情况的)
ps:通过看源代码,最后一个数据是通过这 4 个 整数 算出来的。如果有 1 个补错了,服务端就会检测到并警告。

刚才的是数据是窗口加载时要用到的(这又是一个不错的暗装点\检测点),还有一个 Check 会用到数据。
看样子是从 Server 上获取用户名,如果和本地用户名不匹配,估计又要扰一会头了。
0x0007FF7169C22BD | 48:8BC8 | mov rcx,rax | rax:&L"chinapyg"
好了,控制流和数据都拿到了,该逆向本地验证了。(笑
网络验证与本地验证相结合
在搞定网络验证后,还需要填写一个本地算法生成出来的 Serial 方可通过。
网络传输过来的数据还是服务于本地的软件,目前我的项目是这样,所以补了几百或几千个数据,收包解密后的数据依旧是加密的。
本地验证部分参考的这个 Web Site
山寨 Hi-铁布衫
我们拿到了正版数据,最简单的 Patch 方式,直接把记录到的 地址 给 Hook 掉,把数据补进去。不过为了贴近一丢丢的实际情况(这个方法太容易被对抗了),用下面的方法。
在知道了加密与解密的算法,在程序是单线程发包的情况下,可以尝试 Hook Rc4.EnCode 与 Rc4.DeCode 把正版数据补回去。
分析 Hook 点
这台电脑没有环境,改天让周清帮忙装下~
所以,山寨就略了。
逆向 Rc4.Encode 与 Rc4.DeCode
照着源码跟就好了~ (奇怪,我似乎找不到 CryptoLibEx)坏了,坏了,改日再补。
// main
rc4.SetNormalKey();
__forceinline int Send(std::string _Str)
{
UCHAR* en = new UCHAR[_Str.size()]{ 0 };
rc4.Encode((UCHAR*)_Str.c_str(), en, _Str.size());
return send(connection, (char*)en, _Str.size(), 0);
delete en;
}
__forceinline std::string Recv()
{
auto _buffer = new char[1024]{ 0 };
int _bufferSize = 1024;
int size = recv(connection, _buffer, _bufferSize, 0);
auto r = rc4.Decode((UCHAR*)_buffer, size).GetString();
delete _buffer;
return r;
}
一不小心,发现没搭建好环境,尴尬。不过相信身为 Reverser/Ctfer/Geeker 不会因为这点困难而停止逆向的脚步~
总结、反思与铁布衫0.2
铁布衫 0.001 还是太脆弱了。
- 可以尝试通过 recv 的调用频率、引用定位关键点
- 网络验证无正版 KEY 不可破同时难以分析
- 发包与收包的缓冲区应该及时清除
- 有用的符号太多=>想办法把程序的符号信息全部去除或修改
- 验证协议过于简单=>使用成体系的协议算法=>逆向或收集其他网络验证协议以加强自身
- 创建窗口搜索引用失败的原因(还未尝试重现)
- 暗装可以设计多个
- 可以尝试实现动态心跳包来检测调试
- 实现多线程与服务端通信
链接
(2023.7.24)软件加密与解密-2-1-程序分析方法[XDbg].md
(2023.8.28)Hi铁布衫-CM Ver 0.001 - Cracked-writeup的更多相关文章
- Attribute meta-data#android.support.VERSION@value value=(25.4.0) from AndroidManifest.xml:25:13-35 is also present at AndroidManifest.xml:28:13-35 value=(26.1.0).
Android Studio 编译项目的时候报错 Merging Errors: Error: Attribute meta-data#android.support.VERSION@value va ...
- Netsparker破解版5.3 Netsparker Enterprise 5.3.0.24388[cracked]
Netsparker破解版5.3 Netsparker Enterprise 5.3.0.24388[cracked]该版本更新时间为2019年7月8日下载地址:1 https://www.dr-fa ...
- Visual Studio Code预览版Ver 0.3.0试用体验
当你开始阅读这篇文章时,请先不要把Visual Studio Code和.net.Windows联想到一起,因为VS Code是一个跨平台,支持30多种语言的开箱代码编辑器.不管你是.Net.Java ...
- 多校5-MZL's Border 分类: 比赛 2015-08-05 21:28 7人阅读 评论(0) 收藏
MZL's Border Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others) Total ...
- Borg Maze 分类: POJ 2015-07-27 15:28 5人阅读 评论(0) 收藏
Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 9971 Accepted: 3347 Description The B ...
- Counterfeit Dollar 分类: POJ 2015-06-12 15:28 19人阅读 评论(0) 收藏
Counterfeit Dollar Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 41559 Accepted: 13 ...
- Segment Tree with Lazy 分类: ACM TYPE 2014-08-29 11:28 134人阅读 评论(0) 收藏
#include<stdio.h> #include<string.h> #include<algorithm> using namespace std; stru ...
- Hdu 1507 Uncle Tom's Inherited Land* 分类: Brush Mode 2014-07-30 09:28 112人阅读 评论(0) 收藏
Uncle Tom's Inherited Land* Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (J ...
- nginx 安装手记 分类: Nginx 服务器搭建 2015-07-14 14:28 15人阅读 评论(0) 收藏
Nginx需要依赖下面3个包 gzip 模块需要 zlib 库 ( 下载: http://www.zlib.net/ ) zlib-1.2.8.tar.gz rewrite 模块需要 pcre 库 ( ...
- opnet的sink模块学习 分类: opnet 2014-05-18 10:28 161人阅读 评论(0) 收藏
Sink模块的状态机很简单,只有INIT和DISCARD两个,非强制状态只有DISCARD用于包的销毁.Sink模块的作用就是销毁从输入流接收到的包,并且返回关于包的一系列统计量. Init的入口代码 ...
随机推荐
- 前端开发如何更好的避免样式冲突?级联层(CSS@layer)
作者:vivo 互联网前端团队 - Zhang Jiqi 本文主要讲述了CSS中的级联层(CSS@layer),讨论了级联以及级联层的创建.嵌套.排序和浏览器支持情况.级联层可以用于避免样式冲突,提高 ...
- htop 和 bashtop 的一些不足
htop 和 bashtop 都是 Linux 资源监视器中非常好用的工具,尤其对于展示当前 Linux 操作系统的处理器.内存.硬盘.网络和进程等各项资源的使用情况与状态.但它们都有一个问题,就是当 ...
- 从 Blast2GO 本地化聊一聊 Linux 下 MySQL 的源码安装
Blast2GO 是一个基于序列相似性搜索的 GO 注释和功能分析工具,它可以直接统计分析基因功能信息,并可视化 GO 有向非循环图(DAG)上的相关功能特征,分析 BLAST.GO-mapping. ...
- web_枚举
网页枚举 使用工具 gobuster,Nikto,WPScan Gobuster 安装:sudo apt install gobuster 有用的全局标志 -t 线程 并发线程数(默认10) -v 冗 ...
- 驱动开发:内核LoadLibrary实现DLL注入
远程线程注入是最常用的一种注入技术,在应用层注入是通过CreateRemoteThread这个函数实现的,该函数通过创建线程并调用 LoadLibrary 动态载入指定的DLL来实现注入,而在内核层同 ...
- Supervisor启动并管理Celery相关进程
Supervisor启动并管理Celery相关进程 关于celery在运行过程中, 默认情况下是无法在关机以后自动重启的.所以我们一般开发中会使用supervisor进程监控来对celery程序进行运 ...
- prometheus安装和使用记录
Getting started | Prometheus Configuration | Prometheus Download | Prometheus Download Grafana | Gra ...
- 【whale-starry-stl】01天 list学习笔记
一.知识点 1. std::bidirectional_iterator_tag std::bidirectional_iterator_tag 是 C++ 标准库中定义的一个迭代器类型标签,用于标识 ...
- 一文了解Go语言的匿名函数
1. 引言 无论是在Go语言还是其他编程语言中,匿名函数都扮演着重要的角色.在本文中,我们将详细介绍Go语言中匿名函数的概念和使用方法,同时也提供一些考虑因素,从而帮助在匿名函数和命名函数间做出选择. ...
- AR增强现实 之Metaio For Unity 开发 之HelloWorld
开发工具 unity 4.6 MetaioSDK 6.1 代码编辑器 VS 2013 上图不会配置的请自行百度 1.创建项目并且导入Metaio SDk 开发包 2.导入后目录图 ...