吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 7130|回复: 3
收起左侧

[转贴] Hopper+LLDB+Radare2 动态调试教程

[复制链接]
zyjsuper 发表于 2019-8-8 07:10
本帖最后由 zyjsuper 于 2019-8-8 07:17 编辑

本帖最后由 zyjsuper 于 2019-8-7 20:28 编辑
目录结构如下,本帖只摘录了几个部分,完整版移步:
https://pan.wps.cn/l/s5RHeje4k
Hopper+LLDB+Radare2动态调试教程.pdf



教程背景:
Youtube闲逛时,无意间发现了飘云阁飞树大神(tree_fly)的频道,地址如下:
https://www.youtube.com/channel/UCcyUJWGHkxVtA59143ojUxA


其中一个教程感觉挺经典,链接地址为:https://www.youtube.com/watch?v=pfteHwOmQIM
教程中使用的Crackme地址为:https://reverse.put.as/wp-content/uploads/2010/05/3-Fox.zip
此教程中详细介绍了使用Hopper和LLDB来动态调试程序,爆破注册流程,并且给出如何提取算法以及编写注册机,因为算法相对来讲比较简单,所以适合菜鸟练手使用。于是乎我亲自操作了一遍,觉得有必要分享给菜菜们,本教程中Hopper和LLDB动态调试以及使用Swift编写注册机属完全拷贝大神的操作,如果飞树大神觉得我有侵权行为,请提示删帖。
第三部分 使用Radare2动态调试
使用r2命令调试程序,-d参数进入调试模式。
-A    run 'aaa' command to analyze all referenced code
-d    debug the executable 'file' or running process 'pid'

