这节课主要是复习之前的内容,查缺补漏

TLS

线程局部存储(Thread Local Storage,TLS),是一种变量的存储方法,这个变量在它所在的线程内是全局可访问的,但是不能被其他线程访问到,这样就保持了数据的线程独立性。而熟知的全局变量,是所有线程都可以访问的,这样就不可避免需要锁来控制,增加了控制成本和代码复杂度。

新建控制台应用

image-20240714152937964

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
// test.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
#include <windows.h>
#include <iostream>
using namespace std;

DWORD WINAPI ThreadFunc(LPVOID lpParam)
{
DWORD dw = (DWORD)TlsGetValue(0);
TlsSetValue(0, (LPVOID)0x44557788);
return 0;
}
int main()
{
TlsSetValue(0, (LPVOID)0x123456);
DWORD dw = (DWORD)TlsGetValue(0);
DWORD dwThreadId, dwThrdParam = 1;
HANDLE hThread;
char szMsg[80];
hThread = CreateThread(
NULL,
0,
ThreadFunc,
&dwThrdParam,
0,
&dwThreadId
);
WaitForSingleObject(hThread, INFINITE);
dw = (DWORD)TlsGetValue(0);
return 0;
}

dw的值为0x123456

image-20240714155310780

运行过ThreadFunc函数后dw的值仍为0x123456

image-20240714155414088

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
// test.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
#include <windows.h>
#include <iostream>
using namespace std;

void FuncC()
{
DWORD dw = (DWORD)TlsGetValue(0);
printf("FuncC tid:%d \t dw:%d\r\n", GetCurrentThreadId(), dw);
}

void FuncB()
{
DWORD dw = (DWORD)TlsGetValue(0);
FuncC();
printf("FuncB tid:%d \t dw:%d\r\n", GetCurrentThreadId(), dw);
}

void FuncA()
{
DWORD dw = (DWORD)TlsGetValue(0);
FuncB();
printf("FuncA tid:%d \t dw:%d\r\n", GetCurrentThreadId(), dw);
}

DWORD WINAPI ThreadFunc(LPVOID lpParam)
{
DWORD dwTest = 0x11223344;
//FuncA(dwTest)
FuncA();
DWORD dw = (DWORD)TlsGetValue(0);
TlsSetValue(0, (LPVOID)dwTest);
return 0;
}
int main()
{
TlsSetValue(0, (LPVOID)0x123456);
DWORD dw = (DWORD)TlsGetValue(0);

DWORD dwThreadId, dwThrdParam = 1;
HANDLE hThread;
char szMsg[80];
hThread = CreateThread(
NULL,
0,
ThreadFunc,
&dwThrdParam,
0,
&dwThreadId
);
WaitForSingleObject(hThread, INFINITE);
dw = (DWORD)TlsGetValue(0);
return 0;
}

image-20240714162000076

高低位

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
LARGE_INTEGER li;
//0x7777888812345678
DWORD dwLow = 0x12345678;
DWORD dwHi = 0x77778888;
__int64 nVal = 0x7777888812345678;

union MyUnion//共用体,lhm_n
{
struct
{
DWORD dwLow;
DWORD dwHi;
}lh;
__int64 m_n;
};
MyUnion u;
u.lh.dwLow = dwLow;
u.lh.dwHi = dwHi;

运行结果

image-20240714170201382

修改文件权限

GetFileAttributes

为一个指定的文件或目录返回文件系统的属性。可以使用GetFileAttributesEx 函数获得更多的属性信息。如果要实现交互式操作,可以使用GetFileAttributesTransacted 函数。

image-20240715131929726

参数

lpFileName [in]*文件或目录的名字,对于ANSI版本,名字不能大于MAX_PATH。
返回值
如果函数成功,返回值包含文件或目录的属性。如果函数失败,返回值是INVALID_FILE_ATTRIBUTES。
备注
当该函数作用在一个挂载文件夹时,它返回目录的文件系统的属性,而不是根目录的信息。为了获得与文件属性关联的卷信息,可以调用GetVolumeNameForVolumeMountPoint 函数。

SetFileAttributes

image-20240715132207204

参数:lpFileName:输入参数,为需要设置文件属性的文件或目录。返回值:返回BOOL值,表示是否成功。

使用说明:文件系统中对文件属性的表示使用了DWORD类型的数据,多个文件属性用“|”运算连在一起

