標 題:
【原創】hook api 反OD調試的一種思路
作 者:
藍雲
時 間:
2007-07-23,15:32
鏈 接:
http://bbs.pediy.com/showthread.php?t=48413
hook api 反OD調試的一種思路
by胡華
本程序在backer的耐心指導下完成,非常感謝backer的幫助!!!
關於OD怎樣在程序中下斷點相信大家都知道,就是用WriteProcessMemory函數在要下斷點的地方寫入0xCC,也就是int 3的中斷,
如果我們掛鉤OD的WriteProcessMemory函數不讓它下斷點是不是就可以讓OD不能正常跟蹤了呢?有了這個思路,下面就是實踐了。
首先得解決幾個問題:
1.我們的目標是最好在OD正常加載本程序後就已經被hook,怎麼解決?
這個問題其實很簡單,我們知道全局類的初始化工作在main函數之前,OD正常加載後會停在WinMain函數處,如果把hook api 代
碼放在一個全局類的構造函數中就可以了,呵呵,就這麼簡單。
2.要得到OD的輸入表中的WriteProcessMemory函數的跳轉地址
呵呵,用OD來調試OD不就很容易得到了麼?
用OD調試OD後我們得到WriteProcessMemory函數的跳轉地址放在0x0050D450這個地方。
3.如果前面的兩個問題解決,現在剩下的就是程序在運行期間要判斷自己的父進程是否是OD,如果是OD那麼就可以肯定被OD加載,
問題是怎麼方便的取得父進程?如果用列取進程列表的方式來獲的父進程,這比較麻煩,但是的確是一種思路。我們不採取這種
思路,其實在ntdll.dll中有一個函數可以得到父進程,下面用代碼來說話吧:
NTDLL.DLL中有一個函數叫NtQueryInformationProcess,用它可以將指定類型的進程信息拷貝到某個緩衝。其原型如下:
NTSYSAPI
NTSTATUS
NTAPI
NtQueryInformationProcess (
IN HANDLE ProcessHandle, // 進程句柄
IN PROCESSINFOCLASS InformationClass, // 信息類型
OUT PVOID ProcessInformation, // 緩衝指針
IN ULONG ProcessInformationLength, // 以字節爲單位的緩衝大小
OUT PULONG ReturnLength OPTIONAL // 寫入緩衝的字節數
);
第一個參數是希望操作的進程句柄,這個句柄必須以PROCESS_QUERY_INFORMATION模式存取。爲了取得一個句柄,我們必須用
OpenProcess函數:
HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION,FALSE,dwProcessID);
第二個參數是請求信息的類型,這個參數可以有許多個值,本文例子中將用ProcessBasicInformation (值爲0)。
因此,如果第二個參數是ProcessBasicInformation的話,則第三個參數必須爲一個指針指向結構PROCESS_BASIC_INFORMATION:
typedef struct
{
DWORD ExitStatus; // 接收進程終止狀態
DWORD PebBaseAddress; // 接收進程環境塊地址
DWORD AffinityMask; // 接收進程關聯掩碼
DWORD BasePriority; // 接收進程的優先級類
ULONG UniqueProcessId; // 接收進程ID
ULONG InheritedFromUniqueProcessId; //接收父進程ID
} PROCESS_BASIC_INFORMATION;
這個結構的最後一個參數是InheritedFromUniqueProcessId,它就是我們所要的東西。
得到了父進程id之後,呵呵,現在開始打開進程了
DWORD dwId=GetCurrentProcessId();
DWORD dwParentId;
dwParentId=GetParentProcessID(dwId); //獲取父進程id
hParentProcess=OpenProcess(PROCESS_ALL_ACCESS,FALSE,dwParentId);
又有一個問題怎麼判斷是否是OD呢?
我們可以用讀取內存的方式查看某一段代碼是不是OD的就行了,要檢查哪段代碼那就隨你了,
我這裏是讀取OD的0x00401000開始的幾個字節。
更簡單的方法是讀取0x0050D450這個地址判斷是不是WriteProcessMemory這個函數的真實跳轉地址,如果是那就基本可以斷定是OD了,呵呵,不會那麼巧其它的有的程序也會是這個地址吧!
判斷是OD後,現在要做的就是在OD中申請一段空間把要執行的代碼寫在這個地址了
BYTE bRet=0xC3; //這是hook api後轉到這要執行的代碼
LPVOID lpWriteFunAddress=(void*)0x0050D450;
LPVOID lpNewWriteFunAddress=NULL;
lpNewWriteFunAddress=VirtualAllocEx(hParentProcess,NULL,sizeof(bRet),MEM_COMMIT,PAGE_READWRITE);
//插入函數返回代碼
if(lpNewWriteFunAddress==NULL)
{
MessageBox(NULL,"virtualalloc err","error",MB_OK);
}
if(WriteProcessMemory(hParentProcess, lpNewWriteFunAddress, &bRet, sizeof(bRet), NULL)==0)
{
MessageBox(NULL,"insert retn err","error",MB_OK);
}
寫入後現在就是把0x0050D450這個地址的WriteProcessMemory函數的真實跳轉地址改爲我們上面申請的地址了:
//改變api地址
DWORD flOldProtect;
VirtualProtect(lpWriteFunAddress,sizeof (lpWriteFunAddress),PAGE_READWRITE,&flOldProtect);
if(WriteProcessMemory(hParentProcess, lpWriteFunAddress,
&lpNewWriteFunAddress,
sizeof(lpNewWriteFunAddress), NULL)==0)
{
MessageBox(NULL,"insert fun addr err","error",MB_OK);
}
不知道大家注意沒,我插入的要執行的代碼只有一個字節BYTE bRet=0xC3,
其實就是ret,呵呵,知道了吧,只要在OD中按F2下斷點就會執行WriteProcessMemory這個函數,而這個函數現在是什麼都不做就直接返
回了,也不用考慮堆棧平衡,我們要的就是OD悄無聲息的掛掉!如果想忽悠一下而不讓OD掛掉,那就用ret14了,大家盡情的發揮吧!!!
好了,到這裏已經結束了,再次感謝backer的指導!!!
hook api 反OD調試的一種思路
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.