From 0ad175fa9af370d27f3185f8396c8929febdff92 Mon Sep 17 00:00:00 2001 From: A5t4t1ne <62953863+A5t4t1ne@users.noreply.github.com> Date: Mon, 9 Dec 2024 10:22:34 +0100 Subject: [PATCH 1/3] add nonnull encoder --- modules/encoders/aarch64/nonnull.rb | 90 +++++++++++++++++++++++++++++ 1 file changed, 90 insertions(+) create mode 100644 modules/encoders/aarch64/nonnull.rb diff --git a/modules/encoders/aarch64/nonnull.rb b/modules/encoders/aarch64/nonnull.rb new file mode 100644 index 000000000000..7e501515b99d --- /dev/null +++ b/modules/encoders/aarch64/nonnull.rb @@ -0,0 +1,90 @@ +## +# This module requires Metasploit: https://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +class MetasploitModule < Msf::Encoder + Rank = NormalRanking + + def initialize + super( + 'Name' => 'AArch64 null-byte encoder', + 'Description' => %q{ + Output is guaranteed to be NULL-byte free. + }, + 'Author' => 'A5t4t1ne', + 'Arch' => ARCH_AARCH64, + 'License' => MSF_LICENSE + ) + end + + # Encodes payload + def encode_block(state, buf) + enc_pl = '_' * buf.length * 2 # encoding nibbles to chars -> length will be doubled + + for i in 0...buf.length do + q = buf[i].ord + enc_pl[2 * i] = mkchr((q >> 4) & 0xF) # c will always be between 0x41 ('A') and 0x50 ('P') + enc_pl[2 * i + 1] = mkchr(q & 0xF) + end + + return decode_stub(state, enc_pl) + end + + def mkchr(ch) + return (0x41 + ch).chr + end + + # Generate the decode stub + def decode_stub(_state, enc_buf) + forward_jump, nops, backward_jump, while_condition = min_jmp_back(enc_buf) + + return 'jiL0' + # adr x10, 0x98D2D - calc addr of encoded shellcode + "JaB\xf1" + # subs x10, x10, #0x98, lsl #12 + "\x4a\x95\x34\xf1" + # subs x10, x10, #0xd25 + "\x4b\x01\x1f\xca" + # eor x11, x10, xzr - start of encoded shellcode becomes start of decoded instructions + 'sBSj' + # ands w19, w19, w19, lsr #16 - clear w19 + 'sBSj' + # ands w19, w19, w19, lsr #16 + 'b2Sj' + # ands w2, w19, w19, lsr #12 - clear w2 + while_condition + # loop: tbnz w2, #, #0x40 - branch to code after n-iterations + 'RQA9' + # ldrb w18, [x10, #84] - load first byte + 'YUA9' + # ldrb w25, [x10, #85] - load second byte + "Jm0\xb1" + # adds x10, x10, #0xc1b - encoded_buf_index += 2 + "Je0\xf1" + # subs x10, x10, #0xc19 + "\x52\x02\x04\x11" + # add w18, w18, #0x100 - sub 0x41 (upper nibble) + "\x52\x06\x05\x51" + # sub w18, w18, #0x141 + "\x39\x03\x04\x11" + # add w25, w25, #0x100 - sub 0x41 (lower nibble) + "\x39\x07\x05\x51" + # sub w25, w25, #0x141 + "\x39\x13\x12\x2a" + # orr w25, w25, w18, lsl #4 - assemble the nibbles to the original byte + "\x79\x51\x01\x39" + # strb w25, [x11, #84] - store original byte + "ki0\xb1" + # adds x11, x11, #0xc1a - x11++ decoded payload index + "ke0\xf1" + # subs x11, x11, #0xc19 + 'Bh01' + # adds w2, w2, #0xc1a - w2++ (loop counter) + 'Bd0q' + # subs w2, w2, #0xc19 + forward_jump + # tbz w19, #9, - jump into nops + enc_buf + + nops + + backward_jump # tbz w19, #9, - end of decoding while-loop + end + + def min_jmp_back(enc_buf) + jump_back_offsets = [ + [540, 600, "\xf3\x10\x48\x36", "\x53\xed\x4f\x36", "\x02\x02\x48\x37"], # +540, -600, 512 iterations + [1040, 1100, "\x93\x20\x48\x36", "\xb3\xdd\x4f\x36", "\x02\x02\x50\x37"], # +1040, -1100, 1024 iterations + [2060, 2140, "\x73\x40\x48\x36", "\x33\xbd\x4f\x36", "\x02\x02\x58\x37"], # +2060, -2140, 2048 iterations + [4140, 4276, "\x73\x81\x48\x36", 'szO6', "\x02\x02\x60\x37"], # +4140, -4276, 4096 iterations + ] + + jump_back_offsets.each do |val| + next if enc_buf.length >= val[0] + + bytes_to_fill = val[1] - enc_buf.length + nops = (bytes_to_fill / 4) - 16 # loop lbl is 16 instructions above buffer + + puts("nops: #{nops}, max size: #{val[0]}, buflen: #{enc_buf.length}") + return [val[2], "\x1f\x20\x03\xd5" * nops, val[3], val[4]] + end + + raise ArgumentError, 'Encoding failed, payload too big.' + end +end From 44585bcf45ddb379141e133abc7a60b18bfea402 Mon Sep 17 00:00:00 2001 From: A5t4t1ne <62953863+A5t4t1ne@users.noreply.github.com> Date: Mon, 9 Dec 2024 11:33:35 +0100 Subject: [PATCH 2/3] add comment --- modules/encoders/aarch64/nonnull.rb | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/modules/encoders/aarch64/nonnull.rb b/modules/encoders/aarch64/nonnull.rb index 7e501515b99d..db5a3bd4a1c1 100644 --- a/modules/encoders/aarch64/nonnull.rb +++ b/modules/encoders/aarch64/nonnull.rb @@ -1,6 +1,8 @@ ## # This module requires Metasploit: https://metasploit.com/download # Current source: https://github.com/rapid7/metasploit-framework +# +# This module was developed during a semester projecter under the supervision of the CYD campus. ## class MetasploitModule < Msf::Encoder @@ -10,7 +12,8 @@ def initialize super( 'Name' => 'AArch64 null-byte encoder', 'Description' => %q{ - Output is guaranteed to be NULL-byte free. + This encoder produces an output that is guaranteed to be NULL-byte free. + Max payload size is 4136 Bytes. }, 'Author' => 'A5t4t1ne', 'Arch' => ARCH_AARCH64, @@ -81,7 +84,6 @@ def min_jmp_back(enc_buf) bytes_to_fill = val[1] - enc_buf.length nops = (bytes_to_fill / 4) - 16 # loop lbl is 16 instructions above buffer - puts("nops: #{nops}, max size: #{val[0]}, buflen: #{enc_buf.length}") return [val[2], "\x1f\x20\x03\xd5" * nops, val[3], val[4]] end From ef9c0d85e5b6842d974aa8390506148c20d7b163 Mon Sep 17 00:00:00 2001 From: A5t4t1ne <62953863+A5t4t1ne@users.noreply.github.com> Date: Mon, 16 Dec 2024 11:03:55 +0100 Subject: [PATCH 3/3] change to each_char.with_index and fix typo --- modules/encoders/aarch64/nonnull.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/modules/encoders/aarch64/nonnull.rb b/modules/encoders/aarch64/nonnull.rb index db5a3bd4a1c1..0984e643ce87 100644 --- a/modules/encoders/aarch64/nonnull.rb +++ b/modules/encoders/aarch64/nonnull.rb @@ -2,7 +2,7 @@ # This module requires Metasploit: https://metasploit.com/download # Current source: https://github.com/rapid7/metasploit-framework # -# This module was developed during a semester projecter under the supervision of the CYD campus. +# This module was developed during a semester project under the supervision of the CYD campus. ## class MetasploitModule < Msf::Encoder @@ -25,8 +25,8 @@ def initialize def encode_block(state, buf) enc_pl = '_' * buf.length * 2 # encoding nibbles to chars -> length will be doubled - for i in 0...buf.length do - q = buf[i].ord + buf.each_char.with_index do |c, i| + q = c.ord enc_pl[2 * i] = mkchr((q >> 4) & 0xF) # c will always be between 0x41 ('A') and 0x50 ('P') enc_pl[2 * i + 1] = mkchr(q & 0xF) end