iOS逆向(7)-LLDB,自制LLDB脚本,窜改微信红包金额

在上篇文章从fishhook看runtime,hook系统C函数中已经提到了利用LLDB的部分命令。在咱们玩逆向的时候在大多数时候实际上是拿不到源码的。因此了解一些LLDB来辅助我对别人APP的学(破)习(坏),是很是有必要的。html

自从开始玩逆向,老是会有一些大佬给我发一些转帐信息(为何不是发红包?红包金额有限制,拿不出手),金额还挺大。 都是相似于这样的。
python

88888.88.png

那么道友们想不想都收到这样的红包呢?看完这篇文章,你就能够。若是没有人转给你,评论区告诉我,我给你转,说到作到!git

废话很少说,这篇文章内容很简单,很是容易理解,可是须要记的东西比较多,理财师强烈推荐点个当心心,以备不时之需 O(∩_∩)O哈哈~。github

今天的DEMO也比较简单,能够在点击这里下载到: LLDB正则表达式

本文将介绍的内容以下:express

  • LLDB
  • 自制LLDB脚本
  • chisel
  • DerekSelander-LLDB
  • 实操窜改微信红包

1、LLDB

默认内置于Xcode中的动态调试工具。标准的 LLDB 提供了一组普遍的命令,旨在与老版本的 GDB 命令兼容。 除了使用标准配置外,还能够很容易地自定义 LLDB 以知足实际须要。bash

命令格式以下微信

<command> [<subcommand> [<subcommand>...]] + <action> + [-options [option-value]] + [argument [argument...]]
复制代码
  • []表示命令是可选的,能够有也能够没有
  • <command>(命令)和<subcommand>(子命令):LLDB调试命令的名称。命令和子命令按层级结构来排列:一个命令对象为跟随其的子命令对象建立一个上下文,子命令又为其子命令建立一个上下文,依此类推。
  • <action>:咱们想在前面的命令序列的上下文中执行的一些操做。
  • <options>:行为修改器(action modifiers)。一般带有一些值。
  • <argument>:根据使用的命令的上下文来表示各类不一样的东西。

The full lldb command names are often long, but any unique short form can be used. Instead of "breakpoint set", "br se" is also acceptable. 通常lldb的命令会很长,可是只要可以想出足够断,而且又能表明惟一性的缩写,那么缩写命令也是同一辈子效的如:breakpoint set == br seapp

LLDB的全部命令在 LLVM官网或者Apple官网 均可以查询到。笔者会在这篇文章中列举一些比较经常使用的命令。ide

一、断点设置

命令名称 命令参样例
使用名称设置断点 breakpoint set --name main
使用内存地址设置断点 breakpoint -a 0xXXXXXXXX
删除断点 breakpoint delete 1
使断点失效/生效 breakpoint disable/enable 2
查看全部断点 breakpoint list
OC中全部命名中包含为Test4的方法设置断点 breakpoint set -r Test4

随意上两张样式图:

Breakpoint_1.png
Breakpoint_2.png

附带一张官网截图,这些命令均可以在 找到

12B131A8-D3DC-4256-ADA1-604932CB0071.png

二、断点命令

命令名称 命令参样例
给某一个断点增长命令 breakpoint command add 1
查看全部断点命令 breakpoint command list
删除断点命令 breakpoint command delete 1
使某个断点命令生效/失效 breakpoint command enable/disable
给某一个断点增长命令 breakpoint command delete

给某一处断点加上一段代码,使其每次被断住的时候均可以自动执行终端代码,以下图:

breakpoint command add.png

三、执行代码

expression就是执行代码的命令,也就是经常使用的p,按照官网所说的缩写惟一性原则eexpr,也是能够的。 如图:

expression_2.png
expression_2.png

四、查看堆栈,流程控制

命令名称 命令参样例
查看当前全部堆栈 bt
返回上一步堆栈 up
查看某一条堆栈 frame select 1
查看当前堆栈的参数 frame variable
堆栈回滚到上一条 thread return
程序继续执行 c
单步下一步 n
进入下一个函数(方法) s
汇编级别的单步下一步 ni
汇编级别的进入下一个函数(方法) si

一样是一张样式图:

bt.png

五、内存断点

某个属性地址只要有改变,就触发断点。至关于对某个属性设置了KVO。

