aliases 命令

列举出所有的简写命令(别名)

gef➤  aliases
[+] Aliases defined:
fmtstr-helper                   →  format-string-helper
telescope                       →  dereference
dps                             →  dereference
dq                              →  hexdump qword
dd                              →  hexdump dword
dw                              →  hexdump word
dc                              →  hexdump byte
cs-dis                          →  capstone-disassemble
ctx                             →  context
start-break                     →  entry-break
ps                              →  process-search
[...]

创建/删除 简写命令(别名)

GEF定义了自己的别名机制,该机制覆盖了GDB提供的传统别名。

用户可以通过编辑位于~/.gef.rc的GEF配置文件来创建/修改/删除别名。

别名必须位于配置文件的“aliases”部分中。

创建新别名就像在本节中创建新条目一样简单:

$ nano ~/.gef.rc
[...]
[aliases]
my-new-alias = gdb-or-gef-command <arg1> <arg2> <etc...>

加入 PEDA 或 WinDBG的喜好设定

例如对于那些使用WinDBG并喜欢其命令的人(比如我),可以通过GEF别名将它们集成到GDB中,如下所示:

$ nano ~/.gef.rc
[...]
[aliases]
# some windbg aliases
dps = dereference
dq = hexdump qword
dd = hexdump dword
dw = hexdump word
dc = hexdump byte
dt = pcustom
bl = info breakpoints
bp = break
be = enable breakpoints
bd = disable breakpoints
bc = delete breakpoints
tbp = tbreak
tba = thbreak
pa = advance
ptc = finish
t = stepi
p = nexti
g = gef run
uf = disassemble

注意:Gef本身就已经支持了这里面的许多别名 (例如eb命令)。

这里有一些PEDA别名用于过去使用PEDA的人。

# some peda aliases
telescope = dereference
start = entry-break
stack = dereference $sp 10
argv = show args
kp = info stack
findmem = search-pattern

下次加载GDB(和GEF)时将加载这些新增的别名。 或者您可以使用以下命令强制GEF重新加载设置:

gef➤  gef restore

aslr 命令

轻松的在被调试的二进制文件上检查,启用或禁用ASLR。

检查ASLR启用状态:

gef➤  aslr
ASLR is currently disabled

启用ASLR:

gef➤  aslr on
[+] Enabling ASLR
gef➤  aslr
ASLR is currently enabled

禁用ASLR:

gef➤  aslr off
[+] Disabling ASLR

注意: 此命令不能影响已加载的进程,以后GDB将附加到该进程。 禁用随机化的唯一方法是设置内核设置/proc/sys/kernel/randomize_va_space 为0。

assemble 命令

如果您已经安装了keystone,那么gef将提供一个方便的命令来将本机指令直接组装到您当前正在调试的体系结构的操作码上。

通过 assemble 或它的别名来调用该命令 asm:

gef➤ asm [INSTRUCTION [; INSTRUCTION ...]]

mark

使用-l LOCATION选项,gef会将keystone生成的汇编代码直接写入指定的内存位置。 这使得简单地覆盖操作码非常方便。

mark

canary 命令

如果使用Smash Stack Protector(SSP)编译当前调试的进程即-fstack-protector标志已传递给编译器,则此命令将显示该canary的值。 这样可以方便地避免在内存中手动搜索此值。

命令canary不接受任何参数。

gef➤ canary

mark

capstone-disassemble 命令

如果已安装 capstone 库及其Python绑定,则可以使用它来反汇编调试会话中的任何内存。 这个插件的创建是为了提供“GDB”的反汇编功能的替代方案,它有时会让事情变得混乱。

您可以使用其别名cs-disassemblecs加要反汇编的位置。 如果没有指定位置,它将使用$pc

gef➤ cs main

mark

checksec 命令

checksec 命令来源于 checksec.sh。 它提供了一种方便的方法来确定在二进制文件中启用了哪些安全保护。

您可以在当前调试的进程上使用该命令:

gef➤  checksec
[+] checksec for '/vagrant/test-bin'
Canary:                                           No
NX Support:                                       Yes
PIE Support:                                      No
No RPATH:                                         Yes
No RUNPATH:                                       Yes
Partial RelRO:                                    Yes
Full RelRO:                                       No

或者直接指定要检查的二进制文件,例如:

$ gdb -ex "checksec ./tests/test-x86"

config 命令

除了可以从_~/.gef.rc~读取配置外, 还可以在运行时使用gef config命令配置gef

要查看加载的所有命令的所有设置:

gef➤  gef config

mark

或者获取某一个设置项的值:

gef➤  gef config pcustom.struct_path

当然,您可以编辑这些设置的值。 例如,如果要在抵达断点显示当前上下文之前清除屏幕:

gef➤  gef config context.clear_screen 1

要将GEF的当前设置保存到系统,以使这些选项在所有未来的GEF会话中保持不变,只需运行:

gef➤  gef save
[+] Configuration saved to '/home/vagrant/.gef.rc'

启动时,如果gef找到文件${HOME}/.gef.rc,它将自动加载其值。

要在会话期间重新加载设置,只需运行:

gef➤  gef restore
[+] Configuration from '/home/hugsy/.gef.rc' restored

您也可以在gdb会话之外调整此配置文件以满足您的需要。

context 命令

mark

gef(与PEDAfG! famous gdbinit不同)在遇到断点时提供全面的上下文菜单。

  • 寄存器上下文框显示当前寄存器值。 红色值表示自上次执行停止以来该寄存器的值已更改。 它可以方便地跟踪值。 也可以通过reg命令访问和/或取消引用寄存器值。
  • 堆栈上下文框显示堆栈指针寄存器指向的内存中的10个(默认情况下可以调整)条目。 如果这些值是指针,则它们被连续解除引用。
  • 代码上下文框显示要执行的下一条指令,默认显示10条指令(默认情况下可以调整)。

编辑上下文布局

gef允许您通过重新排列显示上下文的顺序来配置您自己的显示设置。

gef➤ gef config context.layout

目前有6个部分可以显示:

  • legend : 颜色代码的文字说明
  • regs : 寄存器的状态
  • stack : $sp 寄存器指向的内存内容
  • code : 正在执行的代码
  • args : 如果在函数调用处停止,则打印调用参数
  • source : 如果用source编译,这将显示相应的源代码行
  • threads : 所有线程
  • trace : 执行调用跟踪
  • extra : 如果检测到漏洞(易受攻击的格式字符串,堆漏洞等),它将显示在此窗格中
  • memory : 查看任意内存位置

