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;}