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 ...
随机推荐
- sql print
这个因为你使用了varchar+int ,但是print只支持一种类型的输出,你要么通过转换函数将@no转换成字符类型,要么去掉@name.print '李勇' + convert(varchar, ...
- js比较函数
//1.//bySort函数接受一个首要比较字符串和一个可选的次要比较函数做为参数//并返回一个可以用来包含该成员的对象数组进行排序的比较函数//当o[firstName] 和 p[firstName ...
- mysql分组取topn
本文来自 http://www.jb51.net/article/31590.htm 有些语句sql top n 是sqlserver语法 --按某一字段分组取最大(小)值所在行的数据 代码如下: ...
- Windows下载安装虚拟机和CentOS7
1,想要在Windows系统中安装linux系统,首先需要安装一个虚拟机VMware VMware 12下载地址:https://my.vmware.com/cn/web/vmware/info/sl ...
- Agc019_C Fountain Walk
传送门 题目大意 给定网格图上起点和终点每个格子是长为$100$米的正方形,你可以沿着线走. 平面上还有若干个关键点,以每个关键点为圆心,$10$为半径画圆,表示不能进入圆内的线,但是可以从圆周上走, ...
- Dilworth 定理
主要是做个笔记 DAG 最长反链 = 最小链覆盖 反链:反链上任意两个点 $(u,v)$ ,$u$ 不能到 $v$,$v$ 也不能到 $u$ 最小链覆盖:选出若干可以相交的链,覆盖整张图,注意与“最小 ...
- Linux命令学习(21):netstat命令
版权声明 更新:2017-06-13博主:LuckyAlan联系:liuwenvip163@163.com声明:吃水不忘挖井人,转载请注明出处! 1 文章介绍 本文介绍了Linux下面的netstat ...
- C++中rand()函数的用法
1.rand()不需要参数,它会返回一个从0到最大随机数的任意整数,最大随机数的大小通常是固定的一个大整数. 2.如果你要产生0~99这100个整数中的一个随机整数,可以表达为:int num = r ...
- ubuntu tftp server config
1.安装tftp-server sudo apt-get install tftpd-hpa sudo apt-get install tftp-hpa(如果不需要客户端可以不安装) tftp-hpa ...
- selenium+headless chrome安装使用
pip install selenium 因为phantomJS将停止维护,所以建议使用headless chromeChromeDriver is a separate executable tha ...