这次拿三个问题来讨论,是关于调试器的。因为对于反病毒工程师而言,类似于OllyDbg和IDA的使用方法是必须掌握的,但是在面试中又不太方便考察,所以只能对其快捷键或者调试器实现原理之类的问题进行提问。这里我还是选取比较权威的书籍上的答案,免得仅仅提供我自己的答案会误导大家,也难有说服力。如果说大家以后在面试的时候遇到这些问题,只要回答出关键点就可以,无需一字不落地背下来。因为我摘录的答案的篇幅往往比较长,为的就是让大家更为全面地看待这个问题。

问题4——6如下:

4、在IDA中,快捷键X的作用是什么?什么是交叉引用?

答:(以下内容选自《加密与解密 第三版》第3.2.5节)

通过交叉参考(XREF)可以知道指令代码相互调用关系。如下面代码所示,这句“CODE XREF:sub_401120+B↑j”,表示该调用地址是401120,“j”表示跳转(jump)。其他一些符号:“o”表示偏移值(offset),“p”表示子程序(procedure)。双击这里或按回车键可以跳到调用该处的地方。

.text:00401165                    loc_401165:                ;CODE XREF:sub_401120+B↑j
.text:00401065 push 0 ;nExitCode
.text:00401067 FF 15 B0 40 40 00 call ds:PostQuitMessage</span>

在loc_401165字符上按X键,将打开交叉参考窗口。

(关于交叉引用更为详细的说明,可参考《IDA Pro权威指南 第2版》第9章——交叉引用与绘图功能)

 

5、请解释一下什么是DR寄存器。

答:(以下内容选自《IDA Pro代码破解揭秘》第6.2节)

要真正理解调试,了解各种中断及调试寄存器是很有必要的,特别是有关进程状态变化的。Intel Software Developers Manual在这方面依然是最好的参考资料,我知道的与它相比,不过是小巫见大巫。不过,IA-32平台处理调试基本上是通过二者(中断或调试寄存器)之一实现的。

首先介绍一下调试寄存器。IA-32平台有8个调试寄存器,最多可以监视4个地址。访问这些寄存器是通过mov指令(调试寄存器暗中充当目的操作数或源操作数)的变体实现的。要知道,访问这些寄存器是需要有RING0特权的,这当然是一个限制,但考虑其影响极大,这样做也是有道理的。对每一个断点,有必要具体指定涉及的地址、位置的长度(范围在一个字节与双字之间)、处理程序(当生成一个调试异常时)以及这个断点是否被启用。前4个调试寄存器,DR0到DR3可以包含4个32位地址(定义了断点应该出现的地址)。接下来的2个调试寄存器DR4和DR5取决于操作模式可以交替使用。当DE(Debugging
Extension,调试扩展)标志被设在CR4(Control Register4,控制寄存器4)里时,DR4和DR5保留,试图引用它们时,将引发一个无效操作码异常。如果这个标志没有被设置,DR4和DR5则作为别名替代调试寄存器6和7。

DR6(DebugRegister 6,调试寄存器6),作为调试状态寄存器指示对最后发生的调试异常进行条件检查的结果。用位模式访问DR6,位0到位3与前4个调试寄存器相关。这些位指示哪个断点条件被满足而生成了一个调试异常。DR6的位13在置位时表示下一条指令引用一个调试寄存器,连同DR7(我们随后就会介绍)的一部分被使用。位14对我们来说或许是最有诱惑力的,它被置位时指示处理器处于单步模式(single-step mode),我们稍后介绍。最后使用的是位15,它指示当调试陷阱标志被置位时,作为任何切换的结果都会抛出调试异常。最后,我们介绍调试寄存器7,也就是DR7。所有的黑客都对这个寄存器垂涎欲滴,它也被称为调试控制寄存器,像DR6一样被理解为位字段。这个寄存器的第一个字节对应断点是否是活动的,如果是活动的则对应它的作用域。位0、2、4和6确定调试寄存器是否被启用,位1、3、5和7对应同样的断点,但基于全局的作用域。在这个例子里,作用域被定义为在任务切换时断点是否保持,是否针对全局启用的断点对所有的任务都是可用的。根据Intel的手册,现在的处理器不支持位8和9。不过在以前,可以用它们确定引起断点事件的精确的指令。接下来是位13,这是一个比较有意思的位,它允许在访问调试寄存器本身之前中断。最后是位16到31,这些位确定什么类型的访问会引起断点,以及所在地址的数据长度。当CR4中的DE标志被置位时,位16到17、20到21、24到25、28到29被解释成下面的意思:

