linux - shellcode 在两个循环而不是一个循环中执行
问题描述
我成功地构建了我的 shellcode。
[BITS 64]
segment .text
global _start
_start: jmp call
back: lea rsi, [rsp]
mov rdi, [rsi]
xor rax, rax
push rax
lea rdx, [rsp]
mov al, 0x3b
syscall
call: call back
db "/bin/sh",0
但是代码执行有一些神秘之处。我仍然无法弄清楚问题所在,也许有人能够提供帮助。
当我用radare2调试代码时,设置参数和系统调用的整个过程会执行两次。我不知道它有什么问题。寄存器,翻录等看起来不错。最后,shell 在第二个循环后弹出。但是对于在堆栈上执行来说,这是一件很痛苦的事情,因为我的 /bin/sh 在第二个循环中搞砸了。
第一个系统调用返回 -14(错误地址)
我已经尝试了一些代码变体和 RTFM。帮助
先感谢您 :)
解决方案
好吧,argv
数组格式不正确。您将该参数设置为堆栈上的地址,但您没有放置空指针来终止它。
这是执行第一条指令时的堆栈(下部)_start
:
...
0
argN
...
arg0
argc <-- rsp
请注意,这些是您的程序的参数。另请注意,这<--
意味着“指向”(或:包含的地址)。
何时back
调用堆栈是:
...
0
argN
...
arg0
count
ptr to shell path <-- rsp
在lea
s (顺便说一下,lea
这种简单的寻址模式只是 a mov
)和xor
之后,堆栈是:
...
0
argN
...
arg0
count
ptr to shell path <-- rsp, rsi
rdi = ptr to shell path
然后就在syscall
我们之前:
...
0
argN
...
arg0
count
ptr to shell path <-- rsi
rdi = ptr to shell path
0 <-- rsp, rdx
然后execve
将从rdi
(检查)、envp
从rdx
(检查)和argv
从rsi
(失败)读取可执行路径。
最后一个失败,因为execve
将从 shell 的路径读取堆栈到第一个 0,但count
不是一个有效的指针(它可能是 1)。
系统调用失败,执行失败,call back
重复这些步骤,但这次来自上一次迭代的 0 将正确终止argv
:
...
0
argN
...
arg0
count
ptr to shell path
0
ptr to shell path <-- rsi
rdi = ptr to shell path
0 <-- rsp, rdx
你可以:
- 什么都不做,并以这种方式保留它作为调用 shell 的一种棘手方法(请注意,某些值
count
可以解释为有效指针,给 shell 一个参数)。 - 将 更改
count
为零。您可以向上移动xor eax, eax
并使用mov [rsp+8], rax
. 只要您可以在[rsp+8]
. - 自己推一个零。要么在寄存器中弹出返回地址,然后在推入零后将其推入,或者使用
xchg
或类似的。 - 通过
argv
和envp
作为NULL
(即归零rsi
和rdx
)。在 Linux 上,这与您已经在执行的操作具有相同的效果(使用单个空指针传递数组)。 - 如果你想将你的程序参数传递给 shell,你可以 double pop 然后推送返回地址或弹出返回地址并使用 a
mov
覆盖count
。
推荐阅读
- asp.net-mvc - MapMvcAttributeRoutes 起始页
- angular - 在 cPanel 上部署 Angular webApp
- python - 在字符串python中查找未知模式
- jquery - 使用 Css 或 Jquery 对 Bootstrap 卡的叠加效果/切换效果
- python - Pandas 索引和列创建
- r - r - 替换特定列中的字符串
- node.js - 通过 node.js 在 mac 上运行 js 时出错。怎么修?
- css - Angular 材质:snackbar 隐藏在具有高 z-index 的组件后面
- php - 当我尝试访问数组项时,我只得到 1. 一个
- npm - npm 审计修复未修复低漏洞