MetaTrader是一款外汇业务在线交易平台软件,个人感觉其界面非常人性化,操作起来也很方便。在国内其有很多种版本,如RBS MetaTrader,MetaTrader4,IBFSMetaTrader4等,刚好有一朋友需要扩展功能,因此就好好研究了下。

朋友在一证券公司上班,需用MetaTrader实现功能如下:

1,共有10台机器,其中一台为服务器,另9台为客户机。

2,当服务器切换币种汇率或图表等窗口时,客户机也需相应地切换。

3,服务器可设定每隔几分钟在几种选定的币种中切换窗口或更换图表,此时客户机也需相应操作。

简单说说实现方法:

1,用ollydbg和IDA逆出MetaTrader的大概工作流程,发现当切换窗口或更换图表是运用发送消息的方式。截取对应的消息值和消息句柄。

2,简单地利用UDP通信实现服务器与客户机的同步。

3,当拦截到服务器有切换窗口或更换图表的操作时,即拦截其操作,把拦截到的参数值作为参数用UDP协议传送到客户机,客户机接到相应命令后即实行相应操作。

简单地摘出程序分析:

UINT PatchProcess(LPVOID ThreadParam)
{
CEmbededWizardPatchDlg* wndProgress = (CEmbededWizardPatchDlg *) ThreadParam;//把它变成CSCommTestDlg这个类的指针
ASSERT(wndProgress);
ASSERT(wndProgress->IsKindOf(RUNTIME_CLASS(CEmbededWizardPatchDlg)));
HWND hwnd;
CString strTemp=_T(""),strTitle=_T("NULL");

CString strWindowName[21] =
{
"EURUSD",//0
"USDJPY",//1
"GBPUSD",//2
"AUDUSD",//3
"USDCHF",//4
"USDCAD",//5
"NZDUSD",//6
"EURAUD",//7
"EURCHF",//8
"EURGBP",//9
"EURJPY",//10
"GBPCHF",//11
"GBPJPY",//12
"GOLD",//13
"SILVER",//14
"CL",//15
"USDX",//16
"DJI",//17
"NASDAQ",//18
"HSI",//19
"S&P500"//20
};

STARTUPINFO si ;
PROCESS_INFORMATION pi ;
ZeroMemory(&si, sizeof(STARTUPINFO)) ;
ZeroMemory(&pi, sizeof(PROCESS_INFORMATION)) ;
si.cb = sizeof(STARTUPINFO) ;

BOOL WhileDoFlag=TRUE;
BYTE ReadBuffer[MAX_PATH]={0};
BYTE dwINT3code[1]={0xCC};
BYTE dwWindowBreadPointOldbyte[1]={0};
BYTE dwTemplateBreadPointOldbyte[1]={0};

if( !CreateProcess(SZFILENAME,
NULL,
NULL,
NULL,
FALSE,
DEBUG_PROCESS|DEBUG_ONLY_THIS_PROCESS,
NULL,
NULL,
&si,
&pi )
)
{
MessageBox(NULL, "CreateProcess Failed.", "ERROR", MB_OK);
return FALSE;
}

DEBUG_EVENT DBEvent ;
CONTEXT Regs ;
DWORD dwState,Oldpp;

Regs.ContextFlags = CONTEXT_FULL | CONTEXT_DEBUG_REGISTERS ;

while (WhileDoFlag) {
WaitForDebugEvent (&DBEvent, INFINITE);
dwState = DBG_EXCEPTION_NOT_HANDLED ;
switch (DBEvent.dwDebugEventCode)
{
case CREATE_PROCESS_DEBUG_EVENT:
//如果进程开始,则将断点地址的代码改为INT3中断,同时备份原机器码
ReadProcessMemory(pi.hProcess, (LPCVOID)(BREAK_POINT_NEWWINDOW), &dwWindowBreadPointOldbyte, sizeof(dwWindowBreadPointOldbyte), NULL) ;
VirtualProtectEx(pi.hProcess, (LPVOID)BREAK_POINT_NEWWINDOW, 1, PAGE_EXECUTE_READWRITE, &Oldpp);
WriteProcessMemory(pi.hProcess, (LPVOID)BREAK_POINT_NEWWINDOW,&dwINT3code, 1,NULL); //打补丁

ReadProcessMemory(pi.hProcess, (LPCVOID)(BREAK_POINT_TEMPLATE), &dwTemplateBreadPointOldbyte, sizeof(dwTemplateBreadPointOldbyte), NULL) ;
VirtualProtectEx(pi.hProcess, (LPVOID)BREAK_POINT_TEMPLATE, 1, PAGE_EXECUTE_READWRITE, &Oldpp);
WriteProcessMemory(pi.hProcess, (LPVOID)BREAK_POINT_TEMPLATE,&dwINT3code, 1,NULL); //打补丁

dwState = DBG_CONTINUE ;
break;

case EXIT_PROCESS_DEBUG_EVENT :
WhileDoFlag=FALSE;
wndProgress->PostMessage(WM_CLOSE,NULL,NULL );//关闭整个程序
break ;

case EXCEPTION_DEBUG_EVENT:
switch (DBEvent.u.Exception.ExceptionRecord.ExceptionCode)
{
case EXCEPTION_BREAKPOINT:
{
GetThreadContext(pi.hThread, &Regs) ;
if(Regs.Eip==BREAK_POINT_NEWWINDOW+1){//0x7C92120F BREAK_POINT_NEWWINDOW+1
//中断触发异常事件,这个是真正需要的中断。先恢复原机器码
Regs.Eip--;
WriteProcessMemory(pi.hProcess, (LPVOID)BREAK_POINT_NEWWINDOW,&dwWindowBreadPointOldbyte, 1,NULL);

进行真正需要的操作,把对应的栈地址写成需要的数据/
hwnd = ::FindWindow("MetaQuotes::MetaTrader::4.00",NULL);//第一个参数为类名,返回找到窗口的句柄
GetWindowText(hwnd,strTemp.GetBuffer(MAX_PATH),MAX_PATH);
if(strTemp.Find(strTitle)<0) //没有找到,表示可能跟之前菜单不一样
{
strTemp.ReleaseBuffer();
// int length1 = strTemp.GetLength();//注意,在GetLength前一定要先ReleaseBuffer。
int index1 = strTemp.Find("-");
int index2 = strTemp.Find(",");
if(index1 > 0 && index2 >0)//表示这个标题栏有相应信息
{

strTemp = strTemp.Mid(index1 + 2,index2 - index1 - 2);
index1 =strTemp.Find("-");
if(index1 > 0)
{
if(strTemp.Find("[")>0)
strTemp = strTemp.Right(strTemp.GetLength() - index1 - 3);
else
strTemp = strTemp.Right(strTemp.GetLength() - index1 - 2);
}else
{
if(strTemp.Find("[")>=0)
strTemp = strTemp.Right(strTemp.GetLength()-1);

}

if(strTemp != strTitle)
{
strTitle = strTemp;
strTemp = "WINDOW="+strTemp;
wndProgress->SendUDPMessage(strTemp);
}
}

}
/
//---------------------------设置另一个临时断点BREAK_POINT_NEWWINDOW_TEMP,相互设置,用来每次都能中断------------------
ReadProcessMemory(pi.hProcess, (LPCVOID)(BREAK_POINT_NEWWINDOW_TEMP), &dwWindowBreadPointOldbyte, sizeof(dwWindowBreadPointOldbyte), NULL) ;
VirtualProtectEx(pi.hProcess, (LPVOID)BREAK_POINT_NEWWINDOW_TEMP, 1, PAGE_EXECUTE_READWRITE, &Oldpp);
WriteProcessMemory(pi.hProcess, (LPVOID)BREAK_POINT_NEWWINDOW_TEMP,&dwINT3code, 1,NULL); //设置成INT3中断
SetThreadContext(pi.hThread, &Regs) ;
}
else if(Regs.Eip==BREAK_POINT_NEWWINDOW_TEMP+1){
//中断触发异常事件,这个中断仅仅是为了能设下面这个中断
Regs.Eip--;
WriteProcessMemory(pi.hProcess, (LPVOID)BREAK_POINT_NEWWINDOW_TEMP,&dwWindowBreadPointOldbyte, 1,NULL);//恢复操作
//---------------------------进行真正需要的操作,把对应的栈地址写成需要的数据

//---------------------------设置另一个临时断点,相互设置,用来每次都能中断------------------
ReadProcessMemory(pi.hProcess, (LPCVOID)(BREAK_POINT_NEWWINDOW), &dwWindowBreadPointOldbyte, sizeof(dwWindowBreadPointOldbyte), NULL) ;
VirtualProtectEx(pi.hProcess, (LPVOID)BREAK_POINT_NEWWINDOW, 1, PAGE_EXECUTE_READWRITE, &Oldpp);
WriteProcessMemory(pi.hProcess, (LPVOID)BREAK_POINT_NEWWINDOW,&dwINT3code, 1,NULL); //设置成INT3中断

SetThreadContext(pi.hThread, &Regs) ;

}

else if(Regs.Eip==BREAK_POINT_TEMPLATE+1){
//中断触发异常事件,这个中断仅仅是为了能设下面这个中断
Regs.Eip--;
WriteProcessMemory(pi.hProcess, (LPVOID)BREAK_POINT_TEMPLATE,&dwTemplateBreadPointOldbyte, 1,NULL);//恢复操作
//---------------------------进行真正需要的操作,把对应的栈地址写成需要的数据
strTemp.Format("%d",Regs.Edx);
strTemp = "TEMPLATE="+strTemp;
wndProgress->SendUDPMessage(strTemp);

//---------------------------设置另一个临时断点,相互设置,用来每次都能中断------------------
ReadProcessMemory(pi.hProcess, (LPCVOID)(BREAK_POINT_TEMPLATE_TEMP), &dwTemplateBreadPointOldbyte, sizeof(dwTemplateBreadPointOldbyte), NULL) ;
VirtualProtectEx(pi.hProcess, (LPVOID)BREAK_POINT_TEMPLATE_TEMP, 1, PAGE_EXECUTE_READWRITE, &Oldpp);
WriteProcessMemory(pi.hProcess, (LPVOID)BREAK_POINT_TEMPLATE_TEMP,&dwINT3code, 1,NULL); //设置成INT3中断

SetThreadContext(pi.hThread, &Regs) ;

}
else if(Regs.Eip==BREAK_POINT_TEMPLATE_TEMP+1){
//中断触发异常事件,这个中断仅仅是为了能设下面这个中断
Regs.Eip--;
WriteProcessMemory(pi.hProcess, (LPVOID)BREAK_POINT_TEMPLATE_TEMP,&dwTemplateBreadPointOldbyte, 1,NULL);//恢复操作
//---------------------------设置另一个临时断点,相互设置,用来每次都能中断------------------
ReadProcessMemory(pi.hProcess, (LPCVOID)(BREAK_POINT_TEMPLATE), &dwTemplateBreadPointOldbyte, sizeof(dwTemplateBreadPointOldbyte), NULL) ;
VirtualProtectEx(pi.hProcess, (LPVOID)BREAK_POINT_TEMPLATE, 1, PAGE_EXECUTE_READWRITE, &Oldpp);
WriteProcessMemory(pi.hProcess, (LPVOID)BREAK_POINT_TEMPLATE,&dwINT3code, 1,NULL); //设置成INT3中断

SetThreadContext(pi.hThread, &Regs) ;

}

dwState = DBG_CONTINUE ;
break;
}
}
break;
}

ContinueDebugEvent(pi.dwProcessId, DBEvent.dwThreadId, dwState) ;
} //.end while
CloseHandle(pi.hProcess) ;
CloseHandle(pi.hThread) ;
AfxGetMainWnd()->SendMessage(WM_CLOSE);
return TRUE;
}