00 – Break onexecution

01 – Break onwrite

10 – Break onI/O read or writes

11 – Break onread and writes but not instruction fetches

当DE标志没有置位时,除了10的值没有定义以外,其他的解释同上面一样。位18到19、22到23、26到27、30到31对应各种断点的长度,值00表示长度为1,值01表示2字节长度。在32位平台上10未被定义,在64位平台上它表示8字节长度。你可能已经猜到了,11表示长度为4字节。

现在,把所有这些位与DR0至DR3联系起来似乎比较困难,但实际并不是这样的。每个2位组合对应DR0至DR3范围里特定的连续的寄存器。这些长度必须对齐某些边界(取决于它们的大小)——例如,16位需要以字为界,32位以双字为界。这由处理器通过掩码地址的低位相关地址来强制执行,因此,一个未对齐的地址将不会产生预期的结果。如果访问起始地址加上它的长度范围内的任意地址,将产生异常,通过使用2个断点有效地允许未对齐的断点;每个断点被适当地对齐,在它们两个之间包含了讨论的长度。这里还有一点值得一提。当断点访问类型只是执行时,应当把长度设为00,其它的值导致未定义的行为。

注意:有趣的是,调试寄存器本身并没有受到很多关注。不过,私下里还是有很多利用它们的rootkits和后门。比如说,可以在指向进程结构的指针上设置一个全局访问断点,在进程的链表里隐藏进程。当访问这个地址时,将出现调试异常,并重定向到它们的处理程序并执行任意多的任务,包括返回列表里下一个进程的地址。

更糟的是,它们可以启用DR7里的GD标志,并导致访问调试寄存器本身并引发异常,阻挠审查寄存器来检查它们当前的配置。

6、请说明单步执行分为哪几种,区别是什么,其实现原理是什么。

        答:(以下内容选自《IDA Pro代码破解揭秘》第5.2.2节)

单步是指每次执行一条指令,然后把控制权交给调试器的过程。IA-32系列处理器在硬件上直接支持单步。通过一次执行一条指令,我们可以仔细监视代码的特定部分。不过不太可能用这个方法调试整个程序。单步通常用于理解特定部分的代码。

从CPU的角度来看,调试器设置EFLAGS寄存器里的TF(Trap Flag,陷阱标志)位。一条指令执行完后就会生成调试异常,调试器会把这个调试异常当做中断(INT 0x01)捕获。

注意:大多数调试器都提供step(单步)命令。通常把他们称为步入(step into)和步过(step over)。从用户角度来看,它们之间唯一的不同是出现在某些指令上,其实就是call和rep指令上。当碰到call时,步入命令将跟随call,而步过命令将在call之后的指令上中断。这通常由设置断点来完成,而不是单步执行到返回。

        知识扩展:

(以下内容选自《加密与解密 第三版》第2.1.5节)

当执行一个INT 3断点时,该地址处的内容被调试器用INT 3指令替换了,此时OllyDbg将INT 3隐藏了,显示出来仍是下断前的指令,而实际上这个指令已经被替换成了CC。

这个INT 3指令,其机器码是CCh,也常称为CC指令。当被调试进程执行INT3指令导致一个异常时,调试器就会捕捉这个异常从而停在断点处,然后将断点处的指令恢复成原来的指令。当然,如果自己写调试器,也可用其他一些指令代替INT 3来触发异常。

用INT 3断点的好处是可以设置无数个断点,缺点是改变了原程序指令,容易被软件检测到。例如为了防范API被下断,一些软件会检测API的首地址是否为CCh,以此来判断是否被下了断点。在这用C语言来实现这个检测,方法是取得检测函数的地址,然后读取它的第一个字节,判断它是否等于“CCh”。下面这段代码就是对MessageBoxA函数进行的断点检测:

FARPROC Uaddr;
BYTE Mark = 0;
(FARPROC&)Uaddr = GetProcAddress(LoadLibrary("user32.dll"), "MessageBoxA");
Mark = *((BYTE*)Uaddr); //取MessageBoxA函数第一字节
if(Mark = = 0xCC) //如该字节为CC,则认为MessageBoxA函数被下断
return TRUE; //发现断点

程序编译后,对MessageBoxA设断,程序将会发现自己被设断跟踪。当然躲过检测的方法是将断点下在函数内部或末尾,例如可以将断点下在函数入口的下一行,就可以躲过检测了。

(以下内容选自《加密与解密 第三版》第15.3.7节——通过TrapFlag检测)

CPU符号位EFLAGS中一位叫做TF,即TRAP FLAG。当这个TF=1的时候CPU执行完EIP的指令就会触发一个单步异常。例如这段代码:

pushfd
push eflags
or dword ptr [esp],100h ;TF=1
popfd ;这条指令之后TF=1了
nop ;这一条执行后会触发异常,应该提前安装SHE,跳到其他地方执行
jmp die ;如果顺序执行下来了,说明被跟踪

本篇文章参考资料:

    1、段钢(主编),Blowfish、沈晓斌、丁益青、单海波、王勇、赵勇、唐植明、softworm、afanty、李江涛、林子深、印豪、冯典、罗翼、林小华、郭春杨(编委),《加密与解密(第三版)》,电子工业出版社。

2、[美]Chris Eagle(著),石华耀、段桂菊(译),《IDA Pro权威指南(第2版)》,人民邮电出版社。

3、[美]Dan Kaminsky、Justin Ferguson、Jason Larsen、Luis Miras、Walter Pearce(著),看雪论坛翻译小组(译),《IDAPro代码破解揭秘》,人民邮电出版社。