命令名称 命令参样例
直接观察一个变量 watchpoint set variable global_var
直接观察一个变量的地址 watchpoint set expression -- 0xxxxxx
删除断点 watchpoint delete 1
使断点失效/生效 watchpoint disable/enable 2
查看全部断点 watchpoint list

06BE6F9B-09CD-4CCA-89B4-0CD068B5FC0B.png

五、库文件image

命令名称 命令参样例
查看工程中使用的库(包括MachO本身) image list
查找可执行文件或共享库的原始地址 image lookup --address 0x0000000100000de0
输出NSURL的成员变量及属性信息。 image lookup --type NSURL
导出可执行文件和共享库的全部符号表 image dump symtab

七、HOOK每一个断点

给每一个断点,都执行一段代码。

命令名称 命令参样例
增长一个HOOK target stop-hook add -o "frame variable"
直接全部HOOK target stop-hook list
删除HOOK target stop-hook disable 1
使HOOK失效/生效 target stop-hook disable/enable 2

stop-hook.png

八、寄存器&&内存

命令名称 命令参样例
显示当前线程全部寄存器的值 register read --all
将0x01写入x2寄存器 register write x2 0x01
读取内存0x0002A8A2D中的的值 memory read 0x0002A8A2D (缩写x 0x0002A8A2D )

九、支持Python

例如:

script print "Here is some text"
复制代码

Python.png

2、自制LLDB脚本

一、.lldbinit

LLDB本质上就跟一个程序(或者说进程)同样,每次启动LLDB的时候都会主动加载一个初始化文件,这个文件就是.lldbinit,他的地址位于根目录下:

~/
复制代码

若是你的根目录没有这个文件,那就只用touch建立一个吧

// 建立.lldbinit
touch ~/.lldbinit
// 写入
vi ~/.lldbinit
// 查看
cat ~/.lldbinit
复制代码

.lldbinit中写入以下代码

target stop-hook add -o "frame variable"
复制代码

重启Xcode,运行工程,在任意一个地方加上断点。
会发现当断点断住的时候,自动执行了frame variable

lldbinit效果.png

读到这就有一个颇有意思的事情了:
.lldbinit能够帮咱们预加载部分命令,LLDB又支持Python语法,那么是否是能够将部分Python的代码封装起来,再利用.lldbinit的机制,进而就能够实现用咱们本身的封装好的代码,让咱们更方便的使用LLDB

说干就干。

二、脚本实操

以前咱们使用过命令image list命令查看,查看App运行后再内存中的首地址(ASLR),这个地址实际上是加上了pagezero的值,其实使用命令image list -o能够直接查看ASLR,如图:

ASLR.png
然而咱们每次只须要取的是第一个值,却打印出这么多的信息,有点烦人。这就能够写一个脚本每次取出第一个值,而且打印出来,就是咱们要的结果:
fy_get_ASLR.png
代码以下很短,固然也能够在这下载到: lldbPyDemo.py

import lldb
import re

# 获取ASLR偏移地址
def fy_get_ASLR(debugger, command, result, internal_dict):
    # 获取'image list -o'命令的返回结果
    interpreter = lldb.debugger.GetCommandInterpreter()
    returnObject = lldb.SBCommandReturnObject()
    interpreter.HandleCommand('image list -o', returnObject)
    output = returnObject.GetOutput();
    # 正则匹配出第一个0x开头的16进制地址
    match = re.match(r'.+(0x[0-9a-fA-F]+)', output)
    if match:
        print match.group(1)
    else:
        return None
# And the initialization code to add your commands 
def __lldb_init_module(debugger, internal_dict):
    # 'command script add fy_get_ASLR' : 给lldb增长一个'fy_get_ASLR'命令
    # '-f lldbPyDemo.fy_get_ASLR' : 该命令调用了lldbPyDemo文件的fy_get_ASLR函数
    debugger.HandleCommand('command script add fy_get_ASLR -f lldbPyDemo.fy_get_ASLR')
    print 'The "fy_get_ASLR" python command has been installed and is ready for use.'
复制代码

一样的,每次都主动加载lldbPyDemo.py也有点烦,将其路径加入.lldbinit中,便可实现每次自动加载。

lldbinit_2.png

LLDB全部开放出来的接口均可以在官方网站中找到,有兴趣的同窗能够研究研究。

3、chisel

Chisel is a collection of LLDB commands to assist in the debugging of iOS apps. Chisel是一个用户Debug iOS Apps 的LLDB命令集合

以上介绍来自chisel官网

