标 题: 【分享】西裤哥的 Hook Api Lib 0.2 For C
作 者: 海风月影
时 间: 2007-03-21,15:11:30
链 接: http://bbs.pediy.com/showthread.php?t=41387

对xIkUg的hook lib for delphi研究了一番,尤其是里面的GetOpCodeSize是好东西 ,但不太会用delphi,因此转成 VC代码 共享出来。

转好后发现GetOpCodeSize()有点小BUG,草草修正后发上来  

先贴代码,然后再说明


引用:
{
  
NameAPI Hook Lib for C
  Version
0.2
  
Authorcoded by xIkUg/RCT/CCG     modified by 海风月影[NE365]
  
HomePagehttp:
//www.wintoolspro.com, http://debugman.wintoolspro.com
  
CreateDate2006-12-03
  
ModifiedDate:2007-3-21
}

#include <windows.h>
#include <stdio.h>

//#pragma comment(linker, "/subsystem:windows /entry:main")
#pragma comment(linker"/SECTION:.text,REW" //设PE节:.text,可读可执行
#pragma comment(linker"/MERGE:.data=.text"//合并到.text
#pragma comment(linker"/MERGE:.rdata=.text")//合并到.text
//#pragma comment(linker,"/ALIGN:0x200")

static unsigned long MaskTable[518]={
    
0x000040000x000040000x000040000x00004000,
    
0x000080000x000080000x000000000x00000000,
    
0x000040000x000040000x000040000x00004000,
    
0x000080000x000080000x000000000x00000000,
    
0x000040000x000040000x000040000x00004000,
    
0x000080000x000080000x000000000x00000000,
    
0x000040000x000040000x000040000x00004000,
    
0x000080000x000080000x000000000x00000000,
    
0x000040000x000040000x000040000x00004000,
    
0x000080000x000080000x000000080x00000000,
    
0x000040000x000040000x000040000x00004000,
    
0x000080000x000080000x000000080x00000000,
    
0x000040000x000040000x000040000x00004000,
    
0x000080000x000080000x000000080x00000000,
    
0x000040000x000040000x000040000x00004000,
    
0x000080000x000080000x000000080x00000000,
    
0x000000000x000000000x000000000x00000000,
    
0x000000000x000000000x000000000x00000000,
    
0x000000000x000000000x000000000x00000000,
    
0x000000000x000000000x000000000x00000000,
    
0x000000000x000000000x000000000x00000000,
    
0x000000000x000000000x000000000x00000000,
    
0x000000000x000000000x000000000x00000000,
    
0x000000000x000000000x000000000x00000000,
    
0x000000000x000000000x000040000x00004000,
    
0x000000080x000000080x000010080x00000018,
    
0x000020000x000060000x000001000x00004100
// 
    
0x000000000x000000000x000000000x00000000,
    
0x000001000x000001000x000001000x00000100,
    
0x000001000x000001000x000001000x00000100,
    
0x000001000x000001000x000001000x00000100,
    
0x000001000x000001000x000001000x00000100,
    
0x000041000x000060000x000041000x00004100,
    
0x000040000x000040000x000040000x00004000,
    
0x000040000x000040000x000040000x00004000,
    
0x000040000x000040000x000040000x00004000,
    
0x000000000x000000000x000000000x00000000,
    
0x000000000x000000000x000000000x00000000,
    
0x000000000x000000000x000020020x00000000,
    
0x000000000x000000000x000000000x00000000,
    
0x000000200x000000200x000000200x00000020,
    
0x000000000x000000000x000000000x00000000,
    
0x000001000x000020000x000000000x00000000,
    
0x000000000x000000000x000000000x00000000,
    
0x000001000x000001000x000001000x00000100,
    
0x000001000x000001000x000001000x00000100,
    
0x000020000x000020000x000020000x00002000,
    
0x000020000x000020000x000020000x00002000,
    
0x000041000x000041000x000002000x00000000,
    
0x000040000x000040000x000041000x00006000,
    
0x000003000x000000000x000002000x00000000,
    
0x000000000x000000000x000000000x00000000,
    
0x000040000x000040000x000040000x00004000,
    
0x000001000x000001000x000000000x00000000,
    
0x000040000x000040000x000040000x00004000,
    
0x000040000x000040000x000040000x00004000,
    
0x000001000x000001000x000001000x00000100,
    
0x000001000x000001000x000001000x00000100,
    
0x000020000x000020000x000020020x00000100,
    
0x000000000x000000000x000000000x00000000,
    
0x000000080x000000000x000000080x00000008,
    
0x000000000x000000000x000000000x00000000,
    
0x000000000x000000000x000000000x00000000,
    
0x000000000x000000000x000040000x00004000,
    
0x000040000x000040000x000040000x00004000,
    
0xFFFFFFFF0xFFFFFFFF0x000000000xFFFFFFFF,
    
0x000000000x000000000x000000000x00000000,
    
0xFFFFFFFF0xFFFFFFFF0xFFFFFFFF0xFFFFFFFF,
    
0xFFFFFFFF0xFFFFFFFF0xFFFFFFFF0xFFFFFFFF,
    
0xFFFFFFFF0xFFFFFFFF0xFFFFFFFF0xFFFFFFFF,
    
0xFFFFFFFF0xFFFFFFFF0xFFFFFFFF0xFFFFFFFF,
    
0xFFFFFFFF0xFFFFFFFF0xFFFFFFFF0xFFFFFFFF,
    
0xFFFFFFFF0xFFFFFFFF0xFFFFFFFF0xFFFFFFFF,
    
0xFFFFFFFF0xFFFFFFFF0xFFFFFFFF0xFFFFFFFF,
    
0xFFFFFFFF0xFFFFFFFF0xFFFFFFFF0xFFFFFFFF,
    
0xFFFFFFFF0xFFFFFFFF0xFFFFFFFF0xFFFFFFFF,
    
0xFFFFFFFF0xFFFFFFFF0xFFFFFFFF0xFFFFFFFF,
    
0xFFFFFFFF0xFFFFFFFF0xFFFFFFFF0xFFFFFFFF,
    
0xFFFFFFFF0xFFFFFFFF0xFFFFFFFF0xFFFFFFFF,
    
0xFFFFFFFF0xFFFFFFFF0xFFFFFFFF0xFFFFFFFF,
    
0xFFFFFFFF0xFFFFFFFF0xFFFFFFFF0xFFFFFFFF,
    
0xFFFFFFFF0xFFFFFFFF0xFFFFFFFF0xFFFFFFFF,
    
0xFFFFFFFF0xFFFFFFFF0xFFFFFFFF0xFFFFFFFF,
    
0xFFFFFFFF0xFFFFFFFF0xFFFFFFFF0xFFFFFFFF,
    
0xFFFFFFFF0xFFFFFFFF0xFFFFFFFF0xFFFFFFFF,
    
0xFFFFFFFF0xFFFFFFFF0xFFFFFFFF0xFFFFFFFF,
    
0xFFFFFFFF0xFFFFFFFF0xFFFFFFFF0xFFFFFFFF,
    
0xFFFFFFFF0xFFFFFFFF0xFFFFFFFF0xFFFFFFFF,
    
0xFFFFFFFF0xFFFFFFFF0xFFFFFFFF0xFFFFFFFF,
    
0xFFFFFFFF0xFFFFFFFF0xFFFFFFFF0xFFFFFFFF,
    
0xFFFFFFFF0xFFFFFFFF0xFFFFFFFF0xFFFFFFFF,
    
0xFFFFFFFF0xFFFFFFFF0xFFFFFFFF0xFFFFFFFF,
    
0xFFFFFFFF0xFFFFFFFF0xFFFFFFFF0xFFFFFFFF,
    
0xFFFFFFFF0xFFFFFFFF0xFFFFFFFF0xFFFFFFFF,
    
0xFFFFFFFF0xFFFFFFFF0xFFFFFFFF0xFFFFFFFF,
    
0xFFFFFFFF0xFFFFFFFF0xFFFFFFFF0xFFFFFFFF,
    
0x000020000x000020000x000020000x00002000,
    
0x000020000x000020000x000020000x00002000,
    
0x000020000x000020000x000020000x00002000,
    
0x000020000x000020000x000020000x00002000,
    
0x000040000x000040000x000040000x00004000,
    
0x000040000x000040000x000040000x00004000,
    
0x000040000x000040000x000040000x00004000,
    
0x000040000x000040000x000040000x00004000,
    
0x000000000x000000000x000000000x00004000,
    
0x000041000x000040000xFFFFFFFF0xFFFFFFFF,
    
0x000000000x000000000x000000000x00004000,
    
0x000041000x000040000xFFFFFFFF0x00004000,
    
0x000040000x000040000x000040000x00004000,
    
0x000040000x000040000x000040000x00004000,
    
0xFFFFFFFF0xFFFFFFFF0x000041000x00004000,
    
0x000040000x000040000x000040000x00004000,
    
0x000040000x000040000xFFFFFFFF0xFFFFFFFF,
    
0xFFFFFFFF0xFFFFFFFF0xFFFFFFFF0xFFFFFFFF,
    
0x000000000x000000000x000000000x00000000,
    
0x000000000x000000000x000000000x00000000,
    
0xFFFFFFFF0xFFFFFFFF0xFFFFFFFF0xFFFFFFFF,
    
0xFFFFFFFF0xFFFFFFFF0xFFFFFFFF0xFFFFFFFF,
    
0xFFFFFFFF0xFFFFFFFF0xFFFFFFFF0xFFFFFFFF,
    
0xFFFFFFFF0xFFFFFFFF0xFFFFFFFF0xFFFFFFFF,
    
0xFFFFFFFF0xFFFFFFFF0xFFFFFFFF0xFFFFFFFF,
    
0xFFFFFFFF0xFFFFFFFF0xFFFFFFFF0xFFFFFFFF,
    
0xFFFFFFFF0xFFFFFFFF0xFFFFFFFF0xFFFFFFFF,
    
0xFFFFFFFF0xFFFFFFFF0xFFFFFFFF0xFFFFFFFF,
    
0xFFFFFFFF0xFFFFFFFF0xFFFFFFFF0xFFFFFFFF,
    
0xFFFFFFFF0xFFFFFFFF0xFFFFFFFF0xFFFFFFFF,
    
0xFFFFFFFF0xFFFFFFFF0xFFFFFFFF0xFFFFFFFF,
    
0xFFFFFFFF0xFFFFFFFF0xFFFFFFFF0xFFFFFFFF,
    
0x000000000xFFFFFFFF0xFFFFFFFF0xFFFFFFFF,
    
0xFFFFFFFF0xFFFFFFFF
};

