You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在GDB中读取gs:0x14的值?调试Canary相关问题

调试Canary时读取gs:0x14的方法

我在调试Canary相关问题时,遇到以下汇编指令:

0x080493c2 <+157>:   mov    eax,DWORD PTR [ebp-0xc]
0x080493c5 <+160>:   xor    eax,DWORD PTR gs:0x14

需要读取gs:0x14对应的值,执行info registers gs得到gs寄存器值为0x63,但显然实际地址不是0x63+0x14,且gdb中无法读取gs_base寄存器(提示无效),请问该如何读取这个值?

补充环境信息

  • GDB版本:GNU gdb (Ubuntu 15.0.50.20240403-0ubuntu1) 15.0.50.20240403-git
  • 目标架构:i386
  • 寄存器信息:
(gdb) i r
eax            0x80493d8           134517720
ecx            0xffffd3a0          -11360
edx            0xffffd3c0          -11328
ebx            0x804c000           134529024
esp            0xffffd370          0xffffd370
ebp            0xffffd388          0xffffd388
esi            0x80494e0           134517984
edi            0xf7ffcb60          -134231200
eip            0x80493f9           0x80493f9 <main+33>
eflags         0x216               [ PF AF IF ]
cs             0x23                35
ss             0x2b                43
ds             0x2b                43
es             0x2b                43
fs             0x0                 0
gs             0x63                99

核心原因

gs是段选择子,不是段基地址。它指向全局描述符表(GDT)或局部描述符表(LDT)中的一个条目,实际内存地址是该条目记录的段基址加上偏移0x14,而非gs寄存器的值直接加0x14。

解决方法

方法1:直接用GDB的段寻址语法读取

GDB支持直接通过段寄存器+偏移的方式访问内存,执行以下命令即可读取gs:0x14的4字节值:

x/wx $gs:0x14

如果需要十进制显示,换成x/wd $gs:0x14;要以变量形式打印,用:

p/x *(unsigned int *)($gs:0x14)

方法2:手动计算段基址(复杂场景备用)

如果方法1失效,可手动从GDT中提取段基址:

  1. 读取GDT的基地址和长度:
    info registers gdtr
    
    输出类似gdtr 0xfffff000 0x7ff,第一个值是GDT基地址,第二个是长度。
  2. 解析gs段选择子:gs的值是0x63,二进制为0000000001100011,高13位是段索引(0x18,计算方式:0x63 >> 3 = 0x18)。
  3. 计算GDT中对应条目的地址:GDT基地址 + 段索引 * 8(每个GDT条目占8字节)。
  4. 读取该条目并提取段基址:x86架构下,GDT条目的第2、3、4、7字节组合成32位基地址。
  5. 最终地址 = 段基址 + 0x14,再用x/wx读取该地址。

方法3:利用程序上下文推导

因为调试的是Canary,gs:0x14通常是栈保护的Canary值。可以通过xor指令的前后寄存器值反推:

  1. 在0x080493c5处下断点:
    b *0x080493c5
    
  2. 运行到断点处,记录当前eax值:
    p/x $eax
    
  3. 单步执行一条指令(ni),再记录eax值:
    ni
    p/x $eax
    
  4. 反推gs:0x14的值:原eax值 XOR 新eax值,因为eax_new = eax_old XOR gs_0x14,所以gs_0x14 = eax_old XOR eax_new。

内容的提问来源于stack exchange,提问作者daisy

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.12 12:12:32