日常抄好友代码,原文链接:https://www.jianshu.com/p/1c8280bc88a4
最近分析一个样本,发现其是hook一个API函数,逻辑如下:
HMODULE ntdll = LoadLibraryA("ntdll.dll");
byte * ZwBase =(byte *)GetProcAddress(ntdll,"ZwWriteVirtualMemory");
if(VirtualProtect(ZwBase,10,PAGE_EXECUTE_READWRITE,&lpflOldProtect))
VABase = (byte *)VirtualAlloc(0,10,MEM_COMMIT,PAGE_EXECUTE_READWRITE);
memcpy(VABase,ZwBase,5);
VABase[5] = 0xE9;
*(int *)(VABase+6) = ZwBase - VABase -5;//set jmp addr point
这里值得一提的是如何计算偏移。偏移 = 将要跳转到的地址 - jmp指令执行完后,下一条指令的起始地址,用上面的例子计算一下,要跳转到ZwWriteVirtualMemory的第二条指令,这里的地址等于(ZwBase+5)第一条指令长度为5,jmp指令在新创建的空间中,前面拷贝了5个字节的指令,后面的jmp一个字节,紧接着的偏移地址4个字节所以jmp指令后的地址是(VABase +10),结果:偏移 = ZwBase+5 - (VABase +10)=ZwBase - VABase -5
把API开头的第一条指令改成跳转到hook的函数地址
ZwBase[0] = 0xE9;
*(int *)(ZwBase+1) = (byte *)AttackFunc - ZwBase -5;
上面的API被修改了,等等创建进程一定会用到ZwWriteVirtualMemory,就会跳入我们设定好的API函数,我们的API函数第一步先执行了ZwWriteVirtualMemory这个API没有执行完的部分,等这个函数执行完后,eip将会返回回来,执行我们设定好的恶意代码了。
void AttackFunc(IN HANDLE hProcess, IN PVOID BaseAddress, IN PVOID Buffer, IN ULONG BytesToWrite, OUT PULONG BytesWritten)
{
func((DWORD)hProcess,(DWORD)BaseAddress,(DWORD)Buffer,BytesToWrite,(DWORD)BytesWritten);
MessageBox(0,"infected",0,0);
}
我们废了那么大的劲,如果没创建进程就一点用没有了。
CreateProcessA("C:\\Users\\john\\Desktop\\calc.exe",0,0,0,0,0,0,0,&st,&pi);
// ApiHook.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include
byte * VABase;
typedef int (__stdcall *Func)(DWORD,DWORD,DWORD,DWORD,DWORD);
Func func;
void AttackFunc(IN HANDLE hProcess, IN PVOID BaseAddress, IN PVOID Buffer, IN ULONG BytesToWrite, OUT PULONG BytesWritten)
{
func((DWORD)hProcess,(DWORD)BaseAddress,(DWORD)Buffer,BytesToWrite,(DWORD)BytesWritten);
MessageBox(0,"infected",0,0);
}
int modifyApi()
{
HMODULE ntdll = LoadLibraryA("ntdll.dll");
byte * ZwBase =(byte *)GetProcAddress(ntdll,"ZwWriteVirtualMemory");
DWORD lpflOldProtect=0;
if(VirtualProtect(ZwBase,10,PAGE_EXECUTE_READWRITE,&lpflOldProtect))
{
VABase = (byte *)VirtualAlloc(0,10,MEM_COMMIT,PAGE_EXECUTE_READWRITE);
memcpy(VABase,ZwBase,5);
VABase[5] = 0xE9;
*(int *)(VABase+6) = ZwBase - VABase -5;//set jmp addr point
ZwBase[0] = 0xE9;
*(int *)(ZwBase+1) = (byte *)AttackFunc - ZwBase -5;
if(!VirtualProtect(VABase,10,PAGE_EXECUTE_READWRITE,&lpflOldProtect))
{
return -1;
}
func = (int (__stdcall *)(DWORD,DWORD,DWORD,DWORD,DWORD))VABase;
}
return 1;
}
int _tmain(int argc, _TCHAR* argv[])
{
/*
确定要几个数据
ZwWriteVirtualMemory的第一条指令
跳转到第二条指令
把ZwWriteVirtualMemory第一条指令修改为跳转到指定内存空间
*/
STARTUPINFO st ={0};
PROCESS_INFORMATION pi = {0};
if(modifyApi())
{
CreateProcessA("C:\\Windows\\System32\\calc.exe",0,0,0,0,0,0,0,&st,&pi);
int err = GetLastError();
}
return 0;
}