• 改变进程基址,获取进程基址
#include <Windows.h>
#include <iostream>
#include <strsafe.h>
#include <STDLIB.H>
using namespace std; #pragma comment(linker, "/BASE:0x400000") // 改变进程加载机地址 int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
WCHAR RouteBuffer[60] = { 0 };
DWORD res = GetModuleFileName(NULL, RouteBuffer, sizeof(RouteBuffer)); // 获取当前程序的全路径
WCHAR AfterVersion[130] = { 0 };
HMODULE EBAddress = GetModuleHandle(TEXT("NpCxyFW.exe")); // 获取当前进程的句柄 / 基址
StringCchPrintf(AfterVersion, sizeof(AfterVersion) / 2,
TEXT("程序全路径: %s\nhInstance获取到的程序基址: %x \nGetModuleHandle获取到的程序基址: %x"),
RouteBuffer, hInstance, EBAddress
);
INT Box_1 = MessageBox(NULL, AfterVersion, TEXT("测试"), MB_OKCANCEL);
return 0;
}

  • 通过 GetCommandLine() 获取命令行参数
#include <Windows.h>
#include <iostream>
#include <strsafe.h>
using namespace std; int main(int argc, char *argv[])
{
// 通过 GetCommandLine 获取命令行参数
INT CmdCount = NULL;
PWSTR *CmdLine = CommandLineToArgvW(GetCommandLine(), &CmdCount);
for (size_t i = 1; i < CmdCount; i++)
{
WCHAR *BeforeConversion = CmdLine[i]; CHAR AfterConversion[20] = { 0 };
// 将宽字节字符转换为多字节字符
int res = WideCharToMultiByte(CP_UTF8, NULL, BeforeConversion, -1, AfterConversion, sizeof(AfterConversion), NULL, NULL);
cout << "参数 " << i << ": "<< AfterConversion << endl;
}
return 0;
}

  • 显示进程环境块
#include <Windows.h>
#include <iostream>
#include <wcschr.h>
#include <strsafe.h>
using namespace std; int main(int argc, char *argv[])
{
PTSTR PEnvBlock = GetEnvironmentStrings(); // 获取进程环境块,也可以使用 int main(TCHAR *env[]) 的方式获取 TCHAR SzName[MAX_PATH]; TCHAR SzValue[MAX_PATH];
PTSTR PszCurrent = PEnvBlock;
HRESULT hr = S_OK; PCTSTR PszPos = NULL; int current = 0; while (PszCurrent != NULL) {
if (*PszCurrent != TEXT('=')) { // 若第一个字符不是 '='
PszPos = _tcschr(PszCurrent, TEXT('=')); PszPos++; // 查找 '=' 在字符串中的位置
size_t cbNameLength = (size_t)PszPos - (size_t)PszCurrent - sizeof(TCHAR); // 获取 Name 字段的长度
hr = StringCbCopyN(SzName, MAX_PATH, PszCurrent, cbNameLength); // 将 Name 字段拷贝到 szName 中
if (FAILED(hr)) break; hr = StringCchCopyN(SzValue, MAX_PATH, PszPos, _tcslen(PszPos) + 1); // 将 '=' 字符之后的内容拷贝至 szValue 中
if (SUCCEEDED(hr))
{
_tprintf(TEXT("[%u] %s=%s\r\n"), current, SzName, SzValue); // 成功便打印出信息
}
else
{
if (hr == STRSAFE_E_INSUFFICIENT_BUFFER) // 错误处理,STRSAFE_E_INSUFFICIENT_BUFFER 缓冲区空间不足
_tprintf(TEXT("[%u] %s=%s...\r\n"), current, SzName, SzValue);
else
_tprintf(TEXT("[%u] %s=???\r\n"), current, SzName); break;
}
}
else {
_tprintf(TEXT("[%u] %s\r\n"), current, PszCurrent); // 若一开始就为 '=' 字符,就直接打印出字符串的内容
}
current++; // 环境变量的个数加 1
while (*PszCurrent != TEXT('\0')) PszCurrent++; // 移动到字符串的结尾
PszCurrent++; // 跳过 '\0'
if (*PszCurrent == TEXT('\0')) break; // 检查它是否不是最后一个字符串
};
FreeEnvironmentStrings(PEnvBlock); //释放空间
return 0;
}
  • 获得某个环境变量
