课后解惑

Q:用JMP ESP地址覆盖时,意思是要跳到ESP去执行,那ESP具体的值是多少呢?

A:你还没有理解覆盖的意义。我们不需要知道ESP具体的值,只需要知道JMP ESP指令的地址就可以了。而JMP ESP指令的地址在同种系统甚至是不同种系统下,都有相同的值,即0x7FFA4512。建议再看看本章节ShellCode的定位部分。

Q:怎么知道JMP ESP指令的地址呢?

A:JMP ESP指令的机器码是FF E4。只要你发现内存里面有一个地方是FF E4,那么就可以用此地方的地址了。比如,你查看内存0x7FFA4512的地方,只要是中文版Windows,一定放的是FF E4指令,所以说是通用地址。

Q:怎么知道JMP ESP指令的机器码是FF E4呢?

A:即可以用查询工具得到,也可以在VC中用“__asm{}”嵌入汇编JMP ESP,再按F10进入调试,然后调出JMP ESP代码对应的机器码。

我们将在ShellCode编写一章,详细讲解得到机器码的过程;在堆溢出一章有查找 call [esi+0x4C] 指令机器码的讲解,过程类似,可以参看。

Q:只能用ESP来定位吗?

A: 当然不是啦!最好把当时寄存器的内容都看一遍,比如覆盖异常时,我们用EBX。

Q: 覆盖异常处理点时,我用的就是CALL EBX指令地址,为什么会失败?

A: 在Windows 2000下,可以用CALL EBX指令地址覆盖;但在XP下,EBX会变为0,需要用POP POP RET的指令地址来覆盖。这也有个中文版NT/Win2000/Win2003都通用的地址——0x7FFA1571。我们将在ShellCode变形一章的MDTM漏洞利用讲解时详细讲到。

Q: 为什么会存在通用地址呢?

A: 上面说的两个通用地址都是指中文版的通用地址。是因为在同一个语言版本中,存在着一个从来没有改动过的程序——svchost。它只是一个壳,用以启动其他程序,所以我们很幸运,能在它那里找到通用的地址。

Q: 有世界通用地址吗?

A: 抱歉,我不知道!但同种版本的各语言版本,比如Windows 2000 SP3的中文版和英文版,在Msvcrt.dll中找到的地址可以通用。

另外,同一种语言的各个系统版本(比如中文版Windows2000、Windows XP),在0x7FFA0000中找到的地址可以通用,就像0x7FFA4512和0x7FFA1571。

如果你找到了世界通用地址,请共享一下,谢谢!

Q:只能是用JMP CALL RET这样的指令地址来覆盖吗?

A:大多数情况下是这样。

Q:Windows可以确切的定位了,但Linux下有确切的定位ShellCode的方法吗?

A:在Linux下,可以把ShellCode放在环境变量,然后就能确切计算出ShellCode在内存中的地址,也非常精确。

Q:在分析你给的那个例子程序时,发现ESP一来就减很大的值,为什么分配这么大的缓冲器还要溢出呢?

A:分配的空间是系统自己用的。但output[8]还是只分配了8个字节的空间。

Q: 奇怪,在“name”数组比较短的时候,测试会报错;但我按照格式覆盖并加上ShellCode后,结果不但没弹出窗口,连错误也不报了,这是怎么回事啊?(这个问题我就遇到了~~~55555)

A: 是用的覆盖地址不对。而没有报错,是因为你覆盖的字符串太长了,把异常处理点也覆盖了,当然报错对话框也弹不出来了。

使用系统相关的地址,我们马上会在第二章ShellCode的编写中讲到。