吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 2649|回复: 21
收起左侧

[原创] Linux下修改Wine运行的PE的内存

[复制链接]
1364847132 发表于 2024-1-10 14:17
众~~~所周知,Wine是个好东西,Linux系统可以用它跑Windows程序。它通过实现一系列的Windows API,将Windows PE (可执行和可载入文件格式)转换为Linux操作系统可以理解的格式。让Windows应用在Linux上找到家的感觉。

再众~~~所周知,Linux下有个有趣的特性——“一切皆文件”。这意味着能在/proc/{pid}/maps里一窥进程的内存分布,还能在/proc/{pid}/mem里随心所欲的“画饼”。理论成立,开始实践。

实践只是为了验证前面的猜想,当然得挑个软柿子捏,于是就找到了一个快20年前的老游戏:“XXX大作战”。

Screenshot_20240110_141415.png

操作第一步,探个究竟,Wine是否真把PE内存镜像本本原原地摆放好了。

通过命令ps -e | grep -i MONE,锁定目标进程PID为17551。

2.png

接着,cat /proc/17551/maps | grep exe揭秘了内存布局,果然跟Windows如出一辙,PE文件映射从0x00400000起点开始。

3.png

这时就能来点wirte和read操作,悄悄摸进/proc/{pid}/mem修改内存,居然比Windows还要简单。

首先是捕捉游戏进程的PID,一段轮子代码搞定。
[C++] 纯文本查看 复制代码
int findPid(string processName) {
    FILE *fp;
    char path[1035];
    fp = popen("ps -ef", "r");
    if (fp == nullptr) {
        printf("Failed to run command\n");
        exit(1);
    }
    while (fgets(path, sizeof(path) - 1, fp) != nullptr) {
        if (::strstr(path, processName.c_str()) != nullptr) {
            ::strtok(path, " ");
            auto token = ::strtok(nullptr, " ");
            return stoi(token);
        }
    }
    pclose(fp);
    return -1;
}

接下来,打开对应的mem文件,妙哉,这文件描述符就相当于是Windows的句柄。
[C++] 纯文本查看 复制代码
int openMem(int pid) {
    char mem_filename[1024];
    sprintf(mem_filename, "/proc/%d/mem", pid);
    return open(mem_filename, O_RDWR);
}

后续两个模板函数分别操控读写内存。
[C++] 纯文本查看 复制代码
template<class T>
T readMem(long address, int mem_file) {
    T a;
    if (lseek(mem_file, address, SEEK_SET) == -1) {
        ::printf("lseek error %s \n", strerror(errno));
    }
    read(mem_file, &a, sizeof(T));
    return a;
}

template<class T>
void writeMem(long address, T value, int mem_file) {
    if (lseek(mem_file, address, SEEK_SET) == -1) {
        ::printf("lseek error %s \n", strerror(errno));
    }
    write(mem_file, &value, sizeof(T));
}


该有的都有了,最后把它们组合起来,验证一下功能。
[C++] 纯文本查看 复制代码
#include <string>
#include <cstring>
#include <fcntl.h>
#include <atomic>

const unsigned int num_current_offset = 0x268c; // 当前收集的数量
const unsigned int kind_current_offset = 0x2690; // 当前收集的种类
const unsigned int isShot_current_offset = 0x2680; // 是否可以释放

using namespace std;

int findPid(string processName) {
    FILE *fp;
    char path[1035];
    fp = popen("ps -ef", "r");
    if (fp == nullptr) {
        printf("Failed to run command\n");
        exit(1);
    }
    while (fgets(path, sizeof(path) - 1, fp) != nullptr) {
        if (::strstr(path, processName.c_str()) != nullptr) {
            ::strtok(path, " ");
            auto token = ::strtok(nullptr, " ");
            return stoi(token);
        }
    }
    pclose(fp);
    return -1;
}

int openMem(int pid) {
    char mem_filename[1024];
    sprintf(mem_filename, "/proc/%d/mem", pid);
    return open(mem_filename, O_RDWR);
}

template<class T>
T readMem(long address, int mem_file) {
    T a;
    if (lseek(mem_file, address, SEEK_SET) == -1) {
        ::printf("lseek error %s \n", strerror(errno));
    }
    read(mem_file, &a, sizeof(T));
    return a;
}

template<class T>
void writeMem(long address, T value, int mem_file) {
    if (lseek(mem_file, address, SEEK_SET) == -1) {
        ::printf("lseek error %s \n", strerror(errno));
    }
    write(mem_file, &value, sizeof(T));
}

int main() {
    int pid = findPid("MONE~OUQ.EXE");
    if (pid == -1)
        return -1;
    int mem_file = openMem(pid);
    long address = 0x484a3c;
    auto class_address = readMem<unsigned int>(address, mem_file);
    while (true) {
        writeMem<int>(class_address + num_current_offset, 2, mem_file);
        writeMem<unsigned char>(class_address + kind_current_offset, 21, mem_file);
        writeMem<unsigned char>(class_address + isShot_current_offset, 1, mem_file);
        sleep(1);
    }
    return 0;
}

最后就是效果图啦
2024-01-10 13-16-40 (6).gif
ps:因为不是用windows api OpenProcessReadProcessMemoryWriteProcessMemory,不知道windows下传统防内存修改方法能不能防得住。

免费评分

参与人数 11威望 +1 吾爱币 +34 热心值 +10 收起 理由
笙若 + 1 + 1 谢谢@Thanks!
Hmily + 1 + 20 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
shenquanwusheng + 1 + 1 热心回复!
smile1110 + 3 + 1 66666
杨辣子 + 1 + 1 谢谢@Thanks!
dechong + 1 谢谢@Thanks!
gunxsword + 1 + 1 热心回复!
whodead + 1 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
offerking + 1 + 1 我很赞同!
侃遍天下无二人 + 4 + 1 谢谢@Thanks!
MNB12345 + 1 我很赞同!

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

 楼主| 1364847132 发表于 2024-1-10 15:05
可坏 发表于 2024-1-10 14:56
exe是怎么在linux下运行的呀

Wine (“Wine Is Not an Emulator” 的首字母缩写)是一个能够在多种 POSIX-compliant 操作系统(诸如 Linux,macOS 及 BSD 等)上运行 Windows 应用的兼容层。Wine 不是像虚拟机或者模拟器一样模仿内部的 Windows 逻辑,而是將 Windows API 调用翻译成为动态的 POSIX 调用,免除了性能和其他一些行为的内存占用,让你能够干净地集合 Windows 应用到你的桌面。

https://www.winehq.org/

免费评分

参与人数 1吾爱币 +1 热心值 +1 收起 理由
610100 + 1 + 1 热心回复!

查看全部评分

hk137 发表于 2024-1-10 14:42
ciker_li 发表于 2024-1-10 14:46
可坏 发表于 2024-1-10 14:56
exe是怎么在linux下运行的呀
mornstar52 发表于 2024-1-10 16:08
Interesting
JuncoJet 发表于 2024-1-10 16:35
大多数依赖显卡的游戏wine都跑不起来
iamok 发表于 2024-1-10 17:07
JuncoJet 发表于 2024-1-10 16:35
大多数依赖显卡的游戏wine都跑不起来

看看现在arm mac上好多游戏还是跑得很好的。
andyle 发表于 2024-1-10 18:26
这个 有点高端
雨卷倾城3236 发表于 2024-1-10 18:56
感谢分享,可能还是硬件要好一些,下载来试用跑不动
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-11-15 06:45

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表