それは可能ですか?実行可能ファイルのメモリに簡単にアクセスして編集できるようにしたいです。または、私が管理者ではない場合、別のプロセスから実行可能ファイルのメモリを編集することはできますか? ptrace ライブラリを試しましたが、管理者でないと失敗します。私はLinuxを使用しています
4 に答える
これがデバッガーの機能です。gdb などのオープン ソース デバッガのコードを調べて、それがどのように機能するかを確認できます。
あなたが何を求めているのか完全にはわかりませんが、これは共有メモリで可能です。
ここを参照してください: http://www.kernel.org/doc/man-pages/online/pages/man7/shm_overview.7.html
答え:
- はい - 動作します。管理者/ルートである必要はありませんが、プロセスのメモリにアクセスする権限、つまり同じユーザーが必要です。
- いいえ - 簡単ではありません
への書き込み/proc/pid/mem
機能は、しばらく前に Linux カーネルに追加されました。したがって、使用しているカーネルによって異なります。小さなプログラムは、これが機能する場合はカーネル 3.2 でチェックされ、失敗する場合は 2.6.32 でチェックされました。
このソリューションは、次の 2 つのプログラムで構成されています。
- 開始された「サーバー」は、メモリを割り当て、このメモリにパターンを書き込み、パターンが印刷された後に配置されるメモリの内容を 3 秒ごとに出力します。
- /proc/pid/maps および /proc/pid/mem を介してサーバーに接続する「クライアント」は、パターンを検索し、他の文字列をサーバーのメモリに書き込みます。
実装はヒープを使用しますが、権限が許す限り、他のプロセスのメモリの他の部分を変更することもできます。
これは非常に「低レベル」であるため、C で実装されていますが、C++ でも動作するはずです。これは概念実証です。製品コードはありません。たとえば、いくつかのエラー チェックが欠落しており、いくつかの固定サイズのバッファがあります。
memholder.c
/*
* Alloc memory - write in some pattern and print out the some bytes
* after the pattern.
*
* Compile: gcc -Wall -Werror memholder.c -o memholder.o
*/
#include <sys/types.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
int main() {
char * m = (char*) malloc(2048);
memset(m, '\xAA', 1024);
strcpy(m + 1024, "Some local data.");
printf("PID: %d\n", getpid());
while(1) {
printf("%s\n", m + 1024);
sleep(3);
}
return 0;
}
memwriter.c
/*
* Searches for a pattern in the given PIDs memory
* and changes some bytes after them.
*
* Compile: gcc -Wall -std=c99 -Werror memwriter.c -o memwriter
*/
#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <sys/mman.h>
#include <sys/ptrace.h>
#include <sys/wait.h>
int open_proc_file(pid_t other_pid, char const * const sn,
int flags) {
char fname[1024];
snprintf(fname, 1023, "/proc/%d/%s", other_pid, sn);
// Open file for reading and writing
int const fd = open(fname, flags );
if(fd==-1) {
perror("Open file");
exit(1);
}
return fd;
}
void get_heap(int fd_maps, size_t * heap_start, size_t * heap_end) {
char buf[65536];
ssize_t const r = read(fd_maps, buf, 65535);
if(r==-1) {
perror("Reading maps file");
exit(1);
}
buf[r] = '\0';
char * const heap = strstr(buf, "[heap]");
if(heap==NULL) {
printf("[heap] not found in maps file");
exit(1);
}
// Look backward to the latest newline
char const * hl_start;
for(hl_start = heap; hl_start > buf && *hl_start != '\n';
--hl_start) {}
// skip \n
++hl_start;
// Convert to beginnig and end address
char * lhe;
*heap_start = strtol(hl_start, &lhe, 16);
++lhe;
*heap_end = strtol(lhe, &lhe, 16);
}
int main(int argc, char *argv[]) {
if(argc!=2) {
printf("Usage: memwriter <pid>\n");
return 1;
}
pid_t const other_pid = atoi(argv[1]);
int fd_mem = open_proc_file(other_pid, "mem", O_RDWR);
int fd_maps = open_proc_file(other_pid, "maps", O_RDONLY);
size_t other_mem_start;
size_t other_mem_end;
get_heap(fd_maps, &other_mem_start, &other_mem_end);
ptrace(PTRACE_ATTACH, other_pid, NULL, NULL);
waitpid(other_pid, NULL, 0);
if( lseek(fd_mem, other_mem_start, SEEK_SET) == -1 ) {
perror("lseek");
return 1;
}
char buf[512];
do {
ssize_t const r = read(fd_mem, buf, 512);
if(r!=512) {
perror("read?");
break;
}
// Check for pattern
int pat_found = 1;
for(int i = 0; i < 512; ++i) {
if( buf[i] != '\xAA' )
pat_found = 0;
break;
}
if( ! pat_found ) continue;
// Write about one k of strings
char const * const wbuf = "REMOTE DATA - ";
for(int i = 0; i < 70; ++i) {
ssize_t const w = write(fd_mem, wbuf, strlen(wbuf));
if( w == -1) {
perror("Write");
return 1;
}
}
// Append a \0
write(fd_mem, "\0", 1);
break;
} while(1);
ptrace(PTRACE_DETACH, other_pid, NULL, NULL);
close(fd_mem);
close(fd_maps);
return 0;
}
出力例
$ ./memholder
PID: 2621
Some local data.
Some local data.
MOTE DATA - REMOTE DA...
他の解釈
あるプロセスの「実行可能ファイル」を別のプロセスに置き換えたいという質問の別の解釈もあります(質問ではなく見出しを読むとき)。exec()
これは、 (および友人)によって簡単に処理できます。
からman exec
:
関数の exec() ファミリは、現在のプロセス イメージを新しいプロセス イメージに置き換えます。
Windows では、これに使用されるメソッドの名前は ReadProcessMemory / WriteProcessMemory ですが、これには管理者権限が必要です。コメントで述べたように、同じことがLinuxにも当てはまります。ユーザープロセスが所有していないメモリを変更できる健全なシステムはありません。
Linux の場合、唯一の機能はptraceです。管理者である必要があります。
http://cboard.cprogramming.com/cplusplus-programming/92093-readprocessmemory-writeprocessmemory-linux-equivalent.htmlには、より詳細な説明が含まれています。
管理者でなくても、プロセスが他のプロセスのメモリを変更できるようにした場合の結果を想像できますか?