Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
99 changes: 99 additions & 0 deletions data/templates/src/elf/dll/elf_dll_loongarch64_template.s
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
; build with:
; nasm elf_dll_loongarch64_template.s -f bin -o template_loongarch64_linux_dll.bin

BITS 64

org 0

ehdr: ; Elf64_Ehdr
db 0x7F, "ELF", 2, 1, 1, 0 ; e_ident
db 0, 0, 0, 0, 0, 0, 0, 0 ;
dw 3 ; e_type = ET_DYN
dw 0x102 ; e_machine = LOONGARCH
dd 1 ; e_version
dq _start ; e_entry
dq phdr - $$ ; e_phoff
dq shdr - $$ ; e_shoff
dd 0 ; e_flags
dw ehdrsize ; e_ehsize
dw phdrsize ; e_phentsize
dw 2 ; e_phnum
dw shentsize ; e_shentsize
dw 2 ; e_shnum
dw 1 ; e_shstrndx

ehdrsize equ $ - ehdr

phdr: ; Elf32_Phdr
dd 1 ; p_type = PT_LOAD
dd 7 ; p_flags = rwx
dq 0 ; p_offset
dq $$ ; p_vaddr
dq $$ ; p_paddr
dq 0xDEADBEEF ; p_filesz
dq 0xDEADBEEF ; p_memsz
dq 0x1000 ; p_align

phdrsize equ $ - phdr
dd 2 ; p_type = PT_DYNAMIC
dd 7 ; p_flags = rwx
dq dynsection ; p_offset
dq dynsection ; p_vaddr
dq dynsection ; p_vaddr
dq dynsz ; p_filesz
dq dynsz ; p_memsz
dq 0x1000 ; p_align

shdr:
dd 1 ; sh_name
dd 6 ; sh_type = SHT_DYNAMIC
dq 0 ; sh_flags
dq dynsection ; sh_addr
dq dynsection ; sh_offset
dq dynsz ; sh_size
dd 0 ; sh_link
dd 0 ; sh_info
dq 8 ; sh_addralign
dq 7 ; sh_entsize
shentsize equ $ - shdr
dd 0 ; sh_name
dd 3 ; sh_type = SHT_STRTAB
dq 0 ; sh_flags
dq strtab ; sh_addr
dq strtab ; sh_offset
dq strtabsz ; sh_size
dd 0 ; sh_link
dd 0 ; sh_info
dq 0 ; sh_addralign
dq 0 ; sh_entsize

dynsection:
; DT_INIT
dq 0x0c
dq _start
; DT_STRTAB
dq 0x05
dq strtab
; DT_SYMTAB
dq 0x06
dq strtab
; DT_STRSZ
dq 0x0a
dq 0
; DT_SYMENT
dq 0x0b
dq 0
; DT_NULL
dq 0x00
dq 0

dynsz equ $ - dynsection

strtab:
db 0
db 0
strtabsz equ $ - strtab

align 16
global _start
_start:
42 changes: 42 additions & 0 deletions data/templates/src/elf/exe/elf_loongarch64_template.s
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
; build with:
; nasm elf_loongarch64_template.s -f bin -o template_loongarch64_linux.bin

BITS 64

org 0x80400000

ehdr: ; Elf32_Ehdr
db 0x7F, "ELF", 2, 1, 1, 0 ; e_ident
db 0, 0, 0, 0, 0, 0, 0, 0 ;
dw 2 ; e_type = ET_EXEC for an executable
dw 0x102 ; e_machine = LOONGARCH
dd 1 ; e_version
dq _start ; e_entry
dq phdr - $$ ; e_phoff
dq 0 ; e_shoff
dd 0 ; e_flags
dw ehdrsize ; e_ehsize
dw phdrsize ; e_phentsize
dw 1 ; e_phnum
dw 0 ; e_shentsize
dw 0 ; e_shnum
dw 0 ; e_shstrndx

