[toc]

常用代码段

0x01 GetProcessId-获取进程id

获取进程id

  • CreateToolhelp32Snapshot
  • Process32First
  • Process32Next
DWORD processNameToId(LPCTSTR lpszProcessName)
{
    HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
    PROCESSENTRY32 pe;
    pe.dwSize = sizeof(PROCESSENTRY32);
    if (!Process32First(hSnapshot, &pe)) {
        MessageBox(NULL, "The frist entry of the process list has not been copyied to the buffer", "Notice", MB_ICONINFORMATION | MB_OK);
        return 0;
    }
    while (Process32Next(hSnapshot, &pe)) {
        if (!strcmp(lpszProcessName, pe.szExeFile)) {
            return pe.th32ProcessID;
        }
    }
 
    return 0;
}
DWORD dwProcessId = processNameToId(szExeName);
if (dwProcessId == 0) {
    MessageBox(NULL, "The target process have not been found !", "Notice", MB_ICONINFORMATION | MB_OK);
    return -1;
}

0x04 OpenProcess-打开目标进程

  • OpenProcess
    HANDLE hTargetProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwProcessId);
    if (!hTargetProcess) {
        MessageBox(NULL, "Open target process failed !", "Notice", MB_ICONINFORMATION | MB_OK);
        return 0;
    }

0x03 IsWow64-判断目标进程是不是64位

BOOL IsWow64(HANDLE hProcess)
{
    typedef BOOL(WINAPI* LPFN_ISWOW64PROCESS) (HANDLE, PBOOL);
    LPFN_ISWOW64PROCESS fnIsWow64Process;
 
    BOOL bIsWow64 = FALSE;
    fnIsWow64Process = (LPFN_ISWOW64PROCESS)GetProcAddress(
        GetModuleHandle("kernel32"), "IsWow64Process");
 
    if (NULL != fnIsWow64Process)
    {
        fnIsWow64Process(hProcess, &bIsWow64);
    }
    return bIsWow64;
}

0x04 Is64BitOs-判断当前机器是不是 64bit。

主要用的API为

  • GetNativeSystemInfo
BOOL Is64BitOS()
{
    typedef VOID(WINAPI* LPFN_GetNativeSystemInfo)(__out LPSYSTEM_INFO lpSystemInfo);
    LPFN_GetNativeSystemInfo fnGetNativeSystemInfo = (LPFN_GetNativeSystemInfo)GetProcAddress(GetModuleHandle("kernel32"), "GetNativeSystemInfo");
    if (fnGetNativeSystemInfo)
    {
        SYSTEM_INFO stInfo = { 0 };
        fnGetNativeSystemInfo(&stInfo);
        if (stInfo.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_IA64
            || stInfo.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64)
        {
            return TRUE;
        }
    }
    return FALSE;
}

0x05 EnableDebugPriv-本地提权

  • OpenProcessToken
  • LookupPrivilegeValue
  • AdjustTokenPrivileges
bool enableDebugPriv()
{
    HANDLE hToken;
    LUID sedebugnameValue;
    TOKEN_PRIVILEGES tkp;
    if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken)) {
        return false;
    }
    if (!LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &sedebugnameValue)) {
        CloseHandle(hToken);
        return false;
    }
    tkp.PrivilegeCount = 1;
    tkp.Privileges[0].Luid = sedebugnameValue;
    tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
    if (!AdjustTokenPrivileges(hToken, FALSE, &tkp, sizeof(tkp), NULL, NULL)) {
        CloseHandle(hToken);
        return false;
    }
    return true;
}

getProcessAddr-获取目标进程首地址

主要逻辑,获取目标进程的快照,检索第一个模块的信息并返回模块的 modBaseAddr

  • CreateToolhelp32Snapshot:获取指定进程以及这些进程使用的堆、模块和线程的快照。
  • Module32First
  • MODULEENTRY32