因为其支持brew,安装使用的方法很简单:

brew update
brew install chisel
复制代码

若是本地没有.lldbinit文件,先在根目录建立再打开,不然直接打开

// 建立.lldbinit文件 
touch .lldbinit 
// 打开.lldbinit文件
open .lldbinit 
复制代码

而后在.lldbinit文件中追加以下命令

command script import /path/to/fblldb.py
复制代码

重启Xcode便可使用。

如下挑了一些实用的命令:

命令名称 命令描述 iOS OS X
pviews 打印当前KeyWindow的全部View Yes Yes
pvc 打印当前KeyWindow的全部VC Yes No
fv 根据正则表达式打印查找并打印View Yes No
fvc 根据正则表达式打印查找并打印VC Yes No
show/hide 在不须要continue的状况下显示/隐藏View或者Layer Yes Yes
bmessage 在类的方法或实例的方法上设置符号断点,就算没有实现显示的实现该刚发,也会触发。如viewWillAppear这个方法,在当前控制器中没有实现它,可是又想在调用它的时机触发中断。 Yes Yes
wivar 至关于watchpoint Yes Yes

下图是pviews和pvc的用例图:

pviews&&pvc.png

4、DerekSelander-LLDB

DerekSelander-LLDBchisel同样是一个LLDB的脚本集合,大部分功能一致,但DerekSelander-LLDB有一个很是好用的功能:
sbt:查看当前堆栈,而且尽量的恢复符号表!
这就很牛逼了,要知道在咱们逆向的过程当中,大部分研究的APP都是已经去符号的!
[站外图片上传中...(image-57c79-1554654483282)]

具体使用一样也能够参照官网: DerekSelander-LLDB

DerekSelander-LLDB的安装过程没有chisel那么花哨,不须要用到brew,安装过程以下(官网复制的,我就不翻译了):

一、 To Install, copy the lldb_commands folder to a dir of your choosing.
二、 Open up (or create) ~/.lldbinit
三、 Add the following command to your ~/.lldbinit file: command script import /path/to/lldb_commands/dslldb.py
复制代码

5、实操窜改微信红包

LLDB既然这么好用,那么咱们就利用LLDB来继续分析一下咱们可爱的微信,O(∩_∩)O哈哈~。

利用以前文章iOS逆向(4)-代码注入,窃取微信密码讲到的方法,直接利用Xcode将微信运行在手机上。

随意让一个小伙伴本身的微信号发一个最大的红包(0.01元),进入聊天页面以下图:

红包_1.png

在这个地方断住程序,进入LLDB的调试页面。

Stop.png
输入上文提到的Chisel命令 pviews,会发现终端打印出了很是多的视图结构。直接搜索红包金额 0.01,找到对应的 Label,以下图:
pviews.png

0.01.png

从上图能够发现显示金额的控件是MMUILabel,很像一个UILabel,并且地址为0x10e6c7d00。 在根据LLDB的p命令执行更改文本的代码,以下:

p ((UILabel *)0x10e6c7d00).text = @"¥88888.88"
复制代码

改金额.png
而后程序继续运行。能够看到微信的金额已经被改!
金额被改.png

此时的金额只是一个静态被改变的字符串而已,实际上并不会让咱们多一分钱或者少一分钱。

在普通的生活中,逆向实际上是一件很是有意思的事情,在增长本身的知识面的同时,也能给予咱们不少的欢乐,想一想看这样一张截图往朋友圈一放是否是贼有面子。哈哈,也许你的朋友圈中各类红包转帐截图也是这样来的呢?尤为是常常发这样的转帐信息的代购们。

6、总结

这片文章的内容其实很是简单,首先介绍了一下LLDB的一下基本用法,从而得知其能够支持Python语法,又有.lldbinit文件能够帮咱们自动加载脚本,全部就有了一个简单的LLDB脚本案例,以后又引出facebook出品的ChieslDerekSelander-LLDB两个脚本集合。最后就是利用LLDB进行一些简单的UI分析和执行简单的代码了。

可是,每次使用LLDB都须要断住程序,体验不是很好。那是否是有一种能力,可让程序在正常运行的时候,咱们也能够对APP进行实时的动态分析呢?
答案是确定的,神器Cycript就是这么一个存在,在下一篇文章中,将会围绕Cycript讲解一些逆向工程中很是很是重要的内容!

参考:

相关文章
相关标签/搜索