iOS逆向【Hopper 和 LLDB配合使用】(查看模块偏移后的基地址、添加断点、操作寄存器的值)及LLDB的常用命令

您所在的位置:网站首页 ios反汇编工具 iOS逆向【Hopper 和 LLDB配合使用】(查看模块偏移后的基地址、添加断点、操作寄存器的值)及LLDB的常用命令

iOS逆向【Hopper 和 LLDB配合使用】(查看模块偏移后的基地址、添加断点、操作寄存器的值)及LLDB的常用命令

2024-02-29 01:28| 来源: 网络整理| 查看: 265

新博客

@[toc]

前言Hopper

是一种适用于 OS X 和 Linux 的逆向工程工具,可以用于反汇编、反编译和调试 32位/64位英特尔处理器的 Mac、Linux、Windows 和 iOS 可执行程序!

hopper常用的操作:直接修改汇编代码 (在菜单Modify - Assemble Instruction 进行汇编代码的修改)LLDB是Low Level Debugger的简称,

在iOS开发的调试中LLDB是经常使用的,LLDB是Xcode内置的动态调试工具。使用LLDB可以动态的调试你的应用程序,如果你不做其他的额外处理,因为debugserver缺少task_for_pid权限,所以你只能使用LLDB来调试你自己的App。那么本篇博客中就要使用LLDB来调试从AppStore下载安装的App,并且结合着Hopper来分析第三方App内部的结构。LLDB与Hopper的结合,会让你看到不一样的东西.

在上篇博客《iOS逆向工程之脱壳》 我们已经给微信进行可脱壳处理,所以使用Hopper进行处理是没有问题的。

此部分我们就要将Hopper与LLDB结合在一起发挥其双剑合璧的作用。该部分也算是本篇博客中实战的一部分。

I、查看WeChat线程的模块偏移后基地址1.1 基础概念模块基地址`模块在内存中的起始地址----模块基地址 ASLR偏移ASLR偏移 ---- 虚拟内存起始地址与模块基地址的偏移量 lldb命令的格式如下 : [-options [option-value]] [argument [argument..]] 1.2 查看WeChat线程的模块偏移后基地址

LLDB连接上debugserver后,我们首先使用下方的命令来查看当前进程中的所有模块。从这些输出信息中我们能找到“WeChat”这个进程在虚拟内存相对于模块基地址的偏移量。

(lldb) image list -o -f [ 0] 0x00082000 /private/var/mobile/Containers/Bundle/Application/01ECB9D1-858D-4BC6-90CE-922942460859/WeChat.app/WeChat(0x0000000000086000)

第一个就是“WeChat”程序的相关信息左边0x00082000就是ASLR偏移量(随机偏移量);ASLR偏移量其实就是虚拟内存的启始地址,相对于模块基地址的偏移量。右边0x0000000000086000的地址就是偏移后的地址。

从输出结果我们可以知道:ASLR偏移量 = 0x00082000, 模块偏移后基地址 = 0x0000000000086000

下方是使用Hopper打开的解密后的微信的安装包,其起始地址从下图中我们可以看出是0x4000, 这个地址就是模块偏移前的地址,也就是模块在虚拟内存中的起始地址。从Hopper中我们可以知道:模块偏移前的基地址=0x4000

从上面两组数据我们可以得出:

  模块偏移后的基地址(0x0000000000086000)= ASLR偏移量(0x00082000)+ 模块偏移前基地址(0x4000)

上面这个公式是尤为重要的,因为Hopper中显示的都是“ 模块偏移前基地址”,而LLDB要操作的都是“模块偏移后的基地址”。所以从Hopper到LLDB,我们要做一个地址偏移量的转换。这个会多次用到。当然,有一点需要注意的是Hopper与LLDB所选择的AMR架构的位数得一致,要么是32位,要么都是64位,如果位数不匹配的话,那么计算出来的内存地址肯定是不对的。

II、使用LLDB给微信登录添加断点的例子

将断点添加在登录页面的初始化方法中

分析:首先得知道手机号“登录”视图控制器的内存地址,然后才可以使用LLDB添加断点。使用dump出来的头文件,或者使用hopperWCAccountPhoneLoginControlLogic

- (id)initWithData:(id)arg1;

下方截图中的地址就是“initWithData:”方法偏移前的基地址。根据上面的公式我们很容易就可以计算出该方法“偏移后的基地址”也就是真正的内存地址。算法如下所示:initWithData内存地址 = 0x01ba1c7e + 0x00082000(ALSR偏移) = 0x01c23c7e

III、常用命令//0x000000015bd0ff80等是某个虚拟地址 po 0x000000015bd0ff80 mem read 0x000000015bd0ff80 ;用来取内存查看内存 watchpoint set expression -w read_write -- 0x00000002812cdb80 ;用来设置watchpoint,来观察某个内存的读写情况; watchpoint set expression -w write -- 0x0000000281281e00 dis -a 0x000000015bd0ff80; //反汇编某个地址,如果该地址是个函数符号,则可以看到对应汇编代码; x 0x000000015bd0ff80 ; //这个命令x/n比较有意思,查看对应地址往后n字节的内存 breakpoint set -a 0x00000001ca9abc0c ;命令行的方式设置断点地址,特别有利于设置非符号断点,可直接根据crash地址计算得到当前的运行地址然后直接设置断点. im li ;这个命令把当前所有加载的binary images的地址给出来,可用来结合进行动态分析; thread return 0;直接当前函数调用return或return返回值0 image lookup -a 0x202952620; 符号查找3.1、添加断点

使用下述命令,给上述地址添加断点。断点添加后,点击登录按钮就会跳转到“手机号登录”页面就会执行该断点,下方截图的红框中就是“断点”执行后的效果。从下方截图中我们可以看出该断点的编号是1,Breakpoint后方就是断点编号,该编号会在操作断点是会用到,下方会给出实例。

br s -a 0x01C23C7E

如果发现错误,立即重现查看下

(lldb) image list -o -f|grep 'WeChat' [ 0] 0x00001000 /private/var/mobile/Containers/Bundle/Application/5CC4B194-DDC5-442F-A117-2D135C3FCEA9/WeChat.app/WeChat(0x0000000000005000)

此时的ALSR偏移 = 0x00001000;因此

initWithData内存地址 = 0x01ba1c7e + 0x00001000(ALSR偏移) = 0x01ba2c7e

br s -a 0x01ba2c7e (lldb) br s -a 0x01ba2c7e Breakpoint 1: where = WeChat`ClearDataItem::compareTime(std::__1::shared_ptr const&, std::__1::shared_ptr const&) + 4897562, address = 0x01ba2c7e

