英文:
Getting absolute address of data in shellcode
问题
以下是您的shellcode:
xor rax, rax
xor rdi, rdi
xor rsi, rsi
xor rdx, rdx
; 获取`pathname`的地址
mov rdi, [something]
mov al, 59
mov rdi, rsp
syscall
xor rax, rax
mov al, 60
xor rdi, rdi
syscall
_pathname:
db "/usr/bin/shutdown",0
这是一个简单的execve
和退出操作。问题在于我无法获取访问pathname所需的绝对地址。我找到的“解决方案”是将代码设置得像这样:
call _end
_start:
pop rdi ; _start的绝对地址
; 然后添加字节以到达_end的地址
_end:
call start
db "/usr/bin/shutdown", 0
这对我来说从来都不合理,而且也不起作用。我还尝试使用FPU指令,但它们也不起作用。
有人有解决方案吗?
操作系统:Linux
架构:amd64
英文:
Here's my shellcode:
xor rax, rax
xor rdi, rdi
xor rsi, rsi
xor rdx, rdx
; getting address of `pathname`
mov rdi, [something]
mov al, 59
mov rdi, rsp
syscall
xor rax,rax
mov al, 60
xor rdi, rdi
syscall
_pathname:
db "/usr/bin/shutdown",0
Simple execve
and exit, that's all. The problem is that I can't get the absolute address in order to access pathname. The "solution" to this, that I have found, is rigging the code something like this:
call _end
_start:
pop rdi ; absolute address of _start
; then add bytes to get to address of _end
_end:
call start
db "/usr/bin/shutdown", 0
This never made sense to me, and it didn't work. I also tried using FPU instructions, which were supposed to work as well, but they didn't work either.
Anybody have a solution?
OS: Linux
Architecture: amd64
答案1
得分: 3
在x86-64上,您可以使用RIP相对寻址模式,所以您应该可以简单地执行 lea rdi, [rel _pathname]
。汇编器会计算当前指令(或实际上是下一条指令)的地址与标签 _pathname
之间的位移,并将其编码到指令中。在运行时,这个位移会添加到 rip
中,然后将结果放入 rdi
寄存器中。
x86-32没有相对寻址模式,因此在32位模式下,您的 call/pop
技巧是完成此操作的标准方式,尽管有些笨拙。而且它在64位模式下也有效。但是,由 pop rdi
弹出的地址不是 _start
的地址;而是由 call _start
指令推送的返回地址,即 call _start
指令之后的字节地址。在这种情况下,它恰好是您的 /usr/bin/shutdown
字符串的第一个字节,因此实际上您不需要添加任何内容。
请注意,您将一个空指针传递给 execve
的 argv
和 envp
参数。这对于内核是合法的,但shutdown
程序可能不会预期到这一点,启动时可能会崩溃。因此,您可能需要进行一些额外的工作,以构建一个至少包含 argv[0] == "shutdown"
的最小参数向量。
英文:
On x86-64 you have RIP-relative addressing modes, so you should be able to simply do lea rdi, [rel _pathname]
. The assembler computes the displacement between the address of the current instruction (or actually the next one) and the label _pathname
, and encodes it into the instruction. At runtime this displacement is added to rip
and the result placed in rdi
.
x86-32 doesn't have relative addressing modes, so in 32-bit mode, your call/pop
trick is the standard way to accomplish this, despite being awkward. And it does work in 64-bit mode too. But the address popped by pop rdi
isn't the address of _start
; rather it's the return address pushed by the call _start
instruction, i.e. the address of the byte following the call _start
instruction. In this case it is exactly the first byte of your /usr/bin/shutdown
string, so in fact you wouldn't have to add anything.
Note that you are passing a null pointer as the argv
and envp
arguments to execve
. This is legal for the kernel, but the shutdown
program is probably not expecting this and it may crash upon startup. So you might have to do some more work to construct a minimal argument vector with argv[0] == "shutdown"
at least.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论