VIRTUALS

the virtual labs for the virtuals

0%

【游戏逆向】常见内存操作

摘要:
记录游戏逆向开发中的常见内存操作。

本篇文章的方法皆经过验证,方法之间尽量保证低耦合,以方便单独使用。

内外部NOP

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
/*
* @Author: GuidedHacking.com
*/
namespace mem
{
//Internal Nop
void mem::Nop(char* dst, unsigned int size)
{
DWORD oldprotect;
VirtualProtect(dst, size, PAGE_EXECUTE_READWRITE, &oldprotect);
memset(dst, 0x90, size);
VirtualProtect(dst, size, oldprotect, &oldprotect);
}

//External
void mem::NopEx(char* dst, unsigned int size, HANDLE hProcess)
{
char* nopArray = new char[size];
memset(nopArray, 0x90, size);

DWORD oldprotect;
VirtualProtectEx(hProcess, dst, size, PAGE_EXECUTE_READWRITE, &oldprotect);
WriteProcessMemory(hProcess, dst, nopArray, size, NULL);
VirtualProtectEx(hProcess, dst, size, oldprotect, &oldprotect);
delete[] nopArray;
}
}

内外部Patch

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
/*
* @Author: GuidedHacking.com
*/
namespace mem
{
// internal patch
void mem::Patch(char* dst, char* src, int size)
{
DWORD oldprotect;
VirtualProtect(dst, size, PAGE_EXECUTE_READWRITE, &oldprotect);
memcpy(dst, src, size);
VirtualProtect(dst, size, oldprotect, &oldprotect);
}

//external patch
void mem::PatchEx(HANDLE hProcess, char* dst, char* src, int size)
{
DWORD oldprotect;
VirtualProtectEx(hProcess, dst, size, PAGE_EXECUTE_READWRITE, &oldprotect);
WriteProcessMemory(hProcess, dst, src, size, NULL);
VirtualProtectEx(hProcess, dst, size, oldprotect, &oldprotect);
}

}

内外部读多级指针指向的动态地址

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
/*
* @Author: GuidedHacking.com
*/
// externally read address multi-level ptr points to
uintptr_t FindDMAAddy(HANDLE hProc, uintptr_t ptr, std::vector<unsigned int> offsets)
{
uintptr_t addr = ptr;
for (unsigned int i = 0; i < offsets.size(); ++i)
{
ReadProcessMemory(hProc, (BYTE*)addr, &addr, sizeof(addr), 0);
addr += offsets[i];
}
return addr;
}

// internally read address multi-level ptr points to
uintptr_t FindDMAAddy(uintptr_t ptr, std::vector<unsigned int> offsets)
{
uintptr_t addr = ptr;
for (unsigned int i = 0; i < offsets.size() ; ++i)
{
addr = *(uintptr_t*)addr;
addr += offsets[i];
}
return addr;
}

内外部读地址的值

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
/*
* @Author: accepted.org.cn
*/
// reads memory externally and return a value as result
template <typename T>
T ReadEx(uintptr_t address)
{
T VALUE;
ReadProcessMemory(Game::procHandle, (LPCVOID)(address), &VALUE, sizeof(VALUE), 0);
return VALUE;
}

// reads memory internally and return a value as result
template <typename T>
T Read(uintptr_t address)
{
T VALUE;
unsigned long preProtection;
VirtualProtect(reinterpret_cast<void*>(address), sizeof(address), PAGE_EXECUTE_READWRITE, &preProtection);

VALUE = *(T*)address;

VirtualProtect(reinterpret_cast<void*>(address), sizeof(address), preProtection, &preProtection);
return VALUE;
}

内外部读多级指针对应的值

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
/*
* @Author: accepted.org.cn
*/
// externally read value multi-level ptr points to
template <typename T>
T ReadPtrChainEx(uintptr_t basePtr, std::vector<uintptr_t> offsetList)
{
T VALUE;
// don't reads last offset
int len = offsetList.size() - 1;
// updates base pointer
for (int i = 0; i < len; i++) {
ReadProcessMemory(Game::procHandle, (LPCVOID)(basePtr + offsetList[i]), &basePtr, sizeof(basePtr), 0);
}
// read value with last offset
ReadProcessMemory(Game::procHandle, (LPCVOID)(basePtr + offsetList[len]), &VALUE, sizeof(VALUE), 0);
return VALUE;
}


// internally read value multi-level ptr points to
template <typename T>
T ReadPtrChain(uintptr_t basePtr, std::vector<uintptr_t> offsetList)
{
T VALUE;
// don't reads last offset
int len = offsetList.size() - 1;
// updates base pointer
for (int i = 0; i < len; i++) {
uintptr_t address = basePtr + offsetList[i];
unsigned long preProtection;
VirtualProtect(reinterpret_cast<void*>(address), sizeof(address), PAGE_EXECUTE_READWRITE, &preProtection);

basePtr = *(uintptr_t*)address;

VirtualProtect(reinterpret_cast<void*>(address), sizeof(address), preProtection, &preProtection);
}
uintptr_t address = basePtr + offsetList[len];
// read value with last offset
unsigned long preProtection;
VirtualProtect(reinterpret_cast<void*>(address), sizeof(address), PAGE_EXECUTE_READWRITE, &preProtection);

VALUE = *(T*)address;

VirtualProtect(reinterpret_cast<void*>(address), sizeof(address), preProtection, &preProtection);
return VALUE;
}