吾爱汇编

 找回密码
 立即注册

QQ登录

绑定QQ避免忘记帐号

查看: 28721|回复: 62

[原创逆向图文] 加密狗逆向之硬件复制和软件模拟_Rockey4ND

  [复制链接]
codelive 发表于 2014-10-19 00:49 | 显示全部楼层 |阅读模式

加密狗逆向之硬件复制和软件模拟_Rockey4ND
CodeLive @ 2014-10-18

收到风声说再不发原创的帖子就要被清理了,赶紧熬夜写一篇,呵呵~~

本文主要通过对Rockey4ND狗的分析来说明如何逆向加密狗,包括硬件复制和软件模拟,不谈爆破方法。

首先说明可以硬件复制或者软件模拟的狗要具备下面几种条件:

1.有真狗的运行环境,没狗逆向一般只能爆破;
2.硬件复制要知道狗的用户密码和开发密码,软件模拟密码可以不需要;
3.程序只从狗中读取或写入数据;
4.如果程序在狗中写入了算法函数,这个一般会比较难,但如果逆向出函数算法,也可以模拟;

下面就介绍一款使用了Rockey4ND狗的软件的分析过程,软件名字当然不会说了。
Rockey4ND是无驱HID类型狗,这种截获数据方法有多种,可以用USBTrace,hid.dll替换,HOOK CreateFileA等方法, 但直接有效的方法是直接替换狗的API调用.