#include <Windows.h>
#include <iostream>
#include <strsafe.h>
#include <stdio.h>
using namespace std; int main(TCHAR *env[])
{
PWSTR lpBuffer = NULL;
DWORD Size = GetEnvironmentVariable(TEXT("PATH"), lpBuffer, 0); // 首先判断是否存在 PATH 环境变量
if (Size != 0)
{
DWORD BufferSize = Size * sizeof(TCHAR);
lpBuffer = (PWSTR)malloc(BufferSize); // 存在即分配缓冲区空间
GetEnvironmentVariable(TEXT("PATH"), lpBuffer, BufferSize);
printf("%ls", lpBuffer); // 打印 PATH 环境变量的信息
}
return 0;
}
  • 获取当前目录
#include <Windows.h>
#include <iostream>
#include <stdio.h>
#include <versionhelpers.h>
using namespace std; BOOL CompareOS(INT dwMajorVersion, INT dwMinorVersion); int main(TCHAR *env[])
{
// 获取当前目录方法 1
TCHAR Buffer_1[MAX_PATH] = { 0 };
DWORD DirLength = GetCurrentDirectory(MAX_PATH, Buffer_1);
printf("目录: %ls\n", Buffer_1);
// 获取当前目录方法 2
TCHAR Buffer_2[MAX_PATH];
DWORD PathLength = GetFullPathName(TEXT("C:"), MAX_PATH, Buffer_2, NULL);
printf("目录: %ls\n", Buffer_2); return 0;
}
  • 判断系统版本号的两种方法
VOID JudgeOS() // 通过 VerifyVersionInfo 比较判断,准确度一般
{
if (!CompareOS(10, 0))
if (!CompareOS(6, 3))
if (!CompareOS(6, 2))
if (!CompareOS(6, 1))
if (!CompareOS(6, 0))
if (!CompareOS(5, 2))
if (!CompareOS(5, 1))
if (!CompareOS(5, 0))
cout << "未知的操作系统版本" << endl;
else
cout << "版本在 Window2000 以上" << endl;
else
cout << "版本在 Windows XP 以上" << endl;
else
cout << "版本在 Windows XP Professional x64 Edition 以上" << endl;
else
cout << "版本在 Windows Vista 或者 Windows Server 2008 以上" << endl;
else
cout << "版本在 Windows 7 或者 Windows Server 2008 R2 以上" << endl;
else
cout << "版本在 Windows 8 或者 Windows Server 2012 以上" << endl;
else
cout << "版本在 Windows 8.1 或者 Windows Server 2012 R2 以上" << endl;
else
cout << "版本在 Windows Server 2016 或者 Windows 10 以上" << endl;
} BOOL CompareOS(INT MajorVersion, INT MinorVersion)
{
OSVERSIONINFOEX OSinfo = { 0 };
OSinfo.dwOSVersionInfoSize = sizeof(OSinfo);
OSinfo.dwMajorVersion = MajorVersion; OSinfo.dwMinorVersion = MinorVersion; // 设置比较操作系统版本的区间组合 DWORDLONG dwlConditionMask = 0; // 设置用于比较操作系统的宏
VER_SET_CONDITION(dwlConditionMask, VER_MAJORVERSION, VER_EQUAL);
VER_SET_CONDITION(dwlConditionMask, VER_MINORVERSION, VER_EQUAL); BOOL Res = VerifyVersionInfo(&OSinfo, VER_MAJORVERSION | VER_MINORVERSION, dwlConditionMask); // 第二个参数为比较位,支持 or 操作
return Res; // 函数成功返回非 0 值
}
#include <Windows.h>
#include <iostream>
#include <stdio.h>
#include <versionhelpers.h>
using namespace std;
// 利用官方的便捷函数进行操作系统的判别
INT JudgeOS(); int main(TCHAR *env[])
{
JudgeOS(); // 打印操作系统版本的信息
return 0;
} INT JudgeOS()
{
if (IsWindowsServer())
cout << "操作系统是服务器" << endl;
else
if (!IsWindows10OrGreater())
if (!IsWindows8OrGreater())
if (!IsWindows7SP1OrGreater())
if (!IsWindows7OrGreater())
if (!IsWindowsVistaSP2OrGreater())
if (!IsWindowsVistaSP1OrGreater())
if (!IsWindowsVistaOrGreater())
if (!IsWindowsXPSP3OrGreater())
if (!IsWindowsXPSP2OrGreater())
if (!IsWindowsXPSP1OrGreater())
if (!IsWindowsXPOrGreater())
cout << "未知的操作系统版本" << endl;
else
cout << "当前操作系统版本是否与Windows XP版本匹配或大于Windows XP版本 " << endl;
else
cout << "当前操作系统版本是否与Windows XP Service Pack 1(SP1)版本匹配或大于" << endl;
else
cout << "当前操作系统版本是否与Windows XP Service Pack 2(SP2)版本匹配或大于" << endl;
else
cout << "当前操作系统版本是否与Windows XP Service Pack 3(SP3)版本匹配或大于" << endl;
else
cout << "当前操作系统版本是否与Windows Vista版本匹配或大于Windows Vista版本" << endl;
else
cout << "当前操作系统版本是否与Windows Vista Service Pack 1(SP1)版本匹配或大于" << endl;
else
cout << "当前操作系统版本是否与Windows Vista Service Pack 2(SP2)版本匹配或大于" << endl;
else
cout << "当前操作系统版本是否与Windows 7版本匹配或大于Windows 7版本" << endl;
else
cout << "当前操作系统版本是否与Windows 7 Service Pack 1(SP1)版本匹配或大于" << endl;
else
cout << "当前操作系统版本是否与Windows 8版本匹配或大于Windows 8版本" << endl;
else
cout << "指示当前操作系统版本是否与Windows 10版本匹配或大于Windows 10版本" << endl;
return 0;
}
  • 进程创建
