├── .gitignore ├── Client ├── ConsoleApplication1.sln ├── ConsoleApplication1 │ ├── ConsoleApplication1.c │ ├── ConsoleApplication1.vcxproj │ ├── ConsoleApplication1.vcxproj.filters │ └── ConsoleApplication1.vcxproj.user └── Release │ ├── ConsoleApplication1.exe │ └── ConsoleApplication1.pdb ├── README.md ├── ReadWriteDriver ├── .gitattributes ├── .gitignore ├── README.md ├── RWdriver.sln └── RWdriver │ ├── RWdriver.inf │ ├── RWdriver.vcxproj │ ├── RWdriver.vcxproj.filters │ ├── RWdriver.vcxproj.user │ └── Source.c └── image ├── DEMO.gif ├── img1.png ├── img2.png └── img3.png /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | /Client/.vs 3 | /ReadWriteDriver/x64 4 | /Client/x64 5 | -------------------------------------------------------------------------------- /Client/ConsoleApplication1.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 17 4 | VisualStudioVersion = 17.8.34408.163 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ConsoleApplication1", "ConsoleApplication1\ConsoleApplication1.vcxproj", "{12807974-A5F1-4722-9786-7028BFB4CCE1}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|x64 = Debug|x64 11 | Debug|x86 = Debug|x86 12 | Release|x64 = Release|x64 13 | Release|x86 = Release|x86 14 | EndGlobalSection 15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 16 | {12807974-A5F1-4722-9786-7028BFB4CCE1}.Debug|x64.ActiveCfg = Debug|x64 17 | {12807974-A5F1-4722-9786-7028BFB4CCE1}.Debug|x64.Build.0 = Debug|x64 18 | {12807974-A5F1-4722-9786-7028BFB4CCE1}.Debug|x86.ActiveCfg = Debug|Win32 19 | {12807974-A5F1-4722-9786-7028BFB4CCE1}.Debug|x86.Build.0 = Debug|Win32 20 | {12807974-A5F1-4722-9786-7028BFB4CCE1}.Release|x64.ActiveCfg = Release|x64 21 | {12807974-A5F1-4722-9786-7028BFB4CCE1}.Release|x64.Build.0 = Release|x64 22 | {12807974-A5F1-4722-9786-7028BFB4CCE1}.Release|x86.ActiveCfg = Release|Win32 23 | {12807974-A5F1-4722-9786-7028BFB4CCE1}.Release|x86.Build.0 = Release|Win32 24 | EndGlobalSection 25 | GlobalSection(SolutionProperties) = preSolution 26 | HideSolutionNode = FALSE 27 | EndGlobalSection 28 | GlobalSection(ExtensibilityGlobals) = postSolution 29 | SolutionGuid = {88ECAC6F-05F8-4059-A18F-75AC8013D7E2} 30 | EndGlobalSection 31 | EndGlobal 32 | -------------------------------------------------------------------------------- /Client/ConsoleApplication1/ConsoleApplication1.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #define read_code CTL_CODE(FILE_DEVICE_UNKNOWN, 0x776, METHOD_BUFFERED, FILE_SPECIAL_ACCESS) 6 | #define write_code CTL_CODE(FILE_DEVICE_UNKNOWN, 0x777, METHOD_BUFFERED, FILE_SPECIAL_ACCESS) 7 | 8 | typedef struct info_t { 9 | HANDLE target_pid; 10 | ULONG64 target_address; 11 | PBYTE buffer_address; 12 | SIZE_T Size; 13 | } UserData, * PUserData; 14 | 15 | BOOL SendIoControlCode(HANDLE hDevice, DWORD dwIoControlCode, PVOID pInBuffer, DWORD nInBufferSize, PVOID pOutBuffer, DWORD nOutBufferSize, LPDWORD lpBytesReturned) { 16 | BOOL bResult = DeviceIoControl( 17 | hDevice, 18 | dwIoControlCode, 19 | pInBuffer, 20 | nInBufferSize, 21 | pOutBuffer, 22 | nOutBufferSize, 23 | lpBytesReturned, 24 | NULL 25 | ); 26 | return bResult; 27 | } 28 | 29 | int main(int argc, char* argv[]) { 30 | HANDLE hDevice = CreateFile(L"\\\\.\\cartidriver", GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); 31 | if (hDevice == INVALID_HANDLE_VALUE) { 32 | printf("Error: Could not open device - %d\n", GetLastError()); 33 | return 1; 34 | } 35 | 36 | printf("Test\n"); 37 | UserData data; 38 | data.target_pid = 0x24F0; 39 | data.target_address = 0x7FF7EF73B000; 40 | data.buffer_address = (PBYTE)malloc(64); 41 | data.Size = 64; 42 | 43 | // 初始化目标进程 44 | DWORD bytesReturned; 45 | // 读取内存 46 | if (!SendIoControlCode(hDevice, read_code, &data, sizeof(data), &data, sizeof(data), &bytesReturned)) { 47 | printf("Error: read_code failed - %d\n", GetLastError()); 48 | CloseHandle(hDevice); 49 | free(data.buffer_address); 50 | return 1; 51 | } 52 | 53 | printf("Memory content before write: "); 54 | for (SIZE_T i = 0; i < data.Size; i++) { 55 | printf("%02X ", data.buffer_address[i]); 56 | } 57 | printf("\n"); 58 | 59 | // 准备写入数据 60 | memset(data.buffer_address, 'A', 64); // 将缓冲区填充为64个 'A' 字符 61 | 62 | // 写入内存 63 | if (!SendIoControlCode(hDevice, write_code, &data, sizeof(data), &data, sizeof(data), &bytesReturned)) { 64 | printf("Error: write_code failed - %d\n", GetLastError()); 65 | CloseHandle(hDevice); 66 | free(data.buffer_address); 67 | return 1; 68 | } 69 | 70 | printf("Read After Write:\n"); 71 | // 再次读取内存 72 | if (!SendIoControlCode(hDevice, read_code, &data, sizeof(data), &data, sizeof(data), &bytesReturned)) { 73 | printf("Error: read_code failed - %d\n", GetLastError()); 74 | CloseHandle(hDevice); 75 | free(data.buffer_address); 76 | return 1; 77 | } 78 | 79 | printf("Memory content after write: "); 80 | for (SIZE_T i = 0; i < data.Size; i++) { 81 | printf("%02X ", data.buffer_address[i]); 82 | } 83 | printf("\n"); 84 | 85 | // 清理 86 | CloseHandle(hDevice); 87 | free(data.buffer_address); 88 | 89 | return 0; 90 | } 91 | -------------------------------------------------------------------------------- /Client/ConsoleApplication1/ConsoleApplication1.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | Debug 14 | x64 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | 17.0 23 | Win32Proj 24 | {12807974-a5f1-4722-9786-7028bfb4cce1} 25 | ConsoleApplication1 26 | 10.0 27 | 28 | 29 | 30 | Application 31 | true 32 | v143 33 | Unicode 34 | 35 | 36 | Application 37 | false 38 | v143 39 | true 40 | Unicode 41 | 42 | 43 | Application 44 | true 45 | v143 46 | Unicode 47 | 48 | 49 | Application 50 | false 51 | v143 52 | true 53 | Unicode 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | Level3 76 | true 77 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 78 | true 79 | 80 | 81 | Console 82 | true 83 | 84 | 85 | 86 | 87 | Level3 88 | true 89 | true 90 | true 91 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 92 | true 93 | 94 | 95 | Console 96 | true 97 | true 98 | true 99 | 100 | 101 | 102 | 103 | Level3 104 | true 105 | _DEBUG;_CONSOLE;%(PreprocessorDefinitions) 106 | true 107 | 108 | 109 | Console 110 | true 111 | 112 | 113 | 114 | 115 | Level3 116 | true 117 | true 118 | true 119 | NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 120 | true 121 | 122 | 123 | Console 124 | true 125 | true 126 | true 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | -------------------------------------------------------------------------------- /Client/ConsoleApplication1/ConsoleApplication1.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | 來源檔案 20 | 21 | 22 | -------------------------------------------------------------------------------- /Client/ConsoleApplication1/ConsoleApplication1.vcxproj.user: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | -------------------------------------------------------------------------------- /Client/Release/ConsoleApplication1.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ShallowFeather/ReadWriteDriver/1765d6ae5f58b1c3edbb8d250a3566bb5ea5c9b4/Client/Release/ConsoleApplication1.exe -------------------------------------------------------------------------------- /Client/Release/ConsoleApplication1.pdb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ShallowFeather/ReadWriteDriver/1765d6ae5f58b1c3edbb8d250a3566bb5ea5c9b4/Client/Release/ConsoleApplication1.pdb -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # R/W memory without Mmcopy & attach 2 | 3 | > 補 剛剛測試過結合 https://github.com/Rythorndoran/enum_real_dirbase 此專案可讀 apex 記憶體 4 | 5 | 利用分頁機制切換 page frame number 並刷新 TLB 來讀寫物理記憶體。 6 | 7 | 已實現 IOCTL 之溝通,可以自行替換。 8 | 9 | Kernel Function 的 Offset 需自行替換 (MmAllocateIndependentPages, MiGetPteAddress) 10 | 11 | 目前預設為: 12 | - MmAllocateIndependentPages (ntoskrnl + 0xfd590) 13 | - MiGetPteAddress (ntoskrnl + 0xBA9F8) 14 | 15 | 主要是因為懶得寫特徵去 call 下面也會講要怎麼找 offset。 16 | ## DEMO 17 | ![gif](image/DEMO.gif) 18 | ## 實現細節 19 | ![image](image/img1.png) 20 | 21 | 此讀寫方式實現原理為先利用 MmAllocateIndependentPages 創建頁表 (為了不生成大頁表`PDE`) 且設為 `PTE` 的最大值。 22 | 23 | 然後再去尋找要讀取的 process 當中的虛擬地址,並將他轉成物理地址。 24 | ```c= 25 | ULONG64 TransformationCR3(UINT32 Index, ULONG64 cr3, ULONG64 VirtualAddress) 26 | { 27 | cr3 &= ~0xf; 28 | ULONG64 PAGE_OFFSET = VirtualAddress & ~(~0ul << 12); 29 | SIZE_T BytesTransferred = 0; 30 | ULONG64 a = 0, b = 0, c = 0; 31 | ReadPhysicalAddress(Index, (cr3 + 8 * ((VirtualAddress >> 39) & (0x1ffll))), &a, sizeof(a)); // 讀 PDPE 32 | if (~a & 1) 33 | { 34 | return 0; 35 | } 36 | ReadPhysicalAddress(Index, ((a & ((~0xfull << 8) & 0xfffffffffull)) + 8 * 37 | ((VirtualAddress >> 30) & (0x1ffll))), &b, sizeof(b)); // 讀 PDE 38 | if (~b & 1) 39 | { 40 | return 0; 41 | } 42 | if (b & 0x80) 43 | { 44 | return (b & (~0ull << 42 >> 12)) + (VirtualAddress & ~(~0ull << 30)); 45 | } 46 | ReadPhysicalAddress(Index, ((b & ((~0xfull << 8) & 0xfffffffffull)) + 8 * 47 | ((VirtualAddress >> 21) & (0x1ffll))), &c, sizeof(c)); // 讀 PTE 48 | if (~c & 1) 49 | { 50 | return 0; 51 | } 52 | if (c & 0x80) 53 | { 54 | return (c & ((~0xfull << 8) & 0xfffffffffull)) + (VirtualAddress & ~(~0ull << 55 | 21)); 56 | } 57 | ULONG64 address = 0; 58 | ReadPhysicalAddress(Index, ((c & ((~0xfull << 8) & 0xfffffffffull)) + 8 * 59 | ((VirtualAddress >> 12) & (0x1ffll))), &address, sizeof(address)); // 讀物理地址 60 | address &= ((~0xfull << 8) & 0xfffffffffull); 61 | if (!address) 62 | { 63 | return 0; 64 | } 65 | return address + PAGE_OFFSET; 66 | } 67 | ``` 68 | 藉由上述函數即可將 process 對應的虛擬地址轉換出來, 69 | 70 | 而由於需要 cr3 因此也需要獲取 PEPROCESS 結構才能夠得到 cr3, 71 | 72 | PEPROCESS 的 DTB 其實就是 Cr3, 73 | 74 | Cr3 的 offset 網路上都搜尋的到 這邊是 0x28。 75 | 76 | ![image](image/img2.png) 77 | 78 | 取得物理地址以後所需要的就剩讀取了。 79 | ```c= 80 | VOID ReadPhysicalAddress(UINT32 Index, ULONG64 phy, PVOID buffer, SIZE_T size) 81 | { 82 | PageTable* page = &List[Index]; 83 | page->Pte->PageFrameNumber = phy >> PAGE_SHIFT; 84 | //DbgPrint("Physical Address: 0x%x\n", phy); 85 | __invlpg(page->VirtualAddress); 86 | __movsb((PUCHAR)buffer, (PUCHAR)page->VirtualAddress + (phy & 0xFFF), size); 87 | page->Pte->PageFrameNumber = page->OldPageFrameNumber; 88 | __invlpg(page->VirtualAddress); 89 | } 90 | ``` 91 | 可以看到首先獲取 page 以後將他的 pfn 改成物理地址的 pfn, 92 | 93 | 修改之後刷新 TLB 讓修改生效就能夠取得記憶體當中的數值了, 94 | 95 | 而寫入只需要將 `__movsb` 的值相反就能實現了。 96 | 97 | ## 問題 98 | 需要避免兩個問題 99 | multiprocessor 以及跨頁讀取 100 | > 當中可能有 Cache 問題,不確定寫入 CacheDisable 跟 WriteThrough 能不能解決,不知道怎麼測試。 101 | 102 | 1. multiprocessor 103 | 由於 multiprocessor 可能會導致同時獲取同一個 page 因此需要多開幾個 page 來解決,並且透過KeGetCurrentProcessorIndex 來分配 page 這樣才能保證每個 processor 不會獲取到同一個 page。 104 | 2. 跨頁讀取 105 | 如果說讀寫記憶體時超過了 0xFFF 便會跨頁,那這個問題也很簡單,你沒辦法一次讀超過兩個頁表的內容就讀兩次,當超出範圍時就切到能讀的最大值然後再去讀下一段就好了 。 106 | 107 | ## 找 ntoskrnl offset 108 | 找 offset 很簡單 109 | 110 | 把 ntoskrnl.exe 從系統裡面拉出來丟 IDA 111 | 112 | 因為 ntoskrnl 用 IDA 開啟可以自動載入 PDB 因此很方便就能找出想要使用的 Function 位址 113 | 114 | ![image](image/img3.png) 115 | 116 | 或是其實也可以利用 windbg 然後搜尋該 function 也能獲取 offset 117 | ## Reference 118 | 此專案為 https://bbs.kanxue.com/thread-279103.htm 此篇的概念實現。 119 | 120 | 並參考 lyshark https://www.lyshark.com/post/19fe1026.html 此篇之 cr3 虛擬地址轉物理地址。 121 | -------------------------------------------------------------------------------- /ReadWriteDriver/.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | -------------------------------------------------------------------------------- /ReadWriteDriver/.gitignore: -------------------------------------------------------------------------------- 1 | 2 | /RWdriver/x64 3 | -------------------------------------------------------------------------------- /ReadWriteDriver/README.md: -------------------------------------------------------------------------------- 1 | # RWdriver 2 | Read Memory without attach 3 | -------------------------------------------------------------------------------- /ReadWriteDriver/RWdriver.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 17 4 | VisualStudioVersion = 17.8.34408.163 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "RWdriver", "RWdriver\RWdriver.vcxproj", "{A6C8BD86-C384-4DB6-9F8B-2BFE9EA6EB4C}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|ARM64 = Debug|ARM64 11 | Debug|x64 = Debug|x64 12 | Release|ARM64 = Release|ARM64 13 | Release|x64 = Release|x64 14 | EndGlobalSection 15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 16 | {A6C8BD86-C384-4DB6-9F8B-2BFE9EA6EB4C}.Debug|ARM64.ActiveCfg = Debug|ARM64 17 | {A6C8BD86-C384-4DB6-9F8B-2BFE9EA6EB4C}.Debug|ARM64.Build.0 = Debug|ARM64 18 | {A6C8BD86-C384-4DB6-9F8B-2BFE9EA6EB4C}.Debug|ARM64.Deploy.0 = Debug|ARM64 19 | {A6C8BD86-C384-4DB6-9F8B-2BFE9EA6EB4C}.Debug|x64.ActiveCfg = Debug|x64 20 | {A6C8BD86-C384-4DB6-9F8B-2BFE9EA6EB4C}.Debug|x64.Build.0 = Debug|x64 21 | {A6C8BD86-C384-4DB6-9F8B-2BFE9EA6EB4C}.Debug|x64.Deploy.0 = Debug|x64 22 | {A6C8BD86-C384-4DB6-9F8B-2BFE9EA6EB4C}.Release|ARM64.ActiveCfg = Release|ARM64 23 | {A6C8BD86-C384-4DB6-9F8B-2BFE9EA6EB4C}.Release|ARM64.Build.0 = Release|ARM64 24 | {A6C8BD86-C384-4DB6-9F8B-2BFE9EA6EB4C}.Release|ARM64.Deploy.0 = Release|ARM64 25 | {A6C8BD86-C384-4DB6-9F8B-2BFE9EA6EB4C}.Release|x64.ActiveCfg = Release|x64 26 | {A6C8BD86-C384-4DB6-9F8B-2BFE9EA6EB4C}.Release|x64.Build.0 = Release|x64 27 | {A6C8BD86-C384-4DB6-9F8B-2BFE9EA6EB4C}.Release|x64.Deploy.0 = Release|x64 28 | EndGlobalSection 29 | GlobalSection(SolutionProperties) = preSolution 30 | HideSolutionNode = FALSE 31 | EndGlobalSection 32 | GlobalSection(ExtensibilityGlobals) = postSolution 33 | SolutionGuid = {FAFBC7B4-F0AB-4F86-9643-66AFA605B0AD} 34 | EndGlobalSection 35 | EndGlobal 36 | -------------------------------------------------------------------------------- /ReadWriteDriver/RWdriver/RWdriver.inf: -------------------------------------------------------------------------------- 1 | ; 2 | ; RWdriver.inf 3 | ; 4 | 5 | [Version] 6 | Signature="$WINDOWS NT$" 7 | Class=System 8 | ClassGuid={4d36e97d-e325-11ce-bfc1-08002be10318} 9 | Provider=%ManufacturerName% 10 | DriverVer= 11 | CatalogFile=RWdriver.cat 12 | PnpLockdown=1 13 | 14 | [DestinationDirs] 15 | DefaultDestDir = 13 16 | 17 | [SourceDisksNames] 18 | 1 = %DiskName%,,,"" 19 | 20 | [SourceDisksFiles] 21 | 22 | [Manufacturer] 23 | %ManufacturerName%=Standard,NT$ARCH$.10.0...16299 ; %13% support introduced in build 16299 24 | 25 | [Standard.NT$ARCH$.10.0...16299] 26 | 27 | [Strings] 28 | ManufacturerName="" ;TODO: Replace with your manufacturer name 29 | DiskName="RWdriver Source Disk" 30 | -------------------------------------------------------------------------------- /ReadWriteDriver/RWdriver/RWdriver.vcxproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | x64 7 | 8 | 9 | Release 10 | x64 11 | 12 | 13 | Debug 14 | ARM64 15 | 16 | 17 | Release 18 | ARM64 19 | 20 | 21 | 22 | {A6C8BD86-C384-4DB6-9F8B-2BFE9EA6EB4C} 23 | {dd38f7fc-d7bd-488b-9242-7d8754cde80d} 24 | v4.5 25 | 12.0 26 | Debug 27 | x64 28 | RWdriver 29 | 30 | 31 | 32 | Windows10 33 | true 34 | WindowsKernelModeDriver10.0 35 | Driver 36 | WDM 37 | 38 | 39 | Windows10 40 | false 41 | WindowsKernelModeDriver10.0 42 | Driver 43 | WDM 44 | 45 | 46 | Windows10 47 | true 48 | WindowsKernelModeDriver10.0 49 | Driver 50 | WDM 51 | 52 | 53 | Windows10 54 | false 55 | WindowsKernelModeDriver10.0 56 | Driver 57 | WDM 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | DbgengKernelDebugger 69 | 70 | 71 | DbgengKernelDebugger 72 | 73 | 74 | DbgengKernelDebugger 75 | 76 | 77 | DbgengKernelDebugger 78 | 79 | 80 | 81 | sha256 82 | 83 | 84 | 85 | 86 | sha256 87 | 88 | 89 | false 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | -------------------------------------------------------------------------------- /ReadWriteDriver/RWdriver/RWdriver.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | {8E41214B-6785-4CFE-B992-037D68949A14} 18 | inf;inv;inx;mof;mc; 19 | 20 | 21 | 22 | 23 | Source Files 24 | 25 | 26 | -------------------------------------------------------------------------------- /ReadWriteDriver/RWdriver/RWdriver.vcxproj.user: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | -------------------------------------------------------------------------------- /ReadWriteDriver/RWdriver/Source.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | NTKERNELAPI NTSTATUS IoCreateDriver(PUNICODE_STRING DriverName, PDRIVER_INITIALIZE InitializationFunction); 10 | extern NTSYSAPI PVOID RtlPcToFileHeader(PVOID PcValue, PVOID* BaseOfImage); 11 | 12 | #define read_code CTL_CODE(FILE_DEVICE_UNKNOWN, 0x776, METHOD_BUFFERED, FILE_SPECIAL_ACCESS) 13 | #define write_code CTL_CODE(FILE_DEVICE_UNKNOWN, 0x777, METHOD_BUFFERED, FILE_SPECIAL_ACCESS) 14 | 15 | typedef struct info_t { 16 | HANDLE target_pid; 17 | ULONG64 target_address; 18 | PBYTE buffer_address; 19 | SIZE_T Size; 20 | } UserData, * PUserData; 21 | 22 | typedef struct _MMPTE_HARDWARE64 23 | { 24 | ULONG64 Valid : 1; 25 | ULONG64 Dirty1 : 1; 26 | ULONG64 Owner : 1; 27 | ULONG64 WriteThrough : 1; 28 | ULONG64 CacheDisable : 1; 29 | ULONG64 Accessed : 1; 30 | ULONG64 Dirty : 1; 31 | ULONG64 LargePage : 1; 32 | ULONG64 Global : 1; 33 | ULONG64 CopyOnWrite : 1; 34 | ULONG64 Prototype : 1; 35 | ULONG64 Write : 1; 36 | ULONG64 PageFrameNumber : 36; 37 | ULONG64 Reserved1 : 4; 38 | ULONG64 SoftwareWsIndex : 11; 39 | ULONG64 NoExecute : 1; 40 | } PTE; 41 | 42 | typedef struct PageTable 43 | { 44 | PTE* Pte; 45 | ULONG64 VirtualAddress; 46 | ULONG64 OldPageFrameNumber; 47 | } PageTable; 48 | 49 | typedef PVOID(__fastcall* MmAllocateIndependentPages_t)(IN SIZE_T NumberOfBytes, IN ULONG Node); 50 | MmAllocateIndependentPages_t MmAllocateIndependentPages; 51 | 52 | typedef ULONG64(__fastcall* MiGetPteAddress_t)(IN ULONG64 baseAddress); 53 | MiGetPteAddress_t MiGetPteAddress; 54 | 55 | static uintptr_t ntoskrnl_imagebase; 56 | 57 | PageTable List[64]; 58 | 59 | VOID ReadPhysicalAddress(UINT32 Index, ULONG64 phy, PVOID buffer, SIZE_T size) 60 | { 61 | 62 | PageTable* page = &List[Index]; 63 | _disable(); 64 | page->Pte->PageFrameNumber = phy >> PAGE_SHIFT; 65 | //DbgPrint("Physical Address: 0x%x\n", phy); 66 | __invlpg(page->VirtualAddress); 67 | __movsb((PUCHAR)buffer, (PUCHAR)page->VirtualAddress + (phy & 0xFFF), size); 68 | page->Pte->PageFrameNumber = page->OldPageFrameNumber; 69 | __invlpg(page->VirtualAddress); 70 | _enable(); 71 | } 72 | 73 | VOID WritePhysicalAddress(UINT32 Index, ULONG64 phy, PVOID buffer, SIZE_T size) 74 | { 75 | PageTable* page = &List[Index]; 76 | _disable(); 77 | page->Pte->PageFrameNumber = phy >> PAGE_SHIFT; 78 | //DbgPrint("Physical Address: 0x%x\n", phy); 79 | __invlpg(page->VirtualAddress); 80 | __movsb((PUCHAR)page->VirtualAddress + (phy & 0xFFF), (PUCHAR)buffer, size); 81 | page->Pte->CacheDisable = 1; 82 | page->Pte->WriteThrough = 1; 83 | page->Pte->PageFrameNumber = page->OldPageFrameNumber; 84 | __invlpg(page->VirtualAddress); 85 | _enable(); 86 | 87 | } 88 | 89 | 90 | ULONG64 TransformationCR3(UINT32 Index, ULONG64 cr3, ULONG64 VirtualAddress) 91 | { 92 | cr3 &= ~0xf; 93 | ULONG64 PAGE_OFFSET = VirtualAddress & ~(~0ul << 12); 94 | SIZE_T BytesTransferred = 0; 95 | ULONG64 a = 0, b = 0, c = 0; 96 | ReadPhysicalAddress(Index, (cr3 + 8 * ((VirtualAddress >> 39) & (0x1ffll))), &a, sizeof(a)); 97 | if (~a & 1) 98 | { 99 | return 0; 100 | } 101 | ReadPhysicalAddress(Index, ((a & ((~0xfull << 8) & 0xfffffffffull)) + 8 * 102 | ((VirtualAddress >> 30) & (0x1ffll))), &b, sizeof(b)); 103 | if (~b & 1) 104 | { 105 | return 0; 106 | } 107 | if (b & 0x80) 108 | { 109 | return (b & (~0ull << 42 >> 12)) + (VirtualAddress & ~(~0ull << 30)); 110 | } 111 | ReadPhysicalAddress(Index, ((b & ((~0xfull << 8) & 0xfffffffffull)) + 8 * 112 | ((VirtualAddress >> 21) & (0x1ffll))), &c, sizeof(c)); 113 | if (~c & 1) 114 | { 115 | return 0; 116 | } 117 | if (c & 0x80) 118 | { 119 | return (c & ((~0xfull << 8) & 0xfffffffffull)) + (VirtualAddress & ~(~0ull << 120 | 21)); 121 | } 122 | ULONG64 address = 0; 123 | ReadPhysicalAddress(Index, ((c & ((~0xfull << 8) & 0xfffffffffull)) + 8 * 124 | ((VirtualAddress >> 12) & (0x1ffll))), &address, sizeof(address)); 125 | address &= ((~0xfull << 8) & 0xfffffffffull); 126 | if (!address) 127 | { 128 | return 0; 129 | } 130 | return address + PAGE_OFFSET; 131 | } 132 | 133 | VOID ReadVirtualMemory(UINT32 Index, ULONG64 cr3, ULONG64 VirtualAddress, PVOID Buffer, UINT64 size) { 134 | UINT64 read = 0; 135 | while (size) { 136 | ULONG64 PhysicalMemory = TransformationCR3(Index, cr3, VirtualAddress + read); 137 | if (PhysicalMemory == 0) break; 138 | ULONG64 _read = min(PAGE_SIZE - (PhysicalMemory & 0xfff), size); 139 | //DbgPrint("PhysicalMemory: %p\n", PhysicalMemory); 140 | ReadPhysicalAddress(Index, PhysicalMemory, (PVOID)((UINT_PTR)Buffer + read), _read); 141 | read += _read; 142 | size -= _read; 143 | } 144 | } 145 | 146 | VOID WriteVirtualMemory(UINT32 Index, ULONG64 cr3, ULONG64 VirtualAddress, PVOID Buffer, UINT64 size) { 147 | UINT64 write = 0; 148 | while (size) { 149 | ULONG64 PhysicalMemory = TransformationCR3(Index, cr3, VirtualAddress + write); 150 | if (PhysicalMemory == 0) break; 151 | ULONG64 _write = min(PAGE_SIZE - (PhysicalMemory & 0xfff), size); 152 | //DbgPrint("PhysicalMemory: %p\n", PhysicalMemory); 153 | WritePhysicalAddress(Index, PhysicalMemory, (PVOID)((UINT_PTR)Buffer + write), _write); 154 | write += _write; 155 | size -= _write; 156 | } 157 | } 158 | 159 | 160 | NTSTATUS ctl_io(PDEVICE_OBJECT device_obj, PIRP irp) { 161 | UNREFERENCED_PARAMETER(device_obj); 162 | 163 | irp->IoStatus.Information = sizeof(UserData); 164 | PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(irp); 165 | PUserData Buffer = (PUserData)irp->AssociatedIrp.SystemBuffer; 166 | DbgPrint("IOCTL\n"); 167 | 168 | 169 | if (stack) { 170 | if (Buffer && sizeof(*Buffer) >= sizeof(UserData)) { 171 | ULONG ctl_code = stack->Parameters.DeviceIoControl.IoControlCode; 172 | if (ctl_code == read_code) { 173 | DbgPrint("READ\n"); 174 | UINT32 Index = KeGetCurrentProcessorIndex(); 175 | PEPROCESS Process; 176 | PsLookupProcessByProcessId((HANDLE)Buffer->target_pid, &Process); 177 | PUCHAR Var = (PUCHAR)Process; 178 | ULONG64 cr3 = *(ULONG64*)(Var + 0x28); 179 | //DbgPrint("Address: %llx\n", Buffer->target_address); 180 | //DbgPrint("Cr3: %x\n", cr3); 181 | ReadVirtualMemory(Index, cr3, (ULONG64)Buffer->target_address, Buffer->buffer_address, Buffer->Size); 182 | //ReadVirtualMemory(Index, cr3, (ULONG64)Buffer->target_address, Buffer->buffer_address, Buffer->Size); 183 | } 184 | else if (ctl_code == write_code) { 185 | DbgPrint("WRITE\n"); 186 | UINT32 Index = KeGetCurrentProcessorIndex(); 187 | PEPROCESS Process; 188 | PsLookupProcessByProcessId((HANDLE)Buffer->target_pid, &Process); 189 | PUCHAR Var = (PUCHAR)Process; 190 | ULONG64 cr3 = *(ULONG64*)(Var + 0x28); 191 | //DbgPrint("Address: %llx\n", Buffer->target_address); 192 | //DbgPrint("Cr3: %x\n", cr3); 193 | WriteVirtualMemory(Index, cr3, (ULONG64)Buffer->target_address, Buffer->buffer_address, Buffer->Size); 194 | } 195 | irp->IoStatus.Information = sizeof(UserData); 196 | } 197 | } 198 | 199 | IoCompleteRequest(irp, IO_NO_INCREMENT); 200 | return STATUS_SUCCESS; 201 | } 202 | 203 | NTSTATUS unsupported_io(PDEVICE_OBJECT device_obj, PIRP irp) { 204 | UNREFERENCED_PARAMETER(device_obj); 205 | 206 | irp->IoStatus.Status = STATUS_NOT_SUPPORTED; 207 | IoCompleteRequest(irp, IO_NO_INCREMENT); 208 | return irp->IoStatus.Status; 209 | } 210 | 211 | NTSTATUS create_io(PDEVICE_OBJECT device_obj, PIRP irp) { 212 | UNREFERENCED_PARAMETER(device_obj); 213 | 214 | irp->IoStatus.Status = STATUS_SUCCESS; 215 | IoCompleteRequest(irp, IO_NO_INCREMENT); 216 | return irp->IoStatus.Status; 217 | } 218 | 219 | NTSTATUS close_io(PDEVICE_OBJECT device_obj, PIRP irp) { 220 | UNREFERENCED_PARAMETER(device_obj); 221 | 222 | irp->IoStatus.Status = STATUS_SUCCESS; 223 | IoCompleteRequest(irp, IO_NO_INCREMENT); 224 | return irp->IoStatus.Status; 225 | } 226 | 227 | NTSTATUS DriverEntry(PDRIVER_OBJECT driver_obj, PUNICODE_STRING registery_path) { 228 | UNREFERENCED_PARAMETER(registery_path); 229 | UNICODE_STRING dev_name, sym_link; 230 | PDEVICE_OBJECT dev_obj; 231 | 232 | RtlInitUnicodeString(&dev_name, L"\\Device\\cartidriver"); 233 | auto status = IoCreateDevice(driver_obj, 0, &dev_name, FILE_DEVICE_UNKNOWN, FILE_DEVICE_SECURE_OPEN, FALSE, &dev_obj); 234 | if (status != STATUS_SUCCESS) return status; 235 | 236 | RtlInitUnicodeString(&sym_link, L"\\DosDevices\\cartidriver"); 237 | status = IoCreateSymbolicLink(&sym_link, &dev_name); 238 | if (status != STATUS_SUCCESS) return status; 239 | 240 | /* Init */ 241 | uintptr_t ntoskrnl_imagebase; 242 | RtlPcToFileHeader(&RtlPcToFileHeader, &ntoskrnl_imagebase); 243 | DbgPrint("ntoskrnl_imagebase: %p\n", ntoskrnl_imagebase); 244 | uintptr_t pMmAllocateIndependentPages = ntoskrnl_imagebase + 0xfd590; // ntoskrnl!MmAllocateIndependentPages 245 | MmAllocateIndependentPages = (MmAllocateIndependentPages_t)(pMmAllocateIndependentPages); 246 | uintptr_t pMiGetPteAddress = ntoskrnl_imagebase + 0xBA9F8; 247 | MiGetPteAddress = (MiGetPteAddress_t)(pMiGetPteAddress); 248 | 249 | // Init Table 250 | for (int i = 0; i < 64; i++) { 251 | List[i].VirtualAddress = MmAllocateIndependentPages(0x1000, -1); 252 | memset(List[i].VirtualAddress, 0, 0x1000); 253 | List[i].Pte = MiGetPteAddress(List[i].VirtualAddress); 254 | //DbgPrint("PTE: %p\n", List[i].Pte); 255 | List[i].OldPageFrameNumber = List[i].Pte->PageFrameNumber; 256 | } 257 | /*Test*/ 258 | /* 259 | UINT32 Index = KeGetCurrentProcessorIndex(); 260 | PEPROCESS Process; 261 | PsLookupProcessByProcessId((HANDLE)0x24F0, &Process); 262 | PUCHAR Var = (PUCHAR)Process; 263 | ULONG64 cr3 = *(ULONG64*)(Var + 0x28); 264 | DbgPrint("cr3: %x\n", cr3); 265 | UCHAR buffer[64]; 266 | ReadVirtualMemory(Index, cr3, 0x7FF7EF73B000, buffer, sizeof(buffer)); 267 | for (int i = 0; i < 64; i++) { 268 | DbgPrint("%x ", buffer[i]); 269 | } 270 | */ 271 | 272 | dev_obj->Flags |= DO_BUFFERED_IO; 273 | 274 | for (int t = 0; t <= IRP_MJ_MAXIMUM_FUNCTION; t++) 275 | driver_obj->MajorFunction[t] = unsupported_io; 276 | 277 | driver_obj->MajorFunction[IRP_MJ_CREATE] = create_io; 278 | driver_obj->MajorFunction[IRP_MJ_CLOSE] = close_io; 279 | driver_obj->MajorFunction[IRP_MJ_DEVICE_CONTROL] = ctl_io; 280 | driver_obj->DriverUnload = NULL; 281 | 282 | dev_obj->Flags &= ~DO_DEVICE_INITIALIZING; 283 | DbgPrint("LOAD\n"); 284 | return STATUS_SUCCESS; 285 | } -------------------------------------------------------------------------------- /image/DEMO.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ShallowFeather/ReadWriteDriver/1765d6ae5f58b1c3edbb8d250a3566bb5ea5c9b4/image/DEMO.gif -------------------------------------------------------------------------------- /image/img1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ShallowFeather/ReadWriteDriver/1765d6ae5f58b1c3edbb8d250a3566bb5ea5c9b4/image/img1.png -------------------------------------------------------------------------------- /image/img2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ShallowFeather/ReadWriteDriver/1765d6ae5f58b1c3edbb8d250a3566bb5ea5c9b4/image/img2.png -------------------------------------------------------------------------------- /image/img3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ShallowFeather/ReadWriteDriver/1765d6ae5f58b1c3edbb8d250a3566bb5ea5c9b4/image/img3.png --------------------------------------------------------------------------------