gdb

Debugging Symbol Table 把编译的二进制代码对应到响应的变量名, 方法名 和 行号. 符号表可以嵌入到二进制程序中或者在一个单独的文件中.

通过 -g 的参数把符号表嵌入到二进制代码中:

gcc -g hello.cc -o hello 

# 把 debug 信息分离出来
objcopy --only-keep-debug hello hello.debug
# 或者
cp hello hello.debug
strip --only-keep-debug hello.debug

# 去掉 debug 信息
strip --strip-debug --strip-unneeded hello

# 加入 debug 信息
objcopy --add-gnu-debuglink hello.debug hello

# debug 分离的信息
gdb -s hello.debug -e hello

# 或者 debug 启动之后
gdb
(gdb) exec-file  hello
(gdb) symbol-file hello.debug

基本的命令:

file a.out #指定要 debug 的二进制文件
run #启动程序
run 202 "abc" > out.txt # 给要执行的文件参数 并把结果放入 out.txt

break #添加断点到当前行
break myFuction #添加断点到 myFuction
break 5 #添加断点到第五行
break +5 #添加断点到 -> 从当前行往后数5行

info break #查看断点 
info threads

watch x == 3 #如果条件满足, 则暂停

delete 5 #删除第五个断点
clear #清除当前函数的断点

continue #继续运行直到下个断点或错误
finish #继续运行直到当前函数结束
step #运行下一行指令, 如果下一行是函数, 直接进入这个函数, 然后暂停
step 5 #运行后边的5条指令
next #运行下一行, 如果下一行是函数, 直接执行完这个函数

print var #打印变量 var 的值

set x = 3 #设置变量 x 的值为3
set x = y #设置变量 x 的值为 y 的值

bt #查看当前栈
up #到上一层帧
down #到下一层帧
stack #查看当前帧
return #从当前函数返回
select-frame 3 #

help list #打印 list 命令帮助
list 210 #打印出当前文件的第210行左右的行代码
list hello.c:43 #打印 hello.c 的第43行左右的代码
list hello.c:test #打印 hello.c 的test 函数

call myFunc() #执行 myFunc 函数
call myFunc(4) #执行 myFunc 函数
call strlen(str) #执行系统函数 strlen

display x #每一步都显示 x 的值
undisplay x #不要再每一步都显示 x 的值

一篇比较好的关于 GDB debug Java native 代码或 JDK 代码的文章:
https://medium.com/@pirogov.alexey/gdb-debug-native-part-of-java-application-c-c-libraries-and-jdk-6593af3b4f3f

Windows 上解密 chrome 的 https 流量

https 其实是使用传输层的 SSL/TLS 对内容进行加密. SSL/TLS 首先使用非对称加密传输客户端产生的 pre-master secret key. 然后之后使使用对称加密传输内存, 对称加密的的算法使用之前双方都有的 pre-master secret key 作为秘钥. 如果知道了 pre-master secret key, 那么就能解密 https 的流量了. 下面是 windows 上使用 chrome 截取 pre-master secret key 并使用 wireshark 解密的例子.

  1. 设置环境变量 SSLKEYLOGFILE 的值是本地一个文件
    win_env.png
  2. 重新启动 chrome;
  3. 随便访问一个 https 网站, 查看上面设置的文件里是不是已经有 key 产生;
  4. 启动 wireshark, 设置 TLS 的 key 文件.
    菜单: Edit -> Preferences -> Protocols -> TLS -> (pre-)master secret key log file
    wins_key.png
  5. 使用 wireshark 抓包, 或者 wincap 抓包. 抓包后最好使用 wireshark filter 一下. 找到 http1.1 或者 http2 的内容, 就能看到原文了
    wins_wire.png

Java 如何简单的诊断 https (SSL/TLS) 请求

如果你能控制整个 Java 应用的启动, 那么你可以很简单的加SSL/TLS 的 debug 参数去打印等多的信息. 比如:

java -Djavax.net.debug=all myApp
java -Djavax.net.debug=ss:plaintext myApp 

想查看更多可以用的参数: 必须找一个 App, 不能使用常见的 java -Djavax.net.debug=help -version

