首页    新闻    下载    文档    论坛     最新漏洞    黑客教程    数据库    搜索    小榕软件实验室怀旧版    星际争霸WEB版    最新IP准确查询   
名称: 密码:      忘记密码  马上注册
安全知识 :: 黑客教程

驱动壳编写总结


http://www.gipsky.com/
Author: PolyMeta

Email: <a href="mailto:PolyMeta@whitecell.org">PolyMeta@whitecell.org</a>

Homepage:<a href="http://www.whitecell.org" target=_blank>http://www.whitecell.org</a>

Date: 2006-05-27

壳作为一种主要的软件保护手段大概可以分为压缩壳和<b><a href=http://www.baidu.com/s?tn=piglet&ct=&lm=&z=&rn=&word=加密 target="_blank"><font color=red>加密</font></a></b>壳两类。而现在

流行的加壳程序无论是压缩的还是<b><a href=http://www.baidu.com/s?tn=piglet&ct=&lm=&z=&rn=&word=加密 target="_blank"><font color=red>加密</font></a></b>的几乎都是针对应用层程序的,对于驱动

程序的保护壳则几乎是空白。笔者只在一些国外<b><a href=http://www.baidu.com/s?tn=piglet&ct=&lm=&z=&rn=&word=加密 target="_blank"><font color=red>加密</font></a></b>狗的驱动中见过类似应用层

的保护壳。本篇文章主要介绍驱动加壳程序与应用层加壳程序在编写上的区别以

及一些注重事项。



1.校验和的计算



驱动程序被加壳后必须重新进行校验和的计算,否则加壳后的驱动加载会

失败



;*****************计算pe文件校验和*********************



CalcPECheckSum PROC lpBaseAddr:DWORD,dwFileSize:DWORD

LOCAL CheckSum:DWORD

pushad

mov ecx,dwFileSize

inc ecx

shr ecx,1

xor eax,eax

clc

mov esi,lpBaseAddr

cal_checksum:

adc ax,word ptr [esi]

inc esi

inc esi

loop cal_checksum

mov ebx,dwFileSize

add eax,ebx

mov CheckSum,eax

popad

mov eax,CheckSum

ret

CalcPECheckSum endp



;*******************************************************



2.原始IAT的处理



由于原驱动程序被加上了我们的外壳,所以原驱动程序的IAT表的填写工作

要由我们的外壳程序来完成。应用层壳一般通过GetModuleHandle和GetProcAdd

ress两个API来完成这个工作,或者自己实现这两个API的功能。而驱动壳是要

随驱动程序一起被加载到内核当中去的,但内核里没有这两个函数,需要我们

自己对这两个函数做内核的实现。当然也可以用MmGetSystemRoutineAddress函

数,不过它只能得到ntoskrnl.exe和hal.dll两个模块的函数,对于其它模块则

无能为力了,影响壳的通用性。



壳的GetModuleHandle函数可以通过遍历PsLoadedModuleList链表来实现,

关于遍历这个链表的方法可以参照Futo的代码,通过DRIVEROBJECT的DriverSec

tion成员来完成,而驱动对象可以从堆栈当中找到。



壳的GetProcAddress函数的实现就很简单了,内核模块本身也是PE文件,

直接遍历一下PE的导出表就ok了。



还有一点需要注重的就是UNICODE的转换,PE文件里面的字符串是以ASCII

方式存储的,而内核里的字符串多半是用UNICODE方式存放的,这点需要注重。



3.节表的处理



在给程序加壳的时候一般都要添加新节,用于存放壳的代码,应用层程序

的节表的最后一项和第一个节之间一般是有一个很大的空间可以用来添加新的

节表项的,但一般情况下驱动程序节表的最后一项后面紧接着就是第一个节,

根本没有足够的0x28大小的空间存放新的节表项。解决的方法有两种,第一种

将所有的节向后移动,而第二种方法则是将PE头整体向前移动覆盖掉部分无用

的dos头,留出足够的空间存放新的节表项。



另外一点需要注重的是,加壳后的驱动程序的每一个节表项必须满足如下

两个公式,才能被系统正常加载



1) VirtualAddress == PointerToRawData

2) SizeOfRawData >= VirtualSize



至于为什么,笔者也没搞清楚,这只是笔者通过分析驱动加载代码及实验

的结果,哪位仁兄知道还请赐教:)



4.重定位表的处理



由于驱动程序是要被加载到内核空间中,所以外壳必须实现原来由系统完

成的原驱动程序的重定位工作。原驱动程序的重定位表的处理方法跟应用层 D

LL 文件的处理方法完全一样,代码如下:



mov eax,dword ptr [ebp OriginalRelocateAddr]

add eax,dword ptr [ebp ModuleHandle]

mov ecx,dword ptr [ebp OriginalRelocateSize]

mov ebx,eax

mov esi,dword ptr [ebp ModuleHandle]

sub esi,dword ptr [ebp OriginalBaseAddr] ;esi=diff



NextRelocateBlock:

.if ecx == 0

jmp FixAllRelocate

.endif

assume ebx : ptr IMAGE_BASE_RELOCATION

push ecx

mov ecx,dword ptr [ebx].SizeOfBlock

sub ecx,sizeof IMAGE_BASE_RELOCATION

shr ecx,1

mov eax,ebx

add eax,sizeof IMAGE_BASE_RELOCATION

NextRelocateEntry:

xor edi,edi

mov di,word ptr [eax]

shr edi,12

.if edi == IMAGE_REL_BASED_HIGHLOW

movzx edi,word ptr [eax]

and edi,0fffh

add edi,dword ptr [ebx].VirtualAddress

add edi,dword ptr [ebp ModuleHandle]

add dword ptr [edi],esi

.endif

add eax,2

loop NextRelocateEntry

pop ecx

sub ecx,dword ptr [ebx].SizeOfBlock

add ebx,dword ptr [ebx].SizeOfBlock

jmp NextRelocateBlock

FixAllRelocate:



需要注重的一点:驱动程序被加壳后必须要有重定位表,否则驱动加载会失

败,解决的方法需要自己构造一个假的重定位表来替换原始的重定位表。



另外,由于驱动壳的非凡性,shell的编写和驱动程序的编写没什么区别,

稍有错误就会蓝屏。



写这篇文章的主要目的是对笔者在编写驱动加壳程序的过程中所碰到的一些

问题及其解决方法的总结,避免以后忘了,同时也给想写驱动壳的兄弟们一点我

的心得,少走一些弯路。



WSS(Whitecell Security Systems),一个非营利性民间技术组织,致力于各种系统安全技术的研究。坚持传统的hacker精神,追求技术的精纯。
<< 一个简单的端口扫描编程序题 SQL Server SA权限总结 >>
评分
10987654321
API:
gipsky.com& 安信网络
网友个人意见,不代表本站立场。对于发言内容,由发表者自负责任。

系统导航

 

Copyright © 2001-2010 安信网络. All Rights Reserved
京ICP备05056747号