├── Example
├── Example.vcxproj.user
├── main.cpp
├── Example.vcxproj.filters
└── Example.vcxproj
├── Driver
├── cleaning.h
├── driver.vcxproj.user
├── util.h
├── core.h
├── stdafx.h
├── util.cpp
├── driver.vcxproj.filters
├── cleaning.cpp
├── main.cpp
├── driver.vcxproj
├── core.cpp
└── structs.h
├── README.md
├── Usermode
├── memory.h
└── memory.cpp
└── DoubleDataPointer.sln
/Example/Example.vcxproj.user:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/Driver/cleaning.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 | #include "stdafx.h"
3 |
4 | namespace Cleaning
5 | {
6 | NTSTATUS NullPageFrameNumbers(uint64_t start, uint32_t size);
7 | NTSTATUS CleanFromBigPools(uint64_t start);
8 | }
--------------------------------------------------------------------------------
/Driver/driver.vcxproj.user:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Off
5 |
6 |
--------------------------------------------------------------------------------
/Driver/util.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 | #include "stdafx.h"
3 |
4 |
5 | //https://ntdiff.github.io/
6 | #define WINDOWS_1803 17134
7 | #define WINDOWS_1809 17763
8 | #define WINDOWS_1903 18362
9 | #define WINDOWS_1909 18363
10 | #define WINDOWS_2004 19041
11 | #define WINDOWS_20H2 19569
12 | #define WINDOWS_21H1 20180
13 |
14 | namespace Util {
15 |
16 | PIMAGE_NT_HEADERS getHeader(PVOID module);
17 | PBYTE FindPattern(PVOID base, LPCSTR pattern, LPCSTR mask);
18 | }
--------------------------------------------------------------------------------
/Example/main.cpp:
--------------------------------------------------------------------------------
1 | // Example.cpp : This file contains the 'main' function. Program execution begins and ends there.
2 | //
3 |
4 | #include
5 | #include
6 | #include "..\Usermode\memory.h"
7 |
8 | Memory* pMem = nullptr;
9 | int main()
10 | {
11 | LoadLibraryA("user32.dll");
12 |
13 | uint32_t processId = GetCurrentProcessId();
14 | pMem = new Memory(processId, { "user32.dll" });
15 |
16 | std::cout << "Process Base: " << pMem->base << std::endl;
17 | std::cout << "user32.dll Base: " << pMem->moduleBases["user32.dll"] << std::endl;
18 |
19 | int x = 100;
20 | std::cout << "Rpm: " << pMem->Rpm((uint64_t)&x) << std::endl;
21 |
22 | pMem->Wpm((uint64_t)&x, 15);
23 | std::cout << "After Wpm: " << x << std::endl;
24 |
25 | return 0;
26 | }
--------------------------------------------------------------------------------
/Driver/core.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 | #include "stdafx.h"
3 |
4 | namespace Core {
5 | PVOID GetSystemModuleBase(LPCSTR moduleName);
6 |
7 |
8 | //Sketch
9 | ULONG_PTR GetKernelDirBase();
10 | ULONG_PTR GetProcessCr3(PEPROCESS pProcess);
11 | NTSTATUS ReadVirtual(uint64_t dirbase, uint64_t address, uint8_t* buffer, SIZE_T size, SIZE_T* read);
12 | NTSTATUS WriteVirtual(uint64_t dirbase, uint64_t address, uint8_t* buffer, SIZE_T size, SIZE_T* written);
13 |
14 | //Safe Guarded Calls
15 | NTSTATUS GetModuleBaseAddress(int processId, const char* moduleName, uint64_t* baseAddress);
16 | NTSTATUS GetProcessBaseAddress(int pid, uint64_t* Address);
17 | NTSTATUS ReadProcessMemory(int pid, uint64_t Address, uint64_t AllocatedBuffer, SIZE_T size, SIZE_T* read);
18 | NTSTATUS WriteProcessMemory(int pid, uint64_t Address, uint64_t AllocatedBuffer, SIZE_T size, SIZE_T* written);
19 |
20 |
21 | ULONG_PTR GetKernelDirBase();
22 | }
--------------------------------------------------------------------------------
/Example/Example.vcxproj.filters:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01}
6 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms
7 |
8 |
9 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF}
10 | cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx
11 |
12 |
13 |
14 |
15 | Memory
16 |
17 |
18 | Project
19 |
20 |
21 |
22 |
23 | Memory
24 |
25 |
26 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # DoubleDataPointer
2 | Double data pointer communication in to the kernel mode, the driver should be manually mapped into the kernel. Useful for bypassing Anti-Cheat solutions.
3 |
4 | This project points a data pointer at another data pointer which is pointed to memory inside of the driver. This allows a user to send commands through a uncommonly used windows API, and execute commands at a kernel permission level.
5 |
6 | # Features
7 | - Read Memory
8 | - Write Memory
9 | - Nulls Page Frame numbers of the driver (so it is harder to find the pages with the driver stub)
10 | - Clears Big pools (Usually ExAllocatePool is used to allocate the driver when manually mapping, this takes the driver out of the pig pool tables)
11 | - Physical Memory Read/Write (KeStackAttach can be detected, which is used inside of MmCopyVirtualMemory)
12 | - Uses 2 data pointers so that a surface level check on the first pointer is not outside of a valid module
13 |
14 | # Limitations/Detections
15 | - RIP will be outisde of a valid memory region whenever a stack frame is captured from NMI callbacks. This way anticheats can flag you.
16 | - This project creates alertable threads that can be indexed and captured, later anylyzed or checked for abnormalities.
17 | - The data pointer itself can be directly verified to point to a specific region.
18 |
19 | This project was created ages ago, it is most definetly detected.
20 |
--------------------------------------------------------------------------------
/Driver/stdafx.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 | #include
3 | #include
4 | #include
5 | #include
6 |
7 | #include "structs.h"
8 |
9 | #define RVA(addr, size) ((PBYTE)(addr + *(DWORD*)(addr + ((size) - 4)) + size))
10 | #define printf(text, ...) (DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, text, ##__VA_ARGS__))
11 | //#define WINVER_2004 (19041)
12 | #define COMMUNICATION_KEY (0xDEADBEEF)
13 |
14 |
15 | typedef signed char int8_t;
16 | typedef short int16_t;
17 | typedef int int32_t;
18 | typedef long long int64_t;
19 | typedef unsigned char uint8_t;
20 | typedef unsigned short uint16_t;
21 | typedef unsigned int uint32_t;
22 | typedef unsigned long long uint64_t;
23 |
24 | enum Request {
25 | GETBASE = 0,
26 | GETMODULEBASE = 1,
27 | READPROCESSMEMORY = 2,
28 | WRITEPROCESSMEMORY = 3,
29 | SIGSCAN = 4
30 | };
31 |
32 |
33 |
34 | struct Communication {
35 |
36 | uint64_t key;
37 | Request request;
38 |
39 | int processID;
40 |
41 | uint64_t address;
42 | const char* moduleName;
43 |
44 | uint64_t buffer;
45 | size_t size;
46 |
47 | union
48 | {
49 | size_t written;
50 | size_t read;
51 | };
52 | };
53 |
54 | struct EntryParams
55 | {
56 | uint64_t poolBase;
57 | uint32_t entryPoint;
58 | uint32_t size;
59 | };
60 |
61 | extern "C" NTSTATUS ZwQuerySystemInformation(SYSTEM_INFORMATION_CLASS systemInformationClass, PVOID systemInformation, ULONG systemInformationLength, PULONG returnLength);
62 | extern "C" NTKERNELAPI PVOID PsGetProcessSectionBaseAddress(PEPROCESS Process);
63 | extern "C" NTKERNELAPI PPEB NTAPI PsGetProcessPeb(IN PEPROCESS Process);
64 |
65 | #include "memory.h"
66 | #include "util.h"
67 | #include "core.h"
--------------------------------------------------------------------------------
/Driver/util.cpp:
--------------------------------------------------------------------------------
1 | #pragma once
2 | #include "util.h"
3 |
4 |
5 | namespace Util {
6 |
7 | PIMAGE_NT_HEADERS getHeader(PVOID module) {
8 | return (PIMAGE_NT_HEADERS)((PBYTE)module + PIMAGE_DOS_HEADER(module)->e_lfanew);
9 | }
10 |
11 | PBYTE FindPattern(PVOID module, DWORD size, LPCSTR pattern, LPCSTR mask) {
12 |
13 | auto checkMask = [](PBYTE buffer, LPCSTR pattern, LPCSTR mask) -> BOOL
14 | {
15 | for (auto x = buffer; *mask; pattern++, mask++, x++) {
16 | auto addr = *(BYTE*)(pattern);
17 | if (addr != *x && *mask != '?')
18 | return FALSE;
19 | }
20 |
21 | return TRUE;
22 | };
23 |
24 | for (auto x = 0; x < size - strlen(mask); x++) {
25 |
26 | auto addr = (PBYTE)module + x;
27 | if (checkMask(addr, pattern, mask))
28 | return addr;
29 | }
30 |
31 | return NULL;
32 | }
33 |
34 | PBYTE FindPattern(PVOID base, LPCSTR pattern, LPCSTR mask) {
35 |
36 | auto header = getHeader(base);
37 | auto section = IMAGE_FIRST_SECTION(header);
38 |
39 | for (auto x = 0; x < header->FileHeader.NumberOfSections; x++, section++) {
40 |
41 | /*
42 | * Avoids non paged memory,
43 | * As well as greatly speeds up the process of scanning 30+ sections.
44 | */
45 | if (!memcmp(section->Name, ".text", 5) || !memcmp(section->Name, "PAGE", 4)) {
46 | auto addr = FindPattern((PBYTE)base + section->VirtualAddress, section->Misc.VirtualSize, pattern, mask);
47 | if (addr) {
48 | printf("[mapper] Found in Section -> [ %s ]", section->Name);
49 | return addr;
50 | }
51 | }
52 | }
53 |
54 | return NULL;
55 | }
56 |
57 | }
58 |
--------------------------------------------------------------------------------
/Usermode/memory.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 | #include
3 | #include
4 | #include