引子:分析XP SP2之后的windows系统会经常看到连续的5个nop之后一个mov edi,edi指令,这条指令意义何在?

其实mov edi,edi就是两个字节的nop,作用同2个nop,那么为什么不直接两个nop呢?答案是节省了CPU时钟周期,提高了执行效率。

在vc7\include\listing.inc中详细定义了1到7个字节的类似宏:

;; LISTING.INC
;;
;; This file contains assembler macros and is included by the files created
;; with the -FA compiler switch to be assembled by MASM (Microsoft Macro
;; Assembler).
;;
;; Copyright (c) 1993, Microsoft Corporation. All rights reserved.


;; non destructive nops
npad macro size
if size eq 1
nop
else
if size eq 2
mov edi, edi
else
if size eq 3
; lea ecx, [ecx+00]
DB 8DH, 49H, 00H
else
if size eq 4
; lea esp, [esp+00]
DB 8DH, 64H, 24H, 00H
else
if size eq 5
add eax, DWORD PTR 0
else
if size eq 6
; lea ebx, [ebx+00000000]
DB 8DH, 9BH, 00H, 00H, 00H, 00H
else
if size eq 7
; lea esp, [esp+00000000]
DB 8DH, 0A4H, 24H, 00H, 00H, 00H, 00H
else
%out error: unsupported npad size
.err
endif
endif
endif
endif
endif
endif
endif
endm


;; destructive nops
dpad macro size, reg
if size eq 1
inc reg
else
%out error: unsupported dpad size
.err
endif
endm

回到文章开头,5个nop加上一个mov edi,edi指令巧妙的规避了inline hook实现细节上的一些复杂性。在早些时候,为实现稳定的inline hook,微软专门开发了detours库,其中API开头5个字节的宏定义文件大的让人几乎看不下去,而xp sp2之后这七个字节的设计诞生了一种简单高效的利用方法。

nop
nop
nop
nop
nop
mov edi,edi

只需要简单的改为

jmp xxxxxxx //hook函数地址 5BYTE
jmp short xxxxxxxx //上一个jmp的地址,往回跳5个字节 2BYTE

这样一来,多这么一条mov edi,edi的设计,省去了程序员在PE内部查找连续空间保存原始5字节代码的麻烦,提高了代码执行的稳定性。

本文相关评论 - 1条评论都没有呢

目前还没有评论.