예제 #1
0
   def get_secondary_lookup_code(self, base, size, sec_lookup_off,
                                 mapping_off):
       '''This secondary lookup is only used when rewriting only the main executable.  It is a second, simpler
      lookup function that is used by ret instructions and does NOT rewrite a return address on the stack
      when the destination is outside the mapping.  It instead simply returns the original address and that's
      it.  The only reason I'm doing this by way of a secondary lookup is this should be faster than a
      a parameter passed at runtime, so I need to statically have an offset to jump to in the case of returns.
      This is a cleaner way to do it than split the original lookup to have two entry points.'''
       secondary_lookup = '''
   lookup:
 	push ebx
 	mov ebx,eax
 	call get_eip
   get_eip:
 	pop eax
 	sub eax,%s
 	sub ebx,%s
 	jb outside
 	cmp ebx,%s
 	jae outside
 	mov ebx,[eax+ebx*4+%s]
 	add eax,ebx
 	pop ebx
 	ret
 
   outside:
 	add ebx,%s
 	mov eax,ebx
 	pop ebx
 	ret
   '''
       return _asm(secondary_lookup %
                   (sec_lookup_off + 8, base, size, mapping_off, base))
예제 #2
0
   def get_global_lookup_code(self):
       global_lookup_template = '''
   	cmp eax,[%s]
   	jz sysinfo
   glookup:
   	cmp BYTE PTR [gs:%s],1
   	jz failure
   	mov BYTE PTR [gs:%s],1
   	push eax
   	shr eax,12
   	shl eax,2
   	mov eax,[%s+eax]
   	mov DWORD PTR [esp-32],eax
   	cmp eax, 0xffffffff
   	jz abort
   	test eax,eax
   	jz loader
   	pop eax
         call [esp-36]
   	mov BYTE PTR [gs:%s],0
   	ret
   loader:
   	mov BYTE PTR [gs:%s],0
   	pop eax
   sysinfo:
   	push eax
   	mov eax,[esp+8]
   	call glookup
   	mov [esp+8],eax
   	pop eax
 	ret
   failure:
   	hlt
   abort:
   	hlt
   	mov eax,1
   	int 0x80
   '''
       return _asm(global_lookup_template %
                   (self.context.global_sysinfo, self.context.global_flag,
                    self.context.global_flag, self.context.global_sysinfo + 4,
                    self.context.global_flag, self.context.global_flag))
예제 #3
0
    def get_lookup_code(self, base, size, lookup_off, mapping_off):
        #Example assembly for lookup function
        '''
  	push edx
  	mov edx,eax
  	call get_eip
    get_eip:
  	pop eax			;Get current instruction pointer
  	sub eax,0x8248		;Subtract offset from instruction pointer val to get new text base addr
  	sub edx,0x8048000	;Compare to start (exclusive) and set edx to an offset in the mapping
  	jl outside		;Out of bounds (too small)
  	cmp edx,0x220		;Compare to end (inclusive) (note we are now comparing to the size)
  	jge outside		;Out of bounds (too big)
  	mov edx,[mapping+edx*4]	;Retrieve mapping entry (can't do this directly in generated func)
  	cmp edx, 0xffffffff	;Compare to invalid entry
  	je failure		;It was an invalid entry
  	add eax,edx		;Add the offset of the destination to the new text section base addr
  	pop edx
  	ret
    outside:			;If the address is out of the mapping bounds, return original address
  	add edx,0x8048000	;Undo subtraction of base, giving us the originally requested address
  	mov eax,edx		;Place the original request back in eax
  	pop edx
  	jmp global_lookup	;Check if global lookup can find this
    failure:
  	hlt
    '''
        lookup_template = '''
  	push ebx
  	mov ebx,eax
  	call get_eip
    get_eip:
  	pop eax
  	sub eax,%s
    	%s
  	jb outside
  	cmp ebx,%s
  	jae outside
  	mov ebx,[eax+ebx*4+%s]
  	cmp ebx, 0xffffffff
  	je failure
  	add eax,ebx
  	pop ebx
  	ret
    outside:
  	%s
  	mov eax,ebx
  	pop ebx
  	mov DWORD PTR [esp-32],%s
    	jmp [esp-32]
    failure:
  	hlt
    '''
        exec_code = '''
    	sub ebx,%s
    '''
        exec_restore = '''
    	add ebx,%s
    '''
        exec_only_lookup = '''
    lookup:
  	push ebx
  	mov ebx,eax
  	call get_eip
    get_eip:
  	pop eax
  	sub eax,%s
  	sub ebx,%s
  	jb outside
  	cmp ebx,%s
  	jae outside
  	mov ebx,[eax+ebx*4+%s]
  	add eax,ebx
  	pop ebx
  	ret
  
    outside:
  	add ebx,%s
  	mov eax,[esp+8]
  	call lookup
  	mov [esp+8],eax
  	mov eax,ebx
  	pop ebx
  	ret
    '''

        if self.count == 0:
            self.count = self.count + 1
            print exec_only_lookup % (lookup_off + 8, base, size, mapping_off,
                                      base)

        #For an .so, it can be loaded at an arbitrary address, so we cannot depend on
        #the base address being in a fixed location.  Therefore, we instead compute
        #the old text section's start address by using the new text section's offset
        #from it.  The new text section's offset equals the lookup address and is
        #stored in eax.  I use lea instead of add because it doesn't affect the flags,
        #which are used to determine if ebx is outside the range.
        so_code = '''
    	sub eax,%s
    	sub ebx,eax
    	lea eax,[eax+%s]
    '''
        so_restore = '''
    	sub eax,%s
    	add ebx,eax
    	add eax,%s
    '''
        #retrieve eip 8 bytes after start of lookup function
        if self.context.write_so:
            return _asm(lookup_template %
                        (lookup_off + 8, so_code %
                         (self.context.newbase, self.context.newbase), size,
                         mapping_off, so_restore %
                         (self.context.newbase, self.context.newbase),
                         self.context.global_lookup))
        elif self.context.exec_only:
            return _asm(exec_only_lookup %
                        (lookup_off + 8, base, size, mapping_off, base))
        else:
            return _asm(lookup_template %
                        (lookup_off + 8, exec_code % base, size, mapping_off,
                         exec_restore % base, self.context.global_lookup))
