昨天翻了下看雪论坛的精华9,发现一篇“类的逆向分析”文章,觉得有些意思,给大家看看

rageliu 2008-07-01 10:04:17
加精
问题如下
seg000:00443EDE mov eax, ds:dword_A14E68
seg000:00443EE3 mov eax, [eax+2D4h]
seg000:00443EE9 mov edx, [eax+32040h]
seg000:00443EEF push ebx
seg000:00443EF0 mov ebx, [ecx]
seg000:00443EF2 push esi
seg000:00443EF3 lea ecx, [eax+32040h]
seg000:00443EF9 push edi
seg000:00443EFA call dword ptr [edx+8]

对于这个全局变量 ds:dword_A14E68地址 存放的值 经过一系列变换最后 call dword ptr [edx+8] 我想知道对于这个ds:dword_A14E68地址里面的值应该怎么看,是理解为类指针吗?还是什么?


--------------------------------------------------------------------------------

一个答复为:

class A14E68
{
UnkownClass *cls2D4;
}
class UnkownClass
{
UnkownClass2 cls32040;
}
class UnkownClass2
{
virtual void func1();
virtual void func2();
virtual void func3(void arg1,void arg2,void arg3);
}

call [edx+8] 等于:
A14E68 test;
test.cls2D4->cls32040.func3(arg1,arg2,arg3);

#####################################################################################

大家认为这个答案对吗?如果不对你认为应该是怎么样的?
...全文
4877 125 打赏 收藏 转发到动态 举报
写回复
用AI写文章
125 条回复
切换为时间正序
请发表友善的回复…
发表回复
  • 打赏
  • 举报
回复
mark
yequancha 2011-08-18
  • 打赏
  • 举报
回复
总之我是看不懂···
w20011025 2011-07-10
  • 打赏
  • 举报
回复
对象调用虚函数为什么要用虚表呢?因为调用的时候已经很清楚是什么类型的对象了,就用不着虚函数了吧?多态只能通过对象指针或引用来体现吧?为确认一下我用vs2005做了如下测试:


C/C++ code

class Test
{
public:
int b;
virtual int test();
};

int Test::test()
{
cout<<b<<endl;
return 1;
}

int main()
{
Test test;
Test *ptest = &test;
test.test();
ptest->test();
}


下面是main函数反汇编内容

Assembly code

int main()
{
00401940 push ebp
00401941 mov ebp,esp
00401943 sub esp,0Ch
Test test;
00401946 lea ecx,[test]
00401949 call Test::Test (401000h)
Test *ptest = &test;
0040194E lea eax,[test]
00401951 mov dword ptr [ptest],eax
test.test();
00401954 lea ecx,[test]
00401957 call Test::test (401900h) ;可以看出这里没有使用虚表的,因为对象类型是在编绎期确定的。
ptest->test();
0040195C mov ecx,dword ptr [ptest] ;ecx为对象地址
0040195F mov edx,dword ptr [ecx] ;edx为虚表地址
00401961 mov ecx,dword ptr [ptest] ;ecx为对象地址
00401964 mov eax,dword ptr [edx] ;dword ptr [edx]就是虚表中的第一个函数地址,也就是test()
00401966 call eax
}



上面只是在vs2005上做的试验,并且是 debug版的,但我觉得已经可以说明问题了,对象调用虚函数一般化是不会用虚表的。
study
  • 打赏
  • 举报
回复
mark
xiaoshiquan 2011-05-23
  • 打赏
  • 举报
回复
看雪论坛呀,大学时候经常去逛逛呀!
xiaoshiquan 2011-05-23
  • 打赏
  • 举报
回复
先mark~~

wv136 2010-04-14
  • 打赏
  • 举报
回复
不懂汇编,更不懂反汇编.mark..为什么我每次回复就要登录一次???郁闷
做鸡真好吃 2009-08-21
  • 打赏
  • 举报
回复
mark
clever101 2009-08-05
  • 打赏
  • 举报
回复
不懂逆向工程,学习一下。
jiqing_gao 2008-07-08
  • 打赏
  • 举报
回复
学习
Amuro1987218 2008-07-08
  • 打赏
  • 举报
回复
还在讨论啊,顶顶
rageliu 2008-07-08
  • 打赏
  • 举报
回复
[Quote=引用 114 楼 DarknessTM 的回复:]
TO:red_berries
TO:rageliu

看到上面的虚函数调用没……
[/Quote]

这个问题,上面red_berries已解释
red_berries 2008-07-07
  • 打赏
  • 举报
回复
[Quote=引用 114 楼 DarknessTM 的回复:]
TO:red_berries
TO:rageliu

看到上面的虚函数调用没……
[/Quote]

A *b = new B();
b->method1(5);
你的是使用对象来调用虚函数的吗?我说的是使用对象调用虚函数时不使用虚表,你使用的是对象指针。


A a;
a.method1(5);

B b;
b.method1(5);

这个肯定不会用虚表的
ke2007lin 2008-07-07
  • 打赏
  • 举报
回复
[Quote=引用 2 楼 sanshao27 的回复:]
mark
[/Quote]
DarknessTM 2008-07-07
  • 打赏
  • 举报
回复
TO:red_berries
TO:rageliu

看到上面的虚函数调用没……
DarknessTM 2008-07-07
  • 打赏
  • 举报
回复

class A
{
public:
int x;
A()
{
x =2;
}

virtual ~A()
{

}

virtual int method1(int y)
{
return x + y;
}

virtual int method2(int y)
{
return x * y;
}
};


class B : public A
{
public:

virtual ~B()
{

}

virtual int method1(int y)
{
return x * y;
}

virtual int method2(int y)
{
return x + y;
}
};

int _tmain(int argc, _TCHAR* argv[])
{
A *b = new B();
b->method1(5);

return 0;
}



A *b = new B();
0040101B push 8
0040101D call operator new (4011ACh)
00401022 add esp,4
00401025 mov dword ptr [ebp-18h],eax
00401028 mov dword ptr [ebp-4],0
0040102F cmp dword ptr [ebp-18h],0
00401033 je main+42h (401042h)
00401035 mov ecx,dword ptr [ebp-18h]
00401038 call B::B (401080h)
0040103D mov dword ptr [ebp-1Ch],eax
00401040 jmp main+49h (401049h)
00401042 mov dword ptr [ebp-1Ch],0
00401049 mov eax,dword ptr [ebp-1Ch]
0040104C mov dword ptr [ebp-14h],eax
0040104F mov dword ptr [ebp-4],0FFFFFFFFh
00401056 mov ecx,dword ptr [ebp-14h]
00401059 mov dword ptr [b],ecx
b->method1(5);
0040105C push 5
0040105E mov edx,dword ptr [b]
00401061 mov eax,dword ptr [edx]
00401063 mov ecx,dword ptr [b]
00401066 call dword ptr [eax+4]

return 0;
00401069 xor eax,eax
imcreasy 2008-07-07
  • 打赏
  • 举报
回复
同意你的分析

第一次看见类的逆向分析的东西。
汇编忘得差不多了,不过简单的还是认得。
可是看见通过几句汇编结合构造特性加上其他经验,能分析出这么多,
还真是感慨啊!

以后有机会也玩玩。貌似很要求基础实力啊。

崇拜一个。
[Quote=引用 47 楼 mxlmwl 的回复:]
seg000:00443EDE mov eax, ds:dword_A14E68
seg000:00443EE3 mov eax, [eax+2D4h]
seg000:00443EE9 mov edx, [eax+32040h]
seg000:00443EEF push ebx
seg000:00443EF0 mov ebx, [ecx]
seg000:00443EF2 push esi
seg000:00443EF3 lea ecx, [eax+32040h]
seg000:00443EF9 …
[/Quote]
yanziguosan 2008-07-07
  • 打赏
  • 举报
回复
默默
feilinhe 2008-07-06
  • 打赏
  • 举报
回复
偶懂汇编和c++,但是不懂逆向分析,学习了一下嘿嘿
jingtan 2008-07-06
  • 打赏
  • 举报
回复
seg000:00443EF3 lea ecx, [eax+32040h]
seg000:00443EF9 push edi
seg000:00443EFA call dword ptr [edx+8]