BYTE JMPGate[5] = { 
    
0xE90x000x000x000x00   
// JMP XXXXXXXX
};

BYTE   BeforeStub[94] ={
    
0x58,                                
// 0 pop     eax
    
0xEB0x08,                          // 1 jmp     short 0040100B
    
0x000x000x000x00,              // 3 dd      00000000
    
0x000x000x000x00,              // 7 dd      00000000
    
0xE80x000x000x000x00,        // 11 call    00401010
    
0x59,                                // 16 pop     ecx
    
0x810xE90x100x100x400x00,  // 17 sub     ecx, 00401010
    
0x890xA10x030x100x400x00,  // 23 mov     [ecx+401003], esp
    
0x890x810x070x100x400x00,  // 29 mov     [ecx+401007], eax
    
0xE80x360x010x000x00,        // 35 call    HookProc 这里动态改变地址
    
0x8B0x440x240xFC,              // 40 mov     eax, [esp - 4]
    
0xE80x000x000x000x00,        // 44 call    0040102D
    
0x59,                                // 49 pop     ecx
    
0x890x440x240xFC,              // 50 mov [esp - 4], eax
    
0x810xE90x310x100x400x00,  // 54 sub     ecx, 0040102D
    
0x8B0xA10x030x100x400x00,  // 60 mov     esp, [ecx+401003]
    
0x8B0x810x070x100x400x00,  // 66 mov     eax, [ecx+401007]
    
0x50,                                // 72 push    eax
    
0x900x900x900x90,              // 73 保存入口处代码 16字节
    
0x900x900x900x90,                 
    
0x900x900x900x90,
    
0x900x900x900x90,   
    
0xE90x180x010x000x00         
// 89 jmp     HookedApi
};

