[
  {
    "path": ".gitattributes",
    "content": "assembly/*.inc linguist-language=Assembly\n"
  },
  {
    "path": "LICENSE",
    "content": "MIT License\n\nCopyright (c) 2018 Guilherme Thomazi Bonicontro\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n"
  },
  {
    "path": "README.md",
    "content": "# memrun\nSmall tool written in Golang to run ELF (x86_64) binaries from memory with a given process name. Works on Linux where kernel version is >= 3.17 (relies on the `memfd_create` syscall).\n\n# Usage\n\nBuild it with `$ go build memrun.go` and execute it. The first argument is the process name (string) you want to see in `ps auxww` output for example. Second argument is the path for the ELF binary you want to run from memory. \n\n```\nUsage: memrun process_name elf_binary\n```\n"
  },
  {
    "path": "assembly/README.md",
    "content": "# memrun\nSmall tool written in Assembly (FASM) to run ELF (x86_64) binaries from memory with a given process name. Works on Linux where kernel version is >= 3.17 (relies on the `memfd_create` syscall).\n\n# Usage\n\nBuild it with `$ fasm memrun.asm` and execute it. The first argument is the path for the ELF binary you want to run from memory and the second argument is the process name (string) you want to see in `ps auxww` output for example.\n\n```\nUsage: memrun <path_to_elf_file> <process_name>\n```\n"
  },
  {
    "path": "assembly/memrun.asm",
    "content": "format ELF64 executable 3\n\ninclude \"struct.inc\"\ninclude \"utils.inc\"\n\nsegment readable executable\nentry start\n\nstart:\n;-----------------------------------------------------------------------------\n; parsing command line arguments\n;-----------------------------------------------------------------------------\n  pop   rcx                       ; arg count\n  cmp   rcx, 3                    ; needs to be at least two for the self program arg0 and target arg1\n  jne   usage                     ; exit 1 if not\n\n  add   rsp, 8                    ; skips arg0\n  pop   rsi                       ; gets arg1\n\n  mov   rdi, sourcePath\n  push  rsi                       ; save rsi\n  push  rdi\n  call  strToVar\n\n  pop   rsi                       ; restore rsi\n  pop   rdi\n  mov   rdi, targetProcessName\n  pop   rsi                       ; gets arg2\n  push  rdi\n  call  strToVar\n;-----------------------------------------------------------------------------\n; opening source file for reading\n;-----------------------------------------------------------------------------\n  mov   rdi, sourcePath           ; loads sourcePath to rdi\n  xor   rsi, rsi                  ; cleans rsi so open syscall doesnt try to use it as argument\n  mov   rdx, O_RDONLY             ; O_RDONLY\n  mov   rax, SYS_OPEN             ; open\n  syscall                         ; rax contains source fd (3)\n  push  rax                       ; saving rax with source fd\n;-----------------------------------------------------------------------------\n; getting source file information to fstat struct\n;-----------------------------------------------------------------------------\n  mov   rdi, rax                  ; load rax (source fd = 3) to rdi\n  lea   rsi, [fstat]              ; load fstat struct to rsi\n  mov   rax, SYS_FSTAT            ; sys_fstat\n  syscall                         ; fstat struct conntains file information\n  mov   r12, qword[rsi + 48]      ; r12 contains file size in bytes (fstat.st_size)\n;-----------------------------------------------------------------------------\n; creating memory map for source file\n;-----------------------------------------------------------------------------\n  pop   rax                       ; restore rax containing source fd\n  mov   r8, rax                   ; load r8 with source fd from rax\n  mov   rax, SYS_MMAP             ; mmap number\n  mov   rdi, 0                    ; operating system will choose mapping destination\n  mov   rsi, r12                  ; load rsi with page size from fstat.st_size in r12\n  mov   rdx, 0x1                  ; new memory region will be marked read only\n  mov   r10, 0x2                  ; pages will not be shared\n  mov   r9, 0                     ; offset inside source file\n  syscall                         ; now rax will point to mapped location\n  push  rax                       ; saving rax with mmap address\n;-----------------------------------------------------------------------------\n; close source file\n;-----------------------------------------------------------------------------\n  mov   rdi, r8                   ; load rdi with source fd from r8\n  mov   rax, SYS_CLOSE            ; close source fd\n  syscall\n;-----------------------------------------------------------------------------\n; creating memory fd with empty name (\"\")\n;-----------------------------------------------------------------------------\n  lea   rdi, [bogusName]          ; empty string\n  mov   rsi, MFD_CLOEXEC          ; memfd mode\n  mov   rax, SYS_MEMFD_CREATE\n  syscall                         ; memfd_create\n  mov   rbx, rax                  ; memfd fd from rax to rbx\n;-----------------------------------------------------------------------------\n; writing memory map (source file) content to memory fd\n;-----------------------------------------------------------------------------\n  pop   rax                       ; restoring rax with mmap address\n  mov   rdx, r12                  ; rdx contains fstat.st_size from r12\n  mov   rsi, rax                  ; load rsi with mmap address\n  mov   rdi, rbx                  ; load memfd fd from rbx into rdi\n  mov   rax, SYS_WRITE            ; write buf to memfd fd\n  syscall\n;-----------------------------------------------------------------------------\n; executing memory fd with targetProcessName\n;-----------------------------------------------------------------------------\n  xor   rdx, rdx\n  lea   rsi, [argv]\n  lea   rdi, [fdPath]\n  mov   rax, SYS_EXECVE           ; execve the memfd fd in memory\n  syscall\n;-----------------------------------------------------------------------------\n; exit normally if everything works as expected\n;-----------------------------------------------------------------------------\n  jmp   normal_exit\n;-----------------------------------------------------------------------------\n; initialized data\n;-----------------------------------------------------------------------------\nsegment readable writable\nfstat             STAT\nusageMsg          db \"Usage: memrun <path_to_elf_file> <process_name>\", 0xA, 0\nsourcePath        db 256 dup 0\ntargetProcessName db 256 dup 0\nbogusName         db \"\", 0\nfdPath            db \"/proc/self/fd/3\", 0\nargv              dd targetProcessName\n"
  },
  {
    "path": "assembly/struct.inc",
    "content": "\n; Macroinstructions for defining data structures\n\nmacro struct name\n { virtual at 0\n   define @struct\n   field@struct equ name\n   match child parent, name \\{ restore field@struct\n\t\t\t       field@struct equ child,fields@\\#parent \\}\n   sub@struct equ\n   struc db [val] \\{ \\common define field@struct .,db,<val> \\}\n   struc dw [val] \\{ \\common define field@struct .,dw,<val> \\}\n   struc du [val] \\{ \\common define field@struct .,du,<val> \\}\n   struc dd [val] \\{ \\common define field@struct .,dd,<val> \\}\n   struc dp [val] \\{ \\common define field@struct .,dp,<val> \\}\n   struc dq [val] \\{ \\common define field@struct .,dq,<val> \\}\n   struc dt [val] \\{ \\common define field@struct .,dt,<val> \\}\n   struc rb count \\{ define field@struct .,db,count dup (?) \\}\n   struc rw count \\{ define field@struct .,dw,count dup (?) \\}\n   struc rd count \\{ define field@struct .,dd,count dup (?) \\}\n   struc rp count \\{ define field@struct .,dp,count dup (?) \\}\n   struc rq count \\{ define field@struct .,dq,count dup (?) \\}\n   struc rt count \\{ define field@struct .,dt,count dup (?) \\}\n   macro db [val] \\{ \\common \\local anonymous\n\t\t     define field@struct anonymous,db,<val> \\}\n   macro dw [val] \\{ \\common \\local anonymous\n\t\t     define field@struct anonymous,dw,<val> \\}\n   macro du [val] \\{ \\common \\local anonymous\n\t\t     define field@struct anonymous,du,<val> \\}\n   macro dd [val] \\{ \\common \\local anonymous\n\t\t     define field@struct anonymous,dd,<val> \\}\n   macro dp [val] \\{ \\common \\local anonymous\n\t\t     define field@struct anonymous,dp,<val> \\}\n   macro dq [val] \\{ \\common \\local anonymous\n\t\t     define field@struct anonymous,dq,<val> \\}\n   macro dt [val] \\{ \\common \\local anonymous\n\t\t     define field@struct anonymous,dt,<val> \\}\n   macro rb count \\{ \\local anonymous\n\t\t     define field@struct anonymous,db,count dup (?) \\}\n   macro rw count \\{ \\local anonymous\n\t\t     define field@struct anonymous,dw,count dup (?) \\}\n   macro rd count \\{ \\local anonymous\n\t\t     define field@struct anonymous,dd,count dup (?) \\}\n   macro rp count \\{ \\local anonymous\n\t\t     define field@struct anonymous,dp,count dup (?) \\}\n   macro rq count \\{ \\local anonymous\n\t\t     define field@struct anonymous,dq,count dup (?) \\}\n   macro rt count \\{ \\local anonymous\n\t\t     define field@struct anonymous,dt,count dup (?) \\}\n   macro union \\{ field@struct equ ,union,<\n\t\t  sub@struct equ union \\}\n   macro struct \\{ field@struct equ ,substruct,<\n\t\t  sub@struct equ substruct \\} }\n\nmacro ends\n { match , sub@struct \\{ restruc db,dw,du,dd,dp,dq,dt\n\t\t\t restruc rb,rw,rd,rp,rq,rt\n\t\t\t purge db,dw,du,dd,dp,dq,dt\n\t\t\t purge rb,rw,rd,rp,rq,rt\n\t\t\t purge union,struct\n\t\t\t irpv fields,field@struct \\\\{ restore field@struct\n\t\t\t\t\t\t      \\\\common define fields@struct fields \\\\}\n\t\t\t match name tail,fields@struct, \\\\{ if $\n\t\t\t\t\t\t\t    display 'Error: definition of ',\\\\`name,' contains illegal instructions.',0Dh,0Ah\n\t\t\t\t\t\t\t    err\n\t\t\t\t\t\t\t    end if \\\\}\n\t\t\t match name=,fields,fields@struct \\\\{ restore @struct\n\t\t\t\t\t\t\t      make@struct name,fields\n\t\t\t\t\t\t\t      define fields@\\\\#name fields \\\\}\n\t\t\t end virtual \\}\n   match any, sub@struct \\{ tmp@struct equ field@struct\n\t\t\t    restore field@struct\n\t\t\t    field@struct equ tmp@struct> \\}\n   restore sub@struct }\n\nmacro make@struct name,[field,type,def]\n { common\n    local define\n    define equ name\n   forward\n    local sub\n    match , field \\{ make@substruct type,name,sub def\n\t\t     define equ define,.,sub, \\}\n    match any, field \\{ define equ define,.#field,type,<def> \\}\n   common\n    match fields, define \\{ define@struct fields \\} }\n\nmacro define@struct name,[field,type,def]\n { common\n    virtual\n    db `name\n    load initial@struct byte from 0\n    if initial@struct = '.'\n    display 'Error: name of structure should not begin with a dot.',0Dh,0Ah\n    err\n    end if\n    end virtual\n    local list\n    list equ\n   forward\n    if ~ field eq .\n     name#field type def\n     sizeof.#name#field = $ - name#field\n    else\n     label name#.#type\n     rb sizeof.#type\n    end if\n    local value\n    match any, list \\{ list equ list, \\}\n    list equ list <value>\n   common\n    sizeof.#name = $\n    restruc name\n    match values, list \\{\n    struc name value \\\\{ \\\\local \\\\..base\n    match , @struct \\\\\\{ define field@struct .,name,<values> \\\\\\}\n    match no, @struct \\\\\\{ label \\\\..base\n   forward\n     match , value \\\\\\\\{ field type def \\\\\\\\}\n     match any, value \\\\\\\\{ field type value\n\t\t\t    if ~ field eq .\n\t\t\t     rb sizeof.#name#field - ($-field)\n\t\t\t    end if \\\\\\\\}\n   common label . at \\\\..base \\\\\\}\n   \\\\}\n    macro name value \\\\{\n    match , @struct \\\\\\{ \\\\\\local anonymous\n\t\t\t\t  define field@struct anonymous,name,<values> \\\\\\}\n    match no, @struct \\\\\\{\n   forward\n     match , value \\\\\\\\{ type def \\\\\\\\}\n     match any, value \\\\\\\\{ \\\\\\\\local ..field\n\t\t\t   ..field = $\n\t\t\t   type value\n\t\t\t   if ~ field eq .\n\t\t\t    rb sizeof.#name#field - ($-..field)\n\t\t\t   end if \\\\\\\\}\n   common \\\\\\} \\\\} \\} }\n\nmacro enable@substruct\n { macro make@substruct substruct,parent,name,[field,type,def]\n    \\{ \\common\n\t\\local define\n\tdefine equ parent,name\n       \\forward\n\t\\local sub\n\tmatch , field \\\\{ match any, type \\\\\\{ enable@substruct\n\t\t\t\t\t       make@substruct type,parent,sub def\n\t\t\t\t\t       purge make@substruct\n\t\t\t\t\t       define equ define,.,sub, \\\\\\} \\\\}\n\tmatch any, field \\\\{ define equ define,.\\#field,type,<def> \\\\}\n       \\common\n\tmatch fields, define \\\\{ define@\\#substruct fields \\\\} \\} }\n\nenable@substruct\n\nmacro define@union parent,name,[field,type,def]\n { common\n    virtual at parent#.#name\n   forward\n    if ~ field eq .\n     virtual at parent#.#name\n      parent#field type def\n      sizeof.#parent#field = $ - parent#field\n     end virtual\n     if sizeof.#parent#field > $ - parent#.#name\n      rb sizeof.#parent#field - ($ - parent#.#name)\n     end if\n    else\n     virtual at parent#.#name\n      label parent#.#type\n      type def\n     end virtual\n     label name#.#type at parent#.#name\n     if sizeof.#type > $ - parent#.#name\n      rb sizeof.#type - ($ - parent#.#name)\n     end if\n    end if\n   common\n    sizeof.#name = $ - parent#.#name\n    end virtual\n    struc name [value] \\{ \\common\n    label .\\#name\n    last@union equ\n   forward\n    match any, last@union \\\\{ virtual at .\\#name\n\t\t\t       field type def\n\t\t\t      end virtual \\\\}\n    match , last@union \\\\{ match , value \\\\\\{ field type def \\\\\\}\n\t\t\t   match any, value \\\\\\{ field type value \\\\\\} \\\\}\n    last@union equ field\n   common rb sizeof.#name - ($ - .\\#name) \\}\n    macro name [value] \\{ \\common \\local ..anonymous\n\t\t\t  ..anonymous name value \\} }\n\nmacro define@substruct parent,name,[field,type,def]\n { common\n    virtual at parent#.#name\n   forward\n    local value\n    if ~ field eq .\n     parent#field type def\n     sizeof.#parent#field = $ - parent#field\n    else\n     label parent#.#type\n     rb sizeof.#type\n    end if\n   common\n    sizeof.#name = $ - parent#.#name\n    end virtual\n    struc name value \\{\n    label .\\#name\n   forward\n     match , value \\\\{ field type def \\\\}\n     match any, value \\\\{ field type value\n\t\t\t  if ~ field eq .\n\t\t\t   rb sizeof.#parent#field - ($-field)\n\t\t\t  end if \\\\}\n   common \\}\n    macro name value \\{ \\local ..anonymous\n\t\t\t..anonymous name \\} }\n\n"
  },
  {
    "path": "assembly/utils.inc",
    "content": "SYS_EXIT            = 60\nSYS_OPEN            = 2\nSYS_CLOSE           = 3\nSYS_WRITE           = 1\nSYS_READ            = 0\nSYS_STAT            = 4\nSYS_MEMFD_CREATE    = 319\nSYS_EXECVE          = 59\nSYS_FSTAT           = 5\nSYS_MMAP            = 9\n\nO_RDONLY    = 0\nMFD_CLOEXEC = 1\n\nstruct STAT\n  st_dev     dw  ?     ; ID of device containing file\n  pad1       dw  ?\n  st_ino     dd  ?     ; inode number\n  st_mode    dw  ?     ; protection\n  st_nlink   dw  ?     ; number of hard links\n  st_uid     dw  ?     ; user ID of owner\n  st_gid     dw  ?     ; group ID of owner\n  st_rdev    dw  ?     ; device ID (if special file)\n  pad2       dw  ?\n  st_size    dd  ?     ; total size, in bytes\n  st_blksize dd  ?     ; block size\n  st_blocks  dd  ?\n\n  st_atime   dd  ?     ; time of last access\n  unused1    dd  ?\n\n  st_mtime   dd  ?     ; time of last modification\n  unused2    dd  ?\n\n  st_ctime   dd  ?     ; time of last status change\n  unused3    dd  ?\n  unused4    dd  ?\n  unused5    dd  ?\nends\n\nnormal_exit:\n    xor     rdi, rdi                ; exit code 0\n    mov     rax, SYS_EXIT           ; sys_exit \n    syscall\n\nbad_exit:\n    mov     rdi, 1\n    mov     rax, SYS_EXIT\n    syscall\n\nusage:\n    lea     rdi, [usageMsg]\n    call    print\n    jmp     bad_exit\n\nstrlen:                             ; rdi is the default search for scasb\n    push    rdi\n    push    rcx\n    mov     rcx, -1\n    xor     eax, eax\n    repne   scasb \n    not     rcx\n    mov     rax, rcx \n    pop     rcx\n    pop     rdi\n    ret\n\nprint:\n    push    rsi\n    push    rdx\n    push    rdi\n    call    strlen\n    mov     rdx, rax\n    mov     rsi, rdi\n    mov     rdi, 1\n    mov     rax, SYS_WRITE\n    syscall\n    pop     rsi\n    pop     rdx\n    pop     rdi\n    ret\n\nstrToVar:\n    mov     al, [rsi]          \n    mov     [rdi], al           \n    inc     rsi              \n    inc     rdi\n    cmp     byte [rsi], 0   ; Check for null terminator\n    jne     strToVar        ; loop if not null\n    ret\n"
  },
  {
    "path": "memrun.go",
    "content": "package main\n\nimport (\n\t\"fmt\"\n\t\"io/ioutil\"\n\t\"os\"\n\t\"syscall\"\n\t\"unsafe\"\n)\n\n// the constant values below are valid for x86_64\nconst (\n\tmfdCloexec  = 0x0001\n\tmemfdCreate = 319\n)\n\nfunc runFromMemory(displayName string, filePath string) {\n\tfdName := \"\" // *string cannot be initialized\n\tfd, _, _ := syscall.Syscall(memfdCreate, uintptr(unsafe.Pointer(&fdName)), uintptr(mfdCloexec), 0)\n\n\tbuffer, _ := ioutil.ReadFile(filePath)\n\t_, _ = syscall.Write(int(fd), buffer)\n\n\tfdPath := fmt.Sprintf(\"/proc/self/fd/%d\", fd)\n\t_ = syscall.Exec(fdPath, []string{displayName}, nil)\n}\n\nfunc main() {\n\tlenArgs := len(os.Args)\n\tif lenArgs < 3 || lenArgs > 3 {\n\t\tfmt.Println(\"Usage: memrun process_name elf_binary\")\n\t\tos.Exit(1)\n\t}\n\n\trunFromMemory(os.Args[1], os.Args[2])\n}\n"
  }
]