首页 文章

避免使用JMP CALL POP技术进行shellcode NASM的JMP?

提问于
浏览
2

即使两个程序都遵守shellcode执行所需的相对寻址指令,并且两者都在执行时打印所需的消息,但 2nd Sample 在用作shellcode时失败 . 谁能解释一下这种行为?奇怪的是,与第一个相同的 3rd sample 也失败了 .

输出: Sample 1 Hello World

其他样本(2和3)打印垃圾值

Sample 1

global _start
section .text
        _start:
                jmp widen

        pHworld:
                pop rsi
                xor rax,rax
                mov al,1
                mov rdi,rax
                mov rdx,rdi
                add rdx,11
                syscall
                ;Exit
                xor rax,rax
                mov rax,60
                xor rdi,rdi
                syscall
        widen:
                call pHworld
                Hworld db "Hello World",0xa

Sample 2

global _start
section .text
        _start:
                call pHworld
                Hworld db "Hello World",0xa

        pHworld:
                pop rsi
                xor rax,rax
                mov al,1
                mov rdi,rax
                mov rdx,rdi
                add rdx,11
                syscall
                ;Exit
                xor rax,rax
                mov rax,60
                xor rdi,rdi
                syscall

Sample 3

global _start
section .text
        _start:
                jmp label1

        label1:
                call pHworld
                Hworld db "Hello World",0xa

        pHworld:
                pop rsi
                xor rax,rax
                mov al,1
                mov rdi,rax
                mov rdx,rdi
                add rdx,11
                syscall
                ;Exit
                xor rax,rax
                mov rax,60
                xor rdi,rdi
                syscall

无法休息我的好奇心,我尝试了另一种变化,即使我的objdump没有任何0x00,这也会失败(打印垃圾值) . Sample 4

global _start
section .text
pHworld:
    pop rsi
    xor rax,rax
    mov al,1
    mov rdi,rax
    mov rdx,rdi
    add rdx,11
    syscall
    xor rax,rax
    xor rdi,rdi
    mov al,60
    syscall

l1:
    call pHworld
    Hworld db "Hello World", 0xa

_start:
    jmp l1
    enter code here

Objdump of sample4

./hworld2.s:     file format elf64-x86-64


    Disassembly of section .text:

    0000000000400080 :
      400080:       5e                      pop    rsi
      400081:       48 31 c0                xor    rax,rax
      400084:       b0 01                   mov    al,0x1
      400086:       48 89 c7                mov    rdi,rax
      400089:       48 89 fa                mov    rdx,rdi
      40008c:       48 83 c2 0b             add    rdx,0xb
      400090:       0f 05                   syscall 
      400092:       48 31 c0                xor    rax,rax
      400095:       48 31 ff                xor    rdi,rdi
      400098:       b0 3c                   mov    al,0x3c
      40009a:       0f 05                   syscall 

    000000000040009c :
      40009c:       e8 df ff ff ff          call   400080 

    00000000004000a1 :
      4000a1:       48                      rex.W
      4000a2:       65                      gs
      4000a3:       6c                      ins    BYTE PTR es:[rdi],dx
      4000a4:       6c                      ins    BYTE PTR es:[rdi],dx
      4000a5:       6f                      outs   dx,DWORD PTR ds:[rsi]
      4000a6:       20 57 6f                and    BYTE PTR [rdi+0x6f],dl
      4000a9:       72 6c                   jb     400117 
      4000ab:       64                      fs
      4000ac:       0a eb                   or     ch,bl

    00000000004000ad :
      4000ad:       eb ed                   jmp    40009c

