-
-
[讨论]浅谈一些寄存器在实际中的应用
-
发表于:
2011-10-30 14:06
8778
-
本人新手,只是把一些问题放到一块来看,如有错误之处请指正,文中引用各位前辈的一些文章,详细请阅读原文。
Windows中将线程环境成为“thread context”,实际上指的是寄存器的状态,用一个CONTEXT结构来表示。
其中Esp指向堆栈的栈顶,Eip指向下一条指令。
在程序调用函数过程中堆栈起到关键作用,当参数多余一个是要按照一定的顺序压栈。局部变量也要用到堆栈。(详细参照《解密基础知识入门 》作 者: kanxue ,中关于调用约定和局部变量部分)
因为call之前要把返回的地址压栈,我们可以这样做以达到自定位的目的:
dwVar dd ?
call @F
@@:
pop ebx
sub ebx,offset @B
mov eax,[ebx + offset dwVar]
我们也可以用此来动态获取API入口地址:当父进程创建子进程时,会调用kernel32.dll中的GreateProcess,CreateProcess函数在完成装载应用程序后,会将一个返回地址压栈并转而执行应用程序,这个地址在程序入口的地方用[Esp]就可以读出,该地址位于kernel32.dll中,通过它我们可以得到LoadLibrary和GetProcAddress函数的地址……(这两个用处在《win32汇编语言程序设计》中有详细说明)。
在加壳过程中,外壳初始化的现场环境(各寄存器值)与原程序的现场环境是相同的。加壳程序初始化时保存各寄存器的值,外壳执行完毕,会恢复各寄存器内容。其代码形式一般如下:
PUSHFD ; 将标志寄存器入栈保存
PUSHAD ; push eax, ecx, edx, ebx, esp, ebp, esi, edi
…… ; 外壳代码部分
POPAD ; pop edi, esi, ebp, esp, ebx, edx, ecx, eax
POPFD ; 恢复标志寄存器
JMP OEP ;
OEP: …… ; 解压后的程序原代码
(该部分来自脱壳基础知识入门及FAQ 作 者: kanxue )
这种情况我们可以用Esp定律来找OEP:
这个堆栈平衡原理其找OEP原理这篇文档描述的比较详细:寻找真正的入口(OEP)--广义ESP定律 作者:Lenus
硬件断点的原理:
在寄存器中,有这么一些寄存器,它们用于调试。人们把他们称为调试寄存器,调试寄存器一共有8个名字分别从Dr0-Dr7。所以我们也把调试寄存器简单的称为Drx。
对于Dr0-Dr3的四个调试寄存器,他们的作用是存放中断的地址,例如:401000
对于Dr4,Dr5这两个寄存器我们一般不使用他们,保留
对于Dr6,Dr7这两个寄存器的作用是用来记录你在Dr0-Dr3中下断的地址的属性,比如:对这个401000是硬件读还是写,或者是执行;是对字节还是对字,或者是双字。
(这段来自 硬件断点的原理 作者:Lenus )
在《脱壳基础知识入门及FAQ 》第二课是SEH技术。SEH是基于线程的,使用SEH可以为每个线程设置不同的异常处理程序,而且可以为每个线程设置多个异常处理程序。
Win32为每个线程定义了一个线程信息块,其中保存了线程的一些属性数据,线程信息块的格式被定义为NT_TIB结构:
NT_TIB STRUCT
ExceptionList dd ? ;SEH链入口
StackBase dd ? ;堆栈基址
StackLimit dd ? ;堆栈大小
SubSystemTib dd ?
FiberData dd ?
ArbitraryUserPointer dd ?
Self dd ? ;本NT_TIB结构自身的线性地址
NT_TIB ENDS
NT_TIB结构的第一个字段ExceptionList指向一个EXCEPTION_REGISTRATION结构,SEH异常处理回调函数的入口地址就是由EXCEPTION_REGISTRATION结构指定的,这个结构的定义如下:
EXCEPTION_REGISTRATION STRUCT
prev dd ? ;前一个EXCEPTION_REGISTRATION结构的地址
handler dd ? ;异常处理回调函数地址
EXCEPTION_REGISTRATION ENDS
当异常发生时,系统从TIB中取出ExceptionList字段,然后从ExceptionList字段指定的EXCEPTION_REGISTRATION结构中取出handler字段,并根据其中的地址去调用回调函数,整个过程如图14.1所示,所以只要构建一个含有回调函数地址的EXCEPTION_REGISTRATION结构,然后修改TIB中的ExceptionList字段,指向这个结构就可以注册一个SEH异常处理回调函数。
SEH异常处理程序入口地址的定义
现在还剩下一个关键的问题:到哪里找TIB呢?答案是:TIB永远放在fs段选择器指定的数据段的0偏移处,所以,fs:[0]的地方就是TIB结构的ExceptionList字段,这个答案对于Windows 9x系统和Windows NT系统都是有效的。由于一个进程中的不同线程可以有不同的环境,所以,在不同线程中fs段选择器可以使用不同的值,这种特征使每个线程都可以设置不同的回调函数。
(原文来自《Windows32位汇编语言程序设计教程》)
参照这里可以有更多的了解:
SEH IN ASM 研究(二)---提高篇:关于异常处理的嵌套和堆栈展开 (15千字) 作者:hume
【转帖】好文Structured Exception Handling
[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!