LINUX.ORG.RU

изменить значение по адресу в процессе


0

1

Здравствуйте, дорогие форумчане. Помню в далекие времена пользования виндой, была программа которая автоматизировала действие artmoney (не помню как называется, то ли tmk, то ли tdk). Под linux'oм я нашел аналог artmoney, но так как неудобно постоянно запускать scanmem, постоянно искать значение и т.д., решил это дело автоматизировать. Но дело в том, что дальше быдлокодинга на скриптовых языках - я не пошел. В связи с этим, просьба к желающим, продемонстрировать примером кода, как можно изменить по адресу в определённом процессе значение переменной. Думаю что разберусь на любом языке. Хотя разнообразие приветствуется.

Спасибо. :)

На си это делает системный вызов ptrace, так что скорее всего нужно гуглить что-то вроде ptrace poke example

vzzo ★★★
()
Ответ на: комментарий от vzzo

жестоко, друг, жестоко. Из того что поисковики подсказали - я совершенно не понял как сделать. Нашел это, но знания Си не позволяют самому выдрать оттуда то что нужно.

chinarulezzz ★★
() автор топика
Ответ на: комментарий от vasily_pupkin

если будет время, покажешь пример. Хоть мелкий. Очень нужно.

chinarulezzz ★★
() автор топика

Скачал исходники scanmem'a, полистал, улыбнулся, закрыл и желаю тебе удачи, если соберёшься найти там суть, без неё там никак. Вопрос специфический на самом деле, если не сказать хаккерский, будем ождать, что кто-то знает как это делать и готов поделиться опытом.

je-ke
()
Ответ на: комментарий от chinarulezzz

Ну вот очень тривиальный пример. Две крошечные программки на си:

1. victim.c — при запуске печатает свой pid и адрес переменной, затем каждую секунду печатает ее значение

#include<unistd.h>
#include<stdio.h>
int a=42;
int main(){
	printf("%d %p\n",getpid(),&a);
	for(;;){
		printf("a=%d\n", a);
		sleep(1);
	}
}

2. rapist.c — принимает аргументы вида «r pid addr» или «w pid addr val», соответственно читает или пишет значение в указанном месте.

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

long rd(int pid, long addr){
	ptrace(PTRACE_ATTACH, pid, 0, 0);
	waitpid(pid, 0, WUNTRACED);
	long ret = ptrace(PTRACE_PEEKDATA, pid, addr, 0);
	ptrace(PTRACE_CONT, pid, 0, 0);
	return ret;
}

void wr(int pid, long addr, long val){
	ptrace(PTRACE_ATTACH, pid, 0, 0);
	waitpid(pid, 0, WUNTRACED);
	ptrace(PTRACE_POKEDATA, pid, addr, (void*)val);
}

int main(int argc,char **argv){
	int pid = atoi(argv[2]);
	long addr = strtol(argv[3],0,0);
	switch(*argv[1]){
	case 'r':printf("%d\n",rd(pid, addr));break;
	case 'w':wr(pid,addr,strtol(argv[4],0,0));
	}
}

Как этим пользоваться: в одном терминале запустить victim.c, и любоваться выводом. В соседнем запустить rapist.c с параметрами, напечатанными victim, и поменять значение. Увидеть, что в выводе victim значение поменялось. Победа.

anonymous
()
Ответ на: комментарий от chinarulezzz

Ухх, теперь пойдёт череда велосипедов для dendy-игр))

так если тебе надо изменять состояние эмулируемого кода, это гораздо проще делать в самом эмуляторе.

во многих даже peek/poke встроенное есть.

anonymous
()
Ответ на: комментарий от anonymous

У меня gens-эмулятор. Не нашел как штатно изменять значение. Но в других эмуляторах (pcsx) видел. В начале исходник сегфолтил, понял что туплю на argv.. Потом отказывался менять значение после первого вызова процедуры, наконец дошло про ptrace(PTRACE_DETACH... Эхх, еще бы как-то на экран геймплея выводить информацию... Да как-то попроще, без дизасма...) Натренируюсь на всех играх, что имеются :)

chinarulezzz ★★
() автор топика
Ответ на: комментарий от anonymous

Если ещё заглянешь, опиши случай со стеком, задача та же самая, но теперь для локальных (автоматических) переменных, данный код для них не работает.

je-ke
()
Ответ на: комментарий от je-ke

Давай я лучше руками помахаю.

Локальные переменные по смыслу своему должны жить на стеке. Тогда, если взять их адрес (&) и по нему что-нибудь перезаписать, все должно работать.

Но компиляторы — хитрые ребята, и норовят при первой же возможности засунуть переменную в регистр. Тогда есть два способа решения проблемы:

1. Попросить компилятор так не делать — допустим, сказав volatile.

2. Залезть в регистры — см. PTRACE_GETREGS в ptrace(2)

anonymous
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.