[toc]

前置准备

  • 为了方便测试需要将随机基址关闭

1. 写一个被调试程序

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
//Message.c
#include <stdio.h>
#include <windows.h>
#include <conio.h>
void Message(char *var)
{
printf("var vulue is 0x%s\n", var);
}
int main(int argc, char** argv)
{
char* var = "AAA";
printf("var vulue is 0x%s\n", var);
printf("var address is 0x%p\n", var);
printf("ProcessID is %d\n", GetCurrentProcessId());
printf("Module Message.exe address is 0x%p\n",GetModuleHandleA("Message.exe"));
printf("Message function address is 0x%p\n", &Message);
label:
_getch();
Message(var);
goto label;
return 0;
}

2.写一个程序修改变量var的值

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
#include <windows.h>
#include <stdio.h>
#include <conio.h>

BOOL ChangeOn(HANDLE hProcess)
{
//修改目标地址的指令,更改AAA为BBB
BYTE originalcode[] = { 0x42,0x42,0x42};
SIZE_T baseAddr = 0x00417B30;
DWORD NumberOfByte;
DWORD dwOldProtect;
if(!VirtualProtectEx(hProcess, (LPVOID)baseAddr, sizeof(originalcode), PAGE_READWRITE, &dwOldProtect))
return FALSE;
if(!WriteProcessMemory(hProcess, baseAddr, &originalcode, sizeof(originalcode), &NumberOfByte))
return FALSE;
if(!VirtualProtectEx(hProcess, (LPVOID)baseAddr, sizeof(originalcode), dwOldProtect, &dwOldProtect))
return FALSE;
return TRUE;
}

BOOL ChangeOff(HANDLE hProcess)
{
//1.目标地址的指令改为原本的指令
BYTE originalcode[] = { 0x41,0x41,0x41};
SIZE_T baseAddr = 0x00417B30;
DWORD NumberOfByte;
DWORD dwOldProtect;
if (!VirtualProtectEx(hProcess, (LPVOID)baseAddr, sizeof(originalcode), PAGE_READWRITE, &dwOldProtect))
return FALSE;
if(!WriteProcessMemory(hProcess, baseAddr, &originalcode, sizeof(originalcode), &NumberOfByte))
return FALSE;
if (!VirtualProtectEx(hProcess, (LPVOID)baseAddr, sizeof(originalcode), dwOldProtect, &dwOldProtect))
return FALSE;
return TRUE;

}
void Hook(BOOL Turn)
{
DWORD dwProcId = 11700;
HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwProcId);
if(!hProcess) printf("Error OpenProcess fail\n");
if (TRUE == Turn)
{
if(!ChangeOn(hProcess))
printf("ChangeOn fail\n");
}
else if (FALSE == Turn)
{
if(!ChangeOff(hProcess))
printf("ChangeOff fail\n");
}
CloseHandle(hProcess);
}
int main()
{
system("cls");
printf("select: 1:ChangeOn\t2:ChangOff\n");
while (TRUE)
{
char key = _getch();
if ('1' == key)
{
Hook(TRUE);
printf("select: 1 success\n");
}
else if ('2' == key)
{
Hook(FALSE);
printf("select: 2 success\n");
}
}
return 0;
}

使用CE修改程序中的指令实现InlineHook,在原有函数上添加功能

主函数里的的地址与动态库里的地址可以被Hook,主函数以外的函数不能被Hook

1.写一个测试程序并运行

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
#include <windows.h>
#include <stdio.h>
#include <conio.h>

void Message(int a, int b, int c, int d)
{
static int count = 1;
printf("message %d\n", count);
MessageBoxA(0, 0, 0, 0);
count++;
}
void Demo()
{
static int count = 1;
printf("demo %d\n", count);
count++;
}
int main()
{
printf("Demo address is %p\n", &Demo);
printf("Message address is %p\n", &Message);
printf("main address is %p\n", &main);
printf("MessageBoxA address is %X\n", MessageBoxA);
printf("printf address is %X\n", &printf);
while (1)
{
Demo();
_getch();
}
return 0;

}

2. 使用CE自动汇编脚本Hook函数Printf,每次执行Printf前调用Message函数

