远程注入的弊端
我们知道,通过
CreateRemoteThread,传递
LoadLibrary作为线程地址,写入对方空间的
dll路径作为线程参数,那么就可以把dll注入到对方的空间中.但是这有个问题,对方很容易就可以发现我们注入的dll模块.
还有一种方法就是通过写入ShellCode进入对目标空间,然后在用CreateRemoteThread启动,但是写ShellCode很麻烦,每一个API函数的地址都需要自己获取,而且不能像直接写高级语言一样写ShellCode.
那么有没有一种方法,既可以让对方看不到自己的模块,也不需要自己定位API那,就像平常时写高级语言一样简单那.
答案肯定是有的,请看图:
解决远程注入的弊端
1. 新建一个Dll文件
2.申请内存空间
DWORD HideModule(HMODULE hModule)
{
PIMAGE_DOS_HEADER pDos = (PIMAGE_DOS_HEADER)hModule;//DOS 头
PIMAGE_NT_HEADERS pNt = (PIMAGE_NT_HEADERS)((DWORD)hModule + pDos->e_lfanew);//NT 头
//1.申请空间 从扩展头获取dll加载进入内存的大小OptionalHeader.SizeOfImage
PBYTE mem = (PBYTE)VirtualAlloc(0, pNt->OptionalHeader.SizeOfImage, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
if (NULL == mem)
{
//申请空间失败,做些啥.....
return NULL;
}
........
}
3.拷贝dll进入内存空间
//2.拷贝到新的空间
memcpy(mem, (void *)hModule, pNt->OptionalHeader.SizeOfImage);
4.修复重定位
//3.修复重定位 数据目录第6项是重定位表
PIMAGE_BASE_RELOCATION rBase = (PIMAGE_BASE_RELOCATION)((DWORD)mem + pNt->OptionalHeader.DataDirectory[5].VirtualAddress);
DWORD n = 0;
DWORD Base = (DWORD)mem;
DWORD offset = (DWORD)mem - (DWORD)hModule;//
if (offset == 0)
(DWORD)mem;
typedef struct RELOCATIONITEM
{
WORD value : 12;
WORD attr : 4;
} *PRELOCATIONITEM;
PRELOCATIONITEM rItem;
DWORD *item;
while (true)
{
if (rBase->SizeOfBlock == 0)
break;
rItem = (PRELOCATIONITEM)((PBYTE)rBase + 8);
n = (rBase->SizeOfBlock - 8) / 2;
for (int i = 0; i < n; ++i)
{
if (3 == rItem[i].attr)
{
item = (DWORD *)(Base + rBase->VirtualAddress + rItem[i].value);
*item = (*item + offset);
}
}
rBase = (PIMAGE_BASE_RELOCATION)((PBYTE)rBase + rBase->SizeOfBlock);//指向下一个结构
}
return (DWORD)mem;
整个dll
// dllmain.cpp : 定义 DLL 应用程序的入口点。
#include "stdafx.h"
DWORD oldProtect;
BYTE JmpBtye[5];
DWORD oldAddr;
DWORD HideModule(HMODULE hModule);
DWORD WINAPI HookMessageBox(LPVOID notUse);
BOOL APIENTRY DllMain( HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
MessageBoxW(0, 0, 0, 0);
DWORD newModule=HideModule(hModule);
if (newModule)
{
LPTHREAD_START_ROUTINE hook = (LPTHREAD_START_ROUTINE)(newModule + ((DWORD)HookMessageBox - (DWORD)hModule));
hook(NULL);
//CreateThread(0, 0, hook, 0, 0, 0);
}
break;
}
return FALSE;//返回false相当于卸载模块
}
DWORD HideModule(HMODULE hModule)
{
PIMAGE_DOS_HEADER pDos = (PIMAGE_DOS_HEADER)hModule;//DOS 头
PIMAGE_NT_HEADERS pNt = (PIMAGE_NT_HEADERS)((DWORD)hModule + pDos->e_lfanew);//NT 头
//1.申请空间
PBYTE mem = (PBYTE)VirtualAlloc(0, pNt->OptionalHeader.SizeOfImage, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
if (NULL == mem)
{
//申请空间失败,做些啥.....
return NULL;
}
//2.拷贝到新的空间
memcpy(mem, (void *)hModule, pNt->OptionalHeader.SizeOfImage);
//3.修复重定位 数据目录第6项是重定位表
PIMAGE_BASE_RELOCATION rBase = (PIMAGE_BASE_RELOCATION)((DWORD)mem + pNt->OptionalHeader.DataDirectory[5].VirtualAddress);
DWORD n = 0;
DWORD Base = (DWORD)mem;
DWORD offset = (DWORD)mem - (DWORD)hModule;//
if (offset == 0)
(DWORD)mem;
typedef struct RELOCATIONITEM
{
WORD value : 12;
WORD attr : 4;
} *PRELOCATIONITEM;
PRELOCATIONITEM rItem;
DWORD *item;
while (true)
{
if (rBase->SizeOfBlock == 0)
break;
rItem = (PRELOCATIONITEM)((PBYTE)rBase + 8);
n = (rBase->SizeOfBlock - 8) / 2;
for (int i = 0; i < n; ++i)
{
if (3 == rItem[i].attr)
{
item = (DWORD *)(Base + rBase->VirtualAddress + rItem[i].value);
*item = (*item + offset);
}
}
rBase = (PIMAGE_BASE_RELOCATION)((PBYTE)rBase + rBase->SizeOfBlock);//指向下一个结构
}
return (DWORD)mem;
}
using pMessageBoxW=int (WINAPI*)(HWND hWnd,LPCWSTR lpText,LPCWSTR lpCaption,UINT uType);
pMessageBoxW ToMessageBox;
int WINAPI MyMessageBoxW(HWND hWnd,LPCWSTR lpText,LPCWSTR lpCaption,UINT uType)
{
lpText = L" 你好,路过";
return ToMessageBox(hWnd, lpText, lpCaption, uType);
}
DWORD WINAPI HookMessageBox(LPVOID notUse)
{
//WHERE user32.dll
//Find
HMODULE hModule = LoadLibraryA("user32.dll");
DWORD mAddr = (DWORD)GetProcAddress(hModule, "MessageBoxW");
ToMessageBox = (pMessageBoxW)(mAddr + 2);
oldAddr = mAddr;
//Hook 使用热补丁
DWORD addr = mAddr - 5;
VirtualProtect((void *)addr, 15, PAGE_EXECUTE_READWRITE, &oldProtect);
JmpBtye[0] = 0xE9;
//目标地址 指令地址
*(DWORD *)&JmpBtye[1] = (DWORD)((long long)MyMessageBoxW - (long long)addr - 5);
memcpy((void *)addr, JmpBtye, 5);
//替换 mov edi,edi
__asm
{
mov bx, 0xF9EB //jmp short -5
mov eax, mAddr
mov [eax],bx
}
}
void UnHook()
{
__asm
{
mov bx, 0xFF8B
mov eax, oldAddr
mov[eax], bx
}
}
注入部分的代码:
#include <windows.h>
//获取进程句柄
HANDLE GetThePidOfTargetProcess(HWND hwnd)
{
DWORD pid;
GetWindowThreadProcessId(hwnd, &pid);
HANDLE hProcee = ::OpenProcess(PROCESS_ALL_ACCESS | PROCESS_CREATE_THREAD, 0, pid);
return hProcee;
}
//提升权限
void Up()
{
HANDLE hToken;
LUID luid;
TOKEN_PRIVILEGES tp;
OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken);
LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &luid);
tp.PrivilegeCount = 1;
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
tp.Privileges[0].Luid = luid;
AdjustTokenPrivileges(hToken, 0, &tp, sizeof(TOKEN_PRIVILEGES), NULL, NULL);
}
//进程注入
BOOL DoInjection(char *DllPath, HANDLE hProcess)
{
DWORD BufSize = strlen(DllPath)+1;
LPVOID AllocAddr = VirtualAllocEx(hProcess, NULL, BufSize, MEM_COMMIT, PAGE_READWRITE);
WriteProcessMemory(hProcess, AllocAddr, DllPath, BufSize, NULL);
PTHREAD_START_ROUTINE pfnStartAddr = (PTHREAD_START_ROUTINE)GetProcAddress(GetModuleHandle(TEXT("Kernel32")), "LoadLibraryA");
HANDLE hRemoteThread;
hRemoteThread = CreateRemoteThread(hProcess, NULL, 0, pfnStartAddr, AllocAddr, 0, NULL);
if (hRemoteThread)
{
MessageBox(NULL, TEXT("注入成功"), TEXT("提示"), MB_OK);
return true;
}
else
{
MessageBox(NULL, TEXT("注入失败"), TEXT("提示"), MB_OK);
return false;
}
}
int main()
{
//这里填写窗口标题
HWND hwnd=FindWindowExA(NULL, NULL, NULL, "TestMFC");
Up();
HANDLE hP = GetThePidOfTargetProcess(hwnd);
//开始注入
//这里填写Dll路径
DoInjection("E:\\studio\\VS2017\\HideDll\\Debug\\HideDll.dll", hP);
}
#include <windows.h>
//获取进程句柄
HANDLE GetThePidOfTargetProcess(HWND hwnd)
{
DWORD pid;
GetWindowThreadProcessId(hwnd, &pid);
HANDLE hProcee = ::OpenProcess(PROCESS_ALL_ACCESS | PROCESS_CREATE_THREAD, 0, pid);
return hProcee;
}
//提升权限
void Up()
{
HANDLE hToken;
LUID luid;
TOKEN_PRIVILEGES tp;
OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken);
LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &luid);
tp.PrivilegeCount = 1;
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
tp.Privileges[0].Luid = luid;
AdjustTokenPrivileges(hToken, 0, &tp, sizeof(TOKEN_PRIVILEGES), NULL, NULL);
}
//进程注入
BOOL DoInjection(char *DllPath, HANDLE hProcess)
{
DWORD BufSize = strlen(DllPath)+1;
LPVOID AllocAddr = VirtualAllocEx(hProcess, NULL, BufSize, MEM_COMMIT, PAGE_READWRITE);
WriteProcessMemory(hProcess, AllocAddr, DllPath, BufSize, NULL);
PTHREAD_START_ROUTINE pfnStartAddr = (PTHREAD_START_ROUTINE)GetProcAddress(GetModuleHandle(TEXT("Kernel32")), "LoadLibraryA");
HANDLE hRemoteThread;
hRemoteThread = CreateRemoteThread(hProcess, NULL, 0, pfnStartAddr, AllocAddr, 0, NULL);
if (hRemoteThread)
{
MessageBox(NULL, TEXT("注入成功"), TEXT("提示"), MB_OK);
return true;
}
else
{
MessageBox(NULL, TEXT("注入失败"), TEXT("提示"), MB_OK);
return false;
}
}
int main()
{
//这里填写窗口标题
HWND hwnd=FindWindowExA(NULL, NULL, NULL, "TestMFC");
Up();
HANDLE hP = GetThePidOfTargetProcess(hwnd);
//开始注入
//这里填写Dll路径
DoInjection("E:\\studio\\VS2017\\HideDll\\Debug\\HideDll.dll", hP);
}
查看效果:
没注入前:
注入之后
可以看到并没有看到注入的模块.
[课程]Android-CTF解题方法汇总!