1.首先下载一份Rockey4ND的开发SDK,通过查看文件很容易知道,这个狗只有一个API,API定义为:
WORD WINAPI Rockey(WORD function, WORD* handle, DWORD* lp1,  DWORD* lp2, WORD* p1, WORD* p2, WORD* p3, WORD* p4, BYTE* buffer);
主要功能定义(Rockey4_ND_32.h文件):
  1. #define  RY_FIND                1       // Find Dongle
  2. #define  RY_FIND_NEXT           2       // Find Next Dongle
  3. #define  RY_OPEN                3       // Open Dongle
  4. #define  RY_CLOSE               4       // Close Dongle
  5. #define  RY_READ                5       // Read Dongle
  6. #define  RY_WRITE               6       // Write Dongle
  7. #define  RY_RANDOM              7       // Generate Random Number
  8. #define  RY_SEED                8       // Generate Seed Code
  9. #define  RY_WRITE_USERID        9       // Write User ID
  10. #define  RY_READ_USERID         10      // Read User ID
  11. #define  RY_SET_MOUDLE          11      // Set Module
  12. #define  RY_CHECK_MOUDLE        12      // Check Module
  13. #define  RY_WRITE_ARITHMETIC    13      // Write Arithmetic
  14. #define  RY_CALCULATE1          14      // Calculate 1
  15. #define  RY_CALCULATE2          15      // Calculate 2
  16. #define  RY_CALCULATE3          16      // Calculate 3
  17. #define  RY_DECREASE            17      // Decrease Module Unit
  18. #define  RY_CALLNET             18      // NetRockey4ND arithmetic


  19. (1) Find Dongle
  20.     Input:
  21.     function = 1
  22.     *p1 = pass1
  23.     *p2 = pass2
  24.     *p3 = pass3
  25.     *p4 = pass4
  26.     Return:
  27.     *lp1 = Rockey4ND HID
  28.     return 0 = Success, else is error code

  29. (2) Find Next Dongle
  30.     Input:
  31.     function = 2
  32.     *p1 = pass1
  33.     *p2 = pass2
  34.     *p3 = pass3
  35.     *p4 = pass4
  36.     Return:
  37.     *lp1 = Rockey4ND HID
  38.     return 0 = Success, else is error code

  39. (3) Open Dongle
  40.     Input:
  41.     function = 3
  42.     *p1 = pass1
  43.     *p2 = pass2
  44.     *p3 = pass3
  45.     *p4 = pass4
  46.     *lp1 = Rockey4ND HID
  47.     Return:
  48.     *handle = Opened dongle handle
  49.     return 0 = Success, else is error code

  50. (4) Close Dongle
  51.     Input:
  52.     function = 4
  53.     *handle = dongle handle
  54.     Return:
  55.     return 0 = Success, else is error code

  56. (5) Read Dongle
  57.     Input:
  58.     function = 5
  59.     *handle = dongle handle
  60.     *p1 = pos
  61.     *p2 = length
  62.     buffer = pointer of buffer
  63.     Return:
  64.     Fill buffer with read contents
  65.     return 0 = Success, else is error code

  66. (6) Write Dongle
  67.     Input:
  68.     function = 6
  69.     *handle = dongle handle
  70.     *p1 = pos
  71.     *p2 = length
  72.     buffer = pointer of buffer
  73.     Return:
  74.     return 0 = Success, else is error code

  75. (7) Generate Random Number
  76.     Input:
  77.     function = 7
  78.     *handle = dongle handle
  79.     Return:
  80.     *p1 = random number
  81.     return 0 = Success, else is error code

  82. (8) Generate Seed Code
  83.     Input:
  84.     function = 8
  85.     *handle = dongle handle
  86.     *lp2 = seed code
  87.     Return:
  88.     *p1 = seed return code 1
  89.     *p2 = seed return code 2
  90.     *p3 = seed return code 3
  91.     *p4 = seed return code 4
  92.     return 0 = Success, else is error code

  93. (9) Write User ID

  94.     Input:
  95.     function = 9
  96.     *handle = dongle handle
  97.     *lp1 = User ID
  98.     Return:
  99.     return 0 = Success, else is error code

  100. (10) Read User ID
  101.      Input:
  102.      function = 10
  103.      *handle = dongle handle
  104.      Return:
  105.      *lp1 = User ID
  106.      return 0 = Success, else is error code

  107. (11) Set Module

  108.      Input:
  109.      function = 11
  110.      *handle = dongle handle
  111.      *p1 = module number
  112.      *p2 = module content
  113.      *p3 = set whether allow decrease (1 = allow, 0 = no allow)
  114.      Return:
  115.      return 0 = Success, else is error code

  116. (12) Check Module
  117.      Input:
  118.      function = 12
  119.      *handle = dongle handle
  120.      *p1 = module number
  121.      Return:
  122.      *p2 = 1 means the module is valid, 0 means the module is invalid
  123.      *p3 = 1 means the module can't decrease, 0 means the module can decrease
  124.      return 0 = Success, else is error code

  125. (13) Write Arithmetic

  126.      Input:
  127.      function = 13
  128.      *handle = dongle handle
  129.      *p1 = pos
  130.      buffer = arithmetic instruction string
  131.      Return:
  132.      return 0 = Success, else is error code

  133. (14) Calculate 1 (Hide Unit Init Content = HID high 16bit, HID low 16bit, module content, random number)
  134.      Input:
  135.      function = 14
  136.      *handle = dongle handle
  137.      *lp1 = calculate begin pos
  138.      *lp2 = module number
  139.      *p1 = input value 1
  140.      *p2 = input value 2
  141.      *p3 = input value 3
  142.      *p4 = input value 4
  143.      Return:
  144.      *p1 = return code 1
  145.      *p2 = return code 2
  146.      *p3 = return code 3
  147.      *p4 = return code 4
  148.      return 0 = Success, else is error code

  149. (15) Calculate 2 (Hide Unit Init Content = seed return code 1, seed return code 2, seed return code 3, seed return code 4)
  150.      Input:
  151.      function = 15
  152.      *handle = dongle handle
  153.      *lp1 = calculate begin pos
  154.      *lp2 = seed code
  155.      *p1 = input value 1
  156.      *p2 = input value 2
  157.      *p3 = input value 3
  158.      *p4 = input value 4
  159.      Return:
  160.      *p1 = return code 1
  161.      *p2 = return code 2
  162.      *p3 = return code 3
  163.      *p4 = return code 4
  164.      return 0 = Success, else is error code

  165. (16) Calculate 3 (Hide Unit Init Content = module content, module+1 content, module+2 content, module+3 content)
  166.      Input:
  167.      function = 16
  168.      *handle = dongle handle
  169.      *lp1 = calculate begin pos
  170.      *lp2 = module begin pos
  171.      *p1 = input value 1
  172.      *p2 = input value 2
  173.      *p3 = input value 3
  174.      *p4 = input value 4
  175.      Return:
  176.      *p1 = return code 1
  177.      *p2 = return code 2
  178.      *p3 = return code 3
  179.      *p4 = return code 4
  180.      return 0 = Success, else is error code

  181. (17) Decrease Module Unit
  182.      Input:
  183.      function = 17
  184.      *handle = dongle handle
  185.      *p1 = module number
  186.      Return:
  187.      return 0 = Success, else is error code
