在作为单独代码单独运行以及与C ++代码一起运行时,shellcode调用不同的syscall [英] shellcode calls different syscall while runing alone as individiual code and while running with C++ code
问题描述
我有一个运行在shell中的代码:
I've such a code that run's shell:
BITS 64
global _start
_start:
mov rax, 59
jmp short file
c1:
pop rdi
jmp short argv
c2:
pop rsi
mov rdx, 0
syscall
file:
call c1
db '/bin/sh',0
argv:
call c2
dq arg, 0
arg:
db 'sh',0
以这种方式构建时可以使用:
It works when it's built in this way:
nasm -f elf64 shcode.asm
ld shcode.o -o shcode
Althougt,当我使用以下命令将其转换为二进制形式时:
Althougt, when I bring it into binary form with:
nasm -f bin shcode.asm
将其粘贴到以下C ++代码中:
paste it into following C++ code:
int main(void)
{
char kod[]="\xB8\x3B\x00\x00\x00\xEB\x0B\x5F\xEB\x15\x5E\xBA\x00\x00\x00\x00\x0F\x05\xE8\xF0\xFF\xFF\xFF\x2F\x62\x69\x6E\x2F\x73\x68\x00\xE8\xE6\xFF\xFF\xFF\x34\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x73\x68\x00";
reinterpret_cast<void(*)()>(kod)();
return 0;
}
使用clang ++ texp.cpp -o texp.e -Wl,-z,execstack和execute使其执行,外壳未运行.
make it with clang++ texp.cpp -o texp.e -Wl,-z,execstack and execute, shell isn't running.
运行后
strace ./texp.e
我看到这样的内容(我用^ C停止了此过程):
I see something like this (I stopped this process with ^C):
syscall_0xffffffffffffffda(0x7ffc23e0a297, 0x7ffc23e0a2a4, 0, 0x4a0, 0x7fe1ff3039b0, 0x7fe1ff69b960) = -1 ENOSYS (Nie zaimplementowana funkcja)
syscall_0xffffffffffffffda(0x7ffc23e0a297, 0x7ffc23e0a2a4, 0, 0x4a0, 0x7fe1ff3039b0, 0x7fe1ff69b960) = -1 ENOSYS (Nie zaimplementowana funkcja)
.
.
.
syscall_0xffffffffffffffda(0x7ffc23e0a297, 0x7ffc23e0a2a4, 0, 0x4a0, 0x7fe1ff3039b0, 0x7fe1ff69b960) = -1 ENOSYS (Nie zaimplementowana funkcja)
^Csyscall_0xffffffffffffffda(0x7ffc23e0a297, 0x7ffc23e0a2a4, 0, 0x4a0, 0x7fe1ff3039b0, 0x7fe1ff69b960strace: Process 2806 detached
<detached ...>
Nie zaimplementowana funkcja-未实现功能
Nie zaimplementowana funkcja - Function not implemented
因此程序(又名shellcode)可能正确运行了不正确的系统调用.
So the program ( aka shellcode ) is propably running improper syscall.
推荐答案
在您的C ++ shellcode调用程序中,strace
显示您的execve
系统调用是
In your C++ shellcode caller, strace
shows your execve
system call was
execve("/bin/sh", [0x34], NULL) = -1 EFAULT (Bad address)
后面的syscall_0xffffffffffffffda(...) = -1 ENOSYS
来自RAX = -EFAULT
而不是59的无限循环,然后来自RAX=- ENOSYS
(同样无效的呼叫号码).此循环由您的call/pop
创建.
The later syscall_0xffffffffffffffda(...) = -1 ENOSYS
are from an infinite loop with RAX = -EFAULT
instead of 59, and then from RAX=- ENOSYS
(again not a valid call number). This loop is created by your call/pop
.
大概是因为您从未链接的.o
或PIE可执行文件中转储了arg
的绝对地址,这就是0x34
作为绝对地址的方式.
Presumably because you hexdumped an absolute address for arg
from an unlinked .o
or from a PIE executable, which is how you got 0x34
as the absolute address.
很显然,如果要从随机堆栈地址运行且没有重定位修复程序的话,将绝对地址嵌入到您的shellcode中的整个方法将不起作用. dq arg, 0
与位置无关.
Obviously the whole approach of embedding an absolute address in your shellcode doesn't work if it's going to run from a randomized stack address, with no relocation fixup. dq arg, 0
is not position-independent.
您至少需要使用指针自己构造一个argv
数组(通常使用push
).您也可以使用push imm32
来构造arg
本身.例如push 'shsh'
/lea rax, [rsp+2]
.
You need to construct at least the argv
array yourself (usually with push
) using pointers. You could also use a push imm32
to construct arg
itself. e.g. push 'shsh'
/ lea rax, [rsp+2]
.
或者最常见的技巧是利用特定于Linux的功能":您可以通过xor esi,esi
传递argv=NULL
(而不是指向NULL指针的指针).
Or the most common trick is to take advantage of a Linux-specific "feature": you can pass argv=NULL
(instead of a pointer to a NULL pointer) with xor esi,esi
.
(使用mov reg,0
完全违反了jmp/call/pop技巧避免零字节的目的.如果允许零字节,您也可以只使用常规的RIP相对LEA.但是如果不允许,则可以跳转转发数据,然后使用具有负位移的RIP相对LEA.)
(Using mov reg,0
completely defeats the purpose of the jmp/call/pop trick for avoiding zero bytes. You might as well just use a normal RIP-relative LEA if zero bytes are allowed. But if not, you can jump forward over data then use RIP-relative LEA with a negative displacement.)
这篇关于在作为单独代码单独运行以及与C ++代码一起运行时,shellcode调用不同的syscall的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!