要隐藏一个部分,只需使用context.layout设置,并在部分名称前加上-或者省略它。

gef➤ gef config context.layout "-legend regs stack code args -source -threads -trace extra memory"

此配置不会显示sourcethreadstrace部分。

memory窗格将显示memory命令指定的所有位置的内容。 例如,

gef➤ memory watch $sp 0x40 byte

这将打印堆栈的0x40字节的hexdump版本。 此命令便于跟踪内存中任意位置的变化。 跟踪位置可以使用memory unwatch逐个删除,或者与memory reset一起删除。

大多数部分的大小也可以自定义:

  • nb_lines_stack :配置要显示的堆栈行数。
  • nb_lines_backtrack :配置要显示的回溯线数。
  • nb_lines_codenb_lines_code_prev :分别配置在PC之后和之前显示的行数。
  • context.nb_lines_threads :确定线程窗格内显示的行数。 在调试大量多线程应用程序(apache2,firefox等)时,这很方便。 它接收一个整数作为值:如果该值为“-1”,则将显示所有线程状态。 否则,如果该值设置为“N”,则最多将显示“N”个线程状态。

要使堆栈在顶部显示最大堆栈地址(即向下增加堆栈),请启用以下设置:

gef➤ gef config context.grow_stack_down True

如果保存的指令指针不在显示的堆栈部分内,则创建一个包含已保存的ip并且根据架构指示帧指针的部分。

0x00007fffffffc9e8│+0x00: 0x00007ffff7a2d830  →  <__main+240> mov edi, eax    ($current_frame_savedip)
0x00007fffffffc9e0│+0x00: 0x00000000004008c0  →  <__init+0> push r15    ← $rbp
. . . (440 bytes skipped)
0x00007fffffffc7e8│+0x38: 0x0000000000000000
0x00007fffffffc7e0│+0x30: 0x0000000000000026 ("&"?)
0x00007fffffffc7d8│+0x28: 0x0000000001958ac0
0x00007fffffffc7d0│+0x20: 0x00007ffff7ffa2b0  →  0x5f6f7364765f5f00
0x00007fffffffc7c8│+0x18: 0x00007fff00000000
0x00007fffffffc7c0│+0x10: 0x00007fffffffc950  →  0x0000000000000000
0x00007fffffffc7b8│+0x08: 0x0000000000000000
0x00007fffffffc7b0│+0x00: 0x00007fffffffc7e4  →  0x0000000000000000      ← $rsp

将上下文输出重定向到另一个 TTY/file

默认情况下,gef上下文将显示在当前TTY上。 这可以通过设置context.redirect变量来覆盖,以将上下文发送到另一个部分。

为此,请使用gef config选择你希望上下文重定向到的TTY/file/socket等。

在提示符中输入命令tty

$ tty
/dev/pts/0

接下来我们把结果告诉 gef !

gef➤ gef config context.redirect /dev/pts/0

成功: mark

要恢复正常,请删除以下值:

gef➤ gef config context.redirect ""

举例

  • 首先显示代码部分,然后寄存器,栈,隐藏其他所有内容:
gef➤ gef config context.layout "code regs stack"
  • 在抵达断点时停止显示上下文部分:
gef➤ gef config context.enable 0
  • 在抵达断点时显示上下文部分之前清除屏幕:
gef➤ gef config context.clear_screen 1
  • 不要对regs部分中的寄存器取消引用(更紧凑):
gef➤ gef config context.show_registers_raw 1
  • 不要“显示”被调用的函数的开头。
gef➤  gef config context.peek_calls False
  • 从寄存器视图中隐藏指定寄存器。
gef➤  gef config context.ignore_registers "$cs $ds $gs"

dereference 命令

dereference命令(也就是PEDA中的别名telescope)旨在简化GDB中地址的解除引用,以确定它实际指向的内容。

这是一个有用的便利功能,可以在GDB中使用连续的“x / x”手动跟踪值。