注意堆栈平衡

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
[ENABLE]
//code from here to '[DISABLE]' will be used to enable the cheat
alloc(newmem,2048)
label(returnhere)
label(originalcode)
label(exit)

newmem: //this is allocated memory, you have read,write,execute access
//place your code here
push 0
push 0
push 0
call 00401050
add esp,c
originalcode:
push ebp
mov ebp,esp
and esp,-08

exit:
jmp returnhere

"C+windows.exe"+1010:
jmp newmem
nop
returnhere:

[DISABLE]
//code from here till the end of the code will be used to disable the cheat
dealloc(newmem)
"C+windows.exe"+1010:
db 55 8B EC 83 E4 F8
//push ebp
//mov ebp,esp
//and esp,-08

3. 使用CE自动汇编脚本Hook函数Printf,每次执行Printf前调用MessageBoxA函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
[ENABLE]
//code from here to '[DISABLE]' will be used to enable the cheat
alloc(newmem,2048)
label(returnhere)
label(originalcode)
label(exit)

newmem: //this is allocated memory, you have read,write,execute access
//place your code here
push 0
push 0
push 0
push 0
call 7630B730//MessageBoxA
originalcode:
push ebp
mov ebp,esp
and esp,-08

exit:
jmp returnhere

"C+windows.exe"+1010:
jmp newmem
nop
returnhere:


[DISABLE]
//code from here till the end of the code will be used to disable the cheat
dealloc(newmem)
"C+windows.exe"+1010:
db 55 8B EC 83 E4 F8
//push ebp
//mov ebp,esp
//and esp,-08

使用C语言编写InlineHook,在原有函数上添加功能

1.在本进程中InlineHook,分配一块内存空间用来写入修改后的指令并将被Hook的地址处指令修改为jmp到分配内存空间的首地址,

  • jmp指令跳转地址需要计算.计算公式:E9后面的地址 = 目标地址 - 当前地址 - 5

  • 3984CB=007B0000-00417B30-5,CE上面显示指令为E9 CB8439

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
#include <windows.h>
#include <stdio.h>
#include <conio.h>
#include <malloc.h>

/***********************0x00400000处原本的指令共5字节*********************/
//00400000 - 4D - dec ebp
//00400001 - 5A - pop edx
//00400002 - 90 - nop
//00400003 - 00 03 - add[ebx], al
/*****************************************************************/

/***********************分配内存处写的指令***************************/
// - 6A 00 - push 00
// - 6A 00 - push 00
// - 6A 00 - push 00
// - 6A 00 - push 00
//
// - E9 [offset] - jmp 0x400000
/*****************************************************************/

/***********************源地址改变后的指令5字节***************************/
//jmp [allocAddr]
/*****************************************************************/
BOOL InlineHook()
{
//1.将汇编指令转为机器码
BYTE allocCode[] = {0x4D,0x5A,0x90,0x00,0x03,
0x6A,0x00,0x6A,0x00,0x6A,0x00,0x6A,0x00,
0xE9,0x00,0x00,0x00,0x00};//jmp 0x400000
DWORD baseAddr = 0x400000;
//2.分配一块内存空间准备写入指令
LPVOID allocAddr = malloc(1024);
//3.通过指针指向allocCode中0xE9的后面
unsigned* allocJmp = allocCode + sizeof(allocCode) - 4;
//4.计算目标地址与当前地址的偏移,E9后面的地址 = 目标地址 - 当前地址 - 5
//将计算到的偏移使用*allocJmp赋值给allocCode里最后一行0xE9的后面
*allocJmp = baseAddr - ((unsigned)allocAddr+sizeof(allocCode)-5) - 5;
//5.将allocCode中的值复制到分配的地址中
memcpy(allocAddr, allocCode,sizeof(allocCode));
printf("AllocAddr is 0x%p\n", allocAddr);
//6.将baseAddr处的指令修改为jmp [allocAddr]
BYTE baseCode[] = { 0xE9,0x00,0x00,0x00,0x00};
//7.计算jmp [allocAddr]中[allocAddr]的值
//将计算到的偏移赋值给*allocJmp
unsigned* baseJmp = baseCode + 1;
*baseJmp=(unsigned)allocAddr - 0x400005 -5;
//8.将0x400000处的地址改为可读可写可执行后将baseCode的值复制到内存中
DWORD dwOldProtect;
if (!VirtualProtectEx(GetCurrentProcess(), (LPVOID)baseAddr, sizeof(baseCode), PAGE_READWRITE, &dwOldProtect))
return FALSE;
memcpy(baseAddr, baseCode, sizeof(baseCode));
if (!VirtualProtectEx(GetCurrentProcess(), (LPVOID)baseAddr, sizeof(baseCode), dwOldProtect, &dwOldProtect))
return FALSE;
printf("baseCode is 0x%X\n", baseCode);
return TRUE;
}

