Dns被莫名篡改的问题定位(笔记)

news2024/11/17 19:52:50
引言:最近发现用户的多台机器上出现了Dns被莫名修改的问题,从系统事件上看并未能正常确定到是那个具体软件所为,现在的需求就是确定和定位哪个软件具体所为。

解决思路:
  1. 首先到IPv4设置页面对Dns进行设置:
  2. 通过ProcExp确定了该窗口的宿主进程是Explorer.exe,通过ProcMon对Explorer进行监控,并未发现Explorer将静态Dns的地址写入注册表(后来发现其实Explorer是通过DllHost.exe来实现对注册表修改的,所以没监控到)。
  3. 通过对Explorer进行逆向分析发现Explorer实现比较复杂,后来通过网络发现修改Dns可以通过Netsh.exe这个程序来实现:
  4. 于是转到对Netsh.exe的逆向分析上来,经过仔细分析,发现Netsh.exe对dns的修改是通过netiohlp.dll的NhIpHandleSetDnsServer来实现的:

     
  5. 通过进一步定位发现是NhIpAddDeleteSetServer:
  6. 并发现会通过写入注册表来保存相关信息:

    并通过定位发现注册表地址是:
  7. 并且有重启Dnscahe服务等相关操作:
  8. 1)通过设置系统全局钩子来挂钩系统下所有进程然后挂钩SetRegvalue等api监控,该进程通过SetWindowHookEx来设置全局钩子(其实该挂钩方式不能挂钩没有消息循环的经常),通过inject-helper.exe进程来挂钩发现不能挂钩系统下的所有进程,而且新创建的进程也无法挂钩。
    2)通过设置KnowDlls注册表发现也无法正常挂钩所有进程。
    3)通过底层驱动挂钩,这个方法能监控到应用层的所有进程对注册表的操作,但为了回溯到目标进程,可能也需要加入对父子进程的回溯,这个相对麻烦一些。
  9. 笔者采用相对比较简单容易操作的方法。采用ProcMon来对注册表的监控:

    1)设置第一项筛选:operation is RegSetValue 操作

    2)设置第二项筛选:path is HKLM\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\Interfaces\{33701f65-c437-47a4-9162-071bd72b3425}\NameServer (复制这个字符串修改UUID即可)

    最后的效果如下图:

    设置好后可以看到监控效果:

  10. 但是我们需要追踪最初始的设置Dns的进程,比如进程A调用了Netsh或DllHost等其他的三方进程来设置Dns,这个时候仅仅监控到Netsh或者DllHost等进程是没用的,需要对进程进行父进程的回溯,才知道源操作进程。
  11. 这个时候需要写一个ProcMon的插件,然后在ProcMon在监控到操作进程后能第一时间对父进程进行回溯。

    编写一个Dll插件,并通过窗口子类化方式来对ProcMon的ListView控件进行消息监控:
     
    static DWORD WINAPI DoWork(LPVOID param)
     {
         swprintf_s(g_szProfilePath, L"%s\\record_%d.log", GetCurrentExePath().c_str(), GetCurrentProcessId());
        
         do {
             HWND hwndTaskManager = FindWindowW(L"PROCMON_WINDOW_CLASS", L"Process Monitor - Sysinternals: www.sysinternals.com");
             if (!hwndTaskManager)
             {
                 MessageBox(NULL, L"查找进程窗口失败", L"错误", NULL);
                 break;
             }
             DWORD TaskManagerPID = 0;
             GetWindowThreadProcessId(hwndTaskManager, &TaskManagerPID);
             if (TaskManagerPID != GetCurrentProcessId())
             {
                 MessageBox(NULL, L"TaskManagerPID != GetCurrentProcessId()", L"错误", NULL);
                 break;
             }
             //EnumChildWindows(hwndTaskManager, _EnumChildProc, NULL);
             g_hListView = FindWindowExW(hwndTaskManager, NULL, L"SysListView32", L"");
             if (!g_hListView)
             {
                 MessageBox(NULL, L"获取listview句柄为空", L"错误", NULL);
                 break;
             }
    
             fnOriginNetworkList = (WNDPROC)SetWindowLongPtrW(
                 g_hListView,
                 GWLP_WNDPROC,
                 (LONG_PTR)NetworkListWndProc);
         } while (0);
         return 0;
     }
    // 这里是ListView控件的消息处理函数 
    LRESULT CALLBACK NetworkListWndProc(
         HWND hwnd,      // handle to window
         UINT_PTR uMsg,      // message identifier
         WPARAM wParam,  // first message parameter
         LPARAM lParam   // second message parameter
     )
     {
         if (uMsg == LVM_SETITEMTEXT || uMsg == LVM_SETITEMTEXTA || uMsg == 4211)
         { 
             wchar_t szSection[50] = { 0 };
             wsprintf(szSection, L"%d_%d", g_iPrevItem, pItem->iItem);
             wchar_t szSubItem[50] = { 0 };
             wsprintf(szSubItem, L"%d", pItem->iSubItem);
             WritePrivateProfileStringW(szSection, szSubItem, pItem->pszText, g_szProfilePath);
    
             if (pItem->iSubItem == 3) // process ID
             {
                 time_t tm = time(NULL);
                 struct tm now;
                 localtime_s(&now, &tm);
                 wchar_t str[100] = { 0 };
                 wcsftime(str, sizeof(str) / 2, L"%A %c", &now);
                 WritePrivateProfileStringW(szSection, L"time", str, g_szProfilePath);
    
                 DWORD pid = _wtoi(pItem->pszText);
                 stuProcNode node = { _wtoi(pItem->pszText), szSection };
                 PushProcNodeQueue(node);  // 这里不卡顿消息线程,把父进程回溯抛到另一个独立线程处理
             }
         }
    
         LRESULT rc = CallWindowProc(
             fnOriginNetworkList,
             hwnd,
             uMsg,
             wParam,
             lParam);
    
         return rc;
     }
    // 这里是父进程回溯操作
    static DWORD WINAPI  DoQueryProcess(LPVOID param)
     {
         while (1)
         {
             WaitForSingleObject(g_hQueryProcEvt, INFINITE); // 新的请求进入队列会触发事件
    
             std::vector<stuProcNode> ProcNodeList;
             GetProcNodeQueue(ProcNodeList);
    
             for (int i = 0; i < ProcNodeList.size(); i++)
             {
                 std::wstring strpPidNameList;
                 DWORD pid = ProcNodeList[i].dwPid;
                 while (1)
                 {  
                     // 回溯一下父进程
                     HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, pid);
                     if (hProcess == (HANDLE)-1 || hProcess == 0)
                     {
                         break;
                     }
    
                     WCHAR szPath[MAX_PATH] = { 0 };
                     GetProcessImageFileName(hProcess, szPath, MAX_PATH);
    
                     strpPidNameList += L"  [";
                     wchar_t buffer[20] = { 0 };
                     _itow_s(pid, buffer, 20, 10);
                     strpPidNameList += buffer;
                     strpPidNameList += L"  ";
                     strpPidNameList += wcsrchr(szPath, L'\\') ? wcsrchr(szPath, L'\\') + 1 : L"NULL";
                     strpPidNameList += L"]  ";
    
                     PROCESS_BASIC_INFORMATION pbi = { 0 };
                     if (0 == NtQueryInformationProcess(hProcess, 0, &pbi, sizeof(pbi), NULL))
                     {
                         pid = pbi.InheritedFromUniqueProcessId;
                     }
                     else
                     {
                         break;
                     }
                     
                     CloseHandle(hProcess);
                 }
                 WritePrivateProfileStringW(ProcNodeList[i].strSection.c_str(), L"PidNameINFO", strpPidNameList.c_str(), g_szProfilePath);
             }
         }
         return 0;
     }
  12. 代码写好了,这个时候通过CFF软件修改ProcMon的导入表,使其依赖我们的插件,这个时候当ProcMon启动的时候就会自动加载我们的插件了,相当于变相注入到了ProcMon进程。
    看看效果:

  13. 这样的监控程序就算写好了,可以交付运维去部署监控了,一旦监控到就会输出到日志文件,并把父子进程进行了回溯。
  14.  

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1882755.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【MySQL备份】Percona XtraBackup基础篇

目录 1.关于Percona XtraBackup 2. Percona XtraBackup有哪些特点&#xff1f; 3.安装Percona XtraBackup 3.1.环境信息 3.2.安装步骤 4. xtrabackup内部流程图 5.Percona XtraBackup基础语法 5.1.全量备份 5.2.增量备份 5.2.1.基于全量备份的增量备份 5.2.2.基于前…

Java学习 (六) 面向对象--this、继承、方法重写、super

一、this 关键字 1、this 演示 vi Person.java public class Person {String name;int age;//显示声明构造器public Person(String s , int i){name s;age i;}public void setAge(int age){age age;}}vi PersonTest.java public class PersonTest {public static void m…

nextTick的应用和原理理解

一.代码的理解 <template><div id"app"><div></div><button click"fn" ref"box"> {{ name }}</button></div> </template><script> export default {data: function () {return {n…

【Linux】计算机网络基础:协议、分层结构与数据传输解析

文章目录 前言1. 认识“协议”1.1. 什么是协议1.2. 网络分层结构——网络 vs OS之间的关系1.2.1. 软案分层1.2.2. 网络分层(为什么&#xff1f;是什么&#xff1f;怎么办&#xff1f;) 1.3. 站在语言角度&#xff0c;重新理解协议 2. 网络传输基本流程3. 数据包封装和分用4. 网…

【剑指Offer系列】68-二叉树的最近公共祖先(哈希)

思路&#xff1a;使用map存储每个节点的父节点&#xff0c;则两个节点的最近公共祖先&#xff0c;即二者的最近父节点 1、中序遍历二叉树&#xff08;当前节点的下一个节点&#xff09; 2、记录每个节点的父节点 3、列出p的族谱、q的族谱 4、寻找二者最近的祖先 class Soluti…

安装 Docker 环境(通过云平台创建一个实例实现)

目录 1. 删除原有 yum 2. 手动配置 yum 源 3. 删除防火墙规则 4. 保存防火墙配置 5. 修改系统内核。打开内核转发功能。 6. 安装 Docker 7. 设置本地镜像仓库 8.重启服务 1. 删除原有 yum rm -rfv /etc/yum.repos.d/* 2. 手动配置 yum 源 使用 centos7-1511.iso 和 Xi…

《Programming from the Ground Up》阅读笔记:p1-p18

《Programming from the Ground Up》学习第1天&#xff0c;p1-18总结&#xff0c;总计18页。 一、技术总结 1.fetch-execute cycle p9, The CPU reads in instructions from memory one at a time and executes them. This is known as the fetch-execute cycle。 2.genera…

安防监控视频平台LntonCVS视频融合共享平台水电站视频智能监控系统的设计与特点

水电站作为重要的能源基地&#xff0c;其安全运行对保障能源供应和社会稳定至关重要。然而&#xff0c;传统的人工监控方式存在高成本、监控范围有限和反应速度慢等问题。因此&#xff0c;引入先进的视频智能监控系统成为当务之急&#xff0c;以提高效率和安全性。 安徽羚通科技…

Anti-C-Myc Antibody (Chicken) - FITC Conjugated

C-myc基因是myc基因家族的重要成员之一&#xff0c;是一种可使细胞无限增殖&#xff0c;获永生化功能&#xff0c;促进细胞分裂的基因&#xff0c;c-myc基因与多种肿瘤发生发展有关。C-myc基因定位于染色体8q24、IgH、IgK、Igλ链的基因位点分别在14q32、2P13和 22q11&#xff…

SeeSR: Towards Semantics-Aware Real-World Image Super-Resolution

CVPR2024 香港理工大学&OPPO&bytedancehttps://github.com/cswry/SeeSR?tabreadme-ov-file#-licensehttps://arxiv.org/pdf/2311.16518#page5.80 问题引入 因为有些LR退化情况比较严重&#xff0c;所以超分之后的结果会出现语义的不一致的情况&#xff0c;所以本文训…

模拟电子学基本概念+Keil5安装指南!!

2024-7-1&#xff0c;星期一&#xff0c;16:56&#xff0c;天气&#xff1a;阴转小雨&#xff0c;心情&#xff1a;晴。大家好啊&#xff0c;今天换了一个新的主题&#xff0c;为什么嘞&#xff0c;是因为截止到昨天&#xff0c;电路基础部分的内容已经暂时告一段落啦&#xff…

高斯过程的数学理解

目录 一、说明 二、初步&#xff1a;多元高斯分布 三、 线性回归模型与维度的诅咒 四、高斯过程的数学背景 五、高斯过程的应用&#xff1a;高斯过程回归 5.1 如何拟合和推理高斯过程模型 5.2 示例&#xff1a;一维数据的高斯过程模型 5.3 示例&#xff1a;多维数据的高斯过程模…

奔驰G350升级原厂自适应悬挂系统有哪些作用

奔驰 G350 升级自适应悬挂系统后&#xff0c;可根据行车路况自动调整悬架高度和弹性&#xff0c;从而提升驾乘的舒适性和稳定性。 这套系统的具体功能包括&#xff1a; • 多种模式选择&#xff1a;一般有舒适、弯道、运动及越野等模式。例如&#xff0c;弯道模式在过弯时能为…

自定义vue3 hooks

文章目录 hooks目录结构demo hooks 当页面内有很多的功能&#xff0c;js代码太多&#xff0c;不好维护&#xff0c;可以每个功能都有写一个js或者ts&#xff0c;这样的话&#xff0c;代码易读&#xff0c;并且容易维护&#xff0c;组合式setup写法与此结合&#x1f44d;&#…

如何设置农历日程提醒 农历提醒小妙招

在中国&#xff0c;农历仍然承载着深厚的文化传统和民俗意义。无论是庆祝传统节日&#xff0c;还是纪念亲朋的生日&#xff0c;农历日期都显得格外重要。然而&#xff0c;随着生活节奏的加快&#xff0c;我们有时会因忙碌而遗忘这些特殊的日子。这时&#xff0c;一个能够准确提…

提升写作效率:探索AI在现代办公自动化中的应用

工欲善其事&#xff0c;必先利其器。 随着AI技术与各个行业或细分场景的深度融合&#xff0c;日常工作可使用的AI工具呈现出井喷式发展的趋势&#xff0c;AI工具的类别也从最初的AI文本生成、AI绘画工具&#xff0c;逐渐扩展到AI思维导图工具、AI流程图工具、AI生成PPT工具、AI…

二维码中的文件如何列表排列?轻松在线做文件活码的简单技巧

现在二维码是常用来展示文件的手段之一&#xff0c;将文件生成二维码之后扫码就能够快速在手机上查看文件内容&#xff0c;减少了下载内存占用及传输的时间&#xff0c;通过这种方式可以更加方便快捷的获取文件内容。怎么把多个文件用列表的方式来扫码展示呢&#xff1f; 多个…

Golang开发:构建支持并发的网络爬虫

Golang开发&#xff1a;构建支持并发的网络爬虫 随着互联网的快速发展&#xff0c;获取网络数据成为了许多应用场景中的关键需求。网络爬虫作为一种自动化获取网络数据的工具&#xff0c;也因此迅速崛起。而为了应对日益庞大的网络数据&#xff0c;开发支持并发的爬虫成为了必…

销量位列第一!强力巨彩LED单元板成绩斐然

据全球知名科技研究机构Omdia《LED显示产品出货分析-中国-2023》报告显示&#xff0c;2023年强力巨彩LED显示屏销量与单元板产品销量均位列第一&#xff0c;其品牌和市场优势可见一斑。 厦门强力巨彩自2004年成立之初&#xff0c;便以技术创新和严格品控为核心竞争力&#xff0…