在 x86 上对堆栈金丝雀进行分段

逆向工程 x86 分割
2021-07-06 11:02:18

我刚刚编译了一些 C 代码,gets这些代码使用并反汇编了代码。该平台是 Ubuntu 32 位。

有这 3 行检查金丝雀值是否被篡改。

   0x08048455 <+33>:    mov    edx,DWORD PTR [esp+0x7c]
   0x08048459 <+37>:    xor    edx,DWORD PTR gs:0x14
   0x08048460 <+44>:    je     0x8048467 <main+51>

我设置了一个断点0x08048459,看到gs寄存器的值为 0x33。

我的问题是:

  1. 鉴于 gs 是 0x33,gs:0x14 是什么?0x33 是某个东西的索引吗?它是某种内存位置吗?
  2. 是否有任何 x86 指令将 gs 的值移动到任何其他寄存器?或者也许将它推入堆栈?
1个回答

检查linux 内核源代码中的堆栈保护gs寄存器由内核初始化为一个 percpu 结构,其中包含一个旨在用作堆栈金丝雀的随机值。对于 32 位程序,此堆栈金丝雀位于偏移 20 (0x14) 处。它为每个进程随机化以避免恶意软件能够依赖它始终是相同的值。

0x33 实际上是内核中表的索引,您无权访问,因此从用户态来看它毫无意义。构成 percpu 结构的虚拟内存通过 gs 和 gs 映射到的内核表索引映射到物理内存“某处”,但该物理内存映射到任何可以“正常”寻址的地址,即通过'正常' cs/ds/ss 段。

当您在 google 上搜索段寄存器时,您可能会发现一些信息说“段寄存器左移 4 位,然后添加到偏移量,以产生实际地址”,但这仅适用于实模式Linux 一直使用保护模式您可以在此处找到有关实模式和保护模式下的段的更多详细信息

要读取该值,push gs您可以使用一条指令。还有一个pop gs但如前所述,知道该值对您没有帮助,将值设置为任何内容很可能会导致分段错误。