一般来说ecx是对象地址。因为这里edx = ecx。我认为 dword ptr [edx+8] 是对象里的一个类型为函数指针的数据成员,而不是虚函数表中的一个项。
加载更多回复(105)
逆向编译技术 原文: Reverse Compilation Techniques 作者: Cristina Cifuentes 下载: http://www.itee.uq.edu.au/~cristina/dcc.html 译: 月中人 【看雪论坛】 时间: 2007-5-1 摘要 本论文提出逆向编译器或反编译器的编写技术。这些技术基于编译器和优化理论,并以独特的方式应用于反编译;这些技术以前从未被公开发表。 反编译器由几个阶段组成,即被组织成与语言或机器特征相关的几个模块。前端是一个机器依赖的模块,句法分析二进制程序、分析其指令的语义、并且生成该程序的低级中间表示法和每一子程序的控制流向图。通用的反编译机器是一个与语言和机器无关的模块,分析低级中间代码,将它转换成对任何高级语言都可接受的高级表示法,并且分析控制流向图的结构、把它们转换成用高级控制结构表现的图。最后,后端是一个目标语言依赖的模块,生成目标语言代码。 反编译的过程中要使用一些工具:把二进制程序装入内存,对这一程序做句法分析或反汇编,以及反编译或者分析该程序来生成高级语言程序。这个过程借助编译器和库的签名来识别特定的编译器和库子程序。只要在二进制程序中识别出编译器签名,就不去反编译这些编译器启动代码(start-up)和库子程序:对于前者,从最后的目标程序去掉启动代码的那些例程,反编译器从主(main)程序入口点开始分析;对于后者,那些子程序用其库函数名代替。 所提出的技术在一个适用于Intel i80286体系结构的反编译器(原型)样机上得以实现,该样机名为dcc,在DOS操作系统下运行,为输入源的.exe文件或.com文件产生目标C程序。在第9章,将反编译输出的程序同它最初的高级语言程序做了采样比较,并且对反编译结果做出一个分析。 第1章从编译器角度对反编译做一介绍,第2章从20世纪60年代早期反编译出现开始介绍它的历史概况,第3章介绍源二进制程序的静态二进制代码和在运行时间实现程序的动作之间的关系,第4章描述前端模块这个阶段,第5章详细说明用来分析中间代码的数据优化技术,把中间代码转换成一个更高级的表示法,第6章详细说明用来分析控制流向图结构的控制结构转换技术,把控制流向图转换成一个高级控制结构的图,第7章描述后端模块,第8章介绍反编译工具程序,第9章综述dcc的实现以及取得的成果,第10章给出结论以及这项研究的工作前景。 本论文有些部分已经公开发表或者提交给国际定期刊物。两篇文章在1993年出现在第19号《拉丁美洲信息会议》(XIX 'Conferencia Latinoamericana de Informatica'):“一个反编译方法学”[CG93] 和“反编译使用的一个结构化的算法”[Cif93]。前一篇文章提出反编译的阶段(如第1章第1.3节所述)、前端(第4章)、控制流分析阶段的初始工作(第6章)、以及dcc工作实现的说明。后一篇文章提出控制流分析阶段使用的结构化的算法(第6章)。一篇刊物文章“二进制程序的反编译”[CG94] 已经被《软件-实践与经验》(Software - Practice & Experience)接受发表;这篇文章概述建立一个反编译器所使用的技术(第4,5,6,7章的摘要)、在反编译过程中如何借助签名生成器工具(第8章第8.2节)、以及用dcc反编译的一个程序样本(第9章)。有两篇文章目前正考虑在国际刊物上发表。“子过程之间数据流的反编译”[Cif94a]被提交给《程序语言杂志》(the Journal of Programming Languages),文中完整描述了数据流分析器的优化操作,把低级的中间代码转换成一个高级的表示法。“结构化反编译图”[Cif94b] 被提交给《计算机杂志》(The Computer Journal),文中给出结构化控制流向图的最后的改进方法,以及用dcc反编译的一个程序样本。 本论文提出的技术更充分地拓展文献中前人的工作。关于为了确定寄存器参数和寄存器返回值所需要做的子过程寄存器分析、为了清除掉有关栈的指令(即push和pop)所需要的分析、以及控制结构集之结构化,过去没有相关的反编译研究文献。这次研究做的创新性工作在第5,6,8章描述。第5章第5.2节、第5.4节举例并且描述九种不同型的优化,将低级中间代码转换成高级表示法。这些优化考虑条件码、子程序调用(即,子过程之间的分析)和寄存器漏出(spill),清除掉中间指令的所有低级特征(比如条件码和寄存器),而且把高级概念之表达式引入中间表示法。第6章第6.2节、第6.6节举例并且描述将各种不同型的循环和条件转移包括多分支条件(例如case语句)结构化的算法。在这个领域中前人的工作成果主要集中在循环的结构化,很少文章尝试二路(2-way)条件分支的结构化,而对于多路条件分支则没有研究说明。本论文提出一个完整的方法,基于一个预先确定的、一般化的高级控制结构集合(集),对所有型的结构进行结构化。在第6章第6.4节给出一个确定一般化的控制结构的集合(集)的标准。第8章描述反编译程序使用的全部工具,最重要工具是签名生成器(第8.2节),它用于在操作系统不共享库的体系结构下确定编译器和库的签名,比如DOS操作系统。   如你想系统地学习加解密知识,请参考由本站与广大网友合作推出的新书《加密与解密--软件保护技术及完全解决方案 》,本书全面介绍Windows下软件的保护与破解技术,内容全面,讲解详细,配套光盘备有实战习题,适合各位爱好者使用。 书号:5053-6923-7/TP.3948 定价:40元(含盘) 出版单位:电子工业出版社     由本站与广大网友合作的新书《加密与解密--软件保护技术与解决方案》于近日上市,全国新华书店发行,需要者可于近期到本地各大书店咨询。   看完这本书,解密不再神秘。不论是解密爱好者还是软件编程者都应该好好去看看

16,472

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC相关问题讨论
社区管理员
  • 基础类社区
  • Web++
  • encoderlee
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

        VC/MFC社区版块或许是CSDN最“古老”的版块了,记忆之中,与CSDN的年龄几乎差不多。随着时间的推移,MFC技术渐渐的偏离了开发主流,若干年之后的今天,当我们面对着微软的这个经典之笔,内心充满着敬意,那些曾经的记忆,可以说代表着二十年前曾经的辉煌……
        向经典致敬,或许是老一代程序员内心里面难以释怀的感受。互联网大行其道的今天,我们期待着MFC技术能够恢复其曾经的辉煌,或许这个期待会永远成为一种“梦想”,或许一切皆有可能……
        我们希望这个版块可以很好的适配Web时代,期待更好的互联网技术能够使得MFC技术框架得以重现活力,……

试试用AI创作助手写篇文章吧