学逆向论坛

找回密码
立即注册

只需一步,快速开始

发新帖

2万

积分

41

好友

1157

主题
发表于 2020-9-1 10:58:26 | 查看: 4547| 回复: 0

第四课 通过修改PE加载DLL

第四课 通过修改PE加载DLL

第四课 通过修改PE加载DLL

第四课 通过修改PE加载DLL
  下面通过实例来讲解

第四课 通过修改PE加载DLL

第四课 通过修改PE加载DLL

第四课 通过修改PE加载DLL

第四课 通过修改PE加载DLL

第四课 通过修改PE加载DLL

第四课 通过修改PE加载DLL

第四课 通过修改PE加载DLL

第四课 通过修改PE加载DLL

第四课 通过修改PE加载DLL

第四课 通过修改PE加载DLL

第四课 通过修改PE加载DLL

第四课 通过修改PE加载DLL

第四课 通过修改PE加载DLL

第四课 通过修改PE加载DLL
  下面分析myhack3.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"

HWND g_hWnd = NULL;

#ifdef __cplusplus
extern "C" {
#endif
// IDT 형식을 위한 dummy export function...
__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);
    }

    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;
}

第四课 通过修改PE加载DLL

第四课 通过修改PE加载DLL

第四课 通过修改PE加载DLL

第四课 通过修改PE加载DLL

第四课 通过修改PE加载DLL

第四课 通过修改PE加载DLL

第四课 通过修改PE加载DLL

第四课 通过修改PE加载DLL

第四课 通过修改PE加载DLL

第四课 通过修改PE加载DLL
  下面看一下DropFile()

第四课 通过修改PE加载DLL

第四课 通过修改PE加载DLL

第四课 通过修改PE加载DLL

第四课 通过修改PE加载DLL

第四课 通过修改PE加载DLL

第四课 通过修改PE加载DLL

第四课 通过修改PE加载DLL

第四课 通过修改PE加载DLL

第四课 通过修改PE加载DLL

第四课 通过修改PE加载DLL

第四课 通过修改PE加载DLL

第四课 通过修改PE加载DLL

第四课 通过修改PE加载DLL

第四课 通过修改PE加载DLL

第四课 通过修改PE加载DLL

第四课 通过修改PE加载DLL

第四课 通过修改PE加载DLL

第四课 通过修改PE加载DLL

第四课 通过修改PE加载DLL

第四课 通过修改PE加载DLL
  复习一下IID结构体的定义
  typedef struct _IMAGE_IMPORT_DESCRIPTOR {
  union {
  DWORD   Characteristics;     // 0 for terminating null import descriptor
  DWORD   OriginalFirstThunk; // RVA 指向INT (PIMAGE_THUNK_DATA)
  };
  DWORD   TimeDateStamp;   
  DWORD   ForwarderChain;     // -1 if no forwarders
  DWORD   Name;            //dll 名称
  DWORD   FirstThunk;         //指向引入函数真实地址单元处的RVA  IAT
  } IMAGE_IMPORT_DESCRIPTOR;
  typedef IMAGE_IMPORT_DESCRIPTOR UNALIGNED *PIMAGE_IMPORT_DESCRIPTOR;

第四课 通过修改PE加载DLL

第四课 通过修改PE加载DLL

第四课 通过修改PE加载DLL

第四课 通过修改PE加载DLL

第四课 通过修改PE加载DLL

第四课 通过修改PE加载DLL

第四课 通过修改PE加载DLL

第四课 通过修改PE加载DLL

第四课 通过修改PE加载DLL

第四课 通过修改PE加载DLL

第四课 通过修改PE加载DLL

第四课 通过修改PE加载DLL

第四课 通过修改PE加载DLL

第四课 通过修改PE加载DLL

第四课 通过修改PE加载DLL

第四课 通过修改PE加载DLL

第四课 通过修改PE加载DLL

第四课 通过修改PE加载DLL

第四课 通过修改PE加载DLL

第四课 通过修改PE加载DLL

第四课 通过修改PE加载DLL

第四课 通过修改PE加载DLL
  首先在空白位置创建新的IDT

第四课 通过修改PE加载DLL

第四课 通过修改PE加载DLL

第四课 通过修改PE加载DLL

第四课 通过修改PE加载DLL

第四课 通过修改PE加载DLL

第四课 通过修改PE加载DLL

第四课 通过修改PE加载DLL

第四课 通过修改PE加载DLL
  删除绑定导入表

第四课 通过修改PE加载DLL