[Asm] 纯文本查看 复制代码
zyjsupers-MacBook-Air:~ zyjsuper$ r2 -Ad ~/Desktop/3-Fox/Fox.app/Contents/MacOS/Fox   
= attach 2181 2181
bin.baddr 0x00001000
Using 0x1000
asm.bits 32
[x] Analyze all flags starting with sym. and entry0 (aa)
[Warning: Invalid range. Use different search.in=? or anal.in=dbg.maps.x
Warning: Invalid range. Use different search.in=? or anal.in=dbg.maps.x
[x] Analyze function calls (aac)
[x] Analyze len bytes of instructions for references (aar)
[x] Check for objc references
[x] Check for vtables
[TOFIX: aaft can't run in debugger mode.ions (aaft)
[x] Type matching analysis for all functions (aaft)
[x] Use -AA or aaaa to perform additional experimental analysis.
-- ♥ --
[0x0001101c]> afl                                                                        #显示函数列表
0x00002698    3 63           entry0
0x000026fa    1 9            main
0x00002bd4    1 6            sym.imp.exit
0x00004068   99 4716 -> 4803 sym..objc_class_name_FoxAppDelegate
0x00003104    6 3924         sym._NXArgc
0x00003100    6 3928         sym._NXArgv
0x000030f8    6 3936         sym.___progname
0x00001000    1 1            map.Fox.r_x
0x000026d8    1 20           sym.dyld_stub_binding_helper
0x000026ec    1 14           sym.__dyld_func_lookup
0x00002703    1 5            sym.public_int_FoxAppDelegate::applicationDidFinishLaunching_int
0x00002708    1 11           sym.public_int_FoxAppDelegate::window
0x00002713    1 14           sym.public_int_FoxAppDelegate::setWindow_int
0x00002721    1 76           sym.public_int_FoxAppDelegate::validateSerial_int__int
0x00002bda    1 6            sym.imp.objc_msgSend
0x0000276d    1 47           sym.public_int_FoxAppDelegate::awakeFromNib
0x0000279c    4 575          sym.public_int_FoxAppDelegate::openLicenseFile_int
0x000029db    1 60           sym.public_int_NSString_CocoaCryptoHashing_::sha1HexHash
0x00002a17    1 60           sym.public_int_NSString_CocoaCryptoHashing_::sha1Hash
0x00002a53    3 143          sym.public_int_NSData_CocoaCryptoHashing_::sha1Hash
0x00002bb6    1 6            sym.imp.CC_SHA1
0x00002bce    1 6            sym.imp.__stack_chk_fail
0x00002ae2    5 211          sym.public_int_NSData_CocoaCryptoHashing_::sha1HexHash
0x00002be0    1 6            sym.imp.sprintf
0x00002be6    3 36           sym._stub_helpers
0x00002bbc    1 6            sym.imp.NSApplicationMain
0x00002bc2    1 6            sym.imp.NSHomeDirectory
0x00002bc8    1 6            sym.imp.NSRunAlertPanel
[0x0001101c]> db sym.public_int_FoxAppDelegate::validateSerial_int__int    #在函数起始位置设置断点。
[0x0001101c]> dc                                                        #运行程序

程序运行起来,打开license文件验证..........

[Asm] 纯文本查看 复制代码
.....................
/BuildRoot/Library/Caches/com.apple.xbs/Sources/AppleFSCompression/AppleFSCompression-96.200.3/Libraries/CompressData/CompressData.c:353: Error: Unknown compression scheme encountered for file '/System/Library/PrivateFrameworks/FinderKit.framework/Resources/Base.lproj/ColumnPreview.nib'
hit breakpoint at: 2721
[0x00002721]> pdf                                            		   #显示函数内容
    ;-- eax:
            ;-- eip:
┌ (fcn) sym.public_int_FoxAppDelegate::validateSerial_int__int 76
│   sym.public_int_FoxAppDelegate::validateSerial_int__int (int32_t arg_10h, int32_t arg_14h);
│           ; arg int32_t arg_10h @ ebp+0x10
│           ; arg int32_t arg_14h @ ebp+0x14
│           ; var int32_t var_4h @ esp+0x4
│           ; var int32_t var_8h @ esp+0x8
│           0x00002721 b    55             push ebp
│           0x00002722      89e5           mov ebp, esp
│           0x00002724      83ec18         sub esp, 0x18
│           0x00002727      a108400000     mov eax, dword str.sha1HexHash ; [0x4008:4]=0x2e06 str.sha1HexHash
│           ; DATA XREF from segment.LINKEDIT (+0x9599)
│           0x0000272c      89442404       mov dword [var_4h], eax
│           0x00002730      8b4514         mov eax, dword [arg_14h]    ; [0x14:4]=-1 ; 20
│           0x00002733      890424         mov dword [esp], eax
│           0x00002736      e89f040000     call sym.imp.objc_msgSend   ; void *objc_msgSend(void *instance, char *selector)
│           0x0000273b      8b1504400000   mov edx, dword [0x4004]     ; [0x4004:4]=0x91464d06
│           0x00002741      89542404       mov dword [var_4h], edx
│           0x00002745      890424         mov dword [esp], eax
│           0x00002748      e88d040000     call sym.imp.objc_msgSend   ; void *objc_msgSend(void *instance, char *selector)
│           0x0000274d      8b5510         mov edx, dword [arg_10h]    ; [0x10:4]=-1 ; 16
│           0x00002750      89542408       mov dword [var_8h], edx
│           0x00002754      8b1500400000   mov edx, dword map.Fox.rw   ; [0x4000:4]=0x9018aad3
│           0x0000275a      89542404       mov dword [var_4h], edx
│           0x0000275e      890424         mov dword [esp], eax
│           0x00002761      e874040000     call sym.imp.objc_msgSend   ; void *objc_msgSend(void *instance, char *selector)
│           0x00002766      84c0           test al, al
│           0x00002768      0f95c0         setne al
│           0x0000276b      c9             leave
└           0x0000276c      c3             ret
[0x00002721]> db 0x00002733                            #在合适位置设置以下几个断点
[0x00002721]> db 0x0000273b
[0x00002721]> db 0x0000274d
[0x00002721]> db 0x00002750
[0x00002721]> db 0x00002766
[0x00002721]> db                                        #显示断点列表
0x00002721 - 0x00002722 1 --x sw break enabled cmd="" cond="" name="sym.public_int_FoxAppDelegate::validateSerial_int__int" module="/Users/zyjsuper/Desktop/3-Fox/Fox.app/Contents/MacOS/Fox"
0x00002733 - 0x00002734 1 --x sw break enabled cmd="" cond="" name="0x00002733" module="/Users/zyjsuper/Desktop/3-Fox/Fox.app/Contents/MacOS/Fox"
0x0000273b - 0x0000273c 1 --x sw break enabled cmd="" cond="" name="0x0000273b" module="/Users/zyjsuper/Desktop/3-Fox/Fox.app/Contents/MacOS/Fox"
0x0000274d - 0x0000274e 1 --x sw break enabled cmd="" cond="" name="0x0000274d" module="/Users/zyjsuper/Desktop/3-Fox/Fox.app/Contents/MacOS/Fox"
0x00002750 - 0x00002751 1 --x sw break enabled cmd="" cond="" name="0x00002750" module="/Users/zyjsuper/Desktop/3-Fox/Fox.app/Contents/MacOS/Fox"
0x00002766 - 0x00002767 1 --x sw break enabled cmd="" cond="" name="0x00002766" module="/Users/zyjsuper/Desktop/3-Fox/Fox.app/Contents/MacOS/Fox"

[0x00002721]> dc
hit breakpoint at: 2733
[0x00002721]> pf xxS @eax                                  #显示eax寄存器的内存数据
0x08d7b2c0 = 0xa83f7870
0x08d7b2c4 = 0x0100078c
0x08d7b2c8 = 0x08d7b2c8 -> 0x77616805 
[0x00002721]> psz @ 0x08d7b2c8                            #显示此参数的值,即用户名
hawke
[0x00002721]> dc
hit breakpoint at: 273b
[0x00002721]> pf xxS @ eax
0x00209f90 = 0xa83f7870
0x00209f94 = 0x0100078c
0x00209f98 = 0x00209f98 -> 0x37383528 
[0x00002721]> psz @ 0x00209f98                #用户名经过sha1HexHash 函数加密后的字符串
(587377f4518ef068e17b393074c0a2183cd055d2
[0x00002721]> dc
hit breakpoint at: 274d
[0x00002721]> pf xxS @eax
0x006569a0 = 0xa83f7870
0x006569a4 = 0x010007ad
0x006569a8 = 0x006569a8 -> 0x006cd3e0 
[0x00002721]> psz @ 0x006cd3e0
(587377F4518EF068E17B393074C0A2183CD055D2           #转换成大写字母
[0x00002721]> dc
hit breakpoint at: 2750
[0x00002721]> pf xxS @ edx
0x08da1180 = 0xa83f7870
0x08da1184 = 0x0100078c
0x08da1188 = 0x08da1188 -> 0x58585804 
[0x00002721]> psz @ 0x08da1188                         #显示license文件中的序列号
XXXX
[0x00002721]> dc 
hit breakpoint at: 2766
[0x00002766]> dr al
0x00000000
[0x00002766]> dr al=1                                   #手动将寄存器al的值改成1
0x00000000 ->0x00000001
[0x00002766]> dr al
0x00000001
[0x00002766]> dc


程序验证license通过,至此,使用radare2动态调试分析爆破成功。

                                                          第四部分 分析整理算法

算法比较简单,此处引用加密与解密第四版中的介绍如下:序列号保护的本质就是验证用户名和序列号之间的映射关系,越复杂的映射关系越难破解,根据映射关系的不同,程序检测序列号有以下几种方式:序列号 = F (用户名)如果把这个过程看作加密解密并进行密文对比的过程,那么用户名就是明文,而序列号则是密文,F函数就是加密算法了。这种保护方法虽然简单,但极为不安全,因为在程序运行的某一时刻,内存中一定会出现正确的序列号,也就是加密函数结束后。只要找到正确的时间点,甚至完全不用关心算法就可以完成验证。用户名 = F (序列号)这里是把序列号作为明文,用户名作为密文了,这种方式通常需要F函数是一种对称加密算法的解密函数,而官方生成序列号时则使用加密函数对用户名进行加密得到的,这样就不会出现内存中有正确序列号的情况。这种保护方式的关键就是解密算法了,一旦得到解密算法就有机会逆向出加密算法,这样也就完成了验证。F1 (用户名) = F2 (序列号) 这种方式是上一种的扩展,它相当于多套了几层加密而已。验证方式是:用户名 = F( F2(序列号) )特殊值 = F (用户名, 序列号)这种保护方式的数学原理就比较复杂了,但保护效果相比前几种有了很大提升。不过在设计上有难度,并且可能出现用户名与序列号映射不唯一的情况。 Crackme使用的算法逻辑为: 序列号 = F (用户名)Serial(序列号)=uppercaseString(sha1HexHash(name)),将用户名经过sha1算法加密得到的hash值,再将hash值中的字母转化成大写,就得到了用户名对应的序列号。得到了算法逻辑,我们就可以按照此算法去编写注册机。

                                            第五部分 使用Python编写KeyGen

[Python] 纯文本查看 复制代码
#!/usr/bin/env python2
#-*-coding:utf-8-*-

'''
@version: python2.7
@author: ‘zyjsuper‘
@license: Apache Licence 
@software: PyCharm
@file: Crackme3.py
@time: $2019-08-06 18:27
'''

import string
import random
from hashlib import sha1

ch =  string.ascii_letters

#生成一个5到8位长度的随机用户名
def gen_name():
    result = ""
    for i in range(random.randint(5,8)):
        result = result+random.choice(ch)
    return result

name = gen_name()

#将用户名使用sha1加密
psw=sha1()
psw.update(name.encode('utf8'))

#将加密后的hash值转化大写字母
serial=string.upper(psw.hexdigest())


#生成对应的license文件内容
license = ('''
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
        <key>regName</key>
        <string>%s</string>
        <key>regNumber</key>
        <string>%s</string>
</dict>
</plist>
'''  %(name,serial))

#将license写入文件
with open("reg.foxlicense","w") as file:
    file.write(license)

print '*'*55
print "Valid license file has been generated successfully!"
print '*'*55

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

75769837 发表于 2019-8-8 13:46
收藏 收藏 收藏
夜O无眠 发表于 2019-11-24 11:45
songying2013 发表于 2020-7-23 09:17
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-11-16 09:38

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

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