Example #1
0
// FindFindRegexpMatch finds the first match of r in the process memory. This function works as FindFindBytesSequence
// but instead of searching for a literal bytes sequence it uses a regexp. It tries to match the regexp in the memory
// as is, not interpreting it as any charset in particular.
func FindRegexpMatch(p process.Process, address uintptr, r *regexp.Regexp) (found bool, foundAddress uintptr,
	harderror error, softerrors []error) {

	const buffer_size = uint(4096)

	foundAddress = uintptr(0)
	found = false
	harderror, softerrors = memaccess.SlidingWalkMemory(p, address, buffer_size,
		func(address uintptr, buf []byte) (keepSearching bool) {
			loc := r.FindIndex(buf)
			if loc == nil {
				return true
			}

			foundAddress = address + uintptr(loc[0])
			found = true
			return false
		})

	return
}
Example #2
0
// FindByFindBytesSequence finds for the first occurrence of needle in the Process starting at a given address (in the
// process address space). If the needle is found the first argument will be true and the second one will contain it's
// address.
func FindBytesSequence(p process.Process, address uintptr, needle []byte) (found bool, foundAddress uintptr,
	harderror error, softerrors []error) {

	const min_buffer_size = uint(4096)
	buffer_size := min_buffer_size
	if uint(len(needle)) > buffer_size {
		buffer_size = uint(len(needle))
	}

	foundAddress = uintptr(0)
	found = false
	harderror, softerrors = memaccess.SlidingWalkMemory(p, address, buffer_size,
		func(address uintptr, buf []byte) (keepSearching bool) {
			i := bytes.Index(buf, needle)
			if i == -1 {
				return true
			}

			foundAddress = address + uintptr(i)
			found = true
			return false
		})
	return
}
Example #3
0
func (r Runner) walkProcMemory(proc process.Process, procname string) (err error) {
	// find longest byte string to search for, which determines the buffer size
	bufsize := uint(4096)
	// find lowest offset, which determines start address
	offset := ^uintptr(0) >> 1
	// verify that at least one search is interested in inspecting the memory
	// of this process
	shouldWalkMemory := false
	// if at least one search wants to log failures, do so, otherwise omit them
	logFailures := false
	for label, search := range r.Parameters.Searches {
		// if the search is not active or the search as no content or by check to run, skip it
		if !search.isactive || (search.checkmask&checkContent == 0 && search.checkmask&checkByte == 0) {
			search.deactivate()
			r.Parameters.Searches[label] = search
			continue
		}
		shouldWalkMemory = true
		// find the largest bufsize needed
		for _, c := range search.checks {
			if c.code&checkByte != 0 {
				if uint(len(c.bytes)) > (bufsize / 2) {
					bufsize = 2 * uint(len(c.bytes))
					// pad to always have an even bufsize
					if bufsize%2 != 0 {
						bufsize++
					}
				}
			}
		}
		// find the smallest offset needed
		if uintptr(search.Options.Offset) < offset {
			offset = uintptr(search.Options.Offset)
		}
		if search.Options.LogFailures {
			logFailures = true
		}
	}
	if !shouldWalkMemory {
		if debug {
			fmt.Println("walkProcMemory: no check needs to read the memory of process", proc.Pid(), procname)
		}
		return
	}
	// keep track of the number of bytes read to exit when maxlength is reached
	var readBytes float64
	walkfn := func(curStartAddr uintptr, buf []byte) (keepSearching bool) {
		if readBytes == 0 {
			readBytes += float64(len(buf))
		} else {
			readBytes += float64(len(buf) / 2)
		}
		if debug {
			fmt.Println("walkProcMemory: reading", bufsize, "bytes starting at addr", curStartAddr, "; read", readBytes, "bytes so far")
		}
		for label, search := range r.Parameters.Searches {
			matchedall := true
			if !search.isactive {
				continue
			}
			// if the search is meant to stop at a given address, and we're passed
			// that point then deactivate the search now
			if readBytes >= search.Options.MaxLength {
				search.deactivate()
				goto skip
			}
			keepSearching = true
			for i, c := range search.checks {
				switch c.code {
				case checkContent:
					if c.regex.FindIndex(buf) == nil {
						// not found
						matchedall = false
						continue
					}
					c.storeMatch(proc)
					search.checks[i] = c
				case checkByte:
					if bytes.Index(buf, c.bytes) < 0 {
						// not found
						matchedall = false
						continue
					}
					c.storeMatch(proc)
					search.checks[i] = c
				}
			}
			// if all the checks have matched on this search, deactivate it
			if matchedall {
				search.deactivate()
			}
		skip:
			r.Parameters.Searches[label] = search
		}
		if debug && !keepSearching {
			fmt.Println("walkProcMemory: stopping the memory search for", proc.Pid(), procname)
		}
		return
	}
	if debug {
		fmt.Println("walkProcMemory: reading memory of", proc.Pid(), procname)
	}
	err, serr := memaccess.SlidingWalkMemory(proc, offset, bufsize, walkfn)
	if err != nil {
		return err
	}
	if logFailures {
		for _, err = range serr {
			stats.Failures = append(stats.Failures, err.Error())
			if debug {
				fmt.Printf("walkProcMemory: soft error -> %v\n", err)
			}
		}
	}
	stats.MemoryRead += readBytes
	return
}