给OD扩展功能示例

文章转自看雪论坛:https://bbs.pediy.com/thread-207265.htm

原版 OD 中有许多 bug 和未扩展的功能,以原版 OD 为例,为 OD 扩展功能

扩展OD帮助文档打开格式

这里写图片描述

选择帮助文档是一个对话框,调用了GetOpenFileName,其参数指向的是 OPENFILENAME 类型,该类型中第四个成员就是指向过滤的字符串,下面在OD中定位这个API看有没有使用。

这里写图片描述

断下来后,EBP+8的地方就是 OPENFILENAME 类型的指针,观察EBP+8指向的内存值。

这里写图片描述

这里写图片描述

反复打开几次文件选择对话框,文件过滤字符串都是在 0x0018C64C 位置,对话框关闭后这个值会改变(因为这是一个栈空空间),那么跟下这个值的最终来源位置。通过栈回溯一直找,最后找到_Browsefilename这个函数,在这个函数下断点,观察 0x0018B5F4 中的第 4 个 int 位置的值是不是过滤字符串的地址,如果不是就对它下内存写入断点,如果已经是了就还需要往上回溯,一直找到它不是为止。通过内存写入断点找到是下面这行指令把过滤字符地址复制到对应位置,现在只要hook这行指令即可:

这里写图片描述

为OD添加一个 F1 打开帮助文档

再窗口过程函数中下 WM_COMMAND 条件断点,再点击打开帮助文档的菜单,得到其菜单 ID,然后就可以 HOOK 窗口过程函数来对其进行处理。

这里写图片描述

窗口过程函数显示

有空写…

相关代码

#include "stdafx.h"
#include <WINDOWS.H>
#include <stdlib.h>
#include "plugin.h"

///////////////////////////////////////////////////////////////
/************************   ClsProc  ************************/
///////////////////////////////////////////////////////////////

DWORD g_dwOld;

DWORD __stdcall MyGetClassLong(  HWND hWnd,  // handle to window
                               int nIndex)  // offset of value to retrieve
{
    if (IsWindowUnicode(hWnd))
    {
        return GetClassLongW(hWnd, nIndex);
    }

    return GetClassLongA(hWnd, nIndex);
}

BOOL RepairClsProc()
{
    //api hook
    LPVOID addr = (LPVOID)0x50d858;

    BOOL bRet = VirtualProtect(addr, 0x1, PAGE_EXECUTE_READWRITE, &g_dwOld);
    if (!bRet)
    {
        return FALSE;   
    }


    //LPVOID myFuncPtr = MyGetClassLong;

    *(DWORD*)addr = (DWORD)MyGetClassLong;


    bRet = VirtualProtect(addr, 0x1, g_dwOld, &g_dwOld);
    if (!bRet)
    {
        return FALSE;   
    }
    return TRUE;

}

///////////////////////////////////////////////////////////////
/************************   打开格式  ************************/
///////////////////////////////////////////////////////////////

/************/

typedef struct FILTER
{
    char m_Comm;
    int m_Offset;
    char m_Nop;
}_FILTER, *PFILTER;


PCHAR g_lpszbuf = NULL;

_export __declspec(naked) void MyOpenHelpDocument()
{
  __asm
  {
    mov eax, g_lpszbuf
      mov dword ptr ss:[ebp - 0x2B68], eax
      ret
  }
}


//Hook代码
unsigned int g_pfilter = 0x476AD2;
#define SHOW_COUNT 5

