.NET平台原理调试分析【一】WinDBG+OllyDBG by:凉游浅笔深画眉

我在.NET平台诞生了12年后才接触到它,而国内.NET平台的逆向技术兴起于10年前。

我是不幸的,不幸的是起步比前辈们晚了10年左右,十分后悔当初把最好的学习时间奉献给了游戏。最后发现,玩再多游戏也并没什么卵用。

我也是幸运的,幸运的是前人已留下了太多对.NET平台的探索脚印。我只需要跟随着他们的脚步快速前进,而不会绕很多弯路和四处碰壁。

最后感谢那些写过文章供后人学习的前辈们,虽然很多文章都是七八年前的,但受用至今。

此文既不是破解,也不讲脱壳,只是逆向角度分析.NET程序执行原理。仅希望抛砖引玉,待各位大牛们帮我完善接下来的分析过程。

---------------------------------------------------分割线----------------------------------------------------------

调试环境:Windows XP SP3   注:调试环境请使用Win7之前的系统,Win7之后的系统有所变化。

目标对象:一个基于.NET Framework 2.0框架编写的EXE文件

所需工具:IDA,OllyDBG,WinDBG,CFFExplorer,Depends

调试环境:Windows XP SP3  注:调试环境请使用Win7之前的系统,Win7之后的系统有所变化。

目标对象:一个基于.NET Framework 2.0框架编写的EXE文件

所需工具:IDAOllyDbgWinDBG,CFFExplorer,Depends

 

1.首先我们用CFF打开一个.NET程序,找到可选头,这里有个AddressOfEntryPont域,它的值是000030CE,这是一个RVA(相对虚拟地址)。这个AddressOfEntryPont标志着加载器要运行加载PE文件时执行的第一个指令的地址。

2.我们再找到ImageBase这个域,它的值是00400000,ImageBse标志着程序载入内存的理想初始地址(基地址),这里也是为什么采用XP系统来调试.NET程序的原因,有兴趣的朋友可以研究下。

3.我们可以看到AddressOfEntryPont位于.text区段上,我们来计算一下这个000030CE在文件中的物理地址是多少:

物理地址=RVA-Visual Address+Raw Address

由图可知 Visual Address=2000,Raw Address = 200

所以: 物理地址=000030CE-2000+200=12CE

4.我们切换到十六进制编辑界面,找到12CE位置,下图可以看到这几个字符 FF 25 00 20 40 00

5.FF 25 00 20 40 00是什么意思,我们打开OD来看看。在OD中,我们按Ctrl+B,然后输入FF 25可以看到,FF25代表的是汇编指令中的JMP,也就是无条件跳转。后面的00 20 40 00,其实是一个内存地址00402000,所以整句代码连起来就是 jmp 00402000 (意思就是程序加载后直接跳转到00402000这里来执行)。

6.为了验证我们刚才所分析的是否正确,我们现在需要借助WinDBG来进行分析。首先将目标程序载入WinDBG,程序会自动断下来。我们在Command窗口中可以看到如下信息,程序主模块从00400000处开始加载,也就是我们刚才在CFF中看到的ImageBase(基地址)。

7.配合我们刚才的偏移地址000030CE,我们在下面的命令栏中输入指令“u 00400000+000030CE”,这条指令的意思是从地址00400000+000030CE处反编译8条机器码。

8.回车之后看到了一个让我们心动的结果,004030CE处的前6个字节反编译对应的汇编代码为 Jmp 00402000,正好验证了我们前面的分析。

9.证实了前面的分析完全正确,接下来我们我们去探索一下00402000究竟什么。下一步我们在命令栏中输入dps WindowsFormsApplication3+0x2000 也可以输入dps 00402000

10.回车之后看到如下信息mscoree!CorExeMain,可以看到00402000这个地址代表的是mscoree.dll这个模块的_CorExeMain函数,位置在79004ddb处。

11.如果WinDBG看上去并不是那么直观,那我们继续借助OD来分析吧。我们用OD中载入程序,Ctrl+G转到我们在WinDBG中看到的地址79004ddb处,然后F2在这个地址下断点。

12.重新载入并运行当前程序,程序执行到我们刚才下断点的地方就会自动断下来。这时候留心观察寄存器里EIP的值(为什么要观察EIP,因为EIP标志着程序将执行的下一句指令),我们可以很清楚地看到,程序下一句将要执行的是mscoree.dll这个模块中的_CorExeMain函数。

13.既然程序的加载需要调用到mscoree.dll中的_CorExeMain函数,那么我们很容易猜想到,_CorExeMain函数会被保存到程序的导入表中,程序运行的时候进行调用。我们在CFF中切换到到程序IAT(导入表),可以很清晰地看到,.NET程序导入了mscoree.dll的_CorExeMain函数,这也是.NET程序唯一的导入函数。

14.当然我们也可以借助于别的分析工具来分析当前程序依赖的DLL。

 

我们把目标程序用Depends载入,可以很清晰地看到该程序仅仅只依赖mscoree.dll中的_CorExeMain函数。

15.综上所述,PE Loader加载了.NET镜像文件之后,首先会执行一句JMP mscoree. _CorExeMain(这里特别指明是mscoree中的_CorExeMain是有原因的,今后有时间再讲述为什么特别指明mscoree这个模块),借助微软的mscoree.dll来启动我们的.NET托管运行环境。

 

_CorExeMain这个函数究竟做了哪些工作,如何一步一步启动托管运行环境的,等有时间继续写吧。

时间: 2024-12-24 22:30:42

.NET平台原理调试分析【一】WinDBG+OllyDBG by:凉游浅笔深画眉的相关文章

