首页
论坛
课程
招聘
[分享]西裤哥的 Hook Api Lib 0.2 For C
2007-3-21 15:11 16818

[分享]西裤哥的 Hook Api Lib 0.2 For C

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

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

先贴代码,然后再说明


{
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
}

#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]={
0x00004000, 0x00004000, 0x00004000, 0x00004000,
0x00008000, 0x00008000, 0x00000000, 0x00000000,
0x00004000, 0x00004000, 0x00004000, 0x00004000,
0x00008000, 0x00008000, 0x00000000, 0x00000000,
0x00004000, 0x00004000, 0x00004000, 0x00004000,
0x00008000, 0x00008000, 0x00000000, 0x00000000,
0x00004000, 0x00004000, 0x00004000, 0x00004000,
0x00008000, 0x00008000, 0x00000000, 0x00000000,
0x00004000, 0x00004000, 0x00004000, 0x00004000,
0x00008000, 0x00008000, 0x00000008, 0x00000000,
0x00004000, 0x00004000, 0x00004000, 0x00004000,
0x00008000, 0x00008000, 0x00000008, 0x00000000,
0x00004000, 0x00004000, 0x00004000, 0x00004000,
0x00008000, 0x00008000, 0x00000008, 0x00000000,
0x00004000, 0x00004000, 0x00004000, 0x00004000,
0x00008000, 0x00008000, 0x00000008, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00004000, 0x00004000,
0x00000008, 0x00000008, 0x00001008, 0x00000018,
0x00002000, 0x00006000, 0x00000100, 0x00004100, //
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000100, 0x00000100, 0x00000100, 0x00000100,
0x00000100, 0x00000100, 0x00000100, 0x00000100,
0x00000100, 0x00000100, 0x00000100, 0x00000100,
0x00000100, 0x00000100, 0x00000100, 0x00000100,
0x00004100, 0x00006000, 0x00004100, 0x00004100,
0x00004000, 0x00004000, 0x00004000, 0x00004000,
0x00004000, 0x00004000, 0x00004000, 0x00004000,
0x00004000, 0x00004000, 0x00004000, 0x00004000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00002002, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000020, 0x00000020, 0x00000020, 0x00000020,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000100, 0x00002000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000100, 0x00000100, 0x00000100, 0x00000100,
0x00000100, 0x00000100, 0x00000100, 0x00000100,
0x00002000, 0x00002000, 0x00002000, 0x00002000,
0x00002000, 0x00002000, 0x00002000, 0x00002000,
0x00004100, 0x00004100, 0x00000200, 0x00000000,
0x00004000, 0x00004000, 0x00004100, 0x00006000,
0x00000300, 0x00000000, 0x00000200, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00004000, 0x00004000, 0x00004000, 0x00004000,
0x00000100, 0x00000100, 0x00000000, 0x00000000,
0x00004000, 0x00004000, 0x00004000, 0x00004000,
0x00004000, 0x00004000, 0x00004000, 0x00004000,
0x00000100, 0x00000100, 0x00000100, 0x00000100,
0x00000100, 0x00000100, 0x00000100, 0x00000100,
0x00002000, 0x00002000, 0x00002002, 0x00000100,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000008, 0x00000000, 0x00000008, 0x00000008,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00004000, 0x00004000,
0x00004000, 0x00004000, 0x00004000, 0x00004000,
0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0xFFFFFFFF,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0x00002000, 0x00002000, 0x00002000, 0x00002000,
0x00002000, 0x00002000, 0x00002000, 0x00002000,
0x00002000, 0x00002000, 0x00002000, 0x00002000,
0x00002000, 0x00002000, 0x00002000, 0x00002000,
0x00004000, 0x00004000, 0x00004000, 0x00004000,
0x00004000, 0x00004000, 0x00004000, 0x00004000,
0x00004000, 0x00004000, 0x00004000, 0x00004000,
0x00004000, 0x00004000, 0x00004000, 0x00004000,
0x00000000, 0x00000000, 0x00000000, 0x00004000,
0x00004100, 0x00004000, 0xFFFFFFFF, 0xFFFFFFFF,
0x00000000, 0x00000000, 0x00000000, 0x00004000,
0x00004100, 0x00004000, 0xFFFFFFFF, 0x00004000,
0x00004000, 0x00004000, 0x00004000, 0x00004000,
0x00004000, 0x00004000, 0x00004000, 0x00004000,
0xFFFFFFFF, 0xFFFFFFFF, 0x00004100, 0x00004000,
0x00004000, 0x00004000, 0x00004000, 0x00004000,
0x00004000, 0x00004000, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0x00000000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF
};

