修改思路
PE文件中导入dll信息以结构体列表形式存储在IDT中。只要将myhack.dll添加到列表尾部即可。
IDT结构
IDT的描述在IMAGE_OPTION_HEADER里面的IMPORT Table,通过size可以确定是否有足够的空间让我们添加
IDT是由IMAGE_IMPORT_DESCRIPTION(简称IID)结构体组成的数组,数组末尾以NULL结构体结束。每个IID结构体为0x14字节所以这里IID区域为RVA
真正的IDT在Section .rdata的IMPORT Directory Table
这里可以数一下我这里有16个结构体(18*0x14=0x168)前面查到的size为0x168
没有足够的空间。
移动IDT
需要找一个足够大的空间,这段空间在磁盘文件中但是不会被加载到内存。
看一下rdata头的信息
size of raw data表示该节区在磁盘中的大小,0x50a00
virtual size表示该节区在内存中的大小,0x5081c
回头看一下IDT的size是0x168,需要的是0x168+0x14=0x17c
data段没被加载的空间大小为
>>> hex(0x50a00-0x5081c)
'0x1e4'
所以.rdata区域的空间完全足够用了。
找到IDT的所有数据准备搬家
把它放到hex(0x152600+0x5081c)='0x1a2e1c’这个地址处
修改IIMPORT Table的值
需要把刚才设置的IDT的地址和size放入到IMPORT Table里面,注意这里填入的是RVA(也就是载入内存时的地址)。
RVA_IDT=RVA_idata+size_idata_R=0x154000+0x5081c=0x1A481C
这里是小端存储所以应该倒着存放,别忘了size要改为0x17c
删除绑定导入表
BOUND IMPORT TABLE(绑定导入表)是一种提高DLL加载速度的技术,不是必须项这里为了方便删除掉它。这里不存在就不需要多余的操作了。
创建IDT表项
如图,每一项都有
import Name Table RVA RVA to INT
紧跟着2位0
Name RVA RVA to Dll Name
import Address Table RVA RVA to IAT
IDT表结构
这三项也放在不被加载的区域即可,这里放置在IDT表下面。
修改如下
修改IAT节区属性
实际运行的时候IAT将会被替换所以写入的IAT可以是随意的数据,但是想要执行这个操作还需要修改IAT节区为可写。
可以看到,默认rdata节区是不可写的。
在原属性上添加IMAGE_SCN_MEM_WRITE(80000000)
跟原本的40000040进行或运算c0000040.
找到了一个自动化的脚本
https://www.cnblogs.com/HsinTsao/p/7435137.html
myhack.dll
#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.google.com/index.html"
#define DEF_INDEX_FILE L"index.html"
//DownloadURL
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!\n");
return FALSE;
}
hURL = InternetOpenUrl(hInternet, szURL, NULL, 0, INTERNET_FLAG_RELOAD,0);
if (NULL == hInternet)
{
OutputDebugString(L"InternetOpen() failed!\n");
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);
}
bRet = TRUE;
_DownloadURL_EXIT:
if (pFile)
fclose(pFile);
if (hURL)
InternetCloseHandle(hURL);
if (hInternet)
{
InternetCloseHandle(hInternet);
}
return bRet;
}
//downloadURL会下载szURL中指定的网页文件并将其保存在szFile目录中
//DropFile
HWND g_hWnd = 0;
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"GetWndHandleFromPIF() failed!!\n");
return FALSE;
}
PostMessage(hWnd, WM_DROPFILES, (WPARAM)pBuf, NULL);
return TRUE;
}
//dummy函数
#ifdef __cplusplus
extern "C"{
#endif
//出现在IDT中的dump export function......
__declspec(dllexport)void dummy()
{
return;
}
#ifdef __cplusplus
}
#endif
//dll main函数
DWORD WINAPI ThreadProc(LPVOID lParam)
{
TCHAR szPath[MAX_PATH] = { 0, };
TCHAR *p = NULL;
GetModuleFileName(NULL, szPath, sizeof(szPath));
if (p = _tcsrchr(szPath, L'\\'))
{
_tcscpy_s(p + 1, wcslen(DEF_INDEX_FILE) + 1, DEF_INDEX_FILE);
if (DownloadURL(DEF_URL, szPath))
{
DropFile(szPath);
}
}
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;
}