Return 从 Shellcode 而不是退出

Return from Shellcode instead of exit

我正在为 uni 进行共享内存分配,我有 'borrowed' 和 'massaged' 一些我在 post 中看到的 shellcode 我在这里读过并且其他地方。我已经能够构建一个在我的 MacBook (Mojave) 上运行的示例,并且几乎可以满足我的要求。

但是,由于我在 OS 环境(本例中为 MacOS)中的汇编编程经验不多,而且我不完全理解下面的汇编,所以我需要一点帮助来解决我的最后一个问题。

在我的 C 样板包装器中,我有一个周期性调用我的 shellcode 的循环,但该循环只执行一次迭代。这使我得出结论,第二个 syscall(在下面的代码中)正在执行 exit 0,从而终止该过程。

如何将程序集修改为 return 而不是 exit?

注意 如果有人问我,我可以 post 关于我正在使用的包装器代码和工具的更多信息。

bits 64

Section .text
  global start

start:
  jmp       short MESSAGE     ;00000000  EB24              jmp short 0x26

GOBACK:
  mov       eax, 0x2000004    ;00000002  B804000002        mov eax,0x2000004  ; write
  mov       edi, 0x1          ;00000007  BF01000000        mov edi,0x1
  lea       rsi, [rel msg]    ;0000000C  488D3518000000    lea rsi,[rel 0x2b]
  mov       edx, 0xf          ;00000013  BA0F000000        mov edx,0xf
  syscall                     ;00000018  0F05              syscall

  mov       eax,0x2000001     ;0000001A  B801000002        mov eax,0x2000001  ;exit
  mov       edi,0x0           ;0000001F  BF00000000        mov edi,0x0
  syscall                     ;00000024  0F05              syscall


MESSAGE:
  call      GOBACK
  msg:      db      "Hello, world!", 0dh, 0ah
  .len:     equ     $ - msg

这是我的 C 样板代码,其中包括上面的 shellcode。

#include <string.h>
#include <sys/mman.h>
#include <unistd.h>

const char shellcode[] = "\xeb\x24\xb8\x04\x00\x00\x02\xbf\x01\x00\x00\x00\x48\x8d\x35\x18\x00\x00\x00\xba\x0f\x00\x00\x00\x0f\x05\xb8\x01\x00\x00\x02\xbf\x00\x00\x00\x00\x0f\x05\xe8\xd7\xff\xff\xff\x48\x65\x6c\x6c\x6f\x2c\x20\x77\x6f\x72\x6c\x64\x21\x0d\x0a";

int main(int argc, char **argv)
{
  void *mem = mmap(0, sizeof(shellcode), PROT_READ|PROT_WRITE, MAP_SHARED|MAP_ANONYMOUS, -1, 0);

  memcpy(mem, shellcode, sizeof(shellcode));

  mprotect(mem, sizeof(shellcode), PROT_READ|PROT_WRITE|PROT_EXEC);

  for (int i = 0; i < 10; i++) {
    int (*func)();
    func = (int (*)())mem;
    (int)(*func)();
    sleep(5);
  }

  munmap(mem, sizeof(shellcode));

  return 0;
}

I have a loop that calls my shellcode

因此,如果它是实际的 call,那么您就可以开始了,唯一需要做的更改是删除最后 3 条指令(movmovsyscall) 并用 ret 替换它们,因为 return 地址已经在堆栈上了。但是我们需要额外清理一下堆栈,因为文本字符串的地址是为了 syscall 而放在那里的,我们想在 return 之前摆脱它。

此外,由于您的 shellcode 包含一个偏移量(第一个 jmp 操作码的值为 0x24),因此不删除任何内容(因为它会更改偏移量)更安全,而是用 NOP。除非你每次都修改 shellcode 的源代码并生成它——否则删除东西就没问题了。

所以我实际上建议做的是用 0x90(NOP) 替换构成最后 3 个操作码的字节,最后 2 个字节替换为 pop rax\ret 所以字节0x580xc3。最终的 shellcode 可能如下所示:

const char shellcode[] = "\xeb\x24\xb8\x04\x00\x00\x02\xbf\x01\x00\x00\x00\x48\x8d\x35\x18\x00\x00\x00\xba\x0f\x00\x00\x00\x0f\x05\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x58\xc3\xe8\xd7\xff\xff\xff\x48\x65\x6c\x6c\x6f\x2c\x20\x77\x6f\x72\x6c\x64\x21\x0d\x0a";