# -*- coding: binary -*-

module Msf
module Exploit::Local::Linux
  include Exploit::Local::CompileC

  def linux_x86_syscall_wrappers(metasm_exe)
    cparser.parse <<-EOC
      #ifndef size_t
      #define size_t int
      #endif
      #ifndef off_t
      #define off_t unsigned long
      #endif

      #define O_CREAT 64
      #define O_RDWR 2

      #define MAP_PRIVATE   0x02
      #define MAP_FIXED     0x10
      #define MAP_ANONYMOUS 0x20
      #define MAP_ANON MAP_ANONYMOUS
      #define MAP_FAILED ((void *)-1)

      #define PROT_READ  0x1
      #define PROT_WRITE 0x2
      #define PROT_EXEC  0x4

      void exit(int status);
      int read(int fd, void *buf, size_t count);
      int write(int fd, void *buf, size_t count);
      int open(const char *pathname, int flags, int mode);
      int unlink(const char *pathname);
      int ftruncate(int fd, off_t length);
      int socket(int, int, int);
      int sendfile(int in_fd, int out_fd, void *, int count);
      void *__mmap2(void *addr, size_t length, int prot, int flags, int fd, off_t offset);

      #ifdef DEBUGGING
      void sigtrap();
      #else
      #define sigtrap()
      #endif
      void *__get_tls();

    EOC
    metasm_exe.parse <<-EOS
      sigtrap:
        int    3
        ret
      exit:
        mov    eax, 1         ; sys_exit
        mov    ebx, [esp+4]
        int    0x80
        ret
      read:
        mov    eax, 3         ; sys_write
        mov    edx,[esp+12]   ; length
        mov    ecx,[esp+8]    ; string
        mov    ebx,[esp+4]    ; file descriptor
        int    0x80
        ret
      write:
        mov    eax, 4         ; sys_write
        mov    edx,[esp+12]   ; length
        mov    ecx,[esp+8]    ; string
        mov    ebx,[esp+4]    ; file descriptor
        int    0x80
        ret
      open:
        mov    eax, 5         ; sys_open
        mov    edx,[esp+12]   ; mode
        mov    ecx,[esp+8]    ; flags
        mov    ebx,[esp+4]    ; file name
        int    0x80
        cmp    eax, -129
        jb     1f
        neg    eax
        push   eax
        call   __set_errno
        add    esp, 4
        or     eax, -1
      1:
        ret
      ftruncate:
        push   ebx
        push   ecx
        mov    eax, 93        ; sys_ftruncate
        mov    ecx,[esp+16]   ; file descriptor
        mov    ebx,[esp+12]   ; size
        int    0x80
        cmp    eax, -129
        jb     1f
        neg    eax
        push   eax
        call   __set_errno
        add    esp, 4
        or     eax, -1
      1:
        pop    ecx
        pop    ebx
        ret
      socket:
        push   ebx
        push   ecx
        mov    eax, 102       ; sys_socketcall
        mov    ebx, 1
        mov    ecx, esp
        add    ecx, 12
        int    0x80
        cmp    eax, -129
        jb     1f
        neg    eax
        push   eax
        call   __set_errno
        add    esp, 4
        or     eax, -1
      1:
        pop    ecx
        pop    ebx
        ret
      sendfile:
        push   ebx
        push   ecx
        push   edx
        push   esi

        mov    eax, 187       ; sys_sendfile
        mov    esi,[esp+32]   ; size
        mov    edx,[esp+28]   ; offset
        mov    ecx,[esp+24]    ; out_fd
        mov    ebx,[esp+20]    ; in_fd
        int    0x80
        cmp    eax, -129
        jb     1f
        neg    eax
        push   eax
        call   __set_errno
        add    esp, 4
        or     eax, -1
      1:
        pop    esi
        pop    edx
        pop    ecx
        pop    ebx
        ret

      unlink:
        mov    eax, 10        ; sys_unlink
        mov    ebx,[esp+4]    ; filename
        int    0x80
        ret

      ; stolen from bionic
      __mmap2:
        push   ebx
        push   ecx
        push   edx
        push   esi
        push   edi
        push   ebp

        mov    eax, 192
        mov    ebx, [esp+28]
        mov    ecx, [esp+32]
        mov    edx, [esp+36]
        mov    esi, [esp+40]
        mov    edi, [esp+44]
        mov    ebp, [esp+48]
        int    0x80
        cmp    eax, -129
        jb     1f
        neg    eax
        push   eax
        call   __set_errno
        add    esp, 4
        or     eax, -1
      1:
        pop    ebp
        pop    edi
        pop    esi
        pop    edx
        pop    ecx
        pop    ebx
        ret

      ; Thread Local Storage, used by errno
      __get_tls:
        mov    eax, gs:[0]
        ret
    EOS

  end
end
end