BYTE AfterStub[130] = {
    
0x58,                                
// 00   pop     eax
    
0xEB0x0C,                          // 01   jmp     short 0040100F
    
0x000x000x000x00,              // 03   dd      00000000
    
0x000x000x000x00,              // 07   add     [eax], al
    
0x000x000x000x00,              // 0B   add     [eax], al
    
0xE80x000x000x000x00,        // 0F   call    00401014
    
0x59,                                // 14   pop     ecx
    
0x810xE90x140x100x400x00,  // 15   sub     ecx, 00401014
    
0x890xA10x030x100x400x00,  // 1B   mov     [ecx+401003], esp
    
0x890x810x070x100x400x00,  // 21   mov     [ecx+401007], eax
    
0x8D0x890x430x100x400x00,  // 27   lea     ecx, [ecx+401043] //api返回地址
    
0x51,                                // 2D   push    ecx   //入栈,这样调用完API就回到0x43处了
    
0x90,                                // 2E   nop  保存入口处代码 16字节
    
0x90,                                // 2F   nop
    
0x90,                                // 30   nop
    
0x90,                                // 31   nop
    
0x90,                                // 32   nop
    
0x90,                                // 33   nop
    
0x90,                                // 34   nop
    
0x90,                                // 35   nop
    
0x90,                                // 36   nop
    
0x90,                                // 37   nop
    
0x90,                                // 38   nop
    
0x90,                                // 39   nop
    
0x90,                                // 3A   nop
    
0x90,                                // 3B   nop
    
0x90,                                // 3C   nop
    
0x90,                                // 3D   nop
    
0xE90x570x010x000x00,        // 3E   jmp     0040119A //跳回API入口
    
0x8B0x5C0x240xFC,              // 43   mov     ebx, [esp-4] //api 返回地址
    
0xE80x000x000x000x00,        // 47   call    0040104C
    
0x59,                                // 4C   pop     ecx
    
0x890x5C0x240xFC,              // 4D   mov     [esp-4], ebx
    
0x810xE90x4C0x100x400x00,  // 51   sub     ecx, 0040104C
    
0x890x810x0B0x100x400x00,  // 57   mov     [ecx+40100B], eax
    
0x8B0xA10x030x100x400x00,  // 5D   mov     esp, [ecx+401003]
    
0xE80x320x010x000x00,        // 63   call    0040119A   // call HookAfter
    
0xE80x000x000x000x00,        // 68   call    0040106D
    
0x59,                                // 6D   pop     ecx
    
0x810xE90x6D0x100x400x00,  // 6E   sub     ecx, 0040106D
    
0x8B0x810x070x100x400x00,  // 74   mov     eax, [ecx+401007]
    
0x50,                                // 7A   push    eax
    
0x8B0x810x0B0x100x400x00,  // 7B   mov     eax, [ecx+40100B]
    
0xC3                                 // 81   retn
};



