func TestWalkMemoryDoesntOverlapTheBuffer(t *testing.T) { cmd, err := test.LaunchTestCaseAndWaitForInitialization() if err != nil { t.Fatal(err) } defer cmd.Process.Kill() pid := uint(cmd.Process.Pid) proc, err, softerrors := process.OpenFromPid(pid) test.PrintSoftErrors(softerrors) if err != nil { t.Fatal(err) } pageSize := uint(os.Getpagesize()) bufferSizes := []uint{1024, pageSize, pageSize + 100, pageSize * 2, pageSize*2 + 123} for _, size := range bufferSizes { lastRegion := MemoryRegion{} err, softerrors = WalkMemory(proc, 0, size, func(address uintptr, buffer []byte) (keepSearching bool) { currentRegion := MemoryRegion{Address: address, Size: uint(len(buffer))} if memoryRegionsOverlap(lastRegion, currentRegion) { t.Errorf("Regions overlap while reading %d at a time: %v %v", size, lastRegion, currentRegion) return false } lastRegion = currentRegion return true }) test.PrintSoftErrors(softerrors) if err != nil { t.Fatal(err) } } }
func TestSearchInOtherProcess(t *testing.T) { cmd, err := test.LaunchTestCaseAndWaitForInitialization() if err != nil { t.Fatal(err) } defer cmd.Process.Kill() pid := uint(cmd.Process.Pid) proc, err, softerrors := process.OpenFromPid(pid) test.PrintSoftErrors(softerrors) if err != nil { t.Fatal(err) } defer proc.Close() for i, buf := range buffersToFind { found, _, err, softerrors := FindBytesSequence(proc, 0, buf) test.PrintSoftErrors(softerrors) if err != nil { t.Fatal(err) } else if !found { t.Fatalf("memoryGrep failed for case %d, the following buffer should be found: %+v", i, buf) } } // This must not be present found, _, err, softerrors := FindBytesSequence(proc, 0, notPresent) test.PrintSoftErrors(softerrors) if err != nil { t.Fatal(err) } else if found { t.Fatalf("memoryGrep failed, it found a sequense of bytes that it shouldn't") } }
func main() { flag.Parse() proc, harderror, softerrors := process.OpenFromPid(uint(*pid)) logErrors(harderror, softerrors) switch *action { case "<nil>": log.Fatal("Missing action flag.") case "file-search": data, err := ioutil.ReadFile(*fileneedle) if err != nil { log.Fatal(err) } encoded := strings.Replace(strings.Replace(strings.TrimSpace(string(data)), " ", "", -1), "\n", "", -1) data, err = hex.DecodeString(encoded) if err != nil { log.Fatal(err) } found, address, harderror, softerrors := memsearch.FindBytesSequence(proc, uintptr(*addr), data) logErrors(harderror, softerrors) if found { log.Printf("Found in address: %x\n", address) } case "search": found, address, harderror, softerrors := memsearch.FindBytesSequence(proc, uintptr(*addr), []byte(*needle)) logErrors(harderror, softerrors) if found { log.Printf("Found in address: %x\n", address) } case "regexp-search": r, err := regexp.Compile(*regexpString) if err != nil { log.Fatal(err) } found, address, harderror, softerrors := memsearch.FindRegexpMatch(proc, uintptr(*addr), r) logErrors(harderror, softerrors) if found { log.Printf("Found in address: %x\n", address) } case "print": buf := make([]byte, *size) harderror, softerrors = memaccess.CopyMemory(proc, uintptr(*addr), buf) logErrors(harderror, softerrors) log.Println(string(buf)) default: log.Fatal("Unrecognized action ", *action) } }
func TestRegexpSearchInOtherProcess(t *testing.T) { cmd, err := test.LaunchTestCaseAndWaitForInitialization() if err != nil { t.Fatal(err) } defer cmd.Process.Kill() pid := uint(cmd.Process.Pid) proc, err, softerrors := process.OpenFromPid(pid) test.PrintSoftErrors(softerrors) if err != nil { t.Fatal(err) } defer proc.Close() for i, str := range regexpToMatch { r, err := regexp.Compile(str) if err != nil { t.Fatal(err) } found, _, err, softerrors := FindRegexpMatch(proc, 0, r) test.PrintSoftErrors(softerrors) if err != nil { t.Fatal(err) } else if !found { t.Fatalf("memoryGrep failed for case %d, the following regexp should be found: %s", i, str) } } // These must not match for i, str := range regexpToNotMatch { r, err := regexp.Compile(str) if err != nil { t.Fatal(err) } found, _, err, softerrors := FindRegexpMatch(proc, 0, r) test.PrintSoftErrors(softerrors) if err != nil { t.Fatal(err) } else if found { t.Fatalf("memoryGrep failed for case %d, the following regexp shouldnt be found: %s", i, str) } } }
func TestManuallyWalk(t *testing.T) { cmd, err := test.LaunchTestCase() if err != nil { t.Fatal(err) } defer cmd.Process.Kill() pid := uint(cmd.Process.Pid) proc, err, softerrors := process.OpenFromPid(pid) test.PrintSoftErrors(softerrors) if err != nil { t.Fatal(err) } var region MemoryRegion region, err, softerrors = NextReadableMemoryRegion(proc, 0) test.PrintSoftErrors(softerrors) if err != nil { t.Fatal(err) } if region == NoRegionAvailable { t.Error("No starting region returned") } previousRegion := region for region != NoRegionAvailable { region, err, softerrors = NextReadableMemoryRegion(proc, region.Address+uintptr(region.Size)) test.PrintSoftErrors(softerrors) if err != nil { t.Fatal(err) } if region != NoRegionAvailable && region.Address < previousRegion.Address+uintptr(previousRegion.Size) { t.Error("Returned region is not after the previous one.") } previousRegion = region } }
func (r Runner) Run(in io.Reader) (out string) { var ts statistics stats = ts // in debug mode, we just panic if !debug { defer func() { if e := recover(); e != nil { // return error in json res := newResults() res.Statistics = stats res.Errors = append(res.Errors, fmt.Sprintf("%v", e)) res.Success = false err, _ := json.Marshal(res) out = string(err[:]) return } }() } t0 := time.Now() err := modules.ReadInputParameters(in, &r.Parameters) if err != nil { panic(err) } err = r.ValidateParameters() if err != nil { panic(err) } // create the checks based on the search parameters for label, search := range r.Parameters.Searches { if debug { fmt.Println("making checks for label", label) } err := search.makeChecks() if err != nil { panic(err) } r.Parameters.Searches[label] = search } // evaluate each process one by one pids, err, serr := process.GetAllPids() if err != nil { panic(err) } if debug { fmt.Println("found", len(pids), "processes to evaluate") } for _, err = range serr { stats.Failures = append(stats.Failures, err.Error()) } for _, pid := range pids { // activate all searches for label, search := range r.Parameters.Searches { search.activate() r.Parameters.Searches[label] = search } proc, err, serr := process.OpenFromPid(pid) if err != nil { // if we encounter a hard failure, skip this process stats.Failures = append(stats.Failures, err.Error()) continue } for _, err = range serr { // soft failures are just logged but we continue inspection stats.Failures = append(stats.Failures, err.Error()) } err = r.evaluateProcess(proc) if err != nil { stats.Failures = append(stats.Failures, err.Error()) } stats.ProcessCount++ } out, err = r.buildResults(t0) if err != nil { panic(err) } if debug { fmt.Println("---- results ----") var tmpres modules.Result err = json.Unmarshal([]byte(out), &tmpres) printedResults, err := r.PrintResults(tmpres, false) if err != nil { panic(err) } for _, res := range printedResults { fmt.Println(res) } } return }
func TestCopyMemory(t *testing.T) { cmd, err := test.LaunchTestCaseAndWaitForInitialization() if err != nil { t.Fatal(err) } defer cmd.Process.Kill() pid := uint(cmd.Process.Pid) proc, err, softerrors := process.OpenFromPid(pid) test.PrintSoftErrors(softerrors) if err != nil { t.Fatal(err) } var region MemoryRegion region, err, softerrors = NextReadableMemoryRegion(proc, 0) test.PrintSoftErrors(softerrors) if err != nil { t.Fatal(err) } if region == NoRegionAvailable { t.Error("No starting region returned") } min_region_size := uint(os.Getpagesize() + 100) // one page plus something for region.Size < min_region_size { if region == NoRegionAvailable { t.Fatal("We couldn't find a region of %d bytes", min_region_size) } region, err, softerrors = NextReadableMemoryRegion(proc, region.Address+uintptr(region.Size)) test.PrintSoftErrors(softerrors) if err != nil { t.Fatal(err) } } buffers := [][]byte{ make([]byte, 2), make([]byte, os.Getpagesize()), make([]byte, min_region_size), } for _, buffer := range buffers { // Valid read err, softerrors = CopyMemory(proc, region.Address, buffer) test.PrintSoftErrors(softerrors) if err != nil { t.Error(fmt.Sprintf("Couldn't read %d bytes from region", len(buffer))) } // Crossing boundaries err, softerrors = CopyMemory(proc, region.Address+uintptr(region.Size)-uintptr(len(buffer)/2), buffer) test.PrintSoftErrors(softerrors) if err == nil { t.Error(fmt.Sprintf("Read %d bytes inbetween regions", len(buffer))) } // Entirely outside region err, softerrors = CopyMemory(proc, region.Address+uintptr(region.Size), buffer) test.PrintSoftErrors(softerrors) if err == nil { t.Error(fmt.Sprintf("Read %d bytes after the region", len(buffer))) } } }
func TestSlidingWalkMemory(t *testing.T) { cmd, err := test.LaunchTestCaseAndWaitForInitialization() if err != nil { t.Fatal(err) } defer cmd.Process.Kill() pid := uint(cmd.Process.Pid) proc, err, softerrors := process.OpenFromPid(pid) test.PrintSoftErrors(softerrors) if err != nil { t.Fatal(err) } pageSize := uint(os.Getpagesize()) bufferSizes := []uint{1024, pageSize, pageSize + 100, pageSize * 2, pageSize*2 + 124} for _, size := range bufferSizes { lastRegion := MemoryRegion{} err, softerrors = SlidingWalkMemory(proc, 0, size, func(address uintptr, buffer []byte) (keepSearching bool) { currentRegion := MemoryRegion{Address: address, Size: uint(len(buffer))} if lastRegion.Address == 0 { lastRegion = currentRegion return true } lastRegionLimit := lastRegion.Address + uintptr(lastRegion.Size) overlappedBytes := uintptr(0) regionIsContigous := false if lastRegionLimit > currentRegion.Address { overlappedBytes = lastRegionLimit - currentRegion.Address } else if lastRegionLimit == currentRegion.Address { regionIsContigous = true } if regionIsContigous { if regionIsContigous { t.Error(fmt.Sprintf("Contigous buffer while we are expecting overlapped ones."+ "buffer size %d - lastRegion %v - currentRegion %v", size, lastRegion, currentRegion)) } return false } // If the last buffer wasn't read complete the current one can't be overlapped if lastRegion.Size != size && overlappedBytes > 0 { t.Error(fmt.Sprintf("Overlapped buffer after non-complete one. "+ "buffer size %d - lastRegion %v - currentRegion %v", size, lastRegion, currentRegion)) return false } // Overlapped bytes should be half of the buffer, or the buffer must came from another region if overlappedBytes != uintptr(size/2) && overlappedBytes != 0 { t.Error(fmt.Sprintf("Overlapping buffer by %d bytes. "+ "buffer size %d - lastRegion %v - currentRegion %v", overlappedBytes, size, lastRegion, currentRegion)) return false } lastRegion = currentRegion return true }) test.PrintSoftErrors(softerrors) if err != nil { t.Fatal(err) } } }
func TestWalkRegionReadsEntireRegion(t *testing.T) { cmd, err := test.LaunchTestCaseAndWaitForInitialization() if err != nil { t.Fatal(err) } defer cmd.Process.Kill() pid := uint(cmd.Process.Pid) proc, err, softerrors := process.OpenFromPid(pid) test.PrintSoftErrors(softerrors) if err != nil { t.Fatal(err) } pageSize := uint(os.Getpagesize()) bufferSizes := []uint{1024, pageSize, pageSize + 100, pageSize * 2, pageSize*2 + 123} var region MemoryRegion region, err, softerrors = NextReadableMemoryRegion(proc, 0) test.PrintSoftErrors(softerrors) if err != nil { t.Fatal(err) } if region == NoRegionAvailable { t.Error("No starting region returned") } min_region_size := bufferSizes[len(bufferSizes)-1] for region.Size < min_region_size { if region == NoRegionAvailable { t.Fatal("We couldn't find a region of %d bytes", min_region_size) } region, err, softerrors = NextReadableMemoryRegion(proc, region.Address+uintptr(region.Size)) test.PrintSoftErrors(softerrors) if err != nil { t.Fatal(err) } } for _, size := range bufferSizes { buf := make([]byte, size) readRegion := MemoryRegion{} _, _, err, softerrors := walkRegion(proc, region, buf, func(address uintptr, buffer []byte) (keepSearching bool) { if readRegion.Address == 0 { readRegion.Address = address readRegion.Size = uint(len(buffer)) return true } readRegionLimit := readRegion.Address + uintptr(readRegion.Size) if readRegionLimit != address { t.Error(fmt.Sprintf("walkRegion skept %d bytes starting at %x", address-readRegionLimit, readRegionLimit)) return false } readRegion.Size += uint(len(buffer)) return true }) test.PrintSoftErrors(softerrors) if err != nil { t.Fatal(err) } if region != readRegion { t.Error(fmt.Sprintf("%v not entirely read", region)) } } }