今天同学过生日,出去吃涮羊肉,差点没撑死,一共4个人,羊肉*6,牛肉*2,金丝蘑*5(),小白菜*2,羊肉丸子*2,紫菜*2,白薯*1,人家不给退,我中午还吃了饭,从2点半吃到4点半
undocument windw....书里那个hook nAtive Api的例子没看懂,主要是那个SpyHookInitializeEx,
// -----------------------------------------------------------------
// The SpyHook macro defines a hook entry point in inline assembly
// language. The common entry point SpyHook2 is entered by a call
// instruction, allowing the hook to be identified by its return
// address on the stack. The call is executed through a register to
// remove any degrees of freedom from the encoding of the call.
#define SpyHook /
__asm push eax /
__asm mov eax, offset SpyHook2 /
__asm call eax
// -----------------------------------------------------------------
// The SpyHookInitializeEx() function initializes the aSpyHooks[]
// array with the hook entry points and format strings. It also
// hosts the hook entry points and the hook dispatcher.
void SpyHookInitializeEx (PPBYTE ppbSymbols,
PPBYTE ppbFormats)
{
DWORD dHooks1, dHooks2, i, j, n;
__asm
{
jmp SpyHook9
ALIGN 8
SpyHook1: ; start of hook entry point section
}
// the number of entry points defined in this section
// must be equal to SDT_SYMBOLS_MAX (i.e. 0xF8)
SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook //08
SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook //10
SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook //18
SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook //20
SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook //28
SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook //30
SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook //38
SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook //40
SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook //48
SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook //50
SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook //58
SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook //60
SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook //68
SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook //70
SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook //78
SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook //80
SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook //88
SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook //90
SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook //98
SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook //A0
SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook //A8
SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook //B0
SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook //B8
SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook //C0
SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook //C8
SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook //D0
SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook //D8
SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook //E0
SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook //E8
SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook //F0
SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook SpyHook //F8
__asm
{
SpyHook2: ; end of hook entry point section
pop eax ; get stub return address
pushfd
push ebx
push ecx
push edx
push ebp
push esi
push edi
sub eax, offset SpyHook1 ; compute entry point index
mov ecx, SDT_SYMBOLS_MAX
mul ecx
mov ecx, offset SpyHook2
sub ecx, offset SpyHook1
div ecx
dec eax
mov ecx, gfSpyHookPause ; test pause flag
add ecx, -1 //
sbb ecx, ecx //这三句不知道是怎样test pAuse flAg的
not ecx //
lea edx, [aSpyHooks + eax * SIZE SPY_HOOK_ENTRY] //EAX中是index,edx存入ASpyHooks中相应index的地址,这时候ASpyHooks应该已经和systemtAble交换过呢,但并不交换formAt InterlockedExchange ((PLONG) ServiceTable+i,
( LONG) aSpyHooks [i].Handler); 只交换hAndler
test ecx, [edx.pbFormat] ; format string == NULL?
jz SpyHook5 //SPYHOOK5是一个退出恢复寄存器的过程
push eax
push edx
call PsGetCurrentThreadId ; get thread id
mov ebx, eax //u ebx=threAd id
pop edx
pop eax
cmp ebx, ghSpyHookThread ; ignore hook installer
jz SpyHook5 //不hook 程序自己,,在spyhook5中,把原来系统systemtAble的hAndler地址换回去调用的就是原来的Api了 mov eax, [edx.Handler] 。。。。xchg eax, [esp] ret ; ...jump to handler
mov edi, gpDeviceContext
lea edi, [edi.SpyCalls] ; get call context array //u edi=gpDeviceContext.SpyCAlls
mov esi, SPY_CALLS ; get number of entries //u esi = SPY_CALLS
SpyHook3:
mov ecx, 1 ; set in-use flag
xchg ecx, [edi.fInUse] //gpDeviceContext.SpyCAlls是个数组,从第一个开始找起,找一个未用过的
jecxz SpyHook4 ; unused entry found //当ecx为0时跳转,找到了就去spyhook4
add edi, SIZE SPY_CALL ; try next entry
dec esi
jnz SpyHook3
mov edi, gpDeviceContext
inc [edi.dMisses] ; count misses //这一块是如果把spyCAlls找遍了还没有空的,就把gpDeviceCOntext.dMisses加一后退出,
jmp SpyHook5 ; array overflow
SpyHook4:
mov esi, gpDeviceContext
inc [esi.dLevel] ; set nesting level //可能表示在一个被hook的函数中再调用被hook的函数,嵌套level
mov [edi.hThread], ebx ; save thread id
mov [edi.pshe], edx ; save PSPY_HOOK_ENTRY
mov ecx, offset SpyHook6 ; set new return address
xchg ecx, [esp+20h] //看样 [esp+20h]是 old return Address,20h就是32字节,从前面看的确没错,这个返回地址是在进入SPYHOOK的时候压进栈的
mov [edi.pCaller], ecx ; save old return address
mov ecx, KeServiceDescriptorTable
mov ecx, [ecx].ntoskrnl.ArgumentTable
movzx ecx, byte ptr [ecx+eax] ; get argument stack size //movzx 扩展符号位数据传送
shr ecx, 2
inc ecx ; add 1 for result slot
mov [edi.dParameters], ecx ; save number of parameters
lea edi, [edi.adParameters]
xor eax, eax ; initialize result slot
stosd //将slot存到edi去,值为0
dec ecx
jz SpyHook5 ; no arguments
lea esi, [esp+24h] ; save argument stack
rep movsd //把esi中的传到edi中,esi中不是gpDeviceContext吗
SpyHook5:
mov eax, [edx.Handler] ; get original handler
pop edi
pop esi
pop ebp
pop edx
pop ecx
pop ebx
popfd
xchg eax, [esp] ; restore eax and...
ret ; ...jump to handler
SpyHook6: //spyhook6是调用nAtive Api的函数后的返回地址,也就是在spyhook5执行结束后就会转到spyhook6来
push eax
pushfd
push ebx
push ecx
push edx
push ebp
push esi
push edi
push eax //这个push是和下面的pop eAx一起的
call PsGetCurrentThreadId ; get thread id
mov ebx, eax
pop eax
mov edi, gpDeviceContext
lea edi, [edi.SpyCalls] ; get call context array
mov esi, SPY_CALLS ; get number of entries
SpyHook7:
cmp ebx, [edi.hThread] ; find matching thread id
jz SpyHook8
add edi, SIZE SPY_CALL ; try next entry
dec esi
jnz SpyHook7
push ebx ; entry not found ?!? //fuk! 你自己写的程序你问谁啊
call KeBugCheck
SpyHook8:
push edi ; save SPY_CALL pointer
mov [edi.adParameters], eax ; store NTSTATUS
push edi //两个push edi,,spyhookprotocol到底需要什么参数? 只需要一个,第一个push edi不是参数 靠 行为诡异
call SpyHookProtocol //没有返回值
pop edi ; restore SPY_CALL pointer // 和前面的push保护了edi,不知道为什么要这样做
mov eax, [edi.pCaller]
mov [edi.hThread], 0 ; clear thread id
mov esi, gpDeviceContext
dec [esi.dLevel] ; reset nesting level
dec [edi.fInUse] ; clear in-use flag
pop edi
pop esi
pop ebp
pop edx
pop ecx
pop ebx
popfd
xchg eax, [esp] ; restore eax and... //[esp]里是spyhook6一开始 push进去的 eAx,关键要看,现在eAx把什么东西换进,这样在esp后面的一个那个入栈的就没有,本来应该是在spyhook2一开始就pop EAX的那个 ,,在进spyhook6的时候也是提前一个就ret了,堆栈里没有留下垃圾。。EAX是[edi.pCAller],是调用Api的函数(cAller)的return Address,,这样,一次nAtive Api就结束了,好象还没看到调用真正NAtive Api的地方,,估计是在SpyHookProtocol中,
ret ; ...return to caller
SpyHook9:
mov dHooks1, offset SpyHook1
mov dHooks2, offset SpyHook2
}
n = (dHooks2 - dHooks1) / SDT_SYMBOLS_MAX;
for (i = j = 0; i < SDT_SYMBOLS_MAX; i++, dHooks1 += n)
{
if ((ppbSymbols != NULL) && (ppbFormats != NULL) &&
(ppbSymbols [j] != NULL))
{
aSpyHooks [i].Handler = (NTPROC) dHooks1;
aSpyHooks [i].pbFormat =
SpySearchFormat (ppbSymbols [j++], ppbFormats);
}
else
{
aSpyHooks [i].Handler = NULL;
aSpyHooks [i].pbFormat = NULL;
}
}
return;
}
// -----------------------------------------------------------------
一开始不知道什么时候才执行spyhook1,后来用s-ice调的时候才大概知道什么意思,自己真是笨啊,
每个SpyHook宏都对应一个地址,从这个地址执行下去就执行了宏中SpyHook2的程序,而由于第一句的pop eAx ,所以不会再返回执行下一个SpyHook,函数SpyHookInitializeEx 在一开始就跳转到SpyHook9,把每个标号SpyHook的地址,及ppbSymbols[]中的一个元素放入ASpyHooks[]中,这个数组以后会和sdt里的内容交换。在DriverEntry里是不会执行到SpyHook2的,执行这些汇编语句是在系统调用nAtive Api的时候,本来应该是Api的地址,却被换成了一个个标号spyhook的地址了,,所以程序会转到这里来执行,完成后面的事
spyhook2计算当前是第几个spyhoook,公式是
index = (ReturnAddress-SpyHook1)*SDT_SYMBOLS_MAX/(spyhook2-spyhook1)-1
spyhook2-spyhook1 = sizeof(spyhook)*SDT_SYMBOLS
ReturnAddress 是开始时的pop eAx
MOVZX - Move with Zero Extend (386+)
Usage: MOVZX dest,src
Modifies flags: None
Copies the value of the source operand to the destination register
with the zeroes extended.
Clocks Size
Operands 808x 286 386 486 Bytes
reg,reg - - 3 3 3
reg,mem - - 6 3 3-7
stosd
Save the data in eax to memory ES:[EDI] and increase EDI by 4 and decrease ecx by 1.
and you can use rep stosd to initialize an integer array to the same value,such as
xor eax,eax
mov ecx,10
push es
push ds
pop es
mov edi, pointer of an array
rep stosd
pop es