1. 程式人生 > >iOS安全攻防(二十)動態除錯利器---gdb基礎篇

iOS安全攻防(二十)動態除錯利器---gdb基礎篇

一、除錯平臺搭建

  1、GNU Debugger。首先安裝ios下的gdb偵錯程式,新增源:cydia.radare.org 。搜尋 GNU Debugger,安裝之。(有些源的GDB好像不能用,這個測試沒問題)

  3、adv-cmds。新增源:apt.saurik.com(這個應該是預設源裡的一個)。

二、附加步驟

  1、首先在ios中開啟你要除錯的app。

  2、遠端ssh登陸到ios。

login as: root
[email protected]192.168.0.2's password:
iPhone:~ root#

  3、使用adv-cmds的工具,便利下系統中的所有程序號。

iPhone:~ root# ps -ax
 366 ??         1:50.90 /var/mobile/Containers/Bundle/Application/653EB29F-15A7-48BA-9226-69C4CF690771/sb.app/sb
//或者ps -ax -c 省略路徑

  前面366就是程序號。(隨便找了個程序,只是舉個列子而已)

  比較常用的ps命令有: 

//查詢名字為QQ的app,-c為省略路徑
iPhone:~ root# ps aux -c|grep QQ mobile 1776 0.0 5.2 726108 53952 ?? Ss 7
:08PM 0:09.13 QQ
//查詢名字為disco字元的app,並且顯示啟動引數
iPhone:~ root# ps -ae|grep disco
   80 ??         0:20.99 /usr/libexec/discoveryd --udsocket standard --loglevel Basic --logclass Everything --logto asl
  176 ??         0:00.24 /usr/libexec/discoveryd_helper --loglevel Detailed --logclass Everything --logto asl

  4、使用gdb 附加366號程序

iPhone:~ root# gdb -p 366
/usr/bin/gdb: line 55: awk: command not found
warning: unrecognized host cpusubtype , defaulting to host==armv7.
GNU gdb 6.3.50-20050815 (Apple version gdb-1708 + reverse.put.as patches v0.4) (Mon Apr 16 00:53:47 UTC 2012)
Copyright 2004 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB.  Type "show warranty" for details.
This GDB was configured as "arm-apple-darwin".

.....省略若干程式碼

0x38e0e4f0 in mach_msg_trap ()
(gdb)

好了,附加成功。下面可以開始輸入命令進行除錯。

 三、常用除錯命令詳解

  首先講一點,gdb中的命令是可以縮寫的,只要包含首字母,並不引起歧義就可以使用,比如 break,可以輸入b,字母必須是連續的(br可以,ba就不行)。

  一些指令都是配套使用的,所以為了講解用法,有些指令會提前簡單說一下用法。

  我將除錯命令分為三種:

  1、控制命令,包括下斷、單步等命令,顧名思義就是控制程式碼流程的命令。

  1.1 break,下斷命令。

  1.1.1 函式下斷:已知函式名,對程式碼進行下斷。

(gdb) b CFRunLoopRunInMode
Breakpoint 3 at 0x2aef7176
(gdb) i b
Num Type           Disp Enb Address    What
3   breakpoint     keep y   0x2aef7176 <CFRunLoopRunInMode+14>

 i b 是 info break的縮寫,功能為列出當前斷點列表。

 1.1.2 不知道函式名,只知道在ida等反彙編引擎中的地址。

  我們知道目標函式在ida中的檔案偏移。

  000190EC:000590EC (點選ida中的程式碼,在左下角顯示的資料)   190ec 是檔案偏移, 590ec是記憶體中的地址。我們很容易得出ida的載入基址為 40000     由於ios的載入基址是隨機的,所以我們先要使用 info sh命令 得出 目標app在記憶體中的載入基址   info sh 是 info sharedlibrary 的縮寫
1 (gdb) info sh
2 The DYLD shared library state has not yet been initialized.
3                                                     Requested State Current State
4 Num Basename                          Type Address         Reason | | Source
5   | |                                    | |                    | | | |
6   1 sb                                   - 0x4000            exec C C /private/var/mobile/Containers/Bundle/Application/...(太長省略)

 我們得到了載入基址是0x4000,那麼 將檔案偏移0x190EC + 0x4000 得到的地址是當前app 我們要下斷的地址0x1D0EC。

(gdb) b * 0x1d0ec
Breakpoint 4 at 0x1d0ec

  1.2 delete/disable/enable 刪除/取消/啟用 斷點。引數為在info b中的斷點號,

