chapter2:逆向工程之学习——动态分析与静态分析结合解CTF(csaw2013reversing2)

前言

最近在准备CTF比赛,刷到一道非常经典的逆向题:攻防世界——csaw2013reversing2。这道题十分完美的用上了静态分析和动态分析的方法。在这里,我先总结一些啥是动态分析,然后再用动态分析与上个月的静态分析来解一道CTF逆向题。关于静态分析: chapter1:逆向工程之学习——静态分析

动态分析

什么是动态分析?

指程序运行的同时跟踪其行为的技术。其实类似于我们在一些IDE中进行代码调试时所用的“Debug”。

动态分析常用工具:OllyDbg

使用方法很简单:直接打开软件,把目标exe文件拖入即可。
我们关键是来看一下:OllyDbg的四个大黑框都是啥。我们主要把注意力放在左上角的框(反编译代码和二进制代码)和右上角的框(寄存器)。左上角的框就相当于你在IDE中需要进行Debug的一些代码,按F2设置断点,按F9执行程序/运行到断点处,F8单步调试。你可以看到图中00401388代表的是这个程序的物理地址,然后你会发现00401388是灰色背景,但是下面的都是黑色背景。那是因为程序正运行到此。

那么右上角的框,代表了一些变量值,这些值都存储再寄存器中(EAX , ECX …),下面还有一些标志位(C , P , A , Z),这些都可以在程序调试中,手动修改,目的是:实现一些违背源程序本意的操作。 比如:得到 Flag
在这里插入图片描述但是,汇编代码冗长,你想快速地找到你想设置断点的程序位置并不容易。所以得结合上次的静态分析技术(忘了可以看我上一篇博客,不看也没关系,等下会在解题部分进行演示)。

如何调试

只要你会用主流的IDE比如Pycharm,VS,IDE,MATLAB 等。学会OllyDbg也不是难事!!!
其实我们只需要遵循三步走:

  • 第一步设置断点并开始调试:F2 – > F9
    在这里插入图片描述

  • 第二步单步调试:F8

  • 第三步观察寄存器,栈区域,必要时修改寄存器
    在这里插入图片描述总之就和你平时调试IDE一样简单!

开始解题

在这里插入图片描述打开运行的话就是一段乱码。然后程序结束。下面开始进行正常的解题分析步骤

开始静态分析

  • Step1:我们先把这个程序丢到PE中看一看是几位的,加没加壳!重点还是看加没加壳
    在这里插入图片描述
  • Step2:丢进IDA 进行静态分析,我们直接找Main函数
    在这里插入图片描述
  • Step3:按F5 对main 函数的汇编代码进行反汇编
int __cdecl __noreturn main(int argc, const char **argv, const char **envp)
{
  int v3; // ecx@1
  LPVOID lpMem; // [sp+8h] [bp-Ch]@1
  HANDLE hHeap; // [sp+10h] [bp-4h]@1

  hHeap = HeapCreate(0x40000u, 0, 0);
  lpMem = HeapAlloc(hHeap, 8u, MaxCount + 1);
  memcpy_s(lpMem, MaxCount, &dword_409B10, MaxCount);
  //注意下面的这个if 语句
  if ( sub_40102A() || IsDebuggerPresent() )
  {
    __debugbreak();
    sub_401000(v3 + 4, (int)lpMem);
    ExitProcess(0xFFFFFFFF);
  }
  MessageBoxA(0, (LPCSTR)lpMem + 1, "Flag", 2u);
  HeapFree(hHeap, 0, lpMem);
  HeapDestroy(hHeap);
  ExitProcess(0);
}

浏览完代码,初步断定,IpMem 中存储了Flag,但不太会走入if 里面的逻辑。
注意下这个sub_40102A() || IsDebuggerPresent()
在这里插入图片描述
sub_410102A 直接返回一个0 , IsDebuggerPresent() 如果你不是调试代码那么也是返回0.

所以,If中的逻辑很可以是对IPMem的一变换——得到Flag,所以正常的思路就是触发这个If内部逻辑。

但是这个IF里有个坑,就是你进去之后你就会立马结束Debug,这样就没法执行下面的变换操作了,所以这里正常的思路就是进入动态调试阶段,并且不要执行debugbreak()函数,这个是可以在OllyDbg中做到的。

但是这个IF还有个坑,就是他没有显示的函数了。也就是说,即使你求出了FLAG,也没法给你显示出来。
这个显示问题容易解决,因为如果你直接运行这个EXE程序,就会直接显示出一个乱码,所以我们只需要在最后让他跳到一个显示函数中即可

在这里插入图片描述IsDebuggerPresent()有两条路,红色代表NO逻辑,绿色代表Yes逻辑。绿色逻辑中含有MessageBoxA,这就是显示函数。所以常规思路就是让IsDebuggerPresent跳入loc_4010B9(物理地址:004010B9)。

好分析至此:基本上确定了解题思路:
1. 进入IF逻辑
2. 跳过debugbreak()
3. 显示IPMem内的信息

开始动态分析

  • Step1:设置IsDebuggerPresent()为断点,运行至断点处
    在这里插入图片描述
  • Step:2 修改EAX寄存器的值为1,强制进入IF逻辑。(不知道为什么,我在调试中,isDebuggerPresent()返回的也是0)
  • Step:3 修改判断逻辑,不要让他进入debuggerbreak()
    在这里插入图片描述
    修改je为Jne。观察左下角可以发现现在显示“跳转未实现”。相当于从“是”逻辑跳转改为“否”逻辑跳转。在这里插入图片描述
  • Step4:将00401B9A int3指令处修改为NOP。这里有个跳转,但是我们需要取消它。所以直接改为NOP。
    在这里插入图片描述
  • Step5: 调用完Call 之后,相当于进入了对IPMem的变换。但是后面就有个jmp,按照原程序的逻辑,这个jmp应该就对应着:ExitProcess(0xFFFFFFFF)。我们只需要让他跳转到MessageBoxA即可。上面已经分析除了他的地址(loc_4010B9(物理地址:004010B9)。)所以修改jmp指令为 004010B9
    在这里插入图片描述最终的Flag: {reversing_is_not_that_hard!}

总结

1.静态分析看整体
2.动态分析看细节
3.静动结合出奇迹

附录:常见汇编寄存器和标志位

在这里插入图片描述

自己利用这些寄存器和标志位来实现一个简单的IF逻辑

在这里插入图片描述

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值