“dereference`需要一个强制参数,一个地址(或符号或寄存器等)来取消引用:

gef➤  dereference $sp
0x00007fffffffe258│+0x00: 0x0000000000400489  →  hlt     ← $rsp
gef➤  telescope 0x7ffff7b9d8b9
0x00007ffff7b9d8b9│+0x00: 0x0068732f6e69622f ("/bin/sh"?)

它还可以选择接受第二个参数,即取消引用的连续地址数(默认为“1”)。

例如,如果要取消引用函数上下文中的所有堆栈条目(在64位体系结构上):

gef➤  p ($rbp - $rsp)/8
$3 = 4
gef➤  dereference $rsp 5
0x00007fffffffe170│+0x00: 0x0000000000400690  →  push r15        ← $rsp
0x00007fffffffe178│+0x08: 0x0000000000400460  →  xor ebp, ebp
0x00007fffffffe180│+0x10: 0x00007fffffffe270  →  0x1
0x00007fffffffe188│+0x18: 0x1
0x00007fffffffe190│+0x20: 0x0000000000400690  →  push r15        ← $rbp

edit-flags 命令

edit-flags命令(别名:flags)提供了一种快速且易于理解的方式来查看和编辑支持它的体系结构的标志寄存器。 如果没有参数,该命令将只返回一个人性化的寄存器标志显示。

可以按照以下语法提供一个或多个参数:

gef➤ flags [(+|-|~)FLAGNAME ...]

其中FLAGNAME是标志的名称(不区分大小写),而+|-|~表示是否设置,取消设置或切换标志的操作。

例如,在x86架构上,如果我们不想进行条件跳转(例如jz指令),但我们想要设置Carry标志,只需使用:

gef➤ flags -ZERO +CARRY

elf-info 命令

elf-info(别名elf)提供了有关当前加载的ELF二进制文件的一些基本信息:

gef➤  elf
Magic                 : 7f 45 4c 46
Class                 : 0x2 - 64-bit
Endianness            : 0x1 - Little-Endian
Version               : 0x1
OS ABI                : 0x0 - System V
ABI Version           : 0x0
Type                  : 0x2 - Executable
Machine               : 0x3e - x86-64
Program Header Table  : 0x0000000000000040
Section Header Table  : 0x0000000000000c98
Header Table          : 0x0000000000000040
ELF Version           : 0x1
Header size           : 0 (0x0)
Entry point           : 0x0000000000400460

entry-break 命令

entry-break(别名start)命令的目标是在二进制文件中可用的最明显的入口点找到并中断。 由于二进制文件将开始运行,因此一些“PLT”条目也将被解析,从而使进一步的调试变得更容易。

它将执行以下操作:

1.查找main。 如果找到,设置临时断点并继续。
2.否则,它会查找__libc_start_main。 如果找到,设置临时断点并继续。
3.最后,如果找不到前两个符号,它将从ELF头获取入口点,设置断点并运行。 如果ELF二进制文件具有有效结构,则此情况永远不会失败。

mark

$(eval) 命令

$命令试图模仿WinDBG中的?命令。

当提供一个参数时,它将评估表达式,并尝试以各种格式显示结果:

gef➤  $ $pc+1
93824992252977
0x555555559431
0b10101010101010101010101010101011001010000110001
b'UUUU\x941'
b'1\x94UUUU'

gef➤  $ -0x1000
-4096
0xfffffffffffff000
0b1111111111111111111111111111111111111111111111111111000000000000
b'\xff\xff\xff\xff\xff\xff\xf0\x00'
b'\x00\xf0\xff\xff\xff\xff\xff\xff'

有两个参数,它只会计算它们之间的差值:

gef➤  vmmap libc
Start              End                Offset             Perm
0x00007ffff7812000 0x00007ffff79a7000 0x0000000000000000 r-x /lib/x86_64-linux-gnu/libc-2.24.so
0x00007ffff79a7000 0x00007ffff7ba7000 0x0000000000195000 --- /lib/x86_64-linux-gnu/libc-2.24.so
0x00007ffff7ba7000 0x00007ffff7bab000 0x0000000000195000 r-- /lib/x86_64-linux-gnu/libc-2.24.so
0x00007ffff7bab000 0x00007ffff7bad000 0x0000000000199000 rw- /lib/x86_64-linux-gnu/libc-2.24.so

gef➤  $ 0x00007ffff7812000 0x00007ffff79a7000
-1658880
1658880

gef➤  $ 1658880
1658880
0x195000
0b110010101000000000000
b'\x19P\x00'
b'\x00P\x19'

format-string-helper 命令

format-string-helper命令将创建一个GEF特定类型的断点,专门用于在使用GlibC库时检测可能不安全的格式字符串。

它将针对多个目标使用此新断点,包括:

  • printf()
  • sprintf()
  • fprintf()
  • snprintf()
  • vsnprintf()

只需调用该命令即可启用此功能。

“fmtstr-helper`是一个较短的别名。

gef➤ fmtstr-helper

然后开始执行。

gef➤ r

如果找到潜在的不安全条目,则断点将触发,停止进程执行,显示触发的原因以及关联的上下文。

mark

functions 命令

functions命令将列出GEF提供的所有 便利功能

  • $_bss([offset]) — 返回当前的bss基址加上给定的偏移量。
  • $_got([offset]) — 返回当前的bss基址加上给定的偏移量。
  • $_heap([offset]) — 返回当前堆基地址加上可选的偏移量。
  • $_pie([offset]) — 返回当前的PIE基地址和可选的偏移量。
  • $_stack([offset]) — 返回当前栈基址加上可选的偏移量。

这些函数可以用作其他命令的参数,以动态计算值。

gef➤  deref $_heap() l4
0x0000000000602000│+0x00: 0x0000000000000000     ← $r8
0x0000000000602008│+0x08: 0x0000000000000021 ("!"?)
0x0000000000602010│+0x10: 0x0000000000000000     ← $rax, $rdx
0x0000000000602018│+0x18: 0x0000000000000000
gef➤  deref $_heap(0x20) l4
0x0000000000602020│+0x00: 0x0000000000000000     ← $rsi
0x0000000000602028│+0x08: 0x0000000000020fe1
0x0000000000602030│+0x10: 0x0000000000000000
0x0000000000602038│+0x18: 0x0000000000000000

gef-remote 命令

可以在远程调试环境中使用gef。 所需文件将自动下载并缓存在临时目录(大多数Unix系统上的/tmp/gef)中。如果更改目标文件,请记得手动删除缓存,否则gef将使用旧的版本。

使用本地副本

如果你想远程调试你已经拥有的二进制文件,你只需要告诉gdb在哪里找到调试信息。

例如,如果我们想调试uname,我们在服务器上执行:

$ gdbserver 0.0.0.0:1234 /bin/uname
Process /bin/uname created; pid = 32280
Listening on port 1234

mark

在客户端上,只需运行gdb

$ gdb /bin/uname
gef➤ target remote 192.168.56.1:1234
Process /bin/uname created; pid = 10851
Listening on port 1234

或者

$ gdb
gef➤ file /bin/uname
gef➤ target remote 192.168.56.1:1234

没有本地副本

可以使用gdb内部函数来复制我们的目标二进制文件。

按照前面的例子,如果我们想调试uname,运行gdb并连接到我们的gdbserver。 为了能够在/proc结构中找到正确的进程,命令gef-remote需要1个参数,即目标主机和端口。 必须提供选项-p并指示远程主机上的进程PID,仅当使用扩展模式(-E)时。

$ gdb
gef➤ gef-remote 192.168.56.1:1234
[+] Connected to '192.168.56.1:1234'
[+] Downloading remote information
[+] Remote information loaded, remember to clean '/tmp/gef/10851' when your session is over

正如您所看到的,如果找不到调试信息,gef将尝试自动下载目标文件并存储在本地临时目录中(在大多数Unix的/tmp上)。 如果成功,它将自动将调试信息加载到gdb并继续调试。

mark

然后,您可以将下载的文件重新用于将来的调试会话,在IDA使用它等。 这使得整个远程调试过程(特别是对于Android应用程序)变得很简单。

QEMU用户模式

虽然GDB通过QEMU用户工作,但QEMU仅支持gdbremote协议中存在的所有命令的有限子集。 例如,不支持诸如remote getremote put(分别从远程目标下载和上载文件)的命令。 因此,gef的默认remote模式也不起作用,因为gef将无法获取远程procfs的内容。

为了避免这种情况并且仍然享受QEMU用户的gef功能,可以人工添加一个简单的存根,使用geq-remote选项-q选项。 请注意,您需要首先正确设置架构:

