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;
}

文章目录