分类 好好学习 下的文章

逆向学习-总结报告1

工具

Ollydbg

被调试文件

TraceMe.exe(无壳)

难度

简单

过程

QQ截图20200412161619.png
打开后,发现是需要通过序列号来授权的,取出文本框内的文本需要通过Win32API的GetDlgItemText或GetWindowText
这个是用GetDlgItemText的
ctrl+g然后找到GetDlgItemText的入口位置下int3断点
QQ截图20200412161951.png
点击check后,程序被中断在74944390,F8走出win32api的子程序
QQ截图20200412162208.png
F8一直向下走,在004011f5被条件转移到了0040122e
QQ截图20200412162451.png
发现不太对劲,好像已经被发现我序列号输错了
判断如果不条件转移就破解成功了,所以现在就可以直接把004011f5改成nop就可以不管怎么输入都正确了

序列号算法分析

因此定位序列号检测算法在004011f5条件转移前面,在GetDlgItemText后面
QQ截图20200412162735.png
经过分析后(分析见od注释)发现,004011e5处的call 00401340是唯一一个可能作为验证算法的地方,故判断00401340为序列号验证子程序的入口
004011e5处下断点,ctrl+f2重新开始,运行到004011e5处f7跟进子程序
QQ截图20200412163236.png
QQ截图20200412163243.png
看着汇编指令慢慢分析后,把注释也标在旁边,最后自己翻译成自创的伪代码(怎么舒服怎么写)
QQ截图20200412163525.png
最后只要保证序列号和被这个算法一通算下来的[ebp]一样就行

note

读这段汇编的时候最后稍微卡了一下,因为neg这个指令没仔细了解,也没学过,看名字也就是个正转成负数这类的东西了
但我看到后面sbb的时候意识到问题不对劲,因为如果标志寄存器中的cf位为1的话会导致一个sbb要额外减去1
查了一通发现neg在弄不为0的操作数的时候cf会变成1
所以调用lstrcmpA这个Win32API的时候,目的根本就不是比谁大,而是看是否相同
因为sbb eax,eax不管怎样来说eax-eax都是为0的,但由于cf的存在,它就有可能变成-1或0
而neg操作的对象正是lstrcmpA的返回值(比较对象相同返回0,大于返回正数,小于返回负数)
然后执行完sbb eax,eax后,再来一手inc eax就把结果变成了0和1
所以只要[eax]和[ebp]相同的话,这个序列号检查子程序会返回1(意味着输入正确),不同就0(意味着输入错误)

总结

这个主要还是找下感觉看着书上做的,但发现这个不算难的,做着做着还是发现可以做出来的,分析也不算费劲,前面也说到发现关键子程序做到了唯一定位
后面的序列号检查算法分析(翻译成自己的伪代码)是自己独立做的,后来对比下这个程序的源码发现差不多

参考

段钢-加密与解密
小哈龙-影响标志位的汇编指令-https://blog.csdn.net/qq_22642239/article/details/51442739

在Win32中看 堆,虚拟内存,内存映射文件,执行文件,页文件 和 物理内存 的区别

在Win32中看 堆,虚拟内存,内存映射文件,执行文件,页文件 和 物理内存 的区别

物理地址

物理内存(RAM)中的地址是物理地址,物理内存容量也就相当于内存条的容量。

线性地址

线性地址也就是虚拟地址。
由于Windows的分页机制的存在,每一段线性地址都会被映射到相应的物理地址,这个单位是页(4KB)
在这里插入图片描述
有人会问了,线性地址到物理地址的映射关系是怎么的来的?
这个是Windows的事了,这个关系由“页表”和”页目录“决定,这个不是这篇文章的主题

虚拟内存

在虚拟内存中使用的是线性地址。
虚拟内存原则上可以很大(受限于磁盘大小)。
上面的线性地址和物理地址的映射图看似线性地址的大小最大只能达到物理内存大小,而实际上虚拟内存的原理简单的来说就是把磁盘中的大小拿来用,但你在程序中却通过线性地址对他们进行读写。
这个的实现办法是通过页文件实现的。在硬盘中,有一个页文件,这个页文件的大小是可以变化的。
如果想要读取的线性地址所对应的数据直接就在物理内存中,那就可以直接读取。
如果想要读取的线性地址所对应的数据在页文件中,Windows就会把一部分物理内存中不常用的数据放回页文件中,再将页文件中想要读取的数据放进物理内存中,然后将线性地址映射到数据再物理内存中的地址,然后数据就可以通过线性地址被访问
在这里插入图片描述

堆是内存中的一块区域,每个程序都会有一个被Windows创建的进程堆(又称作默认堆)
堆其实是抽象于虚拟内存的,底层调用的是虚拟内存的接口(本质上进行的是虚拟内存操作)
在堆中分配内存块相当于是保留了一段线性地址空间并将这段地址提交物理内存(将线程地址映射到了实际的物理内存中)
在这里插入图片描述

内存映射文件

通过内存映射文件,程序在一段线性地址上的读写操作就相当于对这段线性地址所映射的磁盘中的文件的读写,这样子,就不用将磁盘中的文件读入内存的缓冲区来进行读写操作了
内存映射文件是直接将一段线性地址映射到文件中的,并没有被放入物理内存和页文件中

参考

  1. Windows环境下32位汇编语言程序设计 - 罗云彬
  2. MSDN - layered memory management in win32

本文还在这些地方发布了

  1. https://blog.csdn.net/u013289971/article/details/105339458
  2. https://cqp.cc/t/48992