MetaTrader软件的功能扩展(关于程序补丁制作的一个例子)相关推荐

  1. 小程序工程化实践(上篇)-- 手把手教你撸一个小程序 webpack 插件,一个例子带你熟悉 webpack 工作流程...

    本文基于 webpack 4 和 babel 7,Mac OS,VS Code 小程序开发现状: 小程序开发者工具不好用,官方对 npm 的支持有限,缺少对 webpack, babel 等前端常用工 ...

  2. python代码用c语言封装_使用C语言扩展Python程序的简单入门指引

    一.简介 Python是一门功能强大的高级脚本语言,它的强大不仅表现在其自身的功能上,而且还表现在其良好的可扩展性上,正因如此,Python已经开始受到越来越多人的青睐,并且被屡屡成功地应用于各类大型 ...

  3. Android设备新型恶意软件,融合银行木马、键盘记录器和移动勒索软件等功能

    2019独角兽企业重金招聘Python工程师标准>>> 网络犯罪分子目前正在开发一种针对Android设备的新型恶意软件,它融合了银行木马.键盘记录器和移动勒索软件的功能. 根据来自 ...

  4. 建立牢固的多功能Smartphone应用程序

    Smartphone对抗 Pocket PC Phone Edition 你也许听说过Pocket PC Phone Edition,它是另一个装备微软软件的电话.为了避免混乱,我将澄清Pocket ...

  5. 百万军中取上将首级如探囊取物, 千万行里改关键源码在弹指瞬间。 功能超强的程序编辑器!

    TSEPro11_Setup.exe 百万军中取上将首级如探囊取物, 千万行里改关键源码在弹指瞬间. 功能超强的程序编辑器! 为防内容被恶意篡改,参考 MD5 (TSEPro11_Setup.exe) ...

  6. 黑苹果驱动]Mac OS X Snow Lepard的内核功能扩展kext大致解析

    Kext是Mac OS 的硬件驱动,它存放位置在系统中:      /System/Library/Extensions/ #系统核心级别存放位置,系统自有驱动位置-      /Library/Ex ...

  7. Array王锐大神力作:osg与PhysX结合系列内容——第1节 PhysX核心功能及基本程序结构介绍

    [Array王锐大神力作]osg与PhysX结合系列内容--PhysX核心功能及基本程序结构介绍 本节内容 下载和编译PhysX PhysX的核心功能 PhysX的基本程序结构 PhysX与OSG结合 ...

  8. 【漆天编程】MetaTrader软件的前世今生

    MT4(MetaTrader4)是市场行情接收软件,由迈达克软件公司在2005 年 7 月1 日正式发布,提供免费试用,有中文界面.它包括先前系统所有的特点,并且对这些功能和组成部分进行了进一步的介绍 ...

  9. Emacs Lisp 功能扩展集锦

    From 参考 Emacs Lisp 功能扩展集锦 session.el desktop.el ibuffer.el browse-kill-ring.el ido.el tabbar.el spee ...