第四课 通过修改PE加载DLL
  IAT中存储的函数地址是dll未加载的地址,当PE文件中不存在绑定导入表时,IAT就与INT一样,此时导入表中的时间戳就为0;否则导入表中的时间戳为-1时,dll的真正时间戳存放于绑定导入表中(绑定导入表地址存放在数据目录的第12项,IAT是第13项)。
  现在大多数情况,导入表的TimeDateStamp都为0,而Windows早期的自带软件(如WinXP的notepad.exe)基本都采用了TimeDateStamp为-1的情况即包含绑定导入表的情况。PE中包含导入表的优点是程序启动快,但是其缺点也十分明显,当存在dll地址重定位和dll修改更新,则绑定导入表也需要修改更新。
  //最后一个结构全0表示绑定导入表结束
  typedef struct _IMAGE_BOUND_IMPORT_DESCRIPTOR {
      DWORD   TimeDateStamp;      //表示绑定的时间戳,如果和PE头中的TimeDateStamp不同则可能被修改过
      WORD    OffsetModuleName;   //dll名称地址
      WORD    NumberOfModuleForwarderRefs;    //依赖dll个数
  // Array of zero or more IMAGE_BOUND_FORWARDER_REF follows
  } IMAGE_BOUND_IMPORT_DESCRIPTOR,  *PIMAGE_BOUND_IMPORT_DESCRIPTOR;
  NumberOfModuleForwarderRefs是指该dll自身依赖的dll的个数。值为n代表该结构后面紧跟了n个IMAGE_BOUND_FORWARDER_REF结构。之后才是导入表导入的下一个dll的结构。而IMAGE_BOUND_FORWARDER_REF结构体如下所示:
  typedef struct _IMAGE_BOUND_FORWARDER_REF {
      DWORD   TimeDateStamp;  //时间戳,同样的作用检查更新情况
      WORD    OffsetModuleName;   //dll名称地址
      WORD    Reserved;   //保留
  } IMAGE_BOUND_FORWARDER_REF, *PIMAGE_BOUND_FORWARDER_REF;
  注意:这两个结构体中所有的OffsetModuleName均不是相对于ImageBase的RVA也不是FOA,而是相对于绑定导入表首地址的偏移地址,即:绑定导入表首地址 + OffsetModuleName= RVA
  绑定导入表结构图解如下所示:

第四课 通过修改PE加载DLL

第四课 通过修改PE加载DLL

第四课 通过修改PE加载DLL

第四课 通过修改PE加载DLL

第四课 通过修改PE加载DLL

第四课 通过修改PE加载DLL
  创建新的IDT:
  先使用Hex Editor完全复制原IDT(RAW:76CC~772F),然后覆盖到IDT的新位置(RAW:7E80)
  复制:

第四课 通过修改PE加载DLL

第四课 通过修改PE加载DLL
  覆盖:

第四课 通过修改PE加载DLL

第四课 通过修改PE加载DLL
  在7ED0处写入IID

第四课 通过修改PE加载DLL

第四课 通过修改PE加载DLL

第四课 通过修改PE加载DLL

第四课 通过修改PE加载DLL

第四课 通过修改PE加载DLL

第四课 通过修改PE加载DLL

第四课 通过修改PE加载DLL

第四课 通过修改PE加载DLL

第四课 通过修改PE加载DLL

第四课 通过修改PE加载DLL
  详解如下图

第四课 通过修改PE加载DLL

第四课 通过修改PE加载DLL

第四课 通过修改PE加载DLL

第四课 通过修改PE加载DLL

第四课 通过修改PE加载DLL

第四课 通过修改PE加载DLL

第四课 通过修改PE加载DLL

第四课 通过修改PE加载DLL
  修改IAT节区的属性

第四课 通过修改PE加载DLL

第四课 通过修改PE加载DLL

第四课 通过修改PE加载DLL

第四课 通过修改PE加载DLL

第四课 通过修改PE加载DLL

第四课 通过修改PE加载DLL

第四课 通过修改PE加载DLL

第四课 通过修改PE加载DLL

第四课 通过修改PE加载DLL

第四课 通过修改PE加载DLL

第四课 通过修改PE加载DLL

第四课 通过修改PE加载DLL

第四课 通过修改PE加载DLL

第四课 通过修改PE加载DLL
  三天才整完这一课,中途在使用winhex的时候出了点小差错弄了很久,只要有耐心,成功之后会非常有成就感的
            
温馨提示:
1.如果您喜欢这篇帖子,请给作者点赞评分,点赞会增加帖子的热度,评分会给作者加学币。(评分不会扣掉您的积分,系统每天都会重置您的评分额度)。
2.回复帖子不仅是对作者的认可,还可以获得学币奖励,请尊重他人的劳动成果,拒绝做伸手党!
3.发广告、灌水回复等违规行为一经发现直接禁言,如果本帖内容涉嫌违规,请点击论坛底部的举报反馈按钮,也可以在【投诉建议】板块发帖举报。
论坛交流群:672619046

小黑屋|手机版|站务邮箱|学逆向论坛 ( 粤ICP备2021023307号 )|网站地图

GMT+8, 2024-4-17 01:49 , Processed in 0.114874 second(s), 42 queries .

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表