BYTE JMPGate[5] = {
0xE9, 0x00, 0x00, 0x00, 0x00 // JMP XXXXXXXX
};

BYTE BeforeStub[94] ={
0x58, // 0 pop eax
0xEB, 0x08, // 1 jmp short 0040100B
0x00, 0x00, 0x00, 0x00, // 3 dd 00000000
0x00, 0x00, 0x00, 0x00, // 7 dd 00000000
0xE8, 0x00, 0x00, 0x00, 0x00, // 11 call 00401010
0x59, // 16 pop ecx
0x81, 0xE9, 0x10, 0x10, 0x40, 0x00, // 17 sub ecx, 00401010
0x89, 0xA1, 0x03, 0x10, 0x40, 0x00, // 23 mov [ecx+401003], esp
0x89, 0x81, 0x07, 0x10, 0x40, 0x00, // 29 mov [ecx+401007], eax
0xE8, 0x36, 0x01, 0x00, 0x00, // 35 call HookProc 这里动态改变地址
0x8B, 0x44, 0x24, 0xFC, // 40 mov eax, [esp - 4]
0xE8, 0x00, 0x00, 0x00, 0x00, // 44 call 0040102D
0x59, // 49 pop ecx
0x89, 0x44, 0x24, 0xFC, // 50 mov [esp - 4], eax
0x81, 0xE9, 0x31, 0x10, 0x40, 0x00, // 54 sub ecx, 0040102D
0x8B, 0xA1, 0x03, 0x10, 0x40, 0x00, // 60 mov esp, [ecx+401003]
0x8B, 0x81, 0x07, 0x10, 0x40, 0x00, // 66 mov eax, [ecx+401007]
0x50, // 72 push eax
0x90, 0x90, 0x90, 0x90, // 73 保存入口处代码 16字节
0x90, 0x90, 0x90, 0x90,
0x90, 0x90, 0x90, 0x90,
0x90, 0x90, 0x90, 0x90,
0xE9, 0x18, 0x01, 0x00, 0x00 // 89 jmp HookedApi
};

BYTE AfterStub[130] = {
0x58, // 00 pop eax
0xEB, 0x0C, // 01 jmp short 0040100F
0x00, 0x00, 0x00, 0x00, // 03 dd 00000000
0x00, 0x00, 0x00, 0x00, // 07 add [eax], al
0x00, 0x00, 0x00, 0x00, // 0B add [eax], al
0xE8, 0x00, 0x00, 0x00, 0x00, // 0F call 00401014
0x59, // 14 pop ecx
0x81, 0xE9, 0x14, 0x10, 0x40, 0x00, // 15 sub ecx, 00401014
0x89, 0xA1, 0x03, 0x10, 0x40, 0x00, // 1B mov [ecx+401003], esp
0x89, 0x81, 0x07, 0x10, 0x40, 0x00, // 21 mov [ecx+401007], eax
0x8D, 0x89, 0x43, 0x10, 0x40, 0x00, // 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
0xE9, 0x57, 0x01, 0x00, 0x00, // 3E jmp 0040119A //跳回API入口
0x8B, 0x5C, 0x24, 0xFC, // 43 mov ebx, [esp-4] //api 返回地址
0xE8, 0x00, 0x00, 0x00, 0x00, // 47 call 0040104C
0x59, // 4C pop ecx
0x89, 0x5C, 0x24, 0xFC, // 4D mov [esp-4], ebx
0x81, 0xE9, 0x4C, 0x10, 0x40, 0x00, // 51 sub ecx, 0040104C
0x89, 0x81, 0x0B, 0x10, 0x40, 0x00, // 57 mov [ecx+40100B], eax
0x8B, 0xA1, 0x03, 0x10, 0x40, 0x00, // 5D mov esp, [ecx+401003]
0xE8, 0x32, 0x01, 0x00, 0x00, // 63 call 0040119A // call HookAfter
0xE8, 0x00, 0x00, 0x00, 0x00, // 68 call 0040106D
0x59, // 6D pop ecx
0x81, 0xE9, 0x6D, 0x10, 0x40, 0x00, // 6E sub ecx, 0040106D
0x8B, 0x81, 0x07, 0x10, 0x40, 0x00, // 74 mov eax, [ecx+401007]
0x50, // 7A push eax
0x8B, 0x81, 0x0B, 0x10, 0x40, 0x00, // 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 ==0) return false;
}

