飘云阁

 找回密码
 加入我们

QQ登录

只需一步,快速开始

查看: 4583|回复: 11

[08版] 浅谈栈机制的应用及程序的自注册

[复制链接]

该用户从未签到

发表于 2008-6-13 11:03:22 | 显示全部楼层 |阅读模式
——

    今天分析的这款程序是X-NetStat Professional V5.52,明码比较的一个软件,我们通过这款程序来简单谈一下栈机制的应用和程序的自注册问题(明码比较的软件都可以实现程序的自注册)。 程序Borland Delphi 6.0 - 7.0写的,无壳,用DeDe可以分析出两个事件的地址:

unRegister2:
00563944  /.  55            PUSH EBP
unAbout2:
00564C70  /.  55            PUSH EBP


    我们点注册按钮程序将自动打开官方注册页面,这一点很不爽,我们在程序中搜索该网页的ASCII找到两处并下断点,点注册时来到这里:



00564848  /.  55            PUSH EBP                                 ;  将这里修改为retn
00564849  |.  8BEC          MOV EBP,ESP
0056484B  |.  6A 01         PUSH 1                                   ; /IsShown = 1
0056484D  |.  6A 00         PUSH 0                                   ; |DefDir = NULL
0056484F  |.  6A 00         PUSH 0                                   ; |Parameters = NULL
00564851  |.  68 68485600   PUSH xns5.00564868                       ; |http://www.freshsoftware.com/xns/pro/register.html
00564856  |.  68 9C485600   PUSH xns5.0056489C                       ; |open
0056485B  |.  E8 EC33EAFF   CALL <JMP.&user32.GetDesktopWindow>      ; |[GetDesktopWindow
00564860  |.  50            PUSH EAX                                 ; |hWnd
00564861  |.  E8 52CEEDFF   CALL <JMP.&shell32.ShellExecuteA>        ; \ShellExecuteA
00564866  |.  5D            POP EBP
00564867  \.  C3            RETN

    我们将该函数的首行修改为retn,使其不执行下方的指令以去掉弹出网页。我们在注册事件的地址00563944下断,随意输入假码点击注册:

00563944  /.  55            PUSH EBP                                 ;  程序中断在这里
00563945  |.  8BEC          MOV EBP,ESP
……
……
00563990  |.  8B45 FC       MOV EAX,DWORD PTR SS:[EBP-4]
00563993  |.  E8 D0020000   CALL xns5.00563C68                       ;  很显然这里可以猜测到就是算法CALL
00563998  |.  84C0          TEST AL,AL                               ;  这里是对该函数返回的AL标志位进行判断
0056399A  |.  0F84 DB000000 JE xns5.00563A7B                         ;  如果AL=0则代表注册失败
005639A0  |.  E8 AFFDFFFF   CALL xns5.00563754                       ;  如果上方没有跳转 下边的指令将保存注册信息
005639A5  |.  A1 E4F15C00   MOV EAX,DWORD PTR DS:[5CF1E4]
……
……
005639D5  |.  8B00          MOV EAX,DWORD PTR DS:[EAX]
005639D7  |.  B9 E83A5600   MOV ECX,xns5.00563AE8                    ;  name
005639DC  |.  BA F83A5600   MOV EDX,xns5.00563AF8                    ;  Registration
……
……
00563A74  |.  E8 17950400   CALL xns5.005ACF90
00563A79  |.  EB 3D         JMP SHORT xns5.00563AB8
00563A7B  |>  E8 F0FDFFFF   CALL xns5.00563870                       ;  上方跳转将跳到这里

    我们F7跟进算法CALL,在数据窗口发现该函数有四处调用,通过现象我们可以大胆的猜测一下还有哪里调用该算法CALL,可能有:启动时的验证,或者过期后、功能验证时也将调用该函数来进行判断。



我们F7跟进算法CALL,F8单步到这里是发现真码:

00563CBB   .  8D45 E8       LEA EAX,DWORD PTR SS:[EBP-18]
00563CBE   .  8B55 F0       MOV EDX,DWORD PTR SS:[EBP-10]            ;  到这里我们看到真码出现
00563CC1   .  E8 6E0EEAFF   CALL xns5.00404B34                       ;  这时注意看堆栈中的数据
00563CC6   .  8D45 EC       LEA EAX,DWORD PTR SS:[EBP-14]
00563CC9   .  8B55 F4       MOV EDX,DWORD PTR SS:[EBP-C]
00563CCC   .  E8 630EEAFF   CALL xns5.00404B34                       ;  我们在这里做文章



我们在EBP寄存器上点右键,跟随到堆栈窗口,向上翻一点就可以看到真码的地址保存在堆栈:



    我们知道,程序在函数中是通过EBP来寻址的,在这个程序中,真码的保存位置为[EBP-10](EBP向上一行地址-4,两行-8,三行-CH,四行-10H),假码的地址为[EBP-C]。既然在栈中看到了真码和假码(真码的地址),那我们就可以利用栈来实现程序的自注册。我们现在程序代码段找到一个空白地址(一般在OD的反汇编窗口将滚动条拉到最下方就可以看到**的00 00 00 00 的空白数据,我们在这里写代码即可),我们找到一片空白数据,将 CALL 00404B34 修改为 CALL  005CABDC ,我们写一些代码来实现将假码替换为真码。

00563CCC   .  E8 630EEAFF   CALL xns5.00404B34                             ;  我们将这里修改为 CALL  005CABDC

Patch代码如下:

005CABDC      56            PUSH ESI                                       ;  将使用到的寄存器压栈
005CABDD      57            PUSH EDI
005CABDE      51            PUSH ECX
005CABDF      53            PUSH EBX
005CABE0      B9 1E000000   MOV ECX,1E                                     ;  真码的长度29+1=1DH
005CABE5      8B75 F0       MOV ESI,DWORD PTR SS:[EBP-10]
005CABE8      8B7D F4       MOV EDI,DWORD PTR SS:[EBP-C]
005CABEB      8BDF          MOV EBX,EDI
005CABED      F3:A4         REP MOVS BYTE PTR ES:[EDI],BYTE PTR DS:[ESI]   ;  实现假码的数据替换为真码
005CABEF      C743 FC 1D000>MOV DWORD PTR DS:[EBX-4],1D                    ;  修改字符串的长度
005CABF6      5B            POP EBX                                        ;  将使用到的寄存器出栈
005CABF7      59            POP ECX
005CABF8      5F            POP EDI
005CABF9      5E            POP ESI
005CABFA      E8 409FE3FF   CALL xns5.00404B3F                             ;  还原我们覆盖的数据
005CABFF      C3            RETN                                           ;  返回

这里先介绍一个传送字符串的汇编指令:

MOV ECX,传送字串的长度
MOV ESI,源地址
MOV EDI,目的地址
CLD 设置DF=0,字符串正向传送
REP MOVSB 以字节形式传送 每次操作后ESI+1,EDI+1,直到ECX=0结束

我们这里还添加了这样两句代码:

MOV EBX,EDI                   // EDI这里保存的是假码的地址
MOV DWORD PTR DS:[EBX-4],1D   // 在[EDI-4]的内存中写入数值1D(该程序的KEY格式固定长度为29=1DH)

在内存中,字符串有两个属性:字符串的地址和字符串的长度,字符串的长度数值就保存在【字符串地址-4】的地址
如下图中KEY的长度存放的地址就在该字符串首地址010F7964-4=010F7960,其数值为1DH。



在CALL中当使用到的寄存器出栈完毕后(注意:压栈和出栈修改的是ESP,当程序访问一个函数时,大多都先将ESP数值保存到EBP,该函数退出前再将EBP保存的数据送还ESP,函数的参数若保存到栈中,我们使用EBP寻址就可以方便的访问这些参数),我们再来还原我们在程序中覆盖的代码:CALL 00404B3F

我们写的函数执行完毕后加上RETN语句返回即可

通过跟踪,我们发现程序的注册信息保存在注册表中:

Windows Registry Editor Version 5.00

[HKEY_CURRENT_USER\Software\X-NetStat Professional 5\Registration]
"name"="Nisy"
"email"="[email protected]"
"key"="11111-11111-11111-11111-11111"

    通过上面我们写的函数,就可以实现程序将真码保存到注册表中。程序启动的时候也将调用这个算法CALL,所以即便我们注册表保存的是假码,程序也会将内存中存放的假码替换成真码来实现注册。

下面我们来看[PYG]解密小组成员 柳韵荷风 更巧妙的修改来实现程序的自注册:

在算法CALL中修改如下:

00563FDF   .  E8 DC0AEAFF   CALL xns5.00404AC0                             ;  这里修改为MOV EBX,DWORD PTR SS:[EBP-10]
00563FE4   .  C3            RETN
00563FE5   .^ E9 3604EAFF   JMP xns5.00404420
00563FEA   .^ EB EB         JMP SHORT xns5.00563FD7
00563FEC   .  8BC3          MOV EAX,EBX
00563FEE   .  5E            POP ESI
00563FEF   .  5B            POP EBX
00563FF0   .  8BE5          MOV ESP,EBP
00563FF2   .  5D            POP EBP
00563FF3   .  C2 0400       RETN 4                                         ;  到这里算法CALL执行完毕返回

修改为:

00563FDF      8B5D F0       MOV EBX,DWORD PTR SS:[EBP-10]
00563FE2      90            NOP
00563FE3      90            NOP
00563FE4   .  C3            RETN
00563FE5   .^ E9 3604EAFF   JMP xns5.00404420
00563FEA   .^ EB EB         JMP SHORT xns5.00563FD7
00563FEC   .  8BC3          MOV EAX,EBX                                    ;  这里将EBX中真码的地址送到EAX中

注意:这样修改后,算法CALL的EAX将保存真码的地址,所以程序启动时调用算法CALL返回的数据AL!=0,仅修改这一处就相当于实现了爆破,我们关注的还是程序自注册,继续看下文:

程序返回算法CALL后:

00563993  |.  E8 D0020000   CALL xns5.00563C68                             ;  算法CALL
00563998      84C0          TEST AL,AL
0056399A      0F84 DB000000 JE xns5.00563A7B

修改为:

00563998      8945 F4       MOV DWORD PTR SS:[EBP-C],EAX                   ;  算法CALL返回后 EAX保存真码的地址
0056399B      90            NOP                                            ;  [EBP-C]保存的是假码的地址 这里将假码的地址替换为真码的地址
0056399C      90            NOP
0056399D      90            NOP
0056399E      90            NOP
0056399F      90            NOP

    我们知道在栈中保存的为字符串的地址,所以替换栈中保存的地址,将[EBP-C]保存的假码地址替换为真码的地址,使程序保存时保存真码,照样可以实现自注册。

    以上两种方法和思路就是简单的对栈中数据的利用,第一种方法是替换栈中指针所指向的数据(字符串),第二种方法是替换栈中保存的地址。这两种思路,是我们处理栈中数据常用到的方法,希望通过本文的学习,大家不仅扩展了程序的爆破思路,同时也对栈有一个更深刻的认识。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?加入我们

x
PYG19周年生日快乐!
  • TA的每日心情
    慵懒
    2019-2-17 18:27
  • 签到天数: 33 天

    [LV.5]常住居民I

    发表于 2008-6-13 11:17:16 | 显示全部楼层
    沙发位,非常不错,学习!
    PYG19周年生日快乐!

    该用户从未签到

     楼主| 发表于 2008-6-13 11:17:56 | 显示全部楼层
    总觉得欠社会这样一本教程 还是那句话:人的价值不是能做什么 而在于做了什么

    虽然我水平不高 但我会尽力把我所懂的知道告诉更多的人 将破解的正确理念告诉学习的人 如果我们密界的人都不去做这件事 还有谁会去做呢
    PYG19周年生日快乐!
  • TA的每日心情
    无聊
    2017-8-31 14:43
  • 签到天数: 7 天

    [LV.3]偶尔看看II

    发表于 2008-6-13 11:19:18 | 显示全部楼层
    来学习一下,,,,非常不错
    PYG19周年生日快乐!
  • TA的每日心情
    擦汗
    2017-9-24 22:49
  • 签到天数: 4 天

    [LV.2]偶尔看看I

    发表于 2008-6-13 11:27:16 | 显示全部楼层
    很好,分析得很详细,来看看
    PYG19周年生日快乐!

    该用户从未签到

     楼主| 发表于 2008-6-13 11:30:16 | 显示全部楼层
    这两天 第二章其他的文章会陆续放出

    等第一章公开的时候 大家会更加惊喜的 ~~
    PYG19周年生日快乐!

    该用户从未签到

    发表于 2008-6-13 11:36:28 | 显示全部楼层
    好文留名!~~支持一下!
    PYG19周年生日快乐!
  • TA的每日心情
    开心
    2015-11-6 10:18
  • 签到天数: 1 天

    [LV.1]初来乍到

    发表于 2008-6-13 11:44:56 | 显示全部楼层
    我一直认为,作为教程,不在于理论的探究多深;应该在于读者的能否理解,可操作性如何!"图"和"文"的结合应该侧重些.我赞成NISY的做法.对于入道"高手"这些,可能不嗤一鼻.但对于初学和刚尝试的群体,绝对是给他们豁然一亮的"一点拨"!这就完成了我们的目的!个人观点!不对的批评!
    PYG19周年生日快乐!
  • TA的每日心情
    开心
    2015-8-3 23:07
  • 签到天数: 3 天

    [LV.2]偶尔看看I

    发表于 2008-6-13 15:37:49 | 显示全部楼层
    好文,学习学习。另:期待“惊喜”
    PYG19周年生日快乐!
  • TA的每日心情
    开心
    2024-1-27 00:17
  • 签到天数: 17 天

    [LV.4]偶尔看看III

    发表于 2008-6-14 01:09:12 | 显示全部楼层
    人的价值不是能做什么 而在于做了什么

    喜欢老大的这句话  

    /:good
    PYG19周年生日快乐!
    您需要登录后才可以回帖 登录 | 加入我们

    本版积分规则

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