This repository has been archived by the owner on Sep 29, 2020. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 82
/
vmmem.c
111 lines (93 loc) · 3.24 KB
/
vmmem.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
#include "mem.h"
#include <stdlib.h>
#include <sys/uio.h>
#include <stdio.h>
#include <unistd.h>
/* Memory read implementation using linux process_vm_ functions */
/*
On windows, first 2^31 physical bytes are really allocated for various PCI device mappings and do not point to actual physical RAM (mmapped region in QEMU case).
It also differs on Windows XP. This should be solved by injecting code into the kernel to retrieve the actual physical memory map of the system
*/
extern uint64_t KFIXC;
extern uint64_t KFIXO;
uint64_t KFIXC = 0x80000000;
uint64_t KFIXO = 0x80000000;
#define KFIX2(x) ((x) < KFIXC ? (x) : ((x) - KFIXO))
ssize_t process_vm_readv(pid_t pid,
const struct iovec *local_iov,
unsigned long liovcnt,
const struct iovec *remote_iov,
unsigned long riovcnt,
unsigned long flags);
ssize_t process_vm_writev(pid_t pid,
const struct iovec *local_iov,
unsigned long liovcnt,
const struct iovec *remote_iov,
unsigned long riovcnt,
unsigned long flags);
ssize_t MemRead(const ProcessData* data, uint64_t localAddr, uint64_t remoteAddr, size_t len)
{
struct iovec local;
struct iovec remote;
local.iov_base = (void*)localAddr;
local.iov_len = len;
remote.iov_base = (void*)(data->mapsStart + KFIX2(remoteAddr));
remote.iov_len = len;
return process_vm_readv(data->pid, &local, 1, &remote, 1, 0);
}
ssize_t MemReadMul(const ProcessData* data, RWInfo* rdata, size_t num)
{
struct iovec local[__IOV_MAX];
struct iovec remote[__IOV_MAX];
size_t i = 0;
size_t startRead = 0;
ssize_t ret = 0;
for (i = 0; i < num; i++) {
local[i - startRead].iov_base = (void*)rdata[i].local;
local[i - startRead].iov_len = rdata[i].size;
remote[i - startRead].iov_base = (void*)(data->mapsStart + KFIX2(rdata[i].remote));
remote[i - startRead].iov_len = rdata[i].size;
if (i - startRead + 1 >= __IOV_MAX) {
ret = process_vm_readv(data->pid, local, __IOV_MAX, remote, __IOV_MAX, 0);
if (ret == -1)
return ret;
startRead = i + 1;
}
}
if (i != startRead)
ret = process_vm_readv(data->pid, local, i - startRead, remote, i - startRead, 0);
return ret;
}
ssize_t MemWrite(const ProcessData* data, uint64_t localAddr, uint64_t remoteAddr, size_t len)
{
struct iovec local;
struct iovec remote;
local.iov_base = (void*)localAddr;
local.iov_len = len;
remote.iov_base = (void*)(data->mapsStart + KFIX2(remoteAddr));
remote.iov_len = len;
return process_vm_writev(data->pid, &local, 1, &remote, 1, 0);
}
ssize_t MemWriteMul(const ProcessData* data, RWInfo* wdata, size_t num)
{
struct iovec local[__IOV_MAX];
struct iovec remote[__IOV_MAX];
size_t i;
size_t startWrite = 0;
ssize_t ret = 0;
for (i = 0; i < num; i++) {
local[i - startWrite].iov_base = (void*)wdata[i].local;
local[i - startWrite].iov_len = wdata[i].size;
remote[i - startWrite].iov_base = (void*)(data->mapsStart + KFIX2(wdata[i].remote));
remote[i - startWrite].iov_len = wdata[i].size;
if (i - startWrite >= (size_t)__IOV_MAX) {
ret = process_vm_writev(data->pid, local, __IOV_MAX, remote, __IOV_MAX, 0);
if (ret == -1)
return ret;
startWrite = i + 1;
}
}
if (i != startWrite)
ret = process_vm_writev(data->pid, local, i - startWrite, remote, i - startWrite, 0);
return ret;
}