#include <Windows.h>
#include <iostream>
#include <stdio.h>
#include <versionhelpers.h>
using namespace std; int main(TCHAR *env[])
{
DWORD ExitCode = NULL; // 创建线程和进程的安全结构体
SECURITY_ATTRIBUTES ProcessSec = { 0 }; SECURITY_ATTRIBUTES ThreadSec = { 0 };
ProcessSec.nLength = sizeof(ProcessSec); ThreadSec.nLength = sizeof(ThreadSec);
ProcessSec.bInheritHandle = TRUE; ThreadSec.bInheritHandle = TRUE; // 指定线程和进程为可以继承 STARTUPINFO StartInfo = { sizeof(STARTUPINFO) };
StartInfo.cb = sizeof(StartInfo); // STARTUPINFO 结构体用于新进程窗口设置
StartInfo.dwFlags = STARTF_USEPOSITION;
StartInfo.dwX = 400; StartInfo.dwY = 400; // 防止窗口重叠
PROCESS_INFORMATION ProcessInfo = { 0 }; // 返回进程信息的结构体 // 创建进程打开 cmd.exe 执行模块
TCHAR CmdLine[] = L"cmd.exe";
BOOL res = CreateProcess(NULL, CmdLine, &ProcessSec, &ThreadSec, TRUE, CREATE_NEW_CONSOLE, NULL, NULL, &StartInfo, &ProcessInfo); // CREATE_NEW_CONSOLE 用于创建一个新的控制台窗口
cout << "创建的新进程 ID: " << ProcessInfo.dwProcessId << endl; // ProcessInfo 结构体包含子进程和线程的 ID
cout << "创建的新线程 ID: " << ProcessInfo.dwThreadId << endl; WaitForSingleObject(ProcessInfo.hThread, INFINITE); // 等待线程执行完毕
CloseHandle(ProcessInfo.hThread); // ProcessInfo 结构体包含子进程和线程的句柄
WaitForSingleObject(ProcessInfo.hProcess, INFINITE); // 等待进程执行完毕
GetExitCodeProcess(ProcessInfo.hProcess, &ExitCode); // 获取进程退出代码
cout << ExitCode << endl;
CloseHandle(ProcessInfo.hProcess); // 关闭进程句柄 return 0;
}
  • 手动提升程序权限