总结

设置文件属性: SetFileAttributes(文件名, 属性值)

读取文件属性:GetFileAttributes(文件名)

读取文件属性
SetFileAttributes(文件名, FILE_ATTRIBUTE_READONLY); // 设定为只读
SetFileAttributes(文件名, FILE_ATTRIBUTE_HIDDEN ); //设定为隐藏
SetFileAttributes(文件名, FILE_ATTRIBUTE_SYSTEM); //设定为系统
SetFileAttributes(文件名, FILE_ATTRIBUTE_ARCHIVE); //设定为保存
SetFileAttributes(文件名, FILE_ATTRIBUTE_NORMAL); //设定为一般 (取消前四种属性)

设定二种以上的属性:
设定为只读 + 隐藏
SetFileAttributes(文件名, FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_HIDDEN)
设定为只读 + 隐藏 + 系统 + 保存
SetFileAttributes(文件名, FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_ARCHIVE)
取消所有设定
SetFileAttributes(文件名, FILE_ATTRIBUTE_NORMAL)

要读取文件目前的属性,则是用 GetFileAttributes
GetFileAttributes(文件名)
返回值与文件属性的宏定义相比,如返回1,表示FILE_ATTRIBUTE_READONLY

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
// test.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
#include <windows.h>
#include <iostream>
using namespace std;

BOOL GetSeDebugPrivilegeState(HANDLE hToken, LPCTSTR lpszPrivilege, BOOL bEnablePrivilege, BOOL *bPrivilegeState=(BOOL *)0)
{
//获取特权ID
LUID luid;
BOOL bRet = LookupPrivilegeValue(NULL, lpszPrivilege, &luid);
if (!bRet)
{
return FALSE;
}
//获取当前特权状态

//设置SeDebugPrivilege为enable
_TOKEN_PRIVILEGES tp;
_TOKEN_PRIVILEGES tpOld{};
tp.PrivilegeCount = 1;
tp.Privileges[0].Luid = luid;
if (bEnablePrivilege)
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
else
tp.Privileges[0].Attributes = 0;
bRet = AdjustTokenPrivileges(hToken,
FALSE,
&tp,
sizeof(TOKEN_PRIVILEGES),
(PTOKEN_PRIVILEGES)NULL,
(PDWORD)NULL
);
if (!bRet)
{
return FALSE;
}
//将原来的特权状态返回
if (bPrivilegeState != NULL)
{
*bPrivilegeState = tpOld.Privileges[0].Attributes;
}
return TRUE;
}
int main()
{
HANDLE hToken;
OpenProcessToken(GetCurrentProcess(),TOKEN_ADJUST_PRIVILEGES, &hToken);
//特权backup store
GetSeDebugPrivilegeState(hToken, "SeBackPrivilege", TRUE);
GetSeDebugPrivilegeState(hToken, "SeRestorePrivilege", TRUE);

DWORD dwAttr = GetFileAttributes("C:\\Windows\\Media");
DWORD dwNew = dwAttr ^ FILE_ATTRIBUTE_READONLY;
BOOL bRet = SetFileAttributes("C:\\Windows\\Media", dwNew);
//flag - 副本.zip
HANDLE hFile = CreateFile("C:\\Windows\\Media\\Alarm01.wav",
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_BACKUP_SEMANTICS,
NULL);
if (hFile == INVALID_HANDLE_VALUE)
{
return 0;
}
SetFilePointer(hFile, 0, NULL, FILE_END);
DWORD dw = 0x12345678;
bRet = WriteFile(hFile, &dw, sizeof(dw), NULL, NULL);
CloseHandle(hFile);
return 0;
}

成功修改

image-20240714222947546

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
// test.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
#include <windows.h>
#include <iostream>
using namespace std;