(gdb) b *0x690ec
Breakpoint 2 at 0x690ec
(gdb) disable 2
(gdb) info b
Num Type           Disp Enb Address    What
2   breakpoint     keep n   0x000690ec <_mh_execute_header+37100>
(gdb) enable 2
(gdb) info b
Num Type           Disp Enb Address    What
2   breakpoint     keep y   0x000690ec <_mh_execute_header+37100>
(gdb) d 2
(gdb) info b
No breakpoints or watchpoints.

  1.3 nexti 單步補過。當執行函式呼叫指令時,跳過該指令。相當於 od F8

(gdb) ni
0x38e0e4f4 in mach_msg_trap ()

  1.4 stepi 單步步入。當執行函式呼叫指令時,進入函式。相當於od F7

(gdb) si
0x38e0e2e8 in mach_msg ()

  1.5 Continue 繼續執行,相當於OD F9

  1.6 run 執行一個app,沒用過,現在都是附加,以後再追加這段內容。

  1.7 finish 結束當前函式,相當於OD的執行到返回。

(gdb) finish
Run till exit from #0  0x000690ec in _mh_execute_header ()
0x000690ec in _mh_execute_header ()

  1.8  

  2、輸出命令

  2.1 info break 查詢斷點 

(gdb) info b
Num Type           Disp Enb Address    What
1   breakpoint     keep y   0x00013cb8

  2.2 查詢dylib

(gdb) info sh
The DYLD shared library state has not yet been initialized.

  2.3 查詢當前暫存器資訊

