一。目标程序***********
//target.exe
//test.exe
程序预览
附件 85882
本文通过ssdt hook 使test.exe读取内存的值为77
二。验证思路***********
用od打开test.exe看ReadProcessMemory
附件 85883
附件 85884
附件 85885
调用SSDT表中函数的编号为0xBA
windbg中加上断点
kd> bp nt!NtReadVirtualMemory
发现会停很多次
查看堆栈
kd> dd esp
附件 85886
其中esp+8为读内存起始地址
加上条件断点
kd> bc 0
kd> bp nt!NtReadVirtualMemory "j(poi(esp+8)==0x40bdc0)'!process;dd esp';'g'"
附件 85887
发现就是test.exe进程,接收缓冲区地址为0x0012fe48
运行至NtReadVirtualMemory的ret处
kd> ed 0012fe48 0x4d
运行结果
附件 85888
验证成功!
三。编程实现***********
这里说主要内容,附件有代码
这个是挂钩后调用的函数
获取进程名字用的地址是
kd> dt _EProcess获取的
附件 85889
这里是驱动入口
由于ssdt是只读内存,修改只读内存有2种常规方法,这里用的是修改cr0的WP位(问题:这样修改会不会在多CPU下出问题?????有什么好办法),另外一种是用Mdl
Hook的办法也有2种,这里用直接Hook SSDT,另外一种是inline Hook
四。验证***********
附件 85891
第一次发帖
不知道截图附件有没有问题
//target.exe
代码:
int x=5;
int main()
{
while(1)
{
printf("%p %d",&x,x);
Sleep(20000);
}
}
代码:
int main()
{
int pid=0;
PROCESSENTRY32 pe32;
pe32.dwSize = sizeof(pe32);
HANDLE hProcessSnap =
::CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0);
if (hProcessSnap == INVALID_HANDLE_VALUE)
{
printf("CreateToolhelp32Snapshot 调用失败.\n");
return -1;
}
BOOL bMore = ::Process32First(hProcessSnap,&pe32);
while (bMore)
{
if(strcmp(pe32.szExeFile,"target.exe")==0)
{
pid=pe32.th32ProcessID;
break;
}
bMore = ::Process32Next(hProcessSnap,&pe32);
}
::CloseHandle(hProcessSnap);
HANDLE hOpen=OpenProcess(PROCESS_VM_READ, 0, pid);
PVOID pbaseaddr=(PVOID)0x40bdc0;
DWORD data=0;
DWORD readlen=0;
printf("%x",hOpen);
ReadProcessMemory(hOpen,pbaseaddr,&data,4,&readlen);
printf("%d",data);
system("pause");
return 0;
}
附件 85882
本文通过ssdt hook 使test.exe读取内存的值为77
二。验证思路***********
用od打开test.exe看ReadProcessMemory
附件 85883
附件 85884
附件 85885
调用SSDT表中函数的编号为0xBA
windbg中加上断点
kd> bp nt!NtReadVirtualMemory
发现会停很多次
查看堆栈
kd> dd esp
附件 85886
其中esp+8为读内存起始地址
加上条件断点
kd> bc 0
kd> bp nt!NtReadVirtualMemory "j(poi(esp+8)==0x40bdc0)'!process;dd esp';'g'"
附件 85887
发现就是test.exe进程,接收缓冲区地址为0x0012fe48
运行至NtReadVirtualMemory的ret处
kd> ed 0012fe48 0x4d
运行结果
附件 85888
验证成功!
三。编程实现***********
这里说主要内容,附件有代码
这个是挂钩后调用的函数
获取进程名字用的地址是
kd> dt _EProcess获取的
附件 85889
代码:
NTSTATUS MyNtReadVirtualMemory (
IN HANDLE ProcessHandle,
IN PVOID BaseAddress,
OUT PVOID Buffer,
IN ULONG BufferSize,
OUT PULONG NumberOfBytesRead
)
{
NTSTATUS ret=((NTREADVIRTUALMEMORY)g_pReadVirtualMemory)(ProcessHandle,BaseAddress,Buffer,BufferSize,NumberOfBytesRead);
if(ret==STATUS_SUCCESS)
{
PEPROCESS Process;
ret=ObReferenceObjectByHandle(ProcessHandle,EVENT_MODIFY_STATE,*PsProcessType,KernelMode,(PVOID*)&Process,NULL);
if(ret==STATUS_SUCCESS && Process!=NULL)
{
PEPROCESS curProcess=IoGetCurrentProcess();
if (_stricmp((char*)((char*)Process+0x174), "target.exe") == 0 )
{
if(_stricmp((char*)((char*)curProcess+0x174), "test.exe") == 0 )
{
*((CHAR*)Buffer)=77;
}
}
ObDereferenceObject(Process);
}
}
return ret;
}
这里是驱动入口
由于ssdt是只读内存,修改只读内存有2种常规方法,这里用的是修改cr0的WP位(问题:这样修改会不会在多CPU下出问题?????有什么好办法),另外一种是用Mdl
Hook的办法也有2种,这里用直接Hook SSDT,另外一种是inline Hook
代码:
extern "C"
NTSTATUS DriverEntry(void* pModudleBase,int nNothing) {
g_pNtKernelBaseAddr = FindKernelBaseAddr(&g_nNtKernelSizeOfImage);
if (NULL == g_pNtKernelBaseAddr) {
return -1;
}
ULONG nNetIoSizeOfImage = 0;
DWORD nServicesTableRVA=FindAPIRVAByName((PVOID)g_pNtKernelBaseAddr,"KeServiceDescriptorTable");
if (NULL == nServicesTableRVA) {
return FALSE;
}
PSERVICE_DESCRIPTOR_TABLE pServicesTable=(PSERVICE_DESCRIPTOR_TABLE)((PUCHAR)g_pNtKernelBaseAddr + nServicesTableRVA);
PUCHAR pnSSDTVA = (PUCHAR)(pServicesTable->ServiceTableBase);
//
//SSDT Hook
//
PVOID* pReadVirtualMemory=(PVOID*)(pnSSDTVA+(0xba*4));
__asm{
cli
mov eax,cr0
and eax,not 10000h
mov cr0,eax
}
g_pReadVirtualMemory=*pReadVirtualMemory;
*pReadVirtualMemory=(PVOID*)(DWORD)MyNtReadVirtualMemory;
__asm{
mov eax,cr0
or eax,10000h
mov cr0,eax
sti
}
return STATUS_SUCCESS;
}
附件 85891
第一次发帖
不知道截图附件有没有问题