技术面试问题汇总第002篇:猎豹移动反病毒工程师part2的更多相关文章

  1. 技术面试问题汇总第001篇:猎豹移动反病毒工程师part1

    我在2014年7月1日参加了猎豹移动(原金山网络)反病毒工程师的电话面试,但是很遗憾,由于我当时准备不足,加上自身水平不够,面试官向我提出的很多技术问题我都没能答出来(这里面既有基础类的问题,也有比较 ...

  2. 技术面试问题汇总第005篇:猎豹移动反病毒工程师part5

    这是我当初接受面试的最后两个问题,当时,那位面试官问我对漏洞了解多少时,我说一点都不懂,问我懂不懂系统内核时,我同样只能说不知道.后来他跟我说,面试的考查重点不在于我所掌握的知识的广度,而是深度.这也 ...

  3. 技术面试问题汇总第004篇:猎豹移动反病毒工程师part4

    这次所讨论的三个问题,比如DLL以及HOOK,很容易被病毒木马所利用,因此必须要比较全面地进行了解.而异常处理机制,则往往与漏洞相关联.它们自身的概念并不难理解,只是由之引申而来的问题,在计算机安全领 ...

  4. 技术面试问题汇总第003篇:猎豹移动反病毒工程师part3

    从现在开始,面试的问题渐渐深入.这次的三个问题,都是对PE格式的不断深入的提问.从最初的概念,到病毒对PE格式的利用,再到最后的壳的问题.这里需要说明的是,由于壳是一个比较复杂的概念,面试中也仅仅只能 ...

  5. 【转】Java方向如何准备BAT技术面试答案(汇总版)

    原文地址:http://www.jianshu.com/p/1f1d3193d9e3 这个主题的内容之前分三个篇幅分享过,导致网络上传播的比较分散,所以本篇做了一个汇总,同时对部分内容及答案做了修改, ...

  6. Java方向如何准备BAT技术面试答案(汇总版)

    这个主题的内容之前分三个篇幅分享过,导致网络上传播的比较分散,所以本篇做了一个汇总,同时对部分内容及答案做了修改,欢迎朋友们吐槽.转发.因为篇幅长度和时间的原因,部分答案我没有亲自总结.更多精彩内容请 ...

  7. 【转载】Java方向如何准备BAT技术面试答案(汇总版)

    作者:微信公众号JavaQ链接:https://www.nowcoder.com/discuss/31667?type=0&order=0&pos=11&page=1来源:牛客 ...

  8. 【转】Java方向如何准备技术面试答案(汇总版)

    本文转载自:“Java团长”公众号 1.面向对象和面向过程的区别 面向过程优点:性能比面向对象高,因为类调用时需要实例化,开销比较大,比较消耗资源;比如单片机.嵌入式开发.Linux/Unix等一般采 ...

  9. Java方向如何准备技术面试答案(汇总版)

    本文转载自:"Java团长"公众号 1.面向对象和面向过程的区别 面向过程优点:性能比面向对象高,因为类调用时需要实例化,开销比较大,比较消耗资源;比如单片机.嵌入式开发.Linu ...

随机推荐

  1. 如何使用 Github Actions 自动抓取每日必应壁纸?

    如何白嫖 Github 服务器自动抓取必应搜索的每日壁纸呢? 如果你访问过必应搜索网站,那么你一定会被搜索页面的壁纸吸引,必应搜索的壁纸每日不同,自动更换,十分精美.这篇文章会介绍如何一步步分析出必应 ...

  2. Oracle VM VirtualBox下创建CentOS虚拟系统

    下载镜像 创建虚拟电脑 点击新建,输入服务器命名(根据自己喜好),选择好类型和版本(我下载的是64位的CentOS系统,所以选择类型为Linux,版本为其他版本). 修改内存大小 系统建议为512M, ...

  3. 在Asp.Net Core 5 中使用EF Core连接MariaDB

    升级到Asp.Net Core 5,使用EF Core连接MariaDB,使用的Nuget包Pomelo.EntityFrameworkCore.MySql也升级到了5.0.0-alpha.2,然后发 ...

  4. go中errgroup源码解读

    errgroup 前言 如何使用 实现原理 WithContext Go Wait 错误的使用 总结 errgroup 前言 来看下errgroup的实现 如何使用 func main() { var ...

  5. 去哪找Java练手项目?

    经常有读者在微信上问我: 在学编程的过程中,看了不少书.视频课程,但是看完.听完之后感觉还是不会编程,想找一些项目来练手,但是不知道去哪儿找? 类似的问题,有不少读者问,估计是大部分人的困惑. 练手项 ...

  6. Java 树结构实际应用 二(哈夫曼树和哈夫曼编码)

     赫夫曼树 1 基本介绍 1) 给定 n 个权值作为 n 个叶子结点,构造一棵二叉树,若该树的带权路径长度(wpl)达到最小,称这样的二叉树为 最优二叉树,也称为哈夫曼树(Huffman Tree), ...

  7. Webpack 5 配置手册(从0开始)

    针对新手入门搭建项目,Webpack5 配置手册(从0开始) webpack安装顺序 1. `npm init -y`,初始化包管理文件 package.json 2. 新建src源代码目录 3. 新 ...

  8. 使用 dynamic 类型让 ASP.NET Core 实现 HATEOAS 结构的 RESTful API

    上一篇写的是使用静态基类方法的实现步骤:  http://www.cnblogs.com/cgzl/p/8726805.html 使用dynamic (ExpandoObject)的好处就是可以动态组 ...

  9. HashMap 这套八股,不得背个十来遍?

    尽人事,听天命.博主东南大学硕士在读,热爱健身和篮球,乐于分享技术相关的所见所得,关注公众号 @ 飞天小牛肉,第一时间获取文章更新,成长的路上我们一起进步 本文已收录于 「CS-Wiki」Gitee ...

  10. 【RocketMQ源码分析】深入消息存储(2)

    前文回顾 CommitLog篇 --[RocketMQ源码分析]深入消息存储(1) MappedFile篇 --[RocketMQ源码分析]深入消息存储(3) 前文说完了一条消息如何被持久化到本地磁盘 ...