0%

《逆向工程核心原理》学习笔记1

逆向工程核心原理第二章

准备阶段
  • 软件:Ollydbg,visual studio community

  • 使用visual studio创建一个c++控制台项目,粘入以下代码,然后运行生成**x86(Win32)**的HelloWorld.exe文件

    1
    2
    3
    4
    5
    6
    7
    #include <windows.h>
    #include <tchar.h>

    int _tmain(int argc, TCHAR* argv[]) {
    MessageBox(NULL, L"HelloWorld", L"blog.iz4.cc", MB_OK);
    return 0;
    }
  • 《逆向工程核心原理》作者提供的资源下载github仓库:https://github.com/reversecore/book.git;书中用到的代码和可执行文件都能在里面获取

调试定位main函数
  • 简单使用 F7(step into)和F8(step over)查找main函数位置

  • 使用ollydbg打开HelloWorld.exe后,可以看到入口点(EntryPoint)跟《逆向工程核心原理》书中不太一样,应该是vs版本不一致导致的,但不影响后续的分析,这里直接F7跳至下一语句

    image-20211121152315527

  • 跟踪跳转后可以看到002B1F63的地方调用了一个HelloWor*函数,我们继续F7跟踪跳转

    image-20211121152838001

  • F7跟踪进入后,发现函数内部又调用了两个函数,这里为了可以改用F8来筛选出这两个哪个函数是包含我们main函数的代码,因为我们已知程序是会弹出一个HelloWorld的窗,所以F8执行时,只要看执行这两个函数时,哪个会弹窗,那么那个函数就是需要我们进一步分析的

    image-20211121153107618

  • 按照上面的思路,最终定位到第二个HelloWor.__scrt_comon_main这个函数是我们要找的,找到后,我们重新调试Ctrl + F2,然后F7步入HelloWor.__scrt_comon_main这个函数进行进一步分析

    image-20211121154103746

  • F7步入后可以发现,这个函数内部相比前面的函数要复杂的多,调用其他函数的地方也比较多,这里也一样用上面一样的思路来使用F8单步跳过来查找main函数,每执行完一个函数,查看下程序是否出现弹窗,如果出现了那么说明那个函数就是包含我们main函数代码的函数

    image-20211121154705583

  • 最终先定位到HelloWor.invoke_main_slow_path*这个函数,其实从函数名字也大致能看出来(invoke main => 执行main),这个函数就是调用我们main函数的地方,我们F7步入跟踪查看

    image-20211121155019244

  • 可以看到,该函数内部也调用了4个函数,这里还是上面的老办法,继续排查,最终终于找到我们的main函数HelloWor.002B114F,F7步入查看

    image-20211121155242994

  • 可以看到我们代码中定义的字符串"blog.iz4.cc"和"HelloWorld",以及调用MessageBoxW,可以确定这就是我们的main函数,至此终于找到了main函数

  • 小结:我们想定位程序某段代码所在位置时,可以利用F7和F8来完成,根据程序执行到某个位置时,程序状态是否发生改变来定位相应的位置,但这个方法只适用于程序比较简单的情况下,如果程序比较复杂,那么这个方法则非常的麻烦。

使用搜索字符串来定位main函数
  • 重新开始调试,右键选择 中文搜索引擎 => 智能搜索image-20211121160743342

  • 这里可以看到排在最前面的两个字符串就是我们要找的字符串,如果不能一眼看出所找字符串在哪,那么可以Ctrl + F进行搜索查找,这里我们双击字符串"HelloWrold"就能进入我们的main函数当中,比上面的运行调试的代码更为快捷。

    image-20211121160910496

    image-20211121161101566

根据API调用查找main函数位置
  • 原理:根据程序运行时的行为来推断其可能用到了哪些API,然后查看程序所有调用该API的地方,再判断是否为目标函数

  • 重新开始调试,右键选择 查找 => 所有模块间的调用

    image-20211121181902720

  • 点击窗口内容,输入MessageBoxW,则自动定位到相应API调用的地方,双击user32.MessageBoxW,定位到程序调用该API的位置,也就找到了我们的main函数所在的位置

    image-20211121182118531

    image-20211121183241282