$ qemu-arm -g 1234 ./my/arm/binary
$ gdb-multiarch ./my/arm/binary
gef➤  set architecture arm
gef➤  gef-remote -q localhost:1234

mark

heap 命令

heap命令提供有关指定为参数的堆块的信息。 目前,它只支持GlibC堆格式 (参见 this link 获取malloc结构信息)。子命令的语法很简单:

gef➤ heap <sub_commands>

heap chunks 命令

展示堆段的所有chunks

gef➤ heap chunks

在某些情况下,分配将从内存页的头立即开始。 如果是,请指定第一个块的基址,如下所示:

gef➤ heap chunks <LOCATION>

mark

heap chunk 命令

此命令提供Glibc malloc-ed chunked的可视信息。 只需将地址提供给chunk 的用户内存指针,以显示与特定chunk 相关的信息:

gef➤ heap chunk <LOCATION>

mark

heap arenas 命令

多线程程序有不同的分配区,而且main_arena的知识还不够。 gef因此提供arena子命令,以帮助您在调用命令时列出程序中分配的所有分配区。

mark

heap set-arena 命令

如果调试符号不存在(例如静态剥离的二进制文件),则可以指示GEF使用以下命令在不同的位置找到main_arena

gef➤ heap set-arena <LOCATION>

如果分配区地址正确,则所有heap命令都将起作用,并使用指定的地址为main_arena

heap bins 命令

Glibc使用bins来保存已被freechunk。 这是因为通过sbrk(需要系统调用)进行分配开销很大。 Glibc使用这些bins来记住以前分配的chunk。 因为bin是单链表或双链表,我发现总是查询gdb以获取指针地址,取消引用它,获取值chunk等等是非常痛苦的…所以我决定实现heap bin 子命令,允许获取以下信息:

  • fastbins
  • bins
    • unsorted
    • small bins
    • large bins

heap bins fast 命令

在利用堆损坏漏洞时,有时可以方便地了解fastbinsY数组的状态。

fast子命令通过显示此列表中的fastbins列表来帮助实现。 没有任何其他参数,它将显示main_arena的信息。 它接受一个可选参数,即另一个arena的地址(您可以使用heap arenas轻松找到它)。

gef➤ heap bins fast
[+] FastbinsY of arena 0x7ffff7dd5b20
Fastbin[0] 0x00
Fastbin[1]  →  FreeChunk(0x600310)  →  FreeChunk(0x600350)
Fastbin[2] 0x00
Fastbin[3] 0x00
Fastbin[4] 0x00
Fastbin[5] 0x00
Fastbin[6] 0x00
Fastbin[7] 0x00
Fastbin[8] 0x00
Fastbin[9] 0x00

其他的 heap bins X 命令

heap bins的所有其他子命令的工作方式与fast相同。 如果没有提供参数,gef将回退到main_arena。 否则,它将使用指向malloc_state结构的基址的地址并相应地打印出信息。

heap-analysis-helper 命令

heap-analysis-helper 命令旨在通过跟踪和分析内存块的分配和释放来帮助识别Glibc堆不一致的过程。

目前,可以跟踪以下问题:

  • NULL free
  • Use-after-Free
  • Double Free
  • Heap overlap

可以通过运行命令简单地激活帮助程序heap-analysis-helper

gef➤ heap-analysis
[+] Tracking malloc()
[+] Tracking free()
[+] Disabling hardware watchpoints (this may increase the latency)
[+] Dynamic breakpoints correctly setup, GEF will break execution if a possible vulnerabity is found.
[+] To disable, clear the malloc/free breakpoints (`delete breakpoints`) and restore hardware breakpoints (`set can-use-hw-watchpoints 1`)

帮助程序将创建专门设计的破坏程序以保持分配,从而发现潜在的漏洞。一旦激活,只需清除__GI___libc_free()__GI___libc_malloc()即可禁用堆分析断点。也可以通过gef config命令启用/禁用手动准时检查。

允许以下设置:

  • check_null_free: 在遇到free(NULL)时中断执行(默认情况下禁用);
  • check_double_free: 在遇到double free时中断执行;

mark

  • check_weird_free: 针对执行free()非跟踪指针调用时 ;
  • check_uaf: 在遇到可能的Use-after-Free条件时中断执行。

mark

就像格式字符串漏洞助手一样,heap-analysis-helper 可能无法检测复杂的堆场景和/或提供一些误报警报。必须手动确定每个发现。

heap-analysis-helper还可以用来简单地跟踪的内存块的分配和释放。可以通过将上述所有配置设置为False来简单地启用跟踪:

gef➤  gef config heap-analysis-helper.check_double_free False
gef➤  gef config heap-analysis-helper.check_free_null False
gef➤  gef config heap-analysis-helper.check_weird_free False
gef➤  gef config heap-analysis-helper.check_uaf False

然后,gef不会通知您检测到的任何不一致,而只是在分配/释放块时显示清除消息。

mark

要获取有关当前跟踪的块的信息,请使用show 子命令:

gef➤  heap-analysis-helper show

mark

help 命令

显示已加载命令的帮助菜单。

mark

hexdump 命令

模仿WinDBG命令。

此命令至少需要2个参数,表示数据的格式,以及用作打印hexdump的位置的值/地址/符号。可选的第3个参数用于指定要显示的qword / dword / word / bytes的数量。

该命令默认提供与WinDBG兼容的别名:

  • hexdump qword -> dq
  • hexdump dword -> dd
  • hexdump word -> dw
  • hexdump byte -> db

如果字节是可打印的,hexdump byte也会尝试显示ASCII字符值(类似于Linux 上的hexdump -C命令)。

语法如下:

hexdump (qword|dword|word|byte) LOCATION L[SIZE] [UP|DOWN]

例子:

  • 显示 4 QWORD 的 $pc:
gef➤  dq $pc l4
0x7ffff7a5c1c0+0000 │ 0x4855544155415641
0x7ffff7a5c1c0+0008 │ 0x0090ec814853cd89
0x7ffff7a5c1c0+0010 │ 0x377d6f058b480000
0x7ffff7a5c1c0+0018 │ 0x748918247c894800
  • 显示 32 bytes 的堆栈中的某个位置:
gef➤  db 0x00007fffffffe5e5 l32
0x00007fffffffe5e5     2f 68 6f 6d 65 2f 68 75 67 73 79 2f 63 6f 64 65     /home/hugsy/code
0x00007fffffffe5f5     2f 67 65 66 2f 74 65 73 74 73 2f 77 69 6e 00 41     /gef/tests/win.A