BOOL RepairHelp()
{

  int i;
  FILTER Filter;
  unsigned int *pFilterAddress = (unsigned int*)g_pfilter;
  DWORD dwOld = 0;
  int nCount = 0;
  PCHAR pTemp = 0;
  g_lpszbuf = (PCHAR)malloc(MAXBYTE);
  if (g_lpszbuf == NULL)
  {
    return -1;
  }



  memset(g_lpszbuf, 0, MAXBYTE);
  //新过滤字符串 
  PCHAR Temp[SHOW_COUNT];
  Temp[0] = "*.chm 文件(*.chm)";
  Temp[1] = "*.chm";

  Temp[2] = "帮助文件(*.hlp)";
  Temp[3] = "*.hlp";

  Temp[4] = "任何文件(*.*)";
  Temp[5] = "*.*";


  pTemp = g_lpszbuf;
  //拷贝准备好的过滤字符串到malloc开辟出来的空间中 
  for (i = 0; i < SHOW_COUNT + 1; i++)
  {

    strcpy(pTemp, Temp[i]);

    nCount = strlen(Temp[i]) + 1;

    pTemp += nCount;     
  }
  OutputDebugStringA("Check it!");

  //准备Hook指令 (Filter是一个全局变量,自定义的一个6字节结构体)
  Filter.m_Comm = 0xE8;
  Filter.m_Offset = (int)MyOpenHelpDocument - g_pfilter - 5;

  //原始指令是6个字节,我们修改为JMP后是5字节,所以最后一字节修改为NOP
  Filter.m_Nop = 0x90;

  dwOld = 0;
  //打开内存保护并使用memcpy拷贝指令到目标位置,然后还原内存属性
  int nRet = VirtualProtect((void*)g_pfilter, 6, PAGE_EXECUTE_READWRITE, &dwOld);
  if (nRet == 0)
  {
    MessageBox(NULL, "Error", "SetHookFail", MB_OK);
    return -1;
  }
  memcpy((void*)g_pfilter, (void*)&Filter, sizeof(Filter));


  nRet = VirtualProtect((void*)g_pfilter, 6, dwOld, &dwOld);
  if (nRet == 0)
  {
    return -1;
  }


  return TRUE;
}


///////////////////////////////////////////////////////////////
/************************ F1 帮助文档 ************************/
///////////////////////////////////////////////////////////////


typedef LRESULT  (__stdcall *CALLWINDOWPROC)
(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);

CALLWINDOWPROC pfnNextProcCall;

//新的过程函数
LRESULT MyCallWindowProc(
                                                 HWND hWnd,              // handle to window
                                                 UINT uMsg,               // message
                                                 WPARAM wParam,          // first message parameter
                                                 LPARAM lParam
                                                 )
{

    DWORD wNotifyCode = HIWORD(wParam);
    DWORD dwID = LOWORD(wParam);
    if (uMsg == WM_KEYDOWN)
    {
        if (dwID == VK_F1)
        {
            OutputDebugString("F1");
            PostMessage(hWnd, WM_COMMAND, 0x9C8, NULL);
            return TRUE;
        }


    }

    return CallWindowProc(pfnNextProcCall, hWnd, uMsg, wParam, lParam);
}

BOOL F1Help(HWND hw)
{

    pfnNextProcCall = (CALLWINDOWPROC)GetWindowLong(hw, GWL_WNDPROC);
    if (pfnNextProcCall == 0)
    {
        OutputDebugString("GetWindowLong False ");
        return FALSE;
    }

    //Hook窗口过程
    if (SetWindowLong(hw, GWL_WNDPROC, (long)MyCallWindowProc) == 0)
    {
        OutputDebugString("MyCallWindowProc False");
        return FALSE;
  }

    return TRUE;
}


///////////////////////////////////////////////////////////////
/********************** OD 插件必须函数 **********************/
///////////////////////////////////////////////////////////////


extc int _export cdecl ODBG_Plugindata(char shortname[32]) {
  strcpy(shortname,"MyPlug");       // Name of plugin
  return PLUGIN_VERSION;
};


extc int _export cdecl ODBG_Plugininit(
                                       int ollydbgversion,HWND hw,ulong *features) {

  // Check that version of OllyDbg is correct.
  if (ollydbgversion<PLUGIN_VERSION)
    return -1;

  BOOL bRet = RepairClsProc();
  if (bRet == FALSE)
  {
      MessageBox(NULL, "Error", "Load Fail!", MB_OK);
      return -1;
  }

  bRet = RepairHelp();
  if (bRet == FALSE)
  {
        MessageBox(NULL, "Error", "Load Fail!", MB_OK);
    return -1;
  }

    bRet = F1Help(hw);
  if (bRet == FALSE)
  {
        MessageBox(NULL, "Error", "Load Fail!", MB_OK);
    return -1;
  }

  return 0;
};

BOOL APIENTRY DllMain( HANDLE hModule, 
                       DWORD  ul_reason_for_call, 
                       LPVOID lpReserved
                     )
{
    return TRUE;
}
已标记关键词 清除标记
相关推荐
©️2020 CSDN 皮肤主题: 编程工作室 设计师:CSDN官方博客 返回首页