gdb code sign on macos

gdb调试&签名

gdb debug with macos

安装gdb gcc

1brew install gdb gcc

编译&调试

源码

1#include "stdio.h"
2#include "string.h"
3
4int main() {
5    char value[] = "root";
6    printf("%s\n", value);
7    return 0;
8}

编译

编译输出为testdebug需要使用

1gcc -o test test.c -g 

debug

1gdb test

error

1macOS的debugger是lldb,得自己安装gdb,并且安装后要仔细的设置一下(比较麻烦),否则会报错:
2
3WARNING: Debugger executable '/usr/local/bin/gdb' is not signed. As a result, debugger may not work properly. 
4
5ERROR: Unable to start debugging. Unexpected GDB output from command "-exec-run". Unable to find Mach task port for process-id 5602: (os/kern) failure (0x5).
6
7(please check gdb is codesigned - see taskgated(8))

安装签名

创建证书

打开钥匙串访问.app 或者 command + space 聚焦搜索中输入 Keychain Access.app 添加 系统类 证书

第1步

设置 Identity Type 为 Self Signed Root ; 设置 Certificate Type 为 Code Signing ; 勾选 Let me override defaults,然后Continue

第2步

第3步

第4步

第5步

第6步

第7步

第8步

第9步

第10步

第10步

有时 系统 目录下 找不到刚才创建的证书,可以去 登录中查找,然后拷贝到 系统 分类行

第10步

检查证书

1.在命令行Terminal中输入下面的命令,gdb_codesign 要改成自己的证书名称,确保 keychain 是 System keychain

1 security find-certificate -c gdb_codesign |grep System.keychain

2.再确保证书没有过期,命令行输入,同样 gdb_codesign 要改成自己的证书名称,

1 security find-certificate -p -c gdb_codesign | openssl x509 -checkend 0

3.查看trust settings信息

1security dump-trust-settings -d

对gdb签名

1.编辑vi gdb-entitlement.xml

 1<?xml version="1.0" encoding="UTF-8"?>
 2<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN"
 3"http://www.apple.com/DTDs/PropertyList-1.0.dtd">
 4<plist version="1.0">
 5<dict>
 6    <key>com.apple.security.cs.allow-jit</key>
 7    <true/>
 8    <key>com.apple.security.cs.allow-unsigned-executable-memory</key>
 9    <true/>
10    <key>com.apple.security.cs.allow-dyld-environment-variables</key>
11    <true/>
12    <key>com.apple.security.cs.disable-library-validation</key>
13    <true/>
14    <key>com.apple.security.cs.disable-executable-page-protection</key>
15    <true/>
16    <key>com.apple.security.cs.debugger</key>
17    <true/>
18    <key>com.apple.security.get-task-allow</key>
19    <true/>
20</dict>
21</plist>

2.命令行中输入以下命令,gdb_codesign 改成自己的证书名字,必要时在命令前加上 sudo,如果需要频繁地构建 gdb,可以加上 –enable-codesign=gdb_codesign (gdb_codesign改成自己的)

1codesign --entitlements gdb-entitlement.xml -fs gdb_codesign $(which gdb)

3.检查

1codesign -vv $(which gdb)
2codesign -d --entitlements :- $(which gdb)

debug调试

1gdb test
 1gdb filename 加载该文件到gdb
 2gdb -tui 带画面的调试
 3
 4l(list): 显示代码,list 行号:将显示当前文件以“行号”为中心的前后10行代码,如:list 12,list 函数名:将显示“函数名”所在函数的源代码,如:list main;
 5b(break): 设置断点,参数可以是行数,函数名,也可以用文件名:行数或者文件名:函数名;
 6tb(tbreak): 临时断点,参数和b的一样;
 7info b(i b/info break): 查看断点,查看断点;
 8
 9clear n: 清除第n行的断点;
10d (delete) n: 删除第n个断点;
11disable n: 暂停第n个断点;
12enable n: 开启第n个断点;
13r (run):执行程序;
14
15s(step):有函数时,进入函数函数体,没有时,单步执行;
16n  (next):单步执行,不进入函数体;
17c (continue):遇到断点以后,程序会阻塞,输入c可以让程序继续执行;
18p (print):打印表达式,表达式可以是变量,也可以是操作,也可以是函数调用 print 1,print a+1 print f(a);
19until:可以运行程序直到退出循环体;
20finish:运行程序,直到当前函数完成返回,并打印函数返回时的堆栈地址和返回值及参数值等信息;
21watch:设置一个监视点,一旦被监视的“表达式”的值改变,gdb将强行终止正在被调试的程序;
22frame n:移动到指定的栈帧,并打印栈的信息,n为帧编号,如果不指定n,打印当前栈的信息;
23set args 参数:指定运行时的参数;
24show args:查看设置好的参数;
25show paths:查看程序运行路径;set environment varname [=value] 设置环境变量。show environment [varname] 查看环境变量;
26cd 相当于shell的cd;
27pwd :显示当前所在目录;
28info program: 来查看程序的是否在运行,进程号,被暂停的原因;
29bt(backtrace):查看堆栈信息,因为栈是后进先出,所以要从下往上看,最下面的是最先执行的函数;
30threads:查看所有线程信息;
31shell XXX:执行shell命令行,XXX为shell命令,如shell ls就执行shell里的ls命令;
32thread n:切换线程,参数为线程号,可以通过threads查看,一般常用的是通过threads查看线程序号,通过thread n切换过去,再用bt查看线程栈的信息;
33condition:给断点设置触发条件,比如b 10 if a > b与b 10然后condition 1 if a> b等价(假设b 10的断点号为1),取消断点条件用condition 断点号;
34ignore:特殊断点条件,程序只有到达该断点指定次数以后才会触发,ignore 1 10,忽略断点号为1的断点10次以后才触发;
35kill:将强行终止当前正在调试的程序;
36help 命令:help 命令将显示“命令”的常用帮助信息;
37call 函数(参数):调用“函数”,并传递“参数”,如:call  gdb_test(55);
38layout:用于分割窗口,可以一边查看代码,一边测试;
39layout src:显示源代码窗口;
40layout asm:显示反汇编窗口;
41layout regs:显示源代码/反汇编和CPU寄存器窗口;
42layout split:显示源代码和反汇编窗口;
43display: 在每次单步进行指令后,紧接着输出被设置的表达式及值;
44stepi或nexti:单步跟踪一些机器指令;
45Ctrl + L:刷新窗口;
46quit:简记为 q ,退出gdb;
47回车:重复上一条命令;
48执行下一步操作,注意命令行此时显示的并不是当前执行的操作,而是下一次要执行的。

参考