hijack-fd 命令

gef可用于修改已调试进程的文件描述符。新文件描述符可以指向文件,管道,套接字,设备等。

要使用它,只需运行

gef➤ hijack-fd FDNUM NEWFILE

例如,

gef➤ hijack-fd 1 /dev/null

将修改当前进程文件描述符以将STDOUT重定向到 /dev/null

检查此asciicast以获取可视化示例:mark

此命令还支持连接到ip:port(如果它作为参数提供)。例如

gef➤ hijack-fd 0 localhost:8888

将STDIN重定向到localhost:8888

还有一个例子: mark

ida-interact 命令

gef提供了一个简单的XML-RPC客户端,用于与在特定IDA Python插件中运行的服务器通信ida_gef.py(可在这里免费下载 )

只需下载此脚本,然后在IDA中运行即可。当服务器运行时,您将在“输出”窗口中看到一个文本,例如:

[+] Creating new thread for XMLRPC server: Thread-1
[+] Starting XMLRPC server: 0.0.0.0:1337
[+] Registered 6 functions.

这表明XML-RPC服务器已准备就绪并正在侦听。

gef可以通过ida-interact命令与它进行交互。此命令接收要执行的函数的名称作为第一个参数,所有其他参数是远程函数的参数。

要枚举可用的功能,只需运行

gef➤  ida-interact -h

mark

现在,要执行RPC,请使用命令ida-interact并附加其参数(如果需要)。

例如:

gef➤  ida ida.set_color 0x40061E

将编辑远程IDB并设置0x40061E处的背景颜色为0x005500(默认值)。

另一个方便的例子是直接从gef向IDA中添加注释:

gef➤  ida ida.add_comment 0x40060C "<<<--- stack overflow"
[+] Success

结果:

mark

请使用–help参数查看所有可用的方法及其语法。

值得注意的是, Binary Ninja 支持已被添加:

mark

通过使用脚本 binja_gef.py.

ksymaddr 命令

ksymaddr有助于按名称查找内核符号。

语法很简单:

ksymaddr <PATTERN>

例如,

gef➤  ksymaddr commit_creds
[+] Found matching symbol for 'commit_creds' at 0xffffffff8f495740 (type=T)
[*] Found partial match for 'commit_creds' at 0xffffffff8f495740 (type=T): commit_creds
[*] Found partial match for 'commit_creds' at 0xffffffff8fc71ee0 (type=R): __ksymtab_commit_creds
[*] Found partial match for 'commit_creds' at 0xffffffff8fc8d008 (type=r): __kcrctab_commit_creds
[*] Found partial match for 'commit_creds' at 0xffffffff8fc9bfcd (type=r): __kstrtab_commit_creds

memory 命令

只要在上下文布局中启用了“内存”部分(默认情况下),就可以注册地址,长度和分组大小。

mark

添加一个查看

memory watch <ADDRESS> [SIZE] [(qword|dword|word|byte)]

移除一个查看

memory unwatch <ADDRESS>

列出所有查看

memory list

清楚所有查看

memory clear

nop 命令

nop命令允许您轻松跳过指令。

gef➤ nop [-b NUM_BYTES] [-h] [LOCATION]

LOCATION表示要绕过的指令的地址。 如果未指定,它将使用程序计数器的当前值。

如果输入-b <bytes>,gef将显式修补指定的字节数。 否则它会在目标位置修补whole指令。

patch 命令

将指定的值修补到指定的地址。

此命令自动别名为标准的WinDBG命令:ebewedeqea

gef➤ patch byte $eip 0x90
gef➤ eb 0x8048000 0x41
gef➤ ea 0xbffffd74 "This is a double-escaped string\\x00"

pattern 命令

此命令将创建或搜索一个 De Bruijn 循环模式,以便于确定内存中的偏移量。

应该注意的是,为了更好的兼容性,GEF中实现的算法与pwntools中的算法相同,因此可以结合使用。

创建

子命令create允许创建一个新pattern:

gef➤  pattern create 128
[+] Generating a pattern of 128 bytes
aaaabaaacaaadaaaeaaafaaagaaahaaaiaaajaaakaaalaaamaaanaaaoaaapaaaqaaaraaasaaataaauaaavaaawaaaxaaayaaazaabbaabcaabdaabeaabfaabgaab
[+] Saved as '$_gef0'

该模式可以在以后用作输入。 为了生成这个输入,GET考虑了体系结构的大小(16,32或64位),以生成它。

pwntools的等效命令是

from pwn import *
p = cyclic(128, n=8)

其中n是体系结构的字节数(8位为64位,4位为32位)。

查找

search子命令寻找作为参数给出的值,试图在De Bruijn序列中找到它

gef➤  pattern search 0x6161616161616167
[+] Searching '0x6161616161616167'
[+] Found at offset 48 (little-endian search) likely
[+] Found at offset 41 (big-endian search)

请注意,寄存器也可以作为值传递:

gef➤  pattern search $rbp
[+] Searching '$rbp'
[+] Found at offset 32 (little-endian search) likely
[+] Found at offset 25 (big-endian search)

pcustom 命令

gef 提供了一种创建任何新结构体(以C结构体方式)和应用于当前调试环境的方法。 除了简单地显示已知和用户定义的结构体之外,它还允许将这些结构体应用于当前上下文。 它打算模仿非常有用的 WinDBG 中的dt命令。

这是通过命令pcustom(用于print custom)实现的,或者你可以使用它的别名dt(参考WinDBG命令)。

相关配置

新结构体可以存储在配置给出的位置:

gef➤ gef config pcustom.struct_path

默认情况下,此位置位于 $TEMP/gef/structs (例如 /tmp/user/1000/gef/structs).

可以在一个名为<struct_name> .py的文件中创建为一个简单的ctypes结构体。

您可以将此路径设置为新位置

gef➤ gef config pcustom.struct_path /my/new/location

并保存此更改,以便下次使用gdb时可以直接使用它

gef➤ gef save
[+] Configuration saved to '~/.gef.rc'

使用用户定义的结构体

使用如下命令您可以通过列出现有的自定义结构体

gef➤  dt -l
[+] Listing custom structures:
 →  struct5
 →  struct6

要创建或编辑结构体,请使用dt <struct_name> -e以使用目标结构体生成EDITOR。 如果文件不存在,gef将创建树和文件,并用ctypes模式填充它,你可以立即使用!