#include <Windows.h>
#include <iostream>
#include <strsafe.h>
using namespace std; void ErrorExit(LPTSTR lpszFunction, DWORD LastError);
int main(int argc, char *argv[], TCHAR *env[])
{
SHELLEXECUTEINFOW ExeInfo = { sizeof(ExeInfo) }; // 初始化结构体
ExeInfo.lpVerb = TEXT("runas"); ExeInfo.lpFile = TEXT("cmd.exe"); ExeInfo.nShow = SW_SHOWNORMAL; // 设置操作的文件
if (!ShellExecuteEx(&ExeInfo))
{
DWORD LastError = GetLastError(); // 获取权限失败,保存错误代码
TCHAR ErrString[10] = L"错误代码";
ErrorExit(ErrString, LastError); // 调用 ErrorExit 函数打印详细信息
}
else
{
cout << "调用成功" << endl;
}
return 0;
} void ErrorExit(LPTSTR lpszFunction, DWORD LastError)
{
// 检索最后错误码的系统错误消息 LPVOID lpMsgBuf;
LPVOID lpDisplayBuf;
DWORD dw = LastError; // 模拟错误代码定义为 123 FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER | // 函数自动使用 LocalAlloc 函数,来为 lpBuffer 分配内存
FORMAT_MESSAGE_FROM_SYSTEM | // 定义可以使用 GetLastError 的返回值赋给 dw
FORMAT_MESSAGE_IGNORE_INSERTS, // 这个标志表示 Arguments 参数将被忽略
NULL, // 消息所在位置,这个参数类型,根据dwFlags标志来设定
dw, // 消息索引,如果 lpSource 是一个字符串,那么这个参数被忽略
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // 设置为本地默认语言
(LPTSTR)&lpMsgBuf, // 接受消息字符串的内存块
0, // 内存大小
NULL); // 消息中的参数 // 显示错误消息并退出进程 lpDisplayBuf = (LPVOID)LocalAlloc(LMEM_ZEROINIT, // 将内存初始化为 0
(lstrlen((LPCTSTR)lpMsgBuf) + lstrlen((LPCTSTR)lpszFunction) + 40) * sizeof(TCHAR)); // 为字符串指针区域申请足够大小的内存 StringCchPrintf((LPTSTR)lpDisplayBuf, LocalSize(lpDisplayBuf), // 目标缓冲区和目标缓冲区的大小
TEXT("%s %d 的含义是: %s"), // 格式字符串
lpszFunction, // 参数1
dw, // 参数2
lpMsgBuf); // 参数3 MessageBox(NULL, (LPCTSTR)lpDisplayBuf, TEXT("Error"), MB_OK); LocalFree(lpMsgBuf); // 释放空间
LocalFree(lpDisplayBuf);
ExitProcess(dw); // 关闭进程
}
  • 查看是否为上下文管理员权限
