一个简单的console工程,vc6,vc7在win2k pro,server上调试通过.
#include <stdio.h>
#include <windows.h>
#include <dbghelp.h>
#pragma comment(lib,"dbghelp.lib")
#pragma comment(lib,"user32.lib")
typedef int (__stdcall *old_messagebox)( hwnd hwnd, lpctstr lptext, lpctstr lpcaption,uint utype );
old_messagebox g_procoldmessagebox = null;
int __stdcall hook_messagebox( hwnd hwnd, lpctstr lptext, lpctstr lpcaption,uint utype)
{
printf("%s/t%d/r/n",__function__,__line__);
if (null != g_procoldmessagebox)
return g_procoldmessagebox(hwnd,lptext,"不好意思,hook到了!",utype);
else
return messagebox(hwnd,lptext,lpcaption,utype); ;
}
int replace_iat(const char *pdllname,const char *papiname,bool breplace)
{
handle hprocess = ::getmodulehandle (null);
dword dwsize = 0;
pimage_import_descriptor pimageimport = (pimage_import_descriptor)imagedirectoryentrytodata(hprocess,true,
image_directory_entry_import,&dwsize);
if (null == pimageimport)
return 1;
pimage_import_by_name pimageimportbyname = null;
pimage_thunk_data pimagethunkoriginal = null;
pimage_thunk_data pimagethunkreal = null;
while (pimageimport->name)
{
if (0 == strcmpi((char*)((pbyte)hprocess+pimageimport->name),pdllname))
{
break;
}
++pimageimport;
}
if (! pimageimport->name)
return 2;
pimagethunkoriginal = (pimage_thunk_data)((pbyte)hprocess+pimageimport->originalfirstthunk );
pimagethunkreal = (pimage_thunk_data)((pbyte)hprocess+pimageimport->firstthunk );
while (pimagethunkoriginal->u1.function)
{
if ((pimagethunkoriginal->u1 .ordinal & image_ordinal_flag) != image_ordinal_flag)
{
pimageimportbyname = (pimage_import_by_name)((pbyte)hprocess+pimagethunkoriginal->u1 .addressofdata );
if (0 == strcmpi(papiname,(char*)pimageimportbyname->name))
{
memory_basic_information mbi_thunk;
virtualquery(pimagethunkreal, &mbi_thunk, sizeof(memory_basic_information));
virtualprotect(mbi_thunk.baseaddress,mbi_thunk.regionsize, page_readwrite, &mbi_thunk.protect);
if (true == breplace)
{
g_procoldmessagebox =(old_messagebox) pimagethunkreal->u1.function;
pimagethunkreal->u1.function = (dword)hook_messagebox;
}
else
pimagethunkreal->u1.function = (dword)g_procoldmessagebox;
dword dwoldprotect;
virtualprotect(mbi_thunk.baseaddress, mbi_thunk.regionsize, mbi_thunk.protect, &dwoldprotect);
break;
}
}
++pimagethunkoriginal;
++pimagethunkreal;
}
return 0;
}
int main()
{
replace_iat("user32.dll","messageboxa",true);
messagebox(null,"enumiat user32.dll messageboxa true;","",mb_ok);
replace_iat("user32.dll","messageboxa",false);
messagebox(null,"enumiat user32.dll messageboxa false;","",mb_ok);
return getchar();
}
二,=======================================================
1.本地HOOK API(Inline HOOK):
HOOK MessageBoxW 这个,让它跳到我们自己的函数处理之后再调用原来的MessageBoxW,这种本地的HOOK API应该是最简单的HOOK API而且它的作用也不是很明显,但是可以了解什么是HOOK API.
#include <windows.h>
#include <iostream>
using namespace std;
typedef int (WINAPI *pMessageBoxDef)(HWND hWnd, LPCWSTR lpText, LPCWSTR lpCaption, UINT uType);
char szOldMessageBox[5] = {0};
char szJmpMyMessageBox[5] = {(char)0xe9};
pMessageBoxDef pMessageBox = NULL;
int WINAPI MyMessageBox(HWND hWnd, LPCWSTR lpText, LPCWSTR lpCaption, UINT uType)
{
wcout<<L"hWnd:"<<(int)hWnd<<endl;
wcout<<L"lpText:"<<lpText<<endl;
wcout<<L"lpCaption:"<<lpCaption<<endl;
wcout<<L"uType:"<<uType<<endl<<endl;
WriteProcessMemory((void*)-1, pMessageBox, szOldMessageBox, 5, NULL);
MessageBoxW(hWnd, lpText, lpCaption, uType);
WriteProcessMemory((void*)-1, pMessageBox, szJmpMyMessageBox, 5, NULL);
return 0;
}
int main()
{
DWORD dwJmpAddr = 0;
HMODULE hModule = LoadLibrary("User32.Dll");
pMessageBox = (pMessageBoxDef)GetProcAddress(hModule, "MessageBoxW");
dwJmpAddr = (DWORD)MyMessageBox - (DWORD)pMessageBox - 5;
memcpy(szJmpMyMessageBox + 1, &dwJmpAddr, 4);
FreeLibrary(hModule);
ReadProcessMemory((void*)-1, pMessageBox, szOldMessageBox, 5, NULL);//读出原来的前5个字节
WriteProcessMemory((void*)-1, pMessageBox, szJmpMyMessageBox, 5, NULL);//写入我们处理后的5个字节
MessageBoxW(GetForegroundWindow(), L"Inline Hook:MessageBox", L"HOOK API", MB_OK);
MessageBoxW(GetForegroundWindow(), L"Hello World", L"Win32", MB_OK);
return 0;
}
2.Ring3 下 HOOK API(IAT HOOK)
这种HOOK API开始有用了,它可以HOOK 别的进程的API,许多程序的进程隐藏,进程的保护,文件,端口,注册表的隐藏就是使用它.现在实现进程的隐藏(隐藏程序名开头3个字母为CIW的进程),用DLL注入(可以省去很多麻烦).
Dll源代码:
#include <Windows.h>
#include <stdio.h>
#include <ImageHlp.h>
#include <Tlhelp32.h>
#include <commctrl.h>
DWORD WINAPI ThreadProc(LPVOID lpParameter);
void ReplaceIATEntryInOneMod(PSTR pszCalleeModName,
PROC pfnCurrent, PROC pfnNew, HMODULE hmodCaller);
LONG WINAPI InvalidReadExceptionFilter(PEXCEPTION_POINTERS pep);
#define NTSTATUS DWORD
#define NT_SUCCESS(Status) ((NTSTATUS)(Status)>=0)
BOOL WINAPI DllMain(
HANDLE hinstDLL,
DWORD dwReason,
LPVOID lpvReserved
)
{
if( DLL_PROCESS_ATTACH == dwReason )
{
CreateThread(NULL, NULL, ThreadProc, NULL, NULL, NULL);
}
return TRUE;
}
typedef struct _UNICODE_STRING {
USHORT Length;
USHORT MaximumLength;
PWSTR Buffer;
} UNICODE_STRING;
typedef UNICODE_STRING *PUNICODE_STRING;
typedef const UNICODE_STRING *PCUNICODE_STRING;
typedef struct _VM_COUNTERS
{
ULONG PeakVirtualSize;
ULONG VirtualSize;
ULONG PageFaultCount;
ULONG PeakWorkingSetSize;
ULONG WorkingSetSize;
ULONG QuotaPeakPagedPoolUsage;
ULONG QuotaPagedPoolUsage;
ULONG QuotaPeakNonPagedPoolUsage;
ULONG QuotaNonPagedPoolUsage;
ULONG PagefileUsage;
ULONG PeakPagefileUsage;
}VM_COUNTERS,*PVM_COUNTERS;
typedef struct _IO_COUNTERS
{
LARGE_INTEGER ReadOperationCount;
LARGE_INTEGER WriteOperationCount;
LARGE_INTEGER OtherOperationCount;
LARGE_INTEGER ReadTransferCount;
LARGE_INTEGER WriteTransferCount;
LARGE_INTEGER OtherTransferCount;
}IO_COUNTERS,*PIO_COUNTERS;
typedef struct _CLIENT_ID
{
HANDLE UniqueProcess;
HANDLE UniqueThread;
}CLIENT_ID;
typedef enum _THREAD_STATE
{
StateInitialized,
StateReady,
StateRunning,
StateStandby,
StateTerminated,
StateWait,
StateTransition,
StateUnknown
}THREAD_STATE;
typedef enum _KWAIT_REASON
{
Executive,
FreePage,
PageIn,
PoolAllocation,
DelayExecution,
Suspended,
UserRequest,
WrExecutive,
WrFreePage,
WrPageIn,
WrPoolAllocation,
WrDelayExecution,
WrSuspended,
WrUserRequest,
WrEventPair,
WrQueue,
WrLpcReceive,
WrLpcReply,
WrVertualMemory,
WrPageOut,
WrRendezvous,
Spare2,
Spare3,
Spare4,
Spare5,
Spare6,
WrKernel
}KWAIT_REASON;
typedef struct _SYSTEM_THREADS
{
LARGE_INTEGER KernelTime; //CPU内核模式使用时间;
LARGE_INTEGER UserTime; //CPU用户模式使用时间;
LARGE_INTEGER CreateTime; //线程创建时间;
ULONG WaitTime; //等待时间;
PVOID StartAddress; //线程开始的虚拟地址;
CLIENT_ID ClientId; //线程标识符;
LONG Priority; //线程优先级;
LONG BasePriority; //基本优先级;
ULONG ContextSwitchCount; //环境切换数目;
THREAD_STATE State; //当前状态;
KWAIT_REASON WaitReason; //等待原因;
}SYSTEM_THREADS,*PSYSTEM_THREADS;
struct _SYSTEM_PROCESSES
{
ULONG NextEntryDelta;
ULONG ThreadCount;
ULONG Reserved[6];
LARGE_INTEGER CreateTime;
LARGE_INTEGER UserTime;
LARGE_INTEGER KernelTime;
UNICODE_STRING ProcessName;
LONG BasePriority;
ULONG ProcessId;
ULONG InheritedFromProcessId;
ULONG HandleCount;
ULONG Reserved2[2];
VM_COUNTERS VmCounters;
IO_COUNTERS IoCounters; //windows 2000 only
struct _SYSTEM_THREADS Threads[1];
};
typedef DWORD SYSTEM_INFORMATION_CLASS;
typedef int (WINAPI *pNtQuerySystemInformationFun)(
SYSTEM_INFORMATION_CLASS SystemInformationClass,
PVOID SystemInformation,
ULONG SystemInformationLength,
PULONG ReturnLength
);
pNtQuerySystemInformationFun pNtQuerySystemInformation = 0;
int WINAPI MyNtQuerySystemInformation(
SYSTEM_INFORMATION_CLASS SystemInformationClass,
PVOID SystemInformation,
ULONG SystemInformationLength,
OUT PULONG ReturnLength
)
{
DWORD nState = pNtQuerySystemInformation(SystemInformationClass, SystemInformation, SystemInformationLength, ReturnLength);
_SYSTEM_PROCESSES* pProc = (_SYSTEM_PROCESSES*)SystemInformation;
if( NT_SUCCESS(nState))
{
if(SystemInformationClass == 5)
{
struct _SYSTEM_PROCESSES *curr = (struct _SYSTEM_PROCESSES *)SystemInformation;
struct _SYSTEM_PROCESSES *prev = NULL;
while(curr)
{
if (curr->ProcessName.Length > 0)
{
if(0 == memcmp(curr->ProcessName.Buffer, L"CIW", 2 * 3))
{
if(prev)
{
if(curr->NextEntryDelta)
prev->NextEntryDelta += curr->NextEntryDelta;
else
prev->NextEntryDelta = 0;
}
else
{
if(curr->NextEntryDelta)
{
SystemInformation =(_SYSTEM_PROCESSES*)((char *)SystemInformation + curr->NextEntryDelta);
}
else
SystemInformation = NULL;
}
}
}
prev = curr;
if(curr->NextEntryDelta) (curr = (_SYSTEM_PROCESSES*)((char *)curr + curr->NextEntryDelta));
else curr = NULL;
}
}
return 0;
}
}
DWORD WINAPI ThreadProc(LPVOID lpParameter)
{
char szDllName[] = "NTDLL.dll";
pNtQuerySystemInformation = (pNtQuerySystemInformationFun)GetProcAddress(LoadLibrary("NTDLL.DLL"), "NtQuerySystemInformation");
if(!pNtQuerySystemInformation)
ExitProcess(0);
bool bMore = true;
MODULEENTRY32 stMod;
stMod.dwSize = sizeof(MODULEENTRY32);
HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, GetCurrentProcessId());
bMore = Module32First(hSnap, &stMod);
do
{
ReplaceIATEntryInOneMod(szDllName, (PROC)pNtQuerySystemInformation, (PROC)MyNtQuerySystemInformation, stMod.hModule);
bMore = Module32Next(hSnap, &stMod);
}while(bMore);
CloseHandle(hSnap);
return 0;
}
LONGWINAPIInvalidReadExceptionFilter(PEXCEPTION_POINTERSpep){
LONGlDisposition=EXCEPTION_EXECUTE_HANDLER;
return(lDisposition);
}
voidWideToString(LPCWSTRwcChar,char*lpDesStr)
{
WideCharToMultiByte(0,0,wcChar,wcslen(wcChar),lpDesStr,wcslen(wcChar),NULL,NULL);
}
voidStringToWide(constchar*lpStr,WCHAR*wcChar)
{
MultiByteToWideChar(CP_ACP,MB_PRECOMPOSED,lpStr,-1,wcChar,strlen(lpStr));
}
char*Change(char*szText)
{
char*szOrg=szText;
for(;szText;szText++)
{
if(*szText>='A'&&*szText<='Z')
{
*szText=*szText-'A'+'a';
}
}
returnszOrg;
}
EXE 代码:
#include <Windows.h>
#include <tlhelp32.h>
#include <vector>
char szDLLFileName[MAX_PATH] = "E:\\MyProject\\VC\\VC 6.0\\DLL 编程\\REMOTE_HOOK\\Debug\\REMOTE_HOOK.dll"; //要注入的DLL路径
void InfectEXE(int nID)
{
HANDLE hHookProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, nID);
if( hHookProcess == NULL )
{
return ;
}
PVOID pRemoteAddr = VirtualAllocEx(hHookProcess, NULL, strlen(szDLLFileName) + 1, MEM_COMMIT, PAGE_READWRITE);
LPTHREAD_START_ROUTINE dwLoadLibAddr = (LPTHREAD_START_ROUTINE)GetProcAddress(LoadLibrary("Kernel32.Dll"), "LoadLibraryA");
if( dwLoadLibAddr == NULL )
{
return ;
}
DWORD dwSize = 0;
if( WriteProcessMemory(hHookProcess, pRemoteAddr, szDLLFileName, strlen(szDLLFileName), &dwSize) == 0 )
{
return ;
}
DWORD dwThreadID;
HANDLE hThread = CreateRemoteThread(hHookProcess, NULL, NULL, dwLoadLibAddr, pRemoteAddr, NULL, &dwThreadID);
CloseHandle(hThread);
}
char* Change(char* szText)
{
char *szOrg = szText;
for(; *szText; szText++)
{
if( *szText >= 'A' && *szText <= 'Z' )
{
*szText = *szText - 'A' + 'a';
}
}
return szOrg;
}
DWORD GetProcessIdFromName(LPTSTR name) //通过执行文件名获得进程ID的方法
{
char szExeName[MAX_PATH];
PROCESSENTRY32 pe;
DWORD id = 0;
HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0);
pe.dwSize = sizeof(PROCESSENTRY32);
if( !Process32First(hSnapshot,&pe) )
return 0;
do
{
strcpy(szExeName, pe.szExeFile);
if(strcmp(Change(szExeName), name) == 0)
{
id = pe.th32ProcessID;
break;
}
pe.dwSize = sizeof(PROCESSENTRY32);
if( Process32Next(hSnapshot,&pe)==FALSE )
break;
} while(1);
CloseHandle(hSnapshot);
return id;
}
int main()
{
char szHookProcName[521] = "taskmgr.exe";
WinExec(szHookProcName, SW_SHOW);
Sleep(500);
InfectEXE(GetProcessIdFromName(szHookProcName));
return 0;
}
3.Ring0 下 HOOK API(SSDT HOOK),用处多大就不说了,下面是一个进程保护的HOOK.
#include "ntddk.h"
PMDL g_pmdlSystemCall;
PVOID *MappedSystemCallTable;
NTSYSAPI
NTSTATUS
NTAPI ZwOpenProcess (
OUT PHANDLE ProcessHandle,
IN ACCESS_MASK DesiredAccess,
IN POBJECT_ATTRIBUTES ObjectAttributes,
IN PCLIENT_ID ClientId
);
typedef NTSTATUS (*ZwFunDef) (
OUT PHANDLE ProcessHandle,
IN ACCESS_MASK DesiredAccess,
IN POBJECT_ATTRIBUTES ObjectAttributes,
IN PCLIENT_ID ClientId
);
ZwFunDef pOldFun= NULL;
VOID OnUnload(IN PDRIVER_OBJECT DriverObject)
{
DbgPrint("ROOTKIT: OnUnload called\n");
UNHOOK_SYSCALL( ZwOpenProcess, pOldFun, NewFun );
// Unlock and Free MDL
if(g_pmdlSystemCall)
{
MmUnmapLockedPages(MappedSystemCallTable, g_pmdlSystemCall);
IoFreeMdl(g_pmdlSystemCall);
}
}
NTSTATUS NewFun(
OUT PHANDLE ProcessHandle,
IN ACCESS_MASK DesiredAccess,
IN POBJECT_ATTRIBUTES ObjectAttributes,
IN PCLIENT_ID ClientId
)
{
if( ClientId->UniqueProcess == (HANDLE)1472)
return STATUS_SUCCESS;
return pOldFun(ProcessHandle, DesiredAccess, ObjectAttributes, ClientId);
}
NTSTATUS SetSSDTWrite()
{
g_pmdlSystemCall = MmCreateMdl(NULL, KeServiceDescriptorTable.ServiceTableBase, KeServiceDescriptorTable.NumberOfServices*4);
if(!g_pmdlSystemCall)
return STATUS_UNSUCCESSFUL;
MmBuildMdlForNonPagedPool(g_pmdlSystemCall);
// Change the flags of the MDL
g_pmdlSystemCall->MdlFlags = g_pmdlSystemCall->MdlFlags | MDL_MAPPED_TO_SYSTEM_VA;
MappedSystemCallTable = MmMapLockedPages(g_pmdlSystemCall, KernelMode);
return STATUS_SUCCESS;
}
NTSTATUS DriverEntry(IN PDRIVER_OBJECT theDriverObject,
IN PUNICODE_STRING theRegistryPath)
{
theDriverObject->DriverUnload = OnUnload;
SetSSDTWrite();
pOldFun =(ZwFunDef)(SYSTEMSERVICE(ZwOpenProcess));
HOOK_SYSCALL( ZwOpenProcess,NewFun , pOldFun );
return STATUS_SUCCESS;
}
#include <windows.h>
#include <iostream>
using namespace std;
char cOldIst = 85;
LONG WINAPI MyUnhandledExceptionFilter(EXCEPTION_POINTERS* ExceptionInfo)
{
CONTEXT stCT = *(ExceptionInfo->ContextRecord);
cout<<"SEH Hook"<<endl;
DWORD dwSize = 0;
WriteProcessMemory((HANDLE)-1, (LPVOID)stCT.Eip, &cOldIst, 1, &dwSize);
SetThreadContext(GetCurrentThread(), &stCT);
return EXCEPTION_EXECUTE_HANDLER;
}
int MyFunc()
{
cout<<"My Func"<<endl;
return 0;
}
int main()
{
DWORD dwHookAddress = (DWORD)&MyFunc;
SetUnhandledExceptionFilter(MyUnhandledExceptionFilter);
DWORD dwSize = 0, dwOldProtect = 0;
char cInt3 = 204;
ReadProcessMemory((HANDLE)-1, (LPVOID)dwHookAddress, &cOldIst, 1, &dwSize);
WriteProcessMemory((HANDLE)-1, (LPVOID)dwHookAddress, &cInt3, 1, &dwSize);
MyFunc();
return 0;
}