(gdb) (gdb) info reg
Undefined command: "".  Try "help".
(gdb) r0             0x10004005       268451845
Undefined command: "r0".  Try "help".
(gdb) r1             0x7000806        117442566
Undefined command: "r1".  Try "help".
(gdb) r2             0x0      0
Undefined command: "r2".  Try "help".
(gdb) r3             0xc00    3072
Undefined command: "r3".  Try "help".
(gdb) r4             0x0      0
Undefined command: "r4".  Try "help".
(gdb) r5             0x1c03   7171
Undefined command: "r5".  Try "help".
(gdb) r6             0x0      0
Undefined command: "r6".  Try "help".
(gdb) r7             0x1c8df0 1871344
Undefined command: "r7".  Try "help".
(gdb) r8             0xc00    3072
Undefined command: "r8".  Try "help".
(gdb) r9             0x549ff237       1419768375
Undefined command: "r9".  Try "help".
(gdb) r10            0x7000806        117442566
Undefined command: "r10".  Try "help".
(gdb) r11            0x7000806        117442566
Undefined command: "r11".  Try "help".
(gdb) r12            0xffffffe1       -31
Undefined command: "r12".  Try "help".
(gdb) sp             0x1c8dc4 1871300
Undefined command: "sp".  Try "help".
(gdb) lr             0x38e0e2e9       954262249
Undefined command: "lr".  Try "help".
(gdb) pc             0x38e0e2e8       954262248
Undefined command: "pc".  Try "help".
cpsr           {
  0x60000030,
  n = 0x0,
  z = 0x1,
  c = 0x1,
  v = 0x0,
  q = 0x0,
  j = 0x0,
  ge = 0x0,
  e = 0x0,
  a = 0x0,
  i = 0x0,
  f = 0x0,
(gdb) cpsr           {
Undefined command: "cpsr".  Try "help".
(gdb)   0x60000030,
Undefined command: "0x60000030".  Try "help".
(gdb)   n = 0x0,
A syntax error in expression, near `= 0x0,'.
(gdb)   z = 0x1,
Undefined command: "z".  Try "help".
(gdb)   c = 0x1,
Not stopped at any breakpoint; argument ignored.
Continuing.
  v = 0x0,
  q = 0x0,
  j = 0x0,
  ge = 0x0,
  e = 0x0,
  a = 0x0,
  i = 0x0,
  f = 0x0,
  t = 0x1,
  mode = 0x10
}       {
  0x60000030,
  n = 0,
  z = 1,
  c = 1,
  v = 0,
  q = 0,
  j = 0,
  ge = 0,
  e = 0,
  a = 0,
  i = 0,
  f = 0,
  t = 1,
  mode = usr
}
(gdb)

  2.4 Backtrace 查詢當前呼叫堆疊

(gdb) bt
#0  0x38e0e4f0 in mach_msg_trap ()
#1  0x38e0e2e8 in mach_msg ()
#2  0x2afab31a in <redacted> ()
#3  0x2afa98c0 in <redacted> ()
#4  0x2aef73c0 in CFRunLoopRunSpecific ()
#5  0x2aef71d2 in CFRunLoopRunInMode ()
#6  0x2bc30bfc in <redacted> ()
#7  0x2bc7f0bc in <redacted> ()
#8  0x0007fd3e in _mh_execute_header ()
#9  0x0007fb40 in _mh_execute_header ()
(gdb)

  2.5 disassemble 反彙編 可以dump記憶體,沒用過

(gdb) help disassemble
Disassemble a specified section of memory.
Default is the function surrounding the pc of the selected frame.
With a single argument, the function surrounding that address is dumped.
Two arguments are taken as a range of memory to dump.

  2.6 print 列印命令

  可以列印變數,暫存器。

(gdb) p $r0
$3 = 383366272
(gdb) p/x $r1
$4 = 0xb2acbc12
//列印指標,一級,二級

(gdb) info f Stack level
0, frame at 0x1afaf0: pc = 0x690ec in _mh_execute_header; saved pc 0x690ec called by frame at 0x1afaf0 Arglist at 0x1afaf0, args: Locals at 0x1afaf0,
(gdb) p
/x *0x1afaf0 $7 = 0x387e7f41
(gdb) p/x **0x1afaf0
$8 = 0xf8d0b1

 列印flag暫存器

(gdb) p $cpsr
$1 = {
  0x20000030,
  n = 0x0,
  z = 0x0,
  c = 0x1,
  v = 0x0,
  q = 0x0,
  j = 0x0,
  ge = 0x0,
  e = 0x0,
  a = 0x0,
  i = 0x0,
  f = 0x0,
  t = 0x1,
  mode = 0x10
}

  2.7 info frame列印當前棧幀資訊,同上 info f

  2.8 x 命令,沒找到全稱是啥,檢視記憶體地址中的值

(gdb) help x
Examine memory: x/FMT ADDRESS.
ADDRESS is an expression for the memory address to examine.
FMT is a repeat count followed by a format letter and a size letter.
Format letters are o(octal), x(hex), d(decimal), u(unsigned decimal),
  t(binary), f(float), a(address), i(instruction), c(char) and s(string),
  T(OSType), A(floating point values in hex).
Size letters are b(byte), h(halfword), w(word), g(giant, 8 bytes).
The specified number of objects of the specified size are printed
according to the format.

Defaults for format and size letters are those previously used.
Default count is 1.  Default address is following last thing printed
with this command or "print".

  x /nfu 0x<addr>:檢視記憶體地址中的值。

  n表示要顯示的記憶體單元的個數

  f表示顯示方式, 可取如下值

    x 按十六進位制格式顯示變數。

    d 按十進位制格式顯示變數。

    u 按十進位制格式顯示無符號整型。

    o 按八進位制格式顯示變數。

    t 按二進位制格式顯示變數。

    a 按十六進位制格式顯示變數。

    i 指令地址格式

    c 按字元格式顯示變數。

    f 按浮點數格式顯示變數。

  u表示一個地址單元的長度

    b表示單位元組,

    h表示雙位元組,

    w表示四位元組,

    g表示八位元組

  可以用來檢視當前彙編程式碼: 

(gdb) x/5i $pc
0x690ec:  9a 90 9e 98                   ldmls   lr, {r1, r3, r4, r7, r12, pc}
0x690f0:  03 28 26 d1                   teqle   r6, r3, lsl #16
0x690f4:  4b f2 a4 20                   adccs   pc, r4, r11, asr #4
0x690f8:  c0 f2 03 00                   andeq   pc, r3, r0, asr #5
0x690fc:  78 44 00 68                   stmdavs r0, {r3, r4, r5, r6, r10, lr}

  錯誤

(gdb) x/5ih $pc
0x690ec:  9a 90                         str     r0, [sp, #616]
0x690ee:  9e 98                         ldr     r0, [sp, #632]
0x690f0:  03 28                         cmp     r0, #3
0x690f2:  26 d1                         bne.n   0x69142
0x690f4:  4b f2 a4 20                   movw    r0, #45732      ; 0xb2a4

  正確。需要指定指令最小長度?

  2.7 print-object (po) 列印object物件。非常有用。

(gdb) po $r0
/private/var..

  r0 是一個NSString

  三、輸入命令

  3.1 set 修改暫存器與記憶體命令。

(gdb) p $r0
$10 = 5
(gdb) set $r0=100
(gdb) p $r0
$11 = 100

  3.2 signal 向程式傳送訊號。UNIX的系統訊號量通常從1到15,所以<signal>取值也在這個範圍。
  

還有那些比較常用的指令還望指出。

詳細的blog有: