关键点总结:

1.架构切换(retf与retfq与ret)

2.侧信道攻击

首先应该认识到:

retn与retf这两条指令的区别 以及 64位机器是如何执行32位程序的

retn(return near)近跳转,等同于 pop ip

retf(return far)远跳转,等同于 pop ip;pop CS

CS指的是段寄存器(Code-Segment Register),在早期80386时代,它本用于地址拓展,但如今64位的系统下,该寄存器的内容已经和那个时代完全不同了。

现代的CS寄存器中用于存放 数据段选择子(Code-Segment Descriptors),如下为其格式:

本文不再赘述其含义,我们主要关心该选择子的 D 标志位,它用以区分程序应该运行在32位还是64位架构上

因此,如果D标志位被置1,则表示程序应该运行在64位,反之则为32位(请注意,这个说法并不严谨,因为它们的差别不只是一个bit而已,但本文出于便于理解的目的如此称呼,为避免误导,特此提醒)

很多师傅的Writeup中写道:

cs寄存器中0x23表示32位运行模式,0x33表示64位运行模式

实际上,它们只有一个bit的差别而已,0x23:10 0011 ; 0x33:11 0011

高两位是GDT的索引,具体对应到GDT中,其上的D位各不相同,因此导致了运行模式的差异

另外需要提到的一点是,一部分师傅在WP里会这样写:

使用retf切换到32位,retfq再回到64位

但这二者实际上没有区别,不必多此一举,则一即可。但笔者在查阅资料的时候,并没有发现哪份文档写到retfq指令,猜测是由于AT&T语法的关系吧

题目利用思路:

仅有调用号0与5可用。但在32位下,0对于open;在64位下,5对应read。因此我们能够将flag读进内存。

接下来将flag与我们猜测的内容进行比较,如果猜对,那么程序就跳转至死循环处,最终因为超时而down;否则就直接退出。猜测方式很多,较为易懂的是利用sub+jz来实现相等跳转

EXP:

(有时间再补)

参考文章:

https://m-ouse.github.io/post/%E6%B7%B1%E5%85%A5%E7%90%86%E8%A7%A3wow64-I/

https://reverseengineering.stackexchange.com/questions/2006/how-are-the-segment-registers-fs-gs-cs-ss-ds-es-used-in-linux

https://stackoverflow.com/questions/21165678/why-64-bit-mode-long-mode-doesnt-use-segment-registers

Mark:http://liupzmin.com/2021/06/27/theory/stack-insight-01-md/

对我来说算是个冷知识:https://stackoverflow.com/questions/63975447/why-virtual-address-are-48-bits-not-64-bits

插画ID : 93869785


"The unexamined life is not worth living."