gpt4 book ai didi

linux - 在 shellcode NASM 的 JMP CALL POP 技术中避免 JMP?

转载 作者:IT王子 更新时间:2023-10-29 01:04:47 26 4
gpt4 key购买 nike

尽管这两个程序都遵守 shellcode 执行所需的相对寻址指令,并且都在执行时打印所需的消息,但当用作 shellcode 时,2nd Sample 失败了。谁能解释这种行为?奇怪的是,与第一个相同的第三个样本也失败了。

输出:示例 1 Hello World

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

示例 1

global _startsection .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

示例 2

global _startsection .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

示例 3

global _startsection .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。示例 4

global _startsection .textpHworld:    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    syscalll1:    call pHworld    Hworld db "Hello World", 0xa_start:    jmp l1    enter code here

sample4的Objdump

    ./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 

最佳答案

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

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


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

    call next
nop
next:

将被编码为:

e8 01 00 00 00

由于 JMP 指令支持 rel8(相对字节位移),如果目标不再存在,NASM 可以在内存中向前生成一条 JMP 指令超过 127 个字节(有符号字节为 -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/POPmov 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

关于linux - 在 shellcode NASM 的 JMP CALL POP 技术中避免 JMP?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47761584/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com