- r - 以节省内存的方式增长 data.frame
- ruby-on-rails - ruby/ruby on rails 内存泄漏检测
- android - 无法解析导入android.support.v7.app
- UNIX 域套接字与共享内存(映射文件)
尽管这两个程序都遵守 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 位代码中有 rel8
和 rel32
编码。在 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 的生成代码,看看哪里出了问题。 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
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 相同类型的问题。
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/
我在stackoverflow上查过很多类似的问题,比如call.call 1 , call.call 2 ,但我是新人,无法发表任何评论。我希望我能找到关于 JavaScript 解释器如何执行这些
“strace 是一个系统调用跟踪器,即一个调试工具,它打印出另一个进程/程序进行的所有系统调用的跟踪。”如果系统调用递归工作或一个系统调用调用另一个系统调用怎么办。我怎样才能得到这些信息? 可能的解
我的问题很简单:我正在将一个函数传递给其他一些稍后调用的函数(示例回调函数),问题是何时、为何以及最佳做法是什么。 样本:我有 xxx() 函数,我必须传递它,如下面的 window.onload 事
我是 Java 新手,我正在尝试学习 ScheduledExecutorService 接口(interface)。我在网上看到了下面的代码。 我没有看到任何对 Callable.call() 方法的
这是我的调用过程: System.out.println
在 typescript 中,我有一个 DataAccess 类,以便所有 Ajax 调用都通过单个对象进行路由,以节省应用程序中许多地方的代码重复。 在使用这种方法时,我需要使用回调将响应返回到调用
如何使用模拟来计算通过 call 或 apply 进行的函数调用 // mylib.js module.exports = { requestInfo: function(model, id) {
每次我尝试roxygenize 一个包我都会得到这个错误: Error: is.call(call) is not TRUE traceback() 的结果: 11: stop(sprintf(nge
这里如果我有一个记录“调用我的函数”的函数 function myFunction() { console.log('called my function') } Function.prototy
在 Javascript 中,Function.call() 可以在给定 this 值和零个或多个参数的情况下调用 Function。 Function.call 本身就是一个函数。所以理论上,Fun
这个问题已经有答案了: "object is not a function" when saving function.call to a variable (3 个回答) a is a functi
在调用 UITableView 上的 reloadData 方法后,我曾多次遇到此问题,但我不明白为什么? 这是一个问题,因为如果更新 TableView 的数据,tableview将不必要地查询不存
我继承了大约 400 行写得非常奇怪的 Fortran 77 代码,我正在尝试逐步分析它以使其在我的脑海中清晰。 无论如何,我有一个类似 header 的文件(实际上是一个 .h,但其中的代码是 fo
这是我的代码 class AuthAction(callbackUri:String) extends ActionBuilder[UserRequest] with ActionRefiner[
我继承了大约 400 行写得非常奇怪的 Fortran 77 代码,我正在尝试逐步分析它以使其在我的脑海中清晰。 无论如何,我有一个类似 header 的文件(实际上是一个 .h,但其中的代码是 fo
我知道这个问题之前在这里被问过 iOS 6 shouldAutorotate: is NOT being called .但我的情况有点不同。 最初,在应用程序启动时,我加载了一个 viewContr
我是 headfirst 设计模式的读者,我注意到了这一点。 “好莱坞原则,别叫我们,我们叫你” 这意味着高级组件告诉低级组件“不要调用我们,我们调用你” High-Level Component 是
这个问题在这里已经有了答案: Why does passing variables to subprocess.Popen not work despite passing a list of ar
我刚找到一个覆盖 OnPaintBackground 的表单。奇怪的是它从来没有被调用过!就像,完全一样。为什么是这样?表单被刷新、移动、调整大小等等,所以它应该一些重新绘制,对吧? 最佳答案 是否设
调用函数的方式 考虑这个简单的函数: function my(p) { console.log(p) } 我可以这样调用它: my("Hello"); 也像这样: my.call(this, "Hel
我是一名优秀的程序员,十分优秀!