1. 程式人生 > >[DLL劫持] 3 DLL劫持之實踐 例子

[DLL劫持] 3 DLL劫持之實踐 例子

該系列文章是依據本人平時對動態連結庫的學習,歸納總結,所做的學習筆記。如有錯誤或待改善之處,請留下您寶貴的意見或建議。

先說說DLL劫持的原理吧,以下這段來自百度百科對DLL劫持原理的說明:

由於輸入表中只包含DLL名而沒有它的路徑名,因此載入程式必須在磁碟上搜索DLL檔案。首先會嘗試從當前程式所在的目錄載入DLL,如果沒找到,則在Windows系統目錄中查詢,最後是在環境變數中列出的各個目錄下查詢。利用這個特點,先偽造一個系統同名的DLL,提供同樣的輸出表,每個輸出函式轉向真正的系統DLL。程式呼叫系統DLL時會先呼叫當前目錄下偽造的DLL,完成相關功能後,再跳到系統DLL同名函式裡執行。這個過程用個形象的詞來描述就是系統

DLL被劫持(hijack)了。

利用這種方法取得控制權後,可以對主程式進行補丁。此種方法只對除kernel32.dllntdll.dll等核心系統庫以外的DLL有效,如網路應用程式的ws2_32.dll、遊戲程式中的d3d8.dll,還有大部分應用程式都呼叫的lpk.dllsxs.dll,這些DLL都可被劫持。

偽造的dll製作好後,放到程式當前目錄下,這樣當原程式呼叫原函式時就呼叫了偽造的dll的同名函式,進入劫持DLL的程式碼,處理完畢後,再呼叫原DLL此函式。

這種補丁技術,對加殼保護的軟體很有效,選擇掛接的函式最好是在殼中沒有被呼叫的,當掛接函式被執行時,相關的程式碼已被解壓,可以直接補丁了。在有些情況下,必須用計數器統計掛接的函式的呼叫次數來接近

OEP。此方法巧妙地繞過了殼的複雜檢測,很適合加殼程式的補丁製作。

一些木馬或病毒也會利用DLL劫持技術搞破壞,因此當在應用程式目錄下發現系統一些DLL檔案存在時,如lpk.dll,應引起注意。

下面就通過一個簡單的例子,來實現一下DLL劫持:

1.    生成原始的DLL

建立一個dllTest工程,新增lib.hlib.cpp檔案:

Lib.h

#ifndef LIB_H
#define LIB_H

extern "C" int __declspec(dllexport)add(int x, int y);
#endif

Lib.cpp

#include "lib.h"

int add(int x, int y){
	return x + y;
}

編譯生成dllTest.dll

2.    編寫應用程式(採用動態載入方式)

新建工程dllcall,新增檔案dllcall.cpp,修改呼叫目錄,生成,測試,ok