int main()
{
InlineHook();
_getch();
printf("main addr is %p", &main);
return 0;
}

2. 在本进程中InlineHook函数printf

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
#include <windows.h>
#include <stdio.h>
#include <conio.h>
#include <malloc.h>
#include <excpt.h>
#include <stdlib.h>
#include <string.h>

void Message(int a, int b, int c, int d);
void Demo();
BOOL InlineHook();
int main()
{
printf("Demo address is %p\n", &Demo);
printf("Message address is %p\n", &Message);
printf("main address is %p\n", &main);
printf("MessageBoxA address is %X\n", MessageBoxA);
printf("_vfprintf_l address is %X\n", &_vfprintf_l);
InlineHook();
while (1)
{
Demo();
_getch();
}
return 0;

}

void Message(int a, int b, int c, int d)
{
static count = 1;
printf("message %d\n", count);
MessageBoxA(0, 0, 0, 0);
count++;
}
void Demo()
{
static count = 1;
printf("demo %d\n", count);
count++;
return;
}


/***********************printf原本的指令*********************/
//00401010 - 55 - push ebp
//00401011 - 8B EC - mov ebp, esp
//00401013 - 83 E4 F8 - and esp, -08
/*****************************************************************/

/***********************分配内存处写的指令***************************/
// - 6A 00 - push 00
// - 6A 00 - push 00
// - 6A 00 - push 00
// - 6A 00 - push 00
// - E8 [offset] - call 7630B730//MessageBoxA
//
// - 55 - push ebp
// - 8B EC - mov ebp, esp
// - 83 E4 F8 - and esp, -08
//
// - E9 [offset] - jmp Demo+6
/*****************************************************************/

/***********************源地址改变后的指令***************************/
//jmp [allocAddr]
/*****************************************************************/
BOOL InlineHook()
{
//一、分配一段内存并写入修改后的指令
// 指令内容分为三部分
// (1)调用MessageBoxA
// (2)被Hook处地址的原始指令
// (3)jmp到被Hook地址修改指令后的下一处地址
//1.将汇编指令转为机器码
BYTE allocCode[] = { 0x6A,0x00,0x6A,0x00,0x6A,0x00,0x6A,0x00,
0xE8,0x00,0x00,0x00,0x00, //call 7630B730
0x55,0x8B,0xEC,0x83,0xE4,0xF8,
0xE9,0x00,0x00,0x00,0x00 };//jmp printf+6
DWORD messageAddr = 0x7630B730;
DWORD printfAddr = &_vfprintf_l;//0x00401010;
//2.分配一块内存空间准备写入指令
LPVOID allocAddr = malloc(1024);
DWORD dwOldProtect = 0;
if (!VirtualProtectEx(GetCurrentProcess(), allocAddr, 1024, PAGE_EXECUTE_READWRITE, &dwOldProtect))
{
printf("Protect error %d\n", GetLastError());
return FALSE;
}
memset(allocAddr, 0, 1024);
//LPVOID allocAddr=VirtualAllocEx(-1,NULL,1024, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
//3.通过指针指向allocCode中最后一行0xE9的后面
unsigned* allocJmp = allocCode + sizeof(allocCode) - 4;
//4.计算目标地址与当前地址的偏移,E9后面的相对偏移 = 目标地址 - 当前地址 - 5
//将计算到的偏移使用*allocJmp赋值给allocCode里最后一行0xE9的后面
*allocJmp = printfAddr - ((unsigned)allocAddr + sizeof(allocCode) - 5) - 5 + 6;
//5.倒数第三行Call地址计算相对偏移
allocJmp = allocCode + sizeof(allocCode) - 15;
*allocJmp = messageAddr - ((unsigned)allocAddr + sizeof(allocCode) - 16) - 5;
//6.将allocCode中的值复制到分配的地址中
WriteProcessMemory(-1, allocAddr, allocCode, sizeof(allocCode), NULL);
//memcpy(allocAddr, allocCode, sizeof(allocCode));
printf("AllocAddr is 0x%p\n", allocAddr);
//二、修改被Hook的地址指令
//1.将baseAddr处的指令修改为jmp [allocAddr]
BYTE baseCode[] = { 0xE9,0x00,0x00,0x00,0x00,0x90 };
//2.计算jmp [allocAddr]中[allocAddr]的值
//将计算到的偏移赋值给*allocJmp
unsigned* baseJmp = baseCode + 1;
*baseJmp = (unsigned)allocAddr - printfAddr - 5;
//3.将被Hook的地址改为baseCode的值
DWORD NumberOfByte = 0;
__try
{
//WriteProcessMemory(-1, (LPVOID)printfAddr, baseCode, sizeof(baseCode), NULL);
memcpy(printfAddr, baseCode, sizeof(baseCode));
}
__except (EXCEPTION_EXECUTE_HANDLER)
{
DWORD dwOldProtect = 0;
if (!VirtualProtectEx(GetCurrentProcess(), (LPVOID)printfAddr, sizeof(baseCode), PAGE_EXECUTE_READWRITE, &dwOldProtect))
{
printf("Protect error %d\n", GetLastError());
return FALSE;
}
memcpy(printfAddr, baseCode, sizeof(baseCode));
// WriteProcessMemory(-1, (LPVOID)printfAddr, baseCode, sizeof(baseCode), NULL);
VirtualProtectEx(GetCurrentProcess(), (LPVOID)printfAddr, sizeof(baseCode), dwOldProtect, &dwOldProtect);

}
printf("baseCode is 0x%X\n", *baseCode);
return TRUE;
}

