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. ProxySQL简介原理及读写分离应用

    MySQL-ProxySQL中间件简介 同类型产品 MySQL Route:是现在MySQL官方Oracle公司发布出来的一个中间件. Atlas:是由奇虎360公发的基于MySQL协议的数据库中间件 ...

  2. JAVA第三次blog总结

    JAVA第三次blog总结 0.前言 这是我们在博客园上第三次写博客,也是本学期最后一次的JAVA学习大总结.现在我们的JAVA已经接近尾声了,对于编程思想和方法的改变依旧是难点,但是经过这一段时间的 ...

  3. Zookeeper实现服务注册/发现

    what that? Zookeeper在分布式开发中使用频繁,但许多框架都对其进行了封装,初学者可能无法较好的理解其工作原理,该文章演示了使用Zookeeper实现服务注册,服务发现的简单demo, ...

  4. JSP和Servlet的相同点和不同点、有何联系。

    JSP 和 Servlet 有哪些相同点和不同点,他们之间的联系是什么? 联系: JSP 是 Servlet 技术的扩展,本质上是 Servlet 的简易方式,更强调应用的外表表达. JSP编译后是& ...

  5. 【经验心得】谈一谈我IT行业未来的方向

    随着科技的发展,越来越多的入门行业将被淘汰,其实淘汰的不仅仅是工厂.环卫工人.普工这些无技术含量的工作,有一些运维.编辑等低门槛的行业也将被淘汰,这也是我这两年看互联网发展趋势得出来的结论,人类要想发 ...

  6. 「JOISC 2020 Day4」首都城市

    题目   点这里看题目. 分析   做法比较容易看出来.我们对于每个城市,找出那些 " 如果这个城市在首都内,则必须在首都内的其它城市 " ,也就是为了让这个城市的小镇连通而必须选 ...

  7. @codeforces - 685C@ Optimal Point

    目录 @description@ @solution@ @accepted code@ @details@ @description@ 给定若干个三维空间的点 (xi, yi, zi),求一个坐标都为 ...

  8. Redis系列(三):redisServer、redisDb、redisObject、sds四大结构体理解

    一.源码下载: Windows中的Redis源码下载:https://github.com/microsoftarchive/redis/tree/3.2 根据官网说明可知,用VS2013编译,但是必 ...

  9. 最全面的SourceTree账号注册教程

    前言: 作为一个国内开发者而言使用Git操作神器SoureTree最大的问题就是账号注册问题,因为注册账号的链接在不翻墙的情况下基本上是打不开的(弄过的童鞋应该都体会过),所以有的时候我们需要借助一些 ...

  10. numpy中的浅复制和深复制

    浅复制:主要有两种方式,简单的赋值或者使用视图(view) 简单的赋值:其实就是制造了一个别名,数组并没有被copy成新的一份,当使用其中一个别名改变数组值的时候,另一个别名对应的值一并改变. > ...