//获取目标进程首地址
BOOL CImageBloodDlg::getProcessAddr(DWORD dwPID, DWORD& baseAddr)
{
	HANDLE hModuleSnap = INVALID_HANDLE_VALUE;
	MODULEENTRY32 me32;
 
	// 在目标进程中获取所有进程的snapshot
	hModuleSnap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, dwPID);
	if (hModuleSnap == INVALID_HANDLE_VALUE)
	{
		AfxMessageBox(_T("CreateToolhelp32Snapshot (of modules) fail"));
		return(FALSE);
	}
 
	// 设置MODULEENTRY32数据结构大小字段
	me32.dwSize = sizeof(MODULEENTRY32);
 
	//检索第一个模块的信息,不成功则返回
	if (!Module32First(hModuleSnap, &me32))
	{
		AfxMessageBox(_T("Module32First fail")); // 显示调用失败
		CloseHandle(hModuleSnap);    // 清除句柄对象
		return(FALSE);
	}
 
	// 从me32中得到基址
	baseAddr = (DWORD)me32.modBaseAddr;
 
	// 别忘了最后清除模块句柄对象
	CloseHandle(hModuleSnap);
	return(TRUE);
}

获取PEB

来源:libpeconv/libpeconv/src/PEB_lookup.cpp· hasherezade/libpeconv

inline PPEB get_peb()
{
#if defined(_WIN64)
    return (PPEB)__readgsqword(0x60);
#else
    return (PPEB)__readfsdword(0x30);
/*
//alternative way to fetch it:
    LPVOID PEB = NULL;
    __asm {
        mov eax, fs:[30h]
        mov PEB, eax
    };
    return (PPEB)PEB;
 
    or:
    LPVOID PEB = RtlGetCurrentPeb();
*/
#endif
}

判断磁盘时候开启了写保护

/**
 * @ brief 判断磁盘是否开启了写保护
 * @ param wcDrive 磁盘盘符
*/
BOOL IsWriteProtected( TCHAR wcDrive )
{
    TCHAR szPath[10] = L"\\\\.\\A:\0";
    szPath[4] = wcDrive;
 
    HANDLE hDevice = CreateFile(szPath,
        GENERIC_READ | GENERIC_WRITE, 
        FILE_SHARE_READ | FILE_SHARE_WRITE,
        NULL, 
        OPEN_EXISTING, 
        0, NULL);
 
    if (hDevice == INVALID_HANDLE_VALUE)
    {
        return FALSE;
    }
 
    BOOL	bRet	= FALSE;
    DWORD	dwBytesReturn = 0;
    BOOL	bWriteable =  ::DeviceIoControl(hDevice,
        IOCTL_DISK_IS_WRITABLE, 
        NULL, 
        0,                         
        NULL, 
        0, 
        (LPDWORD) &dwBytesReturn, 
        NULL);
    if (bWriteable)
    {
        bRet = FALSE;
    }
    else
    {
        bRet = ::GetLastError() == ERROR_WRITE_PROTECT ? TRUE:FALSE;
    }
 
    ::CloseHandle(hDevice);
 
    return bRet;
 
}

经验

0x01 临时关闭编译告警

#pragma warning(push)
#pragma warning(disable:4305)
		pCandidate=(VOID PTR_T PTR_T)ModuleSectionInfo.pBase;
#pragma warning(pop)

0x02 修改结构体对齐方式

使用 #pragma pack(1) 之后,结构体最小对齐的字节为1。好处是可以让编译器按照更紧凑的方式存储数据,从而节省内存空间。

struct TestStruct  
{  
    char a;     // 占用1字节  
    int b;      // 占用1字节,与a对齐  
    double c;   // 占用8字节,与b对齐  
};  
 
#pragma pack(1)  
struct TestPackStruct  
{  
    char a;     // 占用1字节  
    int b;      // 占用1字节,与a对齐  
    double c;   // 占用8字节,与b对齐  
};  
#pragma pack()
 
/*
TestStruct size:16
TestPackStruct size:13
*/

0x03 未使用的参数、变量

消除未使用参数和结构体警告可以使用下面几个宏:

#define UNREFERENCED_PARAMETER(P) {(P) = (P);}
#define UNREFERENCED_LOCAL_VARIABLE(V) {(V) = (V);}
#define DBG_UNREFERENCED_PARAMETER(P) (P)
#define DBG_UNREFERENCED_LOCAL_VARIABLE(V) (V)

ntdll

【转】利用NtProtectVirtualMemory结束进程-CSDN博客