电子科技大学逆向工程实验报告作业_电子科技大学实验报告
电子科技大学逆向工程实验报告作业由刀豆文库小编整理,希望给你工作、学习、生活带来方便,猜你可能喜欢“电子科技大学实验报告”。
电子科技大学
学生姓名:马侬学
号:
指导教师:何兴高
日
期:实 验 报 告
20152*03**0*
2016.7.15
一. 题目名称:简易记事本软件逆向分析 二. 题目内容
由于记事本功能简单,稍有经验的程序员都可以开发出与记事本功能近似的小软件,所以在一些编程语言工具书上也会出现仿照记事本功能作为参考的示例。为了便于分析因此选取了一个简易的记事本,因此本实验将着重研究从源程序到机器码的详细过程而不注重程序本身的功能。另一方面简易源程序代码约130多行。本实验目的是了解源程序是怎么一步步变成机器码的又是怎么在计算机上运行起来的。
三. 知识点及介绍
利用逆向工程技术,从可运行的程序系统出发,运用解密、反汇编、系统分析、程序理解等多种计算机技术,对软件的结构、流程、算法、代码等进行逆向拆解和分析,推导出软件产品的源代码、设计原理、结构、算法、处理过程、运行方法及相关文档等。随着用户需求的复杂度越来越高软件开发的难度也在不断地上升快速高效的软件开发已成为项目成败的关键之一。为了提高程序员的产品率开发工具的选择尤为重要因为开发工具的自动化程度可以大大减少程序员繁琐重复的工作使其集中关注他所面临的特定领域的问题。为此当前的IDE不可避地要向用户隐藏着大量的操作细节而这些细节包含了大量的有价值的技术。
四. 工具及介绍:
在对软件进行逆向工程时,不可避免地需要用到多种工具,工具的合理使用,可以加快调试速度,提高逆向工程的效率。对于逆向工程的调试环节来说,没有动态调试器将使用的调试工作很难进行。可以看出,各种有效的工具在逆向工程中占据着相当重要的地位,有必要对它们的用法做一探讨。
PE Explorer简介:PE Explorer是功能超强的可视化Delphi、C++、VB程序解析器,能快速对32位可执行程序进行反编译,并修改其中资源。
功能极为强大的可视化汉化集成工具,可直接浏览、修改软件资源,包括菜单、对话框、字符串表等; 另外,还具备有 W32DASM 软件的反编译能力和PEditor 软件的 PE 文件头编辑功能,可以更容易的分析源代码,修复损坏了的资源,可以处理 PE 格式的文件如:EXE、DLL、DRV、BPL、DPL、SYS、CPL、OCX、SCR 等 32 位可执行程序。该软件支持插件,你可以通过增加插件加强该软件的功能,原公司在该工具中捆绑了 UPX 的脱壳插件、扫描器和反汇编器.,出口,进口和延迟导入表的功能,使您可以查看所有的可执行文件使用的外部功能,和其中包含的DLL或库的基础上进行分类的结果。这里一个非常有用的功能是语法的Viewer,它显示功能的调用语法,它知道和可以让你扩大自己的定义的语法数据库。非常好用。
Dumpbin是VC自带的二进制转储工具可以将PE/COFF文件以文字可读的方式显示出来。Microsoft COFF 二进制文件转储器(DUMPBIN.EXE)显示有关通用对象文件格式(COFF)二进制文件的信息。可以使用 DUMPBIN 检查 COFF 对象文件、标准 COFF 对象库、可执行文件和动态链接库(DLL)。具有提供此DLL中所输出的符号的清单的功能。
LINK.exe 将通用对象文件格式(COFF)对象文件和库链接起来,以创建可执行(.exe)文件或动态链接库(DLL)。
五. 源程序
notepad.cpp:
notepad::notepad(QWidget *parent): QMainWindow(parent), ui(new Ui::notepad){ ui->setupUi(this);this->setWindowTitle(“new file”);QObject::connect(ui->NewFileaction, SIGNAL(triggered()), this, SLOT(NewFile()));QObject::connect(ui->OpenFileaction, SIGNAL(triggered()), this, SLOT(OpenFile()));QObject::connect(ui->SaveFileaction, SIGNAL(triggered()), this, SLOT(SaveFile()));QObject::connect(ui->SaveAsFileaction, SIGNAL(triggered()), this, SLOT(SaveAsFile()));QObject::connect(ui->Coloraction, SIGNAL(triggered()), this, SLOT(SetColor()));QObject::connect(ui->Fontaction, SIGNAL(triggered()), this, SLOT(SetFont()));QObject::connect(ui->Aboutaction, SIGNAL(triggered()), this, SLOT(About()));QObject::connect(ui->Helpaction, SIGNAL(triggered()), this, SLOT(Help()));} notepad::~notepad(){ delete ui;} void notepad::changeEvent(QEvent *e){ QMainWindow::changeEvent(e);switch(e->type()){ case QEvent::LanguageChange: ui->retranslateUi(this);break;default: break;} } void notepad::NewFile(){ this->setWindowTitle(“new file”);ui->Text->clear();} void notepad::OpenFile(){ QString filename = QFileDialog::getOpenFileName(this, “get file”,QDir::currentPath(), “(*.*)”);if(!filename.isEmpty()){ QFile *file = new QFile;file->setFileName(filename);if(file->open(QIODevice::ReadOnly)== true){ QTextStream in(file);ui->Text->setText(in.readAll());this->setWindowTitle(filename);} else { QMeageBox::information(this, “ERROR Occurs”, “file not exist”);} file->close();delete file;} } void notepad::SaveFile(){ QString filename = this->windowTitle();// if(filename.compare(“new file”)!= 0)// { QFile *file = new QFile;file->setFileName(filename);if(file->open(QIODevice::WriteOnly)== true){ QTextStream out(file);outtoPlainText();file->close();delete file;} else { QMeageBox::information(this, “ERROR Occurs”, “file open error”);} // } } void notepad::SaveAsFile(){ QString filename = QFileDialog::getSaveFileName(this, “save file”,QDir::currentPath());QFile *file = new QFile;file->setFileName(filename);if(file->open(QIODevice::WriteOnly)== true){ QTextStream out(file);outtoPlainText();file->close();delete file;} else { QMeageBox::information(this, “ERROR Occurs”, “file open error”);} } void notepad::SetColor(){ QColor color = QColorDialog::getColor(Qt::white, this);if(color.isValid()== true){ ui->Text->setTextColor(color);} else { QMeageBox::information(this, “ERROR Occurs”, “set color error”);} } void notepad::SetFont(){ bool ok;QFont font = QFontDialog::getFont(&ok, QFont(“Arial”, 18), this, “set font”);if(ok){ ui->Text->setFont(font);} else { QMeageBox::information(this, “ERROR Occurs”, “set font error”);} } void notepad::About(){ Dialog mychild;mychild.exec();} void notepad::Help(){ QDesktopServices::openUrl(QUrl("www.daodoc.com并不是PE文件,但它也是可执行文件,它运行的环境是虚拟8086模式,并非保护模式。
由PE格式的布局图。PE文件使用的是一个平面地址空间,所有代码和数据都合并在一起,组成一个很大的结构。主要有:.text是在编译或汇编结束时产生的一种块,它的内容全是指令代码;.rdata是运行期只读数据;.data是初始化的数据块;.b是未初始化的数据节;.idata包含其它外来DLL的函数及数据信息,即输入表;.rsrc 包含模块的全部资源:如图标、菜单、位图等。
现在使用PEExplorer对编译的notepad.exe程序进行逆向。如图5所示。由图可以知道程序入口点是0x000028DFh。当程序被加载到内存执行时,第一条指令将从这里取得。注意,这个地址是相对虚拟地址(RVM),程序的入口点地址还要道基地址才能得出。
PEExplorer逆向notepad.exe和数据目录
节区头数据,分别是读到了数据目录和区段头信息。
4)调用协定
调用协定规定了函数调用的参数传递方式及返回值的传递方式。它是应用程序二进制兼容的必要面规范。常见的调用协定有如下方式:1__stdcall 用于调用Win32API函数。采用__stdcall约定时,函数参数按照从右到左的顺序入栈,被调用的函数在返回前清理传送参数的栈,函数参数个数固定。由于函数体本身知道传进来的参数个数,因此被调用的函数可以在返回前用一条retn指令直接清理传递参数的堆栈。2_cdecl: 是C调用约定,按从右至左的顺序压参数入栈,由调用者把参数弹出栈。对于传送参数的内存栈是由调用者来维护的(正因为如此,实现可变参数的函数只能使用该调用约定)。另外,在函数名修饰约定方面也有所不同。fastcall 快速调用方式。它的主要特点就是快,因为它是通过寄存器来传送参数的。实际上,它用ECX和EDX传送前两个双字(DWORD)或更小的参数,剩下的参数仍旧自右向左压栈传送,被调用的函数在返回前清理传送参数的内存栈。4参数传递分析在目标程序中有这样一个函数声明如下:
BOOLShowFileInfo(HWNDhwnd,HDChDC,HDROPhDropInfo)发生调用地方为:
ShowFileInfo(hwnd,hDC,hDropInfo);可以看到最后一条指令是堆栈平衡用的,传递了三个参数,每个参数的大小都为4个字节,所以大小刚好是0x0Ch。还可以看到第一个压栈的参数是hDropInfo,另外两参数都是用ebp来做基址寻址取到的,说明前两个参数不是局部变量。参数传递方向从右到左依次压栈。
5)堆栈平衡
参数传递后由调用者或被调用者负责平衡堆栈,但函数使用了局部变量,那堆栈又是如何保持平衡的呢?这里引入了一个叫栈帧(StackFrame)的概念。栈帧实质就一个函数栈所用的堆栈空间。每个函数都平衡了,那么整个程序栈也就平衡了。如图8所示,函数体的第一条指令就是保存ebp寄存器,它存的就是上一个函数的栈帧边界。第二条指令就是制定当前函数的栈帧的起始位置。第三条
指令就是为函数分配局部变量的堆栈空间了。函数栈的平衡
根椐VC/C++的调用协定,寄存器EAX、ECX、EDX是易变寄存器,也就是说调用函数不能假定被调用函数不改变它们的值。因此,调用函数想保留它们的值,在调用一个函数之前应自已先把它们保存起来了。另外的5个通用寄存器(EBX、ESP、EBP、ESI、EDI),则是非易变的。被调用函数在使用它们之前必须先保存。
所以上图的汇编指令就不难理解了。函数执行完毕后,只需把先前保存在栈中的EBP弹到ESP就保持了栈的平衡了。情况确实如此。如图9所示,最后一条指令是popebp,然后返回。根据返回指令,还可行知此函数使用的是cdecl调用协定。因为它没有参数的堆栈平衡。函数返回平衡堆栈 七. 心得体会
逆向工程是一个实践性很强的课程,通过上机实验使我在本次课程的学习中收获很多,通过对程序的逆向分析,本人对计算机技术有了更深的认识。感谢何兴高老师的谆谆教诲和精彩地讲课,何老师为人随和热情,治学严谨细心。同时希望能进一步学习更多和逆向工程相关的知识。