gef➤  dt mystruct_t -e
[+] Creating '/tmp/gef/structs/mystruct_t.py' from template

代码可以像任何Python(使用ctypes)代码一样定义。

from ctypes import *

'''
typedef struct {
  int age;
  char name[256];
  int id;
} person_t;
'''

class person_t(Structure):
    _fields_ = [
        ("age",  c_int),
        ("name", c_char * 256),
        ("id", c_int),
    ]

    _values_ = [
        # You can define a function to substitute the value
        ("age", lambda age: "Old" if age > 40 else "Young"),
        # Or alternatively a list of 2-tuples
        ("id", [
            (0, "root"),
            (1, "normal user"),
            (None, "Invalid person")
        ])
    ]

pcustom至少需要一个参数,即结构体的名称。 只有一个参数时,pcustom将转储此结构体的所有字段。

gef➤  dt person_t
+0000 age c_int (x4)  →  Young
+0004 name c_char_Array_256 (x100)
+0104 id c_int (x1)   →  normal user

通过提供地址或GDB符号,gef将把这个用户定义的结构体应用于指定的地址:

mark

这意味着我们现在可以非常轻松地创建新的用户定义结构体

观看Asciinema的演示视频:

asciicast

此外,如果您已成功配置IDA设置(请参阅命令ida-interact),您还可以直接在GDB会话中直接导入在IDA中进行逆向工程的结构体:

mark

然后使用命令ida ImportStructs导入所有结构体,或者ida ImportStruct <StructName>只导入一个特定的结构体:

gef➤  ida ImportStructs
[+] Success

mark

pie 命令

pie命令提供了一种为启用PIE的二进制文件设置断点的有用方法。 pie命令提供我们称之为“PIE断点”的东西。 PIE断点只是一个虚拟断点,当进程附加时,它将被设置为实际断点。 PIE断点的地址是二进制基址的偏移量。

请注意,您需要使用整个PIE命令序列来支持PIE断点,尤其是pie命令提供的“附加”命令,如pie attachpie run等。

用法:

gef➤ pie <sub_commands>

pie breakpoint 命令

此命令设置新的PIE断点。 它可以像gdb中的普通breakpoint命令一样使用。 该位置只是与基址的偏移量。 此命令后不会立即设置断点。 相反,它将在您使用pie attachpie runpie remote实际附加到进程时设置,因此它可以解析正确的基址。

用法:

gef➤ pie breakpoint <LOCATION>

pie info 命令

由于PIE断点不是真正的断点,因此该命令提供了一种观察所有PIE断点状态的方法。

这就像gdb中的info breakpoint

gef➤  pie info
VNum    Num Addr
1   N/A 0xdeadbeef

VNum是虚拟号码,它是PIE断点的编号。 Num是gdb中相应实际断点数的编号。 地址是PIE断点的地址。

您可以忽略VNum参数以获取所有PIE断点的信息。

用法:

gef➤  pie info [VNum]

pie delete 命令

给定该PIE断点的VNum时,此命令将删除PIE断点。

用法:

gef➤  pie delete <VNum>

pie attach 命令

与gdb的attach命令相同。 如果您有PIE断点,请始终使用此命令而不是原始attach。 这将在附加时设置真正的断点。

用法与attach相同。

pie remote 命令

与gdb的remote命令相同。 如果您有PIE断点,请始终使用此命令而不是原始remote。 这将在附加时设置真正的断点。

用法与remote相同。

pie run 命令

与gdb的run命令相同。 如果您有PIE断点,请始终使用命令而不是原始run。 这将在附加时设置真正的断点。

用法与run相同。

print-format 命令

  • 命令print-format(别名pf)将根据指定的编程语言的语法将任意位置转储为字节数组。 目前,支持的输出语言是
    • Python (py – 默认)
    • C (c)
    • Assembly (asm)
    • Javascript (js)
gef➤  print-format -h
[+] print-format [-f FORMAT] [-b BITSIZE] [-l LENGTH] [-c] [-h] LOCATION
        -f FORMAT specifies the output format for programming language, avaliable value is py, c, js, asm (default py).
        -b BITSIZE sepecifies size of bit, avaliable values is 8, 16, 32, 64 (default is 8).
        -l LENGTH specifies length of array (default is 256).
        -c The result of data will copied to clipboard (requires xclip)
        LOCATION specifies where the address of bytes is stored.

例如,此命令将从$rsp转储10个字节,并将结果复制到剪贴板。

gef➤  print-format -f py -b 8 -l 10 -c $rsp
[+] Copied to clipboard
buf = [0x87, 0xfa, 0xa3, 0xf7, 0xff, 0x7f, 0x0, 0x0, 0x30, 0xe6]

process-search 命令

process-search(又名ps)是一个方便的命令,用于在主机上列出和过滤进程。 它的目的是在针对分叉过程(例如在新连接上分叉的tcp/listen守护进程)时使调试过程更容易一些。

如果没有参数,它将返回用户可以访问的所有进程:

gef➤  ps
1               root            0.0             0.4             ?           /sbin/init
2               root            0.0             0.0             ?           [kthreadd]
3               root            0.0             0.0             ?           [ksoftirqd/0]
4               root            0.0             0.0             ?           [kworker/0:0]
5               root            0.0             0.0             ?           [kworker/0:0H]
6               root            0.0             0.0             ?           [kworker/u2:0]
7               root            0.0             0.0             ?           [rcu_sched]
8               root            0.0             0.0             ?           [rcuos/0]
9               root            0.0             0.0             ?           [rcu_bh]
10              root            0.0             0.0             ?           [rcuob/0]
11              root            0.0             0.0             ?           [migration/0]
[...]

或者启用过滤器:

gef➤  ps bash
22590           vagrant         0.0             0.8             pts/0       -bash

ps也允许使用以下选项:

  • -ssmart)将丢弃一些进程(属于不同的用户,用作参数的模式而不是命令等)
  • -aattach)将自动附加到找到的第一个进程

因此,例如,如果您的目标进程名为/home/foobar/plop,但现有实例通过socat使用,如

$ socat tcp-l:1234,fork,reuseaddr exec:/home/foobar/plop

每次向tcp/1234打开一个新连接时,plop将被分叉,并且gef可以通过命令轻松附加到它

gef➤  ps -as plop

process-status 命令