在API代码中打断点查找main函数
  • 原理:根据程序运行时的行为来推断其可能用到了哪些API,在相应API的代码中设下断点,然后让程序运行至断点处,再执行"运行到返回"来找到程序相应的调用该API的代码位置

  • 重新开始调试,右键选择 查找 => 所有模块名称,然后点击数据窗口,输入MessageBoxW进行筛选,然后双击筛选结果MessageBoxW进入MessageBoxW函数所在位置

    image-20211121201358362

  • 按下F2(设置/取消)断点,管理所有断点可以点击图中BreakPoint下方的b按钮打开断点管理窗口,设置断点后,可以按F9使之运行到断点处(需要只有一个断点,多个断点则停在靠前的断点处),或着按F4运行运行至光标处

    image-20211121201551539

  • 然后Ctrl + F9运行到返回,这里实际上并不会直接返回程序调用MessageBoxW的地方,需要我们先点击程序的"确定",点击完后再按Ctrl + F9,则能返回到main函数

    image-20211121202252468

  • 如下图,可以看到最终返回的位置是程序调用MessageBoxW之后的下一句语句,这样也找到了main函数所在位置

    image-20211121202454724

修改字符串"HelloWorld"为"Hi World!"
  • 找到main函数后,我们可以知道"HelloWorld"这个字符串所在的地址,如下图地址为"002B7B4C"

  • image-20211121203058760

  • 接下来,我们点击左下角的数据窗口,Ctrl + G输入"002B7B4C",跳转至地址"002B7B4C",可以看到该数据内容就是字符串"HelloWorld"

    image-20211121203421142

  • 光标选择HelloWorld字符串,然后Ctrl + E进行编辑,这里一般来说修改字符串后的字符串长度应该小于等于原字符串长度,否则可能引起程序出错,这里选择修改Unicode的"HelloWorld"为"Hi World!",然后选择HEX将末尾的64 00 改为 00 00,即用NULL填充,从c++的角度就是用'\0'标记该处为字符串终点,此外这里是两个字节的原因是编码为Unicode,所以才两个字节一个字符

    image-20211121203541937

    image-20211121203916635

  • 保存后,运行程序,可以看到程序的弹窗内容已被修改为"Hi World!",但是这样的修改不是永久的

    image-20211121204417052

  • 如果需要永久保存我们的修改,需要右键选择左下角的数据窗口,然后选择复制到可执行文件

    image-20211121204635349

  • 然后进入如下的数据窗口,右键选择保存文件即可

    image-20211121204811555

修改字符串"HelloWorld"为长字符串"HelloReversingWorld!!!"
  • 前面提到的方法虽然也能修改字符串内容,但当我们需要修改的字符串比原字符串长的多时,该方法就不适用了,下面介绍的方法原理很简单,在程序中非常多"00"的地方也就是比较"空闲"的地方里面放我们需要加的字符串,然后将程序在引用"HelloWorld"的地方将相应的地址替换为我们的字符串地址即可,但有点需要注意的是,不是所有非常多"00"的地方都适合,我们需要在程序存放字符串常量的区域去找大片的空白区

  • 我们先跟之前方法一样跳转至"HelloWrold"字符串所在位置,然后向下拖动,找到一大片"00"数据区域,然后选择一个位置开始写入我们的字符串即可

    image-20211121210133985

  • 如下图,选择编辑002B861C处的数据,取消勾选保持大小,这样可以输入我们想要的字符串长度,输入HelloReversingWorld!!!

    image-20211121210636401

  • 保存完后,我们回到程序引用"HelloWorld"字符串的地方,修改该处的汇编指令,将指向"HelloWorld"的地址替换为"HelloReversingWorld!!!"的地址

  • 如下图,按"空格"修改光标所在的汇编代码,将地址改为"HelloReversingWorld!!!"的地址即"0x002B861C",保存然后运行查看结果

    image-20211121211137711

  • 最终效果如下,可以看到同样达到修改字符串的目的

    image-20211121211644720