复制代码
    最好先看看SDK中自带的示例程序,对狗的API一般是如何调用的。


2.分析软件,发现软件是直接使用DLL来对狗进行访问的,Rockey4ND的DLL名字是: Rockey4ND.dll,对这种直接使用DLL来调用的程序真是无语,连分析API函数特征都不需要了(如果是静态库方式调用就需要分析API地址)。


3.建立一个DLL工程,实现和狗API一样的函数: Rockey,定义如下:

  1. WORD WINAPI Rockey(WORD function, WORD* handle, DWORD* lp1,  DWORD* lp2, WORD* p1, WORD* p2, WORD* p3, WORD* p4, BYTE* buffer)
  2. {
  3.     WORD ret = ERR_SUCCESS;
  4.     // ......后面再说
  5.     return ret;
  6. }

  7. Makefile内容:

  8. LIBRARY ApiRockey4
  9. EXPORTS
  10.     Rockey @ 1

  11. 这样DLL就导出了和加密狗一样的API, 同时也要把自己的DLL改为Rockey4ND.dll,原Rockey4ND.dll就要换一个名字,比如改为:Rockey4ND.org.dll
复制代码


4.获取原狗DLL的API地址:
  1.     1)定义API函数,然后声明一个全局变量:

  2.         typedef WORD (WINAPI * api_Rockey)(WORD function, WORD* handle, DWORD* lp1,  DWORD* lp2,
  3.         WORD* p1, WORD* p2, WORD* p3, WORD* p4, BYTE* buffer);

  4.         // 这个就是为了保存原API的地址
  5.         api_Rockey g_Rockey = NULL;

  6.     2)获取原API地址:
  7.         HMODULE hModule = LoadLibraryW(L"Rockey4ND.org.dll");
  8.         if(hModule != NULL)
  9.         {
  10.             // 获取原API函数地址
  11.             g_Rockey = (api_Rockey)GetProcAddress(hModule, "Rockey");
  12.         }
  13.     在DLL加载的时候运行上面的代码
  14.     BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
  15.     {
  16.         switch (ul_reason_for_call)
  17.         {
  18.         case DLL_PROCESS_ATTACH:
  19.             {
  20.                 // 加载原DLL模块
  21.                 HMODULE hModule = LoadLibraryW(L"Rockey4ND.org.dll");
  22.                 if(hModule != NULL)
  23.                 {
  24.                     // 获取原API函数地址
  25.                     g_Rockey = (api_Rockey)GetProcAddress(hModule, "Rockey");
  26.                 }
  27.             }
  28.             break ;
  29.         case DLL_THREAD_ATTACH:
  30.         case DLL_THREAD_DETACH:
  31.         case DLL_PROCESS_DETACH:
  32.             {
  33.             }
  34.             break;
  35.         }
  36.         return TRUE;
  37.     }
复制代码


5.数据截获
  1.     WORD WINAPI Rockey(WORD function, WORD* handle, DWORD* lp1,  DWORD* lp2, WORD* p1, WORD* p2, WORD* p3, WORD* p4, BYTE* buffer)
  2.     {
  3.         WORD ret = ERR_SUCCESS;

  4.         // 这里是执行原API调用
  5.         ret = g_Rockey(function, handle, lp1, lp2, p1, p2, p3, p4, buffer);

  6.         // 根据定义,我把对狗进行数据读写的数据转化为字符串,便于记录
  7.         string strBuffer;
  8.         if((function == RY_READ) || (function == RY_WRITE))
  9.         {
  10.             if((p2 != NULL) && ((*p2) > 0))
  11.             {
  12.                 // 数据转换成文本
  13.                 strBuffer = data2HexString((const char *)buffer, (*p2));
  14.             }
  15.         }

  16.         // 格式所有参数
  17.         string str = formatString("Rockey(function(%d), handle(0x%04X), "
  18.             "lp1(0x%08X), lp2(0x%08X), "
  19.             "0x%04X, 0x%04X, 0x%04X, 0x%04X, "
  20.             "%s), ret = %d\r\n",
  21.             (int)(function), (handle != NULL) ? (int)(*handle) : 0,
  22.             (lp1 != NULL) ? (int)(*lp1) : 0, (lp2 != NULL) ? (int)(*lp2) : 0,
  23.             (p1 != NULL) ? (int)(*p1) : 0, (p2 != NULL) ? (int)(*p2) : 0,
  24.             (p3 != NULL) ? (int)(*p3) : 0, (p4 != NULL) ? (int)(*p4) : 0,
  25.             strBuffer.c_str(), (int)(ret));

  26.         //打印输出或者记录到文件
  27.         logOutput(str);

  28.         return ret;
  29.     }
