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講解一些逆向工程中很是很是重要的內容!

參考:

相關文章
相關標籤/搜索