BOOL GetSeDebugPrivilegeState(HANDLE hToken, LPCTSTR lpszPrivilege, BOOL bEnablePrivilege, BOOL *bPrivilegeState=(BOOL *)0)
{
//获取特权ID
LUID luid;
BOOL bRet = LookupPrivilegeValue(NULL, lpszPrivilege, &luid);
if (!bRet)
{
return FALSE;
}
//获取当前特权状态

//设置SeDebugPrivilege为enable
_TOKEN_PRIVILEGES tp;
_TOKEN_PRIVILEGES tpOld{};
tp.PrivilegeCount = 1;
tp.Privileges[0].Luid = luid;
if (bEnablePrivilege)
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
else
tp.Privileges[0].Attributes = 0;
bRet = AdjustTokenPrivileges(hToken,
FALSE,
&tp,
sizeof(TOKEN_PRIVILEGES),
(PTOKEN_PRIVILEGES)NULL,
(PDWORD)NULL
);
if (!bRet)
{
return FALSE;
}
//将原来的特权状态返回
if (bPrivilegeState != NULL)
{
*bPrivilegeState = tpOld.Privileges[0].Attributes;
}
return TRUE;
}
int main()
{
HANDLE hToken;
OpenProcessToken(GetCurrentProcess(),TOKEN_ADJUST_PRIVILEGES, &hToken);
//特权backup store
GetSeDebugPrivilegeState(hToken, "SeBackPrivilege", TRUE);
GetSeDebugPrivilegeState(hToken, "SeRestorePrivilege", TRUE);

//DWORD dwAttr = GetFileAttributes("C:\\Windows\\Media");
//DWORD dwNew = dwAttr ^ FILE_ATTRIBUTE_READONLY;
//BOOL bRet = SetFileAttributes("C:\\Windows\\Media", dwNew);
//flag - 副本.zip
HANDLE hFile = CreateFile("C:\\Windows\\Media\\Alarm01.wav",
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_BACKUP_SEMANTICS,
NULL);
if (hFile == INVALID_HANDLE_VALUE)
{
return 0;
}
SetFilePointer(hFile, 0, NULL, FILE_END);
DWORD dw = 0x12345678;
BOOL bRet = WriteFile(hFile, &dw, sizeof(dw), NULL, NULL);
CloseHandle(hFile);
return 0;
}

image-20240714223831628

恢复成原来的样子

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
// test.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
#include <windows.h>
#include <iostream>
using namespace std;

BOOL GetSeDebugPrivilegeState(HANDLE hToken, LPCTSTR lpszPrivilege, BOOL bEnablePrivilege, BOOL *bPrivilegeState=(BOOL *)0)
{
//获取特权ID
LUID luid;
BOOL bRet = LookupPrivilegeValue(NULL, lpszPrivilege, &luid);
if (!bRet)
{
return FALSE;
}
//获取当前特权状态

//设置SeDebugPrivilege为enable
_TOKEN_PRIVILEGES tp;
_TOKEN_PRIVILEGES tpOld{};
tp.PrivilegeCount = 1;
tp.Privileges[0].Luid = luid;
if (bEnablePrivilege)
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
else
tp.Privileges[0].Attributes = 0;
bRet = AdjustTokenPrivileges(hToken,
FALSE,
&tp,
sizeof(TOKEN_PRIVILEGES),
(PTOKEN_PRIVILEGES)NULL,
(PDWORD)NULL
);
if (!bRet)
{
return FALSE;
}
//将原来的特权状态返回
if (bPrivilegeState != NULL)
{
*bPrivilegeState = tpOld.Privileges[0].Attributes;
}
return TRUE;
}
int main()
{
HANDLE hToken;
OpenProcessToken(GetCurrentProcess(),TOKEN_ADJUST_PRIVILEGES, &hToken);
//特权backup store
GetSeDebugPrivilegeState(hToken, "SeBackPrivilege", TRUE);
GetSeDebugPrivilegeState(hToken, "SeRestorePrivilege", TRUE);

//DWORD dwAttr = GetFileAttributes("C:\\Windows\\Media");
//DWORD dwNew = dwAttr ^ FILE_ATTRIBUTE_READONLY;
//BOOL bRet = SetFileAttributes("C:\\Windows\\Media", dwNew);
//flag - 副本.zip
HANDLE hFile = CreateFile("C:\\Windows\\Media\\Alarm01.wav",
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_BACKUP_SEMANTICS,
NULL);
if (hFile == INVALID_HANDLE_VALUE)
{
return 0;
}
SetFilePointer(hFile, -8, NULL, FILE_END);//修改
SetEndOfFile(hFile);//修改
//DWORD dw = 0x12345678;
//BOOL bRet = WriteFile(hFile, &dw, sizeof(dw), NULL, NULL);
CloseHandle(hFile);
return 0;
}

image-20240714224425329