复制代码


6.把自己的DLL替换后,运行程序,如果程序没问题,所有数据都会被记录:
    // 查找狗,ret = 0,表示找到狗,成功.
    Rockey(function(1), handle(0x0000), lp1(0x66666666), lp2(0x77777777), 0x1111, 0x2222, 0x3333, 0x4444, ), ret = 0
    // 打开狗,ret = 0,打开成功
    Rockey(function(3), handle(0x0000), lp1(0x66666666), lp2(0x77777777), 0x1111, 0x2222, 0x3333, 0x4444, ), ret = 0
    // 查找下一个,ret = 17, 没有找到更多的狗,失败
    Rockey(function(2), handle(0x0000), lp1(0x66666666), lp2(0x77777777), 0x1111, 0x2222, 0x3333, 0x4444, ), ret = 17
    // 从位置0x0008,读取0x0010长度的数据,读取到的内容是:A869BA3E70096F3C0D578FE34E5F8FD4
    Rockey(function(5), handle(0x0000), lp1(0x66666666), lp2(0x77777777), 0x0008, 0x0010, 0x3333, 0x4444, A869BA3E70096F3C0D578FE34E5F8FD4), ret = 0

    通过参数定义可以知道,开发商ID是0x66666666, 加密狗的4个密码也获取到了,基本密码为:0x1111, 0x2222,高级密码:0x3333, 0x4444 (我截获的密码当然不是这个啦)。
    然后多运行几次程序,看看每次读取的数据是否都是相同的,如果每次都一样,那真的是要恭喜你了,但如果有调用狗内函数的功能,那就复杂了,这里暂时不讨论算法这种情况。

7.硬件复制方案:
    1)既然4个密码都有了,最完美的方案就是硬件复制,从TB上面买空狗;
    2)用官方工具可以直接复制,Rockey4ND_Editor.exe,这个在Rockey4ND的SDK中有,就是使用上面稍有复杂;
    3)如果觉得工具有点麻烦的话,可以写一个程序,先从原狗中把数据都读出来,然后再把数据写入到新狗中;

8.软件模拟方案:
    就是把我们之前记录数据的部分反过来,下面是大概的代码,一些代码不具体解释了:

  1.     WORD WINAPI Rockey(WORD function, WORD* handle, DWORD* lp1,  DWORD* lp2, WORD* p1, WORD* p2, WORD* p3, WORD* p4, BYTE* buffer)
  2.     {
  3.         WORD ret = ERR_SUCCESS;
  4.         *handle = NULL;
  5.         switch(function)
  6.         {
  7.         case RY_FIND:
  8.             {  
  9.                 // 返回开发商ID
  10.                 *lp1 = 0x66666666;
  11.             }
  12.             break ;
  13.         case RY_OPEN:
  14.             {
  15.                 // 返回句柄
  16.                 *handle = 0x8888;
  17.             }
  18.             break ;
  19.         case RY_FIND_NEXT:
  20.             {
  21.                 // 没有更多加密狗
  22.                 ret = ERR_NOMORE;
  23.             }
  24.             break ;
  25.         case RY_READ:
  26.             {
  27.                 // gRockey4Data是原狗的所有数据
  28.                 memcpy(buffer, gRockey4Data+(*p1), (*p2));
  29.             }
  30.             break ;
  31.         case RY_WRITE:
  32.             {
  33.                 memcpy(gRockey4Data+(*p1), buffer, (*p2));
  34.             }
  35.             break ;
  36.         case RY_RANDOM:
  37.             {
  38.                 *p1 = (WORD)(rand()%(0x10000));
  39.             }
  40.             break ;
  41.         case RY_SEED:
  42.             {
  43.                 *p1 = (WORD)(rand()%(0x10000));
  44.                 *p2 = (WORD)(rand()%(0x10000));
  45.                 *p3 = (WORD)(rand()%(0x10000));
  46.                 *p4 = (WORD)(rand()%(0x10000));
  47.             }
  48.             break ;
  49.         }
  50.     }