此命令用于替换旧命令pidfd

process-status提供了对当前运行进程的详尽描述,通过扩展GDBinfo proc命令提供的信息,以及来自procfs结构的所有信息。

gef➤ ps -s zsh
22879
gef➤ attach 22879
[...]
gef➤ status
[+] Process Information
        PID  →  22879
        Executable  →  /bin/zsh
        Command line  →  '-zsh'
[+] Parent Process Information
        Parent PID  →  4475
        Command line  →  'tmux new -s cool vibe
[+] Children Process Information
        PID  →  26190 (Name: '/bin/sleep', CmdLine: 'sleep 100000')
[+] File Descriptors:
        /proc/22879/fd/0  →  /dev/pts/4
        /proc/22879/fd/1  →  /dev/pts/4
        /proc/22879/fd/2  →  /dev/pts/4
        /proc/22879/fd/10  →  /dev/pts/4
[+] File Descriptors:
        No TCP connections

registers 命令

registers命令将打印所有寄存器并取消引用任何指针。 它没有任何参数。

MIPS主机上的示例:

gef> reg
$zero     : 0x00000000
$at       : 0x00000001
$v0       : 0x7fff6cd8 -> 0x77e5e7f8 -> <__libc_start_main+200>: bnez v0,0x77e5e8a8
$v1       : 0x77ff4490
$a0       : 0x00000001
$a1       : 0x7fff6d94 -> 0x7fff6e85 -> "/root/demo-mips"
$a2       : 0x7fff6d9c -> 0x7fff6e91 -> "SHELL=/bin/bash"
$a3       : 0x00000000
$t0       : 0x77fc26a0 -> 0x0
$t1       : 0x77fc26a0 -> 0x0
$t2       : 0x77fe5000 -> "_dl_fini"
$t3       : 0x77fe5000 -> "_dl_fini"
$t4       : 0xf0000000
$t5       : 0x00000070
$t6       : 0x00000020
$t7       : 0x7fff6bc8 -> 0x0
$s0       : 0x00000000
$s1       : 0x00000000
$s2       : 0x00000000
$s3       : 0x00500000
$s4       : 0x00522f48
$s5       : 0x00522608
$s6       : 0x00000000
$s7       : 0x00000000
$t8       : 0x0000000b
$t9       : 0x004008b0 -> <main>: addiu sp,sp,-32
$k0       : 0x00000000
$k1       : 0x00000000
$s8       : 0x00000000
$status   : 0x0000a413
$badvaddr : 0x77e7a874 -> <__cxa_atexit>: lui gp,0x15
$cause    : 0x10800024
$pc       : 0x004008c4 -> <main+20>: li v0,2
$sp       : 0x7fff6ca0 -> 0x77e4a834 -> 0x29bd
$hi       : 0x000001a5
$lo       : 0x00005e17
$fir      : 0x00739300
$fcsr     : 0x00000000
$ra       : 0x77e5e834 -> <__libc_start_main+260>: lw gp,16(sp)
$gp       : 0x00418b20

reset-cache 命令

这是一个过时的函数,用于重置GEF内部memoize缓存,不需要再从命令行调用它。

这个命令很快就会消失……

ropper 命令

ropper是一个gadget查找工具,可以通过pip轻松安装。 它提供了一个非常方便的--search函数来从正则表达式搜索gadget:

mark

ropper带有一整套选项,所有选项都记录在--help菜单中。

scan 命令

scan搜索位于属于另一个程序的内存映射(haystack)中的地址。

mark

