繁体   English   中英

为什么系统调用不起作用?

[英]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

如果您打算直接调用int 0x80BSD (OS/X 所基于的)上的 32 位程序要求您将额外的 4 个字节压入堆栈。 FreeBSD 文档中你会发现:

默认情况下,FreeBSD 内核使用 C 调用约定。 此外,尽管使用 int 80h 访问内核,但假定程序将调用发出 int 80h 的函数,而不是直接发出 int 80h。

[剪辑]

但是汇编语言程序员喜欢减少循环。 上面的例子需要一个 call/ret 组合。 我们可以通过推送一个额外的双字来消除它:

 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

外壳代码

您的代码实际上称为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指令: syscall

将args传递给系统调用的方法也不同:32位使用堆栈,64位使用类似于函数调用约定的寄存器。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM