[英]Using gas, how can I get the offset to a particular label?
I'm using pwnlib
to write a small shellcode for a challenge. 我正在使用
pwnlib
编写一个小的Shellcode来应对挑战。 My shellcode needs to modify itself to pass application filters. 我的shellcode需要修改自身才能通过应用程序过滤器。 I first wrote it with nasm, and did something like that:
我首先用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 uses gas
, however, so my assembly code has to conform to its syntax. 但是,Pwnlib使用
gas
,因此我的汇编代码必须符合其语法。 Besides the obvious ( //
instead of ;
, .byte
instead of db
), I'm stuck with one last problem: while nasm
happily converted my labels to integers (for add al, do_mov_rdi_rax
and add al, do_syscall - do_mov_rdi_rax
), gas
keeps telling me that it can't represent addressing type BFD_RELOC_8
, or something like that (I somehow ended up with a French version of gas
, sorry for the lacking error message). 除了显而易见的(
//
而不是;
,. .byte
而不是db
),我还有一个问题: nasm
高兴地将我的标签转换为整数(用于add al, do_mov_rdi_rax
并add al, do_syscall - do_mov_rdi_rax
), gas
一直告诉我它不能代表寻址类型BFD_RELOC_8
或类似的东西(我以某种方式最终以法文版gas
,抱歉缺少错误消息)。
How can I get the address of the labels as integers? 如何获得标签的整数地址? My shellcode is based at address 0 (and gas is told with
.org 0x0
). 我的shellcode基于地址0(并通过
.org 0x0
告知gas)。
Since labels wouldn't work, I dug through the gas
documentation and found that it's also possible to create expression symbols, and that one could use .
由于标签不起作用,我翻阅了
gas
文档,发现也可以创建表达式符号,并且可以使用.
to get the location's address. 获取该位置的地址。 As it turns out, with the Mach-O output format,
gas
will accept this: 事实证明,对于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
On the first add, simply using do_mov_rdi_rax
wouldn't work, but using the difference between it and main
worked perfectly. 在第一个添加项上,仅使用
do_mov_rdi_rax
是行不通的,但是使用它和main
之间的差异可以完美地工作。 (Replacing main
with a literal zero, however, would not do it.) (但是,用字面的零替换
main
不会这样做。)
There are other problems with it, though: support for sub dword [rax], edx
appears to be lacking. 但是,它还有其他问题:对
sub dword [rax], edx
似乎缺少sub dword [rax], edx
。 With gas 2.25 on my Mac, it got assembled as sub dword [rax+4], edx
, which is very wrong. 在Mac上使用gas 2.25时,将其组装为
sub dword [rax+4], edx
,这是非常错误的。 The version of as
that ships with Xcode refuses to assemble it, citing absolute 32-bit addressing use; Xcode附带的
as
版本拒绝汇编,理由是绝对使用32位寻址。 gas 2.24.90 for Debian also refused to assemble it because there would be too many memory references, somehow. Debian的gas 2.24.90也拒绝汇编它,因为某种程度上会存在太多的内存引用。 Because this is all incorrect, I'll stick with a nasm-assembled binary version of the shellcode instead of using pwnlib's
asm
to compile it. 因为这都是不正确的,所以我会坚持使用由nasm组装的shellcode二进制版本,而不是使用pwnlib的
asm
进行编译。
What you're doing is very unusual and it looks like it requires a relocation that the Mach-O object format used by OS X doesn't support. 您正在执行的操作非常不寻常,并且似乎需要重新定位,而OS X不支持使用Mach-O对象格式。 The problem isn't that you're trying to use a label as an integer, it's that you're trying to use a label as an 8-bit integer.
问题不是您要尝试将标签用作整数,而是要尝试将标签用作8位整数。 That's not very useful in practice, and something a compiler would never do.
这在实践中不是很有用,而编译器则永远不会做。
If you really want to add only the lower 8 bits of the address of a symbol (or the difference between two symbols) to the lower 8 bits of RAX you're going to use the label as an 32-bit integer first. 如果您确实只想将符号地址的低8位(或两个符号之间的差)加到RAX的低8位,您将首先使用标签作为32位整数。
For example you could move it into another 32-bit register first: 例如,您可以先将其移动到另一个32位寄存器中:
mov $do_mov_rdi_rax, %ecx
add %cl, %al
...
mov $(do_syscall - do_mov_rdi_rax), %ecx
add %cl, %al
If you don't have a free register for this than you load it from memory: 如果没有免费的寄存器,则从内存中加载它:
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
If didn't really want to be using 8-bit arithmetic and want to do the addition using all 64-bits of the address then you use the 64-bit register RAX instead: 如果不是真的想使用8位算术并且想要使用地址的所有64位进行加法运算,则可以使用64位寄存器RAX代替:
add $do_mov_rdi_rax, %rax
...
add $(do_syscall - do_mov_rdi_rax), %rax
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.