java -Djavax.net.debug=help myApp

一个访问百度首页的 (-Djavax.net.debug=ss:plaintext) 的输出:

javax.net.ssl|DEBUG|01|main|2021-08-06 07:43:20.943 PDT|SSLCipher.java:1769|Plaintext before ENCRYPTION (
  0000: 47 45 54 20 2F 20 48 54   54 50 2F 31 2E 30 0A 0A  GET / HTTP/1.0..
)
javax.net.ssl|DEBUG|01|main|2021-08-06 07:43:21.233 PDT|SSLCipher.java:1671|Plaintext after DECRYPTION (
  0000: 48 54 54 50 2F 31 2E 30   20 35 30 30 20 49 6E 74  HTTP/1.0 500 Int
  0010: 65 72 6E 61 6C 20 53 65   72 76 65 72 20 45 72 72  ernal Server Err
  0020: 6F 72 0D 0A 43 6F 6E 74   65 6E 74 2D 4C 65 6E 67  or..Content-Leng
  0030: 74 68 3A 20 30 0D 0A 43   6F 6E 74 65 6E 74 2D 54  th: 0..Content-T
  0040: 79 70 65 3A 20 74 65 78   74 2F 70 6C 61 69 6E 3B  ype: text/plain;
  0050: 20 63 68 61 72 73 65 74   3D 75 74 66 2D 38 0D 0A   charset=utf-8..
  0060: 44 61 74 65 3A 20 46 72   69 2C 20 30 36 20 41 75  Date: Fri, 06 Au
  0070: 67 20 32 30 32 31 20 31   34 3A 34 33 3A 32 31 20  g 2021 14:43:21 
  0080: 47 4D 54 0D 0A 53 65 72   76 65 72 3A 20 62 66 65  GMT..Server: bfe
  0090: 0D 0A 0D 0A                                        ....
)

更多信息参考:

  1. https://docs.oracle.com/javase/7/docs/technotes/guides/security/jsse/ReadDebug.html
  2. https://docs.oracle.com/javase/7/docs/technotes/guides/security/jsse/JSSERefGuide.html#Debug
  3. https://access.redhat.com/solutions/973783

MAC 上解密 chrome 的 https 流量

Chrome 或者 Firefox 都支持: 如果设置了环境变量 SSLKEYLOGFILE, 就把 SSL/TLS 的 pre-master secret key 写到设置的文件里面去. 之后可以使用这个 pre-master secret key 文件在 wireshark 里面解密加密的流量.

----- 原来的步骤 1, 2 在2023年底不行了, 换成如下 --------------
在命令行执行:

SSLKEYLOGFILE=/tmp/google/ssl-key.log /Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome --user-data-dir=/tmp/google

---------- 补丁结束 ----------------

  1. 设置 SSLKEYLOGFILE 环境变量
    可以简单在命令行使用 export 命令 (记得之后打开 Chrome 要在这个命令行)

    export SSLKEYLOGFILE=~/ssh_key.log
  2. 在同一个命令行窗口打开 chrome

    open /Applications/Google\ Chrome.app/
  3. 在 chrome 随便访问一个 https 的网站, 检查 ~/ssh_key.log 是不是有内容
  4. 打开 wireshark 拦截流量或者 使用 tcpdump 有针对性的拦截

    sudo tcpdump host 103.144.218.5 -w mydump.pcap 
  5. 打开 wireshark, 分析这个加密的流量.
    显示设置SSL/TLS 的 pre-master secret key log 文件:
    菜单: preferences -> Protocols -> TLS (Wireshark 3.0 之前是 SSL):

    Preferences.png

  6. 关于 key log 文件的格式:https://developer.mozilla.org/en-US/docs/Mozilla/Projects/NSS/Key_Log_Format

    之后:

    1. 首先找到带有 data 的行
    2. 可以看 http 或 http 2 的数据
    3. 点击下面(3)的 Decrypted data, 其实里面看上去是乱码, 因为直接解密后还是压缩的, 所以是乱码;
    4. 点解下面(4)的 uncompressed entity body 可以看到加压后的明文
      xiaohui_pcap.png