30.使用C语言在windows中用数组执行机器指令
[toc]
一、在C语言中直接使用数组执行机器指令
1.写一个C语言程序,内容为调用MessageBoxA弹出一个消息框
1 |
|
2.写一个C语言程序,内容为使用x86内联汇编调用MessageBoxA弹出一个消息框
1 |
|
3. 写一个x86 C语言程序,使用数组调用MessageBoxA弹出一个消息框
将汇编指令转换为机器码
1
2
3
4
5
6
7
8
9char mcode[] = {
0x6A,0x00, //push 0
0x6A,0x00, //push 0
0x6A,0x00, //push 0
0x6A,0x00, //push 0
0xB8,0x50,0xAF,0x37,0x77, //mov eax, 7737AF50h
0xFF,0xD0, //call eax
0xC3 //ret
};编写代码
1 |
|
4. 64位C语言程序,使用数组调用汇编指令
1 |
|
5. 在AMD64中使用msvc编译器与机器指令用数组调用MessageBoxA(程序中需要加载User32.dll后才能运行成功)
要加载User32.dll有两种方法,
第一种为静态加载动态库,需要在程序中使用过User32.dll里的函数。
第二种为动态加载动态库,需要在调用call指令前使用LoadLibraryA加载User32.dll。
将汇编代码转为机器码
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/*
sub rsp,28h
xor r9,r9
xor r8,r8
xor rdx,rdx
xor rcx,rcx
mov rax,0x7FFAB222A3C0
call rax
add rsp,28h
ret
*/
// 定义机器码
unsigned char code[] = {
0x48,0x83,0xEC,0x28
,0x4D,0x31,0xC9
,0x4D,0x31,0xC0
,0x48,0x31,0xD2
,0x48,0x31,0xC9
,0x48,0xB8,0xC0,0xA3,0x22,0xB2,0xFA,0x7F
,0x00,0x00,0xFF,0xD0
,0x48,0x83,0xC4,0x28
,0xC3
};
2. 编写C语言代码
```c
void MessageM()
{
/*
sub rsp,28h
xor r9,r9
xor r8,r8
xor rdx,rdx
xor rcx,rcx
mov rax,0x7FFAB222A3C0
call rax
add rsp,28h
ret
*/
// 定义机器码
unsigned char code[] = {
0x48,0x83,0xEC,0x28
,0x4D,0x31,0xC9
,0x4D,0x31,0xC0
,0x48,0x31,0xD2
,0x48,0x31,0xC9
,0x48,0xB8,0xC0,0xA3,0x22,0xB2,0xFA,0x7F
,0x00,0x00,0xFF,0xD0
,0x48,0x83,0xC4,0x28
,0xC3
};
//更改内存属性为可读可写可执行
DWORD dwOldProtect = 0;
VirtualProtectEx(GetCurrentProcess(), (LPVOID)&code, sizeof(DWORD), PAGE_EXECUTE_READWRITE, &dwOldProtect);
long long (*funcPtr)() = &code;
// 调用机器码
long long result = funcPtr();
printf("Result: %lld\n", result);
}
int LoadUser32()
{
HMODULE hUser32 = LoadLibraryA("User32.dll");
if (hUser32 == NULL)
{
printf("加载 User32.dll 失败 (Error code: %d)\n", GetLastError());
return -1;
}
return 0;
}
int main()
{
LoadUser32();
MessageM();
return 0;
}
二、 分配地址来复制并执行数组中的机器码
1. 将x86汇编指令调用MessageBoxA转为机器码后分配地址来复制并执行
1 |
|
2. 将64位汇编指令自增转为机器码后分配地址来复制并执行
1 |
|
3. 在AMD64中使用msvc编译器与机器指令用动态内存调用MessageBoxA(需加载模块User32.dll)
这里使用方法一,静态加载动态库User32.dll,具体为使用User32.dll中的函数MessageBoxA
1 |
|
All articles in this blog are licensed under CC BY-NC-SA 4.0 unless stating additionally.
