简体   繁体   English

使用气体,如何获得特定标签的偏移量?

[英]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_raxadd 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.

相关问题 如何获得与objdump输出的标签相对应的ELF二进制文件中的文件偏移量? - How do I get the file offset in an ELF binary corresponding to a label outputted by objdump? 如何获取二进制文件的文本部分的偏移量和大小? - How can I get the offset and size of the text section of a binary? 使用“.intel_syntax noprefix”如何获取标签的内存地址? - Using “.intel_syntax noprefix” how can I get memory address of a label? 使用GDB [GAS]读取内存偏移 - reading memory offset with GDB [GAS] 如何从共享库的文本部分获取偏移量和数据? - How can I get the offset and data from the text section of a shared libray? 如何在64位Linux上使用Gas('as')组装32位二进制文​​件? - How can I use Gas ('as') to assemble a 32 bit binary on a 64 bit linux? 如何在Gas汇编程序中分配超过2GB的内存? - How can I allocate more than 2GB of memory in gas assembler? 如何从GAS源识别GDB中的全局变量? - How I can recognize global variable in GDB from GAS-source? 如何在寄存器内的特定偏移量处打印字符? - How to print a character at a particular offset within a register? 在 GAS.intel-syntax 程序集中在 memory 标签和寄存器上使用“偏移”和“[]”有什么区别? - What is the difference between using “offset” and “[ ]” on memory labels and registers in GAS .intel-syntax assembly?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM