Example #1
0
File: darwin.c Project: 8l/go-learn
// Read/write from a Mach data segment.
static int
machsegrw(Map *map, Seg *seg, uvlong addr, void *v, uint n, int isr)
{
	mach_port_t task;
	int r;

	task = idtotask(map->pid);
	if(task == -1)
		return -1;

	if(isr){
		vm_size_t nn;
		nn = n;
		if(me(vm_read_overwrite(task, addr, n, (uintptr)v, &nn)) < 0)
			return -1;
		return nn;
	}else{
		r = vm_write(task, addr, (uintptr)v, n);
		if(r == KERN_INVALID_ADDRESS){
			// Happens when writing to text segment.
			// Change protections.
			if(me(vm_protect(task, addr, n, 0, VM_PROT_WRITE|VM_PROT_READ|VM_PROT_EXECUTE)) < 0){
				fprint(2, "vm_protect: %s\n", r);
				return -1;
			}
			r = vm_write(task, addr, (uintptr)v, n);
		}
		if(r != 0){
			me(r);
			return -1;
		}
		return n;
	}
}
Example #2
0
/**
 * (Safely) read len bytes from @a source, storing in @a dest.
 *
 * @param task The task from which data from address @a source will be read.
 * @param source The address within @a task from which the data will be read.
 * @param dest The destination address to which copied data will be written.
 * @param len The number of bytes to be read.
 *
 * @return On success, returns KERN_SUCCESS. If the pages containing @a source + len are unmapped, KERN_INVALID_ADDRESS
 * will be returned. If the pages can not be read due to access restrictions, KERN_PROTECTION_FAILURE will be returned.
 *
 * @warning Unlike all other plcrash_* functions, plcrash_async_read_addr returns a kern_return_t value.
 * @todo Modify plcrash_async_read_addr and all API clients to use plcrash_error_t values.
 */
kern_return_t plcrash_async_read_addr (mach_port_t task, pl_vm_address_t source, void *dest, pl_vm_size_t len) {
#ifdef PL_HAVE_MACH_VM
    pl_vm_size_t read_size = len;
    return mach_vm_read_overwrite(task, source, len, (pointer_t) dest, &read_size);
#else
    vm_size_t read_size = len;
    return vm_read_overwrite(task, source, len, (pointer_t) dest, &read_size);
#endif
}
kern_return_t ksmach_copyMem(const void* const src, void* const dst, const int numBytes)
{
    vm_size_t bytesCopied = 0;
    return vm_read_overwrite(mach_task_self(),
                             (vm_address_t)src,
                             (vm_size_t)numBytes,
                             (vm_address_t)dst,
                             &bytesCopied);
}
Example #4
0
static int __read(RIO *io, RIODesc *fd, ut8 *buf, int len) {
	vm_size_t size = 0;
        int err = vm_read_overwrite (RIOMACH_TASK (fd->data),
		(vm_offset_t)io->off, len, (pointer_t)buf, &size);
        if (err == -1) {
                eprintf ("Cannot read\n");
                return -1;
        }
        return (int)size;
}
Example #5
0
static int __read(RIO *io, RIODesc *fd, ut8 *buf, int len) {
	vm_size_t size = 0;
	int blen, err, copied = 0;
	int blocksize = 32;
	RIOMach *riom = (RIOMach *)fd->data;

	if (task_is_dead (riom->pid)) {
		return -1;
	}
	memset (buf, 0xff, len);
	if (RIOMACH_PID (fd->data) == 0) {
		if (io->off < 4096) {
			return len;
		}
	}
	copied = getNextValid (io, fd, io->off) - io->off;
	if (copied < 0) copied = 0;

	while (copied < len) {
		blen = R_MIN ((len - copied), blocksize);
		//blen = len;
		err = vm_read_overwrite (RIOMACH_TASK (fd->data),
			(ut64)io->off + copied, blen,
			(pointer_t)buf + copied, &size);
		switch (err) {
		case KERN_PROTECTION_FAILURE:
			//eprintf ("r_io_mach_read: kern protection failure.\n");
			break;
		case KERN_INVALID_ADDRESS:
			if (blocksize == 1) {
				memset (buf+copied, 0xff, len-copied);
				return size+copied;
			}
			blocksize = 1;
			blen = 1;
			buf[copied] = 0xff;
			break;
		}
		if (err == -1 || size < 1) {
			return -1;
		}
		if (size == 0) {
			if (blocksize == 1) {
				memset (buf+copied, 0xff, len-copied);
				return len;
			}
			blocksize = 1;
			blen = 1;
			buf[copied] = 0xff;
		}
		copied += blen;
	}
	return len;
}
Example #6
0
kern_return_t Task_readMemory(Task* self, VMAddr addr, void* data, vm_size_t length) {
	kern_return_t retVal = KERN_INVALID_ARGUMENT;
	if (self == NULL || data == NULL) {
		Log_invalidArgument("self: %p, data: %p", self, data);
		
	} else {
		vm_size_t count = length;
		retVal = vm_read_overwrite(self->task, addr, length, (vm_address_t) data, &count);
		if (retVal != KERN_SUCCESS || length != count) {
			Log_errorMach(retVal, "vm_read_overwrite");
			
		}
	}
	return retVal;
}
Example #7
0
static bool readProcessMemory(const mach_port_t &task,
                              const vm_address_t &from,
                              const vm_size_t &size,
                              vm_address_t to) {
  vm_size_t bytes;
  auto status = vm_read_overwrite(task, from, size, to, &bytes);
  if (status != KERN_SUCCESS) {
    return false;
  }

  if (bytes != size) {
    return false;
  }
  return true;
}
Example #8
0
static int __read(RIO *io, RIODesc *fd, ut8 *buf, int len) {
	vm_size_t size = 0;
	int blen, err, copied = 0;
	int blocksize = 32;
	if (RIOMACH_PID (fd->data) == 0) {
		if (io->off<4096)
			return len;
	}
	memset (buf, 0xff, len);
	while (copied<len) {
		blen = R_MIN ((len-copied), blocksize);
		//blen = len;
		err = vm_read_overwrite (RIOMACH_TASK (fd->data),
			(ut64)io->off+copied, blen, (pointer_t)buf+copied, &size);
		switch (err) {
		case KERN_PROTECTION_FAILURE:
			//eprintf ("r_io_mach_read: kern protection failure.\n");
			break;
		case KERN_INVALID_ADDRESS:
			if (blocksize == 1) {
				memset (buf+copied, 0xff, len-copied);
				return size+copied;
			}
			blocksize = 1;
			blen = 1;
			buf[copied] = 0xff;
			//eprintf("invaddr %d\n",len);
			break;
		}
		if (err == -1) {
			//eprintf ("Cannot read\n");
			return -1;
		}
		if (size==0) {
			if (blocksize == 1) {
				memset (buf+copied, 0xff, len-copied);
				return len; //size+copied;
			}
			blocksize = 1;
			blen = 1;
			buf[copied] = 0xff;
		}
		//if (size != blen) { return size+copied; }
		copied += blen;
	}
	return len; //(int)size;
}
Example #9
0
uint8_t* _yr_fetch_block_data(
    YR_MEMORY_BLOCK* block)
{
  YR_PROC_ITERATOR_CTX* context = (YR_PROC_ITERATOR_CTX*) block->context;
  vm_size_t size = block->size;

  if (context->buffer_size < block->size)
  {
    if (context->buffer != NULL)
      yr_free(context->buffer);

    context->buffer = yr_malloc(block->size);

    if (context->buffer != NULL)
    {
      context->buffer_size = block->size;
    }
    else
    {
      context->buffer_size = 0;
      return NULL;
    }
  }

  if (vm_read_overwrite(
      context->task,
      block->base,
      block->size,
      (vm_address_t) context->buffer,
      &size) != KERN_SUCCESS)
  {
    return NULL;
  }

  return context->buffer;
}
Example #10
0
int yr_process_get_memory(
    pid_t pid,
    YR_MEMORY_BLOCK** first_block)
{
  task_t task;
  kern_return_t kr;

  vm_size_t size = 0;
  vm_address_t address = 0;
  vm_region_basic_info_data_64_t info;
  mach_msg_type_number_t info_count;
  mach_port_t object;

  unsigned char* data;

  YR_MEMORY_BLOCK* new_block;
  YR_MEMORY_BLOCK* current_block = NULL;

  *first_block = NULL;

  if ((kr = task_for_pid(mach_task_self(), pid, &task)) != KERN_SUCCESS)
    return ERROR_COULD_NOT_ATTACH_TO_PROCESS;

  do {

    info_count = VM_REGION_BASIC_INFO_COUNT_64;

    kr = vm_region_64(
        task,
        &address,
        &size,
        VM_REGION_BASIC_INFO,
        (vm_region_info_t) &info,
        &info_count,
        &object);

    if (kr == KERN_SUCCESS)
    {
      data = (unsigned char*) yr_malloc(size);

      if (data == NULL)
        return ERROR_INSUFICIENT_MEMORY;

      if (vm_read_overwrite(
              task,
              address,
              size,
              (vm_address_t)
              data,
              &size) == KERN_SUCCESS)
      {
        new_block = (YR_MEMORY_BLOCK*) yr_malloc(sizeof(YR_MEMORY_BLOCK));

        if (new_block == NULL)
        {
          yr_free(data);
          return ERROR_INSUFICIENT_MEMORY;
        }

        if (*first_block == NULL)
          *first_block = new_block;

        new_block->base = address;
        new_block->size = size;
        new_block->data = data;
        new_block->next = NULL;

        if (current_block != NULL)
          current_block->next = new_block;

        current_block = new_block;
      }
      else
      {
        yr_free(data);
      }

      address += size;
    }


  } while (kr != KERN_INVALID_ADDRESS);

  if (task != MACH_PORT_NULL)
    mach_port_deallocate(mach_task_self(), task);

  return ERROR_SUCCESS;
}
/**
 * (Safely) read len bytes from addr, storing in dest. Uses mach vm_read_overwrite to
 * avoid dereferencing a bad pointer.
 */