复制代码


硬件复制和软件模拟不需要对原程序进行逆向,软件升级一般也不需要做任何改动,算是完美的方案,本文是通过Rockey4ND来举例说明加密狗的完美分析方法,同样适用于其他加密狗,只要程序仅对狗的数据进行访问,狗内没有算法函数的情况就可以用差不多的方法实现。

本文完,因为时间关系,没有仔细校验错误,有不对的地方还希望大家指正, 谢谢大家。







评分

参与人数 49威望 +2 HB +88 THX +30 收起 理由
开天辟地 + 1
花盗睡鼠 + 2 + 1 [吾爱汇编论坛52HB.COM]-学破解防破解,知进攻懂防守!
29590 + 1
怀东 + 2 + 1
24567 + 1
Jawon + 2
一路走来不容易 + 1
Soul1999 + 1
仙仙猫 + 1
渴望宁静 + 1
消逝的过去 + 1
zyyujq + 1
l278785481 + 1
temp + 1 + 1
Pythonic_vi + 1
hbyaojing + 1 [吾爱汇编论坛52HB.COM]-感谢楼主热心分享,小小评分不成敬意!
SmallEXpel + 1
落雪玉 + 1 [吾爱汇编论坛52HB.COM]-感谢楼主热心分享,小小评分不成敬意!
流言飞鱼 + 1
jaunic + 1
hnymsh + 1
lies + 1
cd37ycs + 1 + 1 [快捷评语]--吃水不忘打井人,给个评分懂感恩!
HAINING + 2 + 1
zhm + 1 + 1 [快捷评语]--积极评分,从我做起。感谢分享!
曰可 + 1 [快捷评语] - 评分=感恩!简单却充满爱!感谢您的作品!
pinsy + 1 分享精神,是最值得尊敬的!苦苦求了你几千年啊
ddx123 + 1 分享精神,是最值得尊敬的!
小笙 + 1 分享精神,是最值得尊敬的!
涵涵涵仔 + 1 能分享加密狗软件的链接吗?在线等
XIAODOUDOU + 1 + 1 评分=感恩!简单却充满爱!感谢您的作品!
a122783999 + 1 + 1 祝学破解论坛全体成员2016年开心每一天!
billbox + 1 + 1 转的一手好帖!学习了!
十月 + 1 + 1 评分=感恩!简单却充满爱!感谢您的作品!
fzip + 2 + 1 吃水不忘引水人,学习中!
lou121505 + 1 + 1 你将受到所有人的崇拜!
若只如初见 + 1 支持原创,感谢楼主!
am873 + 3 + 1 你将受到所有人的崇拜!
kasher + 3 + 1 支持原创,感谢楼主!
fun + 1 + 1 你将受到所有人的崇拜!
清晨 + 3 + 1 高级教程,膜拜学习
Ylca + 1 + 1 建议前辈拿个软件实践一下!
heiheidz + 1 + 2 请注明转载还是原创
Crook + 3 + 1 你将受到所有人的崇拜!
yypE + 3 + 1 你将受到所有人的崇拜!
rain灿 + 3 + 1 厉害。。。
小强 + 8 + 1 你将受到所有人的崇拜!
Cari + 3 + 1 我很赞同!
Shark恒 + 1 + 20 + 1 你将受到所有人的崇拜!

查看全部评分

吾爱汇编论坛-学破解,防破解!知进攻,懂防守!逆向分析,软件安全!52HB.COM
 楼主| codelive 发表于 2014-10-19 00:52 | 显示全部楼层

扫地僧 发表于 2014-10-19 00:51
谢谢分享,不过大大可以把代码弄的清楚些吗,根本看不明白- -

