使用气体,我怎样才能得到特定标签的偏移量?
Using gas, how can I get the offset to a particular label?
我正在使用 pwnlib
编写一个小的 shellcode 来应对挑战。我的 shellcode 需要修改自身以通过应用程序过滤器。我首先用 nasm 写了它,然后做了类似的事情:
sub edx, edx
mov dl, 0x82
add al, do_mov_rdi_rax
sub dword [rax], edx
mov dh, 0x82
add al, do_syscall - do_mov_rdi_rax
sub dword [rax], edx
shr edi, 31
do_mov_rdi_rax:
; mov rsi, rax
; (with 0x82 added to first byte to pass validation)
db 0xca, 0x89, 0xc6
sub eax, eax
do_syscall:
; syscall
; (with 0x82 added to both bytes to pass validation)
db 0x91, 0x87
Pwnlib 使用 gas
,但是,所以我的汇编代码必须符合它的语法。除了显而易见的(//
而不是 ;
,.byte
而不是 db
),我还遇到了最后一个问题:虽然 nasm
愉快地转换了我的标签到整数(对于 add al, do_mov_rdi_rax
和 add al, do_syscall - do_mov_rdi_rax
),gas
一直告诉我它不能表示寻址类型 BFD_RELOC_8
,或类似的东西(我不知何故得到了一个gas
的法语版本,抱歉缺少错误消息)。
如何获取标签的整数地址?我的 shellcode 基于地址 0(并且 gas 被告知 .org 0x0
)。
您正在做的事情很不寻常,看起来它需要 OS X 使用的 Mach-O 对象格式不支持的重定位。问题不在于您试图将标签用作整数,而是您试图将标签用作 8 位整数。这在实践中不是很有用,编译器永远不会做的事情。
如果您真的只想将符号地址的低 8 位(或两个符号之间的差异)添加到 RAX 的低 8 位,您将使用标签作为 32 位整数优先。
例如,您可以先将其移动到另一个 32 位寄存器中:
mov $do_mov_rdi_rax, %ecx
add %cl, %al
...
mov $(do_syscall - do_mov_rdi_rax), %ecx
add %cl, %al
如果您没有可用的寄存器,那么您可以从内存中加载它:
add indirect_do_mov_rdi_rax, %al
...
add indirect_difference, %al
indirect_do_mov_rdi_rax:
.long do_mov_rdi_rax
indirect_difference:
.long do_syscall - do_mov_rdi_rax
如果真的不想使用 8 位算术,而是想使用地址的所有 64 位进行加法运算,那么您可以改用 64 位寄存器 RAX:
add $do_mov_rdi_rax, %rax
...
add $(do_syscall - do_mov_rdi_rax), %rax
由于标签不起作用,我仔细研究了 gas
文档,发现也可以创建表达式符号,并且可以使用 .
来获取位置的地址。事实证明,使用 Mach-O 输出格式,gas
将接受此格式:
.set main, .
sub edx, edx
mov dl, 0x82
add al, do_mov_rdi_rax - main
sub dword [rax], edx
mov dh, 0x82
add al, do_syscall - do_mov_rdi_rax
sub dword [rax], edx
shr edi, 31
.set do_mov_rdi_rax, .
// mov rsi, rax
// (with 0x82 added to first byte to pass validation)
.byte 0xca, 0x89, 0xc6
sub eax, eax
.set do_syscall, .
// syscall
// (with 0x82 added to both bytes to pass validation)
.byte 0x91, 0x87
在第一次添加时,简单地使用 do_mov_rdi_rax
是行不通的,但是使用它与 main
之间的差异就可以完美地工作。 (然而,将 main
替换为文字零不会这样做。)
不过,它还有其他问题:似乎缺乏对 sub dword [rax], edx
的支持。在我的 Mac 上使用 gas 2.25,它得到 assembled 为 sub dword [rax+4], edx
,这是非常错误的。 Xcode 附带的 as
版本拒绝 assemble 它,引用绝对 32 位寻址使用; Debian 的 gas 2.24.90 也拒绝 assemble 它,因为不知何故会有太多的内存引用。因为这都是不正确的,我将坚持使用 shellcode 的 nasm-assembled 二进制版本,而不是使用 pwnlib 的 asm
来编译它。
我正在使用 pwnlib
编写一个小的 shellcode 来应对挑战。我的 shellcode 需要修改自身以通过应用程序过滤器。我首先用 nasm 写了它,然后做了类似的事情:
sub edx, edx
mov dl, 0x82
add al, do_mov_rdi_rax
sub dword [rax], edx
mov dh, 0x82
add al, do_syscall - do_mov_rdi_rax
sub dword [rax], edx
shr edi, 31
do_mov_rdi_rax:
; mov rsi, rax
; (with 0x82 added to first byte to pass validation)
db 0xca, 0x89, 0xc6
sub eax, eax
do_syscall:
; syscall
; (with 0x82 added to both bytes to pass validation)
db 0x91, 0x87
Pwnlib 使用 gas
,但是,所以我的汇编代码必须符合它的语法。除了显而易见的(//
而不是 ;
,.byte
而不是 db
),我还遇到了最后一个问题:虽然 nasm
愉快地转换了我的标签到整数(对于 add al, do_mov_rdi_rax
和 add al, do_syscall - do_mov_rdi_rax
),gas
一直告诉我它不能表示寻址类型 BFD_RELOC_8
,或类似的东西(我不知何故得到了一个gas
的法语版本,抱歉缺少错误消息)。
如何获取标签的整数地址?我的 shellcode 基于地址 0(并且 gas 被告知 .org 0x0
)。
您正在做的事情很不寻常,看起来它需要 OS X 使用的 Mach-O 对象格式不支持的重定位。问题不在于您试图将标签用作整数,而是您试图将标签用作 8 位整数。这在实践中不是很有用,编译器永远不会做的事情。
如果您真的只想将符号地址的低 8 位(或两个符号之间的差异)添加到 RAX 的低 8 位,您将使用标签作为 32 位整数优先。
例如,您可以先将其移动到另一个 32 位寄存器中:
mov $do_mov_rdi_rax, %ecx
add %cl, %al
...
mov $(do_syscall - do_mov_rdi_rax), %ecx
add %cl, %al
如果您没有可用的寄存器,那么您可以从内存中加载它:
add indirect_do_mov_rdi_rax, %al
...
add indirect_difference, %al
indirect_do_mov_rdi_rax:
.long do_mov_rdi_rax
indirect_difference:
.long do_syscall - do_mov_rdi_rax
如果真的不想使用 8 位算术,而是想使用地址的所有 64 位进行加法运算,那么您可以改用 64 位寄存器 RAX:
add $do_mov_rdi_rax, %rax
...
add $(do_syscall - do_mov_rdi_rax), %rax
由于标签不起作用,我仔细研究了 gas
文档,发现也可以创建表达式符号,并且可以使用 .
来获取位置的地址。事实证明,使用 Mach-O 输出格式,gas
将接受此格式:
.set main, .
sub edx, edx
mov dl, 0x82
add al, do_mov_rdi_rax - main
sub dword [rax], edx
mov dh, 0x82
add al, do_syscall - do_mov_rdi_rax
sub dword [rax], edx
shr edi, 31
.set do_mov_rdi_rax, .
// mov rsi, rax
// (with 0x82 added to first byte to pass validation)
.byte 0xca, 0x89, 0xc6
sub eax, eax
.set do_syscall, .
// syscall
// (with 0x82 added to both bytes to pass validation)
.byte 0x91, 0x87
在第一次添加时,简单地使用 do_mov_rdi_rax
是行不通的,但是使用它与 main
之间的差异就可以完美地工作。 (然而,将 main
替换为文字零不会这样做。)
不过,它还有其他问题:似乎缺乏对 sub dword [rax], edx
的支持。在我的 Mac 上使用 gas 2.25,它得到 assembled 为 sub dword [rax+4], edx
,这是非常错误的。 Xcode 附带的 as
版本拒绝 assemble 它,引用绝对 32 位寻址使用; Debian 的 gas 2.24.90 也拒绝 assemble 它,因为不知何故会有太多的内存引用。因为这都是不正确的,我将坚持使用 shellcode 的 nasm-assembled 二进制版本,而不是使用 pwnlib 的 asm
来编译它。