Fix byte_xori encoder

The byte_xori encoder for mipsbe does not work correctly. At the end of the decoding, it should invoke cacheflush() with the correct parameters:
int cacheflush(char *addr, int nbytes, int cache)

I think this is because the encoder is based of the longxori encoder, which itself is pretty old (2008), and before kernel 2.6.11, cacheflush() did not need any parameters (from the cacheflush man page):
BUGS
Linux kernels older than version 2.6.11 ignore the addr and nbytes arguments, making this function fairly expensive. Therefore, the whole cache is always flushed.

This commit fixes that by setting up the parameters correctly. As an unfortunate side effect this increases the shellcode by 16 bytes, but it is absolutely necessary for it to work properly.

Note that this bug is not present when testing the encoder output on an emulator like qemu; emulators do not need to flush the caches to work properly.
GSoC/Meterpreter_Web_Console
Pedro Ribeiro 2018-12-18 15:37:47 +00:00 committed by GitHub
parent 483a3618ae
commit 34c9555717
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 10 additions and 3 deletions

View File

@ -18,8 +18,9 @@ class MetasploitModule < Msf::Encoder::Xor
},
'Author' =>
[
'Julien Tinnes <julien[at]cr0.org>', # original longxor encoder, which this one is based on
'juan vazquez' # byte_xori encoder
'Julien Tinnes <julien[at]cr0.org>', # original longxor encoder, which this one is based on
'juan vazquez', # byte_xori encoder
'Pedro Ribeiro <pedrib@gmail.com>', # fix for Linux >= 2.6.11 (set up cacheflush() args properly)
],
'Arch' => ARCH_MIPSBE,
'License' => MSF_LICENSE,
@ -44,6 +45,7 @@ class MetasploitModule < Msf::Encoder::Xor
# 16-bits not (again, see also commented source)
reg_14 = (number_of_passes+1)^0xFFFF
reg_5 = state.buf.length^0xFFFF
decoder = Metasm::Shellcode.assemble(Metasm::MIPS.new(:big), <<EOS).encoded.data
main:
@ -54,7 +56,7 @@ endm
li ($14, #{reg_14}) ; 0x240exxxx - store in $14 the number of passes (two's complement) - xxxx (number of passes)
nor $14, $14, $0 ; 0x01c07027 - get in $14 the number of passes
li ($11,-69) ; 0x240bffbb - store in $11 the offset to the end of the decoder (two's complement) (from the addu instr)
li ($11,-84) ; 0x240bffbb - store in $11 the offset to the end of the decoder (two's complement) (from the addu instr)
; acts as getpc
next:
@ -63,6 +65,7 @@ next:
nor $11, $11, $0 ; 0x01605827 - get in $11 the offset to the end of the decoder (from the addu instr)
addu $25, $31, $11 ; 0x03ebc821 - get in $25 a pointer to the end of the decoder stub
addu $16, $31, $11 ; $16 too (used to set up the cacheflush() arg down below)
slti $23, $0, 0x#{slti_imm(state)} ; 0x2817xxxx - Set $23 = 0 (Set $23 = 1 if $0 < imm; else $23 = 0) / xxxx: imm
lb $17, -1($25) ; 0x8f31fffc - Load xor key in $17 (stored on the last byte of the decoder stub)
@ -83,6 +86,10 @@ loop:
bne $0, $30, loop ; 0x17c0fff9 - branch to loop if $30 != 0 (ranch while bytes to decode)
addu $25, $25, $15 ; 0x032dc821 - next instruction to decode, executed because of the pipelining
addiu $4, $16, -4 ; cacheflush() addr parameter
li( $10,#{reg_5}) ; cacheflush() nbytes parameter
nor $5, $10, $0 ; same as above
li ($2, 4147) ; 0x24021033 - cacheflush sytem call
syscall 0x52950 ; 0x014a540c
nop ; encoded shellcoded must be here (xor key right here ;) after decoding will result in a nop