在其他进程中通过C语言实现InlineHook,在原有函数上添加功能

1. 准备一个被Hook的程序

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
#include <windows.h>
#include <stdio.h>
#include <conio.h>

void Message(int a, int b, int c, int d)
{
static count = 1;
printf("message %d\n", count);
MessageBoxA(0, 0, 0, 0);
count++;
}
void Demo()
{
static count = 1;
printf("demo %d\n", count);
count++;
return;
}

int main()
{
printf("Demo address is %p\n", &Demo);
printf("Message address is %p\n", &Message);
printf("main address is %p\n", &main);
printf("MessageBoxA address is %X\n", MessageBoxA);
printf("_vfprintf_l address is %X\n", &_vfprintf_l);
printf("GetCurrentProcessId() %d\n", GetCurrentProcessId());
while (1)
{
Demo();
_getch();
}
return 0;

}

2. 使用C语言在其他进程中InlineHook函数printf,使用16进制指令

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
#include <windows.h>
#include <stdio.h>
#include <conio.h>
#include <malloc.h>
#include <excpt.h>
#include <stdlib.h>
#include <string.h>

/***********************printf原本的指令*********************/
//00401010 - 55 - push ebp
//00401011 - 8B EC - mov ebp, esp
//00401013 - 83 E4 F8 - and esp, -08
/*****************************************************************/


SIZE_T printAddr = 0x00401040;
static LPVOID allocAddrHook;
void HookStep2(HANDLE handle)
{
printf("Step2:allocAddrHook addr 0x%p\n", allocAddrHook);
BYTE printCode[] = { 0xE9,0x00,0x00,0x00,0x00,0x90 };
//1.计算
SIZE_T* baseJmp = printCode + 1;
*baseJmp = (SIZE_T)allocAddrHook - (SIZE_T)printAddr - 5;
//2.写入
__try
{
WriteProcessMemory(handle, printAddr, printCode, sizeof(printCode), NULL);
}
__except (EXCEPTION_EXECUTE_HANDLER)
{
DWORD dwOldProtect = 0;
if (!VirtualProtectEx(handle, printAddr, sizeof(printCode), PAGE_EXECUTE_READWRITE, &dwOldProtect))
{
printf("Protect error %d\n", GetLastError());
return FALSE;
}
WriteProcessMemory(handle, printAddr, printCode, sizeof(printCode), NULL);
VirtualProtectEx(handle, printAddr, sizeof(printCode), dwOldProtect, &dwOldProtect);
}

}