kern_return_t plframe_read_addr (const void *source, void *dest, size_t len) {
    vm_size_t read_size = len;
    return vm_read_overwrite(mach_task_self(), (vm_address_t) source, len, (pointer_t) dest, &read_size);
}
Example #12
0
static OSStatus DoLoadMemory(
	AuthorizationRef			auth,
    const void *                userData,
	CFDictionaryRef				request,
	CFMutableDictionaryRef      response,
    aslclient                   asl,
    aslmsg                      aslMsg
)
    // Implements the kGetUIDsCommand.  Gets the process's three UIDs and 
    // adds them to the response dictionary.
{	
	//asl_log(asl, aslMsg, ASL_LEVEL_DEBUG, "DoLoadMemory()");
    
	// Pre-conditions
    if(auth == NULL || request == NULL || response == NULL)
        return kMemToolBadParameter;
    
    // CFShow(request);
    
    // load in the WoW ProcessID
    pid_t wowPID = 0;
    CFNumberRef cfPID = CFDictionaryGetValue(request, CFSTR(kWarcraftPID));
    if(!CFNumberGetValue(cfPID, kCFNumberIntType, &wowPID) || wowPID <= 0) {
        return kMemToolBadPID;
    }
    
    // load in the memory address
    unsigned int address = 0;
    CFNumberRef cfAddress = CFDictionaryGetValue(request, CFSTR(kMemoryAddress));
    if(!CFNumberGetValue(cfAddress, kCFNumberIntType, &address) || address == 0) {
        return kMemToolBadAddress;
    }
    
    // load in memory length
    vm_size_t length = 0;
    CFNumberRef cfLength = CFDictionaryGetValue(request, CFSTR(kMemoryLength));
    if(!CFNumberGetValue(cfLength, kCFNumberIntType, &length) || length == 0) {
        return kMemToolBadLength;
    }
    
    bool memSuccess = false;
    if(wowPID && address && length) {
        //asl_log(asl, aslMsg, ASL_LEVEL_DEBUG, "Reading pid %d at address 0x%X for length %d", wowPID, address, length);
        
        // create buffer for our data
        Byte buffer[length];
        
        int i;
        for(i=0; i<length; i++)
            buffer[i] = 0;
        
        // get a handle on the WoW task
        mach_port_t wowTask;
        task_for_pid(current_task(), wowPID, &wowTask);
        
        vm_size_t bytesRead = length;
        memSuccess = ((KERN_SUCCESS == vm_read_overwrite(wowTask, address, length, (vm_address_t)&buffer, &bytesRead)) && (bytesRead == length) );
        
        //(KERN_SUCCESS == vm_write(wowTask, address, (vm_offset_t)&buffer, length));
        
        if(memSuccess) {
            CFDataRef memoryContents = CFDataCreate(NULL, buffer, length);
            if(memoryContents != NULL) {
                // we got our memory! add it to the return dictionary
                CFDictionaryAddValue(response, CFSTR(kMemoryContents), memoryContents);
                CFRelease(memoryContents);
                return kMemToolNoError;
            }
        }
    } else {
        return kMemToolBadParameter;
    }

	return kMemToolUnknown;
}
Example #13
0
static int __read(RIO *io, RIODesc *desc, ut8 *buf, int len) {
	vm_size_t size = 0;
	int blen, err, copied = 0;
	int blocksize = 32;
	RIODescData *dd = (RIODescData *)desc->data;
	if (!io || !desc || !buf || !dd) {
		return -1;
	}
	if (dd ->magic != r_str_hash ("mach")) {
		return -1;
	}
	memset (buf, 0xff, len);
	int pid = __get_pid (desc);
	task_t task = pid_to_task (desc, pid);
	if (task_is_dead (desc, pid)) {
		return -1;
	}
	if (pid == 0) {
		if (io->off < 4096) {
			return len;
		}
	}
	copied = getNextValid (io, desc, io->off) - io->off;
	if (copied < 0) {
		copied = 0;
	}
	while (copied < len) {
		blen = R_MIN ((len - copied), blocksize);
		//blen = len;
		err = vm_read_overwrite (task,
			(ut64)io->off + copied, blen,
			(pointer_t)buf + copied, &size);
		switch (err) {
		case KERN_PROTECTION_FAILURE:
			//eprintf ("r_io_mach_read: kern protection failure.\n");
			break;
		case KERN_INVALID_ADDRESS:
			if (blocksize == 1) {
				memset (buf+copied, 0xff, len-copied);
				return size+copied;
			}
			blocksize = 1;
			blen = 1;
			buf[copied] = 0xff;
			break;
		}
		if (err == -1 || size < 1) {
			return -1;
		}
		if (size == 0) {
			if (blocksize == 1) {
				memset (buf + copied, 0xff, len - copied);
				return len;
			}
			blocksize = 1;
			blen = 1;
			buf[copied] = 0xff;
		}
		copied += blen;
	}
	return len;
}
Example #14
0
int dump_kernel_task(int argc, char *argv[])
{
    task_t task;
    kern_return_t error;
    pid_t pid = 0;
    int fd;
    
    error = task_for_pid(mach_task_self(), pid, &task);
    if (error != KERN_SUCCESS) {
        printf("task for pid failed for pid=%d error=%d\n", pid, error);
    	return 0;
    }

    vm_address_t address=0;
    char *buf = malloc(4096);
    vm_address_t start = strtoul(argv[1],0,0);
    vm_address_t end = strtoul(argv[2], 0, 0);
    int ret;

    printf("Reading from %x to %x\n", start, end);
    fd = -1;
    for (address = start; address < end; address += 0x1000)
    {
        memset(buf, 0, 4096);
        mach_msg_type_number_t count = 0;
        
        //
        // Region is mapped 0,0. but there's a bug where
        // reading < 4096 will work :-) 
        //
        ret = vm_read_overwrite
                (task,
                 address,
                 PAGE_SIZE/2,
                 buf,
                 &count);
        if (ret == 0)
        {
            ret = vm_read_overwrite
                    (task,
                     address + PAGE_SIZE/2,
                     PAGE_SIZE/2,
                     buf + PAGE_SIZE/2,
                     &count);
        }
             
        if (ret == 0)
        {
            if (fd == -1)
            {
                char namebuf[40];
                sprintf(namebuf, "kmem/%.8x.mem", address);
                fd = open(namebuf, O_CREAT|O_WRONLY);
                if (fd == -1){
                    printf("unable to open file %s for writing\n", namebuf);
                    break;
                }
            }
            write(fd, buf, 4096);
        } else
        {
            printf("Failed to read: ret=%d address= %x", ret, address);
            break;
        }
    }

    close(fd);
   
    printf("Finished\n");
    mach_port_deallocate(mach_task_self(), task);
    return 0;
}
Example #15
0

#include "KSMemory.h"

//#define KSLogger_LocalLevel TRACE
#include "KSLogger.h"

#include <mach/mach.h>


static inline int copySafely(const void* restrict const src, void* restrict const dst, const int byteCount)
{
    vm_size_t bytesCopied = 0;
    kern_return_t result = vm_read_overwrite(mach_task_self(),
                                             (vm_address_t)src,
                                             (vm_size_t)byteCount,
                                             (vm_address_t)dst,
                                             &bytesCopied);
    if(result != KERN_SUCCESS)
    {
        return 0;
    }
    return (int)bytesCopied;
}

static inline int copyMaxPossible(const void* restrict const src, void* restrict const dst, const int byteCount)
{
    const uint8_t* pSrc = src;
    const uint8_t* pSrcMax = (uint8_t*)src + byteCount;
    const uint8_t* pSrcEnd = (uint8_t*)src + byteCount;
    uint8_t* pDst = dst;