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静态注入的更多相关文章

  1. Dll注入:修改PE文件 IAT注入

    PE原理就不阐述了, 这个注入是PE感染的一种,通过添加一个新节注入,会改变PE文件的大小,将原有的导入表复制到新节中,并添加自己的导入表描述符,最后将数据目录项中指向的导入表的入口指向新节. 步骤: ...

  2. 利用模块加载回调函数修改PE导入表实现注入

    最近整理PE文件相关代码的时候,想到如果能在PE刚刚读进内存的时候再去修改内存PE镜像,那不是比直接对PE文件进行操作隐秘多了么? PE文件在运行时会根据导入表来进行dll库的"动态链接&q ...

  3. 基于Mono.Cecil的静态注入

    Aop注入有2种方式:动态注入和静态注入,其中动态注入有很多实现了 动态注入有几种方式: 利用Remoting的ContextBoundObject或MarshalByRefObject. 动态代理( ...

  4. Android中通过进程注入技术修改广播接收器的优先级

    前言 这个周末又没有吊事,在家研究了如何通过进程的注入技术修改广播接收器的优先级,关于这个应用场景是很多的,而且也很重要,所以就很急的去fixed了. Android中的四大组件中有一个广播:Broa ...

  5. spring 静态注入

    1.静态注入 在setter 方法修改为非 static , 然后在上面注入即可 @Component public class WeixinConfig { // token public stat ...

  6. 日志系统实战(一)—AOP静态注入

    背景 近期在写日志系统,需要在运行时在函数内注入日志记录,并附带函数信息,这时就想到用Aop注入的方式. AOP分动态注入和静态注入两种注入的方式. 动态注入方式 利用Remoting的Context ...

  7. 使用Dagger2做静态注入, 对比Guice.

    Dagger 依赖注入的诉求, 这边就不重复描述了, 在上文Spring以及Guice的IOC文档中都有提及, 既然有了Guice, Google为啥还要搞个Dagger2出来重复造轮子呢? 因为使用 ...

  8. spring静态注入

    与其说是静态注入(IOC),不如讲是对JavaBean 的静态成员变量进行赋值. 一般我们在使用依赖注入的时候,如果当前对象(javaBean )创建(实例化)一次,那么非静态的成员变量也会实例化一次 ...

  9. 转: spring静态注入

    与其说是静态注入(IOC),不如讲是对JavaBean 的静态成员变量进行赋值. 一般我们在使用依赖注入的时候,如果当前对象(javaBean )创建(实例化)一次,那么非静态的成员变量也会实例化一次 ...

随机推荐

  1. 基于Azure IoT开发.NET物联网应用系列-全新的Azure IoT架构

    物联网技术已经火了很多年了,业界各大厂商都有各自成熟的解决方案.我们公司主要搞新能源汽车充电,充电桩就是物联网技术的最大应用,车联网.物联网.互联网三网合一.2017年的时候重点研究过Azure Io ...

  2. 【深度思考】JDK8中日期类型该如何使用?

    在JDK8之前,处理日期时间,我们主要使用3个类,Date.SimpleDateFormat和Calendar. 这3个类在使用时都或多或少的存在一些问题,比如SimpleDateFormat不是线程 ...

  3. render props的运用

    2020-04-03 render props的运用 术语 “render prop” 是指一种在 React 组件之间使用一个值为函数的 prop 共享代码的简单技术 通常的 这个值为函数的prop ...

  4. CenterOS7 修改 SSH 端口

    首先修改 /etc/ssh/sshd_config 文件中的 Port.修改前一定要备份 可以同时启用多个Port所以最好先追加一个端口,新端口校验没问题之后再把原端口删除 防火墙设置 # 永久开放端 ...

  5. 十几万条数据的表中,基于帝国cms 。自己亲身体验三种批量更新数据的方法,每一种的速度是什么样的

    需求是 上传Excel 读取里面的数据.根据Excel中某一个字段,与数据表中的一个字段的唯一性.然后把 Excel表中数据和数据库表中数据一次更改.本次测试一次更新31条数据. 本次测试基于帝国cm ...

  6. qemu-guest-agent详解

    qemu guest agent简称qga, 是运行在虚拟机内部的一个守护程序(qemu-guest-agent.service),他可以管理应用程序,执行宿主机发出的命令. QEMU为宿主机和虚拟机 ...

  7. Mybatis框架介绍

    MyBatis 本是apache的一个开源项目iBatis, 2010年这个项目由apache software foundation 迁移到了google code,并且改名为MyBatis.201 ...

  8. Jenkins项目构建运行

    [准备环境] 继Jenkins环境搭建完成后,进行插件的管理 [思路] 项目顺序是,开发提交代码到代码仓库,测试通过Jenkins拉下开发的代码打包部署: 1.开发提交代码 2.Jenkins自动从代 ...

  9. 并发编程之详解InheritableThreadLocal类原理

    [本文版权归微信公众号"代码艺术"(ID:onblog)所有,若是转载请务必保留本段原创声明,违者必究.若是文章有不足之处,欢迎关注微信公众号私信与我进行交流!] 在Java并发编 ...

  10. Wireshark论证TCP3次握手的过程

    wireshark过滤条件:ip.addr == 120.79.36.180 千万别写成 ip.dst == 120.79.36.180 ,这样子就看不到服务器给我们返回的包了 此时,在浏览器输入12 ...