最新文章

  1. C/C++中判断两个变量是否相等,相减是否为0、大于0或小于0时要特别注意机器误差带来的影响
  2. Ansible基本使用及常用模块详解
  3. 在OUTLOOK或OWA中查看邮件的SCL级别(转)
  4. MySQL:8种SQL典型错误用法,值得收藏!
  5. python网络爬虫面试题,搞定这套Python爬虫面试题(面试会so easy)
  6. cmds在线重定义增加列
  7. 58天 -算法 openJudge百炼 2787-凑24 - 递归
  8. function与感叹号
  9. FluentAPI --- 用C#写的JS代码生成器
  10. 用户态处理arp、ndisc neighbour solication 报文
  11. 分布式系统中协调和复制技术的原理
  12. 浅谈最近公共祖先(LCA)
  13. 【雷达通信】基于matlab联邦滤波算法惯性+GPS+地磁组合导航仿真【含Matlab源码 1276期】
  14. 北京/苏州内推 | 微软亚洲互联网工程院招聘NLP算法工程师(可实习)
  15. java学习总结(16.06.07)类的静态成员和非静态成员
  16. win10计算机打开速度慢,win10电脑系统开机启动速度慢如何解决?
  17. 北京数码视讯s905l固件_数码视讯Q6联通版S905L芯片第三方刷机免拆卡刷固件
  18. Mysql连接命令join
  19. 软件测试与游戏测试的不同之处
  20. Camtasia2023简体中文版屏幕录像 支持MP4/AVI/WMV等多种格式

热门文章

  1. 1.3T计算机学科视频教程
  2. 一个整数,它加上100后是一个完全平方数,再加上168又是一个完全平方数
  3. MATLAB机器人工具箱(一 机器人运动学)
  4. Go unkown reversion问题解决
  5. 14.1 常见数据结构、List集合(ArrayList、LinkedList)、Set集合(HashSet、LinkedHashSet)、可变参数方法
  6. Windows+python3.6+Anaconda安装shogun包
  7. Matlab中ylim函数的使用
  8. PTA -- 题附代码(形状继承) (图形继承与多态)
  9. 计算机生物学专业大学排名,2021中国生物信息学专业大学排名 最好的高校排行榜...
  10. Python----------列表操作