最近弄了一只狗狗rockey6
非常行业的那种软件,几乎所有的程序功能都需要狗内的算法
甚至鼠标在软件操作区的点击坐标都是狗算出来的
经过朋友的指点,终于搞定了这个R6狗
现分享一下针对该狗的模拟技术
首先需要用木马DLL去读取软件和狗之间的数据,然后分析数据推出算法
因算法不是定数,所以在各位的修为了
下面的代码是针对软件对狗的查找,打开,读取硬件信息,读取狗内文件,运行狗内算法等功能的模拟先看rockey6的SDK
// 1. 查找计算机上连接的加密锁设备
TDIC_Find =function():integer;stdcall;
// 返回:
// 如果返回值小于 0,表示返回的是一个错误编码,具体含义请看下面的错误编码。
// 如果返回值为 0,表示没有任何读卡器设备存在。
// 如果返回值大于 0,返回的是读卡器的个数(注意: 通常即使用户不插入设备,
// 因为驱动程序一直存在,驱动程序会报告读卡器存在,这时候需要通过 DIC_Open
// 命令进一步确认是否真的有设备存在),我们假设在同一台计算机上面最多有 32
// 个读卡器设备。
// ===========================================================
由这个SDK函数得知TDIC_Find 返回大于0既是找到狗
本文以一只狗为例 就是返回1
模拟代码
EXTERN_C int WINAPI DIC_Find()
{
return(1);
}
这样我们的模拟DLL就可以欺骗程序的第一步:找狗
第二步
找到狗了当然要打开了,继续看,监听到的读狗数据
===DIC_Open===
hic = 00000000
DICFind = 00000000
看下SDK的定义
TDIC_Open =function(hic:Integer; reader_name:pchar):integer;stdcall;
// 输入:
// hic 设备的句柄
// 这是一个枚举值,是一个 0, 1, 2, ... Dic_Find() 返回值之内的值。
// 例如,Dic_Find() 返回 3,表示找到了 3 个读卡器设备,那么
// Dic_Open(0, reader_name) 表示的就是打开第 1 个找到的读卡器设备,
// 1 就表示第 2 个,依此类推。
// 如果 hic 的值为负值,Dic_Open 会尝试直接使用 reader_name 中的读卡
// 器名称去直接打开对应的读卡器。
// reader_name 读卡器的名称
// 这是一个输入输出值,当 hic 为负值的时候,用来输入读卡器的名称。
// 如果这个值不为空(NULL),那么在成功的打开读卡器后,会从这里返回读
// 卡器的名称。
// 另外,对于虚拟设备来说,这是要打开的路径文件名。
// 返回值:
// 大于等于0 表示成功,返回的就是 hic 的打开句柄
// 小于0 返回的是一个错误编码,具体含义请看下面的错误编码部分。
============================================
综上所知TDIC_Open返回0既是打开成功
那我们就模拟一下让软件认为已经把狗打开
EXTERN_C int WINAPI DIC_Open(int hic, char* reader_name)
{
return(0);
}
这样软件就认为打开狗了,如果弱智的软件作者只是判断是否有狗的话,到这里软件就免狗运行了
不过这个软件作者不是弱智
程序对狗的文件读取等操作进行分析和模拟功能:02000000 GET_CARD_INFO 查询加密狗信息 02000000是命令号
看下SDK描述
// 6. 加密锁操作命令函数
TDIC_Command =function(hic:integer; cmd:integer; cmddata:pchar):integer;stdcall;
// 输入:
// hic 设备的句柄
// cmd 具体的命令,具体见 后面的Command 定义
// cmddata 跟命令相关的数据
//==========================================================
GET_CARD_INFO便是在TDIC_Command中使用的命令 对应命令号0x02000000
返回狗信息存储在缓冲区
然后用TDIC_Get来读取缓冲区数据
SDK描述
// 7. 帮助用户从 DIC_Command 命令中的 data 中提取数据的函数
TDIC_Get =function(xdata:pchar; p1:integer; p2:integer; buffer:pchar):integer;stdcall;
// 输入:
// xdata 提取的目标缓冲区
// p1 模式/偏移,最高位为 1 表示这是模式操作,否则是用户自定义的偏移值
// p2 返回方式/尺寸,最高2位表示返回的方式,剩余的位表示操作的尺寸
// buffer 提取出数据的字符型缓冲区
// =======================================
函数返回0为成功执行,其他数值为错误码
下面开始模拟这一步操作,返回狗正确的ATR信息
char _ATR[]={0x45,0x43,............................,0x00};
先定义一下指针数据,这里的数据是你通过监听得到的数据,数据不同定义不同,这里简化了
定义好数据之后返回给程序
if(cmd==0x2000000)memcpy(cmddata,_ATR,sizeof(_ATR));
这就简单了,判断命令号是否是GET_CARD_INFO 以便返回先前定义的数据
数据写进cmddata缓冲区 大小为定义数据的大小
对狗的打开操作之后就会查询狗的厂商等信息来判断狗是否是本狗(也就是ATR信息)
到了这里就可以欺骗程序查询狗的ATR信息了
下面会对程序查询狗的硬件信息进行分析和模拟上面介绍了软件查询加密狗信息的应对处理
通过上面的介绍可以写程序返回正确的加密狗信息给程序
这样程序就得到了合法的狗信息 下面将介绍针对软件读取狗内文件的应对处理
对于智能狗而言都有一定大小的存储区,一般1K-512K不等
Rockey6的存储区大小是512K
存储区可以存放一般二进制文件和可执行文件
文件属性的不同,加密狗对其的保护力度不同
如普通文件,软件可对其读取,写入操作
可执行文件,不可读,不可写,只能运行
普通文件一般用于存放软件的LICENSE文件,可执行文件就是狗内的算法文件,程序调用算法传入一定参数,狗返回一定结果
用于软件的某种功能操作
下面先看软件对狗内普通文件的处理
由SDK得知,读取狗内文件的函数原型
// 6. 加密锁操作命令函数
function DIC_Command( hic:int; cmd:int; cmddata: pchar):int;
// 输入:
// hic 设备的句柄
// cmd 具体的命令
// cmddata 跟命令相关的数据
其实这个事通用函数,操作功能取决于CMD的定义
读取文件的功能是:READ_FILE :Integer = $0000b000;
cmddata将会传入将要读取的文件ID,一般为前4个字节,对应狗内相应ID的文件
通过监视CHECK_SUPER_PASS功能可以得到狗密码,有了密码就可以自己把狗内文件导出来分析
这里略过了
有了文件之后呢,就可以开始写程序进行模拟返回文件信息了
程序在调用DIC_COMMAND功能和Read_file命令之后调用DIC_Set命令取出由上一命令成功执行后写入缓冲区的数据
根据这一点我们就可以自己把需要的文件数据写进缓冲区,也就是cmddata
如果程序读狗的文件ID有多个,还需要判断一下读的是哪个ID的文件
判断略过
下面是将文件数据写进缓冲区
先定义文件数据
file1101[长度]={0x00,0x11,......0xNN}定义区分文件ID的长度和实际数据
memcpy(cmddata+2,file1101+d[0],d[1]); 将需要的文件数据写入内存 后面的参数是实际情况而定
判断好文件ID返回数据之后,这样狗内文件数据就完美返回给狗了
如果程序没有用到算法程序那么恭喜你,这个狗已经完美模拟了
如果不幸你在监视狗的时候看到了03000000命令
那就是说狗内有算法了
至于狗内算法的分析不在本文探讨范围之内,狗内算法一般靠调试程序猜出算法
一般没有很复杂的算法,狗内算法一般都是浮点运算
分析出算法之后就可以自己写算法函数到模拟DLL里面
然后判断03000000命令调用返回即可
算法分析正确就可以硬复制Rockey6了,剩下的事情参考飞天网站上的资料即可完成
好了,到此 揭开加密狗模拟的神秘面纱之rockey6 全文完
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课