예제 #4
0
   def get_auxvec_code(self, entry):
       #Example assembly for searching the auxiliary vector
       '''
 	mov [esp-4],esi		;I think there's no need to save these, but in case somehow the
 	mov [esp-8],ecx		;linker leaves something of interest for _start, let's save them
 	mov esi,[esp]		;Retrieve argc
 	mov ecx,esp		;Retrieve address of argc
 	lea ecx,[ecx+esi*4+4]	;Skip argv
   loopenv:			;Iterate through each environment variable
 	add ecx,4		;The first loop skips over the NULL after argv
 	mov esi,[ecx]		;Retrieve environment variable
 	test esi,esi		;Check whether it is NULL
 	jnz loopenv		;If not, continue through environment vars
 	add ecx,4		;Hop over 0 byte to first entry
   loopaux:			;Iterate through auxiliary vector, looking for AT_SYSINFO (32)
 	mov esi,[ecx]		;Retrieve the type field of this entry
 	cmp esi,32		;Compare to 32, the entry we want
 	jz foundsysinfo		;Found it
 	test esi,esi		;Check whether we found the entry signifying the end of auxv
 	jz restore		;Go to _start if we reach the end
 	add ecx,8		;Each entry is 8 bytes; go to next
 	jmp loopaux
   foundsysinfo:
 	mov esi,[ecx+4]		;Retrieve sysinfo address
 	mov [sysinfo],esi	;Save address
   restore:
 	mov esi,[esp-4]
 	mov ecx,[esp-8]
   	push global_mapping	;Push address of global mapping for popgm
   	call popgm
   	add esp,4		;Pop address of global mapping
 	jmp realstart
   '''
       auxvec_template = '''
 	mov [esp-4],esi
 	mov [esp-8],ecx
 	mov esi,[esp]
 	mov ecx,esp
 	lea ecx,[ecx+esi*4+4]
   loopenv:
 	add ecx,4
 	mov esi,[ecx]
 	test esi,esi
 	jnz loopenv
 	add ecx,4
   loopaux:
 	mov esi,[ecx]
 	cmp esi,32
 	jz foundsysinfo
 	test esi,esi
 	jz restore
 	add ecx,8
 	jmp loopaux
   foundsysinfo:
 	mov esi,[ecx+4]
 	mov [%s],esi
   restore:
 	mov esi,[esp-4]
 	mov ecx,[esp-8]
   	push %s
   	call [esp]
   	add esp,4
   	mov DWORD PTR [esp-12], %s
 	jmp [esp-12]
   '''
       return _asm(auxvec_template %
                   (self.context.global_sysinfo, self.context.global_lookup +
                    self.context.popgm_offset, self.context.newbase + entry))