(隱式方式:使用原來的.lib檔案,使用之後的dll

Dllcall.cpp

// dllCall.cpp : 以顯式方式呼叫DLL
#include <stdio.h>
#include "windows.h"
typedef int ( * lpAddFun)(int,int);
	
int main(int argc, char* argv[])
{
    HINSTANCE hDll;   //DLL控制代碼	
	lpAddFun addFun;  //函式指標
    hDll = LoadLibrary("..\\Release\\dllTest.dll");
	if (hDll != NULL)
	{
		addFun = (lpAddFun)GetProcAddress(hDll,"add");	
		if(addFun!=NULL)
		{
		    int result =  addFun(2,3);    
			printf("%d",result);
		}
		FreeLibrary(hDll);
	}	
	system("pause");
	return 0;
}

3.      使用AheadLib反編譯DLL

使用工具AheadLib.exe,反編譯dllTest.dll,生成dllTest.cpp,新建dll工程,編譯該cpp,生成第二個dllTest.dll

DllText.cpp

// 標頭檔案
#include <Windows.h>
// 匯出函式
#pragma comment(linker, "/EXPORT:add=_AheadLib_add,@1")
	
// 巨集定義
#define EXTERNC extern "C"
#define NAKED __declspec(naked)
#define EXPORT __declspec(dllexport)
#define ALCPP EXPORT NAKED
#define ALSTD EXTERNC EXPORT NAKED void __stdcall
#define ALCFAST EXTERNC EXPORT NAKED void __fastcall
#define ALCDECL EXTERNC NAKED void __cdecl
// Hook 名稱空間
namespace Hook
{
	HHOOK m_hHook;
	// HOOK 控制代碼
	// HOOK 函式
	LRESULT CALLBACK HookProc(INT iCode, WPARAM wParam, LPARAM lParam)
	{
		if (iCode > 0)
		{
			;
		}

		return CallNextHookEx(m_hHook, iCode, wParam, lParam);
	}
	// Hook
	inline BOOL WINAPI Hook(INT iHookId = WH_CALLWNDPROC)
	{
		m_hHook = SetWindowsHookEx(iHookId, HookProc, NULL, GetCurrentThreadId());
		return (m_hHook != NULL);
	}
	// Unhook
	inline VOID WINAPI Unhook()
	{
		if (m_hHook)
		{
			UnhookWindowsHookEx(m_hHook);
		}
	}
}
// AheadLib 名稱空間
namespace AheadLib
{
	HMODULE m_hModule = NULL;	// 原始模組控制代碼
	DWORD m_dwReturn[1] = {0};	// 原始函式返回地址
	// 載入原始模組
	inline BOOL WINAPI Load()
	{
		TCHAR tzPath[MAX_PATH];
		TCHAR tzTemp[MAX_PATH * 2];

		lstrcpy(tzPath, TEXT("dllTestOrg"));
		
		///這一句是為了證明我的ws2_32.dll能被執行
		MessageBox(NULL, tzPath, TEXT("DLL Path"), MB_ICONSTOP);
		
		m_hModule = LoadLibrary(tzPath);
		if (m_hModule == NULL)
		{
			wsprintf(tzTemp, TEXT("無法載入 %s,程式無法正常執行。"), tzPath);
			MessageBox(NULL, tzTemp, TEXT("AheadLib"), MB_ICONSTOP);
		}

		return (m_hModule != NULL);	
	}	
	// 釋放原始模組
	inline VOID WINAPI Free()
	{
		if (m_hModule)
		{
			FreeLibrary(m_hModule);
		}
	}
	// 獲取原始函式地址
	FARPROC WINAPI GetAddress(PCSTR pszProcName)
	{
		FARPROC fpAddress;
		CHAR szProcName[16];
		TCHAR tzTemp[MAX_PATH];

		if (m_hModule == NULL)
		{
			if (Load() == FALSE)
			{
				ExitProcess(-1);
			}
		}
		fpAddress = GetProcAddress(m_hModule, pszProcName);
		if (fpAddress == NULL)
		{
			if (HIWORD(pszProcName) == 0)
			{
				wsprintf(szProcName, "%d", pszProcName);
				pszProcName = szProcName;
			}

			wsprintf(tzTemp, TEXT("無法找到函式 %hs,程式無法正常執行。"), pszProcName);
			MessageBox(NULL, tzTemp, TEXT("AheadLib"), MB_ICONSTOP);
			ExitProcess(-2);
		}

		return fpAddress;
	}
}
using namespace AheadLib;
// 入口函式
BOOL WINAPI DllMain(HMODULE hModule, DWORD dwReason, PVOID pvReserved)
{
	if (dwReason == DLL_PROCESS_ATTACH)
	{
		DisableThreadLibraryCalls(hModule);

		Hook::Hook();
	}
	else if (dwReason == DLL_PROCESS_DETACH)
	{
		Free();		Hook::Unhook();
	}
	return TRUE;
}
// 匯出函式
ALCDECL AheadLib_add(void)
{
	GetAddress("add");
	__asm JMP EAX;
}

重新使用之前的應用程式測試

將第二個自己生成的dll替代原來的dll,將原來的dll名改成dllTestOrg.dll,放入相應的目錄,測試,OK

5.    Dll劫持成功

 附件:



相關推薦

[DLL劫持] 3 DLL劫持實踐 例子

該系列文章是依據本人平時對動態連結庫的學習,歸納總結,所做的學習筆記。如有錯誤或待改善之處,請留下您寶貴的意見或建議。 先說說DLL劫持的原理吧,以下這段來自百度百科對DLL劫持原理的說明: 由於輸入表中只包含DLL名而沒有它的路徑名,因此載入程式必須在磁碟上搜索DLL

[DLL劫持] 1 DLL劫持DLL基礎(1)

該系列文章是依據本人平時對動態連結庫的學習,歸納總結,所做的學習筆記。如有錯誤或待改善之處,請留下您寶貴的意見或建議。 最近在研究逆向工程的相關知識,主要用到的是C++逆向,工具有IDA和OLLYDBG等,學了有一段時間了,一直苦於總結能力不夠,不知道逆向的東西該怎麼總結

劫持 Opengl32.dll 實現遊戲MOD

oca 方式 api img blank scrip 我只 assembly 方法 前提是你的遊戲是用的Opengl,如果是DX的,自行谷歌方法,應該差不多,參考GTA5 最近玩了款《天命奇禦》的國產網遊,自己手動寫了個MOD,本來是直接修改Chap-Assembl

實現DLL記憶體補丁,DLL劫持技術

 在windows下當一個可執行檔案執行時,Windows載入器將可執行模組對映到程序的地址空間中,載入器分析可執行模組的輸入表,並設法找出任何需要的DLL,並將它們對映到程序的地址空間中。由於輸入表是根據DLL名來進行查詢,首先是查詢當前目錄下有沒這檔案,沒有話在去查

大資料ETL實踐探索(3)---- pyspark 大資料ETL利器

5.spark dataframe 資料匯入Elasticsearch 5.1 dataframe 及環境初始化 初始化, spark 第三方網站下載包:elasticsearch-spark-20_2.11-6.1.1.jar http://spark.apache.org/t

Allegro學習提示由於找不到cdsCommon.dll,libem.dll以及突然打不開PCB Editor等軟體

1.確認這兩個檔案都在,那就是沒有在環境變數裡新增路徑的問題,在安裝目錄SPB_16.6下搜尋cdsCommon.dll,libem.dll,如下圖所示:接著右鍵開啟檔案位置,複製路徑WIN10中右鍵我的電腦(此電腦),選擇屬性,開啟如下圖,選擇左側高階系統設定開啟環境變數:

OpenLayers 3實踐與原理探究3-ol3一個完整的例子

【注】所有程式碼掛在我的github上,本例對應demo2 接著我們看一個比較長的例子,例子實現的是可以繪製圖形,可以根據自己的設定列印地圖 我們先看顯示效果是: 由於ol3的api現在更新變化挺大的,所以自己執行的例子的時候注意版本是3.17.1

DNS 劫持及解決方案 HTTPDNS

1. 為什麼會有 DNS DNS 即域名系統(Domain Name Server),其主要用於將域名解析為對應的 IP 地址。 那麼為什麼會有域名到 IP 地址的解析這一需要呢?就需要從人的角度和計算機的角度去分析了。 人的角度:網路上的主機一般是通過

Spring Security應用開發(11) 並發控制實踐

nag line then 9.png page 總結 -c ole for 本文分別介紹了四種不同情況下,Spring Security的Session管理和並發控制的不同配置的配置方法,以及所產生的效果。 (1)首先編寫了session_error.jsp頁面,用於

Directx9.0 學習教程3 -圖形學創建點 線 三角形 等

d3d custom 發現 介紹 data- directx 組成 water 詳細 1、首先 介紹點的表示方法 struct CUSTOMVERTEX { float x,y,z; }; CUSTOMVERTEX Vertices[] = { {-5.0

zabbix-3.2.6監控一臺新主機

更改 nat eight 啟動 repo sel cpu ota wid 1、更改主機名 [[email protected]/* */ ~]#hostname zabbix-client [[email protected]/* */-

zabbix-3.2.6自定制監控項參數 監控http 80端口是否正常

wid 正常 3.2 添加 1-1 items lan ati agen 1、自定義映射值 配置--->主機--->監控項 創建監控項----展示映像值 再輸入參數 點更新---拉到最下面,就可以看到新添加的參數。 2、item(監

zabbix-3.2.6snmp監控(無需安裝agent也能監控)

6.0 send 是否 available 安全 scroll sna object 2.2.0 一、snmp監控介紹 概述 如果我們需要監控打印機、路由器、UPS等設備,肯定不能使用zabbix agentd,因為他們不能安裝軟件的,還好他們一般都支持SNMP協議,這

zabbix-3.2.6單位符號Unit symbols

href 訪問 itl title target lan 解決 pla http 概述 在zabbix裏面,我們不需要使用大數字來,例如我們可以不使用86400來表示一天,這個數字又不容易理解也容易出錯。用什麽辦法來解決大數字問題呢?我們可以使用單位來簡化,例如簡化zab

zabbix-3.2.6snmp方式監控windows

pfx name local ima div pan mask bit 成功 一、在windows中添加snmp 在服務中添加public和接受服務器的IP地址。 二、在zabbix-server服務器中安裝net-snmp軟件 1、修改配置文件

Python自動化3.0-------學習路-------第一個程序用戶登錄!

hide lap 標記 之路 判斷 () exit isp 互信 一、用戶登錄程序 知識點:1.input() 2.while 循環 3.fot 循環

Python自動化3.0-------學習路-------模塊初識!

div 函數 傳遞 情況 必須 sys 先來 存在 argv 模塊初識   Python的強大之處在於他有非常豐富和強大的標準庫和第三方庫,幾乎你想實現的任何功能都有相應的Python庫支持,以後的課程中會深入講解常用到的各種庫,現在,我們先來象征性的學2個簡單的

Python自動化3.0-------學習路------日期和時間!

unix dst python自動化 相關 http -a 年份 字符串 cti Python 日期和時間 Python 程序能用很多方式處理日期和時間,轉換日期格式是一個常見的功能。 Python 提供了一個 time 和 calendar 模塊可以用於格式化日期和時間。

Python自動化3.0-------學習路-------函數!

rgs 未命名 ack 結果 string 提示 mutable tab 外部 Python 函數 函數是組織好的,可重復使用的,用來實現單一,或相關聯功能的代碼段。 函數能提高應用的模塊性,和代碼的重復利用率。你已經知道Python提供了許多內建函數,比如print()。

架構師速成8.3-可用性分庫分表

路由 運行 進行 一鍵 常量 popu 同步 width track 有狀態分布式,涉及的知識就比較多了,只是我們能夠拿幾個現實的樣例由淺入深的來理解。 數據庫的分庫分表 如果你是一個開發負責人,開始使用單機的數據庫,突然一天數據庫硬盤掛掉了。你沒有