ApiEntry = GetProcAddress(DllHandle,ApiName);
if (ApiEntry == NULL) return false;

ReplaceCodeSize = GetOpCodeSize(ApiEntry);

while (ReplaceCodeSize < 5)
ReplaceCodeSize += GetOpCodeSize((PVOID)((DWORD)ApiEntry + (DWORD)ReplaceCodeSize));

if (ReplaceCodeSize > 16) return false;

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

CopyMemory(OpCode, ApiEntry, ReplaceCodeSize);

StubPtr = VirtualAlloc(NULL, sizeof(BeforeStub), MEM_COMMIT, PAGE_EXECUTE_READWRITE);

if (StubPtr == NULL) return false;

CopyMemory(StubPtr, BeforeStub, sizeof(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), OpCode, ReplaceCodeSize);

Addr = (DWORD)StubPtr - (DWORD)ApiEntry - 5;
*(
DWORD*)(JMPGate + 1) = Addr;

WriteProcessMemory(GetCurrentProcess(), ApiEntry, JMPGate, sizeof(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 ==0) return false;
}

ApiEntry = GetProcAddress(DllHandle,ApiName);
if (ApiEntry == NULL) return false;

ReplaceCodeSize = GetOpCodeSize(ApiEntry);

while (ReplaceCodeSize < 5)
ReplaceCodeSize += GetOpCodeSize((PVOID)((DWORD)ApiEntry + (DWORD)ReplaceCodeSize));

if (ReplaceCodeSize > 16) return false;

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

CopyMemory(OpCode, ApiEntry, ReplaceCodeSize);

StubPtr = VirtualAlloc(NULL, sizeof(AfterStub), MEM_COMMIT, PAGE_EXECUTE_READWRITE);

if (StubPtr == NULL) return false;

CopyMemory(StubPtr, AfterStub, sizeof(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), OpCode, ReplaceCodeSize);

Addr = (DWORD)StubPtr - (DWORD)ApiEntry - 5;
*(
DWORD*)(JMPGate + 1) = Addr;

