[iOS逆向实战 之十]动态调试利器---gdb基础篇

个人原创,转帖请注明来源:cnblogs.com/jailbreaker

一、调试平台搭建

  1、GNU Debugger。首先安装ios下的gdb调试器,添加源:cydia.radare.org 。搜索 GNU Debugger,安装之。(有些源的GDB好像不能用,这个测试没问题)

  2、openSSH。这个应该都会装,没装过的参考,http://www.cnblogs.com/jailbreaker/p/4142609.html

  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 *0x690ecBreakpoint 2 at 0x690ec(gdb) disable 2(gdb) info bNum Type           Disp Enb Address    What2   breakpoint     keep n   0x000690ec <_mh_execute_header+37100>(gdb) enable 2(gdb) info bNum Type           Disp Enb Address    What2   breakpoint     keep y   0x000690ec <_mh_execute_header+37100>(gdb) d 2(gdb) info bNo 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有:

http://blog.csdn.net/21cnbao/article/details/7385161

http://www.cnblogs.com/visayafan/archive/2011/09/27/2193632.html

时间: 2024-10-10 04:15:22

[iOS逆向实战 之十]动态调试利器---gdb基础篇的相关文章

[iOS逆向实战 之一]arm寄存器简介

个人原创,转帖请注明来源:cnblogs.com/jailbreaker [iOS逆向实战]这个系列的帖子,会涉及到arm汇编,以及调试工具的使用,加上实战解析一步步逆向,深入浅出. 这是第一篇帖子,简要说下arm的各个寄存器的功能. R0-R3:用于函数参数及返回值的传递 R4-R6, R8, R10-R11:没有特殊规定,就是普通的通用寄存器 R7:栈帧指针(Frame Pointer).指向前一个保存的栈帧(stack frame)和链接寄存器(link register, lr)在栈上的

[iOS逆向实战 之三]函数之基本类型(int)参数传递

个人原创,转帖请注明来源:cnblogs.com/jailbreaker 在这[iOS逆向实战 之一]中讲到函数调用的参数传递通过r0-r3来实现,这篇帖子我们来验证下.先看一个4个参数的函数代码: main方法简单调用compute方法,先看main的汇编代码: 明显可以看出,参数值1,2,3,4分别传递给r0-r3,然后通过b调用函数 compute,接着看下compute的汇编代码: 最后一行 是返回到 调用者的下一行,之前帖子已经学过了,前面面3条代注释如下: add r0, r1  

调试利器GDB(上)

调试利器GDB(上) 1.1 GDB初识 1.1.1什么是GDB? GDB是GNU项目中的调试器(gnu debuger),能够跟尊程序的执行,也能恢复程序崩溃前的状态 1.1.2为什么需要GDB? 软件产品的研发过程必然伴随bug,调试时软件开发中不可或缺的技术(调试工具很重要) 1.1.3 DBG与binutils 1.2 GDB的常规使用 1.自定义程序得到启动方式(指定影响程序运行的参数)2.设置条件断点(在满足条件时程序暂停执行)3.回溯检查导致程序异常结束的原因(core dump)

linux-c/c++调试利器gdb、ddd小试

linux-c/c++调试利器gdb.ddd小试 原文链接: http://deepfuture.iteye.com/blog/749148 博客分类: C++/C/lisp CC++C#LinuxUbuntu 一.gdb,在shell窗口调试 main.c内容: main.c #include <stdio.h> int main() { int y=0; for (int i=0;i<10;i++){ y+=i; } return 0; } 深未来技术原创文章,如转载,请注明来源ht

调试利器GDB(下)

调试利器GDB(下) 2.1数据断点 GDB中支持数据断点的设置,watch命令用于监视变量是否被改变(本质为硬件断点)用法:watch var_name 2.2 GDB中的内存查看 GDB中可以查看任意内存区域中的数据,命令格式:x /Nuf expressionN -需要打印的单元数u -每个单元的大小f -打印数据的格式其数据格式如下: 2.3 GDB中的打印格式 实例:判断系统大小端 2.4函数调用栈查看 backtrace,查看函数调用的顺序(函数调用栈的信息)frame N 切换到栈

热烈庆祝《Vue.js 实战教程 V2.x(一)基础篇》上线了!

课程简介 课程地址:https://ke.qq.com/course/432961 机构名称:大华软件学院 授课讲师:大强老师 课程名称:Vue.js 实战教程 V2.x(一)基础篇 课程简介:包括前端发展史.Vue.js简介.第一个Vue.js程序.安装环境和Vue.Vue实例.模板语法.计算属性和侦听器.Class与Style绑定.条件渲染.列表渲染.事件处理.表单输入绑定.组件基础等等. 适合人群: 1.初出茅庐,想学习前端开发的同学: 2.没用过Vue.js,想学习更多框架的同学: 3.

[iOS逆向实战 之四]创建objc对象

个人原创,转帖请注明来源:cnblogs.com/jailbreaker objc是完全面向对象的语言,所以逆向的重点就是逆向类,这篇帖子通过ida的神奇的f5功能,来逆向某个对象的创建. 我们直接看ida中的main方法的逆向出来的arm代码: 基本上看不出所以然,我们使用ida的f5分析得出c语法的伪代码如下: 提一下,我在源码中,把自动内存管理ARC关掉了,为的是让代码更整洁. 在 8,9行都看到objc_msgSend,这个objc_msgSend其实是编译器生成的代码,在源码中没有的,

[iOS逆向实战 之六]看懂mach-o(1)

个人原创,转帖请注明来源:cnblogs.com/jailbreaker 在win下搞逆向需要看懂pe,同样搞iOS安全攻防必须看懂mach-o格式,水果的官方mach-o文档在此:https://developer.apple.com/library/mac/documentation/DeveloperTools/Conceptual/MachORuntime/index.html 本文中实际项目分析,来达到“看懂”的目的,使用的工具还是前一篇blog所用的hopper. 先将目标文件拖进h

[iOS逆向实战 之九]重组mach-o格式实现简单反ida

个人原创,转帖请注明来源:cnblogs.com/jailbreaker 之前3篇大致讲了下mach-o的相关知识,这篇主要讲解如何通过对mach-o文件简单的更改达到反ida静态分析的目的,此篇目的是抛砖引玉,掌握mach-o格式可以按自己的思路去更改,做到防反汇编器. mach-o文件格式的节: 1.struct section { /* for 32-bit architectures */ 2.    char        sectname[16];   /* name of this