void HookStep1(HANDLE handle)
{
//1.分配
allocAddrHook = VirtualAllocEx(handle, NULL, 1024, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
//2.计算
BYTE printCode[] = { 0x6A,0x00,0x6A,0x00,0x6A,0x00,0x6A,0x00,
0xE8,0x00,0x00,0x00,0x00, //call 7630B730
0x55,0x8B,0xEC,0x83,0xE4,0xF8,
0xE9,0x00,0x00,0x00,0x00 };//jmp printf+6
//jmp printf+6
SIZE_T* offset = printCode + sizeof(printCode) - 4;
*offset = (printAddr+6) - ((SIZE_T)allocAddrHook+ sizeof(printCode)-5) - 5;
//call 7630B730
offset = printCode + sizeof(printCode) - 15;
*offset = 0x7630B730 - ((SIZE_T)allocAddrHook + sizeof(printCode) - 16) - 5;
//3写入
WriteProcessMemory(handle, (LPVOID)allocAddrHook, printCode, sizeof(printCode), NULL);
}

void InlineHook(DWORD dwPid)
{
HANDLE handle=OpenProcess(PROCESS_ALL_ACCESS,FALSE,dwPid);
if (NULL==handle)
{
printf("error handle not open\n");
return 0;
}
else {
printf("handle is 0x%X\n",handle);
}
/*
2. 将原始地址的指令修改为jmp到分配的第一段空间中。
1. 将分配第一段的内存空间用来修改指令。功能为Call第二段指令并且保存原始地址的指令,
执行完毕后跳转会原始地址的下一条地址
*/
HookStep1(handle);
printf("In allocAddrHook addr 0x%X\n", allocAddrHook);
HookStep2(handle);
CloseHandle(handle);
}

int main()
{
printf("MessageBoxA address is %X\n", &MessageBoxA);
printf("printf address is %X\n", &printf);
DWORD dwPid = 68400;
InlineHook(dwPid);
return 0;

}

3. 使用C语言在其他进程中InlineHook函数printf,使用汇编指令

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
#include <windows.h>
#include <stdio.h>
#include <conio.h>
#include <malloc.h>
#include <excpt.h>
#include <stdlib.h>
#include <string.h>

/***********************printf原本的指令*********************/
//00401010 - 55 - push ebp
//00401011 - 8B EC - mov ebp, esp
//00401013 - 83 E4 F8 - and esp, -08
/*****************************************************************/


SIZE_T printAddr = 0x00401040;
static LPVOID allocAddrHook;
void __declspec(naked) AsmCall()
{
__asm {
push 0
push 0
push 0
push 0
mov edx, 7630B730h
call edx
push ebp
mov ebp, esp
and esp, -08H
mov eax, 0x00401046
jmp eax
ret
}

}
void HookStep2(HANDLE handle)
{
printf("Step2:allocAddrHook addr 0x%p\n", allocAddrHook);
BYTE printCode[] = { 0xE9,0x00,0x00,0x00,0x00,0x90 };
//1.计算
SIZE_T* baseJmp = printCode + 1;
*baseJmp = (SIZE_T)allocAddrHook - (SIZE_T)printAddr - 5;
//2.写入
__try
{
WriteProcessMemory(handle, printAddr, printCode, sizeof(printCode), NULL);
}
__except (EXCEPTION_EXECUTE_HANDLER)
{
DWORD dwOldProtect = 0;
if (!VirtualProtectEx(handle, printAddr, sizeof(printCode), PAGE_EXECUTE_READWRITE, &dwOldProtect))
{
printf("Protect error %d\n", GetLastError());
return FALSE;
}
WriteProcessMemory(handle, printAddr, printCode, sizeof(printCode), NULL);
VirtualProtectEx(handle, printAddr, sizeof(printCode), dwOldProtect, &dwOldProtect);
}

}

void HookStep1(HANDLE handle)
{
//1.分配
allocAddrHook = VirtualAllocEx(handle, NULL, 1024, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
//2.写入
WriteProcessMemory(handle, (LPVOID)allocAddrHook, AsmCall, 1024, NULL);
}

void InlineHook(DWORD dwPid)
{
HANDLE handle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwPid);
if (NULL == handle)
{
printf("error handle not open\n");
return 0;
}
else {
printf("handle is 0x%X\n", handle);
}
/*
2. 将原始地址的指令修改为jmp到分配的第一段空间中。
1. 将分配第一段的内存空间用来修改指令。功能为Call第二段指令并且保存原始地址的指令,
执行完毕后跳转会原始地址的下一条地址
*/
HookStep1(handle);
printf("In allocAddrHook addr 0x%X\n", allocAddrHook);
HookStep2(handle);
CloseHandle(handle);
}

int main()
{
printf("MessageBoxA address is %X\n", &MessageBoxA);
printf("printf address is %X\n", &printf);
DWORD dwPid = 96252;
InlineHook(dwPid);
return 0;

}

4. 使用C语言注入Dll的方式实现InlineHook

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
// dllmain.c : Defines the entry point for the DLL application.
#include <windows.h>
#include <stdio.h>

void InlineHook();
BOOL APIENTRY DllMain(HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
MessageBoxW(NULL, L"how you doing", L"what's up", MB_OK);
InlineHook();
break;
case DLL_THREAD_ATTACH:
break;
case DLL_THREAD_DETACH:
break;
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
SIZE_T printAddr = 0x00401040;
void __declspec(naked) HookCode()
{
__asm {
push 0
push 0
push 0
push 0
mov edx, MessageBoxA
call edx
push ebp
mov ebp, esp
and esp, -08H
add printAddr,6
mov eax, printAddr
jmp eax
ret
}

}
void InlineHook()
{
BYTE printCode[] = { 0xE9,0x00,0x00,0x00,0x00,0x90 };
//1.计算
SIZE_T* baseJmp = printCode + 1;
*baseJmp = (SIZE_T)HookCode - (SIZE_T)printAddr - 5;
//2.写入
__try
{
memcpy( printAddr, printCode, sizeof(printCode));
}
__except (EXCEPTION_EXECUTE_HANDLER)
{
DWORD dwOldProtect = 0;
if (!VirtualProtectEx(GetCurrentProcess(), printAddr, sizeof(printCode), PAGE_EXECUTE_READWRITE, &dwOldProtect))
{
printf("Protect error %d\n", GetLastError());
return FALSE;
}
memcpy(printAddr, printCode, sizeof(printCode));
VirtualProtectEx(GetCurrentProcess(), printAddr, sizeof(printCode), dwOldProtect, &dwOldProtect);
}
return;
}

5. 使用C语言注入Dll的方式实现InlineHook,使用Call指令而非jmp指令,被Hook的地址更换为printf函数中ret指令处地址

  • 将被Hook的地址更换为printf函数中ret指令处地址,此时为0x00401075
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
// dllmain.c : Defines the entry point for the DLL application.
#include <windows.h>
#include <stdio.h>

void InlineHook();
BOOL APIENTRY DllMain(HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
MessageBoxW(NULL, L"how you doing", L"what's up", MB_OK);
InlineHook();
break;
case DLL_THREAD_ATTACH:
break;
case DLL_THREAD_DETACH:
break;
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
SIZE_T printAddr = 0x00401040+0x35;
void HookCode()
{
__asm {
push 1
push 0
push 0
push 0
mov edx, MessageBoxA
call edx
//ret 裸函数需要,正常函数无需
}
return;

}
void InlineHook()
{
BYTE printCode[] = { 0xE8,0x00,0x00,0x00,0x00,0xC3 };
//1.计算
SIZE_T* baseJmp = printCode + 1;
*baseJmp = (SIZE_T)HookCode - (SIZE_T)printAddr - 5;
//2.写入
__try
{
memcpy( printAddr, printCode, sizeof(printCode));
}
__except (EXCEPTION_EXECUTE_HANDLER)
{
DWORD dwOldProtect = 0;
if (!VirtualProtectEx(GetCurrentProcess(), printAddr, sizeof(printCode), PAGE_EXECUTE_READWRITE, &dwOldProtect))
{
printf("Protect error %d\n", GetLastError());
return FALSE;
}
memcpy(printAddr, printCode, sizeof(printCode));
VirtualProtectEx(GetCurrentProcess(), printAddr, sizeof(printCode), dwOldProtect, &dwOldProtect);
}
return;
}

6.使用C语言注入Dll的方式实现InlineHook,使用Call指令而非jmp指令,使用汇编指令修改原地址指令。被Hook的地址更换为printf函数中ret指令处地址

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
// dllmain.c : Defines the entry point for the DLL application.
#include <windows.h>
#include <stdio.h>

void InlineHook();
BOOL APIENTRY DllMain(HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
MessageBoxW(NULL, L"how you doing", L"what's up", MB_OK);
InlineHook();
break;
case DLL_THREAD_ATTACH:
break;
case DLL_THREAD_DETACH:
break;
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
SIZE_T printAddr = 0x00401040+0x35;
void __declspec(naked) HookCode()
{
__asm {
push 1
push 0
push 0
push 0
mov edx, MessageBoxA
call edx
ret
}

}
LPVOID HookCodeAddr = &HookCode;
void __declspec(naked) printCode()
{
__asm {
call [HookCodeAddr]
ret
}
}
void InlineHook()
{;
unsigned size = 7;
printf("%X\n", HookCode);
//写入
__try
{
memcpy( printAddr, printCode, size);
}
__except (EXCEPTION_EXECUTE_HANDLER)
{
DWORD dwOldProtect = 0;
if (!VirtualProtectEx(GetCurrentProcess(), printAddr, size, PAGE_EXECUTE_READWRITE, &dwOldProtect))
{
printf("Protect error %d\n", GetLastError());
return FALSE;
}
memcpy(printAddr, printCode, size);
VirtualProtectEx(GetCurrentProcess(), printAddr, size, dwOldProtect, &dwOldProtect);
}
return;
}

使用InlineHook替换原有函数功能

1. 使用CE编写汇编脚本替换掉Printf函数,使其执行完新指令后直接返回,而不执行printf函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
[ENABLE]
//code from here to '[DISABLE]' will be used to enable the cheat
alloc(newmem,2048)
label(returnhere)
label(originalcode)
label(exit)

newmem: //this is allocated memory, you have read,write,execute access
//place your code here
push 0
push 0
push 0
push 0
call 7649B730//MessageBoxA
ret

originalcode:
push ebp
mov ebp,esp
and esp,-08

exit:
jmp returnhere

"Message.exe"+1010:
jmp newmem
nop
returnhere:




[DISABLE]
//code from here till the end of the code will be used to disable the cheat
dealloc(newmem)
"Message.exe"+1010:
db 55 8B EC 83 E4 F8
//push ebp
//mov ebp,esp
//and esp,-08

2. 使用C语言编写Dll文件替换掉Printf函数,使其执行完新指令后直接返回,而不执行printf函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
// dllmain.c : Defines the entry point for the DLL application.
#include <windows.h>
#include <stdio.h>

void InlineHook();
BOOL APIENTRY DllMain(HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
MessageBoxW(NULL, L"how you doing", L"what's up", MB_OK);
InlineHook();
break;
case DLL_THREAD_ATTACH:
break;
case DLL_THREAD_DETACH:
break;
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}


void __declspec(naked) HookCode()
{
static LPVOID MsgAddr = &MessageBoxA;
__asm {
push 1
push 0
push 0
push 0
mov edx, [MsgAddr]
call edx
ret
}

}

LPVOID HookCodeAddr=&HookCode;;
void __declspec(naked) printCode()
{
__asm {
jmp [HookCodeAddr]
ret
}
}
void InlineHook()
{
SIZE_T printAddr = 0x00401010;
unsigned size = 6;
//写入
__try
{
memcpy(printAddr, printCode, size);
}
__except (EXCEPTION_EXECUTE_HANDLER)
{
DWORD dwOldProtect = 0;
if (!VirtualProtectEx(GetCurrentProcess(), printAddr, size, PAGE_EXECUTE_READWRITE, &dwOldProtect))
{
printf("Protect error %d\n", GetLastError());
return FALSE;
}
memcpy(printAddr, printCode, size);
VirtualProtectEx(GetCurrentProcess(), printAddr, size, dwOldProtect, &dwOldProtect);
}
return;
}