逆向第一课(.NET平台原理)

一.什么是.NET .NET是架构与操作系统之上的平台,它是一套虚拟机!它提供了一套完整的程序开发框架,包括新的编程语言,新的程序运行方式,新的服务等 .NET平台三个重要特性 a.统一了编程语言 过去,不同编程语言间的协作拥有者或多或少的兼容性问题,比较麻烦..NET则统一了编程语言:无论程序是用C#,还是C++,或者是VB编写,最终都被编译为.NET中间语言(MSIL) b.扩展了PE文件的格式 可执行文件中不再保存机器码,而是保存IL指令和元数据,部分PE结构被扩展用于保存.NET的相关信

白屏调试分析

前些天在展讯8825上调试一个ili9807的屏,屏幕一直显示为白屏,这就非常麻烦了,因为白屏意味着基本的显示也没有, 调试屏的时候,即使是显示花屏或者任何的乱彩色线条,甚至是简单的几条线,也算是成功了一小部分,能显示数据, 意味着基本的数据链路是联通的. 开始是从屏的连接器上找问题,从硬件上测量FPC是正常连接的,简单的就是测量屏与主板的各个引脚是连接通的, 各引脚上的电压是正常的,各引脚是否短路,经过长时间的测量和ic原厂的工程师帮助下,硬件在FPC上飞线, 屏的FPC终于是正常联通了!这立

GDB多线程调试分析

0x00: 在Linux系统上Gdb提供了一组多线程调试命令,如表所示: 多线程调试的主要任务是准确及时地捕捉被调试程序线程状态的变化的事件,并且GDB针对根据捕捉到的事件做出相应的操作,其实最终的结果就是维护一根叫thread list的链表.上面的调试命令都是基于thread list链表来实现的,后面会有讲到. 0x01:Gdb在linux平台多线程调试实现主要依赖下面三个文件 thread.c:文件它的任务非常简单,就是多线程调试命令子集的实现,比如info threads.当用户在gd

OSSIM平台安全事件关联分析实践

OSSIM平台安全事件关联分析实践 在<开源安全运维平台OSSIM最佳实践>一书中叙述到,事件关联是整个OSSIM关联分析的核心,对于OSSIM的事件关联需要海量处理能力,主要便于现在需要及时存储从设备采集到的日志,并能关联匹配和输出,进而通过Web UI展示.从实时性上看,关联分析的整个处理过程不能间断,这对系统的实时性要求较高,另外Ossim系统是基于规则的,Ossim内部具有多套高速规则分析引擎,以实现模式匹配和对关联分析结果调用.所以系统的关联引擎是一个典型数据处理系统,必须依靠强大的

MTK65XX平台充电调试总结

MTK平台充电调试总结 摘要:调试电池的充放电管理,首先需要深入了解锂电池的电池原理和特点,充放电特性以及基本的电池安全问题.然后需要对MTK的电池管理驱动程序有深入的了解,理解电池充放电算法的基本原理.在此基础上,对充放电导致的问题进行调试优化. 一. 锂电池工作原理和特性 1.工作原理: 锂离子电池以碳素材料为负极,以含锂的化合物作正极.它主要依靠锂离子在正极和负极之间移动来工作.在充放电过程中,Li+ 在两个电极之间往返嵌入和脱嵌:充电时,Li+从正极脱嵌,经过电解质嵌入负极,负极处于富锂

[原]调试实战——使用windbg调试DLL卸载时的死锁

原调试debugwindbg死锁deadlock 前言 最近我们的程序在退出时会卡住,调查发现是在卸载dll时死锁了.大概流程是这样的:我们的dll在加载的时候会创建一个工作线程,在卸载的时候,会设置退出标志并等待之前开启的工作线程结束.为了研究这个经典的死锁问题,写了一个模拟程序,用到的dump文件及示例代码参考附件. {% note info %} 这也是几年前在项目中遇到的一个问题,我对之前的笔记进行了整理重新发布于此. {% endnote %} 关键代码 主程序 WaitDllUnlo

jQuery之ajax错误调试分析

jQuery之ajax错误调试分析 jQuery中把ajax封装得非常好.但是日常开发中,我偶尔还是会遇到ajax报错.这里简单分析一下ajax报错 一般的jQuery用法如下,ajax通过post方式提交"汤姆和老鼠"这段数据到xxx.php文件中.成功后则打印返回的数据,失败则打印错误原因. 1 2 3 4 5 6 7 8 9 10 $.ajax({     url:"xxx.php",     type:"post",     dataty

Java NIO原理 图文分析及代码实现

Java NIO原理 图文分析及代码实现 博客分类: java底层 java NIO原理阻塞I/O非阻塞I/O Java NIO原理图文分析及代码实现 前言:  最近在分析hadoop的RPC(Remote Procedure Call Protocol ,远程过程调用协议,它是一种通过网络从远程计算机程序上请求服务,而不需要了解底层网络技术的协议.可以参考:http://baike.baidu.com/view/32726.htm )机制时,发现hadoop的RPC机制的实现主要用到了两个技术

loosejar原理简要分析

loosejar这个小工具可以动态分析出应用中有每个jar包的实际使用情况,详情请参阅<通过loosejar清理应用中冗余的jar包>基本原理是利用instrumentation的特性用 Instrumentation,开发者可以构建一个独立于应用程序的代理程序(Agent),用来监测和协助运行在 JVM 上的程序,甚至能够替换和修改某些类的定义.有了这样的功能,开发者就可以实现更为灵活的运行时虚拟机监控和 Java 类操作了.关于instrumentation的详细介绍,可以参阅这篇文章&l