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. redis 分布式锁的简单使用

    RedisLock--让 Redis 分布式锁变得简单 目录 1. 项目介绍 2. 快速使用 2.1 引入 maven 坐标 2.2 注册 RedisLock 2.3 使用 3. 参与贡献 4. 联系 ...

  2. 权限系统设计(0):权限系统设计基本概念改需-MAC/RBAC引子

    此篇主要对权限系统设计所涉的一些专业术语重点梳理.从我们windows的文件系统 自主访问控制 到基于角色访问控制. 权限设计基本术语 对后面会用到的词汇做一个简要说明 什么是权限(许可) 权限(Pr ...

  3. profile(/etc/profile)和bash_profile的区别

    profile(/etc/profile)和bash_profile的区别 profile(/etc/profile),用于设置系统级的环境变量和启动程序,在这个文件下配置会对所有用户生效.当用户登录 ...

  4. .NET Core加解密实战系列之——RSA非对称加密算法

    目录 简介 功能依赖 生成RSA秘钥 PKCS1格式 PKCS8格式 私钥操作 PKCS1与PKCS8格式互转 PKCS1与PKCS8私钥中提取公钥 PEM操作 PEM格式密钥读取 PEM格式密钥写入 ...

  5. Mybaties概述

  6. Razor 视图

    Razor 视图 关于视图引擎 视图引擎简单理解就是能够支持对视图的解析,在 ASP.NET MVC 中,视图引擎的作用就是把视图处理成浏览器能够执行的 HTML 代码,不同的视图引擎,语法规则不一样 ...

  7. 动作函数-web_submit_data

    web_submit_data("login.pl", "Action=http://127.0.0.1:1080/WebTours/login.pl", &q ...

  8. 容器技术之Docker-swarm

    前文我聊到了docker machine的简单使用和基本原理的说明,回顾请参考https://www.cnblogs.com/qiuhom-1874/p/13160915.html:今天我们来聊一聊d ...

  9. Jmeter系列(29)- 详解 JDBC Connection Configuration

    如果你想从头学习Jmeter,可以看看这个系列的文章哦 https://www.cnblogs.com/poloyy/category/1746599.html 前言 发起 jdbc 请求前,需要有 ...

  10. python list遍历方法汇总

    list=['a','b','c','d','e'] #方法1: print('#方法1:') #i值为列表的item,list为列表名,因此i值即为列表元素 for i in list: #list ...