int GetOpCodeSize(PVOID Start);
boolean SetOnBefore(PCHAR DllName,PCHAR ApiName,PVOID HookProc);
boolean SetOnAfter(PCHAR DllName,PCHAR ApiName,PVOID HookProc);


boolean SetOnBefore(PCHAR DllName,PCHAR ApiName,PVOID HookProc)
{
    
PVOID    ApiEntry;
    
HMODULE DllHandle;
    
int ReplaceCodeSize;
    
BYTE OpCode[16];
    
LPVOID StubPtr;
    
DWORD Addr;
    
DWORD RetSize;

    
DllHandle GetModuleHandle(DllName);
    
if (DllHandle ==0)
    {
        
DllHandle LoadLibrary(DllName);
        
if (DllHandle ==0return false;
    }

    
ApiEntry GetProcAddress(DllHandle,ApiName);
    
if (ApiEntry == NULLreturn false;
    
    
ReplaceCodeSize GetOpCodeSize(ApiEntry);
    
    
while (ReplaceCodeSize 5)
        
ReplaceCodeSize += GetOpCodeSize((PVOID)((DWORD)ApiEntry + (DWORD)ReplaceCodeSize));

    
if (ReplaceCodeSize 16return false;

    
if (VirtualProtect(ApiEntry,ReplaceCodeSize,PAGE_READWRITE,NULL))
        
return false;

    
CopyMemory(OpCodeApiEntryReplaceCodeSize);

    
StubPtr VirtualAlloc(NULLsizeof(BeforeStub), MEM_COMMITPAGE_EXECUTE_READWRITE);
    
    
if (StubPtr == NULLreturn false;

    
CopyMemory(StubPtrBeforeStubsizeof(BeforeStub));

    
Addr = (DWORD)HookProc - (DWORD)StubPtr 35 5;
    *(
DWORD *) ((DWORD)StubPtr 36) = Addr;

    
Addr = (DWORD)ApiEntry ReplaceCodeSize - (DWORD)StubPtr 89 5;
    *(
DWORD *) ((DWORD)StubPtr 90) = Addr;

    
CopyMemory((LPVOID)((DWORD)StubPtr 73), OpCodeReplaceCodeSize);

    
Addr = (DWORD)StubPtr - (DWORD)ApiEntry 5;
    *(
DWORD*)(JMPGate 1) = Addr;
    
    
WriteProcessMemory(GetCurrentProcess(), ApiEntryJMPGatesizeof(JMPGate), (DWORD*)RetSize);

    
return true;
}

boolean SetOnAfter(PCHAR DllName,PCHAR ApiName,PVOID HookProc)
{
    
PVOID    ApiEntry;
    
HMODULE DllHandle;
    
int ReplaceCodeSize;
    
BYTE OpCode[16];
    
LPVOID StubPtr;
    
DWORD Addr;
    
DWORD RetSize;    

    
DllHandle GetModuleHandle(DllName);
    
if (DllHandle ==0)
    {
        
DllHandle LoadLibrary(DllName);
        
if (DllHandle ==0return false;
    }

    
ApiEntry GetProcAddress(DllHandle,ApiName);
    
if (ApiEntry == NULLreturn false;
    
    
ReplaceCodeSize GetOpCodeSize(ApiEntry);
    
    
while (ReplaceCodeSize 5)
        
ReplaceCodeSize += GetOpCodeSize((PVOID)((DWORD)ApiEntry + (DWORD)ReplaceCodeSize));

    
if (ReplaceCodeSize 16return false;

    
if (VirtualProtect(ApiEntry,ReplaceCodeSize,PAGE_READWRITE,NULL))
        
return false;

    
CopyMemory(OpCodeApiEntryReplaceCodeSize);

    
StubPtr VirtualAlloc(NULLsizeof(AfterStub), MEM_COMMITPAGE_EXECUTE_READWRITE);
    
    
if (StubPtr == NULLreturn false;

    
CopyMemory(StubPtrAfterStubsizeof(AfterStub));

    
Addr = (DWORD)HookProc - (DWORD)StubPtr 0x63 5;
    *(
DWORD *) ((DWORD)StubPtr 0x64) = Addr;

    
Addr = (DWORD)ApiEntry ReplaceCodeSize - (DWORD)StubPtr 0x3E 5;
    *(
DWORD *) ((DWORD)StubPtr 0x3F) = Addr;

    
CopyMemory((LPVOID)((DWORD)StubPtr 0x2E), OpCodeReplaceCodeSize);

    
Addr = (DWORD)StubPtr - (DWORD)ApiEntry 5;
    *(
DWORD*)(JMPGate 1) = Addr;
    
    
WriteProcessMemory(GetCurrentProcess(), ApiEntryJMPGatesizeof(JMPGate), (DWORD*)RetSize);

    
return true;
}


int GetOpCodeSize(PVOID Start)
{
/* 为了防止某些网站转贴时斩头去尾留中间,将信息在此COPY一份
{
  Name: API Hook Lib for C
  Version: 0.2
  Author: coded by xIkUg/RCT/CCG     modified by 海风月影[NE365]
  HomePage: http://www.wintoolspro.com, http://debugman.wintoolspro.com
  CreateDate: 2006-12-03
  ModifiedDate:2007-3-21
}

*/
    
DWORDTlb=(DWORD*)MaskTable;
    
PBYTE pOPCode;
    
DWORD tc;
    
BYTE dhdlal;
    
int OpCodeSize =-1;
    
    
0;
    
pOPCode = (PBYTEStart;
    
0;

    
do {
        
&= 0x0F7;
        
= *(BYTE *) pOPCode++;
        
|= Tlb[c] ;
        
    } 
while( ((0x000000FF) & 8) != 0);
    
    
if ((== 0x0F6) || (== 0x0F7))
    {
        
|= 0x00004000;
        
if ( (0x38 & *(BYTE *) pOPCode++) == 0)
            
|= 0x00008000;
    }
    
else if (== 0x0CD)
    {
        
|= 0x00000100;
        
if ( (*(BYTE *) pOPCode++) == 0x20)
            
|= 0x00000400;
    }
    
else if (== 0x0F)
    {
        
al = *(BYTE *) pOPCode++;
        
|= Tlb[al 0x100];
        
if (== 0xFFFFFFFF)
            
return OpCodeSize;
    }

    
if ((((0x0000FF00) >> 8) & 0x80) != 0)
    {
        
dh = (0x0000FF00) >> 8;
        
dh ^= 0x20;
        
if ((1) == 0
            
dh ^= 0x21;
        
&= 0xFFFF00FF;
        
|= (dh << 8);
    }
    
    
if ((((0x0000FF00) >> 8) & 0x40) != 
    {
        
al = *(BYTE *) pOPCode++;
        
= (DWORD)al;
        
|= (al << 8);
        
&= 0xC007;
        
if ( (0x0000FF00) != 0xC000 )
        {
            
if ( ((0x000000FF) & 0x10) == 0)
            {
                
if ((0x000000FF) == 4)
                {
                    
al = *(BYTE *) pOPCode++;
                    
al &= 7;
                    
&= 0x0000FF00;
                    
|= al;
                }
                
                
if ((0x0000FF00) != 0x4000)
                {
                    
if ((0x0000FF00) == 0x8000)    |= 4;
                    
else if (c==5|= 4;
                }
                
else
                    
|= 1;

            }
            
else
            
{
                
if (!= 6)
                {
                    
if((0x0000FF00) == 0x4000)
                        
|= 1;
                    
else if ((0x0000FF00) == 0x8000
                        
|= 2;
                }
                
else
                    
|= 2;
            }
        }
    }

    
if ((((0x000000FF)) & 0x20) != 0)
    {
        
dl 0x000000FF;
        
dl ^= 2;
        
&= 0xFFFFFF00;
        
|= dl;
        
if ((dl 0x10) == 0)
        {
            
dl ^= 6;
            
&= 0xFFFFFF00;
            
|= dl;
        }
    }

    
if ((((0x0000FF00) >> 8) & 0x20) != 0)
    {
        
dh = (0x0000FF00) >> 8;
        
dh ^= 2;   
        
&= 0xFFFF00FF;
        
|= (dh << 8);
        
if ((dh 0x10) == 0)
        {
            
if (dh 0x40
//是否是 0x6x
                
dh ^= 1;   // 当dh = 0x2x 这里计算多2,当=62的时候却是 异或1
            
&= 0xFFFFFF00;
            
|= dh;
        }
    }
    
    
OpCodeSize = (DWORDpOPCode - (DWORDStart;
    
&= 0x707;
    
OpCodeSize += 0x000000FF;
    
OpCodeSize += (0x0000FF00) >> 8;
/*
    一旦OpCode是 66 开头,会出问题
    如,第一个例子
    66:814D E4 0103   or      word ptr ss:[ebp-1C], 301  
    计算出来是8,其实是 814D E4 01030000 的7位 加上66一个字节

    而,第二个例子
    66:8906           mov     word ptr ds:[esi], ax    
    正确,是3

    原因是这样的
    引用老罗的Learningopcode:
//////////////////////////////////////////////////////////////////////////

现在我们将要学习剩下的几个Prefixes,它们可以被划分为5个集合,分别是:

Change DEFAULT operand size. (66)
Change DEFAULT address size. (67)
Repeat prefixes. (F2, F3)
Segment override prefixes(change DEFAULT segment). (2E, 36, 3E, 26, 64, 65)
LOCK prefix. (F0)

prefix 66的作用是切换默认的操作数大小。请注意我们并没有说“指定”,
而是“切换”!反映到这个例子中,就是“切换默认的32位操作数到16位”
,而不是“指定操作数的大小为16位”。

也许并不是所有情况下的操作数大小都可以随意改变的。
假如这个改变是不允许的,那么它就会被忽略。
//////////////////////////////////////////////////////////////////////////
    
    因此,第一个例子操作数从32位变成了16位,第二个例子无法改变,所以就没变

    因此,此算法没有考虑prefix 66开头的变化,要加上66开头的处理
    66也占一个字节,因此,第一个其实是 8
    
*/
/*
    单独处理 66 开头的问题
    1字节66 ,1字节操作码,4字节操作数,因此至少要大于等于6以上
    如 

    0040A339      66:B8 FF00    mov     ax, 0FF
    0040A33D      0000          add     byte ptr ds:[eax], al

    ★我们这里假设windows 32位系统中没有单独操作16位的OpCode(事实估计也是这样的)
*/
    
if (((*(char*)Start) & 0x000000FF) == 0x66)    
        
if OpCodeSize >= 6)   
            
OpCodeSize -= 2;   
//减2处理 ,将 dword 型转成 word 型

    
return OpCodeSize;
}

int main()
{
    
//Just for test
    
HMODULE hModule;
    
hModule GetModuleHandle("Kernel32.dll");
    
PVOID ApiEntry GetProcAddress(hModule,"GetVolumeInformationW");
    
int a,b,i;
    
GetOpCodeSize(ApiEntry);
    
0;
    
while (507
    {
        
for (0;bi++)
        {
            
printf("%02X ",(*(char *)((DWORD)ApiEntry + (DWORD)+(DWORD)i)) & 0x000000FF);
        }
        
a+=b;
        
printf("     %d\n",b);
        
GetOpCodeSize((PVOID)((DWORD)ApiEntry +(DWORD)a));
    }

    
return 0;
}

GetOpCodeSize()对某些命令会算错,经多次试验,排查,发现问题在这里

代码:
if ((dh & 0x10) == 0)
{
    dh ^= 6;   // 这里不能异或6,是异或1,而且不是所以情况都要异或
    t &= 0xFFFFFF00;
    t |= dh;
}
改成这个,就可以了(我没研究到底为什么,反正能用就行)
代码:
if (dh & 0x40) //是否是 0x6x
    dh ^= 1;   // 当dh = 0x2x 这里计算多2,当=62的时候却是 异或1
还有一个问题,应该是GetOpCodeSize本身的问题了

/*
  一旦OpCode以Prefix 66 开头,会出问题
  如,第一个例子
  66:814D E4 0103   or      word ptr ss:[ebp-1C], 301  
  计算出来是8,其实是 814D E4 01030000 的7位 加上66一个字节

  而,第二个例子
  66:8906           mov     word ptr ds:[esi], ax  
  正确,是3

  原因是这样的
  引用老罗的Learningopcode:
//////////////////////////////////////////////////////////////////////////

现在我们将要学习剩下的几个Prefixes,它们可以被划分为5个集合,分别是:

Change DEFAULT operand size. (66)
Change DEFAULT address size. (67)
Repeat prefixes. (F2, F3)
Segment override prefixes(change DEFAULT segment). (2E, 36, 3E, 26, 64, 65)
LOCK prefix. (F0)

prefix 66的作用是切换默认的操作数大小。请注意我们并没有说“指定”,
而是“切换”!反映到这个例子中,就是“切换默认的32位操作数到16位”
,而不是“指定操作数的大小为16位”。

也许并不是所有情况下的操作数大小都可以随意改变的。
假如这个改变是不允许的,那么它就会被忽略。
//////////////////////////////////////////////////////////////////////////
  
  因此,第一个例子操作数从32位变成了16位,第二个例子无法改变,所以就没变

  因此,此算法没有考虑prefix 66开头的变化,要加上66开头的处理
  66也占一个字节,因此,第一个其实是 8
*/

这里我是在最后进行修正的,前面那些分支就没去管它  

修正如下:
/*
  单独处理 66 开头的问题
  1字节66 ,1字节操作码,4字节操作数,因此至少要大于等于6以上
  如 

  0040A339      66:B8 FF00    mov     ax, 0FF
  0040A33D      0000          add     byte ptr ds:[eax], al

  ★我们这里假设windows 32位系统中没有单独操作16位的OpCode(事实估计也是这样的 )
*/
代码:
  if (((*(char*)Start) & 0x000000FF) == 0x66)  // 单独处理 66 开头的问题
    if ( OpCodeSize >= 6)   //1字节66 ,1字节操作码,4字节操作数,因此至少要大于等于6以上
      OpCodeSize -= 2;   //减2处理 ,将 dword 型转成 word 型
上面的代码里有个main(),我测试了一下GetVolumeInformationW这个API函数,一共500+个字节,用OD反汇编对照了一下,OpCode长度没判断错,暂且认为它已经正确了吧,下面就可以用GetOpCodeSize干点坏事了,哈哈  

thx to xIkUg,luocong

posted on 2011-03-17 14:14  pearry  阅读(419)  评论(0编辑  收藏  举报