dll注入及卸载实践
三种方法:具体详见《逆向工程核心原理》。
1、创建远程线程CreateRemoteThread()
2、使用注册表AppInit_DLLs
3、消息钩取SetWindowsHookEx()
一、远程线程(注意将szPATH数组建在函数中会出现栈溢出,需要建立全局变量)
#include "windows.h"
#include "tchar.h" #pragma comment(lib, "urlmon.lib") HMODULE g_hMod = NULL;
TCHAR szPath[MAX_PATH] = { , };
DWORD WINAPI ThreadProc(LPVOID lParam) { if (!GetModuleFileName(g_hMod, szPath, MAX_PATH))
return FALSE; TCHAR *p = _tcsrchr(szPath, '\\');
if (!p)
return FALSE; _tcscpy_s(p + , MAX_PATH, L"index.html"); URLDownloadToFile(NULL, L"http://www.xidian.edu.cn", szPath, , NULL); return ;
} BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) {
HANDLE hThread = NULL; g_hMod = (HMODULE)hinstDLL; switch (fdwReason)
{
case DLL_PROCESS_ATTACH:
hThread = CreateThread(NULL, , ThreadProc, NULL, , NULL);
CloseHandle(hThread);
break;
} return TRUE;
}
myhack.cpp
#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 = ;
tp.Privileges[].Luid = luid;
if (bEnablePrivilege)
tp.Privileges[].Attributes = SE_PRIVILEGE_ENABLED;
else
tp.Privileges[].Attributes = ; // 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 InjectDll(DWORD dwPID, LPCTSTR szDllPath)
{
HANDLE hProcess = NULL, hThread = NULL;
HMODULE hMod = NULL;
LPVOID pRemoteBuf = NULL;
DWORD dwBufSize = (DWORD)(lstrlen(szDllPath) + ) * sizeof(TCHAR);
LPTHREAD_START_ROUTINE pThreadProc; // 获得dwPID进程ID对应的目标进程句柄
if (!(hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwPID)))
return FALSE; // 在目标进程地址空间中为DLL路径名szDllPath开辟一块存储空间,将szDllPath路径字符串写入该空间
pRemoteBuf = VirtualAllocEx(hProcess, NULL, dwBufSize, MEM_COMMIT, PAGE_READWRITE);
WriteProcessMemory(hProcess, pRemoteBuf, (LPVOID)szDllPath, dwBufSize, NULL); // 获取当前进程地址空间中LoadLibraryW()函数的地址,该函数由kernel32.dll导入
hMod = GetModuleHandle(L"kernel32.dll");
pThreadProc = (LPTHREAD_START_ROUTINE)GetProcAddress(hMod, "LoadLibraryW"); // 在目标进程中运行线程,该线程执行LoadLibraryW()函数并传入被注入DLL路径作为参数
hThread = CreateRemoteThread(hProcess, NULL, , pThreadProc, pRemoteBuf, , NULL);
WaitForSingleObject(hThread, INFINITE); CloseHandle(hThread);
CloseHandle(hProcess); return TRUE;
} int _tmain(int argc, TCHAR *argv[])
{
if (argc != ) {
_tprintf(L"USAGE : %s <pid> <dll_path>\n", argv[]);
return ;
}
if (!SetPrivilege(SE_DEBUG_NAME, TRUE))
return ; // inject dll
if (InjectDll((DWORD)_tstol(argv[]), argv[]))
_tprintf(L"InjectDll(\"%s\") success.\n", argv[]);
else
_tprintf(L"InjectDll(\"%s\") failed.\n", argv[]); return ;
}
inject.cpp
卸载:
// EjectDll.exe #include "windows.h"
#include "tlhelp32.h"
#include "tchar.h" //由进程名找到进程id号
DWORD FindProcessID(LPCTSTR szProcessName) {
DWORD dwPID = 0xFFFFFFFF;
HANDLE hSnapShot = INVALID_HANDLE_VALUE;
PROCESSENTRY32 pe; // 获得系统进程的快照
pe.dwSize = sizeof(PROCESSENTRY32);
hSnapShot = CreateToolhelp32Snapshot(TH32CS_SNAPALL, NULL); Process32First(hSnapShot, &pe);
do {
if (!_tcsicmp(szProcessName, (LPCTSTR)pe.szExeFile)) {
dwPID = pe.th32ProcessID;
break;
}
} while (Process32Next(hSnapShot, &pe)); CloseHandle(hSnapShot);
return dwPID;
} BOOL SetPrivilege(LPCTSTR lpszPrivilege, BOOL bEnablePrivilege) {
TOKEN_PRIVILEGES tp;
HANDLE hToken;
LUID luid; if (!OpenProcessToken(GetCurrentProcess(),
TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken))
return FALSE; if (!LookupPrivilegeValue(NULL, // lookup privilege on local system
lpszPrivilege, // privilege to lookup
&luid)) // receives LUID of privilege
return FALSE; tp.PrivilegeCount = ;
tp.Privileges[].Luid = luid;
if (bEnablePrivilege)
tp.Privileges[].Attributes = SE_PRIVILEGE_ENABLED;
else
tp.Privileges[].Attributes = ; // Enable the privilege or disable all privileges.
if (!AdjustTokenPrivileges(hToken, FALSE, &tp,
sizeof(TOKEN_PRIVILEGES), (PTOKEN_PRIVILEGES)NULL, (PDWORD)NULL))
return FALSE; if (GetLastError() == ERROR_NOT_ALL_ASSIGNED)
return FALSE; return TRUE;
} BOOL EjectDll(DWORD dwPID, LPCTSTR szDllName) {
BOOL bMore = FALSE, bFound = FALSE;
HANDLE hSnapshot, hProcess, hThread;
HMODULE hModule = NULL;
MODULEENTRY32 me = { sizeof(me) };
LPTHREAD_START_ROUTINE pThreadProc; // dwPID = notepad进程的id号
// 使用TH32CS_SNAPMODULE参数,获得加载到notepad进程地址空间的DLL信息
hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, dwPID); bMore = Module32First(hSnapshot, &me);
for (; bMore; bMore = Module32Next(hSnapshot, &me)) {
if (!_tcsicmp((LPCTSTR)me.szModule, szDllName) ||
!_tcsicmp((LPCTSTR)me.szExePath, szDllName)) {
bFound = TRUE;
break;
}
} if (!bFound) {
CloseHandle(hSnapshot);
return FALSE;
} if (!(hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwPID)))
return FALSE; hModule = GetModuleHandle(L"kernel32.dll");
pThreadProc = (LPTHREAD_START_ROUTINE)GetProcAddress(hModule, "FreeLibrary");
hThread = CreateRemoteThread(hProcess, NULL, ,
pThreadProc, me.modBaseAddr,
, NULL);
WaitForSingleObject(hThread, INFINITE); CloseHandle(hThread);
CloseHandle(hProcess);
CloseHandle(hSnapshot); return TRUE;
} int _tmain(int argc, TCHAR* argv[]) {
DWORD dwPID = 0xFFFFFFFF; dwPID = FindProcessID(L"notepad.exe");
if (dwPID == 0xFFFFFFFF) //没有找到notepad进程
return ; // 更改特权
if (!SetPrivilege(SE_DEBUG_NAME, TRUE))
return ; // 卸载DLL
if (EjectDll(dwPID, L"myhack.dll"))
_tprintf(L"EjectDll(%d, \"%s\") success!!!\n", dwPID, L"myhack.dll");
else
_tprintf(L"EjectDll(%d, \"%s\") failed!!!\n", dwPID, L"myhack.dll"); return ;
}
eject.cpp
二、使用注册表(调用进程执行程序)
修改AppInit_DLLs和LoadAppInit_DLLs,路径名使用单右斜杠
#include "windows.h"
#include "tchar.h" BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) {
TCHAR szCmd[MAX_PATH] = { , };
TCHAR szPath[MAX_PATH] = { , };
TCHAR *p = NULL;
STARTUPINFO si = { , };
PROCESS_INFORMATION pi = { , }; si.cb = sizeof(STARTUPINFO);
si.dwFlags = STARTF_USESHOWWINDOW;
si.wShowWindow = SW_HIDE; switch (fdwReason) {
case DLL_PROCESS_ATTACH:
//获得当前DLL被装载到的进程的可执行文件的路径到szPath中
if (!GetModuleFileName(NULL, szPath, MAX_PATH))
break;
if (!(p = _tcsrchr(szPath, '\\')))
break;
if (lstrcmpi(p + , _T("notepad.exe")))
break;
//当前DLL被加载到的进程的可执行文件为notepad.exe,调用IE访问www.xidian.edu.cn
wsprintf(szCmd, _T("%s %s"), _T("C:\\Users\\Administrator\\AppData\\Local\\Google\\Chrome\\Application\\chrome.exe"), _T("http://www.xidian.edu.cn"));
if (!CreateProcess(NULL, (LPTSTR)(LPCTSTR)szCmd,
NULL, NULL, FALSE, NORMAL_PRIORITY_CLASS, NULL, NULL, &si, &pi))
break;
if (pi.hProcess != NULL)
CloseHandle(pi.hProcess);
break;
}
return TRUE;
}
myhack2.cpp
三、消息钩取
详见12.24逆向工程上机作业
dll注入及卸载实践的更多相关文章
- 《逆向工程核心原理》——DLL注入与卸载
利用CreateRemoteThread #include <iostream> #include <tchar.h> #include <Windows.h> # ...
- DLL注入实践
Windows系统大量使用dll作为组件复用,应用程序也会通过dll实现功能模块的拆分.DLL注入技术是向一个正在运行的进程插入自有DLL的过程. Window下的代码注入 常见的Windows代码注 ...
- DLL远程注入与卸载
以下提供两个函数,分别用于向其它进程注入和卸载指定DLL模块.支持Unicode编码. #include <windows.h>#include <tchar.h>#inclu ...
- DLL远程注入及卸载实现
实现win7 64位系统下dll的远程注入及卸载,尚未再其他系统测试 源码地址:https://github.com/ndhisrfzs/InjectDll
- DLL注入
最近的项目涉及了软件破解方面的知识,记录一下. 将dll注入另一个进程. // Inject.cpp : Defines the exported functions for the DLL appl ...
- [转]Dll注入经典方法完整版
Pnig0s1992:算是复习了,最经典的教科书式的Dll注入. 总结一下基本的注入过程,分注入和卸载 注入Dll: 1,OpenProcess获得要注入进程的句柄 2,VirtualAllocEx在 ...
- 第22章 DLL注入和API拦截(2)
22.4 使用远程线程来注入DLL 22.4.1 概述 (1)远程线程注入是指一个进程在另一个进程中创建线程,然后载入我们编写的DLL,并执行该DLL代码的技术.其基本思路是通过CreateRemot ...
- 第22章 DLL注入和API拦截(1)
22.1 注入的一个例子(跨进程子类化窗口) ①子类化窗口可以改变窗口的行为,让发往该窗口的消息重新发到我们指定的过程来处理.但这种行为只能在本进程中(如A),对于从一个进程(如B)去子类化另一个进程 ...
- c++实现dll注入其它进程
DLL注入技术才具有强大的功能和使用性,同时简单易用,因为DLL中可以实现复杂的功能和很多的技术. 技术要点: 1.宿主进程调用LoadLibrary,就可以完成DLL的远程注入.可以通过Create ...
随机推荐
- git 上传项目到分支
步骤 git init git add . git commit -m'代码描述' git remote add origin 远程仓库地址 git branch xxx # 创建新分支 git ch ...
- python中的变量与对象
一. 什么是变量 变量就是以前学习的数学中常见的等式x = 3(x是变量,3是变量值),在编程中,变量不仅可以是数学,还可以是任意数据类型 二. 变量的命名规则 变量名必须是英文大小写.数字和_的组合 ...
- LNMP安装及配置
LNMP官方网站:http://lnmp.org http://oneinstack.com/install/ 安装详细介绍:http://lnmp.org/install.html 1,安装LNMP ...
- GEF入门实例_总结_03_显示菜单和工具栏
一.前言 本文承接上一节: GEF入门实例_总结_02_新建初始RCP空项目 这一节,我们来给我们的插件加上菜单. 二.基础知识 1.action bar.menubar.coolbar 含义 a ...
- 网络编程基础--多线程---concurrent.futures 模块---事件Event---信号量Semaphore---定时器Timer---死锁现象 递归锁----线程队列queue
1 concurrent.futures 模块: # from abc import abstractmethod,ABCMeta # # class A(metaclass=ABCMeta): # ...
- Equation
You are given an equation: Ax2 + Bx + C = 0. Your task is to find the number of distinct roots of th ...
- 排列(加了点小set就过了,哈哈哈)
Ray又对数字的列产生了兴趣: 现有四张卡片,用这四张卡片能排列出很多不同的4位数,要求按从小到大的顺序输出这些4位数. 输入描述: 1 2 3 4 1 1 2 3 0 1 2 3 0 0 0 0输出 ...
- LeetCode 315. Count of Smaller Numbers After Self
原题链接在这里:https://leetcode.com/problems/count-of-smaller-numbers-after-self/ 题目: You are given an inte ...
- webpack 故障处理
Webpack 的配置比较复杂,很容出现错误,下面是一些通常的故障处理手段. 一般情况下,webpack 如果出问题,会打印一些简单的错误信息,比如模块没有找到.我们还可以通过参数 --display ...
- <Yii 学习>写入日志
$postStr ='test:'.(empty( $GLOBALS["HTTP_RAW_POST_DATA"])?'':$GLOBALS["HTTP_RAW_POST_ ...