linux c++ ce简单实现
思路是通过遍历/proc
目标的/proc/$pid/status第一行的name是你的游戏进程的名字
找到pid后通过/proc/$pid/maps你可以看到游戏的堆栈的地址。
然后用FindAllDataAddress这个函数找到目标数值的地址,然后使用writeprocessmemory这个函数写入数值。
Find函数的本质是个KMP,但是由于内存的地址空间有可能很大,所以实现了一个用buffer大小的内存空间来不断循环KMP的过程。
ce.cpp
#include <stdio.h>
#include <iostream>
#include <string>
#include <string.h>
#include <sys/types.h>
#include <dirent.h>
#include <vector>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
using namespace std;
static int isdigitstr(const char *str)
{
return (strspn(str, "0123456789")==strlen(str));
}
static bool is_file(std::string filename)
{
struct stat buffer;
return (stat (filename.c_str(), &buffer) == 0 && S_ISREG(buffer.st_mode));
}
static bool is_dir(std::string filefodler)
{
struct stat buffer;
return (stat (filefodler.c_str(), &buffer) == 0 && S_ISDIR(buffer.st_mode));
}
vector<string> GetFolderAllFilesName(string folder_path)
{
vector<string> file_names;
if(is_dir(folder_path))
{
DIR *dir = opendir(folder_path.c_str());
if(dir!=nullptr)
{
struct dirent *t_dirent = readdir(dir);
while(t_dirent!=nullptr)
{
file_names.push_back(t_dirent->d_name);
t_dirent = readdir(dir);
}
}
closedir(dir);
}
return file_names;
}
string GetProcessNameByPid(int pid)
{
string name="";
string process_pcb_folder_path = "/proc/"+to_string(pid);
if(is_dir(process_pcb_folder_path))
{
string status_file_path = process_pcb_folder_path+"/status";
FILE *fs = fopen(status_file_path.c_str(), "r");
if(fs!=nullptr)
{
char c=fgetc(fs);
while(c!=':')c=fgetc(fs);
c=fgetc(fs);
while(c=='\t')c=fgetc(fs);
while(c!=EOF&&c!='\n')
{
name+=c;
c=fgetc(fs);
}
}
fclose(fs);
}
return name;
}
int FindProcessPid(string process_name)
{
int pid = -1;
string proc_dir = "/proc";
vector<string> proc_pids;
vector<string> files_name = GetFolderAllFilesName(proc_dir);
for(int i=0;i!=files_name.size();i++)
{
if(isdigitstr(files_name[i].c_str()))
proc_pids.push_back(files_name[i]);
}
for(int i=0;i!=proc_pids.size();i++)
{
string t_process_name = GetProcessNameByPid(atoi(proc_pids[i].c_str()));
if(t_process_name==process_name)
{
pid = atoi(proc_pids[i].c_str());
break;
}
}
return pid;
}
void* ReadProcessMemory(int pid, unsigned long address, int bytes)
{
string process_mem_file_path = "/proc/"+to_string(pid)+"/mem";
void *buffer = malloc(sizeof(int));
memset(buffer, 0, sizeof(int));
int fd = open(process_mem_file_path.c_str(), O_RDWR);
if(fd!=-1)
{
lseek(fd, address, SEEK_SET);
read(fd, buffer, bytes);
}
close(fd);
return buffer;
}
bool WriteProcessMemory(int pid, unsigned long address, void *data, int bytes)
{
string process_mem_file_path = "/proc/"+to_string(pid)+"/mem";
int fd = open(process_mem_file_path.c_str(), O_RDWR);
if(fd!=-1)
{
lseek(fd, address, SEEK_SET);
write(fd, data, bytes);
}
close(fd);
return 1;
}
unsigned long FindFirstDataAddress(int pid, unsigned long start_address, unsigned long end_address, void *data, int bytes, int buffer_size=1024)
{
unsigned long ans = -1;
unsigned long search_size = end_address-start_address;
if(bytes > search_size)return ans;
string process_mem_file_path = "/proc/"+to_string(pid)+"/mem";
int fd = open(process_mem_file_path.c_str(), O_RDWR);
if(fd!=-1)
{
// build next
int *next = (int *)malloc(bytes*sizeof(int));
memset(next, 0, bytes*sizeof(int));
char *data_char = (char *)data;
int i=0,j=2;
while(j<bytes)
{
if(data_char[i]==data_char[j-1])
{
i++;
if(data_char[j]==data_char[i])next[j]=next[i];
else next[j] = i;
}
else
{
if(i!=0)
{
i = next[i];
j--;
}
}
j++;
}
// use next find
char *buffer =(char*)malloc(buffer_size);
i=0, j=0;
unsigned long next_address = start_address;
lseek(fd, next_address, SEEK_SET);
int i_end=min(search_size, (unsigned long)buffer_size);
next_address+=i_end;
read(fd, buffer, i_end);
while(j<bytes)
{
if(buffer[i]==data_char[j])
{
i++;
j++;
}
else
{
if(j!=0)
j = next[j];
else
i++;
if(i_end-i >= bytes-j)continue;
else
{
// move unused buffer to the front
int t_i=0;
while(i<i_end)
{
buffer[t_i] = buffer[i];
t_i++;
i++;
}
i=0;
// read newdata to buffer
int read_cnt = min((unsigned long)(buffer_size-t_i), end_address-next_address);
read(fd, buffer+t_i, read_cnt);
i_end = t_i+read_cnt;
next_address += read_cnt;
if(i_end-i >= bytes-j)continue;
else break;
}
}
}
free(next);
free(buffer);
ans = (j==bytes?(next_address-i_end+i-j):-1);
}
close(fd);
return ans;
}
vector<unsigned long> FindAllDataAddress(int pid, unsigned long start_address, unsigned long end_address, void *data, int bytes, int buffer_size=1024)
{
vector<unsigned long> addresses;
unsigned long search_size = end_address-start_address;
if(bytes > search_size)return addresses;
string process_mem_file_path = "/proc/"+to_string(pid)+"/mem";
int fd = open(process_mem_file_path.c_str(), O_RDWR);
if(fd!=-1)
{
// build next
int *next = (int *)malloc(bytes*sizeof(int));
memset(next, 0, bytes*sizeof(int));
char *data_char = (char *)data;
int i=0,j=2;
while(j<bytes)
{
if(data_char[i]==data_char[j-1])
{
i++;
if(data_char[j]==data_char[i])next[j]=next[i];
else next[j] = i;
}
else
{
if(i!=0)
{
i = next[i];
j--;
}
}
j++;
}
// use next find
char *buffer =(char*)malloc(buffer_size);
i=0, j=0;
unsigned long next_address = start_address;
lseek(fd, next_address, SEEK_SET);
int i_end=min(search_size, (unsigned long)buffer_size);
next_address+=i_end;
read(fd, buffer, i_end);
// printf("next_address: %lx\n", next_address);
while(next_address<end_address||j<bytes)
{
if(buffer[i]==data_char[j])
{
i++;
j++;
}
else
{
if(j!=0)
j = next[j];
else
i++;
if(i_end-i >= bytes-j)continue;
else
{
// move unused buffer to the front
int t_i=0;
while(i<i_end)
{
buffer[t_i] = buffer[i];
t_i++;
i++;
}
i=0;
// read newdata to buffer
int read_cnt = min((unsigned long)(buffer_size-t_i), end_address-next_address);
read(fd, buffer+t_i, read_cnt);
i_end = t_i+read_cnt;
next_address += read_cnt;
if(i_end-i >= bytes-j)continue;
else break;
}
}
if(j!=bytes)continue;
else
{
addresses.push_back(next_address-i_end+i-j);
i++;
j=0;
// move unused buffer to the front
int t_i=0;
while(i<i_end)
{
buffer[t_i] = buffer[i];
t_i++;
i++;
}
i=0;
// read newdata to buffer
int read_cnt = min((unsigned long)(buffer_size-t_i), end_address-next_address);
read(fd, buffer+t_i, read_cnt);
i_end = t_i+read_cnt;
next_address += read_cnt;
if(i_end-i >= bytes-j)continue;
else break;
}
}
free(next);
free(buffer);
}
close(fd);
return addresses;
}
// void locate_address()
// {
// string process_name="game";
// int pid = FindProcessPid(process_name);
// int number = 10008;
// int bytes = 4;
// unsigned long start_address = 0x7ffea204a000;
// unsigned long end_address = 0x7ffea206b000;
// vector<unsigned long> addr[3];
// int cnt=0;
// char c = '\n';
// while(c=='\n')
// {
// printf("number input:");
// scanf("%d", &number);
// printf("number: %d\n", number);
// int now_no = cnt%2;
// addr[now_no] = FindAllDataAddress(pid, start_address, end_address, &number, bytes);
// // printf("%d\n", addr[now_no].size());
// if(cnt>0)
// {
// int last_no = (cnt-1)%2, now_no = cnt%2;
// addr[2].clear();
// for(int i=0;i!=addr[now_no].size();i++)
// {
// bool flag = false;
// for(int j=0;j!=addr[last_no].size();j++)
// {
// if(addr[now_no][i]==addr[last_no][j])
// {
// flag = true;
// break;
// }
// }
// if(flag)
// {
// addr[2].push_back(addr[now_no][i]);
// }
// }
// addr[now_no] = addr[2];
// }
// printf("find %d\n", addr[now_no].size());
// if(addr[now_no].size()<5)
// {
// for(int i=0;i!=addr[now_no].size();i++)
// {
// printf("%p\n", addr[now_no][i]);
// }
// }
// cnt++;
// printf("scan again(yes:\\n)");
// getchar();
// scanf("%c", &c);
// }
// int now_no = (cnt-1)%2;
// if(addr[now_no].size()>0)
// {
// for(int i=0;i!=addr[now_no].size();i++)
// {
// printf("%p\n", addr[now_no][i]);
// }
// }
// else
// printf("no data was find!\n");
// }
// void test_find_first()
// {
// string process_name="game";
// int pid = FindProcessPid(process_name);
// int number = 10003;
// int bytes = 4;
// printf("search number: %d\n", number);
// unsigned long start_address = 0x7ffceab12000;
// unsigned long end_address = 0x7ffceab33000;
// unsigned long address = FindFirstDataAddress(pid, start_address, end_address, &number, 4);
// printf("adderss: %p\n", address);
// void *buffer = ReadProcessMemory(pid, address, 4);
// printf("address value %d\n", *(int *)buffer);
// free(buffer);
// }
// void test_find_all()
// {
// string process_name="game";
// int pid = FindProcessPid(process_name);
// int number = 10008;
// int bytes = 4;
// printf("search number: %d\n", number);
// // 7ffea204a000-7ffea206b000
// unsigned long start_address = 0x7ffea204a000;
// unsigned long end_address = 0x7ffea206b000;
// vector<unsigned long> addresses = FindAllDataAddress(pid, start_address, end_address, &number, 4);
// for(int i=0;i!=addresses.size();i++)
// {
// printf("adderss: %p\n", addresses[i]);
// void *buffer = ReadProcessMemory(pid, addresses[i], 4);
// printf("address value %d\n", *(int *)buffer);
// free(buffer);
// }
// }
void locate_address_for_survivingmars()
{
string process_name="SurvivingMars_1";
int pid = FindProcessPid(process_name);
printf("pid: %d\n", pid);
unsigned long number = 0;
int bytes = 8;
//7ffdce494000-7ffdce4b5000
//0131b000-0133c000
//0133c000-01375000
//7f626550d000-7f6265571000 rw-p 00000000 00:00 0
//7f6265571000-7f6265572000 ---p 00000000 00:00 0
//7f6265572000-7f6265d72000 rw-p 00000000 00:00 0
//7ffdce494000-7ffdce4b5000 rw-p 00000000 00:00 0 [stack]
//7ffdce5f3000-7ffdce5f7000 r--p 00000000 00:00 0 [vvar]
//7ffdce5f7000-7ffdce5f9000 r-xp 00000000 00:00 0
unsigned long start_address = 0x7ffdce5f3000;
unsigned long end_address = 0x7ffdce5f7000;
printf("start end address: %p - %p\n", start_address, end_address);
vector<unsigned long> addr[3];
int cnt=0;
char c = '\n';
while(c=='\n')
{
printf("number input:");
scanf("%ld", &number);
printf("number: %ld\n", number);
int now_no = cnt%2;
addr[now_no] = FindAllDataAddress(pid, start_address, end_address, &number, bytes);
// printf("%d\n", addr[now_no].size());
if(cnt>0)
{
int last_no = (cnt-1)%2, now_no = cnt%2;
addr[2].clear();
for(int i=0;i!=addr[now_no].size();i++)
{
bool flag = false;
for(int j=0;j!=addr[last_no].size();j++)
{
if(addr[now_no][i]==addr[last_no][j])
{
flag = true;
break;
}
}
if(flag)
{
addr[2].push_back(addr[now_no][i]);
}
}
addr[now_no] = addr[2];
}
printf("find %d\n", addr[now_no].size());
if(addr[now_no].size()<5)
{
for(int i=0;i!=addr[now_no].size();i++)
{
printf("%p\n", addr[now_no][i]);
}
}
cnt++;
printf("scan again(yes:\\n)");
getchar();
scanf("%c", &c);
}
int now_no = (cnt-1)%2;
if(addr[now_no].size()>0)
{
for(int i=0;i!=addr[now_no].size();i++)
{
printf("%p\n", addr[now_no][i]);
}
}
else
printf("no data was find!\n");
}
int main()
{
// test_find_all();
// locate_address();
locate_address_for_survivingmars();
return 0;
}
game.cpp
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
using namespace std;
int main()
{
int i=9999;
cout<<"i have already opened!"<<endl;
while(1)
{
printf("i = %d, addr = %p, pid = %d\n",i, &i, getpid());
getchar();
i++;
}
return 0;
}