scan需要两个参数,第一个是要搜索的内存部分,第二个是要搜索的内容。 参数是针对进程内存映射的(与vmmap一样,以确定要搜索的内存范围。

search-pattern 命令

gef允许您在在运行时搜索进程内存布局的所有段中的特定字符串。 search-pattern命令,别名grep,旨在直接使用:

gef➤  search-pattern MyPattern

mark

它将提供一个易于理解的特定字符串的发现,包括它/它们被发现的部分,以及与该部分相关的权限。

search-pattern也可用于搜索地址。 为此,只需确保您的字符串以“0x”开头并且是有效的十六进制地址。 例如:

gef➤  search-pattern 0x4005f6

mark

search-pattern命令也可以用作搜索地址交叉引用的方法。 因此,别名xref也指向命令search-pattern。 因此,上面的命令相当于xref 0x4005f6,这使得它更直观。

set-permission 命令

添加此命令是为了便于漏洞利用过程,方法是直接从调试器更改特定内存页上的权限。

默认情况下,GDB不允许您这样做,因此该命令将修改正在调试的二进制文件的代码部分,并添加本机mprotect系统调用存根。 例如,对于x86,将插入以下存根:

pushad
mov eax, mprotect_syscall_num
mov ebx, address_of_the_page
mov ecx, size_of_the_page
mov edx, permission_to_set
int 0x80
popad

在此存根之后添加断点,该点在命中时将恢复原始上下文,允许您继续执行。

mprotectset-permission的别名。 举个例子,在这个二进制文件中将stack设置为READ|WRITE|EXECUTE

mark

运行

gef➤ mprotect 0xfffdd000

就是这样! gef 将使用内存运行时的信息来正确调整整个部分的保护。

mark

或者在PowerPC VM上获得完整的演示视频: mark

shellcode 命令

shellcode是@JonathanSalwan shellcodes数据库的命令行客户端。 它可以用来直接通过GEF搜索和下载你正在寻找的shellcode。 有两个原始子命令,searchget

gef➤ shellcode search arm
[+] Showing matching shellcodes
901     Linux/ARM       Add map in /etc/hosts file - 79 bytes
853     Linux/ARM       chmod("/etc/passwd", 0777) - 39 bytes
854     Linux/ARM       creat("/root/pwned", 0777) - 39 bytes
855     Linux/ARM       execve("/bin/sh", [], [0 vars]) - 35 bytes
729     Linux/ARM       Bind Connect UDP Port 68
730     Linux/ARM       Bindshell port 0x1337
[...]
gef➤ shellcode get 698
[+] Downloading shellcode id=698
[+] Shellcode written as '/tmp/sc-EfcWtM.txt'
gef➤ system cat /tmp/sc-EfcWtM.txt
/*
Title:     Linux/ARM - execve("/bin/sh", [0], [0 vars]) - 27 bytes
Date:      2010-09-05
Tested on: ARM926EJ-S rev 5 (v5l)
Author:    Jonathan Salwan - twitter: @jonathansalwan

shell-storm.org

Shellcode ARM without 0x20, 0x0a and 0x00
[...]

stub 命令

stub命令允许你存根函数,可选择指定返回值。

gef➤  stub [-h] [-r RETVAL] [LOCATION]

LOCATION表示要绕过的功能的地址。 如果未指定,gef将认为程序计数器处的指令是函数的开始。

如果提供了-r RETVAL,gef会将返回值设置为提供的值。 否则,它会将返回值设置为0。

例如,绕过fork()调用是微不足道的。 由于返回值设置为0,因此它实际上将我们放入“子”进程。 必须注意的是,这是一个与经典的“set follow-fork-mode child”不同的行为,因为在这里我们不会产生一个新的进程,我们只是欺骗父进程认为它已经成为了孩子。

例子

绕过 fork() 调用:

  • Without stub: mark
  • With stub: mark

theme 命令

通过改变颜色方案来定制GEF

gef➤  theme
context_title_message                   : red bold
default_title_message                   : red bold
default_title_line                      : green bold
context_title_line                      : green bold
disable_color                           : 0
xinfo_title_message                     : blue bold

改变颜色

您可以使用theme命令更改GEF显示的着色属性。 该命令接受2个参数,要更新的属性的名称及其新的着色值。

颜色可以是以下之一:

  • red
  • green
  • blue
  • yellow
  • gray
  • pink

Color还接受以下属性:

  • bold
  • underline
  • highlight
  • blink

任何其他的值都会被忽略。

gef➤  theme context_title_message blue bold foobar
gef➤  theme
context_title_message                   : blue bold
default_title_message                   : red bold
default_title_line                      : green bold
context_title_line                      : green bold
disable_color                           : 0
xinfo_title_message                     : blue bold

tmux-setup 命令

为了使调试会话更容易,同时更有效,GEF整合了两个命令:

  • tmux-setup
  • screen-setup

这些命令将检查GDB是否从tmux(个别情况下screen)会话中生成,如果是,则将垂直拆分窗格,并将上下文配置为重定向到新窗格,如下所示:

mark

要进行设置,只需输入即可

gef➤ tmux-setup

注意:虽然screen-setup提供了类似的设置,但是screen的结构不允许非常干净的方式来执行此操作。 因此,如果可能,建议使用tmux-setup命令。

trace-run 命令

trace-run命令旨在直接在IDA反汇编程序中提供特定执行所采用的路径。 它应该与IDA脚本ida_color_gdb_trace.py一起使用

它将跟踪并存储执行流程中$pc所取的所有值,从当前值到作为参数提供的值。

gef➤ trace-run <address_of_last_instruction_to_trace>

mark

通过在生成的文本文件上使用脚本ida_color_gdb_trace.py,它将为所采用的路径着色:

mark

unicorn-emulate 命令

如果您已经安装了unicorn 仿真引擎及其Python绑定,gef会集成一个新命令来模拟当前调试环境的指令!

这个命令unicorn-emulate(或它的别名emu)将为你复制当前的内存映射(包括页面权限),默认情况下(即没有任何附加参数),它将模拟指令的执行显示即将执行的(即$pc指向的那个)并显示哪个寄存器被它修改了。

使用-h寻求帮助

gef➤ emu -h

例如,以下命令将仅执行接下来的2条指令:

gef➤ emu -n 2

并显示: mark

在这个例子中,我们可以看到执行后的结果

0x80484db    <main+75>  xor    eax,eax
0x80484dd    <main+77>  add    esp,0x18

寄存器eaxesp被修改。

一个方便的选项是-o /path/to/file.py,它将生成一个嵌入当前执行上下文的纯Python脚本,可以在gef之外重用!这对于处理混淆或解决使用SMT搭建的Crackme非常有用。

vmmap 命令

vmmap显示整个内存空间映射。

mark

正如一位聪明的读者可能已经看到的,内存映射从一个架构到另一个架构不同(这是我首先开始使用GEF的主要原因之一)。 例如,您可以了解到在SPARC体系结构上运行的ELF始终将其.dataheap部分设置为读/写/执行。

vmmap接受一个参数,一个字符串来匹配结果:

mark

xfiles 命令

xfiles是GDB命令的更方便的表示,info files允许您按参数中给出的模式进行过滤。 例如,如果您只想显示代码部分(即.text):

mark

xinfo 命令

xinfo命令显示作为参数给出的特定地址的所有已知信息:

mark

重要说明:出于性能原因,gef会缓存某些结果。 gef将尝试自动刷新自己的缓存,以避免依赖已调试过程的过时信息。 然而,在一些特殊的场景中,gef可能无法检测到一些新事件,使其缓存部分过时。 如果您发现内存映射存在不一致,则可能需要通过运行命令reset-cache强制gef刷新其缓存并获取全新数据。

xor-memory 命令

此命令用于对内存块进行异或。

它的语法是:

xor-memory <display|patch> <address> <size_to_read> <xor_key>

第一个参数(displaypatch)是要执行的操作:

  1. display只显示XOR-ed内存块结果的hexdump,而不写入调试对象的内存。
    gef➤  xor display $rsp 16 1337
    [+] Displaying XOR-ing 0x7fff589b67f8-0x7fff589b6808 with '1337'
    ────────────────────────────────[ Original block ]────────────────────────────────────
    0x00007fff589b67f8     46 4e 40 00 00 00 00 00 00 00 00 00 00 00 00 00     FN@.............
    ────────────────────────────────[ XOR-ed block ]──────────────────────────────────────
    0x00007fff589b67f8     55 79 53 37 13 37 13 37 13 37 13 37 13 37 13 37     UyS7.7.7.7.7.7.7
    
  2. patch将使用xor-ed内容覆盖内存。
    gef➤  xor patch $rsp 16 1337
    [+] Patching XOR-ing 0x7fff589b67f8-0x7fff589b6808 with '1337'
    gef➤  hexdump byte $rsp 16
    0x00007fff589b67f8     55 79 53 37 13 37 13 37 13 37     UyS7.7.7.7
    

版权信息

本中文手册基于GEF – GDB Enhanced Features翻译

原版手册与本中文手册均遵循MIT协议

mark

译者:ERROR404

校对:phosphorus

PDF下载地址

Github 下载

分类: CTF

0 条评论

发表评论

电子邮件地址不会被公开。 必填项已用*标注