DLL注入之修改PE静态注入
DLL注入之修改PE静态注入
0x00 前言
我们要注入的的力量功能是下载baidu首页数据。代码如下:
#include "stdio.h"
#include"stdio.h"
#include "windows.h"
#include "shlobj.h"
#include "Wininet.h"
#include "tchar.h"
#pragma comment(lib, "Wininet.lib")
#define DEF_BUF_SIZE (4096)
#define DEF_URL L"http://www.baidu.com/index.html"
#define DEF_INDEX_FILE L"index.html"
HWND g_hWnd = NULL;
#ifdef __cplusplus
extern "C" {
#endif
__declspec(dllexport) void dummy()
{
return;
}
#ifdef __cplusplus
}
#endif
BOOL DownloadURL(LPCTSTR szURL, LPCTSTR szFile)
{
BOOL bRet = FALSE;
HINTERNET hInternet = NULL, hURL = NULL;
BYTE pBuf[DEF_BUF_SIZE] = {0,};
DWORD dwBytesRead = 0;
FILE *pFile = NULL;
errno_t err = 0;
hInternet = InternetOpen(L"ReverseCore",
INTERNET_OPEN_TYPE_PRECONFIG,
NULL,
NULL,
0);
if( NULL == hInternet )
{
OutputDebugString(L"InternetOpen() failed!");
return FALSE;
}
hURL = InternetOpenUrl(hInternet,
szURL,
NULL,
0,
INTERNET_FLAG_RELOAD,
0);
if( NULL == hURL )
{
OutputDebugString(L"InternetOpenUrl() failed!");
goto _DownloadURL_EXIT;
}
if( err = _tfopen_s(&pFile, szFile, L"wt") )
{
OutputDebugString(L"fopen() failed!");
goto _DownloadURL_EXIT;
}
while( InternetReadFile(hURL, pBuf, DEF_BUF_SIZE, &dwBytesRead) )
{
if( !dwBytesRead )
break;
fwrite(pBuf, dwBytesRead, 1, pFile);
}
/*
_ACRTIMP size_t __cdecl fwrite(
_In_reads_bytes_(_ElementSize * _ElementCount) void const* _Buffer,
_In_ size_t _ElementSize,
_In_ size_t _ElementCount,
_Inout_ FILE* _Stream
);
*/
bRet = TRUE;
_DownloadURL_EXIT:
if( pFile )
fclose(pFile);
if( hURL )
InternetCloseHandle(hURL);
if( hInternet )
InternetCloseHandle(hInternet);
return bRet;
}
BOOL CALLBACK EnumWindowsProc(HWND hWnd, LPARAM lParam)
{
DWORD dwPID = 0;
GetWindowThreadProcessId(hWnd, &dwPID);
if( dwPID == (DWORD)lParam )
{
g_hWnd = hWnd;
return FALSE;
}
return TRUE;
}
HWND GetWindowHandleFromPID(DWORD dwPID)
{
EnumWindows(EnumWindowsProc, dwPID);
return g_hWnd;
}
BOOL DropFile(LPCTSTR wcsFile)
{
HWND hWnd = NULL;
DWORD dwBufSize = 0;
BYTE *pBuf = NULL;
DROPFILES *pDrop = NULL;
char szFile[MAX_PATH] = {0,};
HANDLE hMem = 0;
WideCharToMultiByte(CP_ACP, 0, wcsFile, -1,
szFile, MAX_PATH, NULL, NULL);
dwBufSize = sizeof(DROPFILES) + strlen(szFile) + 1;
if( !(hMem = GlobalAlloc(GMEM_ZEROINIT, dwBufSize)) )
{
OutputDebugString(L"GlobalAlloc() failed!!!");
return FALSE;
}
pBuf = (LPBYTE)GlobalLock(hMem);
pDrop = (DROPFILES*)pBuf;
pDrop->pFiles = sizeof(DROPFILES);
strcpy_s((char*)(pBuf + sizeof(DROPFILES)), strlen(szFile)+1, szFile);
GlobalUnlock(hMem);
if( !(hWnd = GetWindowHandleFromPID(GetCurrentProcessId())) )
{
OutputDebugString(L"GetWndHandleFromPID() failed!!!");
return FALSE;
}
PostMessage(hWnd, WM_DROPFILES, (WPARAM)pBuf, NULL);
return TRUE;
}
DWORD WINAPI ThreadProc(LPVOID lParam)
{
TCHAR szPath[MAX_PATH] = {0,};
TCHAR *p = NULL;
OutputDebugString(L"ThreadProc() start...");
GetModuleFileName(NULL, szPath, sizeof(szPath));
if( p = _tcsrchr(szPath, L'\\') )
{
_tcscpy_s(p+1, wcslen(DEF_INDEX_FILE)+1, DEF_INDEX_FILE);
OutputDebugString(L"DownloadURL()");
if( DownloadURL(DEF_URL, szPath) )
{
OutputDebugString(L"DropFlie()");
DropFile(szPath);
}
}
OutputDebugString(L"ThreadProc() end...");
return 0;
}
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
{
switch( fdwReason )
{
case DLL_PROCESS_ATTACH :
CloseHandle(CreateThread(NULL, 0, ThreadProc, NULL, 0, NULL));
break;
}
return TRUE;
}
编译生成名为myhack3.dll的released文件。如下图:

被注入的文件是一个名为TextView.exe的文件。如下图:

0x01 修改PE文件注入思路
通过修改IID数组添加myhack3.dll,修改INT,IAT,以及字段NAME。
0x02 实施步骤
1)修改IID数组。
我们先找到IID数组所在,3ch找到PE头,值位E0,通过E0+80=160H
找到IID地址。如下图:

可知RVA为84CC大小为64h。
2)通过lordPE查找区段信息,确定84CC的FileOffset值。如下图:

通过上图区段信息可得到84CC位于.rdata区段。转换为FileOffset=84CC-6000+5200=76CC。当然也可以使用LordPE自带的位置计算器计算,如下图:

和我计算的结果一致。
使用HexWorkShop跳转至76cc处。76cc至772F处为IID数组的值。如下图:

显然,再在这个位置添加myhack的IID结构肯定已经放不下了。所以我们得将整体的IID数组搬迁至新位置。
3)确定IID数组的新位置。有三种方式一是找一块空白区域吧,二是增加最后一个节区大小,然后把IID数组搬过去。三是添加新的节区,然后把IID装进去。显然,第一种方式最省事,而且IID数组也不是很大。我们仔细分析区段信息,如下图:

显然区段.rdata磁盘中的大小为2E00而映射到内存中的大小2C56。也就是在2C56至2E00有一块大小为1AA大小的空白区域,这块区域全是用0填充的。我们选定IID数组从RAV=8C80
开始。
4)将原先IID数组的数据复制,在新地址8C80处填充。如下图:

随后在7ED0后面填写自己构造的IID结构。
5)为了方便,我们就干脆将myhack3.dll的IID的值构造在.rdata的剩余区域。
构造值在下表:(无关紧要的字段设置为0)
|
RVA |
RAW |
|
|
INT地址 |
8d00 |
7F00 |
|
Name地址 |
8d10 |
7F10 |
|
IAN地址 |
8d20 |
7F20 |
一次将值填入如下图:

6)根据上表填写THUN_DATA结构,我们myhack.dll的被调用函数放置在803D处。Name处指向的IMAGE_IMPORT_BY_NAME结构的填入myhack.dll。如下图:

最后修改160处的IID入口地址和大小,改为808c和78。如下图:

至此,重构输入表完成。
7)还有一点值得特别注意的是。我们在在.rdata区段修改了IID数组,其中IAT表也会随之改变,这就要求.rdata区域能够有读写权限,不然,IAT无法重构。我们来查看.rdata的读取权限,如下图:

显然,只读。所以我们要添加写权限。我们就在原来值40000040加上写入权限值c00000000。
加完之后值为c00000040。我们将此值写入224处。
8)另存为TextView5.exe。点击运行。记得把myhack.dll放在同一文件目录,不然无法注入。打开processexploer。查看师是否注入成功。下如图:


显然已经成功注入。下图是运行后下载的index.html
0x03 另一种方法
在上面的方法中,我们注意到IAT和INT的地址写的是一样的,且而后面要更改.rdata区块的读出权限。其实我们可以另辟蹊径。用PEview再次打开修改后的文件TextView5。沃恩打开存放在.data区块的IAT表,如下图:(注意下面的图我都是切换了RVA模式)



我们可以更改上图中的IAT表的大小,增加八个字节存放myhack.dll的地址8D30。即6154存放myhack.dll函数地址。这样无需修改权限也能正常载入。
步骤如下:
1)更改myhack.dll的IID结构中的FristThunK值,使它指向地址6154。
如下图:

2)IAT表末尾6154处填入myhack3.dll函数dummy的地址8D30 。如下图:

3)更改IAT表的大小和.rdata的读取权限(恢复原来的只读权限)
如下图:


保存。运行并查看IAT的变化如下图:

DLL注入之修改PE静态注入的更多相关文章
- Dll注入:修改PE文件 IAT注入
PE原理就不阐述了, 这个注入是PE感染的一种,通过添加一个新节注入,会改变PE文件的大小,将原有的导入表复制到新节中,并添加自己的导入表描述符,最后将数据目录项中指向的导入表的入口指向新节. 步骤: ...
- 利用模块加载回调函数修改PE导入表实现注入
最近整理PE文件相关代码的时候,想到如果能在PE刚刚读进内存的时候再去修改内存PE镜像,那不是比直接对PE文件进行操作隐秘多了么? PE文件在运行时会根据导入表来进行dll库的"动态链接&q ...
- 基于Mono.Cecil的静态注入
Aop注入有2种方式:动态注入和静态注入,其中动态注入有很多实现了 动态注入有几种方式: 利用Remoting的ContextBoundObject或MarshalByRefObject. 动态代理( ...
- Android中通过进程注入技术修改广播接收器的优先级
前言 这个周末又没有吊事,在家研究了如何通过进程的注入技术修改广播接收器的优先级,关于这个应用场景是很多的,而且也很重要,所以就很急的去fixed了. Android中的四大组件中有一个广播:Broa ...
- spring 静态注入
1.静态注入 在setter 方法修改为非 static , 然后在上面注入即可 @Component public class WeixinConfig { // token public stat ...
- 日志系统实战(一)—AOP静态注入
背景 近期在写日志系统,需要在运行时在函数内注入日志记录,并附带函数信息,这时就想到用Aop注入的方式. AOP分动态注入和静态注入两种注入的方式. 动态注入方式 利用Remoting的Context ...
- 使用Dagger2做静态注入, 对比Guice.
Dagger 依赖注入的诉求, 这边就不重复描述了, 在上文Spring以及Guice的IOC文档中都有提及, 既然有了Guice, Google为啥还要搞个Dagger2出来重复造轮子呢? 因为使用 ...
- spring静态注入
与其说是静态注入(IOC),不如讲是对JavaBean 的静态成员变量进行赋值. 一般我们在使用依赖注入的时候,如果当前对象(javaBean )创建(实例化)一次,那么非静态的成员变量也会实例化一次 ...
- 转: spring静态注入
与其说是静态注入(IOC),不如讲是对JavaBean 的静态成员变量进行赋值. 一般我们在使用依赖注入的时候,如果当前对象(javaBean )创建(实例化)一次,那么非静态的成员变量也会实例化一次 ...
随机推荐
- 基于Azure IoT开发.NET物联网应用系列-全新的Azure IoT架构
物联网技术已经火了很多年了,业界各大厂商都有各自成熟的解决方案.我们公司主要搞新能源汽车充电,充电桩就是物联网技术的最大应用,车联网.物联网.互联网三网合一.2017年的时候重点研究过Azure Io ...
- 【深度思考】JDK8中日期类型该如何使用?
在JDK8之前,处理日期时间,我们主要使用3个类,Date.SimpleDateFormat和Calendar. 这3个类在使用时都或多或少的存在一些问题,比如SimpleDateFormat不是线程 ...
- render props的运用
2020-04-03 render props的运用 术语 “render prop” 是指一种在 React 组件之间使用一个值为函数的 prop 共享代码的简单技术 通常的 这个值为函数的prop ...
- CenterOS7 修改 SSH 端口
首先修改 /etc/ssh/sshd_config 文件中的 Port.修改前一定要备份 可以同时启用多个Port所以最好先追加一个端口,新端口校验没问题之后再把原端口删除 防火墙设置 # 永久开放端 ...
- 十几万条数据的表中,基于帝国cms 。自己亲身体验三种批量更新数据的方法,每一种的速度是什么样的
需求是 上传Excel 读取里面的数据.根据Excel中某一个字段,与数据表中的一个字段的唯一性.然后把 Excel表中数据和数据库表中数据一次更改.本次测试一次更新31条数据. 本次测试基于帝国cm ...
- qemu-guest-agent详解
qemu guest agent简称qga, 是运行在虚拟机内部的一个守护程序(qemu-guest-agent.service),他可以管理应用程序,执行宿主机发出的命令. QEMU为宿主机和虚拟机 ...
- Mybatis框架介绍
MyBatis 本是apache的一个开源项目iBatis, 2010年这个项目由apache software foundation 迁移到了google code,并且改名为MyBatis.201 ...
- Jenkins项目构建运行
[准备环境] 继Jenkins环境搭建完成后,进行插件的管理 [思路] 项目顺序是,开发提交代码到代码仓库,测试通过Jenkins拉下开发的代码打包部署: 1.开发提交代码 2.Jenkins自动从代 ...
- 并发编程之详解InheritableThreadLocal类原理
[本文版权归微信公众号"代码艺术"(ID:onblog)所有,若是转载请务必保留本段原创声明,违者必究.若是文章有不足之处,欢迎关注微信公众号私信与我进行交流!] 在Java并发编 ...
- Wireshark论证TCP3次握手的过程
wireshark过滤条件:ip.addr == 120.79.36.180 千万别写成 ip.dst == 120.79.36.180 ,这样子就看不到服务器给我们返回的包了 此时,在浏览器输入12 ...