ehdrsize equ $ - ehdr

phdr: ; Elf32_Phdr
dd 1 ; p_type = PT_LOAD
dd 7 ; p_flags = rwx
dq 0 ; p_offset
dq $$ ; p_vaddr
dq $$ ; p_paddr
dq 0xDEADBEEF ; p_filesz
dq 0xDEADBEEF ; p_memsz
dq 0x1000 ; p_align

phdrsize equ $ - phdr

global _start

_start:

Binary file added data/templates/template_loongarch64_linux.bin
Binary file not shown.
Binary file added data/templates/template_loongarch64_linux_dll.bin
Binary file not shown.
33 changes: 33 additions & 0 deletions lib/msf/util/exe.rb
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,13 @@ def self.to_executable(framework, arch, plat, code = '', opts = {})
# TODO: Add remaining RISCV64LE systems here
end

if arch.index(ARCH_LOONGARCH64)
if plat.index(Msf::Module::Platform::Linux)
return to_linux_loongarch64_elf(framework, code)
end
# TODO: Add remaining LOONGARCH64 systems here
end

nil
end

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

# Create a LOONGARCH64 64-bit LE Linux ELF containing the payload provided in +code+
#
# @param framework [Msf::Framework]
# @param code [String]
# @param opts [Hash]
# @option [String] :template
# @return [String] Returns an elf
def self.to_linux_loongarch64_elf(framework, code, opts = {})
to_exe_elf(framework, opts, "template_loongarch64_linux.bin", code)
end

# Create a LOONGARCH64 64-bit LE Linux ELF_DYN containing the payload provided in +code+
#
# @param framework [Msf::Framework]
# @param code [String]
# @param opts [Hash]
# @option [String] :template
# @return [String] Returns an elf
def self.to_linux_loongarch64_elf_dll(framework, code, opts = {})
to_exe_elf(framework, opts, "template_loongarch64_linux_dll.bin", code)
end

# self.to_exe_vba
#
# @param exes [String]
Expand Down Expand Up @@ -2208,6 +2237,8 @@ def self.to_executable_fmt(framework, arch, plat, code, fmt, exeopts)
to_linux_riscv32le_elf(framework, code, exeopts)
when ARCH_RISCV64LE
to_linux_riscv64le_elf(framework, code, exeopts)
when ARCH_LOONGARCH64
to_linux_loongarch64_elf(framework, code, exeopts)
end
elsif plat && plat.index(Msf::Module::Platform::BSD)
case arch
Expand Down Expand Up @@ -2240,6 +2271,8 @@ def self.to_executable_fmt(framework, arch, plat, code, fmt, exeopts)
to_linux_riscv32le_elf_dll(framework, code, exeopts)
when ARCH_RISCV64LE
to_linux_riscv64le_elf_dll(framework, code, exeopts)
when ARCH_LOONGARCH64
to_linux_loongarch64_elf_dll(framework, code, exeopts)
end
end
when 'macho', 'osx-app'
Expand Down
135 changes: 135 additions & 0 deletions modules/nops/loongarch64/simple.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
##
# This module requires Metasploit: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##

# This class implements a simple NOP generator for LoongArch 64-bit (Little Endian)
class MetasploitModule < Msf::Nop

def initialize
super(
'Name' => 'Simple',
'Alias' => 'loongarch64_simple',
'Description' => 'Simple NOP generator',
'License' => MSF_LICENSE,
'Author' => ['bcoles'],
'Arch' => ARCH_LOONGARCH64)
register_advanced_options([
OptBool.new('RandomNops', [false, 'Generate a random NOP sled', true]),
])
end

def generate_sled(length, opts)
badchars = opts['BadChars'] || ''
random = opts['Random'] || datastore['RandomNops']

