#include <stdlib.h>
#include <stdio.h>
#include <sys/ptrace.h>
#include <errno.h>
#include <signal.h>
#include <sys/wait.h>

int read_page(int, void *, char *);
void sighandler(int);

int done;

int main(int argc, char **argv)
{
	int pid=strtol(argv[1], NULL, 0);
	char *search=argv[2];

	signal(SIGINT, sighandler);

	int err=ptrace(PTRACE_ATTACH, pid, NULL, NULL);
	if(err==-1)
	{
		perror("ptrace");
		return 1;
	}

	err=waitpid(pid, NULL, 0);
	if(err==-1)
	{
		perror("waitpid");
		return 1;
	}

	int matches=0;
	done=0;
	for(int i=0x1000; (!done && i); i+=0x1000)
	{
		char buf[0x1000];
		int err=read_page(pid, (void *)i, buf);
		if(err==-1)
			continue;

		int found=0;
		for(int j=0; (!found && j<0x1000); ++j)
		{
			found=1;
			for(int k=0; (found && search[k]); ++k)
				found=(buf[j+k]==search[k]);
		}

		if(found)
		{
			printf("Page 0x%08X\n", i);
			for(int j=0; j<0x1000; j+=16)
			{
				for(int k=0; k<16; ++k)
					printf("%02X ", (unsigned char)buf[j+k]);
				for(int k=0; k<16; ++k)
				{
					unsigned char c=buf[j+k];
					printf("%c", (c>=0x20 && c<=0x7E ? c : '.'));
				}
				printf("\n");
			}
			fflush(stdout);

			++matches;
		}
		if(!(i&0x3FFFF))
		{
			fprintf(stderr, "%08X (%d matches)\e[G", i, matches);
			fflush(stderr);
		}
	}
	ptrace(PTRACE_DETACH, pid, NULL, NULL);

	return 0;
}

int read_page(int pid, void *addr, char *buf)
{
	for(int i=0; i<0x1000; i+=sizeof(long))
	{
		long word=ptrace(PTRACE_PEEKDATA, pid, (char *)addr+i, NULL);
		if(word==-1 && errno)
			return -1;
		*(long *)(buf+i)=word;
	}
}

void sighandler(int s)
{
	done=1;
}