重新生成WeChat.decrypted 6.5.18‘

(lldb) image list -o -f|grep 'WeChat' [ 0] 0x00017000 /private/var/mobile/Containers/Bundle/Application/5CC4B194-DDC5-442F-A117-2D135C3FCEA9/WeChat.app/WeChat(0x000000000001b000)

initWithData内存地址 = 0x016dbf3a + 0x00017000(ALSR偏移) = 0x016f2f3a

br s -a 0x016f2f3a (lldb) br s -a 0x000c3000+0x016dbf3a Breakpoint 17: where = WeChat`__cxa_throw + 16426614, address = 0x0179ef3a

还是没有成功,待续

3.2、断点的单步执行(ni, si)

你可以通过nexti (简写:ni)和stepi (简写:si)来进行单步的调试。ni遇到跳转不会进入到跳转中去,而si则会跳转到相应的分支中去。

(lldb) ni Process 609 stopped * thread #1, queue = 'com.apple.main-thread', stop reason = instruction step over frame #0: 0x327e6478 libsystem_kernel.dylib`mach_msg_trap + 24 libsystem_kernel.dylib`mach_msg_trap: -> 0x327e6478 : bx lr libsystem_kernel.dylib`mach_msg_overwrite_trap: 0x327e647c : mov r12, sp 0x327e6480 : push {r4, r5, r6, r8} 0x327e6484 : ldm r12, {r4, r5, r6, r8} (lldb) si Process 609 stopped * thread #1, queue = 'com.apple.main-thread', stop reason = instruction step into frame #0: 0x327e626c libsystem_kernel.dylib`mach_msg + 40 libsystem_kernel.dylib`mach_msg: -> 0x327e626c : cmp r0, #0x0 0x327e626e : beq 0x327e62be ; 0x327e6270 : str.w r10, [sp, #0x10] 0x327e6274 : tst.w r10, #0x403.3 放开执行该断点(c)

命令c可以执行该断点, 上面这种情况如果执行c命令,因为只有一个断点,该断点执行后,就会跳转到“手机号登陆页面”。

(lldb) c Process 609 resuming3.4断点的禁用和开启

上面也有提到,上述创建的断点的编号是1,我们要对该断点进行禁用和开启操作,具体命令如下所示:

br dis 1 -- 禁用(disable)编号为1的断点 br en 1 -- 启用(enable)编号为1的断点 br dis -- 禁用所有断点 br en -- 启用所有断点(lldb) c Process 609 resuming (lldb) br dis 1 1 breakpoints disabled. (lldb) br en 1 1 breakpoints enabled.3.5、删除breakpoints(lldb) br dis All breakpoints disabled. (5 breakpoints) (lldb) br del About to delete all breakpoints, do you want to do that?: [Y/n] y All breakpoints removed. (5 breakpoints)br del 1 -- 删除(delete)编号为1的断点3.6、 退出lldb(lldb) br del About to delete all breakpoints, do you want to do that?: [Y/n] y All breakpoints removed. (1 breakpoint) (lldb) exit Quitting LLDB will kill one or more processes. Do you really want to proceed: [Y/n] yIV、lldb 操作寄存器的值4.1.输出寄存器的值(p, po)