#include <Windows.h>
#include <iostream>
#include <shlobj.h>
#include <strsafe.h>
using namespace std; VOID WINAPI ErrorCodeTransformation(DWORD ErrorCode);
DWORD WINAPI GetProcessElevation(TOKEN_ELEVATION_TYPE *pElevationType, BOOL* lsAdmin); int main(INT argc, CHAR *argv[], TCHAR *env[])
{
// pElevationType 为令牌的上下文权限类型,IsAdmin 标识是否为管理员权限
TOKEN_ELEVATION_TYPE pElevationType; BOOL IsAdmin;
if (GetProcessElevation(&pElevationType, &IsAdmin))
{
switch (pElevationType)
{
case TokenElevationTypeDefault:
cout << "[-] 进程以默认用户运行,或者UAC被禁用" << endl; break;
case TokenElevationTypeFull:
cout << "[*] 进程的权限被成功提升,而且令牌没有被筛选过" << endl; break;
case TokenElevationTypeLimited:
cout << "[*] 进程使用和一个筛选过的令牌对应的受限的权限运行" << endl; break;
}
if (IsAdmin) cout << "[*] 进程为管理员权限" << endl;
else cout << "[-] 进程为普通权限" << endl;
}
else
{
DWORD ErrorCode = GetProcessElevation(&pElevationType, &IsAdmin);
ErrorCodeTransformation(ErrorCode);// 打印错误信息
}
return 0;
} DWORD WINAPI GetProcessElevation(TOKEN_ELEVATION_TYPE *pElevationType, BOOL* pIsAdmin)
{
HANDLE hToken = NULL; DWORD dwSize; DWORD ErrorCode = NULL;
// OpenProcessToken 用于打开当前进程的令牌,hToken 为令牌的句柄
if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken))
{
// 调用失败返回错误代码
ErrorCode = GetLastError();
return (ErrorCode);
} BOOL bResult = FALSE;
// GetTokenInformation 用于获取当前令牌是什么令牌,令牌种类储存在 pElevationType 中
if (GetTokenInformation(hToken, TokenElevationType, pElevationType, sizeof(TOKEN_ELEVATION_TYPE), &dwSize))
{
BYTE adminSID[SECURITY_MAX_SID_SIZE];
dwSize = sizeof(adminSID);
// CreateWellKnownSid 定义一个描述符为 WinBuiltinAccessControlAssistanceOperatorsSid 的别名 SID
// adminSID 中储存的是新的 SID
CreateWellKnownSid(WinBuiltinAccessControlAssistanceOperatorsSid, NULL, &adminSID, &dwSize);
// 如果当前进程的令牌被筛选过
if (*pElevationType == TokenElevationTypeLimited)
{
HANDLE hUnfilteredToken = NULL;
// 获取当前进程未筛选过令牌的句柄,句柄保存在 hUnfilteredToken
GetTokenInformation(hToken, TokenLinkedToken, (VOID *)&hUnfilteredToken, sizeof(HANDLE), &dwSize);
// CheckTokenMembership 用于将模拟令牌和创建的安全描述符做比较,判断令牌的上下文访问权限是否为管理员
if (CheckTokenMembership(hUnfilteredToken, &adminSID, pIsAdmin)) bResult = TRUE;
CloseHandle(hUnfilteredToken);
}
else
{ // IsUserAnAdmin 函数是 CheckTokenMembership 的包装函数
// 建议直接调用该函数以确定管理员组状态,而不是调用 IsUserAnAdmin
*pIsAdmin = IsUserAnAdmin();
bResult = TRUE;
}
}
CloseHandle(hToken);
return (bResult);
} // 如果返回错误,可调用此函数打印详细错误信息
VOID WINAPI ErrorCodeTransformation(DWORD ErrorCode)
{
LPVOID lpMsgBuf; LPVOID lpDisplayBuf; DWORD dw = ErrorCode;
// 将错误代码转换为错误信息
FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
NULL, dw, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR)&lpMsgBuf, 0, NULL
);
lpDisplayBuf = (LPVOID)LocalAlloc(LMEM_ZEROINIT, (lstrlen((LPCTSTR)lpMsgBuf) + 40) * sizeof(TCHAR));
// 格式化打印
StringCchPrintf((LPTSTR)lpDisplayBuf, LocalSize(lpDisplayBuf), TEXT("错误代码 %d : %s"), dw, lpMsgBuf);
// 输出错误信息
MessageBox(NULL, (LPCTSTR)lpDisplayBuf, TEXT("Error"), MB_OK);
// 释放资源
LocalFree(lpMsgBuf); LocalFree(lpDisplayBuf); ExitProcess(dw);
}
  • 获取系统进程列表,操作进程句柄
