複寫IAT劫持程式執行流(計算器中顯示中文數字)
結果:在計算器視窗中把本來應該顯示的數字替換為中文
須知:計算器顯示資料的時候需要呼叫user32.dll裡面的SetWindowText() API
過程:在程式執行的時候會載入user32.dll到記憶體,這個時候會把IAT裡面寫入成函式的真正地址(具體見文章中圖),這裡自己寫一個dll當dll被載入會修改user32.dll!SetWindowTextW對應的IAT值達到劫持程式執行流的目的。
注意:32位程式要編譯成32位dll,64位同樣
#include"windows.h" LPVOID g_porgFunc = NULL; BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) { switch (fdwReason) { case DLL_PROCESS_ATTACH: g_porgFunc = GetProcAddress(GetModuleHandle(L"user32.dll"), "SetWindowTextW"); //用hookiad.MySetWindowsText()鉤取user32.SetWindowTextW() hook_iat("user32.dll", g_porgFunc, (PROC)MySetWindowTextW); break; case DLL_PROCESS_DETACH: //將calc.exe的IAT恢復原位 hook_iat("user32.dll", (PROC)MySetWindowTextW, g_porgFunc); break; } return True; }
首先獲取要掛鉤函式的地址,
然後把地址替換實現鉤取和脫鉤
然後需要一個轉化函式,函式完成的過程:
1.把傳入的引數進行轉化
2.呼叫原本的引數
typedef BOOL(WINAPI *PFSETWINDOWTEXTW)(HWND hWnd, LPWSTR lpString); //cal.exe的IAT被鉤取之後當代碼中呼叫user32.SetWindowText函式時會首先呼叫hookiat.MyWindowTextW函式 BOOL WINAPI MySetWindowTextW(HWND hWnd,LPWSTR lpString) { wchar_t* pNum = L"零一二三四五六七八九"; wchar_t temp[2] = { 0 }; int i = 0, nLen = 0, nIndex = 0; nLen = wcslen(lpString); for (i = 0; i < nLen; i++) { //將數字轉中文 //lpString 是寬字元版本的字串 if (L'0' <= lpString[i] && lpString[i] <= L'9') { temp[0] = lpString[i]; nIndex = _wtoi(temp);//讀入的字元是寬字元 lpString[i] = pNum[nIndex]; } }//轉化 //呼叫user32.SetWindowTextW()API //修改lpString緩衝區的內容 return ((PFSETWINDOWTEXTW)g_porgFunc)(hWnd, lpString); }
當程式正常執行SetWindowsTextW()API的時候函式會被hook_iat函式劫持為呼叫MySetWindowTextW函式,SetWindowsTextW的2個引數會被傳遞過來作為MySetWindowTextW的引數,這是對第二個引數(要顯示的字元)進行修改完成後再次呼叫SetWindowTextW函式(不過這個時候的第二個引數已經被修改了)
那麼hook_iat是怎麼實現的呢?在看之前先補充一些關於IAT的知識
IAT的結構如圖
BOOL hook_iat(LPCSTR szDllName,PROC pfnorg, PROC pfnNew) { HMODULE hMod; LPCSTR szLibName; PIMAGE_IMPORT_DESCRIPTOR pImportDesc; PIMAGE_THUNK_DATA pThunk; DWORD dwOldProtect, dwRVA; PBYTE pAddr; //hMod,pAddr=ImageBase of cal.exe , VA to IMAGE_DOS_HEADER hMod = GetModuleHandle(NULL);//獲取最近執行exe的控制代碼 pAddr = (PBYTE)hMod; //pAddr=VA to IMAGE_NT_HEADERS pAddr += *((DWORD*)&pAddr[0x3c]); //dwRVA=RVA to IMAGE_IMPORT_DESCRIPTOR Table dwRVA = *((DWORD*)&pAddr[0x80]); //pImportDesc=Va to Image_Import_DESCRIPTOR Table pImportDesc = (PIMAGE_IMPORT_DESCRIPTOR)((DWORD)hMod + dwRVA); for (; pImportDesc->Name; pImportDesc++) { //szLibName=VA to IMAGE_IMPORT_DESCRIPTOR.Name szLibName = (LPCSTR)(DWORD)hMod + pImportDesc->Name; if (!_stricmp(szLibName, szDllName))//找到對應dll { //pThunk=IMAGE_IMPORT_DESCRIPTOR.FirstThunk // =VA to IAT(Import Address Table) pThunk = (PIMAGE_THUNK_DATA)((DWORD)hMod + pImportDesc->FirstThunk); //pThunk->u1.Function=VA to API for (; pThunk->u1.Function; pThunk++) { if (pThunk->u1.Function == (DWORD)pfnorg) { //更改記憶體屬性 VirtualProtect((LPVOID)&pThunk->u1.Function, 4, PAGE_EXECUTE_READWRITE, &dwOldProtect); //修改IAT的值 pThunk->u1.Function = (DWORD)pfnNew; //恢復記憶體屬性 VirtualProtect((LPVOID)&pThunk->u1.Function, 4, dwOldProtect, &dwOldProtect); return TRUE; } } } } return FALSE; } //替換IAT中szDllName動態連結庫的pfnorg函式地址為pfnNew函式的地址
過程分為這幾步
- 找到exe檔案的載入地址(GetModuleHandle(NULL)函式)
- 找到user32.dll的載入地址,和SetWindowTextW的載入地址
- 修改IAT記憶體的屬性用VirtualProtect函式
- 修改IAT->Function值(這個值是函式的真正執行時地址)(dll被主調exe載入到自己的虛擬記憶體空間,所以直接賦值)
- 把記憶體許可權修改回去
除錯:用OD的附加選項
右擊,查詢,所有模組中的名稱
敲入字元即可搜尋到相應的API或者dll
64位程式可以用windbg
總結:包含3個函式,主函式負責被載入的時候呼叫,hook_iat函式負責修改IAT,MySetWindowTextW函式對原函式的具體修改
和除錯方式的比較:除錯方式對原本的exe影響較大,容易被檢測,修改IAT的方式僅僅是增加一個庫或者直接程式碼注入,簡潔。
相關推薦
複寫IAT劫持程式執行流(計算器中顯示中文數字)
結果:在計算器視窗中把本來應該顯示的數字替換為中文 須知:計算器顯示資料的時候需要呼叫user32.dll裡面的SetWindowText() API 過程:在程式執行的時候會載入user32.dll到記憶體,這個時候會把IAT裡面寫入成函式的真正地址(具體見文
Qt 應用程式在ARM9板中顯示中文2-Qt 字型大小的計算
參考:[轉載]::[QT]Qt 字型大小的計算 http://blog.chinaunix.net/uid-23242876-id-3085826.html Qt 字型大小的計算 http://losemyheaven.blo
C語言:編寫一個程式統計輸入字串中,各個數字、空白字元、以及其他所有字元出現的次數。
#include<stdio.h> int main() { int c = 0; int num_count = 0; int emp_count = 0; int els_count = 0; w
用C#編寫的Windows應用程式如何控制TextBox中只能輸入數字?
textbox有個KeyPress事件 把textbox改為對應的就可以用了: private void textBox_KeyPress(object sender, KeyPressEventArgs e)
FLEX+JAVA,FLEX中顯示中文出現亂碼問題解決辦法
這篇文章依然是FLEX+JAVA 因為最近一直在練習這方面的內容 解決這個亂碼的問題,其實非常簡單 由於 在FLEX中採用的是UTF-8字符集 所以 只要JAVA方面返回的字元其編碼方式也採用UTF-8即可 具體做法為在我們寫的servlet中 呼叫respo
matplotlib-在圖表中顯示中文
我使用的方法: # coding=utf-8 from matplotlib.font_manager import FontProperties font = FontProperties(fname='/ly/simsun.ttc', size=14) 其中simsun.ttc需
【cmd】批處理:bat檔案執行,cmd會顯示中文亂碼,Jenkins日誌顯示中文亂碼——解決方案
目錄 一、批處理命令執行亂碼情況 二、解決方法 一、批處理命令執行亂碼情況 (1)Jenkins批處理命令亂碼: (2)cmd視窗顯示亂碼: 二、解決方法 (1)【最關鍵的步驟!】bat檔案編碼格式修改為ANSI格式: (
matplotlib學習筆記1-圖中顯示中文
相信很多初學者和我一樣,在利用matplotlib庫畫圖的時候遇到過圖例不能顯示中文的問題。經過仔細探索(百度+谷歌),現分享一種簡單便捷一勞永逸的方法。 一般畫圖是不能顯示中文圖例的: imp
【python視覺化一Matplotlib 繪製】視覺化圖片中顯示中文
# ----------------------顯示中文----神奇般的存在---------------- from pylab import * mpl.rcParams['font.sans-serif'] = ['SimHei'] # ----------------------
學習筆記:WinEdt 7.0(Latex)在pdf中顯示中文
在.tex檔案中的\documentclass[12pt]{article}這行程式碼下 呼叫\usepackage{ctex} 這個包,這個包是內建的,不需要下載其他字型包。 \documentclass[12pt]{article} \usepackage{ctex}
將字串中的中文數字轉換成阿拉伯數字
1、正則表示式的處理工具類 public class RexUtils { public static String and(String... rules) { St
解決pl/sql developer中資料庫表中顯示中文亂碼問題
2012-02-14 15:44 8人閱讀 評論(0) 收藏 舉報 首先,通過 select userenv('language') from dual; 查詢oracle伺服器端的編碼, 如為: AMERICAN_AMERICA.US7ASCII 顯示
怎樣在pygame中顯示中文
在pygame中,顯示文字是挺麻煩的事情,為了顯示文字,需要用到5、6個語句。比如為了顯示一句話: ZiTiDuiXiang=pygame.font.Font('freesansbold.ttf',32) WenBenKuangDuiXiang=ZiTiDuiX
man中顯示中文
在學習linux命令的過程中,man是很有用的一個工具,但是對於很多英文水平有限的人來說學習起來有些困難,再此提供安裝中文版man的詳細步驟。當然英文水平不好是需要進行自我檢討的,希望在學習的時候利用中英文對照著來看。達到linux和英文一起進步的效果。本文以最常用的cent
django admin中顯示中文
課程 admin djang model elf length mod ret def class Course(models.Model): title = models.CharField(max_length=32,verbose_name=‘課程名稱‘) #
關於Spark執行流式計算程式中跑一段時間出現GC overhead limit exceeded
最近在升級一個框架的時候,發現某個流式計算程式每隔一定的時間就會出現GC overhead limit exceeded的錯誤問題。 這個問題肯定是記憶體不夠,但是初始設定的記憶體是夠的啊,於是進行各種記憶體優化,如將變數定義在迴圈體外等控制,但是發現只是將這個間隔時間往
Wpf ViewModel中 ObservableCollection不支援從排程程式執行緒以外的執行緒對其 SourceCollection 進行的更改
Wpf中ViewModel類裡面經常會需要用到ObservableCollection來管理列表資料,在做非同步通訊的時候也會碰到“不支援從排程程式執行緒以外的執行緒對其 SourceCollection 進行的更改”這樣的異常,解決方法如下 1 ThreadPool.
C# 程式執行中的流程控制
1、C#之流程控制語句:計算機程式執行的控制流程由三種基本的控制結構控制,即順序結構,選擇結構,迴圈結構。 1) 順序結構:從上到下,按照書寫順序執行每一條語句,不會發生跳躍。 程式碼段1; // 先執行程式碼段1 程式碼段2; // 接著執行程式碼段2 ... 2)選擇結構:對
一次性區分執行緒與程序在程式執行中的關係
一直不能區分執行緒是CPU排程和分配的基本單位,程序是作業系統進行資源分配的最小單位的關係,下面這段話是從一片博文中摘抄的,讓我幾周以來的模糊認識一下子清晰起來,希望對大家理解有幫助,原博文地址在前一篇文章中已貼出,好文章讀起來真是受益匪淺,原文如下: 執行緒是CPU排程和分配的基本單位,一定
程式執行過程中卡住,不再執行,也不產生錯誤資訊
有個web專案存放在azure 雲上,由於無法向IIS 一樣可以靈活操作,因此寫了一大堆的log進行程式記錄,剛開始正常執行並寫出日誌檔案。後來發現數據庫不再更新,並且log 每日只寫了一部分,後面的日誌不再執行,也不產生任何錯誤,由此浪費了很多的時間進行除錯操作,都沒有找到原因,而當我將該