静态修改输入表hook
最近在重读加密与解密因此写下相关笔记和感悟方便以后使用
随书文件 https://book.pediy.com/bk4.txt
PE结构
基地址
VCexe一般基址是400000h
DLL一般是10000000H
虚拟地址 VA virtual address
相对虚拟地址 RVA
相对于pe载入地址
RVA转FOV
判断RVA在哪个区内
用RVA减去该区VA加上该区PointerToRaw得到FOV
IID 输入表
OriginalFirstThunk 指向输入名称表(INT)的RVA 保存导入名称
FirstThunk 保存导入地址
绑定操作就是遍历 OriginalFirstThunk 对应的函数的入口地址 用他们重写FirstThunk指向的数组
DLL注入
在通常情况下,程序加载DLL的时机主要有以下3个:
一是在进程创建阶段加载输人表中的DLL,即俗称的“静态输人”;
二是通过调用LoadLibrary(Ex)主动加载,称为“动态加载”;
三是由于系统机制的要求,必须加载系统预设的一些基础服务模块,例如Shell扩展模块、网络服务接
口模块或输人法模块等。
因此,在进行DLL注人时,也不外乎通过这3种手段进行。
通过干预输入表处理过程加载目标dll
当一个进程被创建后,不会直接到EXE本身的入口处执行,
首先被执行的是ndll.ll中的LdrInitializeThunk函数(ntdll是Windows操作系统中一个非常重要的基础模块,它在进程创建阶段就已经被映射到新进程中了)。
LdrInitializeThunk会调用LdrpInitializeProcess对进程的一些必要内容进行初始化
LdrpInitializeProcess会继续调用LdrpWalkImportDescriptor对输人表进行处理,即加载输人表中的模块,并填充应用程序的IAT。
所以,只要在输人表被处理之前进行干预,为输人表增加一个项目,使其指向要加载的目标DLL,或者替换原输入表中的DLL并对调用进行转发,那么新进程的主线程在输人表初始化阶段就会主动加载目标DLL。
静态修改输入表
先编写我们的注入dll
VS2022
// dllmain.cpp : 定义 DLL 应用程序的入口点。
#include "pch.h"
#include "stdio.h"
#pragma warning(disable : 4996)
#include "pch.h"
#define __T(x) L ## x
#define _T(x) __T(x)
extern "C" _declspec(dllexport) void Msg();
void Msg()
{
}
BOOL APIENTRY DllMain(HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
MessageBox(NULL, _T("DLL注入标题"), _T("DLL注入内容"), MB_OK);
break;
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
三项IID 加上IID尾 加上我们新增的一个 共需要5*14h 即64h空间来存放新IID
段reloc有足够空间存放(其实前面的段也有)
直接复制原IID到 .reloc段末尾
然后找个地方存放我们DLL相关信息 即firstthunk和OriginalFirstThunk和dll名称和函数名称
因为.reloc段空间足够 我在底下写相关信息 (记得中间留下2*14h的空间 是新的IID和IID结尾的空间
先填写dll名称和导入函数名称
然后通过FOV计算RVA
先计算导入函数名称
FOV为F54B
段PointerToRawData为F400h
VirtualAddress 为25000h
所以RVA为F54B-F400+25000 =02514B 即firstthunk和OriginalFirstThunk值
再计算导入dll名称
FOV为F540h
所以RVA为F540-F400+25000 =025140
而firstthunk和OriginalFirstThunk的RVA为25130与25138
然后向IID填入相关数据
然后修改reloc可写
然后修改导入表地址
此时新导入表FOV为F480 RVA为025080 再修改size为64h
即可
然后去除bound
然后开始报错) 我的exe为64位自己编写的C++ dll为自己导出的64位dll报错
32位程序 随书文件中的32位dll 成功hook
32位程序 自己编写的32位dll hook失败 原流程运行
64位程序 自己编写的32位或64位dll以及随书的32或64位dll均报错
随书的notepad.exe 自己编写的32位dll hook成功 并可正常使用原功能