# Safe NULL-free nops using general purpose registers ($r12 - $r31)
# All instructions are NULL-free from the base ISA,
# excluding optional extensions (FPU, LSX, LASX, ...)
nops = [
[0x03c0018c].pack('V'), # xori $t0, $t0, 0
[0x03c001ad].pack('V'), # xori $t1, $t1, 0
[0x03c001ce].pack('V'), # xori $t2, $t2, 0
[0x03c001ef].pack('V'), # xori $t3, $t3, 0
[0x03c00210].pack('V'), # xori $t4, $t4, 0
[0x03c00231].pack('V'), # xori $t5, $t5, 0
[0x03c00252].pack('V'), # xori $t6, $t6, 0
[0x03c00273].pack('V'), # xori $t7, $t7, 0
[0x03c00294].pack('V'), # xori $t8, $t8, 0
[0x03c002b5].pack('V'), # xori $r21, $r21, 0
[0x03c002d6].pack('V'), # xori $fp, $fp, 0
[0x03c002f7].pack('V'), # xori $s0, $s0, 0
[0x03c00318].pack('V'), # xori $s1, $s1, 0
[0x03c00339].pack('V'), # xori $s2, $s2, 0
[0x03c0035a].pack('V'), # xori $s3, $s3, 0
[0x03c0037b].pack('V'), # xori $s4, $s4, 0
[0x03c0039c].pack('V'), # xori $s5, $s5, 0
[0x03c003bd].pack('V'), # xori $s6, $s6, 0
[0x03c003de].pack('V'), # xori $s7, $s7, 0
[0x03c003ff].pack('V'), # xori $s8, $s8, 0

[0x0380018c].pack('V'), # ori $t0, $t0, 0
[0x038001ad].pack('V'), # ori $t1, $t1, 0
[0x038001ce].pack('V'), # ori $t2, $t2, 0
[0x038001ef].pack('V'), # ori $t3, $t3, 0
[0x03800210].pack('V'), # ori $t4, $t4, 0
[0x03800231].pack('V'), # ori $t5, $t5, 0
[0x03800252].pack('V'), # ori $t6, $t6, 0
[0x03800273].pack('V'), # ori $t7, $t7, 0
[0x03800294].pack('V'), # ori $t8, $t8, 0
[0x038002b5].pack('V'), # ori $r21, $r21, 0
[0x038002d6].pack('V'), # ori $fp, $fp, 0
[0x038002f7].pack('V'), # ori $s0, $s0, 0
[0x03800318].pack('V'), # ori $s1, $s1, 0
[0x03800339].pack('V'), # ori $s2, $s2, 0
[0x0380035a].pack('V'), # ori $s3, $s3, 0
[0x0380037b].pack('V'), # ori $s4, $s4, 0
[0x0380039c].pack('V'), # ori $s5, $s5, 0
[0x038003bd].pack('V'), # ori $s6, $s6, 0
[0x038003de].pack('V'), # ori $s7, $s7, 0
[0x038003ff].pack('V'), # ori $s8, $s8, 0

[0x02c0018c].pack('V'), # addi.d $t0, $t0, 0
[0x02c001ad].pack('V'), # addi.d $t1, $t1, 0
[0x02c001ce].pack('V'), # addi.d $t2, $t2, 0
[0x02c001ef].pack('V'), # addi.d $t3, $t3, 0
[0x02c00210].pack('V'), # addi.d $t4, $t4, 0
[0x02c00231].pack('V'), # addi.d $t5, $t5, 0
[0x02c00252].pack('V'), # addi.d $t6, $t6, 0
[0x02c00273].pack('V'), # addi.d $t7, $t7, 0
[0x02c00294].pack('V'), # addi.d $t8, $t8, 0
[0x02c002b5].pack('V'), # addi.d $r21, $r21, 0
[0x02c002d6].pack('V'), # addi.d $fp, $fp, 0
[0x02c002f7].pack('V'), # addi.d $s0, $s0, 0
[0x02c00318].pack('V'), # addi.d $s1, $s1, 0
[0x02c00339].pack('V'), # addi.d $s2, $s2, 0
[0x02c0035a].pack('V'), # addi.d $s3, $s3, 0
[0x02c0037b].pack('V'), # addi.d $s4, $s4, 0
[0x02c0039c].pack('V'), # addi.d $s5, $s5, 0
[0x02c003bd].pack('V'), # addi.d $s6, $s6, 0
[0x02c003de].pack('V'), # addi.d $s7, $s7, 0
[0x02c003ff].pack('V'), # addi.d $s8, $s8, 0

[0x0280018c].pack('V'), # addi.w $t0, $t0, 0
[0x028001ad].pack('V'), # addi.w $t1, $t1, 0
[0x028001ce].pack('V'), # addi.w $t2, $t2, 0
[0x028001ef].pack('V'), # addi.w $t3, $t3, 0
[0x02800210].pack('V'), # addi.w $t4, $t4, 0
[0x02800231].pack('V'), # addi.w $t5, $t5, 0
[0x02800252].pack('V'), # addi.w $t6, $t6, 0
[0x02800273].pack('V'), # addi.w $t7, $t7, 0
[0x02800294].pack('V'), # addi.w $t8, $t8, 0
[0x028002b5].pack('V'), # addi.w $r21, $r21, 0
[0x028002d6].pack('V'), # addi.w $fp, $fp, 0
[0x028002f7].pack('V'), # addi.w $s0, $s0, 0
[0x02800318].pack('V'), # addi.w $s1, $s1, 0
[0x02800339].pack('V'), # addi.w $s2, $s2, 0
[0x0280035a].pack('V'), # addi.w $s3, $s3, 0
[0x0280037b].pack('V'), # addi.w $s4, $s4, 0
[0x0280039c].pack('V'), # addi.w $s5, $s5, 0
[0x028003bd].pack('V'), # addi.w $s6, $s6, 0
[0x028003de].pack('V'), # addi.w $s7, $s7, 0
[0x028003ff].pack('V'), # addi.w $s8, $s8, 0
]

