非正规又不可靠的方法获得系统服务号

前段时间对ntdll比较感兴趣,因为我现在只能在RING3徘徊,加上ntdll是最接近RING0的地方。

那IDA反它,发现了ZwXXX的API都是直接调用系统服务了,换句话说就是系统服务RING3的表现形式是ZwXXX的API。ZwXXXAPI里没有什么代码,就是

2000Srv的:
.text:77F8F9C8 ZwAccessCheckByTypeAndAuditAlarm:       ; NtAccessCheckByTypeAndAuditAlarm
.text:77F8F9C8                 mov     eax, 4
.text:77F8F9CD                 lea     edx, [esp+4]
.text:77F8F9D1                 int     2Eh             ; DOS 2+ internal - EXECUTE COMMAND
.text:77F8F9D1                                         ; DS:SI -> counted CR-terminated command string
.text:77F8F9D3                 retn    40h
XP的:
.text:7C92D3CD                 mov     eax, 4
.text:7C92D3D2                 mov     edx, 7FFE0300h
.text:7C92D3D7                 call    dword ptr [edx]
.text:7C92D3D9                 retn    40h

很明显的区别就是XP已经把int进入RING0的方式改为sysenter了(在AMD上是syscall),另外7FFE0300这个地方放着KiFastSystemCall的地址,当然XP也有INT方式的函数:KiIntSystemCall,我想不直接调用KiFastSystemCall而是选择使用函数指针是因为XP不让经典的INT方式消失吧(我是这么想的),改7FFE0300的内容为KiIntSystemCall就等于使用INT方式了,那样会慢哦。

说了点和主题无关的东西。通过以上的分析,得到一个不可靠的结论:凡是Zw打头的API都是去掉系统服务的,然后开头代码都是mov eax,xx,根据这个不可靠的结论, 就可以通过遍厉ntdll.dll的导出函数,然后直接取得服务号就行,呵呵,自己都觉得很不可靠,下面是代码,遍厉导出函数的代码不是我写的,因为仅仅搞清楚了导入表

#include "windows.h"
#include "stdio.h"


BOOLEAN checkZwXXXByCode(DWORD funcEP)
{
 unsigned char code;
 code=*(char*)funcEP;
 if(code==0xb8)
  return TRUE;
 else
  return FALSE;
}
//开始想不加这个,结果输出了一些Rtl开头的API,他们都直接返回0x8004001
BOOLEAN checkZwXXXByName(char* apiName)  
{
 if(*(WORD*)apiName == 0x775A)
  return TRUE;
 return FALSE;
}

DWORD procAPIExportAddr(DWORD hModule)

 char *ptr = (char *)hModule;

 DWORD numEntries;
 DWORD *ExportNamePointerTable;
 DWORD ordinalBase;
 WORD *ExportOrdinalTable; 
 DWORD *ExportAddrTable;
 DWORD i,ii=0;
 char *exportName;
 DWORD funcEP;
 DWORD ord;

 if(!hModule)
  return 0;

 ptr += 0x3c;          // offset 0x3c contains offset to PE header
 
 ptr = (char *)(*(DWORD *)ptr) + hModule + 0x78;  // offset 78h into PE header contains addr of export table

 ptr = (char *)(*(DWORD *)ptr) + hModule;   // ptr now points to export directory table

 // offset 24 into the export directory table == number of entries in the Export Name Pointer Table
 // table
 numEntries = *(DWORD *)(ptr + 24);
 //printf("NumEntries = %d/n", numEntries);

 ExportNamePointerTable = (DWORD *)(*(DWORD *)(ptr + 32) + hModule); 
// offset 32 into export directory contains offset to Export Name Pointer Table 
 ordinalBase = *((DWORD *)(ptr + 16));
 //printf("OrdinalBase is %d/n", ordinalBase);
ExportOrdinalTable = (WORD *)((*(DWORD *)(ptr + 36)) + hModule);
 // offset 36 into export directory contains offset to Ordinal Table
 ExportAddrTable = (DWORD *)((*(DWORD *)(ptr + 28)) + hModule);
// offset 28 into export directory contains offset to Export Addr Table

 for(i = 0; i < numEntries; i++)
 {  
  exportName = (char *)(ExportNamePointerTable[i] + hModule);
  ord= ExportOrdinalTable[i];
  funcEP=ExportAddrTable[ord]+hModule;
  
  if( checkZwXXXByName(exportName) && checkZwXXXByCode(funcEP) )
  { 
   printf("[0x%x]%s/n",*(DWORD*)(funcEP+1),exportName);  //获得功能号
   ii++;
  }
 }
 printf("Total=0x%x/n",ii);      //统计个数
 return 0;
}


main()
{
 DWORD i=0,funcNum;
 DWORD ntdllBase;
 char* funcEP;
 if(ntdllBase=LoadLibrary(".//ntdll.dll"))          //这样是为了也能弄2000的,我的就XP,但是有2000的ntdll
  procAPIExportAddr(ntdllBase);
}

最后发现XP下加了不少系统服务:)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值