我们使用$来访问某个寄存器中的值,并且使用p命令进行打印。下方就是通过p命令将r1寄存器中所存的内容进行打印,在打印之前将$r1进行类型转换,po命令则输出了Objective-C的对象,而p输出的是C语言类型的数据。如下所示:

(lldb) po $r0 (lldb) p (char *)$r1 (char *) $1 = 0x07000806 "\xffffffec\xffffff99"

我们还可以将一个地址所存放的值进行打印,下方这个命令就是输出了$sp指针所指的地址处所存放的值:

(lldb) p/x $sp (unsigned int) $2 = 0x039a3c744.2.修改寄存器中的值

我们不仅可以查看某些寄存器中的值,而且可修改寄存器中的中,通过下述命令我们就可以修改指的寄存器中的值。

register write 寄存器 值

接过在Hopper中对登录模块的分析,发现“WCAccountManualAuthControlLogic”这个类中的“handleAuthResponse:”方法就是用来处理“登录认证响应”的方法。也就是说“handleAuthResponse:”负责处理登录业务逻辑的网络响应,并且在这个函数的前边有一个比较(cmp r0, r1), 根据r0和r1的比较结果来进行跳转。

接下来我们要做的事情就是,在比较寄存器r0和r1中的值时我们要改变r1寄存器中的值,然后观察App的运行效果。下方这个截图是随便输入手机号和密码时所提示的内容。也就是正常的流程会弹出下方的框。

(lldb) image list -o -f|grep 'WeChat' [ 0] 0x00012000 /private/var/mobile/Containers/Bundle/Application/5CC4B194-DDC5-442F-A117-2D135C3FCEA9/WeChat.app/WeChat(0x0000000000016000)

接下来我们要做的就是给`(lldb) br s -a 0x00012000+0x13f087a`(cmp)这个内存地址添加断点,然后去修改寄存器r1的值。

接下来我们先将r0和r1中的值进行打印$r0 ,$r1中的值改成$r0 V、总结5.1 lldb 常用命令

lldb命令的格式如下 :

[-options [option-value]] [argument [argument..]] 连接serverprocess connect connect://127.0.0.1:12345查看进程在虚拟内存相对于模块基地址的偏移量。image list -o -f 只查看微信的进程(lldb) image list -o -f|grep 'WeChat' 5.1.0 断点管理简单地通过文件和行号进行断点 :breakpoint set --file foo.c --line 12 breakpoint set -f foo.c -l 12通过函数的名称来设置断点 :breakpoint set --name foo breakpoint set -n foo可以同时使用 -n来设置多个函数的断点:

`breakpoint set -n foo -n bar

`要为C++函数设置断点,使用method :breakpoint set --method foo breakpoint set -M foo设置 OC里面selector的断点 :breakpoint set --seletor alignLeftEdges: breakpoint set -S alignLeftEdges:也可以针对可执行的image设置断点 :breakpoint set --shlib foo.dylib --name foo breakpoint set -s foo.dylib -n foo

可以重复使用 --shlib来标记多个公共库。

breakpoint简写为br :breakpoint set -n "-[SKTGraphicView alignLeftEdges:]" br s -n "-[SKTGraphicView alignLeftEdges:]"(lldb) br list No breakpoints currently set. (lldb) br li No breakpoints currently set.

使用 breakpoint delete id 删除断点,简写 br del, 使用breakpoint enable id 和 breakpoint disable id 来启用或禁用断点,

5.1.1 自定义alias

我们可以设置alias :

command alias bfl breakpoint set -f %1 -l %2 bfl foo.c 12

用户可以修改~/.lldbinit文件,以存储自己的快捷键。

5.1.2 流程控制process continue 取消暂停,继续执行函数 ,别名是 continue,简写是 c.thread step-over : 执行当前函数中的一行代码,但是不跳进函数。简写是 next ,n 。thread step-in : 跳进函数中, 简写 step,s 。thread step-out : 跳出函数,简写是 finish 。thread list : 列出线程列表thread backtrace : 列出线程堆栈。可以通过thread select 2切换线程。 thread backtrace all 输出所有线程堆栈thread return : 直接返回当前函数, 可以设置返回值。5.1.2.1 thread return通过命令thread return直接返回,以跳过函数的逻辑。可用于Anti ptrace5.1.3 查看当前的断点的函数信息。(lldb) frame info frame #0: 0x0000000114ab4e76 libsystem_kernel.dylib`mach_msg_trap + 10打印出view的所有层次信息po [[UIApp keyWindow] recursiveDescription] 5.1.4 添加Action以在断点时,执行自定义事件(lldb) breakpoint set -n isEven Breakpoint 1: where = DebuggerDance`isEven + 16 at main.m:4, address = 0x00000001083b5d00 (lldb) breakpoint modify -c 'i == 99' 1 (lldb) breakpoint command add 1 Enter your debugger command(s). Type 'DONE' to end. > p i > DONE添加action的触发条件

(lldb) breakpoint modify -c 'i == 99' 1



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3