WriteProcessMemory(GetCurrentProcess(), ApiEntry, JMPGate, sizeof(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
}

*/
DWORD* Tlb=(DWORD*)MaskTable;
PBYTE pOPCode;
DWORD t, c;
BYTE dh, dl, al;
int OpCodeSize =-1;

t = 0;
pOPCode = (PBYTE) Start;
c = 0;

do {
t &= 0x0F7;
c = *(BYTE *) pOPCode++;
t |= Tlb[c] ;

}
while( ((t & 0x000000FF) & 8) != 0);

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

if ((((t & 0x0000FF00) >> 8) & 0x80) != 0)
{
dh = (t & 0x0000FF00) >> 8;
dh ^= 0x20;
if ((c & 1) == 0)
dh ^= 0x21;
t &= 0xFFFF00FF;
t |= (dh << 8);
}

if ((((t & 0x0000FF00) >> 8) & 0x40) != 0 )
{
al = *(BYTE *) pOPCode++;
c = (DWORD)al;
c |= (al << 8);
c &= 0xC007;
if ( (c & 0x0000FF00) != 0xC000 )
{
if ( ((t & 0x000000FF) & 0x10) == 0)
{
if ((c & 0x000000FF) == 4)
{
al = *(BYTE *) pOPCode++;
al &= 7;
c &= 0x0000FF00;
c |= al;
}

if ((c & 0x0000FF00) != 0x4000)
{
if ((c & 0x0000FF00) == 0x8000) t |= 4;
else if (c==5) t |= 4;
}
else
t |= 1;

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

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

if ((((t & 0x0000FF00) >> 8) & 0x20) != 0)
{
dh = (t & 0x0000FF00) >> 8;
dh ^= 2;
t &= 0xFFFF00FF;
t |= (dh << 8);
if ((dh & 0x10) == 0)
{
if (dh & 0x40) //是否是 0x6x
dh ^= 1; // 当dh = 0x2x 这里计算多2,当=62的时候却是 异或1
t &= 0xFFFFFF00;
t |= dh;
}
}

OpCodeSize = (DWORD) pOPCode - (DWORD) Start;
t &= 0x707;
OpCodeSize += t & 0x000000FF;
OpCodeSize += (t & 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;
b = GetOpCodeSize(ApiEntry);
a = 0;
while (a < 507)
{
for (i = 0;i < b; i++)
{
printf("%02X ",(*(char *)((DWORD)ApiEntry + (DWORD)a +(DWORD)i)) & 0x000000FF);
}
a+=b;
printf(" %d\n",b);
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


第五届安全开发者峰会(SDC 2021)10月23日上海召开!限时2.5折门票(含自助午餐1份)

收藏
点赞0
打赏
分享
最新回复 (22)
雪    币: 521
活跃值: 活跃值 (134)
能力值: (RANK:570 )
在线值:
发帖
回帖
粉丝
笨笨雄 活跃值 14 2007-3-21 15:38
2
0
DELPHI转换C有什么工具?

还是人工转换的?

弱弱的问

MASKTABLE只有512的大小,是否不支持3BYTE OPCODE的长度计算?
雪    币: 1931
活跃值: 活跃值 (853)
能力值: (RANK:770 )
在线值:
发帖
回帖
粉丝
海风月影 活跃值 18 2007-3-21 16:30
3
0
最初由 笨笨雄 发布
DELPHI转换C有什么工具?

还是人工转换的?

弱弱的问

MASKTABLE只有512的大小,是否不支持3BYTE OPCODE的长度计算?


手工改的

MASKTABLE据xIkUg说是掩码,我不懂,也没改

我修改完后测试过了,没发现计算错误的OpCode
雪    币: 1876
活跃值: 活跃值 (20)
能力值: (RANK:550 )
在线值:
发帖
回帖
粉丝
hawking 活跃值 12 2007-3-21 17:19
4
0
学习
雪    币: 200
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
sucsor 活跃值 2007-3-21 18:00
5
0
学习,支持深加工!!
雪    币: 263
活跃值: 活跃值 (26)
能力值: ( LV12,RANK:410 )
在线值:
发帖
回帖
粉丝
vxin 活跃值 10 2007-3-21 19:50
6
0
只能膜拜~~
雪    币: 201
活跃值: 活跃值 (11)
能力值: ( LV12,RANK:210 )
在线值:
发帖
回帖
粉丝
sdzbyy 活跃值 5 2007-3-21 22:01
7
0

先收了,回头慢慢研究。
雪    币: 150
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
chinatme 活跃值 2007-3-22 18:47
8
0
估计能看到头大~
雪    币: 201
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
cdsinglee 活跃值 2007-3-22 23:44
9
0
没看懂怎么用..
雪    币: 200
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
宽容 活跃值 2007-3-23 08:01
10
0
确实需要慢慢研究
雪    币: 200
活跃值: 活跃值 (10)
能力值: ( LV6,RANK:90 )
在线值:
发帖
回帖
粉丝
仙剑太郎 活跃值 2 2007-3-23 11:04
11
0
看不懂..只能收藏...
雪    币: 195
活跃值: 活跃值 (10)
能力值: ( LV6,RANK:90 )
在线值:
发帖
回帖
粉丝
aki 活跃值 2 2007-3-23 13:53
12
0
asproooot
雪    币: 202
活跃值: 活跃值 (10)
能力值: ( LV9,RANK:1130 )
在线值:
发帖
回帖
粉丝
binbinbin 活跃值 28 2007-3-23 18:09
13
0
不明白哦。hook api感觉像是用在游戏外挂方面比较多
雪    币: 2071
活跃值: 活跃值 (10)
能力值: (RANK:170 )
在线值:
发帖
回帖
粉丝
Aker 活跃值 4 2007-3-23 20:10
14
0
mark一下 〉。。。。。。。。。
雪    币: 235
活跃值: 活跃值 (350)
能力值: ( LV10,RANK:170 )
在线值:
发帖
回帖
粉丝
4st0ne 活跃值 4 2007-3-24 03:55
15
0
谁能整个ASM版的
雪    币: 217
活跃值: 活跃值 (18)
能力值: ( LV13,RANK:530 )
在线值:
发帖
回帖
粉丝
foxabu 活跃值 13 2007-3-24 18:15
16
0
其实搂主应该认真看看detour的代码 个人认为肯定是比你得代码好的多
而且考虑了多处理器多线程的问题,已经同步的问题。Api Hook 的方式也提供了多种。是非常值得借鉴的。。。。

一般只知道C--〉Delphi今天到好 看到D->C的了。。
就和把VB转C差不多吧。。罕见咯~
雪    币: 521
活跃值: 活跃值 (134)
能力值: (RANK:570 )
在线值:
发帖
回帖
粉丝
笨笨雄 活跃值 14 2007-3-24 20:07
17
0
原来MS已经提供了功能这么完整的代码了

刚下了detour的代码看了disasm.cpp部分。指令长度计算方面跟LZ给的代码差不多。

查两张256的表。。感觉跟LZ给的差不多
雪    币: 1931
活跃值: 活跃值 (853)
能力值: (RANK:770 )
在线值:
发帖
回帖
粉丝
海风月影 活跃值 18 2007-3-26 09:00
18
0
请问,哪里能下载detour的代码,想学习一下

BTW:上面的代码都不是我写的,是xIkUg写的。
我只是将DELPHI版转成了VC版,修改了一下计算指令长度的那个函数
雪    币: 521
活跃值: 活跃值 (134)
能力值: (RANK:570 )
在线值:
发帖
回帖
粉丝
笨笨雄 活跃值 14 2007-3-26 14:26
19
0
http://research.microsoft.com/sn/detours
雪    币: 200
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
ggsddu 活跃值 2007-3-26 15:56
20
0
先收下慢慢看
雪    币: 200
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
cozil 活跃值 2007-3-27 10:03
21
0
感谢,好东西啊,我正需要这样的东东。 我写了一个库通过改写API头部指令实现挂接,但同一个API在2K/XP/2K3上的头部都不一样,所以必须事先记录需要挂接的API头部有几个字节指令要被覆盖,现在有了这个函数,我可以直接分析头部了。
    再次感谢!!!
雪    币: 200
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
WaffenSS 活跃值 2007-3-28 12:09
22
0
强啊楼主,学习中!
雪    币: 243
活跃值: 活跃值 (15)
能力值: ( LV12,RANK:410 )
在线值:
发帖
回帖
粉丝
王仁军 活跃值 10 2007-3-28 14:15
23
0
好,留个记号,以后再来看
游客
登录 | 注册 方可回帖
返回