1. 程式人生 > >複寫IAT劫持程式執行流(計算器中顯示中文數字)

複寫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函式的地址

過程分為這幾步

  1. 找到exe檔案的載入地址(GetModuleHandle(NULL)函式)
  2. 找到user32.dll的載入地址,和SetWindowTextW的載入地址
  3. 修改IAT記憶體的屬性用VirtualProtect函式
  4. 修改IAT->Function值(這個值是函式的真正執行時地址)(dll被主調exe載入到自己的虛擬記憶體空間,所以直接賦值)
  5. 把記憶體許可權修改回去

除錯:用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 每日只寫了一部分,後面的日誌不再執行,也不產生任何錯誤,由此浪費了很多的時間進行除錯操作,都沒有找到原因,而當我將該