1 回答

  • 7

    TL;DR :使用shellcode,您希望避免编码0x00字节,否则当代码用作漏洞利用的字符串时,它们将在第一个0x00处截断 . 这有效地缩短了您的代码 .

    在漏洞利用之外运行时,额外的0x00字节不会导致问题,因为它们没有转换为字符串 . 执行指令与任何普通可执行文件一样 .


    JMP / CALL / POP方法中JMP指令的原因是消除在生成的代码中插入不需要的0x00字节 . 64位代码中的JMP具有 rel8rel32 编码 . 在64位代码中CALL只有 rel32 编码 . 这意味着如果您在64位代码中使用CALL在内存中进行小的传输,它将被编码为32位零扩展目标 . 零扩展会导致不需要的0x00值放在shell代码中 . 在64位代码中,这个CALL指令:

    call next
        nop
    next:
    

    将被编码为:

    e8 01 00 00 00

    由于JMP指令支持 rel8 (相对字节位移),如果目标距离不超过127个字节,则NASM可以在内存中生成JMP指令(有符号字节为-128到127) . 这个JMP指令:

    jmp next
        nop
    next:
    

    将被编码为:

    eb 01

    所以没有额外的零 . 您可能会问为什么JMP / CALL / POP方法中的CALL指令有效 . 原因是负值的符号扩展到高位字节 . 用1填充高位不会产生额外的0x00字节,因此它可以工作 . 这个CALL指令:

    prev:
        call prev
    

    将被编码为:

    e8 fb ff ff ff

    请注意,额外的字节不是0.这就是为什么在内存中较早地调用某个位置可以避免生成零 .


    样本2

    如果我们记住以上内容,我们只需要检查样本2的生成代码,以查看出错的地方 . objdump -D ./sample2 -Mintel 生成:

    0000000000000000 <_start>:
       0:   e8 0c 00 00 00          call   11 <pHworld>   <---------- Extra zeros
    
    0000000000000005 <Hworld>:
       5:   48                      rex.W
       6:   65 6c                   gs ins BYTE PTR es:[rdi],dx
       8:   6c                      ins    BYTE PTR es:[rdi],dx
       9:   6f                      outs   dx,DWORD PTR ds:[rsi]
       a:   20 57 6f                and    BYTE PTR [rdi+0x6f],dl
       d:   72 6c                   jb     7b <pHworld+0x6a>
       f:   64 0a 5e 48             or     bl,BYTE PTR fs:[rsi+0x48]
    
    0000000000000011 <pHworld>:
      11:   5e                      pop    rsi
      12:   48 31 c0                xor    rax,rax
      15:   b0 01                   mov    al,0x1
      17:   48 89 c7                mov    rdi,rax
      1a:   48 89 fa                mov    rdx,rdi
      1d:   48 83 c2 0b             add    rdx,0xb
      21:   0f 05                   syscall
      23:   48 31 c0                xor    rax,rax
      26:   b8 3c 00 00 00          mov    eax,0x3c       <---------- Extra zeros
      2b:   48 31 ff                xor    rdi,rdi
      2e:   0f 05                   syscall
    

    所以我们看到CALL的问题是用额外的零编码,这就是为什么你需要一个传统的JMP / CALL / POP . mov eax, 60 存在第二个问题,因为它编码额外的字节 . 我觉得你打算用 mov al, 60

    样本3

    objdump -D ./sample3 -Mintel 生成:

    0000000000000000 <_start>:
       0:   eb 00                   jmp    2 <label1>     <---------- Extra zeros
    
    0000000000000002 <label1>:
       2:   e8 0c 00 00 00          call   13 <pHworld>   <---------- Extra zeros
    
    0000000000000007 <Hworld>:
       7:   48                      rex.W
       8:   65 6c                   gs ins BYTE PTR es:[rdi],dx
       a:   6c                      ins    BYTE PTR es:[rdi],dx
       b:   6f                      outs   dx,DWORD PTR ds:[rsi]
       c:   20 57 6f                and    BYTE PTR [rdi+0x6f],dl
       f:   72 6c                   jb     7d <pHworld+0x6a>
      11:   64 0a 5e 48             or     bl,BYTE PTR fs:[rsi+0x48]
    
    0000000000000013 <pHworld>:
      13:   5e                      pop    rsi
      14:   48 31 c0                xor    rax,rax
      17:   b0 01                   mov    al,0x1
      19:   48 89 c7                mov    rdi,rax
      1c:   48 89 fa                mov    rdx,rdi
      1f:   48 83 c2 0b             add    rdx,0xb
      23:   0f 05                   syscall
      25:   48 31 c0                xor    rax,rax
      28:   b8 3c 00 00 00          mov    eax,0x3c       <---------- Extra zeros
      2d:   48 31 ff                xor    rdi,rdi
      30:   0f 05                   syscall
    

    与样本2相同的问题类型 .


    样本1

    objdump -D ./sample1 -Mintel 生成:

    0000000000000000 <_start>:
       0:   eb 1f                   jmp    21 <widen>
    
    0000000000000002 <pHworld>:
       2:   5e                      pop    rsi
       3:   48 31 c0                xor    rax,rax
       6:   b0 01                   mov    al,0x1
       8:   48 89 c7                mov    rdi,rax
       b:   48 89 fa                mov    rdx,rdi
       e:   48 83 c2 0b             add    rdx,0xb
      12:   0f 05                   syscall
      14:   48 31 c0                xor    rax,rax
      17:   b8 3c 00 00 00          mov    eax,0x3c       <---------- Extra zeros
      1c:   48 31 ff                xor    rdi,rdi
      1f:   0f 05                   syscall
    
    0000000000000021 <widen>:
      21:   e8 dc ff ff ff          call   2 <pHworld>
    
    0000000000000026 <Hworld>:
      26:   48                      rex.W
      27:   65 6c                   gs ins BYTE PTR es:[rdi],dx
      29:   6c                      ins    BYTE PTR es:[rdi],dx
      2a:   6f                      outs   dx,DWORD PTR ds:[rsi]
      2b:   20 57 6f                and    BYTE PTR [rdi+0x6f],dl
      2e:   72 6c                   jb     9c <Hworld+0x76>
      30:   64                      fs
      31:   0a                      .byte 0xa
    

    虽然你说 sample 1 有效但它仍然有一个需要纠正的问题 . mov rax, 60 需要 mov al, 60 .

相关问题