刚才用代码风格有问题。
话说你这么晚也没睡啊!
吾爱汇编论坛-学破解,防破解!知进攻,懂防守!逆向分析,软件安全!52HB.COM
Cari 发表于 2014-10-19 00:55 | 显示全部楼层

code老师不放试炼品咩
吾爱汇编论坛-学破解,防破解!知进攻,懂防守!逆向分析,软件安全!52HB.COM
 楼主| codelive 发表于 2014-10-19 00:57 | 显示全部楼层

Cari 发表于 2014-10-19 00:55
code老师不放试炼品咩

软件比较敏感,主要是谈方法,关键代码都帖出来了。

点评

Shark恒”点评说:
简单帮你编辑了一下源码,你看这种格式行不行?  详情 回复 发表于 2014-10-19 00:58
吾爱汇编论坛-学破解,防破解!知进攻,懂防守!逆向分析,软件安全!52HB.COM
Cari 发表于 2014-10-19 00:58 | 显示全部楼层

codelive 发表于 2014-10-19 00:57
软件比较敏感,主要是谈方法,关键代码都帖出来了。

soga。期待后续精彩文章。
吾爱汇编论坛-学破解,防破解!知进攻,懂防守!逆向分析,软件安全!52HB.COM
Shark恒 发表于 2014-10-19 00:58 | 显示全部楼层

codelive 发表于 2014-10-19 00:57
软件比较敏感,主要是谈方法,关键代码都帖出来了。

简单帮你编辑了一下源码,你看这种格式行不行?
吾爱汇编论坛-学破解,防破解!知进攻,懂防守!逆向分析,软件安全!52HB.COM
 楼主| codelive 发表于 2014-10-19 00:59 | 显示全部楼层

Shark恒 发表于 2014-10-19 00:58
简单帮你编辑了一下源码,你看这种格式行不行?

这样好多了,谢谢老大,我刚才试过有问题。

点评

Shark恒”点评说:
感谢你的作品,已加入精华!  详情 回复 发表于 2014-10-19 01:01
吾爱汇编论坛-学破解,防破解!知进攻,懂防守!逆向分析,软件安全!52HB.COM
Cari 发表于 2014-10-19 01:01 | 显示全部楼层

Shark恒 发表于 2014-10-19 00:58
简单帮你编辑了一下源码,你看这种格式行不行?

这排版好

点评

Shark恒”点评说:
只是把代码仍进去了,也没做详细的处理。。。对了,你修复的那个OD有毒。。你查一下。好像感染exe  详情 回复 发表于 2014-10-19 01:02
吾爱汇编论坛-学破解,防破解!知进攻,懂防守!逆向分析,软件安全!52HB.COM
Shark恒 发表于 2014-10-19 01:01 | 显示全部楼层

codelive 发表于 2014-10-19 00:59
这样好多了,谢谢老大,我刚才试过有问题。

感谢你的作品,已加入精华!
吾爱汇编论坛-学破解,防破解!知进攻,懂防守!逆向分析,软件安全!52HB.COM
Shark恒 发表于 2014-10-19 01:02 | 显示全部楼层


只是把代码仍进去了,也没做详细的处理。。。对了,你修复的那个OD有毒。。你查一下。好像感染exe
吾爱汇编论坛-学破解,防破解!知进攻,懂防守!逆向分析,软件安全!52HB.COM
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

警告:本站严惩灌水回复,尊重自己从尊重他人开始!

1层
2层
3层
4层
5层
6层
7层
8层
9层
10层

免责声明

吾爱汇编(www.52hb.com)所讨论的技术及相关工具仅限用于研究学习,皆在提高软件产品的安全性,严禁用于不良动机。任何个人、团体、组织不得将其用于非法目的,否则,一切后果自行承担。吾爱汇编不承担任何因为技术滥用所产生的连带责任。吾爱汇编内容源于网络,版权争议与本站无关。您必须在下载后的24个小时之内,从您的电脑中彻底删除。如有侵权请邮件或微信与我们联系处理。

站长邮箱:SharkHeng@sina.com
站长QQ:1140549900


QQ|RSS|手机版|小黑屋|帮助|吾爱汇编 ( 京公网安备11011502005403号 , 京ICP备20003498号-6 )|网站地图

Powered by Discuz!

吾爱汇编 www.52hb.com

快速回复 返回顶部 返回列表