Windows 逆向-堆栈

Oyst3r 于 2023-11-26 发布

前言

这里还没有到画堆栈图这个阶段,还是一个入门的讲解,其中比较绕的可能就是要自己去写一段代码去代替 push 和 pop,去了解这两个操作到底是干了什么,这个其实在滴水的公开课就讲过,但是我还是把它放在了这里面去讲

课堂

引出堆栈

windows 操作系统中的堆栈都是从高地址往低地址存入数据,所以从栈底到栈顶的地址依次从大到小

如果我们要临时存储一些数据,而且数量很少的话,可以将数据放到寄存器中

但是当数据数量很大时,我们需要存到内存中,那么现在我们想要一种内存,可以记录存了多少数据,并且能够非常快的找到数据,于是我们可以这样设计内存。用两个寄存器分别存储栈底和栈顶的内存地址,存数据的时候,TOP 值减 4,释放数据时 TOP 值加 4,如果想要读取中间的某个数值时可以通过 TOP 或者 BASE 加上偏移量的方式去读取

所以可以这么去设计

堆栈操作本质

下述过程就是汇编语言提供 push 和 pop 的变形,即用其他指令来达到和 push 和 pop 一样的功能,这样做对程序来说相对更加安全,让逆向的人花时间去读代码,如果直接用 push 或者 pop,就很容易知道在干什么

入栈

从栈顶压入数据,即往低内存地址存入数据,存入后栈顶的地址编号-4,按照这个原理我们可以写汇编代码来模拟此过程。我们规定 esp 中的值为栈顶地址;ebp 中的值为栈底地址

mov dword ptr ss:[esp-4],0x12345678
lea esp,dword ptr ss:[esp-4]
lea esp,dword ptr ss:[esp-4]
mov dword ptr ss:[esp-4],0x12345678
mov dword ptr ss:[esp-4],0x12345678
sub esp,4
sub esp,4
mov dword ptr ss:[esp],0x12345678

查询

当我们想在堆栈中查找某个地址中数据时,可以通过栈底减偏移量或者栈顶加偏移量来得到数据所在地址

mov esi,dword ptr ss:[ebp-4]       #读第一个压入栈的数据(结果存入esi中)
mov esi,dword ptr ss:[ebp-0x10]    #读取第四个压入栈的数据
mov esi,dword ptr ss:[esp+4]    #读倒数第二个压入栈的数据
mov esi,dword ptr ss:[esp+8]    #读倒数第三个压入栈的数据

出栈

出栈表示将一个或多个数据从栈中移出去,比如我想将栈顶中的值出栈,则最终栈顶的地址应该+4,即栈顶指针下移,但是出栈的那个值还是在内存中,不是说数据出栈就是将这个数据移出内存中,出栈只是此时表示栈的内存结构中没有存储此数据了,但是它还在内存中。下图所示

mov eax,dword ptr ss:[esp]
lea esp,dword ptr ss:[esp+4]
lea esp,dword ptr ss:[esp+4]
mov eax,dword ptr ss:[esp-4]

保留状态

pushad:将八个 32 位通用寄存器中存的值,存入堆栈中,按照顺序存:eax 中的值先入栈,接着是 ecx,edx,ebx,esp,ebp,esi,edi,起到一个记录现场的作用。接着你就可以对寄存器做任意操作,最后反正能还原

popad:将八个 32 位通用寄存器中的值还原成最初 pushad 存入堆栈中的八个 32 位通用寄存器的值。起到一个还原现场的作用。所以综上,pushad 加 popad 就起到一个保护现场的作用

作业

mov ebx,0x0019ff40   #栈底
mov edx,0x0019ff30   #栈顶

mov dword ptr ds:[edx-4],0x11111111
-------------------------------------
mov dword ptr ds:[edx-8],esi   #004010F0
-------------------------------------
mov eax,dword ptr ss:[esp]   #BBBBBBBB
mov dword ptr ds:[edx-0xc],eax
-------------------------------------
mov eax,dword ptr ss:[esp+8]   #75b510f0
mov dword ptr ds:[edx-0x10],eax
-------------------------------------
mov dword ptr ds:[edx-0x14],0xFFDC
-------------------------------------
lea edx,dword ptr ds:[edx-0x14]

未添加数据前,栈结构如下图所示

连续添加五个数据后,栈结构如下图,栈顶地址变为 0x0019ff1c

后续的跟上上面的步骤一步一步操作就行