# Remove nops containing BadChars
nops.delete_if do |nop|
nop.bytes.any? { |byte| badchars.force_encoding('BINARY').include?(byte.chr) }
end

# Give up if no safe nops are available
return if nops.empty?

# Use random instructions for all NOPs
if random
sled = ''
(length / 4).times do
sled << nops.sample
end
return sled
end

# Use a single instruction for all NOPs
return (nops.sample * (length / 4))
end
end
48 changes: 48 additions & 0 deletions modules/payloads/singles/linux/loongarch64/reboot.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
##
# This module requires Metasploit: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##

module MetasploitModule
CachedSize = 32

include Msf::Payload::Single
include Msf::Payload::Linux

def initialize(info = {})
super(
merge_info(
info,
'Name' => 'Linux Reboot',
'Description' => %q{
A very small shellcode for rebooting the system using
the reboot syscall. This payload is sometimes helpful
for testing purposes. Requires CAP_SYS_BOOT privileges.
},
'Author' => 'bcoles',
'License' => MSF_LICENSE,
'Platform' => 'linux',
'Arch' => ARCH_LOONGARCH64,
'References' => [
['URL', 'https://man7.org/linux/man-pages/man2/reboot.2.html'],
['URL', 'https://github.com/bcoles/shellcode/blob/main/loongarch64/reboot/reboot.s'],
]
)
)
end

def generate(_opts = {})
shellcode = [
0x15fdc3a4, # lu12i.w $a0, -4579
0x03bab484, # ori $a0, $a0, 0xead
0x14502425, # lu12i.w $a1, 164129
0x03a5a4a5, # ori $a1, $a1, 0x969
0x14024686, # lu12i.w $a2, 4660
0x03959cc6, # ori $a2, $a2, 0x567
0x0382380b, # li.w $a7, 0x8e
0x002b0101, # syscall 0x101
].pack('V*')

super.to_s + shellcode
end
end
Loading
Loading