X86 使用GDB读取msr

X86 使用GDB读取msr,x86,gdb,x86-64,memory-segmentation,msr,X86,Gdb,X86 64,Memory Segmentation,Msr,在使用GDB调试程序时,是否有办法读取x86-64型号特定寄存器,特别是IA32_FS_BASE和IA32_GS_BASE 不太可取的是使用动态检测包(如Intel的Pintool)的解决方案,但仍然会受到欢迎。x86可以使用指令读取,这是一个很好的解决方案。在Linux中,用户线程可以调用一些系统调用来读取FS_BASE和GS_BASE。它们没有库包装器,所以您必须自己编写代码来调用它们 这是C++中的一种方法,你把这些全局函数定义添加到程序: #include <cstdint>

在使用GDB调试程序时,是否有办法读取x86-64型号特定寄存器,特别是IA32_FS_BASE和IA32_GS_BASE

不太可取的是使用动态检测包(如Intel的Pintool)的解决方案,但仍然会受到欢迎。

x86可以使用指令读取,这是一个很好的解决方案。在Linux中,用户线程可以调用一些系统调用来读取FS_BASE和GS_BASE。它们没有库包装器,所以您必须自己编写代码来调用它们

这是C++中的一种方法,你把这些全局函数定义添加到程序:

#include <cstdint>
#include <asm/prctl.h>
#include <sys/syscall.h>
namespace x86 {
    uint64_t fs_base() {
        uint64_t fs_base;
        syscall(SYS_arch_prctl,ARCH_GET_FS,&fs_base);
        return fs_base;
    }
    uint64_t gs_base() {
        uint64_t gs_base;
        syscall(SYS_arch_prctl,ARCH_GET_GS,&gs_base);
        return gs_base;
    }
}

如果您不想更改代码(或者如果代码不可用),您可以通过以下方式执行类似于amdn答案的操作。调用arch_prctl需要一个指向uint64_t的指针,我使用堆栈空部分的地址(当前堆栈指针下8个字节)。调用返回后,读取存储在该位置的8字节值

使用的常量:ARCH\u GET\u FS=0x1003,ARCH\u GET\u GS=0x1004

(gdb) p $rsp
$1 = (void *)0x7fffffffe6f0

(gdb) call arch_prctl(0x1003, $rsp - 0x8)    
$2 = 0 
(gdb) x /gx $rsp - 0x8
0x7fffffffe6e8: 0x00007ffff7fe0700   => IA32_FS_BASE

(gdb) call arch_prctl(0x1004, $rsp - 0x8)
$3 = 0 
(gdb) x /gx $rsp - 0x8
0x7fffffffe6e8: 0x0000000000000000   => IA32_GS_BASE

自gdb 8以来,寄存器
$fs_base
$gs_base
也可用。这些也可以在代码转储中工作,而不仅仅是实时程序。

最近的x86硬件还具有和WRFSBASE,用于读取基本FS/GS基本注册表的用户空间。就像对于gdb经验不太丰富的人(如我)的示例一样:
pwndbg>i r$FS_base
prints
FS_base 0x7f28edbd7540 139813764035904
(gdb) p $rsp
$1 = (void *)0x7fffffffe6f0

(gdb) call arch_prctl(0x1003, $rsp - 0x8)    
$2 = 0 
(gdb) x /gx $rsp - 0x8
0x7fffffffe6e8: 0x00007ffff7fe0700   => IA32_FS_BASE

(gdb) call arch_prctl(0x1004, $rsp - 0x8)
$3 = 0 
(gdb) x /gx $rsp - 0x8
0x7fffffffe6e8: 0x0000000000000000   => IA32_GS_BASE