文章编号:11115时间:2024-09-30人气:
标 题: MFC逆向初级研究(1)作 者: 北斗之摇光时 间: 2007-03-15 17:14 链 接:详细信息: 【文章标题】: MFC逆向初级研究(1)【文章作者】: 北斗之摇光【作者邮箱】: 【下载地址】: 自己搜索下载【作者声明】: 只是感兴趣,没有其他目的。 失误之处敬请诸位大侠赐教!--------------------------------------------------------------------------------【详细过程】引言本文主要针对微软的VC++6.0中使用MFC产生的EXE文件的逆向研究,我曾经使用微软的Visual Studio 2005编译了一个EXE文件,通过IDA反汇编以后发现该文件与VC++6.0产生的文件还是有所区别,因此特别在此声明一下。 文中主要使用了IDA pro 5.0和在看雪()下载的OllyICE作为工具对目标文件进行反汇编。 在此也感谢看雪论坛的各位的无私奉献,在研究过程的中的困难多通过各位的帖子得到了帮助。 逆向的关键我认为逆向的关键主要是要弄明白目标文件的算法和实现过程,在Window操作系统下,软件的实现过程就体现在其对Window消息的处理,而软件的算法则包含在处理的具体过程中。 对于通过SDK编写的传统的Windows应用程序基本都具备几个共同的特征:WinMain函数、WinProc函数、窗口注册、消息循环。 对于这类目标文件的分析主要集中的WinProc的分析上,WinProc的函数地址获得一般是通过窗口注册函数中的参数获得。 (由于我对于这类文件没有具体逆向过,所以只是大概的说说,有不对的地方请各位不要客气,尽管拍砖)而使用MFC(Microsoft Function Class)顾名思义,该类库主要封装了大部分的Windows API函数所以在代码中看不到原本的SDK编程中的消息循环、窗口过程函数等等东西,所有这些封装在相应的中,让程序员能够专著与处理过程与算法。 这种做法于逆向而言有好处也有坏处:坏处就是加大了对于MFC产生的EXE文件的逆向难度,让许多的和我一样的菜鸟迷失在汇编代码中找不找北了,基本主要就靠猜测实现过程中用到了那些函数,然后对文件导入表的函数下断点来寻找我们所需要的处理过程;好处就是这样的做法使得EXE文件中主要都是目标程序的Window消息处理流程以及算法,而且dll中的大部分函数的功能都能在MSDN中查到。 如果能够通过对目标文件的分析得到这个Window消息处理流程和算法架构,基本上我们就可以重写整个软件;要做到上面的目标,首先我们要对MFC有所了解,推荐没有基础的兄弟们读读候俊杰的《深入浅出MFC》。 该书在逆向过程中完全可以作为一本参考书,让你能通过源代码了解实现过程,网上有很多该书的电子版下载。 一个逆向MFC产生的EXE文件的例子下面我们就通过一个具体的例子来学习一下如何从目标文件中挖到我们需要的东西。 首先我们来产生一个需要的EXE文件。 在此我假定各位对MFC有过一定的使用经验,毕竟逆向分析才是本文的重点。 1.产生例子所需要的目标文件:我们通过VC++6.0的向导来产生一个名为ReverseMFC的工程,这个工程的设置情况如下: Application type of fff:Dialog-Based Application targeting:Win32Classes to be created:Application: CFffApp in ReverseMFC.h and : CFffDlg in ReverseMFCDlg.h and : + Uses shared DLL implementation () + Localizable Text in:中文[中国]直接编译以后就能够运行,为了确定我们是否正确的分析的整个目标文件,在该对话框中加入一个我们自定义的按钮如下,对于该按钮的处理函数如下设定为:AfxMessageBox(I find it!,MB_OK);编译后就得到了我们需要的目标文件。 现在我们得到了所需要的目标文件,在IDA中载入该文件。 在此我们最好是产生Release版本的EXE文件,毕竟所有的发布软件都是Release版本的。 2.具体分析在IDA中按Ctrl+S找到段,该段主要存储了目标文件的类运行时创建信息、MessageMap信息、MessageEntry信息、虚函数表、RTTI数据(如果编译选项中选择了支持RTTI的话)。 在到达段后我们可以看到这样的代码,对数据进行格式转换后可以得到如下图所示的数据。 C0 ; 屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯?C0 ; Segment type: Pure C0 ; Segment permissions: C0 _rdatasegment para public DATA C0 assume cs:_C0 ;org C0 off_4021C0dd offset sub_; DATA XREF: sub_C4 dd offset dword_C8 dword_4021C8dd 111h ; DATA XREF: C4CC dd D0 dd D4 dd D8 dd DC dd offset CWinApp::OnHelp(void)E0 dd E4 dd E8 dd EC dd F0 dd F4 dd F8 off_4021F8dd offset CWinApp::GetRuntimeClass(void)F8 ; DATA XREF: unknown_libname_1-56FC dd offset sub_ dd offset nullsub_ dd offset nullsub_ dd offset nullsub_C dd offset CCmdTarget::OnCmdMsg(uint,int,void *,AFX_CMDHANDLERINFO *)其中的off_4021C0就是一个MessageMap数据;dword_4021C8就是MessageMap所指的MessageEntry数据;off_4021F8就是一个类的虚函数表的开始位置。 那么具体这些数据时那个类的相关数据呢?如此判断的依据是什么?首先我们知道MessageEntry是的数据结构定义如下,而且以6个0表示整个数组的结束。 struct AFX_MSGMAP_ENTRY{UINT nMessage; // windows messageUINT nCode;// control code or WM_NOTIFY codeUINT nID;// control ID (or 0 for windows messages)UINT nLastID;// used for entries specifying a range of control idsUINT nSig; // signature type (action) or pointer to message #AFX_PMSG pfn;// routine to call (or special value)};因此我们有理由假设dword_4021C8就是MessageMap所指的MessageEntry数据。 而MessageMap数据结构定义如下:struct AFX_MSGMAP{#ifdef _AFXDLLconst AFX_MSGMAP* (PASCAL* pfnGetBaseMap)();#elseconst AFX_MSGMAP* pBaseMap;#endifconst AFX_MSGMAP_ENTRY* lpEntries;};off_4021C0的两个数据中第二个数据恰恰就是我们前面假设为MessageEntry的指针,跟入其第一个数据,我们看到如下的代码 ; *************** S U B R O U T I N E *************************************** sub_proc near ; DATA XREF: :off_4021C0 mov eax, ds:AFX_MSGMAP const sub_endp恰恰是一个返回基类的MessageMap的函数。 因此我们也同样有理由假设off_4021C0就是一个MessageMap数据。 对于虚函数表的假设是如何被证明呢?首先我们要知道关于虚函数表的一点知识:虚函数表由虚函数的地址组成,表中函数地址的顺序和它们第一次出现的顺序(即在类定义的顺序)一致。 若有重载的函数,则替换掉基类函数的地址。 通过这个我们可以知道MFC中虚函数表中的函数顺序必然是先按照CObject->CCmdtarget->。 。 。 。 这个类继承顺序中的虚函数顺序来处理虚函数表中的函数顺序的。 只要证明这个我们假设的虚函数中的函数顺序与上面提到的知识相符合则有理由说明我们的假设成立。 首先来看CObject中虚函数的顺序,在查看CObject的声明文件后得到了这个类的虚函数顺序:virtual CRuntimeClass* GetRuntimeClass() const;virtual ~CObject();// virtual destructors are necessaryvirtual void Serialize(CArchive& ar);#if defined(_DEBUG) || defined(_AFXDLL)// Diagnostic Supportvirtual void AssertValid() const;virtual void Dump(CDumpContext& dc) const;再来查看CCmdtarget的虚函数顺序,在查看CObject的声明文件后得到了这个类的虚函数顺序:DECLARE_DYNAMIC(CCmdTarget);virtual BOOL OnCmdMsg(UINT nID, int nCode, void* pExtra,AFX_CMDHANDLERINFO* pHandlerInfo);#ifndef _AFX_NO_OLE_SUPPORT// called when last OLE reference is releasedvirtual void OnFinalRelease();#endif#ifndef _AFX_NO_OLE_SUPPORT// called before dispatching to an automation handler functionvirtual BOOL IsInvokeAllowed(DISPID dispid);virtual BOOL GetDispatchIID(IID* pIID);virtual UINT GetTypeInfoCount();virtual CTypeLibCache* GetTypeLibCache();virtual HRESULT GetTypeLib(LCID lcid, LPTYPELIB* ppTypeLib);之所以还要列出DECLARE_DYNAMIC(CCmdTarget);是因为这个宏的定义如下:#define DECLARE_DYNAMIC(class_name) \protected: \static CRuntimeClass* PASCAL _GetBaseClass(); \public: \static const AFX_DATA CRuntimeClass class##class_name; \virtual CRuntimeClass* GetRuntimeClass() const; \这个virtual CRuntimeClass* GetRuntimeClass() const; 覆盖掉了一开始的CObject的相对应函数。 依次按照类的顺序对照下来,就可以知道该表确实是虚函数表。 同时,对应的GetMessageMap虚函数的位置上跟入后,可以得到如下代码 ; *************** S U B R O U T I N E *************************************** sub_proc near ; DATA XREF: mov eax, offset off_ sub_endp恰恰是返回了我们之前假设的MessageMap的地址。 --------------------------------------------------------------------------------【版权声明】: 本文原创于看雪技术论坛, 转载请注明作者并保持文章的完整, 谢谢!
VC6.0, VisualC++2010, Visual Studio的区别VC6.0,全称Microsoft Visual C++ 6.0.三者的中,VC6最老,几乎是上世纪90年代的玩意了。 超期服役到WindowsXP。 兼容性差。 Visual C++2010是一个运行时库(Run time library),用于支持游戏等。 此外,Visual C++ 2010 Express是一款编译器。 比VC+6.0要先进。 但是大部分人没有用过。 Visual Studio, 全称Microsoft Visual Studio。 是当今微软提供的,最先进的编译器。 最新版本VS2015可以编译Windows 10应用程序。 Visual Studio当今(2016年7月28日)最新稳定版本为Microsoft Visual Studio 分为3个版本Visual StudioTeam Services 收费版本,适于团队开发。 Visual Studio Community 面向60亿人民群众的免费开发工具Visual Studio Code重新定义了 Code 编辑。 编写现代 Web 程序和云程序。 免费。 备注: *VC6最小最简洁,只要十几M。 而Visual Studio至少7个G. *VC6写的程序可以从Windows XP 开到Win10. 而Visual Studio的程序需要运行时库,否则会发生“Runtime Library Runtime Error”。 不能在WinXP运行。 当然你可以在编译选项设置他们,但会增加程序体积.
Microsoft Visual C++ Redistributable Package是Visual C++的运行时组件和库,很多软件,尤其是游戏所必须的 Microsoft VC++ 的环境软件,这些游戏就是用VC+编写的,所以安装很多大型游戏的时候,它也会帮你安装这些软件。
如果要卸载的话可以选择9.0.0之前版本的Visual C++,因为此版本之前的库绝大多数是为2010年之前的软件提供API,若卸载了不会影响绝大多数近期更新的软件,但是不否认有新软件还需要的特例,所以只有在必须的时候才选择卸载。
程序编译版本不一样需要的运行组件版本也不一样,所以不建议删除,但是删除之后也可以到微软的官网上下载,再次安装。
Microsoft Visual C++,(简称Visual C++、MSVC、VC++或VC)是Microsoft公司推出的以C++语言为基础的开发Windows环境程序,面向对象的可视化集成编程系统。
它不但具有程序框架自动生成、灵活方便的类管理、代码编写和界面设计集成交互操作、可开发多种程序等优点,而且通过的设置就可使其生成的程序框架支持数据库接口、OLE2.0,WinSock网络。
Microsoft Visual C++ 6.0,简称VC6.0,是微软于1998年推出的一款C++编译器,集成了MFC 6.0,包含标准版(Standard Edition)、专业版(Professional Edition)与企业版(Enterprise Edition)[2]。 发行至今一直被广泛地用于大大小小的项目开发。
Microsoft Visual C++ 6.0对windows7和windows8的兼容性较差。 在Windows7使用VC6.0只需要忽略兼容性提示即可正常使用,但是在Windows8(含Windows8.1)使用VC6.0则需要改原文件名并改兼容性才能正常使用。
在Windows10的第一个版本也可以正常使用VC6.0,但Windows10系统升级更新后中文版VC6.0无法正常使用,提示“0xc”的错误,需要将原文件替换为英文版或者汉化版才能正常使用。
不同的地方很多,具体你可以看msdn上的vs2013的对于C++部分的改进。
我想你的VC++指的应该是VC6.0。
相比来说VC6.0太老了。
在VS2013里使用的是最新的标准,也有好多新的特性,也更安全。
本文档介绍 Visual Studio 2013 中的 Visual C++ 中新增和增强的功能。
有关 Visual Studio 2013 中其他附加内容的信息,请参见 Visual Studio 2013 中的新增功能。
改进的 ISO C/C++ 标准支持 编译器支持以下 ISO C++11 语言功能:函数模板的默认模板参数。
委托构造函数显式转换运算符。
初始值设定项列表和统一初始化。
原始字符串文本。
可变参数模板。
别名模板。
已删除的函数。
非静态数据成员初始值设定项 (NSDMI)。
默认的函数。
* 支持以下 ISO C99 语言功能:_Bool 复合文本。
指定的初始值设定项。
组合带有代码的声明。
字符串文本转换为可修改的值可通过使用新编译器选项 /Zc:strictStrings 禁用。
在 C++98 中,已弃用从字符串文本转换至 char *(和将宽字符串文本转换为 wchar_t *)。
在 C++11 中,已将转换完全移除。
虽然编译器可以严格遵循该标准,但提供了 /Zc:strictStrings 选项,以便你控制转换。
默认情况下,该选项是关闭的。
注意,当你在调试模式下使用此选项,STL 将无法编译。
rvalue/lvalue 引用转换。
通过 rvalue 引用,C++11 可清晰地区分 lvalue 和 rvalue。
过去,在特定强制转换方案中,Visual C++ 编译器不提供此功能。
已添加新编译器选项(/Zc:rvalueCast),以使编译器与 C++ 语言的工作文件相符,(请参见第 5.4 节,[]/1)。
未指定选项时,该默认行为与 Visual Studio 2012 中的相同。
说明* 默认功能下,不支持使用 =default 逐一请求成员移动构造函数和移动赋值运算符。
C99 库为下列标头中缺少的函数添加了声明和实现:math.h、ctype.h、wctype.h、stdio.h、stdlib.h 和 wchar.h。
同样添加的还有新标头 complex.h、stdbool.h、fenv.h 和 inttypes.h,以及在这些新标头中声明的所有功能的实现。
还有新的 C++ 包装器标头(ccomplex、cfenv、cinttypes、ctgmath),并且更新了许多其他内容(ccomplex、cctype、clocale、cmath、cstdint、cstdio、cstring、cwchar和 cwctype)。
有关更多信息,请参见 Visual Studio 2013 中的 C99 库支持。
标准模板库支持 C++11 显式转换运算符、初始值设定项列表、范围枚举和 variadic 模板。
现在所有容器都支持 C++11 细化的元素要求。
支持这些 C++14 功能: “透明运算符函子”less<>、greater<>、plus<>、multiplies<> 等。
make_unique
因为VC6太经典,太成功了。 vc6很适合做底层,运行速度也很快。 相同的程序功能对比如下:1.高版本vs编译的程序如果需要800M内存,20M磁盘空间,运行速度1秒的话,2.使用vc6可以将所需内存降到100M,磁盘空间降低到5M,运行速度<0.5秒。 3.安装包你keyi 比较以下,vs动则x个G,vc6精简版只有25M,即使完整版也只有200多M。 4.高版本vs增加了很多华丽的东西,为了减少编写代码的工作量,但是也阻断了程序员了解操作系统底层。 这就好比使用现代化的工具盖楼,【开发】速度加快了,但是不清楚大楼的组成成分。 而vc6则需要自己一砖一瓦地来盖楼,开发者对每个零件都很清楚。 这就是为什么我们现代化的大楼只有70年的使用寿命,而北京紫禁城可以屹立数百年乃至上千年不倒。 建议题主看一下64k编程大赛的作品【国外的一个考验编程者能力、技巧、运行优化 水平的大赛,参赛作品大小不能超过64K,还要呈现很多画面内容】。 相信你会感到惊奇的。
内容声明:
1、本站收录的内容来源于大数据收集,版权归原网站所有!
2、本站收录的内容若侵害到您的利益,请联系我们进行删除处理!
3、本站不接受违法信息,如您发现违法内容,请联系我们进行举报处理!
4、本文地址:http://www.jujiwang.com/article/7eeeb21df83f690f6864.html,复制请保留版权链接!
概述在Python中,str.split,函数是一个强大的工具,用于根据指定的分隔符将字符串拆分为多个子字符串,它在字符串处理和数据解析等各种任务中非常有用,基础语法str.split,函数的语法如下,str.split,sep=None,maxsplit=,1,sep,可选参数,指定分隔符,默认情况下,它将字符串按照空格字符拆分...。
技术教程 2024-09-28 17:42:10
为了确保应用程序在所有支持的方向下都能提供良好的用户体验,测试应用程序中的模拟器是至关重要的,模拟器模拟器是一种软件工具,它可以模拟实际设备的行为,它允许开发人员在不拥有实际设备的情况下测试他们的应用程序,有很多不同的模拟器可用,每个模拟器都有自己的优点和缺点,以下是一些最流行的模拟器,Android模拟器iOS模拟器WindowsP...。
最新资讯 2024-09-25 20:16:28
鼠标跟踪文字,激活阅读体验导言鼠标跟踪文字,MTF,是一种数字文本技术,允许读者在光标移动时突出显示文本,这种交互式功能增强了阅读体验,让文字仿佛具有生命,身临其境,本文将探讨MTF的功能和好处,并提供关闭它的方法,鼠标跟踪文字的功能MTF的主要功能是通过光标运动来突出显示文本,当读者将光标悬停在单词或句子上时,它会被高亮显示,使其比...。
技术教程 2024-09-24 18:47:33
在网页设计中,div,块级元素,是用于创建和管理内容布局的基础元素之一,它提供了一种灵活的方法来组织和显示文本、图像和交互式元素,当div的内容超过其可用空间时,需要使用滚动条来浏览内容样式来实现滚动条,以下是如何实现水平和垂直滚动条,水平滚动条<,divstyle=overflow,x,scroll,>,<,p>,这...。
技术教程 2024-09-23 04:14:21
在当今快节奏的商业环境中,企业必须不断寻找提高运营效率的方法,自动化流程是一个强大的工具,可以帮助企业节省时间、金钱并提高准确性,自动化的优势节省时间,自动化流程可以帮助企业节省宝贵的时间,通过消除手动任务,企业可以将员工从繁琐、重复性的任务中解放出来,从而专注于更重要的工作,节省金钱,自动化流程还可以帮助企业节省资金,通过减少对人员...。
互联网资讯 2024-09-16 16:52:09
语法错误是计算机程序中的一种错误,它违反了编程语言的语法规则,语法错误会导致程序无法编译或运行,并且会产生错误消息,语法错误通常很容易检测到,可以通过仔细检查程序中的代码来发现,语法错误的常见类型缺少分号,分号是C、Java和Python等编程语言中语句结束的标志,如果缺少分号,程序将无法编译或运行,括号不匹配,括号用于将代码分组,如...。
互联网资讯 2024-09-15 01:22:06
定义单选按钮,又称单选框,是一种用于在一组选项中只能选择一个选项的控件,它通常由一个圆圈或方框以及一个标签组成,标签表示选项的详细信息,特性互斥,同一组中的单选按钮互斥,这意味着一次只能选择一个选项,可见标签,单选按钮的标签清晰可见,以便用户能够轻松识别选项,单击激活,单选按钮通过单击激活,选中它将取消选中其他同组的单选按钮,表单提交...。
最新资讯 2024-09-14 17:47:00
简介RANK函数用于在指定范围内对一组数据进行排名,并将排名结果返回为一个包含排名值的数组,它广泛应用于数据分析、统计和排名系统中,可以帮助我们轻松地识别最大值、最小值或指定范围内的相对位置,语法RANK函数的语法如下,RANK,number,range,[order],number,要进行排名的数字或单元格引用,range,要从中进...。
互联网资讯 2024-09-12 12:50:02
PHP是一款开源的web开发语言,拥有一个庞大而活跃的社区,为PHP开发人员提供丰富的资源和支持,文档PHP社区维护着大量的官方文档,包括,语言手册,全面介绍PHP语法、函数和类框架手册,指导使用流行的PHP框架,如Laravel和Symfony扩展文档,列出可用扩展及其用法这些文档由PHP团队维护,并不断更新,以反映语言和框架的最新...。
技术教程 2024-09-12 02:27:23
Java是一种广泛使用的高级编程语言,用于开发各种应用程序,从桌面软件到移动应用程序,它是现代编程中的基石,拥有庞大的开发者社区和大量的资源,黑马Java培训优势系统化学习,黑马的Java课程按照循序渐进的顺序设计,涵盖了Java编程的基础知识到高级概念,实战项目驱动,您将通过动手实践项目掌握Java技术,解决实际问题并构建自己的应用...。
互联网资讯 2024-09-11 11:40:19
深入剖析、实战案例、专家建议Windows网络编程一直是一个复杂且具有挑战性的话题,但是,有了正确的指导,即使是最复杂的任务也能变得容易掌握,这就是,Windows网络编程权威指南,诞生的原因,这本书由Windows网络编程专家撰写,提供了对Windows网络编程的全面而深入的介绍,它涵盖了从基础概念到高级技术的所有内容,包括,Win...。
本站公告 2024-09-10 12:03:16
引言多线程编程是Java编程的重要组成部分,它允许程序同时执行多个任务,通过利用多线程,开发人员可以显著提高应用程序的性能和响应能力,Java多线程的实现方式在Java中,可以通过以下方式创建和管理线程,实现Runnable接口,创建一个实现Runnable接口的类,该接口包含一个run,方法,该方法定义了线程执行的任务,扩展Thr...。
最新资讯 2024-09-06 10:03:26