#include <Windows.h>
#include <iostream>
#include <shlobj.h>
#include <strsafe.h>
#include <stdio.h>
#include <tlhelp32.h>
using namespace std; VOID WINAPI ErrorCodeTransformation(DWORD ErrorCode);
DWORD WINAPI ProcessInfo(VOID);
DWORD WINAPI ProcessHandle(DWORD ProcessID); int main(INT argc, CHAR *argv[], TCHAR *env[])
{
DWORD ErrorCode = ProcessInfo();
// 打印详细的错误信息
ErrorCodeTransformation(ErrorCode);
return 0;
} DWORD WINAPI ProcessInfo(VOID)
{
// ErrorCode 用于统计错误信息,ProcessCount 用于统计进程数
DWORD ErrorCode = NULL; INT ProcessCount = 0;
// 使用 CreateToolhelp32Snapshot 获取当前所有的进程快照
HANDLE ProcessSnapshot = CreateToolhelp32Snapshot(TH32CS_INHERIT | TH32CS_SNAPALL, 0);
if (ProcessSnapshot == INVALID_HANDLE_VALUE)
{
// 调用错误返回错误代码,以便查出详细的错误信息
ErrorCode = GetLastError();
return (ErrorCode);
}
PROCESSENTRY32W ProcessInfo; ProcessInfo.dwSize = sizeof(ProcessInfo); // 必须初始化结构体大小
// Process32First 用于获取第一个进程,返回进程信息至 ProcessInfo 结构体
BOOL DisResult = Process32First(ProcessSnapshot, &ProcessInfo);
if (!DisResult)
{
// 调用错误返回错误代码,以便查出详细的错误信息
ErrorCode = GetLastError();
return (ErrorCode);
}
// 进程数量加一
ProcessCount++;
cout << " 显示进程 ID: " << ProcessInfo.th32ProcessID << endl;
while (DisResult)
{
ProcessCount++;
// 获取下一个进程的详细信息
DisResult = Process32Next(ProcessSnapshot, &ProcessInfo);
// 打印进程 ID
cout << " ID: " << ProcessInfo.th32ProcessID;
// 有关句柄的详细操作
ProcessHandle(ProcessInfo.th32ProcessID);
// 打印进程名称
printf(" 进程名: %ls\n ", ProcessInfo.szExeFile);
}
return 0;
} DWORD WINAPI ProcessHandle(DWORD ProcessID)
{
DWORD ErrorCode = NULL;
// OpenProcess 将进程 ID 转换进程句柄,方便对进程进行操作
HANDLE ProcessHandle = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, TRUE, ProcessID);
if (!ProcessHandle)
{
// 调用错误返回错误代码,以便查出详细的错误信息
ErrorCode = GetLastError();
if (ErrorCode == 5) cout << " 访问状态: 拒绝访问 ";
return (ErrorCode);
}
else
{
// 操作进程句柄.... }
// 关闭句柄
CloseHandle(ProcessHandle);
return TRUE;
} // 如果返回错误,可调用此函数打印详细错误信息
VOID WINAPI ErrorCodeTransformation(DWORD ErrorCode)
{
LPVOID lpMsgBuf; LPVOID lpDisplayBuf; DWORD dw = ErrorCode;
// 将错误代码转换为错误信息
FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
NULL, dw, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR)&lpMsgBuf, 0, NULL
);
lpDisplayBuf = (LPVOID)LocalAlloc(LMEM_ZEROINIT, (lstrlen((LPCTSTR)lpMsgBuf) + 40) * sizeof(TCHAR));
StringCchPrintf((LPTSTR)lpDisplayBuf, LocalSize(lpDisplayBuf), TEXT("错误代码 %d : %s"), dw, lpMsgBuf);
// 弹窗显示错误信息
MessageBox(NULL, (LPCTSTR)lpDisplayBuf, TEXT("Error"), MB_OK);
LocalFree(lpMsgBuf); LocalFree(lpDisplayBuf); ExitProcess(dw);
}

最新文章

  1. T-SQL 比较N个指段取其中最大值
  2. Vim光标定位
  3. Webpack打包工具实时更新操作(启用观察者模式)
  4. MysqlDumpslow
  5. maven自建仓库 Return code : 405
  6. POJ 1149 PIGS 【网络流】
  7. Pandas简易入门(四)
  8. 用response输出一个验证码
  9. 项目Splash页面的开发与设计
  10. Android 7.0 调取系统相机崩溃解决android.os.FileUriExposedException
  11. JavaScript面向对象轻松入门之概述(demo by ES5、ES6、TypeScript)
  12. 微信小程序(一)基本知识初识别
  13. bzoj 4199 [NOI2015]寿司晚宴
  14. 《javascript设计模式与开发实践》阅读笔记(10)—— 组合模式
  15. 十个推荐使用的 Laravel 的辅助函数
  16. nginx的proxy_redirect
  17. VS2017 安装打包插件
  18. Find the Missing Number II
  19. SpringBoot集成RabbitMQ
  20. Activity-Flag标志位

热门文章

  1. 在windows上安装MySQL数据库注意点及Navicat Premium 15的破解
  2. mongodb 聚合(aggregate)
  3. C# 基础 - 委托、事件
  4. springMVC @InitBinder注解
  5. P1049_装箱问题(JAVA语言)
  6. OpenCV 之 图象几何变换
  7. C# - 实现类型的比较
  8. BST(二叉搜索树)的基本操作
  9. [Fundamental of Power Electronics]-PART II-7.交流等效电路建模-7.1 引言
  10. 使用 shell 做 tcp 协议模拟