Uninformed: Informative Information for the Uninformed

Vol 5» 2006.Sep


First and foremost, the decoder_stub method gives an encoder module the opportunity to dynamically generate a decoder stub. The framework's idea of the decoder stub is equivalent to the stub header described in chapter [*]. In this case, it must simply provide a buffer whose assembly will set up a specific register to point to the start of the encoded data blocks as described in section [*]. The completed version of this method might look something like this:

def decoder_stub(state)
   len = ((state.buf.length + 3) & (~0x3)) / 4

   off = (datastore['BufferOffset'] || 0).to_i

   decoder =
      "\x6a" + [len].pack('C')      +  # push len
      "\x6b\x3c\x24\x0b"            +  # imul 0xb
      "\x60"                        +  # pusha
      "\x03\x0c\x24"                +  # add ecx, [esp]
      "\x6a" + [0x11+off].pack('C') +  # push byte 0x11 + off
      "\x03\x0c\x24"                +  # add ecx, [esp]
      "\x6a\x04"                       # push byte 0x4

   state.context = ''

   return decoder

In this routine, the length of the raw buffer, as found through state.buf.length, is aligned up to a four byte boundary and then divided by four. Following that, an optional buffer offset is stored in the off local variable. The purpose of the BufferOffset optional value is to allow exploits to cause the encoder to account for extra size overhead in the ecx register when doing its calculations. The decoder stub is then generated using the calculated length and offset to produce the stub header. The stub header is then returned to the caller.