win原理Day005.zip
UAC
// UACDlg.cpp : 实现文件
//
#include "stdafx.h"
#include "UAC.h"
#include "UACDlg.h"
#include "afxdialogex.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
// 用于应用程序“关于”菜单项的 CAboutDlg 对话框
class CAboutDlg : public CDialogEx
{
public:
CAboutDlg();
// 对话框数据
enum { IDD = IDD_ABOUTBOX };
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV 支持
// 实现
protected:
DECLARE_MESSAGE_MAP()
};
CAboutDlg::CAboutDlg() : CDialogEx(CAboutDlg::IDD)
{
}
void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
CDialogEx::DoDataExchange(pDX);
}
BEGIN_MESSAGE_MAP(CAboutDlg, CDialogEx)
END_MESSAGE_MAP()
// CUACDlg 对话框
CUACDlg::CUACDlg(CWnd* pParent /*=NULL*/)
: CDialogEx(CUACDlg::IDD, pParent)
{
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}
void CUACDlg::DoDataExchange(CDataExchange* pDX)
{
CDialogEx::DoDataExchange(pDX);
DDX_Control(pDX, IDC_BUTTON1, m_Button);
}
BEGIN_MESSAGE_MAP(CUACDlg, CDialogEx)
ON_WM_SYSCOMMAND()
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
ON_BN_CLICKED(IDC_BUTTON1, &CUACDlg::OnBnClickedButton1)
END_MESSAGE_MAP()
// CUACDlg 消息处理程序
BOOL CUACDlg::OnInitDialog()
{
CDialogEx::OnInitDialog();
// 将“关于...”菜单项添加到系统菜单中。
// IDM_ABOUTBOX 必须在系统命令范围内。
ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
ASSERT(IDM_ABOUTBOX < 0xF000);
CMenu* pSysMenu = GetSystemMenu(FALSE);
if (pSysMenu != NULL)
{
BOOL bNameValid;
CString strAboutMenu;
bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX);
ASSERT(bNameValid);
if (!strAboutMenu.IsEmpty())
{
pSysMenu->AppendMenu(MF_SEPARATOR);
pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
}
}
// 设置此对话框的图标。 当应用程序主窗口不是对话框时,框架将自动
// 执行此操作
SetIcon(m_hIcon, TRUE); // 设置大图标
SetIcon(m_hIcon, FALSE); // 设置小图标
// TODO: 在此添加额外的初始化代码
// 1. 获得本进程的令牌
HANDLE hToken = NULL;
if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken))
return false;
// 2. 获取提升类型
TOKEN_ELEVATION_TYPE ElevationType = TokenElevationTypeDefault;
BOOL bIsAdmin = false;
DWORD dwSize = 0;
if (GetTokenInformation(hToken, TokenElevationType, &ElevationType,
sizeof(TOKEN_ELEVATION_TYPE), &dwSize)) {
// 2.1 创建管理员组的对应SID
BYTE adminSID[SECURITY_MAX_SID_SIZE];
dwSize = sizeof(adminSID);
CreateWellKnownSid(WinBuiltinAdministratorsSid, NULL, &adminSID, &dwSize);
// 2.2 判断当前进程运行用户角色是否为管理员
if (ElevationType == TokenElevationTypeLimited) {
// a. 获取连接令牌的句柄
HANDLE hUnfilteredToken = NULL;
GetTokenInformation(hToken, TokenLinkedToken, (PVOID)&hUnfilteredToken,
sizeof(HANDLE), &dwSize);
// b. 检查这个原始的令牌是否包含管理员的SID
if (!CheckTokenMembership(hUnfilteredToken, &adminSID, &bIsAdmin))
return false;
CloseHandle(hUnfilteredToken);
}
else {
bIsAdmin = IsUserAnAdmin();
}
CloseHandle(hToken);
}
// 3. 判断具体的权限状况
BOOL bFullToken = false;
switch (ElevationType) {
case TokenElevationTypeDefault: /* 默认的用户或UAC被禁用 */
if (IsUserAnAdmin()) bFullToken = true; // 默认用户有管理员权限
else bFullToken = false;// 默认用户不是管理员组
break;
case TokenElevationTypeFull: /* 已经成功提高进程权限 */
if (IsUserAnAdmin()) bFullToken = true; //当前以管理员权限运行
else bFullToken = false;//当前未以管理员权限运行
break;
case TokenElevationTypeLimited: /* 进程在以有限的权限运行 */
if (bIsAdmin) bFullToken = false;//用户有管理员权限,但进程权限有限
else bFullToken = false;//用户不是管理员组,且进程权限有限
}
// 4. 根据权限的不同控制按钮的显示
if (!bFullToken)
Button_SetElevationRequiredState(m_Button.m_hWnd,
!bFullToken);
else
::ShowWindow(m_Button.m_hWnd, SW_SHOW);
return TRUE; // 除非将焦点设置到控件,否则返回 TRUE
}
void CUACDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
if ((nID & 0xFFF0) == IDM_ABOUTBOX)
{
CAboutDlg dlgAbout;
dlgAbout.DoModal();
}
else
{
CDialogEx::OnSysCommand(nID, lParam);
}
}
// 如果向对话框添加最小化按钮,则需要下面的代码
// 来绘制该图标。 对于使用文档/视图模型的 MFC 应用程序,
// 这将由框架自动完成。
void CUACDlg::OnPaint()
{
if (IsIconic())
{
CPaintDC dc(this); // 用于绘制的设备上下文
SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);
// 使图标在工作区矩形中居中
int cxIcon = GetSystemMetrics(SM_CXICON);
int cyIcon = GetSystemMetrics(SM_CYICON);
CRect rect;
GetClientRect(&rect);
int x = (rect.Width() - cxIcon + 1) / 2;
int y = (rect.Height() - cyIcon + 1) / 2;
// 绘制图标
dc.DrawIcon(x, y, m_hIcon);
}
else
{
CDialogEx::OnPaint();
}
}
//当用户拖动最小化窗口时系统调用此函数取得光标
//显示。
HCURSOR CUACDlg::OnQueryDragIcon()
{
return static_cast<HCURSOR>(m_hIcon);
}
void CUACDlg::OnBnClickedButton1()
{
// TODO: 在此添加控件通知处理程序代码
// 1. 隐藏当前窗口
ShowWindow(SW_HIDE);
// 2. 获取当前程序路径
WCHAR szApplication[MAX_PATH] = { 0 };
DWORD cchLength = _countof(szApplication);
QueryFullProcessImageName(GetCurrentProcess(), 0,
szApplication, &cchLength);
// 3. 以管理员权限重新打开进程
SHELLEXECUTEINFO sei = { sizeof(SHELLEXECUTEINFO) };
sei.lpVerb = L"runas"; // 请求提升权限
sei.lpFile = szApplication; // 可执行文件路径
sei.lpParameters = NULL; // 不需要参数
sei.nShow = SW_SHOWNORMAL; // 正常显示窗口
if (ShellExecuteEx(&sei))
exit(0);
else
ShowWindow(SW_SHOWNORMAL);
}
遍历权限
// win原理Day005.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include <windows.h>
BOOL EnableDebugPrivilege(BOOL fEnable){ //提升为调试权限
BOOL fOk = FALSE; HANDLE hToken;
// 以修改权限的方式,打开进程的令牌
if (OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES,
&hToken)) {
// 令牌权限结构体
TOKEN_PRIVILEGES tp;
tp.PrivilegeCount = 1;
//获得LUID
LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &tp.Privileges[0].Luid);
tp.Privileges[0].Attributes = fEnable ? SE_PRIVILEGE_ENABLED : 0;
AdjustTokenPrivileges(hToken, FALSE, &tp, sizeof(tp), NULL, NULL); //修改权限
fOk = (GetLastError() == ERROR_SUCCESS);
CloseHandle(hToken);
}
return(fOk);
}
//遍历权限
void ShowPrivilege()
{
//打开访问令牌
HANDLE hToken;
OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken);
if (!hToken)
{
printf("令牌打开失败\n");
return;
}
//查询令牌中的权限
DWORD dwSize;
//第一次调用是为了获取数据大小
GetTokenInformation(hToken, TokenPrivileges, NULL, NULL, &dwSize);
char* pBuf = new char[dwSize]{};
//第二次调用就可以获取数据了
GetTokenInformation(hToken, TokenPrivileges, pBuf, dwSize, &dwSize);
TOKEN_PRIVILEGES* pTp = (TOKEN_PRIVILEGES*)pBuf;
//权限个数
DWORD dwCount = pTp->PrivilegeCount;
//pTp->Privileges:存储权限的数组
LUID_AND_ATTRIBUTES* pLaa = pTp->Privileges;
for (int i = 0; i < dwCount;i++,pLaa++)
{
char strName[100] = {};
DWORD dwLen = sizeof(strName);
LookupPrivilegeNameA(0, &pLaa->Luid, strName, &dwLen);
//pLaa->Attributes:0表示关闭,1表示默认开启,2:开启,3:默认开启
printf("权限:【%s】-状态:【%d】\n", strName, pLaa->Attributes);
}
//释放内存
delete pBuf;
}
int _tmain(int argc, _TCHAR* argv[])
{
EnableDebugPrivilege(TRUE);
ShowPrivilege();
system("pause");
return 0;
}
虚拟内存
// 虚拟内存.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include <windows.h>
void temp()
{
// DWORD dwPid;
// scanf_s("%d", &dwPid);
// HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwPid);
// //加强版,跨进程申请内存
// LPVOID lpBuf = VirtualAllocEx(hProcess, NULL, 1, MEM_COMMIT, PAGE_READWRITE);
//
// //memcpy(lpBuf, "hello world", sizeof("hello world"));
// //printf("%s", lpBuf);
// //跨进程写内存
// DWORD dwWrite;
// WriteProcessMemory(hProcess,
// lpBuf, "hello world",
// sizeof("hello world"), &dwWrite);
// char szBuf[100] = {};
// DWORD dwRead;
// //跨进程读内存
// ReadProcessMemory(hProcess,
// lpBuf, szBuf,
// sizeof(szBuf), &dwRead);
//
// printf("%s", szBuf);
}
int _tmain(int argc, _TCHAR* argv[])
{
//申请虚拟内存(本进程)
LPVOID lpBuf = VirtualAlloc(NULL,
1,
MEM_COMMIT,
PAGE_READONLY);
//memcpy(lpBuf, "hello world", sizeof("hello world"));
//printf("%s", lpBuf);
//修改内存属性
DWORD dwOld;
VirtualProtect(lpBuf, 1, PAGE_READWRITE, &dwOld);
memcpy(lpBuf, "hello world", sizeof("hello world"));
return 0;
}
遍历虚拟内存
// 遍历虚拟内存.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include <Windows.h>
#include <list>
using std::list;
enum MEMORYSTATE {
e_stat_free = MEM_FREE,
e_stat_reserve = MEM_RESERVE,
e_stat_commit = MEM_COMMIT
};
enum MEMORYTYPE {
e_type_image = MEM_IMAGE,
e_type_mapped = MEM_MAPPED,
e_type_private = MEM_PRIVATE,
};
typedef struct VMINFO {
DWORD address;
DWORD size;
MEMORYSTATE state;
}VMINFO;
void queryVirtualMemoryStatue(HANDLE hProcess, list<VMINFO>* memoryStatue) {
MEMORY_BASIC_INFORMATION mbi = { 0 };
VMINFO statue = { 0 };
DWORD dwAddress = 0;
DWORD dwSize = 0;
BOOL bRet = FALSE;
while (1) {
bRet = VirtualQueryEx(hProcess,
(LPCVOID)dwAddress,
&mbi,
sizeof(MEMORY_BASIC_INFORMATION));
if (bRet == FALSE)
break;
statue.address = dwAddress;
statue.state = (MEMORYSTATE)mbi.State;
dwSize = mbi.RegionSize;
// 输出内存状态,
// 内存状态用于描述虚拟内存有没有和物理存储器进行关联.
// 或是否被预定.
// free : 闲置,没有预定,没有和物理存储器关联
// reserve: 保留,被预定,没有和物理存储器关联
// commit : 提交,已经和物理存储器关联
switch (statue.state) {
case e_stat_free:
printf("0x%08X : Free\n", statue.address);
break;
case e_stat_reserve:
printf("0x%08X : reserve\n", statue.address);
break;
case e_stat_commit:
printf("0x%08X : commit\n", statue.address);
break;
}
// 如果内存地址已经提交到物理内存,则遍历提交到的每一个内存块.
if (statue.state == e_stat_commit) {
dwSize = 0;
LPVOID dwAllocationBase = mbi.AllocationBase;
DWORD dwBlockAddress = (DWORD)dwAddress;
while (1) {
bRet = VirtualQueryEx(hProcess,
(LPCVOID)dwBlockAddress,
&mbi,
sizeof(MEMORY_BASIC_INFORMATION));
if (bRet == FALSE) {
break;
}
// 判断遍历出来的内存块是否是同一块.(看它们的分配的首地址是否相等.)
// 如果不是,则跳出循环.
if (mbi.AllocationBase != dwAllocationBase)
break;
printf("\t0x%08X ", dwBlockAddress);
// 输出内存类型
// 内存类型表示虚拟内存是以何种方式和物理存储器进行关联
// image : 是从影像文件中映射而来
// mapped : 内存映射
// private: 私有内存,其它进程无法访问.
switch (mbi.Type) {
case e_type_image:
printf(" 类型: image ");
break;
case e_type_mapped:
printf(" 类型: mapped ");
break;
case e_type_private:
printf(" 类型: private ");
break;
default:
break;
}
// 输出内存分页属性
// 内存分页属性用于表示内存分页能够进行何种访问,如读,写,执行,写时拷贝.
if (mbi.Protect == 0)
printf("---");
else if (mbi.Protect & PAGE_EXECUTE)
printf("E--");
else if (mbi.Protect & PAGE_EXECUTE_READ)
printf("ER-");
else if (mbi.Protect & PAGE_EXECUTE_READWRITE)
printf("ERW");
else if (mbi.Protect & PAGE_READONLY)
printf("-R-");
else if (mbi.Protect & PAGE_READWRITE)
printf("-RW");
else if (mbi.Protect & PAGE_WRITECOPY)
printf("WCOPY");
else if (mbi.Protect & PAGE_EXECUTE_WRITECOPY)
printf("EWCOPY");
// 输出内存块的大小.
printf(" 大小:0x%X\n", mbi.RegionSize);
// 索引到下一个内存块
dwBlockAddress += mbi.RegionSize;
// 累加内存块的大小
dwSize += mbi.RegionSize;
}
}
statue.size = dwSize;
memoryStatue->push_back(statue);
// 遍历下一块虚拟内存.
dwAddress += dwSize;
}
}
int _tmain(int argc, _TCHAR* argv[])
{
list<VMINFO> vmList;
queryVirtualMemoryStatue(GetCurrentProcess(), &vmList);
return 0;
}
共享内存B
// 共享内存B.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include <windows.h>
int _tmain(int argc, _TCHAR* argv[])
{
//打开文件映射对象
HANDLE hMap = OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE, L"hello");
//关联虚拟内存
LPVOID lpBuf = MapViewOfFile(hMap, FILE_MAP_ALL_ACCESS, 0, 0, 16);
getchar();//暂停一下等待另一头把数据写入到共享内存中
printf("%s", lpBuf);//读取内存数据
//取消映射
UnmapViewOfFile(lpBuf);
//关闭句柄
CloseHandle(hMap);
system("pause");
return 0;
}
堆
// 堆.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include <windows.h>
int _tmain(int argc, _TCHAR* argv[])
{
// 创建一个可增长的堆
// HANDLE hHeap = HeapCreate(0, 0, 0);
// SYSTEM_INFO si; //系统信息
// GetSystemInfo(&si); // 获取系统信息
// //在堆上分配3个页面大小的内存
// LPVOID lpMem = HeapAlloc(hHeap,
// HEAP_ZERO_MEMORY,
// 3);
// HeapFree(hHeap, 0, lpMem);
// HeapDestroy(hHeap);
HANDLE hHeap = GetProcessHeap(); // 获取默认堆
SYSTEM_INFO si; //系统信息
GetSystemInfo(&si); // 获取系统信息
//在堆上分配3个页面大小的内存
LPVOID lpMem = HeapAlloc(hHeap, HEAP_ZERO_MEMORY, si.dwPageSize * 3);
HeapFree(hHeap, 0, lpMem);
HeapDestroy( hHeap );//默认堆是不能被销毁的
return 0;
}
文件映射
// 文件映射.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include <windows.h>
//创建文件映射(关联文件)
void FileMapToFile(char* pFilePath)
{
//获取文件句柄
HANDLE hFile = CreateFileA(pFilePath,
GENERIC_READ | GENERIC_WRITE, TRUE, NULL,
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile == INVALID_HANDLE_VALUE)
{
printf("文件打开失败\n");
return;
}
//创建文件映射对象
HANDLE hMap = CreateFileMapping(hFile, NULL,
PAGE_READWRITE, NULL,
NULL, NULL);
//关联虚拟内存
LPVOID lpBuf = MapViewOfFile(hMap, FILE_MAP_ALL_ACCESS, 0, 0, 0);
*(int*)lpBuf = 0x99999999;
//及时刷新到磁盘文件
FlushViewOfFile(lpBuf, 4);
//取消文件映射
UnmapViewOfFile(lpBuf);
//关闭文件映射对象句柄
CloseHandle(hMap);
CloseHandle(hFile);
}
//进程间通讯(共享内存)
void ShareMemory()
{
//创建文件映射对象
HANDLE hMap = CreateFileMapping(INVALID_HANDLE_VALUE,
NULL, PAGE_READWRITE,
0, 16, L"hello");
//与虚拟内存关联
LPVOID lpBuf = MapViewOfFile(hMap,
FILE_MAP_ALL_ACCESS,
0, 0, //映射偏移量必须是系统内存分配粒度(64KB)的整数倍
16);
//写通讯数据
memcpy(lpBuf, "hello girl", sizeof("hello girl"));
//取消映射(如果不需要再通讯了,在执行)
//UnmapViewOfFile(lpBuf);
//CloseHandle(hMap);
}
int _tmain(int argc, _TCHAR* argv[])
{
//FileMapToFile("123.exe");
ShareMemory();
system("pause");
return 0;
}